From: John Hodge Date: Tue, 10 Sep 2013 09:05:12 +0000 (+0800) Subject: Usermode/AxWin3 - Added scroll command to richtext renderer X-Git-Tag: rel0.15~226 X-Git-Url: https://git.ucc.asn.au/?a=commitdiff_plain;h=16a06e033161374724932f90ebd8be420b4c4b91;p=tpg%2Facess2.git Usermode/AxWin3 - Added scroll command to richtext renderer --- diff --git a/Usermode/Applications/axwin3_src/WM/renderers/richtext.c b/Usermode/Applications/axwin3_src/WM/renderers/richtext.c index 63ee8e56..edf3c7de 100644 --- a/Usermode/Applications/axwin3_src/WM/renderers/richtext.c +++ b/Usermode/Applications/axwin3_src/WM/renderers/richtext.c @@ -59,6 +59,7 @@ void Renderer_RichText_Destroy(tWindow *Window); void Renderer_RichText_Redraw(tWindow *Window); int Renderer_RichText_HandleIPC_SetAttr(tWindow *Window, size_t Len, const void *Data); int Renderer_RichText_HandleIPC_WriteLine(tWindow *Window, size_t Len, const void *Data); + int Renderer_RichText_HandleIPC_ScrollRange(tWindow *Window, size_t Len, const void *Data); int Renderer_RichText_HandleMessage(tWindow *Target, int Msg, int Len, const void *Data); // === GLOBALS === @@ -71,7 +72,8 @@ tWMRenderer gRenderer_RichText = { .nIPCHandlers = N_IPC_RICHTEXT, .IPCHandlers = { [IPC_RICHTEXT_SETATTR] = Renderer_RichText_HandleIPC_SetAttr, - [IPC_RICHTEXT_WRITELINE] = Renderer_RichText_HandleIPC_WriteLine + [IPC_RICHTEXT_WRITELINE] = Renderer_RichText_HandleIPC_WriteLine, + [IPC_RICHTEXT_SCROLLRANGE] = Renderer_RichText_HandleIPC_ScrollRange } }; @@ -321,9 +323,12 @@ void Renderer_RichText_int_UpdateCursorOfs(tRichText_Window *Info) { tRichText_Line *line = Info->CursorLine; size_t ofs = 0; - for( int i = 0; i < Info->CursorCol && ofs < line->ByteLength; i ++ ) + if( line ) { - ofs += ReadUTF8(line->Data + ofs, NULL); + for( int i = 0; i < Info->CursorCol && ofs < line->ByteLength; i ++ ) + { + ofs += ReadUTF8(line->Data + ofs, NULL); + } } Info->CursorBytePos = ofs; } @@ -381,12 +386,13 @@ int Renderer_RichText_HandleIPC_WriteLine(tWindow *Window, size_t Len, const voi tRichText_Line *prev = NULL; tRichText_Line *line = Renderer_RichText_int_GetLine(Window, msg->Line, &prev); - int reqspace = ((Len - sizeof(*msg)) + LINE_SPACE_UNIT-1) & ~(LINE_SPACE_UNIT-1); + size_t data_bytes = Len - sizeof(*msg); + int reqspace = (data_bytes + LINE_SPACE_UNIT-1) & ~(LINE_SPACE_UNIT-1); tRichText_Line *new = NULL; if( !line ) { // New line! - tRichText_Line *new = malloc(sizeof(*line) + reqspace); + new = malloc(sizeof(*line) + reqspace); new->Next = (prev ? prev->Next : NULL); new->Prev = prev; new->Num = msg->Line; @@ -394,7 +400,7 @@ int Renderer_RichText_HandleIPC_WriteLine(tWindow *Window, size_t Len, const voi else if( line->Space < reqspace ) { // Need to allocate more space - tRichText_Line *new = realloc(line, sizeof(*line) + reqspace); + new = realloc(line, sizeof(*line) + reqspace); } else { @@ -409,10 +415,13 @@ int Renderer_RichText_HandleIPC_WriteLine(tWindow *Window, size_t Len, const voi if(new->Next) new->Next->Prev = new; line = new; } - line->ByteLength = Len - sizeof(*msg) - 1; - memcpy(line->Data, msg->LineData, Len - sizeof(*msg)); + line->ByteLength = data_bytes - 1; + memcpy(line->Data, msg->LineData, data_bytes); line->bIsClean = 0; + _SysDebug("RichText: %p - Write %i %i'%.*s'", Window, line->Num, line->ByteLength, + line->ByteLength, line->Data); + if( line->Num == info->CursorRow ) { info->CursorLine = line; info->CursorBytePos = MIN(info->CursorBytePos, line->ByteLength); @@ -423,6 +432,74 @@ int Renderer_RichText_HandleIPC_WriteLine(tWindow *Window, size_t Len, const voi return 0; } +int Renderer_RichText_HandleIPC_ScrollRange(tWindow *Window, size_t Len, const void *Data) +{ + tRichText_Window *info = Window->RendererInfo; + const struct sRichTextIPC_ScrollRange *msg = Data; + if( Len < sizeof(*msg) ) return -1; + + if( msg->First >= info->nLines ) + return 1; // Bad start + if( msg->Count > info->nLines - msg->First ) + return 1; // Bad count + if( msg->Count == 0 ) { + // No-op + return 0; + } + + // Find the range start + tRichText_Line *line = info->FirstLine; + tRichText_Line *prev = NULL; + while( line && line->Num < msg->First ) { + prev = line; + line = line->Next; + } + if( !line ) { + _SysDebug("RichText ScrollRange: Search for %i ran off end, nlines=%i", + msg->First, info->nLines); + } + + if( msg->Count < 0 ) + { + _SysDebug("TODO: RichText ScrollRange -ve"); + } + else + { + if( msg->First <= info->FirstVisRow && info->FirstVisRow < msg->First+msg->Range ) + info->FirstVisLine = NULL; + + // Remove 'msg->Count' lines from beginning of the range, ... + while( line && line->Num < msg->First + msg->Count ) + { + tRichText_Line *next = line->Next; + _SysDebug("- RichText ScrollRange: Remove %i '%.*s'", + line->Num, line->ByteLength, line->Data); + free(line); + line = next; + } + // Fix up list + if( prev ) + prev->Next = line; + else + info->FirstLine = line; + if(line) + line->Prev = prev; + // ... and shift ->Num down for the rest + for( ; line && line->Num < msg->First + msg->Range; line = line->Next ) + { + line->Num -= msg->Count; + if( line->Num >= info->FirstVisRow && !info->FirstVisLine ) + info->FirstVisLine = line; + } + + info->nLines -= msg->Count; + } + + info->bNeedsFullRedraw = 1; + + return 0; +} + void Renderer_RichText_HandleKeyFire(tWindow *Window, tRichText_Window *Info, const struct sWndMsg_KeyAction *Msg) { tRichText_Line *line = Info->CursorLine; diff --git a/Usermode/Applications/axwin3_src/include/richtext_messages.h b/Usermode/Applications/axwin3_src/include/richtext_messages.h index 7f53eb21..59e384c4 100644 --- a/Usermode/Applications/axwin3_src/include/richtext_messages.h +++ b/Usermode/Applications/axwin3_src/include/richtext_messages.h @@ -27,6 +27,7 @@ enum eRichText_IPCCalls IPC_RICHTEXT_ADDLINE, IPC_RICHTEXT_WRITELINE, // Set line contents IPC_RICHTEXT_READLINE, // Request line contents + IPC_RICHTEXT_SCROLLRANGE, N_IPC_RICHTEXT }; @@ -58,6 +59,13 @@ struct sRichTextIPC_WriteLine char LineData[]; }; +struct sRichTextIPC_ScrollRange +{ + uint32_t First; + uint16_t Range; + int16_t Count; +}; + enum { // Events diff --git a/Usermode/Applications/axwin3_src/libaxwin3.so_src/msg.c b/Usermode/Applications/axwin3_src/libaxwin3.so_src/msg.c index a9e41647..bb09a36d 100644 --- a/Usermode/Applications/axwin3_src/libaxwin3.so_src/msg.c +++ b/Usermode/Applications/axwin3_src/libaxwin3.so_src/msg.c @@ -12,6 +12,7 @@ #include // AxWin3 common #include "include/internal.h" #include "include/ipc.h" +#include #define assert(cnd) do{if(!(cnd)){_SysDebug("Assertion failed: %s", #cnd);}}while(0) @@ -127,12 +128,22 @@ void AxWin3_int_SendIPCMessage(tAxWin_IPCMessage *Msg) char tmpbuf[giAxWin3_int_UDPHeaderLen + size]; memcpy(tmpbuf, gaAxWin3_int_UDPHeader, giAxWin3_int_UDPHeaderLen); memcpy(tmpbuf + giAxWin3_int_UDPHeaderLen, Msg, size); - _SysWrite(giConnectionNum, tmpbuf, sizeof(tmpbuf)); + size_t rv = _SysWrite(giConnectionNum, tmpbuf, sizeof(tmpbuf)); + if( rv == -1 ) { + _SysDebug("AxWin3 SendIPCMessage: UDP Write Failed %s", strerror(errno)); + exit(1); + } } break; case CONNTYPE_IPCPIPE: - case CONNTYPE_TCP: - _SysWrite(giConnectionNum, Msg, size); + case CONNTYPE_TCP: { + size_t rv = _SysWrite(giConnectionNum, Msg, size); + if( rv != size ) { + _SysDebug("AxWin3 SendIPCMessage: Write Failed %s - sent %i want %i", + strerror(errno), rv, size); + exit(1); + } + } break; default: break; diff --git a/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_menu.c b/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_menu.c index 65525b98..9894abd0 100644 --- a/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_menu.c +++ b/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_menu.c @@ -87,7 +87,7 @@ tAxWin3_MenuItem *AxWin3_Menu_AddItem( _SysDebug("ERROR: Realloc Failed"); return NULL; } - + ret = &info->Items[info->nItems-1]; ret->ID = info->nItems - 1; ret->Window = Menu; @@ -96,11 +96,14 @@ tAxWin3_MenuItem *AxWin3_Menu_AddItem( ret->SubMenu = SubMenu; { - tMenuIPC_AddItem *req; - int data_size; if(!Label) Label = ""; - data_size = sizeof(*req)+strlen(Label)+1; + tMenuIPC_AddItem *req; + int data_size = sizeof(*req) + strlen(Label)+1; req = malloc(data_size); + if( !req ) { + free(ret); + return NULL; + } req->ID = ret->ID; req->Flags = Flags; req->SubMenuID = AxWin3_int_GetWindowID(SubMenu); 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 1ac98fe5..4e87f005 100644 --- a/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_richtext.c +++ b/Usermode/Applications/axwin3_src/libaxwin3.so_src/r_richtext.c @@ -54,7 +54,8 @@ static void _SendAttrib(tHWND Window, int Attr, uint32_t Value) tHWND AxWin3_RichText_CreateWindow(tHWND Parent, int Flags) { - tHWND ret = AxWin3_CreateWindow(Parent, "RichText", Flags, sizeof(tRichText_Window), AxWin3_RichText_MessageHandler); + tHWND ret = AxWin3_CreateWindow(Parent, "RichText", Flags, + sizeof(tRichText_Window), AxWin3_RichText_MessageHandler); // tRichText_Window *info = AxWin3_int_GetDataPtr(ret); return ret; } @@ -110,6 +111,22 @@ void AxWin3_RichText_SetCursorPos(tHWND Window, int Row, int Column) _SendAttrib(Window, _ATTR_CURSORPOS, ((Row & 0xFFFFF) << 12) | (Column & 0xFFF)); } +void AxWin3_RichText_ScrollRange(tHWND Window, int FirstRow, int RangeCount, int DownCount) +{ + if( FirstRow < 0 ) + return ; + if( RangeCount < -2 || RangeCount == 0 ) + return ; + if( RangeCount > 0 && DownCount > RangeCount ) + return ; + + struct sRichTextIPC_ScrollRange msg; + msg.First = FirstRow; + msg.Range = RangeCount; + msg.Count = DownCount; + AxWin3_SendIPC(Window, IPC_RICHTEXT_SCROLLRANGE, sizeof(msg), &msg); +} + void AxWin3_RichText_SendLine(tHWND Window, int Line, const char *Text) { // TODO: Local sanity check on `Line`? diff --git a/Usermode/Applications/axwin3_src/libaxwin3.so_src/wm.c b/Usermode/Applications/axwin3_src/libaxwin3.so_src/wm.c index f1ffd3b2..f1de00b7 100644 --- a/Usermode/Applications/axwin3_src/libaxwin3.so_src/wm.c +++ b/Usermode/Applications/axwin3_src/libaxwin3.so_src/wm.c @@ -325,9 +325,7 @@ void *AxWin3_WaitMessage(tHWND Window, int MessageID, size_t *Length) void AxWin3_SendIPC(tHWND Window, int Message, size_t Length, const void *Data) { - tAxWin_IPCMessage *msg; - - msg = AxWin3_int_AllocateIPCMessage(Window, Message, IPCMSG_FLAG_RENDERER, Length); + tAxWin_IPCMessage *msg = AxWin3_int_AllocateIPCMessage(Window, Message, IPCMSG_FLAG_RENDERER, Length); memcpy(msg->Data, Data, Length); AxWin3_int_SendIPCMessage(msg); free(msg); 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 89b4fc5f..8b091667 100644 --- a/Usermode/Libraries/libaxwin3.so_src/include_exp/axwin3/richtext.h +++ b/Usermode/Libraries/libaxwin3.so_src/include_exp/axwin3/richtext.h @@ -40,6 +40,14 @@ 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); +/* + * \brief Scroll the specified range of data down (moving lines up) + * \note This is NOT a visual scroll, it scrolls the data + * + * Top/Bottom `DownCount` lines are discarded (bottom if DownCount is -ve) + * UNLESS DownCount is -ve and RangeCount is -1 (indicating insertion of lines) + */ +extern void AxWin3_RichText_ScrollRange(tHWND Window, int FirstRow, int RangeCount, int DownCount); extern void AxWin3_RichText_SendLine(tHWND Window, int Line, const char *Text); #endif