From 814c5d5a3c1fb1e06afa268561e60a529af90b7a Mon Sep 17 00:00:00 2001 From: "John Hodge (sonata)" Date: Wed, 17 Oct 2012 11:47:42 +0800 Subject: [PATCH] Usermode/GUI Shell - Hacking up a GUI terminal --- Usermode/Applications/gui_shell_src/Makefile | 11 ++ .../gui_shell_src/include/display.h | 21 +++ .../gui_shell_src/include/vt100.h | 22 +++ Usermode/Applications/gui_shell_src/main.c | 159 ++++++++++++++++++ Usermode/Applications/gui_shell_src/vt100.c | 54 ++++++ 5 files changed, 267 insertions(+) create mode 100644 Usermode/Applications/gui_shell_src/Makefile create mode 100644 Usermode/Applications/gui_shell_src/include/display.h create mode 100644 Usermode/Applications/gui_shell_src/include/vt100.h create mode 100644 Usermode/Applications/gui_shell_src/main.c create mode 100644 Usermode/Applications/gui_shell_src/vt100.c diff --git a/Usermode/Applications/gui_shell_src/Makefile b/Usermode/Applications/gui_shell_src/Makefile new file mode 100644 index 00000000..7ccfff46 --- /dev/null +++ b/Usermode/Applications/gui_shell_src/Makefile @@ -0,0 +1,11 @@ +# Project: [GUI] Terminal + +-include ../Makefile.cfg + +LDFLAGS += -laxwin3 + +OBJ = main.o +BIN = terminal +DIR := Apps/AxWin/3.0 + +-include ../Makefile.tpl diff --git a/Usermode/Applications/gui_shell_src/include/display.h b/Usermode/Applications/gui_shell_src/include/display.h new file mode 100644 index 00000000..80bc69ca --- /dev/null +++ b/Usermode/Applications/gui_shell_src/include/display.h @@ -0,0 +1,21 @@ +/* + * Acess GUI Terminal + * - By John Hodge (thePowersGang) + * + * display.h + * - RichText Termianl Translation + */ +#ifndef _DISPLAY_H_ +#define _DISPLAY_H_ + +extern void Display_AddText(int Length, const char *UTF8Text); +extern void Display_Newline(int bCarriageReturn); +extern void Display_SetCursor(int Row, int Col); +extern void Display_MoveCursor(int RelRow, int RelCol); +extern void Display_ClearLine(int Dir); // 0: All, 1: Forward, -1: Reverse +extern void Display_ClearLines(int Dir); // 0: All, 1: Forward, -1: Reverse +extern void Display_SetForeground(uint32_t RGB); +extern void Display_SetBackground(uint32_t RGB); + +#endif + diff --git a/Usermode/Applications/gui_shell_src/include/vt100.h b/Usermode/Applications/gui_shell_src/include/vt100.h new file mode 100644 index 00000000..13f830e2 --- /dev/null +++ b/Usermode/Applications/gui_shell_src/include/vt100.h @@ -0,0 +1,22 @@ +/* + * Acess GUI Terminal + * - By John Hodge (thePowersGang) + * + * vt100.h + * - VT100/xterm emulation + */ +#ifndef _VT100_H_ +#define _VT100_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(int Len, const char *Buf); + + +#endif + diff --git a/Usermode/Applications/gui_shell_src/main.c b/Usermode/Applications/gui_shell_src/main.c new file mode 100644 index 00000000..46ce3982 --- /dev/null +++ b/Usermode/Applications/gui_shell_src/main.c @@ -0,0 +1,159 @@ +/* + * Acess GUI Terminal + * - By John Hodge (thePowersGang) + * + * main.c + * - Core + */ +#include +#include +#include +#include +#include "include/display.h" + +// === PROTOTYPES === + int main(int argc, char *argv[]); + int Term_KeyHandler(tHWND Window, int bPress, uint32_t KeySym, uint32_t Translated); + int Term_MouseHandler(tHWND Window, int bPress, uint32_t KeySym, uint32_t Translated); + +// === GLOBALS === +tHWND gMainWindow; +tHWND gMenuWindow; + int giChildStdin; + int giChildStdout; + +// === CODE === +int main(int argc, char *argv[]) +{ + AxWin3_Connect(NULL); + + // --- Build up window + gMainWindow = AxWin3_RichText_CreateWindow(NULL, 0); + AxWin3_SetWindowTitle(gMainWindow, "Terminal"); // TODO: Update title with other info + + gMenuWindow = AxWin3_Menu_Create(gMainWindow); + AxWin3_Menu_AddItem(gMenuWindow, "Copy\tWin+C", NULL, NULL, NULL, 0); + AxWin3_Menu_AddItem(gMenuWindow, "Paste\tWin+V", NULL, NULL, NULL, 0); + // 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); + + // + AxWin3_RichText_SetLineCount(gMainWindow, 3); + AxWin3_RichText_SendLine(gMainWindow, 0, "First line!"); + AxWin3_RichText_SendLine(gMainWindow, 2, "Third line! \x01""ff0000A red"); + // + + AxWin3_ResizeWindow(gMainWindow, 600, 400); + AxWin3_MoveWindow(gMainWindow, 50, 50); + AxWin3_ShowWindow(gMainWindow, 1); + AxWin3_FocusWindow(gMainWindow); + + // Spawn shell + giChildStdout = open("/Devices/FIFO/anon", O_RDWR); + giChildStdin = open("/Devices/FIFO/anon", O_RDWR); + + { + int fds[] = {giChildStdin, giChildStdout, giChildStdout}; + const char *argv[] = {"CLIShell", NULL}; + _SysSpawn("/Acess/Bin/CLIShell", argv, envp, 3, fds, NULL); + } + + // Main loop + for( ;; ) + { + fd_set fds; + + FD_ZERO(&fds); + FD_SET(&fds, giChildStdout); + AxWin3_MessageSelect(giChildStdout + 1, &fds); + + if( FD_ISSET(&fds, giChildStdout) ) + { + // Read and update screen + char buf[32]; + len = read(giChildStdout, sizeof(buf), buf); + if( len <= 0 ) break; + + //Term_HandleOutput(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 KEY_LCTRL: + _bitset(ctrl_state, 0, bPress); + return 0; + case KEY_RCTRL: + _bitset(ctrl_state, 0, bPress); + return 0; + } + #undef _bitset + + // Handle shortcuts + // - Ctrl-A -- Ctrl-Z + if( ctrl_state && KeySym >= KEY_a && KeySym <= KEY_z ) + { + Translated = KeySym - KEY_a + 1; + } + + if( Translated ) + { + // Encode and send + + return 0; + } + + // No translation, look for escape sequences to send + switch(KeySym) + { + case KEY_LEFTARROW: + str = "\x1b[D"; + break; + } + return 0; +} + +int Term_MouseHandler(tHWND Window, int bPress, int Button, int Row, int Col) +{ + return 0; +} + +void Term_HandleOutput(int Len, const char *Buf) +{ + // TODO: Handle graphical / accelerated modes + + int ofs = 0; + int esc_len = 0; + + while( ofs < Len ) + { + esc_len = Term_HandleVT100(Len - ofs, Buf + ofs); + if( esc_len < 0 ) { + Display_AddText(-esc_len, Buf + ofs); + esc_len = -esc_len; + } + Len -= esc_len; + ofs += esc_len; + } +} + diff --git a/Usermode/Applications/gui_shell_src/vt100.c b/Usermode/Applications/gui_shell_src/vt100.c new file mode 100644 index 00000000..51c8016f --- /dev/null +++ b/Usermode/Applications/gui_shell_src/vt100.c @@ -0,0 +1,54 @@ +/* + * Acess GUI Terminal + * - By John Hodge (thePowersGang) + * + * main.c + * - Core + */ +#include +#include "include/vt100.h" +#include "include/display.h" + +int Term_HandleVT100(int Len, const char *Buf) +{ + const int max_length = 16; + static char inc_buf[max_length] + static int inc_len = 0; + + if( inc_len > 0 || *Buf == '\x1b' ) + { + memcpy(inc_buf + inc_len, Buf, min(max_length - inc_len, Len)); + // Handle VT100 (like) escape sequence + + inc_len = 0; + return 1; + } + + switch( *Buf ) + { + case '\b': + // TODO: Backspace + return 1; + case '\t': + // TODO: tab + return 1; + case '\n': + Display_Newline(1); + return 1; + case '\r': + // TODO: Carriage return + return ; + } + + int ret = 0; + while( ret < Len ) + { + if( *Buf == '\n' ) + break; + if( *Buf == '\x1b' ) + break; + ret ++; + Buf ++; + } + return -ret; +} -- 2.20.1