Usermode/GUI Terminal - Renamed folder
authorJohn Hodge <[email protected]>
Sun, 8 Sep 2013 11:59:17 +0000 (19:59 +0800)
committerJohn Hodge <[email protected]>
Sun, 8 Sep 2013 11:59:17 +0000 (19:59 +0800)
13 files changed:
Makefile
Usermode/Applications/gui_shell_src/Makefile [deleted file]
Usermode/Applications/gui_shell_src/display.c [deleted file]
Usermode/Applications/gui_shell_src/include/display.h [deleted file]
Usermode/Applications/gui_shell_src/include/vt100.h [deleted file]
Usermode/Applications/gui_shell_src/main.c [deleted file]
Usermode/Applications/gui_shell_src/vt100.c [deleted file]
Usermode/Applications/gui_terminal_src/Makefile [new file with mode: 0644]
Usermode/Applications/gui_terminal_src/display.c [new file with mode: 0644]
Usermode/Applications/gui_terminal_src/include/display.h [new file with mode: 0644]
Usermode/Applications/gui_terminal_src/include/vt100.h [new file with mode: 0644]
Usermode/Applications/gui_terminal_src/main.c [new file with mode: 0644]
Usermode/Applications/gui_terminal_src/vt100.c [new file with mode: 0644]

index 3940b3e..f450dd7 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -21,7 +21,7 @@ EXTLIBS :=
 USRAPPS := init login CLIShell cat ls mount automounter
 USRAPPS += bomb lspci
 USRAPPS += ip dhcpclient ping telnet irc wget telnetd
-USRAPPS += axwin3 gui_ate gui_shell
+USRAPPS += axwin3 gui_ate gui_terminal
 
 define targetclasses
  AI_$1      := $$(addprefix allinstall-,$$($1))
diff --git a/Usermode/Applications/gui_shell_src/Makefile b/Usermode/Applications/gui_shell_src/Makefile
deleted file mode 100644 (file)
index a38f135..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-# Project: [GUI] Terminal
-
--include ../Makefile.cfg
-
-LDFLAGS += -laxwin3 -lunicode
-
-OBJ = main.o vt100.o display.o
-BIN = terminal
-DIR := Apps/AxWin/3.0
-
--include ../Makefile.tpl
diff --git a/Usermode/Applications/gui_shell_src/display.c b/Usermode/Applications/gui_shell_src/display.c
deleted file mode 100644 (file)
index 0049608..0000000
+++ /dev/null
@@ -1,332 +0,0 @@
-/*
- * Acess GUI Terminal
- * - By John Hodge (thePowersGang)
- *
- * display.c
- * - Abstract display manipulation methods
- */
-#include "include/display.h"
-#include <acess/sys.h> // _SysDebug
-#include <stdlib.h>    // exit
-#include <string.h>
-#include <unicode.h>
-#include <stdio.h>
-#include <axwin3/axwin.h>
-#include <axwin3/richtext.h>
-#include <stdbool.h>
-#include <assert.h>
-
-#define UNIMPLIMENTED()        do{_SysDebug("UNIMPLIMENTED %s", __func__); exit(-1);}while(0)
-
-// === EXTERN ==
-extern tHWND   gMainWindow;
-
-typedef struct sLine   tLine;
-
-struct sLine {
-       char    *Data;
-       // TODO: Cache offsets to avoid scan-forward
-       size_t  Len;
-       size_t  Size;
-       bool    IsDirty;
-};
-
-struct sTerminal {
-        int    ViewCols;
-        int    ViewRows;
-
-        int    CursorRow;
-        int    CursorCol;
-
-       size_t  CursorByte;
-
-       bool    bUsingAltBuf;
-
-       size_t  ViewOffset;     
-       size_t  TotalLines;
-       struct sLine    *PriBuf;
-       
-       struct sLine    *AltBuf;
-};
-
-// === GLOBALS ===
-tTerminal      gMainBuffer;
- int   giCurrentLine;
- int   giCurrentLinePos;       // byte offset, not column
- int   giCurrentCol;
- int   giFirstDispLine;        // First displayed line
- int   giFirstLine;    // Ring buffer start
-char   **gasDisplayLines;
- int   *gaiDisplayLineSizes;
-char   *gabDisplayLinesDirty;
-
-// === CODE ===
-tTerminal *Display_Init(int Cols, int Lines, int ExtraScrollbackLines)
-{
-       tTerminal       *term = &gMainBuffer;
-       term->ViewCols = Cols;
-       term->ViewRows = Lines;
-       term->TotalLines = Lines + ExtraScrollbackLines;
-       term->PriBuf = calloc( sizeof(tLine), (Lines + ExtraScrollbackLines) );
-       
-       AxWin3_RichText_SetLineCount(gMainWindow, Lines+ExtraScrollbackLines);
-       AxWin3_RichText_SetCursorType(gMainWindow, 1);  // TODO: enum
-       return term;
-}
-
-// Return the byte length of a single on-screen character
-size_t _GetCharLength(size_t AvailLength, const char *Text, uint32_t *BaseCodepoint)
-{
-       if( !AvailLength )
-               return 0;
-       
-       size_t  charlen = ReadUTF8(Text, BaseCodepoint);
-       
-       while(charlen < AvailLength)
-       {
-               uint32_t        cp;
-               size_t size = ReadUTF8(Text+charlen, &cp);
-               if( Unicode_IsPrinting(cp) )
-                       break;
-               charlen += size;
-       }
-       
-       return charlen;
-}
-
-tLine *Display_int_GetCurLine(tTerminal *Term)
-{
-        int    lineidx = Term->CursorRow + (Term->bUsingAltBuf ? 0 : Term->ViewOffset);
-       return (Term->bUsingAltBuf ? Term->AltBuf : Term->PriBuf) + lineidx;
-}
-
-size_t Display_int_PushCharacter(tTerminal *Term, size_t AvailLength, const char *Text)
-{
-       tLine   *lineptr = Display_int_GetCurLine(Term);
-       uint32_t        cp;
-       size_t  charlen = _GetCharLength(AvailLength, Text, &cp);
-       bool    bOverwrite = Unicode_IsPrinting(cp);
-       
-       _SysDebug("Line %b:%i += %i '%.*s'", Term->bUsingAltBuf, Term->CursorRow, charlen, charlen, Text);
-
-       // Figure out how much we need to shift the stream
-        int    shift;
-       if( bOverwrite ) {
-               size_t nextlen = _GetCharLength(
-                       lineptr->Len-Term->CursorByte,
-                       lineptr->Data+Term->CursorByte,
-                       NULL);
-               _SysDebug("Char at +%i is %i long (%.*s)", Term->CursorByte, nextlen,
-                               nextlen, lineptr->Data+Term->CursorByte);
-               shift = charlen - nextlen;
-       }
-       else {
-               shift = charlen;
-       }
-       _SysDebug("shift = %i", shift);
-       
-       // Ensure we have space enough
-       if( !lineptr->Data || shift > 0 ) {
-               const size_t    size_step = 64;
-               assert(shift > 0);
-               lineptr->Size = (lineptr->Len+shift+1 + size_step-1) & ~(size_step-1);
-               void *tmp = realloc(lineptr->Data, lineptr->Size);
-               if( !tmp )      perror("Display_int_PushCharacter - realloc");
-               lineptr->Data = tmp;
-       }
-       
-       // Insert into stream
-       char    *base = lineptr->Data + Term->CursorByte;
-       if( Term->CursorByte == lineptr->Len ) {
-               // No shifting needed
-       }
-       else if( shift >= 0 ) {
-               size_t  bytes = lineptr->Len - (Term->CursorByte+shift);
-               _SysDebug("memmove(base+%i, base, %i)", shift, bytes);
-               memmove(base+shift, base, bytes);
-       }
-       else {
-               shift = -shift;
-               size_t  bytes = lineptr->Len - (Term->CursorByte+shift);
-               _SysDebug("memmove(base, base+%i, %i)", shift, bytes);
-               memmove(base, base+shift, bytes);
-       }
-       memcpy(base, Text, charlen);
-       lineptr->IsDirty = true;
-       lineptr->Len += shift;
-       lineptr->Data[lineptr->Len] = 0;        // NULL Terminate
-
-       Term->CursorByte += charlen;
-       
-       // HACKY: Prevents the CursorCol++ in Display_AddText from having an effect
-       if( !bOverwrite )
-               Term->CursorCol --;
-       
-       return charlen;
-}
-
-void Display_AddText(tTerminal *Term, size_t Length, const char *UTF8Text)
-{
-       _SysDebug("%i '%.*s'", Length, Length, UTF8Text);
-       while( Length > 0 )
-       {
-               size_t used = Display_int_PushCharacter(Term, Length, UTF8Text);
-       
-               Length -= used;
-               UTF8Text += used;
-               
-               Term->CursorCol ++;
-               if( Term->CursorCol == Term->ViewCols ) {
-                       Display_Newline(Term, 1);
-               }
-       }
-}
-
-void Display_Newline(tTerminal *Term, bool bCarriageReturn)
-{
-//     Display_Flush();
-
-       // Going down!
-       Term->CursorRow ++;
-       if( Term->CursorRow == Term->TotalLines ) {
-               // TODO: Scrolling
-       }
-       
-       if( bCarriageReturn ) {
-               Term->CursorByte = 0;
-               Term->CursorCol = 0;
-               return ;
-       }
-
-       tLine   *line = Display_int_GetCurLine(Term);
-       
-       Term->CursorByte = 0;
-        int    old_col = Term->CursorCol;
-       Term->CursorCol = 0;
-
-       size_t  ofs = 0;
-       while( Term->CursorCol < old_col && ofs < line->Len ) {
-               ofs += _GetCharLength(line->Len-ofs, line->Data+ofs, NULL);
-               Term->CursorCol ++;
-       }
-       Term->CursorByte = ofs;
-
-       while( Term->CursorCol < old_col )
-               Display_AddText(Term, 1, " ");
-}
-
-void Display_SetCursor(tTerminal *Term, int Row, int Col)
-{
-       UNIMPLIMENTED();
-}
-
-void Display_MoveCursor(tTerminal *Term, int RelRow, int RelCol)
-{
-       if( RelRow != 0 )
-       {
-               UNIMPLIMENTED();
-       }
-       
-       if( RelCol != 0 )
-       {
-               int req_col = Term->CursorCol + RelCol;
-               if( req_col < 0 )       req_col = 0;
-               if( req_col > Term->ViewCols )  req_col = Term->ViewCols;
-
-               tLine   *line = Display_int_GetCurLine(Term);
-               size_t  ofs = 0;
-               for( int i = 0; i < req_col; i ++ )
-               {
-                       size_t clen = _GetCharLength(line->Len-ofs, line->Data+ofs, NULL);
-                       if( clen == 0 ) {
-                               req_col = i;
-                               break;
-                       }
-                       ofs += clen;
-               }
-
-               Term->CursorCol = req_col;
-               Term->CursorByte = ofs;
-       }
-}
-
-void Display_ClearLine(tTerminal *Term, int Dir)       // 0: All, 1: Forward, -1: Reverse
-{
-       if( Dir == 0 )
-       {
-               tLine   *line = Display_int_GetCurLine(Term);
-               // Completely clear line
-               if( line->Data )
-                       free(line->Data);
-               line->Data = NULL;
-               line->IsDirty = true;
-       }
-       else if( Dir == 1 )
-       {
-               // Forward clear (truncate)
-       }
-       else if( Dir == -1 )
-       {
-               // Reverse clear (replace with spaces)
-       }
-       else
-       {
-               // BUGCHECK
-       }
-}
-
-void Display_ClearLines(tTerminal *Term, int Dir)      // 0: All, 1: Forward, -1: Reverse
-{
-       if( Dir == 0 )
-       {
-               // Push giDisplayLines worth of empty lines
-               // Move cursor back up by giDisplayLines
-       }
-       else if( Dir == 1 )
-       {
-               // Push (giDisplayLines - (giCurrentLine-giFirstDispLine)) and reverse
-       }
-       else if( Dir == -1 )
-       {
-               // Reverse clear (replace with spaces)
-       }
-       else
-       {
-               // BUGCHECK
-       }
-}
-
-void Display_SetForeground(tTerminal *Term, uint32_t RGB)
-{
-       char    buf[7+1];
-       sprintf(buf, "\1%06x", RGB&0xFFFFFF);
-       Display_AddText(Term, 7, buf);
-}
-
-void Display_SetBackground(tTerminal *Term, uint32_t RGB)
-{
-       char    buf[7+1];
-       sprintf(buf, "\2%06x", RGB&0xFFFFFF);
-       Display_AddText(Term, 7, buf);
-}
-
-void Display_Flush(tTerminal *Term)
-{
-       for( int i = 0; i < Term->ViewRows; i ++ )
-       {
-                int    line = (Term->ViewOffset + i) % Term->TotalLines;
-               tLine   *lineptr = &Term->PriBuf[line];
-               if( !lineptr->IsDirty )
-                       continue;
-               _SysDebug("Line %i+%i '%.*s'", Term->ViewOffset, i, lineptr->Len, lineptr->Data);
-               AxWin3_RichText_SendLine(gMainWindow, Term->ViewOffset + i, lineptr->Data );
-               lineptr->IsDirty = 0;
-       }
-       AxWin3_RichText_SetCursorPos(gMainWindow, Term->CursorRow, Term->CursorCol);
-}
-
-void Display_ShowAltBuffer(tTerminal *Term, bool AltBufEnabled)
-{
-       UNIMPLIMENTED();
-}
-
diff --git a/Usermode/Applications/gui_shell_src/include/display.h b/Usermode/Applications/gui_shell_src/include/display.h
deleted file mode 100644 (file)
index 26601fe..0000000
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * Acess GUI Terminal
- * - By John Hodge (thePowersGang)
- *
- * display.h
- * - RichText terminal translation
- */
-#ifndef _DISPLAY_H_
-#define _DISPLAY_H_
-
-#include <stdint.h>
-#include <stddef.h>    // size_t
-#include <stdbool.h>
-
-typedef struct sTerminal       tTerminal;
-
-extern tTerminal       *Display_Init(int Cols, int Lines, int ExtraScrollbackLines);
-
-extern void    Display_AddText(tTerminal *Term, size_t Length, const char *UTF8Text);
-extern void    Display_Newline(tTerminal *Term, bool bCarriageReturn);
-extern void    Display_SetCursor(tTerminal *Term, int Row, int Col);
-extern void    Display_MoveCursor(tTerminal *Term, int RelRow, int RelCol);
-extern void    Display_ClearLine(tTerminal *Term, int Dir);    // 0: All, 1: Forward, -1: Reverse
-extern void    Display_ClearLines(tTerminal *Term, int Dir);   // 0: All, 1: Forward, -1: Reverse
-extern void    Display_SetForeground(tTerminal *Term, uint32_t RGB);
-extern void    Display_SetBackground(tTerminal *Term, uint32_t RGB);
-/**
- * \brief Ensure that recent updates are flushed to the server
- * \note Called at the end of an "input" buffer
- */
-extern void    Display_Flush(tTerminal *Term);
-
-/**
- * \brief Switch the display to the alternate buffer (no scrollback)
- */
-extern void    Display_ShowAltBuffer(tTerminal *Term, bool AltBufEnabled);
-
-#endif
-
diff --git a/Usermode/Applications/gui_shell_src/include/vt100.h b/Usermode/Applications/gui_shell_src/include/vt100.h
deleted file mode 100644 (file)
index 162991b..0000000
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * Acess GUI Terminal
- * - By John Hodge (thePowersGang)
- *
- * vt100.h
- * - VT100/xterm emulation
- */
-#ifndef _VT100_H_
-#define _VT100_H_
-
-#include "display.h"
-
-/**
- * Returns either a positive or negative byte count.
- * Positive means that many bytes were used as part of the escape sequence
- * and should not be sent to the display.
- * Negative means that there were that many bytes before the next escape
- * sequence (and hence those should be displayed).
- */
-extern int     Term_HandleVT100(tTerminal *Term, int Len, const char *Buf);
-
-
-#endif
-
diff --git a/Usermode/Applications/gui_shell_src/main.c b/Usermode/Applications/gui_shell_src/main.c
deleted file mode 100644 (file)
index 822f28b..0000000
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * Acess GUI Terminal
- * - By John Hodge (thePowersGang)
- *
- * main.c
- * - Core
- */
-#include <axwin3/axwin.h>
-#include <axwin3/menu.h>
-#include <axwin3/richtext.h>
-#include <axwin3/keysyms.h>
-#include <stdio.h>
-#include <acess/sys.h>
-#include "include/display.h"
-#include "include/vt100.h"
-#include <string.h>
-#include <unicode.h>
-#include <errno.h>
-#include <acess/devices/pty.h>
-
-// === PROTOTYPES ===
- int   main(int argc, char *argv[], const char **envp);
- int   Term_KeyHandler(tHWND Window, int bPress, uint32_t KeySym, uint32_t Translated);
- int   Term_MouseHandler(tHWND Window, int bPress, int Button, int Row, int Col);
-void   Term_HandleOutput(tTerminal *Term, int Len, const char *Buf);
-
-// === GLOBALS ===
-tHWND  gMainWindow;
-tHWND  gMenuWindow;
- int   giPTYHandle;
-
-// === CODE ===
-int main(int argc, char *argv[], const char **envp)
-{
-       AxWin3_Connect(NULL);
-       
-       // --- Build up window
-       gMainWindow = AxWin3_RichText_CreateWindow(NULL, AXWIN3_RICHTEXT_READONLY);
-       AxWin3_SetWindowTitle(gMainWindow, "Terminal"); // TODO: Update title with other info
-
-       gMenuWindow = AxWin3_Menu_Create(gMainWindow);
-       AxWin3_Menu_AddItem(gMenuWindow, "Copy\tWin+C", NULL, NULL, 0, NULL);
-       AxWin3_Menu_AddItem(gMenuWindow, "Paste\tWin+V", NULL, NULL, 0, NULL);
-       // TODO: Populate menu  
-
-
-       // TODO: Tabs?
-       
-       AxWin3_RichText_SetKeyHandler   (gMainWindow, Term_KeyHandler);
-       AxWin3_RichText_SetMouseHandler (gMainWindow, Term_MouseHandler);
-       AxWin3_RichText_SetDefaultColour(gMainWindow, 0xFFFFFF);
-       AxWin3_RichText_SetBackground   (gMainWindow, 0x000000);
-       AxWin3_RichText_SetFont         (gMainWindow, "#monospace", 10);
-       AxWin3_RichText_SetCursorPos    (gMainWindow, 0, 0);
-       AxWin3_RichText_SetCursorType   (gMainWindow, AXWIN3_RICHTEXT_CURSOR_INV);
-       AxWin3_RichText_SetCursorBlink  (gMainWindow, 1);
-
-       tTerminal *term = Display_Init(80, 25, 100);
-       AxWin3_ResizeWindow(gMainWindow, 80*8, 25*16);
-       AxWin3_MoveWindow(gMainWindow, 20, 50);
-       AxWin3_ShowWindow(gMainWindow, 1);
-       AxWin3_FocusWindow(gMainWindow);
-
-       // Create PTY
-       giPTYHandle = _SysOpen("/Devices/pts/ptmx", OPENFLAG_READ|OPENFLAG_WRITE);
-       if( giPTYHandle < 0 ) {
-               perror("Unable to create/open PTY");
-               _SysDebug("Unable to create/open PTY: %s", strerror(errno));
-               return -1;
-       }
-       // - Initialise
-       {
-               _SysIOCtl(giPTYHandle, PTY_IOCTL_SETID, "gui0");
-               struct ptymode  mode = {.InputMode = PTYIMODE_CANON|PTYIMODE_ECHO, .OutputMode=0};
-               struct ptydims  dims = {.W = 80, .H = 25};
-               _SysIOCtl(giPTYHandle, PTY_IOCTL_SETMODE, &mode);
-               _SysIOCtl(giPTYHandle, PTY_IOCTL_SETDIMS, &dims);
-       }
-
-       // Spawn shell
-       {
-                int    fd = _SysOpen("/Devices/pts/gui0", OPENFLAG_READ|OPENFLAG_WRITE);
-                int    fds[] = {fd, fd, fd};
-               const char      *argv[] = {"CLIShell", NULL};
-               int pid = _SysSpawn("/Acess/Bin/CLIShell", argv, envp, 3, fds, NULL);
-               if( pid < 0 )
-                       _SysDebug("ERROR: Shell spawn failed: %s", strerror(errno));
-               _SysIOCtl(fd, PTY_IOCTL_SETPGRP, &pid);
-               _SysClose(fd);
-       }
-
-       // Main loop
-       for( ;; )
-       {
-               fd_set  fds;
-               
-               FD_ZERO(&fds);
-               FD_SET(giPTYHandle, &fds);
-               AxWin3_MessageSelect(giPTYHandle + 1, &fds);
-               
-               if( FD_ISSET(giPTYHandle, &fds) )
-               {
-                       _SysDebug("Activity on child stdout");
-                       // Read and update screen
-                       char    buf[128];
-                       int len = _SysRead(giPTYHandle, buf, sizeof(buf));
-                       if( len <= 0 )  break;
-                       
-                       Term_HandleOutput(term, len, buf);
-               }
-       }
-
-       return 0;
-}
-
-int Term_KeyHandler(tHWND Window, int bPress, uint32_t KeySym, uint32_t Translated)
-{
-       static int      ctrl_state = 0;
-
-       // Handle modifiers
-       #define _bitset(var,bit,set) do{if(set)var|=1<<(bit);else var&=~(1<<(bit));}while(0)
-       switch(KeySym)
-       {
-       case KEYSYM_LEFTCTRL:
-               _bitset(ctrl_state, 0, bPress!=0);
-               return 0;
-       case KEYSYM_RIGHTCTRL:
-               _bitset(ctrl_state, 1, bPress!=0);
-               return 0;
-       }
-       #undef _bitset
-
-       // Handle shortcuts
-       // - Ctrl-A -- Ctrl-Z
-       if( ctrl_state && KeySym >= KEYSYM_a && KeySym <= KEYSYM_z )
-       {
-               Translated = KeySym - KEYSYM_a + 1;
-               _SysDebug("Ctrl-%c: KS %x => Trans %x", 'A'+(KeySym-KEYSYM_a), KeySym, Translated);
-       }
-
-       // == 2 :: FIRE
-       if( bPress == 2 )
-       {
-               if( Translated )
-               {
-                       char    buf[6];
-                        int    len;
-                       
-                       // Encode and send
-                       len = WriteUTF8(buf, Translated);
-                       
-                       _SysDebug("Keystroke %x:%x translated to '%.*s'", KeySym, Translated, len, buf);
-                       _SysWrite(giPTYHandle, buf, len);
-                       
-                       return 0;
-               }
-               
-               // No translation, look for escape sequences to send
-               const char *str = NULL;
-               switch(KeySym)
-               {
-               case KEYSYM_LEFTARROW:
-                       str = "\x1b[D";
-                       break;
-               case KEYSYM_RIGHTARROW:
-                       str = "\x1b[C";
-                       break;
-               case KEYSYM_UPARROW:
-                       str = "\x1b[A";
-                       break;
-               case KEYSYM_DOWNARROW:
-                       str = "\x1b[B";
-                       break;
-               }
-               if( str )
-               {
-                       _SysWrite(giPTYHandle, str, strlen(str));
-               }
-       }
-       return 0;
-}
-
-int Term_MouseHandler(tHWND Window, int bPress, int Button, int Row, int Col)
-{
-       return 0;
-}
-
-void Term_HandleOutput(tTerminal *Term, int Len, const char *Buf)
-{
-       // TODO: Handle graphical / accelerated modes
-
-        int    ofs = 0;
-        int    esc_len = 0;
-
-       while( ofs < Len )
-       {
-               esc_len = Term_HandleVT100(Term, Len - ofs, Buf + ofs);
-               if( esc_len < 0 ) {
-                       Display_AddText(Term, -esc_len, Buf + ofs);
-                       esc_len = -esc_len;
-               }
-               ofs += esc_len;
-               //_SysDebug("Len = %i, ofs = %i", Len, ofs);
-       }
-       
-       Display_Flush(Term);
-}
-
diff --git a/Usermode/Applications/gui_shell_src/vt100.c b/Usermode/Applications/gui_shell_src/vt100.c
deleted file mode 100644 (file)
index cad4119..0000000
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * Acess GUI Terminal
- * - By John Hodge (thePowersGang)
- *
- * vt100.c
- * - VT100/xterm Emulation
- */
-#include <string.h>
-#include <limits.h>
-#include "include/vt100.h"
-#include "include/display.h"
-#include <ctype.h>     // isalpha
-#include <acess/sys.h> // _SysDebug
-
-const uint32_t caVT100Colours[] = {
-       // Black, Red, Green, Yellow, Blue, Purple, Cyan, Gray
-       // Same again, but bright
-       0x000000, 0x770000, 0x007700, 0x777700, 0x000077, 0x770077, 0x007777, 0xAAAAAAA,
-       0xCCCCCC, 0xFF0000, 0x00FF00, 0xFFFF00, 0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFFFFF
-};
-
- int   Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buf);
-
-static inline int min(int a, int b)
-{
-       return a < b ? a : b;
-}
-
-int Term_HandleVT100(tTerminal *Term, int Len, const char *Buf)
-{
-       #define MAX_VT100_ESCAPE_LEN    16
-       static char     inc_buf[MAX_VT100_ESCAPE_LEN];
-       static int      inc_len = 0;
-
-       if( inc_len > 0 || *Buf == '\x1b' )
-       {
-               // Handle VT100 (like) escape sequence
-                int    new_bytes = min(MAX_VT100_ESCAPE_LEN - inc_len, Len);
-                int    ret = 0, old_inc_len = inc_len;
-               memcpy(inc_buf + inc_len, Buf, new_bytes);
-
-               inc_len += new_bytes;
-
-               if( inc_len <= 1 )
-                       return 1;       // Skip 1 character (the '\x1b')
-
-               switch(inc_buf[1])
-               {
-               case '[':       // Multibyte, funtime starts    
-                       ret = Term_HandleVT100_Long(Term, inc_len-2, inc_buf+2);
-                       if( ret > 0 ) {
-                               ret += 2;
-                       }
-                       break;
-               default:
-                       ret = 2;
-                       break;
-               }       
-
-               if( ret != 0 ) {
-                       inc_len = 0;
-                       ret -= old_inc_len;     // counter cached bytes
-               }
-               return ret;
-       }
-
-       switch( *Buf )
-       {
-       case '\b':
-               Display_MoveCursor(Term, -1, 0);
-               Display_AddText(Term, 1, " ");
-               Display_MoveCursor(Term, -1, 0);
-               // TODO: Need to handle \t and ^A-Z
-               return 1;
-       case '\t':
-               // TODO: tab (get current cursor pos, space until multiple of 8)
-               return 1;
-       case '\n':
-               Display_Newline(Term, 1);
-               return 1;
-       case '\r':
-               Display_MoveCursor(Term, INT_MIN, 0);
-               return 1;
-       }
-
-        int    ret = 0;
-       while( ret < Len )
-       {
-               switch(*Buf)
-               {
-               case '\x1b':
-               case '\b':
-               case '\t':
-               case '\n':
-               case '\r':
-                       // Force an exit right now
-                       Len = ret;
-                       break;
-               default:
-                       ret ++;
-                       Buf ++;
-                       break;
-               }
-       }
-       return -ret;
-}
-
-int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer)
-{
-       char    c;
-        int    argc = 0, j = 0;
-        int    args[6] = {0,0,0,0,0,0};
-        int    bQuestionMark = 0;
-       
-       // Get Arguments
-       if(j == Len)    return 0;
-       c = Buffer[j++];
-       if(c == '?') {
-               bQuestionMark = 1;
-               if(j == Len)    return 0;
-               c = Buffer[j++];
-       }
-       if( '0' <= c && c <= '9' )
-       {
-               do {
-                       if(c == ';') {
-                               if(j == Len)    return 0;
-                               c = Buffer[j++];
-                       }
-                       while('0' <= c && c <= '9') {
-                               args[argc] *= 10;
-                               args[argc] += c-'0';
-                               if(j == Len)    return 0;
-                               c = Buffer[j++];
-                       }
-                       argc ++;
-               } while(c == ';');
-       }
-       
-       // Get Command
-       if( !isalpha(c) ) {
-               // Bother.
-               _SysDebug("Unexpected char 0x%x in VT100 escape code", c);
-               return 1;
-       }
-
-       if( bQuestionMark )
-       {
-                int    set = 0;
-               // Special commands
-               switch( c )
-               {
-               case 'h':       // set
-                       set = 1;
-               case 'l':       // unset
-                       switch(args[0])
-                       {
-                       case 25:        // Hide cursor
-                               _SysDebug("TODO: \\e[?25%c Show/Hide cursor", c);
-                               break;
-                       case 1047:      // Alternate buffer
-                               Display_ShowAltBuffer(Term, set);
-                               break;
-                       default:
-                               _SysDebug("TODO: \\e[?%i%c Unknow DEC private mode", args[0], c);
-                               break;
-                       }
-                       break;
-               default:
-                       _SysDebug("Unknown VT100 extended escape char 0x%x", c);
-                       break;
-               }
-       }
-       else
-       {
-               // Standard commands
-               switch( c )
-               {
-               case 'H':
-                       if( argc != 2 ) {
-                       }
-                       else {
-                               Display_SetCursor(Term, args[0], args[1]);
-                       }
-                       break;
-               case 'J':
-                       if( argc == 0 )
-                               Display_ClearLine(Term, 0);
-                       else if( args[0] == 2 )
-                               Display_ClearLines(Term, 0);    // Entire screen!
-                       else
-                               _SysDebug("TODO: VT100 %i J", args[0]);
-                       break;
-               case 'T':       // Scroll down n=1
-                       _SysDebug("TODO: \\x1B[nT - Scroll down");
-                       break;
-               case 'm':
-                       if( argc == 0 )
-                       {
-                               // Reset
-                       }
-                       else
-                       {
-                               int i;
-                               for( i = 0; i < argc; i ++ )
-                               {
-                                       if( args[i] < 8 )
-                                       {
-                                               // TODO: Flags?
-                                       }
-                                       else if( 30 <= args[i] && args[i] <= 37 )
-                                       {
-                                               // TODO: Bold/bright
-                                               Display_SetForeground( Term, caVT100Colours[ args[i]-30 ] );
-                                       } 
-                                       else if( 40 <= args[i] && args[i] <= 47 )
-                                       {
-                                               // TODO: Bold/bright
-                                               Display_SetBackground( Term, caVT100Colours[ args[i]-30 ] );
-                                       } 
-                               }
-                       }
-                       break;
-               // Set scrolling region
-               case 'r':
-                       _SysDebug("TODO: \\x1B[%i;%ir - Set Scroll Region",
-                               args[0], args[1]);
-                       break;
-               default:
-                       _SysDebug("Unknown VT100 long escape char 0x%x '%c'", c, c);
-                       break;
-               }
-       }
-       return j;
-}
diff --git a/Usermode/Applications/gui_terminal_src/Makefile b/Usermode/Applications/gui_terminal_src/Makefile
new file mode 100644 (file)
index 0000000..a38f135
--- /dev/null
@@ -0,0 +1,11 @@
+# Project: [GUI] Terminal
+
+-include ../Makefile.cfg
+
+LDFLAGS += -laxwin3 -lunicode
+
+OBJ = main.o vt100.o display.o
+BIN = terminal
+DIR := Apps/AxWin/3.0
+
+-include ../Makefile.tpl
diff --git a/Usermode/Applications/gui_terminal_src/display.c b/Usermode/Applications/gui_terminal_src/display.c
new file mode 100644 (file)
index 0000000..0049608
--- /dev/null
@@ -0,0 +1,332 @@
+/*
+ * Acess GUI Terminal
+ * - By John Hodge (thePowersGang)
+ *
+ * display.c
+ * - Abstract display manipulation methods
+ */
+#include "include/display.h"
+#include <acess/sys.h> // _SysDebug
+#include <stdlib.h>    // exit
+#include <string.h>
+#include <unicode.h>
+#include <stdio.h>
+#include <axwin3/axwin.h>
+#include <axwin3/richtext.h>
+#include <stdbool.h>
+#include <assert.h>
+
+#define UNIMPLIMENTED()        do{_SysDebug("UNIMPLIMENTED %s", __func__); exit(-1);}while(0)
+
+// === EXTERN ==
+extern tHWND   gMainWindow;
+
+typedef struct sLine   tLine;
+
+struct sLine {
+       char    *Data;
+       // TODO: Cache offsets to avoid scan-forward
+       size_t  Len;
+       size_t  Size;
+       bool    IsDirty;
+};
+
+struct sTerminal {
+        int    ViewCols;
+        int    ViewRows;
+
+        int    CursorRow;
+        int    CursorCol;
+
+       size_t  CursorByte;
+
+       bool    bUsingAltBuf;
+
+       size_t  ViewOffset;     
+       size_t  TotalLines;
+       struct sLine    *PriBuf;
+       
+       struct sLine    *AltBuf;
+};
+
+// === GLOBALS ===
+tTerminal      gMainBuffer;
+ int   giCurrentLine;
+ int   giCurrentLinePos;       // byte offset, not column
+ int   giCurrentCol;
+ int   giFirstDispLine;        // First displayed line
+ int   giFirstLine;    // Ring buffer start
+char   **gasDisplayLines;
+ int   *gaiDisplayLineSizes;
+char   *gabDisplayLinesDirty;
+
+// === CODE ===
+tTerminal *Display_Init(int Cols, int Lines, int ExtraScrollbackLines)
+{
+       tTerminal       *term = &gMainBuffer;
+       term->ViewCols = Cols;
+       term->ViewRows = Lines;
+       term->TotalLines = Lines + ExtraScrollbackLines;
+       term->PriBuf = calloc( sizeof(tLine), (Lines + ExtraScrollbackLines) );
+       
+       AxWin3_RichText_SetLineCount(gMainWindow, Lines+ExtraScrollbackLines);
+       AxWin3_RichText_SetCursorType(gMainWindow, 1);  // TODO: enum
+       return term;
+}
+
+// Return the byte length of a single on-screen character
+size_t _GetCharLength(size_t AvailLength, const char *Text, uint32_t *BaseCodepoint)
+{
+       if( !AvailLength )
+               return 0;
+       
+       size_t  charlen = ReadUTF8(Text, BaseCodepoint);
+       
+       while(charlen < AvailLength)
+       {
+               uint32_t        cp;
+               size_t size = ReadUTF8(Text+charlen, &cp);
+               if( Unicode_IsPrinting(cp) )
+                       break;
+               charlen += size;
+       }
+       
+       return charlen;
+}
+
+tLine *Display_int_GetCurLine(tTerminal *Term)
+{
+        int    lineidx = Term->CursorRow + (Term->bUsingAltBuf ? 0 : Term->ViewOffset);
+       return (Term->bUsingAltBuf ? Term->AltBuf : Term->PriBuf) + lineidx;
+}
+
+size_t Display_int_PushCharacter(tTerminal *Term, size_t AvailLength, const char *Text)
+{
+       tLine   *lineptr = Display_int_GetCurLine(Term);
+       uint32_t        cp;
+       size_t  charlen = _GetCharLength(AvailLength, Text, &cp);
+       bool    bOverwrite = Unicode_IsPrinting(cp);
+       
+       _SysDebug("Line %b:%i += %i '%.*s'", Term->bUsingAltBuf, Term->CursorRow, charlen, charlen, Text);
+
+       // Figure out how much we need to shift the stream
+        int    shift;
+       if( bOverwrite ) {
+               size_t nextlen = _GetCharLength(
+                       lineptr->Len-Term->CursorByte,
+                       lineptr->Data+Term->CursorByte,
+                       NULL);
+               _SysDebug("Char at +%i is %i long (%.*s)", Term->CursorByte, nextlen,
+                               nextlen, lineptr->Data+Term->CursorByte);
+               shift = charlen - nextlen;
+       }
+       else {
+               shift = charlen;
+       }
+       _SysDebug("shift = %i", shift);
+       
+       // Ensure we have space enough
+       if( !lineptr->Data || shift > 0 ) {
+               const size_t    size_step = 64;
+               assert(shift > 0);
+               lineptr->Size = (lineptr->Len+shift+1 + size_step-1) & ~(size_step-1);
+               void *tmp = realloc(lineptr->Data, lineptr->Size);
+               if( !tmp )      perror("Display_int_PushCharacter - realloc");
+               lineptr->Data = tmp;
+       }
+       
+       // Insert into stream
+       char    *base = lineptr->Data + Term->CursorByte;
+       if( Term->CursorByte == lineptr->Len ) {
+               // No shifting needed
+       }
+       else if( shift >= 0 ) {
+               size_t  bytes = lineptr->Len - (Term->CursorByte+shift);
+               _SysDebug("memmove(base+%i, base, %i)", shift, bytes);
+               memmove(base+shift, base, bytes);
+       }
+       else {
+               shift = -shift;
+               size_t  bytes = lineptr->Len - (Term->CursorByte+shift);
+               _SysDebug("memmove(base, base+%i, %i)", shift, bytes);
+               memmove(base, base+shift, bytes);
+       }
+       memcpy(base, Text, charlen);
+       lineptr->IsDirty = true;
+       lineptr->Len += shift;
+       lineptr->Data[lineptr->Len] = 0;        // NULL Terminate
+
+       Term->CursorByte += charlen;
+       
+       // HACKY: Prevents the CursorCol++ in Display_AddText from having an effect
+       if( !bOverwrite )
+               Term->CursorCol --;
+       
+       return charlen;
+}
+
+void Display_AddText(tTerminal *Term, size_t Length, const char *UTF8Text)
+{
+       _SysDebug("%i '%.*s'", Length, Length, UTF8Text);
+       while( Length > 0 )
+       {
+               size_t used = Display_int_PushCharacter(Term, Length, UTF8Text);
+       
+               Length -= used;
+               UTF8Text += used;
+               
+               Term->CursorCol ++;
+               if( Term->CursorCol == Term->ViewCols ) {
+                       Display_Newline(Term, 1);
+               }
+       }
+}
+
+void Display_Newline(tTerminal *Term, bool bCarriageReturn)
+{
+//     Display_Flush();
+
+       // Going down!
+       Term->CursorRow ++;
+       if( Term->CursorRow == Term->TotalLines ) {
+               // TODO: Scrolling
+       }
+       
+       if( bCarriageReturn ) {
+               Term->CursorByte = 0;
+               Term->CursorCol = 0;
+               return ;
+       }
+
+       tLine   *line = Display_int_GetCurLine(Term);
+       
+       Term->CursorByte = 0;
+        int    old_col = Term->CursorCol;
+       Term->CursorCol = 0;
+
+       size_t  ofs = 0;
+       while( Term->CursorCol < old_col && ofs < line->Len ) {
+               ofs += _GetCharLength(line->Len-ofs, line->Data+ofs, NULL);
+               Term->CursorCol ++;
+       }
+       Term->CursorByte = ofs;
+
+       while( Term->CursorCol < old_col )
+               Display_AddText(Term, 1, " ");
+}
+
+void Display_SetCursor(tTerminal *Term, int Row, int Col)
+{
+       UNIMPLIMENTED();
+}
+
+void Display_MoveCursor(tTerminal *Term, int RelRow, int RelCol)
+{
+       if( RelRow != 0 )
+       {
+               UNIMPLIMENTED();
+       }
+       
+       if( RelCol != 0 )
+       {
+               int req_col = Term->CursorCol + RelCol;
+               if( req_col < 0 )       req_col = 0;
+               if( req_col > Term->ViewCols )  req_col = Term->ViewCols;
+
+               tLine   *line = Display_int_GetCurLine(Term);
+               size_t  ofs = 0;
+               for( int i = 0; i < req_col; i ++ )
+               {
+                       size_t clen = _GetCharLength(line->Len-ofs, line->Data+ofs, NULL);
+                       if( clen == 0 ) {
+                               req_col = i;
+                               break;
+                       }
+                       ofs += clen;
+               }
+
+               Term->CursorCol = req_col;
+               Term->CursorByte = ofs;
+       }
+}
+
+void Display_ClearLine(tTerminal *Term, int Dir)       // 0: All, 1: Forward, -1: Reverse
+{
+       if( Dir == 0 )
+       {
+               tLine   *line = Display_int_GetCurLine(Term);
+               // Completely clear line
+               if( line->Data )
+                       free(line->Data);
+               line->Data = NULL;
+               line->IsDirty = true;
+       }
+       else if( Dir == 1 )
+       {
+               // Forward clear (truncate)
+       }
+       else if( Dir == -1 )
+       {
+               // Reverse clear (replace with spaces)
+       }
+       else
+       {
+               // BUGCHECK
+       }
+}
+
+void Display_ClearLines(tTerminal *Term, int Dir)      // 0: All, 1: Forward, -1: Reverse
+{
+       if( Dir == 0 )
+       {
+               // Push giDisplayLines worth of empty lines
+               // Move cursor back up by giDisplayLines
+       }
+       else if( Dir == 1 )
+       {
+               // Push (giDisplayLines - (giCurrentLine-giFirstDispLine)) and reverse
+       }
+       else if( Dir == -1 )
+       {
+               // Reverse clear (replace with spaces)
+       }
+       else
+       {
+               // BUGCHECK
+       }
+}
+
+void Display_SetForeground(tTerminal *Term, uint32_t RGB)
+{
+       char    buf[7+1];
+       sprintf(buf, "\1%06x", RGB&0xFFFFFF);
+       Display_AddText(Term, 7, buf);
+}
+
+void Display_SetBackground(tTerminal *Term, uint32_t RGB)
+{
+       char    buf[7+1];
+       sprintf(buf, "\2%06x", RGB&0xFFFFFF);
+       Display_AddText(Term, 7, buf);
+}
+
+void Display_Flush(tTerminal *Term)
+{
+       for( int i = 0; i < Term->ViewRows; i ++ )
+       {
+                int    line = (Term->ViewOffset + i) % Term->TotalLines;
+               tLine   *lineptr = &Term->PriBuf[line];
+               if( !lineptr->IsDirty )
+                       continue;
+               _SysDebug("Line %i+%i '%.*s'", Term->ViewOffset, i, lineptr->Len, lineptr->Data);
+               AxWin3_RichText_SendLine(gMainWindow, Term->ViewOffset + i, lineptr->Data );
+               lineptr->IsDirty = 0;
+       }
+       AxWin3_RichText_SetCursorPos(gMainWindow, Term->CursorRow, Term->CursorCol);
+}
+
+void Display_ShowAltBuffer(tTerminal *Term, bool AltBufEnabled)
+{
+       UNIMPLIMENTED();
+}
+
diff --git a/Usermode/Applications/gui_terminal_src/include/display.h b/Usermode/Applications/gui_terminal_src/include/display.h
new file mode 100644 (file)
index 0000000..26601fe
--- /dev/null
@@ -0,0 +1,39 @@
+/*
+ * Acess GUI Terminal
+ * - By John Hodge (thePowersGang)
+ *
+ * display.h
+ * - RichText terminal translation
+ */
+#ifndef _DISPLAY_H_
+#define _DISPLAY_H_
+
+#include <stdint.h>
+#include <stddef.h>    // size_t
+#include <stdbool.h>
+
+typedef struct sTerminal       tTerminal;
+
+extern tTerminal       *Display_Init(int Cols, int Lines, int ExtraScrollbackLines);
+
+extern void    Display_AddText(tTerminal *Term, size_t Length, const char *UTF8Text);
+extern void    Display_Newline(tTerminal *Term, bool bCarriageReturn);
+extern void    Display_SetCursor(tTerminal *Term, int Row, int Col);
+extern void    Display_MoveCursor(tTerminal *Term, int RelRow, int RelCol);
+extern void    Display_ClearLine(tTerminal *Term, int Dir);    // 0: All, 1: Forward, -1: Reverse
+extern void    Display_ClearLines(tTerminal *Term, int Dir);   // 0: All, 1: Forward, -1: Reverse
+extern void    Display_SetForeground(tTerminal *Term, uint32_t RGB);
+extern void    Display_SetBackground(tTerminal *Term, uint32_t RGB);
+/**
+ * \brief Ensure that recent updates are flushed to the server
+ * \note Called at the end of an "input" buffer
+ */
+extern void    Display_Flush(tTerminal *Term);
+
+/**
+ * \brief Switch the display to the alternate buffer (no scrollback)
+ */
+extern void    Display_ShowAltBuffer(tTerminal *Term, bool AltBufEnabled);
+
+#endif
+
diff --git a/Usermode/Applications/gui_terminal_src/include/vt100.h b/Usermode/Applications/gui_terminal_src/include/vt100.h
new file mode 100644 (file)
index 0000000..162991b
--- /dev/null
@@ -0,0 +1,24 @@
+/*
+ * Acess GUI Terminal
+ * - By John Hodge (thePowersGang)
+ *
+ * vt100.h
+ * - VT100/xterm emulation
+ */
+#ifndef _VT100_H_
+#define _VT100_H_
+
+#include "display.h"
+
+/**
+ * Returns either a positive or negative byte count.
+ * Positive means that many bytes were used as part of the escape sequence
+ * and should not be sent to the display.
+ * Negative means that there were that many bytes before the next escape
+ * sequence (and hence those should be displayed).
+ */
+extern int     Term_HandleVT100(tTerminal *Term, int Len, const char *Buf);
+
+
+#endif
+
diff --git a/Usermode/Applications/gui_terminal_src/main.c b/Usermode/Applications/gui_terminal_src/main.c
new file mode 100644 (file)
index 0000000..822f28b
--- /dev/null
@@ -0,0 +1,208 @@
+/*
+ * Acess GUI Terminal
+ * - By John Hodge (thePowersGang)
+ *
+ * main.c
+ * - Core
+ */
+#include <axwin3/axwin.h>
+#include <axwin3/menu.h>
+#include <axwin3/richtext.h>
+#include <axwin3/keysyms.h>
+#include <stdio.h>
+#include <acess/sys.h>
+#include "include/display.h"
+#include "include/vt100.h"
+#include <string.h>
+#include <unicode.h>
+#include <errno.h>
+#include <acess/devices/pty.h>
+
+// === PROTOTYPES ===
+ int   main(int argc, char *argv[], const char **envp);
+ int   Term_KeyHandler(tHWND Window, int bPress, uint32_t KeySym, uint32_t Translated);
+ int   Term_MouseHandler(tHWND Window, int bPress, int Button, int Row, int Col);
+void   Term_HandleOutput(tTerminal *Term, int Len, const char *Buf);
+
+// === GLOBALS ===
+tHWND  gMainWindow;
+tHWND  gMenuWindow;
+ int   giPTYHandle;
+
+// === CODE ===
+int main(int argc, char *argv[], const char **envp)
+{
+       AxWin3_Connect(NULL);
+       
+       // --- Build up window
+       gMainWindow = AxWin3_RichText_CreateWindow(NULL, AXWIN3_RICHTEXT_READONLY);
+       AxWin3_SetWindowTitle(gMainWindow, "Terminal"); // TODO: Update title with other info
+
+       gMenuWindow = AxWin3_Menu_Create(gMainWindow);
+       AxWin3_Menu_AddItem(gMenuWindow, "Copy\tWin+C", NULL, NULL, 0, NULL);
+       AxWin3_Menu_AddItem(gMenuWindow, "Paste\tWin+V", NULL, NULL, 0, NULL);
+       // TODO: Populate menu  
+
+
+       // TODO: Tabs?
+       
+       AxWin3_RichText_SetKeyHandler   (gMainWindow, Term_KeyHandler);
+       AxWin3_RichText_SetMouseHandler (gMainWindow, Term_MouseHandler);
+       AxWin3_RichText_SetDefaultColour(gMainWindow, 0xFFFFFF);
+       AxWin3_RichText_SetBackground   (gMainWindow, 0x000000);
+       AxWin3_RichText_SetFont         (gMainWindow, "#monospace", 10);
+       AxWin3_RichText_SetCursorPos    (gMainWindow, 0, 0);
+       AxWin3_RichText_SetCursorType   (gMainWindow, AXWIN3_RICHTEXT_CURSOR_INV);
+       AxWin3_RichText_SetCursorBlink  (gMainWindow, 1);
+
+       tTerminal *term = Display_Init(80, 25, 100);
+       AxWin3_ResizeWindow(gMainWindow, 80*8, 25*16);
+       AxWin3_MoveWindow(gMainWindow, 20, 50);
+       AxWin3_ShowWindow(gMainWindow, 1);
+       AxWin3_FocusWindow(gMainWindow);
+
+       // Create PTY
+       giPTYHandle = _SysOpen("/Devices/pts/ptmx", OPENFLAG_READ|OPENFLAG_WRITE);
+       if( giPTYHandle < 0 ) {
+               perror("Unable to create/open PTY");
+               _SysDebug("Unable to create/open PTY: %s", strerror(errno));
+               return -1;
+       }
+       // - Initialise
+       {
+               _SysIOCtl(giPTYHandle, PTY_IOCTL_SETID, "gui0");
+               struct ptymode  mode = {.InputMode = PTYIMODE_CANON|PTYIMODE_ECHO, .OutputMode=0};
+               struct ptydims  dims = {.W = 80, .H = 25};
+               _SysIOCtl(giPTYHandle, PTY_IOCTL_SETMODE, &mode);
+               _SysIOCtl(giPTYHandle, PTY_IOCTL_SETDIMS, &dims);
+       }
+
+       // Spawn shell
+       {
+                int    fd = _SysOpen("/Devices/pts/gui0", OPENFLAG_READ|OPENFLAG_WRITE);
+                int    fds[] = {fd, fd, fd};
+               const char      *argv[] = {"CLIShell", NULL};
+               int pid = _SysSpawn("/Acess/Bin/CLIShell", argv, envp, 3, fds, NULL);
+               if( pid < 0 )
+                       _SysDebug("ERROR: Shell spawn failed: %s", strerror(errno));
+               _SysIOCtl(fd, PTY_IOCTL_SETPGRP, &pid);
+               _SysClose(fd);
+       }
+
+       // Main loop
+       for( ;; )
+       {
+               fd_set  fds;
+               
+               FD_ZERO(&fds);
+               FD_SET(giPTYHandle, &fds);
+               AxWin3_MessageSelect(giPTYHandle + 1, &fds);
+               
+               if( FD_ISSET(giPTYHandle, &fds) )
+               {
+                       _SysDebug("Activity on child stdout");
+                       // Read and update screen
+                       char    buf[128];
+                       int len = _SysRead(giPTYHandle, buf, sizeof(buf));
+                       if( len <= 0 )  break;
+                       
+                       Term_HandleOutput(term, len, buf);
+               }
+       }
+
+       return 0;
+}
+
+int Term_KeyHandler(tHWND Window, int bPress, uint32_t KeySym, uint32_t Translated)
+{
+       static int      ctrl_state = 0;
+
+       // Handle modifiers
+       #define _bitset(var,bit,set) do{if(set)var|=1<<(bit);else var&=~(1<<(bit));}while(0)
+       switch(KeySym)
+       {
+       case KEYSYM_LEFTCTRL:
+               _bitset(ctrl_state, 0, bPress!=0);
+               return 0;
+       case KEYSYM_RIGHTCTRL:
+               _bitset(ctrl_state, 1, bPress!=0);
+               return 0;
+       }
+       #undef _bitset
+
+       // Handle shortcuts
+       // - Ctrl-A -- Ctrl-Z
+       if( ctrl_state && KeySym >= KEYSYM_a && KeySym <= KEYSYM_z )
+       {
+               Translated = KeySym - KEYSYM_a + 1;
+               _SysDebug("Ctrl-%c: KS %x => Trans %x", 'A'+(KeySym-KEYSYM_a), KeySym, Translated);
+       }
+
+       // == 2 :: FIRE
+       if( bPress == 2 )
+       {
+               if( Translated )
+               {
+                       char    buf[6];
+                        int    len;
+                       
+                       // Encode and send
+                       len = WriteUTF8(buf, Translated);
+                       
+                       _SysDebug("Keystroke %x:%x translated to '%.*s'", KeySym, Translated, len, buf);
+                       _SysWrite(giPTYHandle, buf, len);
+                       
+                       return 0;
+               }
+               
+               // No translation, look for escape sequences to send
+               const char *str = NULL;
+               switch(KeySym)
+               {
+               case KEYSYM_LEFTARROW:
+                       str = "\x1b[D";
+                       break;
+               case KEYSYM_RIGHTARROW:
+                       str = "\x1b[C";
+                       break;
+               case KEYSYM_UPARROW:
+                       str = "\x1b[A";
+                       break;
+               case KEYSYM_DOWNARROW:
+                       str = "\x1b[B";
+                       break;
+               }
+               if( str )
+               {
+                       _SysWrite(giPTYHandle, str, strlen(str));
+               }
+       }
+       return 0;
+}
+
+int Term_MouseHandler(tHWND Window, int bPress, int Button, int Row, int Col)
+{
+       return 0;
+}
+
+void Term_HandleOutput(tTerminal *Term, int Len, const char *Buf)
+{
+       // TODO: Handle graphical / accelerated modes
+
+        int    ofs = 0;
+        int    esc_len = 0;
+
+       while( ofs < Len )
+       {
+               esc_len = Term_HandleVT100(Term, Len - ofs, Buf + ofs);
+               if( esc_len < 0 ) {
+                       Display_AddText(Term, -esc_len, Buf + ofs);
+                       esc_len = -esc_len;
+               }
+               ofs += esc_len;
+               //_SysDebug("Len = %i, ofs = %i", Len, ofs);
+       }
+       
+       Display_Flush(Term);
+}
+
diff --git a/Usermode/Applications/gui_terminal_src/vt100.c b/Usermode/Applications/gui_terminal_src/vt100.c
new file mode 100644 (file)
index 0000000..cad4119
--- /dev/null
@@ -0,0 +1,235 @@
+/*
+ * Acess GUI Terminal
+ * - By John Hodge (thePowersGang)
+ *
+ * vt100.c
+ * - VT100/xterm Emulation
+ */
+#include <string.h>
+#include <limits.h>
+#include "include/vt100.h"
+#include "include/display.h"
+#include <ctype.h>     // isalpha
+#include <acess/sys.h> // _SysDebug
+
+const uint32_t caVT100Colours[] = {
+       // Black, Red, Green, Yellow, Blue, Purple, Cyan, Gray
+       // Same again, but bright
+       0x000000, 0x770000, 0x007700, 0x777700, 0x000077, 0x770077, 0x007777, 0xAAAAAAA,
+       0xCCCCCC, 0xFF0000, 0x00FF00, 0xFFFF00, 0x0000FF, 0xFF00FF, 0x00FFFF, 0xFFFFFFF
+};
+
+ int   Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buf);
+
+static inline int min(int a, int b)
+{
+       return a < b ? a : b;
+}
+
+int Term_HandleVT100(tTerminal *Term, int Len, const char *Buf)
+{
+       #define MAX_VT100_ESCAPE_LEN    16
+       static char     inc_buf[MAX_VT100_ESCAPE_LEN];
+       static int      inc_len = 0;
+
+       if( inc_len > 0 || *Buf == '\x1b' )
+       {
+               // Handle VT100 (like) escape sequence
+                int    new_bytes = min(MAX_VT100_ESCAPE_LEN - inc_len, Len);
+                int    ret = 0, old_inc_len = inc_len;
+               memcpy(inc_buf + inc_len, Buf, new_bytes);
+
+               inc_len += new_bytes;
+
+               if( inc_len <= 1 )
+                       return 1;       // Skip 1 character (the '\x1b')
+
+               switch(inc_buf[1])
+               {
+               case '[':       // Multibyte, funtime starts    
+                       ret = Term_HandleVT100_Long(Term, inc_len-2, inc_buf+2);
+                       if( ret > 0 ) {
+                               ret += 2;
+                       }
+                       break;
+               default:
+                       ret = 2;
+                       break;
+               }       
+
+               if( ret != 0 ) {
+                       inc_len = 0;
+                       ret -= old_inc_len;     // counter cached bytes
+               }
+               return ret;
+       }
+
+       switch( *Buf )
+       {
+       case '\b':
+               Display_MoveCursor(Term, -1, 0);
+               Display_AddText(Term, 1, " ");
+               Display_MoveCursor(Term, -1, 0);
+               // TODO: Need to handle \t and ^A-Z
+               return 1;
+       case '\t':
+               // TODO: tab (get current cursor pos, space until multiple of 8)
+               return 1;
+       case '\n':
+               Display_Newline(Term, 1);
+               return 1;
+       case '\r':
+               Display_MoveCursor(Term, INT_MIN, 0);
+               return 1;
+       }
+
+        int    ret = 0;
+       while( ret < Len )
+       {
+               switch(*Buf)
+               {
+               case '\x1b':
+               case '\b':
+               case '\t':
+               case '\n':
+               case '\r':
+                       // Force an exit right now
+                       Len = ret;
+                       break;
+               default:
+                       ret ++;
+                       Buf ++;
+                       break;
+               }
+       }
+       return -ret;
+}
+
+int Term_HandleVT100_Long(tTerminal *Term, int Len, const char *Buffer)
+{
+       char    c;
+        int    argc = 0, j = 0;
+        int    args[6] = {0,0,0,0,0,0};
+        int    bQuestionMark = 0;
+       
+       // Get Arguments
+       if(j == Len)    return 0;
+       c = Buffer[j++];
+       if(c == '?') {
+               bQuestionMark = 1;
+               if(j == Len)    return 0;
+               c = Buffer[j++];
+       }
+       if( '0' <= c && c <= '9' )
+       {
+               do {
+                       if(c == ';') {
+                               if(j == Len)    return 0;
+                               c = Buffer[j++];
+                       }
+                       while('0' <= c && c <= '9') {
+                               args[argc] *= 10;
+                               args[argc] += c-'0';
+                               if(j == Len)    return 0;
+                               c = Buffer[j++];
+                       }
+                       argc ++;
+               } while(c == ';');
+       }
+       
+       // Get Command
+       if( !isalpha(c) ) {
+               // Bother.
+               _SysDebug("Unexpected char 0x%x in VT100 escape code", c);
+               return 1;
+       }
+
+       if( bQuestionMark )
+       {
+                int    set = 0;
+               // Special commands
+               switch( c )
+               {
+               case 'h':       // set
+                       set = 1;
+               case 'l':       // unset
+                       switch(args[0])
+                       {
+                       case 25:        // Hide cursor
+                               _SysDebug("TODO: \\e[?25%c Show/Hide cursor", c);
+                               break;
+                       case 1047:      // Alternate buffer
+                               Display_ShowAltBuffer(Term, set);
+                               break;
+                       default:
+                               _SysDebug("TODO: \\e[?%i%c Unknow DEC private mode", args[0], c);
+                               break;
+                       }
+                       break;
+               default:
+                       _SysDebug("Unknown VT100 extended escape char 0x%x", c);
+                       break;
+               }
+       }
+       else
+       {
+               // Standard commands
+               switch( c )
+               {
+               case 'H':
+                       if( argc != 2 ) {
+                       }
+                       else {
+                               Display_SetCursor(Term, args[0], args[1]);
+                       }
+                       break;
+               case 'J':
+                       if( argc == 0 )
+                               Display_ClearLine(Term, 0);
+                       else if( args[0] == 2 )
+                               Display_ClearLines(Term, 0);    // Entire screen!
+                       else
+                               _SysDebug("TODO: VT100 %i J", args[0]);
+                       break;
+               case 'T':       // Scroll down n=1
+                       _SysDebug("TODO: \\x1B[nT - Scroll down");
+                       break;
+               case 'm':
+                       if( argc == 0 )
+                       {
+                               // Reset
+                       }
+                       else
+                       {
+                               int i;
+                               for( i = 0; i < argc; i ++ )
+                               {
+                                       if( args[i] < 8 )
+                                       {
+                                               // TODO: Flags?
+                                       }
+                                       else if( 30 <= args[i] && args[i] <= 37 )
+                                       {
+                                               // TODO: Bold/bright
+                                               Display_SetForeground( Term, caVT100Colours[ args[i]-30 ] );
+                                       } 
+                                       else if( 40 <= args[i] && args[i] <= 47 )
+                                       {
+                                               // TODO: Bold/bright
+                                               Display_SetBackground( Term, caVT100Colours[ args[i]-30 ] );
+                                       } 
+                               }
+                       }
+                       break;
+               // Set scrolling region
+               case 'r':
+                       _SysDebug("TODO: \\x1B[%i;%ir - Set Scroll Region",
+                               args[0], args[1]);
+                       break;
+               default:
+                       _SysDebug("Unknown VT100 long escape char 0x%x '%c'", c, c);
+                       break;
+               }
+       }
+       return j;
+}

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