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 ===
.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
}
};
{
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;
}
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;
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
{
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);
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;
#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)
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;
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;
}
_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`?