X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Usermode%2FApplications%2Faxwin3_src%2FWM%2Frenderers%2Frichtext.c;h=3e0fa5411a1ab31811d7dc101430648a0933500f;hb=1b9e758fbf856934974e847c3d5b348d237a0001;hp=eca5765bad4a842ebc4d91eb085cb8595ce51b1c;hpb=fa0ff18a7f85c7dc637aef2dfe5c1ed3dea7aee5;p=tpg%2Facess2.git 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; }