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_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data);
50 tWMRenderer gRenderer_RichText = {
52 .CreateWindow = Renderer_RichText_Create,
53 .Redraw = Renderer_RichText_Redraw,
54 .HandleMessage = Renderer_RichText_HandleMessage
58 int Renderer_RichText_Init(void)
60 WM_RegisterRenderer(&gRenderer_RichText);
64 tWindow *Renderer_RichText_Create(int Flags)
66 tRichText_Window *info;
67 tWindow *ret = WM_CreateWindowStruct( sizeof(*info) );
69 info = ret->RendererInfo;
71 // Initialise font (get an idea of dimensions)
73 WM_Render_GetTextDims(NULL, "yY!", 3, NULL, &h);
79 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)
82 // TODO: Fill only what is needed? What about the rest of the line?
83 WM_Render_DrawRect(Window, X, Row*info->LineHeight,
84 Window->W - X, info->LineHeight,
87 // TODO: Bold, Italic, Underline
88 rwidth = WM_Render_DrawText(Window,
89 X, Row*info->LineHeight,
90 Window->W - X, info->LineHeight,
97 void Renderer_RichText_RenderText(tWindow *Window, int Line, const char *Text)
99 tRichText_Window *info = Window->RendererInfo;
100 tColour fg = info->DefaultFG;
101 tColour bg = info->DefaultBG;
105 const char *oldtext = Text;
107 for( int i = 0; i < info->FirstVisCol + info->DispCols; i ++ )
112 if( i == info->FirstVisCol )
117 if( ch <=3 && bRender ) {
118 // Render previous characters
119 curx += Renderer_RichText_RenderText_Act(Window, info, curx, Line,
120 oldtext, Text - oldtext, fg, bg, flagset);
125 case 1: // FG Select (\1 RRGGBB)
126 len = sscanf(Text, "%6x", &fg);
132 case 2: // BG Select (\2 RRGGBB)
133 len = sscanf(Text, "%6x", &bg);
139 case 3: // Flagset (0,it,uline,bold)
140 len = sscanf(Text, "%1x", &flags);
145 //bItalic = !!(flags & (1 << 2));
146 //bULine = !!(flags & (1 << 1));
147 //bBold = !!(flags & (1 << 0));
150 default: // Any char, nop
154 curx += Renderer_RichText_RenderText_Act(Window, info, curx,
155 Line, oldtext, Text - oldtext, fg, bg, flagset);
156 WM_Render_DrawRect(Window, curx, Line * info->LineHeight,
157 Window->W - curx, info->LineHeight, info->DefaultBG);
160 void Renderer_RichText_Redraw(tWindow *Window)
162 tRichText_Window *info = Window->RendererInfo;
164 tRichText_Line *line = info->FirstVisLine;
167 line = info->FirstLine;
168 while(line && line->Num < info->FirstVisRow )
170 info->FirstVisLine = line;
172 while( line && line->Prev && line->Prev->Num > info->FirstVisRow )
175 for( i = 0; i < info->DispLines && line; i ++ )
177 if( i >= info->nLines - info->FirstVisRow )
179 // TODO: Dirty rectangles?
180 WM_Render_FillRect(Window,
181 0, i*info->LineHeight,
182 Window->W, info->LineHeight,
185 if( line->Num > info->FirstVisRow + i )
187 // TODO: Horizontal scrolling?
190 // NOTE: uses scanf() so commented out for now
191 //Renderer_RichText_RenderText(Window, i, line->Text);
192 WM_Render_DrawText(Window,
193 0, i*info->LineHeight,
194 Window->W, info->LineHeight,
195 info->Font, info->DefaultFG,
198 _SysDebug("RichText: %p - Render %i '%.*s'", Window,
199 line->Num, line->ByteLength, line->Data);
203 // Clear out i -- info->DispLines
204 _SysDebug("RichText: %p - Clear %i px lines with %06x starting at %i",
205 Window, (info->DispLines-i)*info->LineHeight, info->DefaultBG, i*info->LineHeight);
206 WM_Render_FillRect(Window,
207 0, i*info->LineHeight,
208 Window->W, (info->DispLines-i)*info->LineHeight,
213 int Renderer_RichText_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data)
215 tRichText_Window *info = Target->RendererInfo;
218 case WNDMSG_RESIZE: {
219 const struct sWndMsg_Resize *msg = Data;
220 if(Len < sizeof(*msg)) return -1;
221 info->DispLines = msg->H / info->LineHeight;
223 case MSG_RICHTEXT_SETATTR: {
224 const struct sRichTextMsg_SetAttr *msg = Data;
225 if(Len < sizeof(*msg)) return -1;
226 _SysDebug("RichText Attr %i set to %x", msg->Attr, msg->Value);
230 info->DefaultBG = msg->Value;
233 info->DefaultFG = msg->Value;
236 // TODO: Set scroll flag
238 case _ATTR_LINECOUNT:
239 info->nLines = msg->Value;
244 case MSG_RICHTEXT_SENDLINE: {
245 const struct sRichTextMsg_SendLine *msg = Data;
246 if(Len < sizeof(*msg)) return -1;
247 _SysDebug("RichText Line %i = '%.*s'", msg->Line, Len - sizeof(*msg), msg->LineData);
248 if( msg->Line >= info->nLines ) return 1; // Bad count
250 tRichText_Line *line = info->FirstLine;
251 tRichText_Line *prev = NULL;
252 while(line && line->Num < msg->Line)
253 prev = line, line = line->Next;
254 if( !line || line->Num > msg->Line )
258 int space = ((Len - sizeof(*msg)) + 32-1) & ~(32-1);
259 tRichText_Line *new = malloc(sizeof(*line) + space);
260 // TODO: Bookkeeping on how much memory each window uses
263 new->Num = msg->Line;
265 if(new->Prev) new->Prev->Next = new;
266 else info->FirstLine = new;
267 if(new->Next) new->Next->Prev = new;
270 else if( line->Space < Len - sizeof(*msg) )
272 // Need to allocate more space
273 int space = ((Len - sizeof(*msg)) + 32-1) & ~(32-1);
274 tRichText_Line *new = realloc(line, space);
275 // TODO: Bookkeeping on how much memory each window uses
278 if(new->Prev) new->Prev->Next = new;
279 else info->FirstLine = new;
280 if(new->Next) new->Next->Prev = new;
287 line->ByteLength = Len - sizeof(*msg);
288 memcpy(line->Data, msg->LineData, Len - sizeof(*msg));