From: John Hodge Date: Sat, 13 Oct 2012 08:01:42 +0000 (+0800) Subject: AxWin3 - Heaps of bugfixes to RichText renderer X-Git-Tag: rel0.15~679 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=1b9e758fbf856934974e847c3d5b348d237a0001;p=tpg%2Facess2.git AxWin3 - Heaps of bugfixes to RichText renderer --- diff --git a/AcessNative/Makefile b/AcessNative/Makefile index c9cd4816..7448f4fd 100644 --- a/AcessNative/Makefile +++ b/AcessNative/Makefile @@ -1,4 +1,6 @@ -all: - @$(MAKE) -C acesskernel_src - @$(MAKE) -C ld-acess_src +.PHONY: all clean + +all clean: + @$(MAKE) -C acesskernel_src $@ + @$(MAKE) -C ld-acess_src $@ diff --git a/AcessNative/acesskernel_src/Makefile b/AcessNative/acesskernel_src/Makefile index be21e455..b4b7c11d 100644 --- a/AcessNative/acesskernel_src/Makefile +++ b/AcessNative/acesskernel_src/Makefile @@ -44,7 +44,8 @@ ifeq ($(PLATFORM),win) endif ifeq ($(PLATFORM),lin) BIN := ../AcessKernel - CFLAGS += + CFLAGS += + LDFLAGS += -lpthread endif .PHONY: all clean diff --git a/Usermode/Applications/axwin3_src/WM/include/wm.h b/Usermode/Applications/axwin3_src/WM/include/wm.h index 27890bab..e060e246 100644 --- a/Usermode/Applications/axwin3_src/WM/include/wm.h +++ b/Usermode/Applications/axwin3_src/WM/include/wm.h @@ -24,6 +24,8 @@ #define WINFLAG_NODECORATE 0x00000002 //! Window takes up all of screen #define WINFLAG_MAXIMIZED 0x00000004 +//! Window is contained within the parent +#define WINFLAG_RELATIVE 0x00000008 //! Window contents are valid #define WINFLAG_CLEAN 0x00000040 //! All child windows are un-changed @@ -52,6 +54,7 @@ extern void WM_FocusWindow(tWindow *Destination); extern void WM_RaiseWindow(tWindow *Window); extern void WM_ShowWindow(tWindow *Window, int bShow); extern void WM_DecorateWindow(tWindow *Window, int bDecorate); +extern void WM_SetRelative(tWindow *Window, int bRelativeToParent); extern int WM_ResizeWindow(tWindow *Window, int W, int H); extern int WM_MoveWindow(tWindow *Window, int X, int Y); extern int WM_SendMessage(tWindow *Source, tWindow *Dest, int MessageID, int Length, const void *Data); diff --git a/Usermode/Applications/axwin3_src/WM/include/wm_internals.h b/Usermode/Applications/axwin3_src/WM/include/wm_internals.h index 9ab29f86..45769e80 100644 --- a/Usermode/Applications/axwin3_src/WM/include/wm_internals.h +++ b/Usermode/Applications/axwin3_src/WM/include/wm_internals.h @@ -41,8 +41,9 @@ struct sWindow // Position and dimensions int X, Y; - int RealW, RealH; int W, H; + int RealX, RealY; + int RealW, RealH; void *RenderBuffer; //!< Cached copy of the rendered window }; diff --git a/Usermode/Applications/axwin3_src/WM/renderers/richtext.c b/Usermode/Applications/axwin3_src/WM/renderers/richtext.c index eca5765b..3e0fa541 100644 --- a/Usermode/Applications/axwin3_src/WM/renderers/richtext.c +++ b/Usermode/Applications/axwin3_src/WM/renderers/richtext.c @@ -7,25 +7,32 @@ */ #include #include +#include #include #include // sscanf +#include // memcpy #define LINES_PER_BLOCK 30 // === TYPES === -typedef struct sRichText_LineBlock +typedef struct sRichText_Line { - struct sRichText_LineBlock *Next; - int FirstLine; - char *Lines[LINES_PER_BLOCK]; -} tRichText_LineBlock; + struct sRichText_Line *Next; + struct sRichText_Line *Prev; + int Num; + // TODO: Pre-rendered cache? + short ByteLength; + short Space; + char Data[]; +} tRichText_Line; typedef struct sRichText_Window { int DispLines, DispCols; int FirstVisRow, FirstVisCol; int nLines, nCols; int CursorRow, CursorCol; - tRichText_LineBlock FirstBlock; + tRichText_Line *FirstLine; + tRichText_Line *FirstVisLine; tColour DefaultFG; tColour DefaultBG; tFont *Font; @@ -60,11 +67,16 @@ tWindow *Renderer_RichText_Create(int Flags) tWindow *ret = WM_CreateWindowStruct( sizeof(*info) ); if(!ret) return NULL; info = ret->RendererInfo; - // Everything starts at zero? + + // Initialise font. + int h; + WM_Render_GetTextDims(NULL, "yY!", 3, NULL, &h); + info->LineHeight = h; + return ret; } -static inline int Renderer_RichText_RenderText_Act(tWindow *Window, tRichText_Window *info, int X, int Row, const char *Text, int Bytes, tColour FG, tColour BG) +static inline int Renderer_RichText_RenderText_Act(tWindow *Window, tRichText_Window *info, int X, int Row, const char *Text, int Bytes, tColour FG, tColour BG, int Flags) { int rwidth; // TODO: Fill only what is needed @@ -72,6 +84,7 @@ static inline int Renderer_RichText_RenderText_Act(tWindow *Window, tRichText_Wi Window->W - X, info->LineHeight, BG ); + // TODO: Bold, Italic, Underline rwidth = WM_Render_DrawText(Window, X, Row*info->LineHeight, Window->W - X, info->LineHeight, @@ -86,9 +99,7 @@ void Renderer_RichText_RenderText(tWindow *Window, int Line, const char *Text) tRichText_Window *info = Window->RendererInfo; tColour fg = info->DefaultFG; tColour bg = info->DefaultBG; - int bBold = 0; - int bULine = 0; - int bItalic = 0; + int flagset = 0; int bRender = 0; int curx = 0; const char *oldtext = Text; @@ -106,7 +117,7 @@ void Renderer_RichText_RenderText(tWindow *Window, int Line, const char *Text) if( ch <=3 && bRender ) { // Render previous characters curx += Renderer_RichText_RenderText_Act(Window, info, curx, Line, - oldtext, Text - oldtext, fg, bg); + oldtext, Text - oldtext, fg, bg, flagset); oldtext = Text; } switch(ch) @@ -131,53 +142,68 @@ void Renderer_RichText_RenderText(tWindow *Window, int Line, const char *Text) // Bad client } Text += len; - bItalic = !!(flags & (1 << 2)); - bULine = !!(flags & (1 << 1)); - bBold = !!(flags & (1 << 0)); + //bItalic = !!(flags & (1 << 2)); + //bULine = !!(flags & (1 << 1)); + //bBold = !!(flags & (1 << 0)); + flagset = flags & 7; break ; default: // Any char, nop break; } } - curx += Renderer_RichText_RenderText_Act(Window, info, curx, Line, oldtext, Text - oldtext, fg, bg); - WM_Render_DrawRect(Window, curx, Line * info->LineHeight, Window->W - curx, info->LineHeight, info->DefaultBG); + curx += Renderer_RichText_RenderText_Act(Window, info, curx, + Line, oldtext, Text - oldtext, fg, bg, flagset); + WM_Render_DrawRect(Window, curx, Line * info->LineHeight, + Window->W - curx, info->LineHeight, info->DefaultBG); } void Renderer_RichText_Redraw(tWindow *Window) { tRichText_Window *info = Window->RendererInfo; int i; - tRichText_LineBlock *lines = &info->FirstBlock; + tRichText_Line *line = info->FirstVisLine; - // Locate the first line block - for( i = info->FirstVisRow; i > LINES_PER_BLOCK && lines; i -= LINES_PER_BLOCK ) - lines = lines->Next; + if( !line ) { + line = info->FirstLine; + while(line && line->Num < info->FirstVisRow ) + line = line->Next; + info->FirstVisLine = line; + } + while( line && line->Prev && line->Prev->Num > info->FirstVisRow ) + line = line->Prev; - for( i = 0; i < info->DispLines && lines; i ++ ) + for( i = 0; i < info->DispLines && line; i ++ ) { if( i >= info->nLines - info->FirstVisRow ) break; // TODO: Dirty rectangles? - WM_Render_DrawRect(Window, + WM_Render_FillRect(Window, 0, i*info->LineHeight, Window->W, info->LineHeight, info->DefaultBG ); + if( line->Num > info->FirstVisRow + i ) + continue ; // TODO: Horizontal scrolling? // TODO: Formatting - //Renderer_RichText_RenderText(Window, i, lines->Lines[i % LINES_PER_BLOCK]); + + // NOTE: uses scanf() so commented out for now + //Renderer_RichText_RenderText(Window, i, line->Text); WM_Render_DrawText(Window, 0, i*info->LineHeight, Window->W, info->LineHeight, info->Font, info->DefaultFG, - lines->Lines[i % LINES_PER_BLOCK], + line->Data, -1); - - if( (i + 1) % LINES_PER_BLOCK == 0 ) - lines = lines->Next; + _SysDebug("RichText: %p - Render %i '%.*s'", Window, + line->Num, line->ByteLength, line->Data); + + line = line->Next; } // Clear out i -- info->DispLines - WM_Render_DrawRect(Window, + _SysDebug("RichText: %p - Clear %i px lines with %06x starting at %i", + Window, (info->DispLines-i)*info->LineHeight, info->DefaultBG, i*info->LineHeight); + WM_Render_FillRect(Window, 0, i*info->LineHeight, Window->W, (info->DispLines-i)*info->LineHeight, info->DefaultBG @@ -186,10 +212,81 @@ void Renderer_RichText_Redraw(tWindow *Window) int Renderer_RichText_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data) { + tRichText_Window *info = Target->RendererInfo; switch(Msg) { - case MSG_RICHTEXT_SETATTR: - break; + case WNDMSG_RESIZE: { + const struct sWndMsg_Resize *msg = Data; + if(Len < sizeof(*msg)) return -1; + info->DispLines = msg->H / info->LineHeight; + return 1; } + case MSG_RICHTEXT_SETATTR: { + const struct sRichTextMsg_SetAttr *msg = Data; + if(Len < sizeof(*msg)) return -1; + _SysDebug("RichText Attr %i set to %x", msg->Attr, msg->Value); + switch(msg->Attr) + { + case _ATTR_DEFBG: + info->DefaultBG = msg->Value; + break; + case _ATTR_DEFFG: + info->DefaultFG = msg->Value; + break; + case _ATTR_SCROLL: + // TODO: Set scroll flag + break; + case _ATTR_LINECOUNT: + info->nLines = msg->Value; + break; + } + return 1; } + // Update a line + case MSG_RICHTEXT_SENDLINE: { + const struct sRichTextMsg_SendLine *msg = Data; + if(Len < sizeof(*msg)) return -1; + _SysDebug("RichText Line %i = '%.*s'", msg->Line, Len - sizeof(*msg), msg->LineData); + if( msg->Line >= info->nLines ) return 1; // Bad count + + tRichText_Line *line = info->FirstLine; + tRichText_Line *prev = NULL; + while(line && line->Num < msg->Line) + prev = line, line = line->Next; + if( !line || line->Num > msg->Line ) + { + // New line! + // Round up to 32 + int space = ((Len - sizeof(*msg)) + 32-1) & ~(32-1); + tRichText_Line *new = malloc(sizeof(*line) + space); + // TODO: Bookkeeping on how much memory each window uses + new->Next = line; + new->Prev = prev; + new->Num = msg->Line; + new->Space = space; + if(new->Prev) new->Prev->Next = new; + else info->FirstLine = new; + if(new->Next) new->Next->Prev = new; + line = new; + } + else if( line->Space < Len - sizeof(*msg) ) + { + // Need to allocate more space + int space = ((Len - sizeof(*msg)) + 32-1) & ~(32-1); + tRichText_Line *new = realloc(line, space); + // TODO: Bookkeeping on how much memory each window uses + new->Space = space; + + if(new->Prev) new->Prev->Next = new; + else info->FirstLine = new; + if(new->Next) new->Next->Prev = new; + line = new; + } + else + { + // It fits :) + } + line->ByteLength = Len - sizeof(*msg); + memcpy(line->Data, msg->LineData, Len - sizeof(*msg)); + return 1; } } return 0; } diff --git a/Usermode/Applications/axwin3_src/WM/renderers/widget.c b/Usermode/Applications/axwin3_src/WM/renderers/widget.c index 88529543..b8c454c8 100644 --- a/Usermode/Applications/axwin3_src/WM/renderers/widget.c +++ b/Usermode/Applications/axwin3_src/WM/renderers/widget.c @@ -87,7 +87,7 @@ tWindow *Renderer_Widget_Create(int Flags) tWidgetWin *info; int eletable_size = DEFAULT_ELETABLE_SIZE; - _SysDebug("Renderer_Widget_Create: (Flags = 0x%x)", Flags); + //_SysDebug("Renderer_Widget_Create: (Flags = 0x%x)", Flags); // TODO: Use `Flags` as default element count? // - Actaully, it's taken by the root ele flags @@ -214,14 +214,14 @@ void Widget_UpdateDimensions(tElement *Element) else fullCross = Element->CachedH - Element->PaddingT - Element->PaddingB; - _SysDebug("%i (p=%i) - WxH=%ix%i", - Element->ID, (Element->Parent ? Element->Parent->ID : -1), - Element->CachedW, Element->CachedH - ); - _SysDebug(" %s dynWith = %i, fullCross = %i", - (Element->Flags & ELEFLAG_VERTICAL ? "Vert" : "Horiz"), - dynWith, fullCross - ); + //_SysDebug("%i (p=%i) - WxH=%ix%i", + // Element->ID, (Element->Parent ? Element->Parent->ID : -1), + // Element->CachedW, Element->CachedH + // ); + //_SysDebug(" %s dynWith = %i, fullCross = %i", + // (Element->Flags & ELEFLAG_VERTICAL ? "Vert" : "Horiz"), + // dynWith, fullCross + // ); // Pass 2 - Set sizes and recurse for( child = Element->FirstChild; child; child = child->NextSibling ) diff --git a/Usermode/Applications/axwin3_src/WM/renderers/widget/subwin.c b/Usermode/Applications/axwin3_src/WM/renderers/widget/subwin.c index 4cdaabad..fcf196d5 100644 --- a/Usermode/Applications/axwin3_src/WM/renderers/widget/subwin.c +++ b/Usermode/Applications/axwin3_src/WM/renderers/widget/subwin.c @@ -11,6 +11,8 @@ void Widget_SubWin_Render(tWindow *Window, tElement *Element) { + // Ensure that child window is positioned relative to this window + WM_SetRelative(Element->Data, 1); // Note: Doesn't actually render, but does poke the child window WM_MoveWindow(Element->Data, Element->CachedX, Element->CachedY); WM_ResizeWindow(Element->Data, Element->CachedW, Element->CachedH); @@ -20,4 +22,3 @@ DEFWIDGETTYPE(ELETYPE_SUBWIN, WIDGETTYPE_FLAG_NOCHILDREN, .Render = Widget_SubWin_Render ) - diff --git a/Usermode/Applications/axwin3_src/WM/video.c b/Usermode/Applications/axwin3_src/WM/video.c index fe379648..1c857fb4 100644 --- a/Usermode/Applications/axwin3_src/WM/video.c +++ b/Usermode/Applications/axwin3_src/WM/video.c @@ -133,8 +133,6 @@ void Video_Blit(uint32_t *Source, short DstX, short DstY, short W, short H) { uint32_t *buf; - _SysDebug("Video_Blit: (%p, %i, %i, %i, %i)", Source, DstX, DstY, W, H); - if( DstX >= giScreenWidth) return ; if( DstY >= giScreenHeight) return ; // TODO: Handle -ve X/Y by clipping @@ -146,8 +144,6 @@ void Video_Blit(uint32_t *Source, short DstX, short DstY, short W, short H) if( W <= 0 || H <= 0 ) return; - _SysDebug(" - Resolved to (%p, %i, %i, %i, %i)", Source, DstX, DstY, W, H); - if( DstX < giVideo_FirstDirtyLine ) giVideo_FirstDirtyLine = DstY; if( DstY + H > giVideo_LastDirtyLine ) diff --git a/Usermode/Applications/axwin3_src/WM/wm.c b/Usermode/Applications/axwin3_src/WM/wm.c index 019ce5a8..fe944e3a 100644 --- a/Usermode/Applications/axwin3_src/WM/wm.c +++ b/Usermode/Applications/axwin3_src/WM/wm.c @@ -216,16 +216,49 @@ void WM_DecorateWindow(tWindow *Window, int bDecorate) WM_Invalidate(Window); } +void WM_SetRelative(tWindow *Window, int bRelativeToParent) +{ +// _SysDebug("WM_SetRelative: (%p{Parent=%p},%i)", Window, Window->Parent, bRelativeToParent); + // No meaning if no parent + if( !Window->Parent ) + return ; + + // Check that the flag is changing + if( !!bRelativeToParent == !!(Window->Flags & WINFLAG_RELATIVE) ) + return ; + + if( bRelativeToParent ) { + // Set + Window->Flags |= WINFLAG_RELATIVE; + WM_MoveWindow(Window, Window->X, Window->Y); + } + else { + // Clear + Window->Flags &= ~WINFLAG_RELATIVE; + WM_MoveWindow(Window, Window->X - Window->Parent->X, Window->Y - Window->Parent->Y); + } +} + int WM_MoveWindow(tWindow *Window, int X, int Y) { +// _SysDebug("Move %p to (%i,%i)", Window, X, Y); // Clip coordinates if(X + Window->W < 0) X = -Window->W + 1; if(Y + Window->H < 0) Y = -Window->H + 1; if(X >= giScreenWidth) X = giScreenWidth - 1; if(Y >= giScreenHeight) Y = giScreenHeight - 1; + // If relative to the parent, extra checks + if( (Window->Flags & WINFLAG_RELATIVE) && Window->Parent ) + { + if( X > Window->Parent->W ) return 1; + if( Y > Window->Parent->H ) return 1; + } + // TODO: Re-sanitise + Window->X = X; Window->Y = Y; + // TODO: Why invalidate buffer? WM_Invalidate(Window); return 0; @@ -301,7 +334,7 @@ int WM_SendMessage(tWindow *Source, tWindow *Dest, int Message, int Length, cons void WM_Invalidate(tWindow *Window) { if(!Window) return ; - _SysDebug("Invalidating %p", Window); +// _SysDebug("Invalidating %p", Window); // Don't invalidate twice (speedup) // if( !(Window->Flags & WINFLAG_CLEAN) ) return; @@ -328,7 +361,7 @@ void WM_int_UpdateWindow(tWindow *Window) // Calculate RealW/RealH if( !(Window->Flags & WINFLAG_NODECORATE) ) { - _SysDebug("Applying decorations to %p", Window); + //_SysDebug("Applying decorations to %p", Window); Decorator_UpdateBorderSize(Window); Window->RealW = Window->BorderL + Window->W + Window->BorderR; Window->RealH = Window->BorderT + Window->H + Window->BorderB; @@ -344,6 +377,17 @@ void WM_int_UpdateWindow(tWindow *Window) Window->RealH = Window->H; } + if( (Window->Flags & WINFLAG_RELATIVE) && Window->Parent ) + { + Window->RealX = Window->Parent->X + Window->Parent->BorderL + Window->X; + Window->RealY = Window->Parent->Y + Window->Parent->BorderT + Window->Y; + } + else + { + Window->RealX = Window->X; + Window->RealY = Window->Y; + } + Window->Renderer->Redraw(Window); Window->Flags |= WINFLAG_CLEAN; } @@ -371,15 +415,15 @@ void WM_int_BlitWindow(tWindow *Window) if( !(Window->Flags & WINFLAG_SHOW) ) return ; - _SysDebug("Blit %p (%p) to (%i,%i) %ix%i", Window, Window->RenderBuffer, - Window->X, Window->Y, Window->RealW, Window->RealH); - Video_Blit(Window->RenderBuffer, Window->X, Window->Y, Window->RealW, Window->RealH); +// _SysDebug("Blit %p (%p) to (%i,%i) %ix%i", Window, Window->RenderBuffer, +// Window->RealX, Window->RealY, Window->RealW, Window->RealH); + Video_Blit(Window->RenderBuffer, Window->RealX, Window->RealY, Window->RealW, Window->RealH); if( Window == gpWM_FocusedWindow && Window->CursorW ) { Video_FillRect( - Window->X + Window->BorderL + Window->CursorX, - Window->Y + Window->BorderT + Window->CursorY, + Window->RealX + Window->BorderL + Window->CursorX, + Window->RealY + Window->BorderT + Window->CursorY, Window->CursorW, Window->CursorH, 0x000000 ); diff --git a/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_richtext.c b/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_richtext.c index 74b437b1..b1620dd2 100644 --- a/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_richtext.c +++ b/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_richtext.c @@ -9,6 +9,8 @@ #include #include "include/internal.h" #include +#include +//#include // === TYPES === typedef struct sRichText_Window @@ -89,3 +91,16 @@ void AxWin3_RichText_SetCursorPos(tHWND Window, int Row, int Column) return ; _SendAttrib(Window, _ATTR_CURSORPOS, ((Row & 0xFFFFF) << 12) | (Column & 0xFFF)); } + +void AxWin3_RichText_SendLine(tHWND Window, int Line, const char *Text) +{ + // TODO: Local sanity check on `Line`? + struct sRichTextMsg_SendLine *msg; + size_t len = sizeof(*msg) + strlen(Text) + 1; + char buffer[len]; + msg = (void*)buffer; + msg->Line = Line; + strcpy(msg->LineData, Text); + AxWin3_SendMessage(Window, Window, MSG_RICHTEXT_SENDLINE, len, msg); +} + diff --git a/Usermode/Applications/gui_ate_src/main.c b/Usermode/Applications/gui_ate_src/main.c index e83ab7c4..82a9117b 100644 --- a/Usermode/Applications/gui_ate_src/main.c +++ b/Usermode/Applications/gui_ate_src/main.c @@ -33,7 +33,7 @@ int main(int argc, char *argv[]) AxWin3_Connect(NULL); // --- Build up window - gMainWindow = AxWin3_Widget_CreateWindow(NULL, 400, 600, ELEFLAG_VERTICAL); + gMainWindow = AxWin3_Widget_CreateWindow(NULL, 600, 400, ELEFLAG_VERTICAL); AxWin3_SetWindowTitle(gMainWindow, "Acess Text Editor"); // TODO: Update title with other info gMainWindow_Root = AxWin3_Widget_GetRoot(gMainWindow); @@ -69,6 +69,13 @@ int main(int argc, char *argv[]) AxWin3_RichText_SetCursorPos (gMainWindow_TextArea, 0, 0); AxWin3_RichText_SetCursorType (gMainWindow_TextArea, AXWIN3_RICHTEXT_CURSOR_VLINE); AxWin3_RichText_SetCursorBlink (gMainWindow_TextArea, 1); + + // + AxWin3_RichText_SetLineCount(gMainWindow_TextArea, 3); + AxWin3_RichText_SendLine(gMainWindow_TextArea, 0, "First line!"); + AxWin3_RichText_SendLine(gMainWindow_TextArea, 2, "Third line!, should be a nice gap above"); + // + AxWin3_ShowWindow(gMainWindow_TextArea, 1); // TODO: Status Bar? diff --git a/Usermode/Libraries/libaxwin3.so_src/include_exp/axwin3/richtext.h b/Usermode/Libraries/libaxwin3.so_src/include_exp/axwin3/richtext.h index 2a6c5aec..661c02be 100644 --- a/Usermode/Libraries/libaxwin3.so_src/include_exp/axwin3/richtext.h +++ b/Usermode/Libraries/libaxwin3.so_src/include_exp/axwin3/richtext.h @@ -39,6 +39,7 @@ extern void AxWin3_RichText_SetFont(tHWND Window, const char *FontName, int Poin extern void AxWin3_RichText_SetCursorType(tHWND Window, int Type); extern void AxWin3_RichText_SetCursorBlink(tHWND Window, int bBlink); extern void AxWin3_RichText_SetCursorPos(tHWND Window, int Row, int Column); +extern void AxWin3_RichText_SendLine(tHWND Window, int Line, const char *Text); #endif