Usermode/libaxwin4 - Handle demarshal failure
[tpg/acess2.git] / Usermode / Applications / irc_src / window.c
index 1314cec..ba12880 100644 (file)
@@ -7,6 +7,8 @@
 #include <stdio.h>     // TODO: replace with calls into ACurses_*
 #include <stdlib.h>
 #include <assert.h>
+#include "server.h"
+#include <ctype.h>
 
 struct sMessage
 {
@@ -14,6 +16,7 @@ struct sMessage
        time_t  Timestamp;
        enum eMessageClass      Class;
        char    *Source;        // Pointer to the end of `Data`
+       size_t  PrefixLen;
        char    Data[];
 };
 
@@ -28,12 +31,16 @@ struct sWindow
 
 // === PROTOTYPES ===
 void   Windows_RepaintCurrent(void);
+size_t WordBreak(const char *Line, size_t avail);
+size_t Windows_int_PaintMessagePrefix(const tMessage *Message, bool EnablePrint);
+size_t Windows_int_PaintMessageLine(const tMessage *Message, size_t Offset, bool EnablePrint);
+ int   Windows_int_GetMessageLines(const tMessage *Message);
  int   Windows_int_PaintMessage(tMessage *Message);
 
 // === GLOBALS ===
 tWindow        gWindow_Status = {
        NULL, NULL, NULL,       // No next, empty list, no server
-       0, {""} // No activity, empty name (rendered as status)
+       0, {"(status)"} // No activity, empty name (rendered as status)
 };
 tWindow        *gpWindows = &gWindow_Status;
 tWindow        *gpCurrentWindow = &gWindow_Status;
@@ -41,59 +48,142 @@ tWindow    *gpCurrentWindow = &gWindow_Status;
 // === CODE ===
 void Windows_RepaintCurrent(void)
 {
-       tMessage *msg = gpCurrentWindow->Messages;
-       
        // TODO: Title bar?
+       SetCursorPos(1, 1);
+       printf("\x1b[37;44m\x1b[2K%s\x1b[0m\n", gpCurrentWindow->Name);
+
+        int    avail_rows = giTerminal_Height - 3;
 
        // Note: This renders from the bottom up
-       for( int y = giTerminal_Height - 1; y -- && msg; msg = msg->Next)
+       tMessage *msg = gpCurrentWindow->Messages;
+       for( int y = avail_rows; msg && y > 0; )
        {
-               y -= Windows_int_PaintMessage(msg);
+               int lines = Windows_int_GetMessageLines(msg);
+               y -= lines;
+               size_t  ofs = 0;
+               size_t  len;
+                int    i = 0;
+               do {
+                       SetCursorPos(2 + y+i, 1);
+                       len = Windows_int_PaintMessageLine(msg, ofs, (y+i >= 0));
+                       ofs += len;
+                       i ++;
+               } while( len > 0 );
+               msg = msg->Next;
        }
 
+       // Status line is our department
+       SetCursorPos(giTerminal_Height-1, 1);
+       printf("\x1b[37;44m\x1b[2K[%s] [%s/%s]\x1b[0m", Server_GetNick(gpCurrentWindow->Server),
+               Server_GetName(gpCurrentWindow->Server), gpCurrentWindow->Name);
+       fflush(stdout);
        // Bottom line is rendered by the prompt
+}
+
+size_t WordBreak(const char *Line, size_t avail)
+{
+       // If sufficient space, don't need to break on a word
+       if( strlen(Line) < avail )
+               return strlen(Line);
+       
+       // Search backwards from end of space for a non-alpha-numeric character
+       size_t  ret = avail-1;
+       while( ret > 0 && isalnum(Line[ret]) )
+               ret --;
+       
+       // if one wasn't found in a sane area, just split
+       if( ret < avail-20 || ret == 0 )
+               return avail;
        
+       return ret;
 }
 
-int Windows_int_PaintMessage(tMessage *Message)
+size_t Windows_int_PaintMessagePrefix(const tMessage *Message, bool EnablePrint)
 {
-       printf("\33[T");        // Scroll down 1 (free space below)
-       SetCursorPos(giTerminal_Height-2, 1);
+       size_t  len = 0;
+       
+       unsigned long   seconds_today = Message->Timestamp/1000 % (24 * 3600);
+       if(EnablePrint)
+               printf("%02i:%02i:%02i ", seconds_today/3600, (seconds_today/60)%60, seconds_today%60);
+       else
+               len += snprintf(NULL, 0, "%02i:%02i:%02i ", seconds_today/3600, (seconds_today/60)%60, seconds_today%60);
        
-       size_t  prefixlen = 0;
-       prefixlen += printf("%02i:%02i:%02i ", (Message->Timestamp/3600)%24, (Message->Timestamp/60)%60, Message->Timestamp%60);
+       const char *format;
        switch(Message->Class)
        {
-       case MSG_CLASS_BARE:    break;
+       case MSG_CLASS_BARE:
+               format = "";
+               break;
        case MSG_CLASS_CLIENT:
                if(Message->Source)
-                       prefixlen += printf("[%s] ", Message->Source);
-               prefixlen += printf("-!- ");
+                       format = "[%s] -!- ";
+               else 
+                       format = "-!- ";
                break;
        case MSG_CLASS_WALL:
-               prefixlen += printf("[%s] ", Message->Source);
+               format = "[%s] ";
                break;
        case MSG_CLASS_MESSAGE:
-               prefixlen += printf("<%s> ", Message->Source);
+               format = "<%s> ";
                break;
        case MSG_CLASS_ACTION:
-               prefixlen += printf("* %s ", Message->Source);
+               format = "* %s ";
                break;
        }
-        int    avail = giTerminal_Width - prefixlen;
-        int    msglen = strlen(Message->Data);
-       
-       int     nLines = 1;
-       printf("%.*s", avail, Message);
-       while( msglen > avail ) {
-               msglen -= avail;
-               Message += avail;
-               printf("\33[T");
-               SetCursorPos(giTerminal_Height-2, prefixlen+1);
-               printf("%.*s", avail, Message);
-               nLines ++;
+       
+       if( EnablePrint )
+               len += printf(format, Message->Source);
+       else
+               len += snprintf(NULL, 0, format, Message->Source);
+
+       return len;
+}
+
+size_t Windows_int_PaintMessageLine(const tMessage *Message, size_t Offset, bool EnablePrint)
+{
+       _SysDebug("Windows_int_PaintMessageLine: Message=%p,Offset=%i,EnablePrint=%b",
+               Message, (int)Offset, EnablePrint);
+       if( Offset > strlen(Message->Data) ) {
+               _SysDebug("Windows_int_PaintMessageLine: No message left");
+               return 0;
        }
+       _SysDebug("Windows_int_PaintMessageLine: Message->Data=\"%.*s\"+\"%s\"",
+               (int)Offset, Message->Data, Message->Data+Offset);
        
+       size_t  avail = giTerminal_Width - Message->PrefixLen;
+       const char *msg_data = Message->Data + Offset;
+       int used = WordBreak(msg_data, avail);
+       
+       if( EnablePrint )
+       {
+               if( Offset == 0 )
+                       Windows_int_PaintMessagePrefix(Message, true);
+               else {
+                       for(int i = 0; i < Message->PrefixLen; i ++)
+                               printf(" ");
+                       //printf("\x1b[%iC", Message->PrefixLen);
+               }
+               printf("%.*s", used, msg_data);
+       }
+       
+       _SysDebug("used(%i) >= strlen(msg_data)(%i)", used, strlen(msg_data));
+       if( used >= strlen(msg_data) )
+               return 0;
+       
+       return Offset + used;
+}
+
+int Windows_int_GetMessageLines(const tMessage *Message)
+{
+       assert(Message->PrefixLen);
+       const size_t    avail = giTerminal_Height - Message->PrefixLen;
+       const size_t    msglen = strlen(Message->Data);
+       size_t  offset = 0;
+        int    nLines = 0;
+       do {
+               offset += WordBreak(Message->Data+offset, avail);
+               nLines ++;
+       } while(offset < msglen);
        return nLines;
 }
 
@@ -203,10 +293,18 @@ void Window_AppendMessage(tWindow *Window, enum eMessageClass Class, const char
        
        msg->Class = Class;
        msg->Source = (Source ? msg->Data + len+1 : NULL);
+       msg->Timestamp = _SysTimestamp();
+       
        va_start(args, Message);
        vsnprintf(msg->Data, len+1, Message, args);
        va_end(args);
        
+       if( Source ) {
+               strcpy(msg->Source, Source);
+       }
+       
+       msg->PrefixLen = Windows_int_PaintMessagePrefix(msg, false);
+       
        msg->Next = Window->Messages;
        Window->Messages = msg;
        
@@ -215,8 +313,15 @@ void Window_AppendMessage(tWindow *Window, enum eMessageClass Class, const char
                // Scroll if needed, and redraw?
                // - Lazy option of draw at bottom of screen
                printf("\33[s");        // Save cursor
-               Windows_int_PaintMessage(msg);
-               printf("\x1b[u");       // Restore cursor
+               size_t  offset = 0, len;
+               do {
+                       printf("\33[S");        // Scroll down 1 (free space below)
+                       SetCursorPos(giTerminal_Height-2, 1);
+                       len = Windows_int_PaintMessageLine(msg, offset, true);
+                       offset += len;
+               } while( len > 0 );
+               printf("\33[u");        // Restore cursor
+               fflush(stdout);
        }
 }
 
@@ -240,4 +345,14 @@ void Window_AppendMsg_TopicTime(tWindow *Window, const char *User, const char *T
 {
        Window_AppendMessage(Window, MSG_CLASS_CLIENT, NULL, "Topic set by %s at %s", User, Timestamp);
 }
+void Window_AppendMsg_Kick(tWindow *Window, const char *Operator, const char *Nick, const char *Reason)
+{
+       Window_AppendMessage(Window, MSG_CLASS_CLIENT, NULL, "%s was kicked from %s by %s [%s]",
+               Nick, Window->Name, Operator, Reason);
+}
+void Window_AppendMsg_Mode(tWindow *Window, const char *Operator, const char *Flags, const char *Args)
+{
+       Window_AppendMessage(Window, MSG_CLASS_CLIENT, NULL, "mode/%s [%s %s] by %s",
+               Window->Name, Flags, Args, Operator);
+}
 

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