2 * Acess2 Window Manager v3
3 * - By John Hodge (thePowersGang)
6 * - Formatted Line Editor
9 #include <wm_renderer.h>
10 #include <wm_messages.h>
11 #include <richtext_messages.h>
12 #include <stdio.h> // sscanf
13 #include <string.h> // memcpy
15 #define LINES_PER_BLOCK 30
18 typedef struct sRichText_Line
20 struct sRichText_Line *Next;
21 struct sRichText_Line *Prev;
23 // TODO: Pre-rendered cache?
28 typedef struct sRichText_Window
30 int DispLines, DispCols;
31 int FirstVisRow, FirstVisCol;
33 int CursorRow, CursorCol;
34 tRichText_Line *FirstLine;
35 tRichText_Line *FirstVisLine;
44 int Renderer_RichText_Init(void);
45 tWindow *Renderer_RichText_Create(int Flags);
46 void Renderer_RichText_Redraw(tWindow *Window);
47 int Renderer_RichText_HandleIPC_SetAttr(tWindow *Window, size_t Len, const void *Data);
48 int Renderer_RichText_HandleIPC_WriteLine(tWindow *Window, size_t Len, const void *Data);
49 int Renderer_RichText_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data);
52 tWMRenderer gRenderer_RichText = {
54 .CreateWindow = Renderer_RichText_Create,
55 .Redraw = Renderer_RichText_Redraw,
56 .HandleMessage = Renderer_RichText_HandleMessage,
57 .nIPCHandlers = N_IPC_RICHTEXT,
59 [IPC_RICHTEXT_SETATTR] = Renderer_RichText_HandleIPC_SetAttr,
60 [IPC_RICHTEXT_WRITELINE] = Renderer_RichText_HandleIPC_WriteLine
65 int Renderer_RichText_Init(void)
67 WM_RegisterRenderer(&gRenderer_RichText);
71 tWindow *Renderer_RichText_Create(int Flags)
73 tRichText_Window *info;
74 tWindow *ret = WM_CreateWindowStruct( sizeof(*info) );
76 info = ret->RendererInfo;
78 // Initialise font (get an idea of dimensions)
80 WM_Render_GetTextDims(NULL, "yY!", 3, NULL, &h);
86 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)
89 // TODO: Fill only what is needed? What about the rest of the line?
90 WM_Render_DrawRect(Window, X, Row*info->LineHeight,
91 Window->W - X, info->LineHeight,
94 // TODO: Bold, Italic, Underline
95 rwidth = WM_Render_DrawText(Window,
96 X, Row*info->LineHeight,
97 Window->W - X, info->LineHeight,
104 void Renderer_RichText_RenderText(tWindow *Window, int Line, const char *Text)
106 tRichText_Window *info = Window->RendererInfo;
107 tColour fg = info->DefaultFG;
108 tColour bg = info->DefaultBG;
112 const char *oldtext = Text;
114 for( int i = 0; curx < Window->W; i ++ )
119 if( i == info->FirstVisCol )
125 // Not an escape - move along
130 // Render previous characters
131 curx += Renderer_RichText_RenderText_Act(Window, info, curx, Line,
132 oldtext, Text - oldtext - 1, fg, bg, flagset);
133 if( curx >= Window->W )
139 case 1: // FG Select (\1 RRGGBB)
140 if( sscanf(Text, "%6x%n", &fg, &len) != 1 || len != 6 ) {
142 _SysDebug("foreground scanf failed - len=%i", len);
147 _SysDebug("FG update to %x", fg);
149 case 2: // BG Select (\2 RRGGBB)
150 if( sscanf(Text, "%6x%n", &bg, &len) != 1 || len != 6 ) {
152 _SysDebug("background scanf failed - len=%i", len);
157 _SysDebug("BG update to %x", bg);
159 case 3: // Flagset (0,it,uline,bold)
160 if( sscanf(Text, "%1hhx%n", &flags, &len) != 1 || len != 1 ) {
162 _SysDebug("Flagset scanf failed - len=%i", len);
168 case 4: // Escape (do nothing)
170 // NOTE: No update to oldtext
176 curx += Renderer_RichText_RenderText_Act(Window, info, curx,
177 Line, oldtext, Text - oldtext + 1, fg, bg, flagset);
178 WM_Render_DrawRect(Window, curx, Line * info->LineHeight,
179 Window->W - curx, info->LineHeight, info->DefaultBG);
182 void Renderer_RichText_Redraw(tWindow *Window)
184 tRichText_Window *info = Window->RendererInfo;
186 tRichText_Line *line = info->FirstVisLine;
189 line = info->FirstLine;
190 while(line && line->Num < info->FirstVisRow )
192 info->FirstVisLine = line;
194 while( line && line->Prev && line->Prev->Num > info->FirstVisRow )
197 for( i = 0; i < info->DispLines && line; i ++ )
199 if( i >= info->nLines - info->FirstVisRow )
201 // TODO: Dirty rectangles?
202 WM_Render_FillRect(Window,
203 0, i*info->LineHeight,
204 Window->W, info->LineHeight,
207 if( line->Num > info->FirstVisRow + i )
209 // TODO: Horizontal scrolling?
212 // Formatted text out
213 Renderer_RichText_RenderText(Window, i, line->Data);
214 _SysDebug("RichText: %p - Render %i '%.*s'", Window,
215 line->Num, line->ByteLength, line->Data);
219 // Clear out i -- info->DispLines
220 _SysDebug("RichText: %p - Clear %i px lines with %06x starting at %i",
221 Window, (info->DispLines-i)*info->LineHeight, info->DefaultBG, i*info->LineHeight);
222 WM_Render_FillRect(Window,
223 0, i*info->LineHeight,
224 Window->W, (info->DispLines-i)*info->LineHeight,
229 if( info->CursorRow >= info->FirstVisRow && info->CursorRow < info->FirstVisRow + info->DispLines )
231 if( info->CursorCol >= info->FirstVisCol && info->CursorCol < info->FirstVisCol + info->DispCols )
233 // TODO: Kill hardcoded 8 with cached text distance
234 WM_Render_FillRect(Window,
235 (info->CursorCol - info->FirstVisCol) * 8,
236 (info->CursorRow - info->FirstVisRow) * info->LineHeight,
245 int Renderer_RichText_HandleIPC_SetAttr(tWindow *Window, size_t Len, const void *Data)
247 tRichText_Window *info = Window->RendererInfo;
248 const struct sRichTextIPC_SetAttr *msg = Data;
249 if(Len < sizeof(*msg)) return -1;
251 _SysDebug("RichText Attr %i set to %x", msg->Attr, msg->Value);
255 info->DefaultBG = msg->Value;
258 info->DefaultFG = msg->Value;
260 case _ATTR_CURSORPOS:
261 info->CursorRow = msg->Value >> 12;
262 info->CursorCol = msg->Value & 0xFFF;
265 // TODO: Set scroll flag
267 case _ATTR_LINECOUNT:
268 info->nLines = msg->Value;
275 int Renderer_RichText_HandleIPC_WriteLine(tWindow *Window, size_t Len, const void *Data)
277 tRichText_Window *info = Window->RendererInfo;
278 const struct sRichTextIPC_WriteLine *msg = Data;
279 if( Len < sizeof(*msg) ) return -1;
280 if( msg->Line >= info->nLines ) return 1; // Bad count
282 tRichText_Line *line = info->FirstLine;
283 tRichText_Line *prev = NULL;
284 while(line && line->Num < msg->Line)
285 prev = line, line = line->Next;
286 if( !line || line->Num > msg->Line )
290 int space = ((Len - sizeof(*msg)) + 32-1) & ~(32-1);
291 tRichText_Line *new = malloc(sizeof(*line) + space);
292 // TODO: Bookkeeping on how much memory each window uses
295 new->Num = msg->Line;
297 if(new->Prev) new->Prev->Next = new;
298 else info->FirstLine = new;
299 if(new->Next) new->Next->Prev = new;
302 else if( line->Space < Len - sizeof(*msg) )
304 // Need to allocate more space
305 int space = ((Len - sizeof(*msg)) + 32-1) & ~(32-1);
306 tRichText_Line *new = realloc(line, space);
307 // TODO: Bookkeeping on how much memory each window uses
310 if(new->Prev) new->Prev->Next = new;
311 else info->FirstLine = new;
312 if(new->Next) new->Next->Prev = new;
319 line->ByteLength = Len - sizeof(*msg);
320 memcpy(line->Data, msg->LineData, Len - sizeof(*msg));
322 WM_Invalidate( Window );
327 int Renderer_RichText_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data)
329 tRichText_Window *info = Target->RendererInfo;
332 case WNDMSG_RESIZE: {
333 const struct sWndMsg_Resize *msg = Data;
334 if(Len < sizeof(*msg)) return -1;
335 info->DispLines = msg->H / info->LineHeight;