Merge branch 'master' of git://localhost/acess2
authorJohn Hodge <[email protected]>
Sun, 18 May 2014 06:27:39 +0000 (14:27 +0800)
committerJohn Hodge <[email protected]>
Sun, 18 May 2014 06:27:39 +0000 (14:27 +0800)
16 files changed:
KernelLand/Kernel/arch/x86/proc.asm
KernelLand/Kernel/arch/x86/proc.c
KernelLand/Kernel/arch/x86_64/desctab.asm
KernelLand/Kernel/arch/x86_64/mm_virt.c
KernelLand/Kernel/drv/vterm_termbuf.c
KernelLand/Kernel/drv/vterm_vt100.c
KernelLand/Modules/Network/E1000/e1000.c
Usermode/Applications/Makefile.tpl
Usermode/Applications/gui_terminal_src/vt100.c
Usermode/Applications/irc_src/input.c
Usermode/Applications/irc_src/main.c
Usermode/Applications/irc_src/server.c
Usermode/Applications/irc_src/server.h
Usermode/Applications/irc_src/window.c
Usermode/Applications/irc_src/window.h
Usermode/Libraries/libnet.so_src/address.c

index b8c01bc..be4c10d 100644 (file)
@@ -38,7 +38,7 @@ Proc_CloneInt:
        mov esi, [esp+0x20+8]
        mov [esi], eax
        ; Undo the pusha
-       add esp, 0x20
+       popa
        mov eax, .newTask
        ret
 .newTask:
index 5637985..460c920 100644 (file)
@@ -463,6 +463,14 @@ tTID Proc_NewKThread(void (*Fcn)(void*), void *Data)
        return newThread->TID;
 }
 
+#if 0
+tPID Proc_NewProcess(Uint Flags, void (*Fcn)(void*), size_t SaveSize, const void *Data)
+{
+       tThread *newThread = Threads_CloneTCB(CLONE_VM);
+       return 0;
+}
+#endif
+
 /**
  * \fn int Proc_Clone(Uint *Err, Uint Flags)
  * \brief Clone the current process
@@ -473,6 +481,7 @@ tPID Proc_Clone(Uint Flags)
        tThread *cur = Proc_GetCurThread();
        Uint    eip;
 
+       Log_Warning("Proc", "Proc_Clone is deprecated");
        // Sanity, please
        if( !(Flags & CLONE_VM) ) {
                Log_Error("Proc", "Proc_Clone: Don't leave CLONE_VM unset, use Proc_NewKThread instead");
@@ -482,6 +491,9 @@ tPID Proc_Clone(Uint Flags)
        // New thread
        newThread = Threads_CloneTCB(Flags);
        if(!newThread)  return -1;
+       ASSERT(newThread->Process);
+       //ASSERT(CheckMem(newThread->Process, sizeof(tProcess)));
+       //LOG("newThread->Process = %p", newThread->Process);
 
        newThread->KernelStack = cur->KernelStack;
 
@@ -490,6 +502,9 @@ tPID Proc_Clone(Uint Flags)
        if( eip == 0 ) {
                return 0;
        }
+       //ASSERT(newThread->Process);
+       //ASSERT(CheckMem(newThread->Process, sizeof(tProcess)));
+       //LOG("newThread->Process = %p", newThread->Process);
        newThread->SavedState.EIP = eip;
        newThread->SavedState.SSE = NULL;
        newThread->SavedState.bSSEModified = 0;
index e833173..e5e3f24 100644 (file)
@@ -404,7 +404,7 @@ SyscallStub:
        mov [rsp+0x10], rdi     ; Arg1
        mov [rsp+0x18], rsi     ; Arg2
        mov [rsp+0x20], rdx     ; Arg3
-       mov [rsp+0x28], r10     ; Arg4
+       mov [rsp+0x28], r10     ; Arg4 (r10 used in place of rcx)
        mov [rsp+0x30], r8      ; Arg5
        mov [rsp+0x38], r9      ; Arg6
 
index 3d89ea6..57308d7 100644 (file)
@@ -861,15 +861,16 @@ void *MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr)
        void    *ret;
        
        // Sanity Check
-       if(MaxBits < 12 || !PhysAddr)   return 0;
+       ASSERTCR(MaxBits, >=, 12, NULL);
        
        // Fast Allocate
        if(Pages == 1 && MaxBits >= PHYS_BITS)
        {
                phys = MM_AllocPhys();
-               *PhysAddr = phys;
                ret = MM_MapHWPages(phys, 1);
                MM_DerefPhys(phys);
+               if(PhysAddr)
+                       *PhysAddr = phys;
                return ret;
        }
        
@@ -880,7 +881,8 @@ void *MM_AllocDMA(int Pages, int MaxBits, tPAddr *PhysAddr)
        
        // Allocated successfully, now map
        ret = MM_MapHWPages(phys, Pages);
-       *PhysAddr = phys;
+       if(PhysAddr)
+               *PhysAddr = phys;
        // MapHWPages references the pages, so deref them back down to 1
        for(;Pages--;phys+=0x1000)
                MM_DerefPhys(phys);
@@ -897,9 +899,8 @@ void *MM_MapTemp(tPAddr PAddr)
 {
        const int max_slots = (MM_TMPMAP_END - MM_TMPMAP_BASE) / PAGE_SIZE;
        tVAddr  ret = MM_TMPMAP_BASE;
-        int    i;
        
-       for( i = 0; i < max_slots; i ++, ret += PAGE_SIZE )
+       for( int i = 0; i < max_slots; i ++, ret += PAGE_SIZE )
        {
                tPAddr  *ent;
                if( MM_GetPageEntryPtr( ret, 0, 1, 0, &ent) < 0 ) {
index 5078722..fed577a 100644 (file)
@@ -176,6 +176,8 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch)
 
        HEAP_VALIDATE();
        
+       // TODO: Schedule a delayed screen update
+       
        //LEAVE('-');
 }
 
index 4428b64..1399d7b 100644 (file)
@@ -5,7 +5,7 @@
  * drv/vterm_vt100.c
  * - Virtual Terminal - VT100 (Kinda) Emulation
  */
-#define DEBUG  0
+#define DEBUG  1
 #include "vterm.h"
 
 #define sTerminal      sVTerm
@@ -44,7 +44,7 @@ void Display_ScrollDown(tTerminal *Term, int CountDown)
        LOG("(%i)", CountDown);
        VT_int_UpdateScreen(Term, 0);
        if( Term->Flags & VT_FLAG_ALTBUF )
-               VT_int_ScrollText(Term, CountDown);
+               VT_int_ScrollText(Term, -CountDown);
        else
        {
                if(Term->ViewTopRow + CountDown < 0)
index 0ad49b0..600f334 100644 (file)
@@ -64,6 +64,7 @@ int E1000_Install(char **Arguments)
        // Allocate card array
        gaE1000_Cards = calloc(sizeof(tCard), card_count);
        if( !gaE1000_Cards ) {
+               Log_Warning("E1000", "Allocation of %i card structures failed", card_count);
                return MODULE_ERR_MALLOC;
        }       
 
@@ -88,6 +89,7 @@ int E1000_Install(char **Arguments)
                        Log_Debug("E1000", "Card %i: %P IRQ %i", card_idx, card->MMIOBasePhys, card->IRQ);
 
                        if( E1000_int_InitialiseCard(card) ) {
+                               Log_Warning("E1000", "Initialisation of card #%i failed", card_idx);
                                return MODULE_ERR_MALLOC;
                        }
                        
index a6c8508..2b645af 100644 (file)
@@ -56,8 +56,7 @@ $(_OBJPREFIX)%.o: %.c
 ifneq ($(_OBJPREFIX),)
        @mkdir -p $(dir $@)
 endif
-       $V$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
-       $V$(CC) -M -MP -MT $@ $(CPPFLAGS) $< -o $(_OBJPREFIX)$*.dep
+       $V$(CC)  $(CFLAGS)   $(CPPFLAGS) -c $< -o $@ -MQ $@ -MP -MD -MF $(_OBJPREFIX)$*.dep
 
 $(_OBJPREFIX)%.o: %.cpp
        @echo [CXX] -o $@
index cdf5371..4c35bfd 100644 (file)
@@ -17,6 +17,8 @@
 # include <assert.h>
 # include <stdlib.h>   // malloc/free
 
+# define ASSERTC(a, r, b)      assert(a r b)
+
 static inline int MIN(int a, int b)
 {
        return a < b ? a : b;
@@ -170,7 +172,7 @@ int Term_HandleVT100(tTerminal *Term, int Len, const char *Buf)
                        if( ret <= old_inc_len ) {
                                _SysDebug("Term_HandleVT100: ret(%i) <= old_inc_len(%i), inc_len=%i, '%*C'",
                                        ret, old_inc_len, st->cache_len, st->cache_len, st->cache);
-                               assert(ret > old_inc_len);
+                               ASSERTC(ret, >, old_inc_len);
                        }
                        st->cache_len = 0;
                        //_SysDebug("%i bytes of escape code '%.*s' (return %i)",
@@ -446,9 +448,13 @@ int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer)
                        Display_MoveCursor(Term, 0, -(args[0] != 0 ? args[0] : 1));
                        break;
                case 'H':
-                       if( argc != 2 ) {
+                       if( argc == 0 ) {
+                               Display_SetCursor(Term, 0, 0);
                        }
-                       else {
+                       else if( argc == 1 ) {
+                               Display_SetCursor(Term, args[0]-1, 0);
+                       }
+                       else if( argc == 2 ) {
                                // Adjust 1-based cursor position to 0-based
                                Display_SetCursor(Term, args[0]-1, args[1]-1);
                        }
@@ -631,7 +637,7 @@ int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer)
                        break;
                // Set scrolling region
                case 'r':
-                       Display_SetScrollArea(Term, args[0], (args[1] - args[0]));
+                       Display_SetScrollArea(Term, args[0]-1, (args[1] - args[0])+1);
                        break;
                
                case 's':
index 2236152..b99935c 100644 (file)
@@ -42,9 +42,11 @@ void Input_HandleSelect(int nfds, const fd_set *rfds)
                        }
                        free(cmd);
                        // Prompt
-                       SetCursorPos(giTerminal_Height-1, 1);
+                       SetCursorPos(giTerminal_Height, 1);
                        printf("\x1B[2K");      // Clear line
-                       printf("[%s]", Window_GetName(NULL));
+                       int prompt_len = printf("[%s] ", Window_GetName(NULL));
+                       SetCursorPos(giTerminal_Height, prompt_len+1);
+                       fflush(stdout);
                }
        }
 }
@@ -104,6 +106,15 @@ void Cmd_window(char *ArgString)
        }
 }
 
+void Cmd_me(char *ArgString)
+{
+       tServer *srv = Window_GetServer(NULL);
+       if( srv && Window_IsChat(NULL) ) {
+               Window_AppendMessage(NULL, MSG_CLASS_ACTION, Server_GetNick(srv), "%s", ArgString);
+               Server_SendCommand(srv, "PRIVMSG %s :\1ACTION %s\1\n", Window_GetName(NULL), ArgString);
+       }
+}
+
 const struct {
        const char *Name;
        void    (*Fcn)(char *ArgString);
index e3e2af4..6169519 100755 (executable)
@@ -7,6 +7,7 @@
 #include <string.h>
 #include <net.h>
 #include <stdarg.h>
+#include <acess/devices/pty.h>
 
 #include "common.h"
 #include "input.h"
@@ -35,6 +36,11 @@ void ExitHandler(void)
 {
        printf("\x1B[?1047l");
        printf("Quit: %s\n", gsExitReason);
+
+       // stty +echo,canon
+       struct ptymode  mode = {.InputMode = 0, .OutputMode = 0};
+       mode.InputMode = PTYIMODE_CANON|PTYIMODE_ECHO;
+       _SysIOCtl(0, PTY_IOCTL_SETMODE, &mode);
 }
 
 void Exit(const char *Reason)
@@ -55,24 +61,21 @@ int main(int argc, const char *argv[], const char *envp[])
        ACurses_Init();
        
        printf("\x1B[?1047h");
-       printf("\x1B[%i;%ir", 1, giTerminal_Height-1);
-       
-       SetCursorPos(giTerminal_Height-1, 1);
-       printf("[(status)] ");
+       printf("\x1B[%i;%ir", 2, giTerminal_Height-2);
        
        // HACK: Static server entry
        // UCC (University [of Western Australia] Computer Club) IRC Server
-       tServer *starting_server = Server_Connect( "UCC", "130.95.13.18", 6667 );
+//     tServer *starting_server = Server_Connect( "UCC", "130.95.13.18", 6667 );
        // Freenode (#osdev)
-//     gWindow_Status.Server = Server_Connect( "Freenode", "89.16.176.16", 6667 );
+       tServer *starting_server = Server_Connect( "Freenode", "84.240.3.129", 6667 );
        // Local servers
 //     gWindow_Status.Server = Server_Connect( "VMHost", "10.0.2.2", 6667 );
 //     gWindow_Status.Server = Server_Connect( "BitlBee", "192.168.1.39", 6667 );
        
-       if( !starting_server )
-               return -1;
-       
        Windows_SetStatusServer(starting_server);
+       Windows_RepaintCurrent();
+       SetCursorPos(giTerminal_Height-1, 1);
+       printf("[(status)] ");
        
        MainLoop();
 
@@ -83,10 +86,14 @@ int main(int argc, const char *argv[], const char *envp[])
 
 int MainLoop(void)
 {
-       SetCursorPos(giTerminal_Height-1, 1);
+       SetCursorPos(giTerminal_Height, 1);
        printf("[(status)] ");
        fflush(stdout);
        
+       // stty -echo,canon
+       struct ptymode  mode = {.InputMode = 0, .OutputMode = 0};
+       _SysIOCtl(0, PTY_IOCTL_SETMODE, &mode);
+       
        for( ;; )
        {
                fd_set  readfds, errorfds;
@@ -121,7 +128,7 @@ int ParseArguments(int argc, const char *argv[])
 void Redraw_Screen(void)
 {
        printf("\x1B[2J");      // Clear screen
-       printf("\x1B[0;0H");    // Reset cursor
+       printf("\x1B[H");       // Reset cursor
 
        Windows_RepaintCurrent();
 }
index c8bfea5..1b85df4 100644 (file)
@@ -16,8 +16,9 @@ void  ParseServerLine(tServer *Server, char *Line);
 // === GLOBALS ===
 const char     *gsUsername = "user";
 const char     *gsHostname = "acess";
-const char     *gsRealName = "Acess2 IRC Client";
+const char     *gsRealName = "An Acess User";
 const char     *gsNickname = "acess";
+const char     *gsVersionResponse = "Acess2 IRC Client / Running on some VM probably";
 tServer        *gpServers;
 
 // === CODE ===
@@ -109,7 +110,11 @@ tServer *Server_Connect(const char *Name, const char *AddressString, short PortN
 
 const char *Server_GetNick(const tServer *Server)
 {
-       return Server->Nick;
+       return Server ? Server->Nick : "NULL";
+}
+const char *Server_GetName(const tServer *Server)
+{
+       return Server ? Server->Name : "NULL";
 }
 
 void Server_SendCommand(tServer *Server, const char *Format, ...)
@@ -134,16 +139,40 @@ void Cmd_PRIVMSG(tServer *Server, const char *Dest, const char *Src, const char
 {
        tWindow *win;
        if( strcmp(Dest, Server->Nick) == 0 ) {
-               win = Windows_GetByName(Server, Src);
-               if(!win)
-                       win = Window_Create(Server, Src);
+               win = Windows_GetByNameOrCreate(Server, Src);
        }
        else {
-               win = Windows_GetByName(Server, Dest);
-               if(!win)
-                       win = Window_Create(Server, Dest);
+               win = Windows_GetByNameOrCreate(Server, Dest);
+       }
+       
+       // Detect CTCP
+       if( Message[0] == '\1' && Message[strlen(Message)-1] == '\1' )
+       {
+               Message += 1;
+               // message is a CTCP command
+               if( strcmp(Message, "VERSION\1") == 0 )
+               {
+                       // Put a message in the status window, and reply
+                       Window_AppendMessage(WINDOW_STATUS, MSG_CLASS_CLIENT, Server->Name, "CTCP VERSION request from %s", Src);
+                       // - Always reply via NOTICE
+                       Server_SendCommand(Server, "NOTICE %s :\1VERSION %s\1", Src, gsVersionResponse);
+               }
+               else if( strncmp(Message, "ACTION ", 7) == 0 )
+               {
+                       Message += 7;
+                       // Put a message in the status window, and reply
+                       Window_AppendMessage(win, MSG_CLASS_ACTION, Src, "%.*s", (int)(strlen(Message)-1), Message);
+               }
+               else
+               {
+                       Window_AppendMessage(WINDOW_STATUS, MSG_CLASS_CLIENT, Server->Name, "Unknown CTCP '%s' from %s",
+                               Message, Src);
+               }
+       }
+       else
+       {
+               Window_AppendMessage(win, MSG_CLASS_MESSAGE, Src, "%s", Message);
        }
-       Window_AppendMessage(win, MSG_CLASS_MESSAGE, Src, "%s", Message);
 }
 
 /**
@@ -226,20 +255,38 @@ void ParseServerLine_Numeric(tServer *Server, const char *ident, int Num, char *
                Window_AppendMsg_TopicTime( Windows_GetByNameOrCreate(Server, user), message, timestamp );
                break;
        case 353:       // /NAMES list
+               // TODO: Parse the /names list and store it locally, dump to window when end is seen
                // <user> = <channel> :list
                // '=' was eaten in and set to message
                user = GetValue(Line, &pos);    // Actually channel
                message = Line + pos + 1;       // List
-               // TODO: parse and store
                Window_AppendMessage( Windows_GetByNameOrCreate(Server, user), MSG_CLASS_CLIENT, "NAMES", message );
                break;
        case 366:       // end of /NAMES list
                // <user> <channel> :msg
                // - Ignored
                break;
+
+       case   1:       // welcome
+       case   2:       // host name and version (text)
+       case   3:       // host uptime
+       case   4:       // host name, version, and signature
+       case   5:       // parameters
+       
+       case 250:       // Highest connection count
+       case 251:       // user count (network)
+       case 252:       // Operator count
+       case 253:       // Unidentified connections
+       case 254:       // Channel count
+       case 255:       // Server's stats
+       case 265:       // Local users -- min max :Text representation
+       case 266:       // Global users (same as above)
+       
        case 372:       // MOTD Data
        case 375:       // MOTD Start
        case 376:       // MOTD End
+               Window_AppendMessage( WINDOW_STATUS, MSG_CLASS_WALL, Server->Name, "%s", message);
+               break;
                
        default:
                //printf("[%s] %i %s\n", Server->Name, num, message);
@@ -255,11 +302,9 @@ void ParseServerLine_String(tServer *Server, const char *ident, const char *cmd,
        if( strcmp(cmd, "NOTICE") == 0 )
        {
                const char *class = GetValue(Line, &pos);
-               _SysDebug("NOTICE class='%s'", class);
-               
                const char *message = (Line[pos] == ':') ? Line + pos + 1 : GetValue(Line, &pos);
+               _SysDebug("NOTICE class='%s'", class);
                
-               //printf("[%s] NOTICE %s: %s\n", Server->Name, ident, message);
                char *ident_bang = strchr(ident, '!');
                if( ident_bang ) {
                        *ident_bang = '\0';
@@ -290,6 +335,28 @@ void ParseServerLine_String(tServer *Server, const char *ident, const char *cmd,
                
                Window_AppendMsg_Part( Windows_GetByNameOrCreate(Server, channel), ident, "" );
        }
+       else if( strcmp(cmd, "MODE" ) == 0 )
+       {
+               // ident MODE channel flags nick[ nick...]
+               const char      *channel = GetValue(Line, &pos);
+               const char      *flags = GetValue(Line, &pos);
+               const char      *args = Line + pos;
+               
+               Window_AppendMsg_Mode( Windows_GetByNameOrCreate(Server, channel), ident, flags, args );
+       }
+       else if( strcmp(cmd, "KICK" ) == 0 )
+       {
+               // ident KICK channel nick :reason
+               const char      *channel = GetValue(Line, &pos);
+               const char      *nick = GetValue(Line, &pos);
+               const char      *message = Line + pos + 1;
+               
+               Window_AppendMsg_Kick( Windows_GetByNameOrCreate(Server, channel), ident, nick, message );
+               if( strcmp(nick, Server->Nick) == 0 ) {
+                       // Oh, that was me :(
+                       // - what do?
+               }
+       }
        else
        {
                Window_AppendMessage( WINDOW_STATUS, MSG_CLASS_BARE, Server->Name, "Unknown command '%s' %s", cmd, Line);
index 0fd4f51..edc9bd0 100644 (file)
@@ -22,6 +22,7 @@ extern tServer        *Server_Connect(const char *Name, const char *AddressString, shor
 extern  int    Server_HandleIncoming(tServer *Server);
 
 extern const char      *Server_GetNick(const tServer *Server);
+extern const char      *Server_GetName(const tServer *Server);
 
 extern void    Server_SendCommand(tServer *Server, const char *Format, ...) __attribute__((format(__printf__,2,3)));
 
index 1314cec..db3e4da 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,133 @@ 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)
+{
+       if( Message->Data[Offset] == '\0' ) {
+               return 0;
        }
        
+       size_t  avail = giTerminal_Width - Message->PrefixLen;
+       const char *msg_data = Message->Data + Offset;
+       int used = WordBreak(msg_data+Offset, avail);
+       
+       if( EnablePrint )
+       {
+               if( Offset == 0 )
+                       Windows_int_PaintMessagePrefix(Message, true);
+               else
+                       printf("\x1b[%iC", Message->PrefixLen);
+               printf("%.*s", used, msg_data);
+       }
+       
+       if( msg_data[used] == '\0' )
+               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 +284,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 +304,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[T");        // Scroll down 1 (free space below)
+                       SetCursorPos(giTerminal_Height-2, 1);
+                       len = Windows_int_PaintMessageLine(Message, offset, true);
+                       offset += len;
+               } while( len > 0 );
+               printf("\33[u");        // Restore cursor
+               fflush(stdout);
        }
 }
 
@@ -240,4 +336,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);
+}
 
index da97f3e..620e1a5 100644 (file)
@@ -24,6 +24,8 @@ extern void   Window_AppendMessage(tWindow *Window, enum eMessageClass Class, cons
 extern void    Window_AppendMsg_Join(tWindow *Window, const char *Usermask);
 extern void    Window_AppendMsg_Quit(tWindow *Window, const char *Usermask, const char *Reason);
 extern void    Window_AppendMsg_Part(tWindow *Window, const char *Usermask, const char *Reason);
+extern void    Window_AppendMsg_Kick(tWindow *Window, const char *Operator, const char *Nick, const char *Reason);
+extern void    Window_AppendMsg_Mode(tWindow *Window, const char *Operator, const char *Flags, const char *Args);
 extern void    Window_AppendMsg_Topic(tWindow *Window, const char *Topic);
 extern void    Window_AppendMsg_TopicTime(tWindow *Window, const char *User, const char *Timestmap);
 
index 66a28b1..8887362 100644 (file)
@@ -7,7 +7,8 @@
  */
 #include <net.h>
 #include <stdint.h>
-#include <stdio.h>
+//#include <stdio.h>
+#include <stdlib.h>
 #define DEBUG  0
 
 static inline uint32_t htonl(uint32_t v)
@@ -37,43 +38,50 @@ static inline uint16_t htons(uint16_t v)
  */
 static int Net_ParseIPv4Addr(const char *String, uint8_t *Addr)
 {
-        int    i = 0;
         int    j;
-        int    val;
+       const char *pos = String;
        
-       for( j = 0; String[i] && j < 4; j ++ )
+       for( j = 0; *pos && j < 4; j ++ )
        {
-               val = 0;
-               for( ; String[i] && String[i] != '.'; i++ )
-               {
-                       if('0' > String[i] || String[i] > '9') {
-                               #if DEBUG
-                               printf("0<c<9 expected, '%c' found\n", String[i]);
-                               #endif
-                               return 0;
-                       }
-                       val = val*10 + String[i] - '0';
+               char    *end;
+               unsigned long val = strtoul(pos, &end, 10);
+               if( *end && *end != '.' ) {
+                       #if DEBUG
+                       _SysDebug("%s: Unexpected character, '%c' found", __func__, *end);
+                       #endif
+                       return 0;
+               }
+               if( *pos == '.' ) {
+                       #if DEBUG
+                       _SysDebug("%s: Two dots in a row", __func__);
+                       #endif
+                       return 0;
                }
                if(val > 255) {
                        #if DEBUG
-                       printf("val > 255 (%i)\n", val);
+                       _SysDebug("%s: val > 255 (%i)", __func__, val);
                        #endif
                        return 0;
                }
+               #if DEBUG
+               _SysDebug("%s: Comp '%.*s' = %lu", __func__, end - pos, pos, val);
+               #endif
                Addr[j] = val;
                
-               if(String[i] == '.')
-                       i ++;
+               pos = end;
+               
+               if(*pos == '.')
+                       pos ++;
        }
        if( j != 4 ) {
                #if DEBUG
-               printf("4 parts expected, %i found\n", j);
+               _SysDebug("%s: 4 parts expected, %i found", __func__, j);
                #endif
                return 0;
        }
-       if(String[i] != '\0') {
+       if(*pos != '\0') {
                #if DEBUG
-               printf("EOS != '\\0', '%c'\n", String[i]);
+               _SysDebug("%s: EOS != '\\0', '%c'", __func__, *pos);
                #endif
                return 0;
        }

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