Usermode/AxWin3 - Added scroll command to richtext renderer
authorJohn Hodge <[email protected]>
Tue, 10 Sep 2013 09:05:12 +0000 (17:05 +0800)
committerJohn Hodge <[email protected]>
Tue, 10 Sep 2013 09:05:44 +0000 (17:05 +0800)
Usermode/Applications/axwin3_src/WM/renderers/richtext.c
Usermode/Applications/axwin3_src/include/richtext_messages.h
Usermode/Applications/axwin3_src/libaxwin3.so_src/msg.c
Usermode/Applications/axwin3_src/libaxwin3.so_src/r_menu.c
Usermode/Applications/axwin3_src/libaxwin3.so_src/r_richtext.c
Usermode/Applications/axwin3_src/libaxwin3.so_src/wm.c
Usermode/Libraries/libaxwin3.so_src/include_exp/axwin3/richtext.h

index 63ee8e5..edf3c7d 100644 (file)
@@ -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;
index 7f53eb2..59e384c 100644 (file)
@@ -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
index a9e4164..bb09a36 100644 (file)
@@ -12,6 +12,7 @@
 #include <ipcmessages.h>       // AxWin3 common
 #include "include/internal.h"
 #include "include/ipc.h"
+#include <errno.h>
 
 #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;
index 65525b9..9894abd 100644 (file)
@@ -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);
index 1ac98fe..4e87f00 100644 (file)
@@ -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`?
index f1ffd3b..f1de00b 100644 (file)
@@ -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);
index 89b4fc5..8b09166 100644 (file)
@@ -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

UCC git Repository :: git.ucc.asn.au