From 85eb17b306404571aa39596946c87ad9bb1d9d13 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Fri, 30 Apr 2010 23:43:46 +0800 Subject: [PATCH] Many changes, bugfixes to user vsnprintf and to escape code handling - Added coloured messages to kernel output - Implemented arguments to staticly compiled modules - Updated VTerm to only change video modes when needed (not fully tested yet) - Other misc changes to kernel - Dramatic overhaul of AxWin, nearing completion --- Kernel/Makefile.BuildNum | 2 +- Kernel/arch/x86/errors.c | 2 +- Kernel/arch/x86/main.c | 50 ++- Kernel/arch/x86/time.c | 5 +- Kernel/drv/vterm.c | 197 +++++--- Kernel/include/acess.h | 4 +- Kernel/include/tpl_drv_video.h | 13 +- Kernel/lib.c | 63 ++- Kernel/logging.c | 9 +- Kernel/modules.c | 58 ++- Kernel/system.c | 135 ++++-- Kernel/threads.c | 3 +- Modules/IPStack/ipv4.c | 4 +- Modules/IPStack/ipv6.c | 14 +- Usermode/Applications/Makefile.tpl | 13 +- Usermode/Applications/axwin2_src/WM/Makefile | 2 +- Usermode/Applications/axwin2_src/WM/common.h | 5 +- .../Applications/axwin2_src/WM/decorator.c | 76 ++++ .../Applications/axwin2_src/WM/interface.c | 23 +- Usermode/Applications/axwin2_src/WM/main.c | 7 +- .../Applications/axwin2_src/WM/messages.c | 10 +- Usermode/Applications/axwin2_src/WM/video.c | 22 + Usermode/Applications/axwin2_src/WM/wm.c | 425 +++++++++++++++++- Usermode/Applications/axwin2_src/WM/wm.h | 69 ++- Usermode/Libraries/libc.so_src/fileIO.c | 69 ++- Usermode/include/axwin/messages.h | 3 +- Usermode/include/stdio.h | 1 + Usermode/include/string.h | 29 -- Usermode/include/sys/sys.h | 2 - 29 files changed, 1081 insertions(+), 234 deletions(-) create mode 100644 Usermode/Applications/axwin2_src/WM/decorator.c delete mode 100644 Usermode/include/string.h diff --git a/Kernel/Makefile.BuildNum b/Kernel/Makefile.BuildNum index 306f0f32..88ef808d 100644 --- a/Kernel/Makefile.BuildNum +++ b/Kernel/Makefile.BuildNum @@ -1 +1 @@ -BUILD_NUM = 2072 +BUILD_NUM = 2138 diff --git a/Kernel/arch/x86/errors.c b/Kernel/arch/x86/errors.c index f5391832..ac54bc11 100644 --- a/Kernel/arch/x86/errors.c +++ b/Kernel/arch/x86/errors.c @@ -71,7 +71,7 @@ void ErrorHandler(tRegs *Regs) Regs->int_num, csaERROR_NAMES[Regs->int_num], Regs->err_code); Warning(" CS:EIP = 0x%04x:%08x", Regs->cs, Regs->eip); if(Regs->cs == 0x08) - Warning(" SS:ESP = 0x0010:%08x", 0x10, (Uint)Regs+sizeof(tRegs)); + Warning(" SS:ESP = 0x0010:%08x", (Uint)Regs+sizeof(tRegs)); else Warning(" SS:ESP = 0x%04x:%08x", Regs->ss, Regs->esp); Warning(" EFLAGS = 0x%08x", Regs->eflags); diff --git a/Kernel/arch/x86/main.c b/Kernel/arch/x86/main.c index fa3cb454..2dca5635 100644 --- a/Kernel/arch/x86/main.c +++ b/Kernel/arch/x86/main.c @@ -23,11 +23,20 @@ extern int Time_Setup(void); extern Uint Proc_Clone(Uint *Err, Uint Flags); extern void Threads_Sleep(void); extern void Threads_Exit(void); +// --- Core --- +extern void System_Init(char *Commandline); -extern int Modules_LoadBuiltins(void); +// === PROTOTYPES === +void Arch_LoadBootModules(void); // === GLOBALS === char *gsBootCmdLine = NULL; +struct { + void *Base; + Uint Size; + char *ArgString; +} *gaArch_BootModules; + int giArch_NumBootModules = 0; // === CODE === int kmain(Uint MbMagic, void *MbInfoPtr) @@ -81,35 +90,44 @@ int kmain(Uint MbMagic, void *MbInfoPtr) // Load Virtual Filesystem VFS_Init(); - // Initialise builtin modules - Log_Log("Arch", "Initialising builtin modules..."); - Modules_LoadBuiltins(); - - Log_Log("Arch", "Loading %i Modules...", mbInfo->ModuleCount); - // Load initial modules mods = (void*)( mbInfo->Modules + KERNEL_BASE ); + giArch_NumBootModules = mbInfo->ModuleCount; + gaArch_BootModules = malloc( giArch_NumBootModules * sizeof(*gaArch_BootModules) ); for( i = 0; i < mbInfo->ModuleCount; i ++ ) { // Adjust into higher half - mods[i].Start += KERNEL_BASE; - mods[i].End += KERNEL_BASE; + mods[i].Start += KERNEL_BASE; + mods[i].End += KERNEL_BASE; mods[i].String += KERNEL_BASE; - Log_Log("Arch", "Loading '%s'", mods[i].String); - - if( !Module_LoadMem( (void *)mods[i].Start, mods[i].End-mods[i].Start, (char *)mods[i].String ) ) - { - Log_Warning("Arch", "Unable to load module\n"); - } + gaArch_BootModules[i].Base = (void *)mods[i].Start; + gaArch_BootModules[i].Size = mods[i].End - mods[i].Start; + gaArch_BootModules[i].ArgString = (char *)mods[i].String; } // Pass on to Independent Loader Log_Log("Arch", "Starting system"); - System_Init( gsBootCmdLine ); + System_Init(gsBootCmdLine); // Sleep forever (sleeping beauty) for(;;) Threads_Sleep(); return 0; } + +void Arch_LoadBootModules(void) +{ + int i; + for( i = 0; i < giArch_NumBootModules; i ++ ) + { + Log_Log("Arch", "Loading '%s'", gaArch_BootModules[i].ArgString); + + if( !Module_LoadMem( gaArch_BootModules[i].Base, gaArch_BootModules[i].Size, gaArch_BootModules[i].ArgString ) ) + { + Log_Warning("Arch", "Unable to load module\n"); + } + } + Log_Log("Arch", "Boot modules loaded"); + free( gaArch_BootModules ); +} diff --git a/Kernel/arch/x86/time.c b/Kernel/arch/x86/time.c index 5f7d5927..cdf23705 100644 --- a/Kernel/arch/x86/time.c +++ b/Kernel/arch/x86/time.c @@ -8,8 +8,9 @@ // === MACROS === #define NUM_TIMERS 8 #define TIMER_QUANTUM 100 -#define TIMER_RATE 13 // (Max: 15, Min: 2) - 15 = 1Hz, 13 = 4Hz, 10 = 1024Hz -#define TIMER_FREQ (32768>>TIMER_RATE) //Hz +// 2^(15-rate), 15: 1HZ, 5: 1024Hz, 2: 8192Hz +#define TIMER_RATE 12 // (Max: 15, Min: 2) - 15 = 1Hz, 13 = 4Hz, 12 = 8Hz, 11 = 16Hz 10 = 32Hz, 2 +#define TIMER_FREQ (0x8000>>TIMER_RATE) //Hz #define MS_PER_TICK_WHOLE (1000/(TIMER_FREQ)) #define MS_PER_TICK_FRACT ((Uint64)(1000*TIMER_FREQ-((Uint64)MS_PER_TICK_WHOLE)*0x80000000/TIMER_FREQ)) diff --git a/Kernel/drv/vterm.c b/Kernel/drv/vterm.c index ab1e97d1..b73e8dea 100644 --- a/Kernel/drv/vterm.c +++ b/Kernel/drv/vterm.c @@ -18,13 +18,14 @@ #define NUM_VTS 8 #define MAX_INPUT_CHARS32 64 #define MAX_INPUT_CHARS8 (MAX_INPUT_CHARS32*4) -#define VT_SCROLLBACK 2 // 2 Screens of text -//#define DEFAULT_OUTPUT "VGA" //#define DEFAULT_OUTPUT "BochsGA" #define DEFAULT_OUTPUT "Vesa" #define DEFAULT_INPUT "PS2Keyboard" -#define DEFAULT_WIDTH 80 -#define DEFAULT_HEIGHT 25 +#define DEFAULT_WIDTH 640 +#define DEFAULT_HEIGHT 480 +#define DEFAULT_SCROLLBACK 2 // 2 Screens of text + current screen +#define TEXTTERM_WIDTH (BOOT_WIDTH/8) +#define TEXTTERM_HEIGHT (BOOT_WIDTH/16) #define DEFAULT_COLOUR (VT_COL_BLACK|(0xAAA<<16)) #define VT_FLAG_HIDECSR 0x01 @@ -71,7 +72,8 @@ tVFS_Node *VT_FindDir(tVFS_Node *Node, char *Name); Uint64 VT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); Uint64 VT_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer); int VT_Terminal_IOCtl(tVFS_Node *Node, int Id, void *Data); -void VT_SetResolution(int IsTextMode, int Width, int Height); +void VT_SetResolution(int Width, int Height); +void VT_SetMode(int Mode); void VT_SetTerminal(int ID); void VT_KBCallBack(Uint32 Codepoint); void VT_int_PutString(tVTerm *Term, Uint8 *Buffer, Uint Count); @@ -83,6 +85,8 @@ void VT_int_ChangeMode(tVTerm *Term, int NewMode); // === CONSTANTS === const Uint16 caVT100Colours[] = { + // Black, Red, Green, Yellow, Blue, Purple, Cyan, Gray + // Same again, but bright VT_COL_BLACK, 0x700, 0x070, 0x770, 0x007, 0x707, 0x077, 0xAAA, VT_COL_GREY, 0xF00, 0x0F0, 0xFF0, 0x00F, 0xF0F, 0x0FF, VT_COL_WHITE }; @@ -106,8 +110,9 @@ tVTerm gVT_Terminals[NUM_VTS]; int giVT_CurrentTerminal = 0; tVTerm *gpVT_CurTerm = &gVT_Terminals[0]; // --- Video State --- -short giVT_RealWidth; //!< Real Width -short giVT_RealHeight; //!< Real Height +short giVT_RealWidth = DEFAULT_WIDTH; //!< Screen Width +short giVT_RealHeight = DEFAULT_HEIGHT; //!< Screen Height + int giVT_Scrollback = DEFAULT_SCROLLBACK; // --- Driver Handles --- char *gsVT_OutputDevice = NULL; char *gsVT_InputDevice = NULL; @@ -125,36 +130,35 @@ char *gsVT_InputDevice = NULL; */ int VT_Install(char **Arguments) { - char **args = Arguments; - char *arg; int i; // Scan Arguments if(Arguments) { + char **args = Arguments; + char *arg, *opt, *val; for( ; (arg = *args); args++ ) { - if(arg[0] != '-') continue; + Log_Debug("VTerm", "Argument '%s'", arg); + opt = arg; + val = arg + strpos(arg, '='); *val++ = '\0'; - switch(arg[1]) - { - // Set output device - case 'o': - if(args[1] == NULL) break; + if( strcmp(opt, "Video") == 0 ) { if(gsVT_OutputDevice) free(gsVT_OutputDevice); - gsVT_OutputDevice = malloc(strlen(args[1])+1); - strcpy(gsVT_OutputDevice, args[1]); - args ++; - break; - - // Set input device - case 'i': - if(args[1] == NULL) break; + gsVT_OutputDevice = strdup(val); + } + else if( strcmp(opt, "Input") == 0 ) { if(gsVT_InputDevice) free(gsVT_InputDevice); - gsVT_InputDevice = malloc(strlen(args[1])+1); - strcpy(gsVT_InputDevice, args[1]); - args ++; - break; + gsVT_InputDevice = strdup(val); + } + else if( strcmp(opt, "Width") == 0 ) { + giVT_RealWidth = atoi( val ); + } + else if( strcmp(opt, "Height") == 0 ) { + giVT_RealHeight = atoi( val ); + } + else if( strcmp(opt, "Scrollback") == 0 ) { + giVT_Scrollback = atoi( val ); } } } @@ -171,13 +175,16 @@ int VT_Install(char **Arguments) { gVT_Terminals[i].Mode = TERM_MODE_TEXT; gVT_Terminals[i].Flags = 0; - gVT_Terminals[i].Width = DEFAULT_WIDTH; - gVT_Terminals[i].Height = DEFAULT_HEIGHT; + gVT_Terminals[i].Width = giVT_RealWidth/giVT_CharWidth; + gVT_Terminals[i].Height = giVT_RealHeight/giVT_CharHeight; gVT_Terminals[i].CurColour = DEFAULT_COLOUR; gVT_Terminals[i].WritePos = 0; gVT_Terminals[i].ViewPos = 0; - gVT_Terminals[i].Buffer = calloc( DEFAULT_WIDTH*DEFAULT_HEIGHT*VT_SCROLLBACK, sizeof(tVT_Char) ); + gVT_Terminals[i].Buffer = calloc( + gVT_Terminals[i].Width*gVT_Terminals[i].Height*(giVT_Scrollback+1), + sizeof(tVT_Char) + ); gVT_Terminals[i].Name[0] = '0'+i; gVT_Terminals[i].Name[1] = '\0'; @@ -214,8 +221,9 @@ void VT_InitOutput() Log_Warning("VTerm", "Oh F**k, I can't open the video device '%s'", gsVT_OutputDevice); return ; } + VT_SetResolution(giVT_RealWidth, giVT_RealHeight); VT_SetTerminal( 0 ); - VT_SetResolution(1, 640, 400); + VT_SetMode( VIDEO_BUFFMT_TEXT ); } /** @@ -425,6 +433,7 @@ int VT_Terminal_IOCtl(tVFS_Node *Node, int Id, void *Data) switch(Id) { + // --- Core Defined case DRV_IOCTL_TYPE: LEAVE('i', DRV_TYPE_TERMINAL); return DRV_TYPE_TERMINAL; @@ -443,7 +452,12 @@ int VT_Terminal_IOCtl(tVFS_Node *Node, int Id, void *Data) case TERM_IOCTL_MODETYPE: if(Data != NULL) { + if( CheckMem(Data, sizeof(int)) == 0 ) { + LEAVE('i', -1); + return -1; + } Log_Log("VTerm", "VTerm %i mode set to %i", (int)Node->Inode, *iData); + // Update mode if needed if(term->Mode != *iData) VT_int_ChangeMode(term, *iData); @@ -457,14 +471,26 @@ int VT_Terminal_IOCtl(tVFS_Node *Node, int Id, void *Data) // Get/set the terminal width case TERM_IOCTL_WIDTH: - if(Data != NULL) term->Width = *iData; + if(Data != NULL) { + if( CheckMem(Data, sizeof(int)) == 0 ) { + LEAVE('i', -1); + return -1; + } + term->Width = *iData; + } Log("VT_Terminal_IOCtl - RETURN term->Width = %i", term->Width); LEAVE('i', term->Width); return term->Width; // Get/set the terminal height case TERM_IOCTL_HEIGHT: - if(Data != NULL) term->Height = *iData; + if(Data != NULL) { + if( CheckMem(Data, sizeof(int)) == 0 ) { + LEAVE('i', -1); + return -1; + } + term->Height = *iData; + } Log("VT_Terminal_IOCtl - RETURN term->Height = %i", term->Height); LEAVE('i', term->Height); return term->Height; @@ -480,10 +506,11 @@ int VT_Terminal_IOCtl(tVFS_Node *Node, int Id, void *Data) return -1; } -void VT_SetResolution(int IsTextMode, int Width, int Height) +void VT_SetResolution(int Width, int Height) { tVideo_IOCtl_Mode mode = {0}; int tmp; + int i; // Create the video mode mode.width = Width; @@ -494,12 +521,41 @@ void VT_SetResolution(int IsTextMode, int Width, int Height) // Set video mode VFS_IOCtl( giVT_OutputDevHandle, VIDEO_IOCTL_FINDMODE, &mode ); tmp = mode.id; - giVT_RealWidth = mode.width; - giVT_RealHeight = mode.height; + if( Width != mode.width || Height != mode.height ) + { + Log_Warning("VTerm", + "Selected resolution (%ix%i is not supported) by the device, using (%ix%i)", + giVT_RealWidth, giVT_RealHeight, + mode.width, mode.height + ); + } VFS_IOCtl( giVT_OutputDevHandle, VIDEO_IOCTL_GETSETMODE, &tmp ); - tmp = IsTextMode ? VIDEO_BUFFMT_TEXT : VIDEO_BUFFMT_FRAMEBUFFER; - VFS_IOCtl( giVT_OutputDevHandle, VIDEO_IOCTL_SETBUFFORMAT, &tmp ); + // Resize text terminals if needed + if( giVT_RealWidth != mode.width || giVT_RealHeight != mode.height ) + { + int newBufSize = (giVT_RealWidth/giVT_CharWidth) + *(giVT_RealHeight/giVT_CharHeight) + *(giVT_Scrollback+1); + //tVT_Char *tmp; + // Resize the text terminals + giVT_RealWidth = mode.width; + giVT_RealHeight = mode.height; + for( i = 0; i < NUM_VTS; i ++ ) + { + if( gVT_Terminals[i].Mode != TERM_MODE_TEXT ) continue; + + gVT_Terminals[i].Text = realloc( + gVT_Terminals[i].Text, + newBufSize*sizeof(tVT_Char) + ); + } + } +} + +void VT_SetMode(int Mode) +{ + VFS_IOCtl( giVT_OutputDevHandle, VIDEO_IOCTL_SETBUFFORMAT, &Mode ); } /** @@ -523,9 +579,9 @@ void VT_SetTerminal(int ID) } if( gpVT_CurTerm->Mode == TERM_MODE_TEXT ) - VT_SetResolution( 1, gpVT_CurTerm->Width*giVT_CharWidth, gpVT_CurTerm->Height*giVT_CharHeight ); + VT_SetMode( VIDEO_BUFFMT_TEXT ); else - VT_SetResolution( 0, gpVT_CurTerm->Width, gpVT_CurTerm->Height ); + VT_SetMode( VIDEO_BUFFMT_FRAMEBUFFER ); // Update the screen VT_int_UpdateScreen( &gVT_Terminals[ ID ], 1 ); @@ -612,10 +668,10 @@ void VT_KBCallBack(Uint32 Codepoint) gpVT_CurTerm->ViewPos = 0; return; case KEY_PGDOWN: - if( gpVT_CurTerm->ViewPos < gpVT_CurTerm->Width*(gpVT_CurTerm->Height*(VT_SCROLLBACK-1)) ) + if( gpVT_CurTerm->ViewPos < gpVT_CurTerm->Width*gpVT_CurTerm->Height*(giVT_Scrollback-1) ) gpVT_CurTerm->ViewPos += gpVT_CurTerm->Width; else - gpVT_CurTerm->ViewPos = gpVT_CurTerm->Width*(gpVT_CurTerm->Height*(VT_SCROLLBACK-1)); + gpVT_CurTerm->ViewPos = gpVT_CurTerm->Width*gpVT_CurTerm->Height*(giVT_Scrollback-1); return; } } @@ -725,28 +781,36 @@ int VT_int_ParseEscape(tVTerm *Term, char *Buffer) char c; int argc = 0, j = 1; int tmp; - int args[4] = {0,0,0,0}; + int args[6] = {0,0,0,0}; - switch(Buffer[0]) { + switch(Buffer[0]) + { //Large Code case '[': // Get Arguments - c = Buffer[1]; - do { - while('0' <= c && c <= '9') { - args[argc] *= 10; - args[argc] += c-'0'; - c = Buffer[++j]; - } - if( j != 1 ) argc ++; - } while(c == ';'); + c = Buffer[j++]; + if( '0' <= c && c <= '9' ) + { + do { + while('0' <= c && c <= '9') { + args[argc] *= 10; + args[argc] += c-'0'; + c = Buffer[j++]; + } + argc ++; + } while(c == ';'); + } + /* // Get string (what does this do?) if(c == '"') { - c = Buffer[++j]; + c = Buffer[j++]; while(c != '"') - c = Buffer[++j]; + c = Buffer[j++]; } + */ + + //Log_Debug("VTerm", "argc = %i", argc); // Get Command if( ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) @@ -782,7 +846,7 @@ int VT_int_ParseEscape(tVTerm *Term, char *Buffer) { case 2: { - int i = Term->Height * VT_SCROLLBACK; + int i = Term->Height * (giVT_Scrollback + 1); while( i-- ) VT_int_ClearLine(Term, i); Term->WritePos = 0; Term->ViewPos = 0; @@ -817,15 +881,18 @@ int VT_int_ParseEscape(tVTerm *Term, char *Buffer) } } break; + default: + Log_Warning("VTerm", "Unknown control sequence"); + break; } } break; - default: - break; + default: break; } - return j + 1; + //Log_Debug("VTerm", "j = %i, Buffer = '%s'", j, Buffer); + return j; } /** @@ -841,7 +908,7 @@ void VT_int_PutString(tVTerm *Term, Uint8 *Buffer, Uint Count) if( Buffer[i] == 0x1B ) // Escape Sequence { i ++; - i += VT_int_ParseEscape(Term, (char*)&Buffer[i]); + i += VT_int_ParseEscape(Term, (char*)&Buffer[i]) - 1; continue; } @@ -923,25 +990,25 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch) } // Move Screen - if(Term->WritePos >= Term->Width*Term->Height*VT_SCROLLBACK) + if(Term->WritePos >= Term->Width*Term->Height*(giVT_Scrollback+1)) { int base, i; Term->WritePos -= Term->Width; VT_int_UpdateScreen( Term, 0 ); // Update view position - base = Term->Width*Term->Height*(VT_SCROLLBACK-1); + base = Term->Width*Term->Height*(giVT_Scrollback-1); if(Term->ViewPos < base) Term->ViewPos += Term->Width; if(Term->ViewPos > base) Term->ViewPos = base; // Scroll terminal cache - base = Term->Width*(Term->Height*VT_SCROLLBACK-1); + base = Term->Width*(Term->Height*(giVT_Scrollback+1)-1); // Scroll Back memcpy( Term->Text, &Term->Text[Term->Width], - (Term->Width*Term->Height*VT_SCROLLBACK-Term->Width)*sizeof(tVT_Char) + (Term->Width*Term->Height*(giVT_Scrollback+1)-Term->Width)*sizeof(tVT_Char) ); // Clear last row @@ -1061,7 +1128,7 @@ void VT_int_ChangeMode(tVTerm *Term, int NewMode) case TERM_MODE_TEXT: Log_Log("VTerm", "Set VT %p to text mode", Term); free(Term->Buffer); - Term->Text = calloc( Term->Width*Term->Height*VT_SCROLLBACK, sizeof(tVT_Char) ); + Term->Text = calloc( Term->Width*Term->Height*(giVT_Scrollback+1), sizeof(tVT_Char) ); break; case TERM_MODE_FB: Log_Log("VTerm", "Set VT %p to framebuffer mode (%ix%i)", Term, diff --git a/Kernel/include/acess.h b/Kernel/include/acess.h index 09c4f517..8e62578a 100644 --- a/Kernel/include/acess.h +++ b/Kernel/include/acess.h @@ -95,9 +95,6 @@ typedef struct sKernelSymbol { */ // === FUNCTIONS === -// --- Core --- -extern void System_Init(char *ArgString); - // --- IRQs --- extern int IRQ_AddHandler(int Num, void (*Callback)(int)); @@ -315,6 +312,7 @@ extern int strcmp(const char *__str1, const char *__str2); extern int strncmp(const char *Str1, const char *Str2, size_t num); extern int strucmp(const char *Str1, const char *Str2); extern char *strdup(const char *Str); +extern char **str_split(const char *__str, char __ch); extern int strpos(const char *Str, char Ch); extern int strpos8(const char *str, Uint32 search); extern void itoa(char *buf, Uint num, int base, int minLength, char pad); diff --git a/Kernel/include/tpl_drv_video.h b/Kernel/include/tpl_drv_video.h index f3313f62..1c00c5ed 100644 --- a/Kernel/include/tpl_drv_video.h +++ b/Kernel/include/tpl_drv_video.h @@ -15,8 +15,6 @@ * Writes to the driver's file while in component colour modes * must correspond to a change of the contents of the screen. The framebuffer * must start at offset 0 in the file. - * In pallete colour modes the LFB is preceded by a 1024 byte pallete (allowing - * room for 256 entries of 32-bits each) * Reading from the screen must either return zero, or read from the * framebuffer. * @@ -190,6 +188,17 @@ enum eTplVideo_2DCommands */ VIDEO_2DOP_BLIT, + + /** + * \brief Copy a region from video memory to the framebuffer + */ + VIDEO_2DOP_BLITBUF, + + /** + * \brief Copy and scale a region from video memory to the framebuffer + */ + VIDEO_2DOP_BLITSCALEBUF, + NUM_VIDEO_2DOPS }; diff --git a/Kernel/lib.c b/Kernel/lib.c index ac8f6168..ab64d675 100644 --- a/Kernel/lib.c +++ b/Kernel/lib.c @@ -28,10 +28,11 @@ char *strncpy(char *__str1, const char *__str2, size_t max); int strcmp(const char *str1, const char *str2); int strncmp(const char *str1, const char *str2, size_t num); char *strdup(const char *Str); - int DivUp(int num, int dem); +char **str_split(const char *__str, char __ch); int strpos8(const char *str, Uint32 Search); int ReadUTF8(Uint8 *str, Uint32 *Val); int WriteUTF8(Uint8 *str, Uint32 Val); + int DivUp(int num, int dem); Sint64 timestamp(int sec, int mins, int hrs, int day, int month, int year); Uint rand(void); int CheckString(char *String); @@ -54,8 +55,9 @@ EXPORT(strncpy); EXPORT(strcmp); EXPORT(strncmp); EXPORT(strdup); -EXPORT(DivUp); +EXPORT(str_split); EXPORT(strpos8); +EXPORT(DivUp); EXPORT(ReadUTF8); EXPORT(WriteUTF8); EXPORT(timestamp); @@ -230,8 +232,12 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args) pad = ' '; // - Minimum length - minSize = 1; - if('1' <= c && c <= '9') + if(c == '*') { + minSize = val; + val = va_arg(args, Uint); + c = *__format++; + } + else if('1' <= c && c <= '9') { minSize = 0; while('0' <= c && c <= '9') @@ -241,6 +247,8 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args) c = *__format++; } } + else + minSize = 1; // - Default, Long or LongLong? isLongLong = 0; @@ -300,6 +308,7 @@ int vsnprintf(char *__s, size_t __maxlen, const char *__format, va_list args) case 'C': // Non-Null Terminated Character Array p = (char*)(Uint)val; if(!p) goto printString; + //while(minSize--) PUTCH(*p++); while(minSize--) PUTCH(*p++); break; @@ -451,6 +460,52 @@ char *strdup(const char *Str) return ret; } +/** + * \brief Split a string using the passed character + * \return NULL terminated array of strings on the heap + * \param __str String to split + * \param __ch Character to split by + */ +char **str_split(const char *__str, char __ch) +{ + int i, j; + int len = 1; + char **ret; + char *start; + + for( i = 0; __str[i]; i++ ) + { + if(__str[i] == __ch) + len ++; + } + + ret = malloc( sizeof(char*)*(len+1) + (i + 1) ); + if( !ret ) return NULL; + + j = 1; + start = (char *)&ret[len+1]; + ret[0] = start; + for( i = 0; __str[i]; i++ ) + { + if(__str[i] == __ch) { + *start++ = '\0'; + Log_Debug("Lib", "str_split: ret[%i] = '%s'", j-1, ret[j-1]); + ret[j++] = start; + } + else { + *start++ = __str[i]; + } + } + *start = '\0'; + ret[j] = NULL; + Log_Debug("Lib", "str_split: ret[%i] = '%s'", j-1, ret[j-1]); + + for( j = 0; j < len; j++ ) + Log_Debug("Lib", "str_split: ret[%i] = '%s'", j, ret[j]); + + return ret; +} + /** * \fn int DivUp(int num, int dem) * \brief Divide two numbers, rounding up diff --git a/Kernel/logging.c b/Kernel/logging.c index 18f75fb6..f4a23b4b 100644 --- a/Kernel/logging.c +++ b/Kernel/logging.c @@ -21,7 +21,11 @@ enum eLogLevels LOG_LEVEL_DEBUG, NUM_LOG_LEVELS }; -const char *csaLevelCodes[] = {"k","p","f","e","w","n","l","d"}; +const char *csaLevelColours[] = { + "\x1B[35m", "\x1B[34m", "\x1B[36m", "\x1B[31m", + "\x1B[33m", "\x1B[32m", "\x1B[0m", "\x1B[0m" + }; +const char *csaLevelCodes[] = {"k","p","f","e","w","n","l","d"}; // === TYPES === typedef struct sLogEntry @@ -118,7 +122,8 @@ void Log_AddEvent(char *Ident, int Level, char *Format, va_list Args) */ void Log_Int_PrintMessage(tLogEntry *Entry) { - LogF("%018lli%s [%+8s] %s\n", + LogF("%s%018lli%s [%+8s] %s\x1B[0m\n", + csaLevelColours[Entry->Level], Entry->Time, csaLevelCodes[Entry->Level], Entry->Ident, diff --git a/Kernel/modules.c b/Kernel/modules.c index 68d5ba00..41fb5143 100644 --- a/Kernel/modules.c +++ b/Kernel/modules.c @@ -10,7 +10,9 @@ #define USE_UDI 0 // === PROTOTYPES === - int Modules_LoadBuiltins(void); + int Module_int_Initialise(tModule *Module, char *ArgString); +void Modules_LoadBuiltins(void); +void Modules_SetBuiltinParams(char *Name, char *ArgString); int Module_RegisterLoader(tModuleLoader *Loader); int Module_LoadMem(void *Buffer, Uint Length, char *ArgString); int Module_LoadFile(char *Path, char *ArgString); @@ -34,6 +36,7 @@ tSpinlock glModuleSpinlock; tModule *gLoadedModules = NULL; tModuleLoader *gModule_Loaders = NULL; tModule *gLoadingModules = NULL; +char **gasBuiltinModuleArgs; // === CODE === /** @@ -45,11 +48,12 @@ tModule *gLoadingModules = NULL; * \retval 0 Returned on success * \retval >0 Error code form the module's initialisation function */ -int Module_int_Initialise(tModule *Module) +int Module_int_Initialise(tModule *Module, char *ArgString) { int i, j; int ret; char **deps; + char **args; tModule *mod; ENTER("pModule", Module); @@ -100,7 +104,10 @@ int Module_int_Initialise(tModule *Module) } // Dependency is not loaded, so load it - ret = Module_int_Initialise( &gKernelModules[i] ); + ret = Module_int_Initialise( + &gKernelModules[i], + gasBuiltinModuleArgs ? gasBuiltinModuleArgs[i] : NULL + ); if( ret ) { // The only "ok" error is NOTNEEDED @@ -116,7 +123,15 @@ int Module_int_Initialise(tModule *Module) Module->Version >> 8, Module->Version & 0xFF ); - ret = Module->Init(NULL); + if( ArgString ) + args = str_split( ArgString, ',' ); + else + args = NULL; + + ret = Module->Init(args); + + if(args) free(args); + if( ret != MODULE_ERR_OK ) { switch(ret) { @@ -153,7 +168,7 @@ int Module_int_Initialise(tModule *Module) /** * \brief Initialises builtin modules */ -int Modules_LoadBuiltins() +void Modules_LoadBuiltins() { int i; @@ -163,10 +178,37 @@ int Modules_LoadBuiltins() for( i = 0; i < giNumBuiltinModules; i++ ) { - Module_int_Initialise( &gKernelModules[i] ); + Module_int_Initialise( + &gKernelModules[i], + (gasBuiltinModuleArgs ? gasBuiltinModuleArgs[i] : NULL) + ); } - return 0; + if( gasBuiltinModuleArgs != NULL ) + free(gasBuiltinModuleArgs); +} + +/** + * \brief Sets the parameters for a builtin module + */ +void Modules_SetBuiltinParams(char *Name, char *ArgString) +{ + int i; + if( gasBuiltinModuleArgs == NULL ) { + giNumBuiltinModules = (Uint)&gKernelModulesEnd - (Uint)&gKernelModules; + giNumBuiltinModules /= sizeof(tModule); + gasBuiltinModuleArgs = calloc( giNumBuiltinModules, sizeof(char*) ); + } + + for( i = 0; i < giNumBuiltinModules; i ++ ) + { + if(strcmp( gKernelModules[i].Name, Name ) == 0) { + gasBuiltinModuleArgs[i] = ArgString; + return ; + } + } + + Log_Warning("Modules", "Unknown builtin kernel module '%s'", Name); } /** @@ -258,7 +300,7 @@ int Module_LoadFile(char *Path, char *ArgString) } #if 1 - if( Module_int_Initialise( info ) ) + if( Module_int_Initialise( info, ArgString ) ) { Binary_Unload(base); return 0; diff --git a/Kernel/system.c b/Kernel/system.c index 546b2d80..7c5ff32f 100644 --- a/Kernel/system.c +++ b/Kernel/system.c @@ -32,31 +32,32 @@ typedef struct } tConfigCommand; // === IMPORTS === +extern void Arch_LoadBootModules(); extern int Modules_LoadBuiltins(); -//extern int PCI_Install(); -extern void DMA_Install(); +extern void Modules_SetBuiltinParams(char *Name, char *ArgString); extern void Debug_SetKTerminal(char *File); -extern void StartupPrint(char *Str); // === PROTOTYPES === -void System_Init(char *ArgString); +void System_Init(char *Commandline); void System_ParseCommandLine(char *ArgString); +void System_ExecuteCommandLine(void); void System_ParseVFS(char *Arg); +void System_ParseModuleArgs(char *Arg); void System_ParseSetting(char *Arg); -void System_ExecuteScript(); +void System_ExecuteScript(void); tConfigFile *System_Int_ParseFile(char *File); // === CONSTANTS === const tConfigCommand caConfigCommands[] = { - {"module", 1,2, 0, Module_LoadFile, {(Uint)"",0}}, // Load a module from a file - {"spawn", 1,1, 0, Proc_Spawn, {0}}, // Spawn a process + {"module", 1,2, 00, Module_LoadFile, {(Uint)"",0}}, // Load a module from a file + {"spawn", 1,1, 00, Proc_Spawn, {0}}, // Spawn a process // --- VFS --- - {"mount", 3,4, 0, VFS_Mount, {(Uint)"",0}}, // Mount a device - {"symlink", 2,2, 0, VFS_Symlink, {0}}, // Create a Symbolic Link - {"mkdir", 1,1, 0, VFS_MkDir, {0}}, // Create a Directory - {"open", 1,2, 0, VFS_Open, {VFS_OPENFLAG_READ,0}}, // Open a file - {"close", 1,1, 0x1, VFS_Close, {0}}, // Close an open file - {"ioctl", 3,3, 0x3, VFS_IOCtl, {0}}, // Call an IOCtl + {"mount", 3,4, 00, VFS_Mount, {(Uint)"",0}}, // Mount a device + {"symlink", 2,2, 00, VFS_Symlink, {0}}, // Create a Symbolic Link + {"mkdir", 1,1, 00, VFS_MkDir, {0}}, // Create a Directory + {"open", 1,2, 00, VFS_Open, {VFS_OPENFLAG_READ,0}}, // Open a file + {"close", 1,1, 01, VFS_Close, {0}}, // Close an open file + {"ioctl", 3,3, 03, VFS_IOCtl, {0}}, // Call an IOCtl {"", 0,0, 0, NULL, {0}} }; @@ -64,13 +65,21 @@ const tConfigCommand caConfigCommands[] = { // === GLOBALS === char *gsConfigScript = "/Acess/Conf/BootConf.cfg"; +char *argv[32]; + int argc; // === CODE === -void System_Init(char *ArgString) +void System_Init(char *CommandLine) { + // Parse Kernel's Command Line + System_ParseCommandLine(CommandLine); - // - Parse Kernel's Command Line - System_ParseCommandLine(ArgString); + // Initialise modules + Log_Log("Config", "Initialising builtin modules..."); + Modules_LoadBuiltins(); + Arch_LoadBootModules(); + + System_ExecuteCommandLine(); // - Execute the Config Script Log_Log("Config", "Executing config script..."); @@ -87,8 +96,6 @@ void System_Init(char *ArgString) */ void System_ParseCommandLine(char *ArgString) { - char *argv[32]; - int argc; int i; char *str; @@ -103,13 +110,13 @@ void System_ParseCommandLine(char *ArgString) // Check for the end of the string if(*str == '\0') { argc--; break;} argv[argc] = str; - while(*str && *str != ' ') - { - /*if(*str == '"') { - while(*str && !(*str == '"' && str[-1] != '\\')) - str ++; - }*/ - str++; + if(*str == '"') { + while(*str && !(*str == '"' && str[-1] != '\\')) + str ++; + } + else { + while(*str && *str != ' ') + str++; } if(*str == '\0') break; // Check for EOS *str = '\0'; // Cap off argument string @@ -118,13 +125,44 @@ void System_ParseCommandLine(char *ArgString) if(argc < 32) argc ++; // Count last argument - // --- Parse Arguments --- + // --- Parse Arguments (Pass 1) --- for( i = 1; i < argc; i++ ) { - if( argv[i][0] == '/' ) - System_ParseVFS( argv[i] ); - else + switch(argv[i][0]) + { + // --- VFS --- + // Ignored on this pass + case '/': + break; + + // --- Module Paramaters --- + // -VTerm:Width=640,Height=480,Scrollback=2 + case '-': + System_ParseModuleArgs( argv[i] ); + break; + // --- Config Options --- + // SCRIPT=/Acess/Conf/BootConf.cfg + default: System_ParseSetting( argv[i] ); + break; + } + } +} + +void System_ExecuteCommandLine(void) +{ + int i; + for( i = 1; i < argc; i++ ) + { + switch(argv[i][0]) + { + // --- VFS --- + // Mount /System=ext2:/Devices/ATA/A1 + // Symlink /Acess=/System/Acess2 + case '/': + System_ParseVFS( argv[i] ); + break; + } } } @@ -180,6 +218,37 @@ void System_ParseVFS(char *Arg) } } +/** + * \biref Parse a module argument string + */ +void System_ParseModuleArgs(char *Arg) +{ + char *name, *args; + int i; + + // Remove '-' + name = Arg + 1; + + // Find the start of the args + i = strpos(name, ':'); + if( i == -1 ) { + Log_Warning("Config", "Module spec with no arguments"); + #if 1 + return ; + #else + i = strlen(name); + args = name + i; + #endif + } + else { + name[i] = '\0'; + args = name + i + 1; + } + + Log_Log("Config", "Setting boot parameters for '%s' to '%s'", name, args); + Modules_SetBuiltinParams(name, args); +} + /** * \fn void System_ParseSetting(char *Arg) */ @@ -220,8 +289,9 @@ void System_ParseSetting(char *Arg) /** * \fn void System_ExecuteScript() + * \brief Reads and parses the boot configuration script */ -void System_ExecuteScript() +void System_ExecuteScript(void) { int fp; int fLen = 0; @@ -242,10 +312,11 @@ void System_ExecuteScript() return; } - // Read into memory buffer + // Get length VFS_Seek(fp, 0, SEEK_END); fLen = VFS_Tell(fp); VFS_Seek(fp, 0, SEEK_SET); + // Read into memory buffer fData = malloc(fLen+1); VFS_Read(fp, fLen, fData); fData[fLen] = '\0'; @@ -419,6 +490,8 @@ void System_ExecuteScript() } free( file->Lines[i].Parts ); } + + // Free data free( file ); free( fData ); } diff --git a/Kernel/threads.c b/Kernel/threads.c index f726f275..0a9ab372 100644 --- a/Kernel/threads.c +++ b/Kernel/threads.c @@ -266,10 +266,11 @@ int Threads_WaitTID(int TID, int *status) int initStatus = t->Status; int ret; - if(initStatus != THREAD_STAT_ZOMBIE) + if(initStatus != THREAD_STAT_ZOMBIE) { while(t->Status == initStatus) { Threads_Yield(); } + } ret = t->RetStatus; switch(t->Status) diff --git a/Modules/IPStack/ipv4.c b/Modules/IPStack/ipv4.c index d65adb6e..a1b9178b 100644 --- a/Modules/IPStack/ipv4.c +++ b/Modules/IPStack/ipv4.c @@ -103,6 +103,7 @@ void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buff int dataLength; if(Length < sizeof(tIPv4Header)) return; + #if 0 //Log_Log("IPv4", "Version = %i", hdr->Version); //Log_Log("IPv4", "HeaderLength = %i", hdr->HeaderLength); //Log_Log("IPv4", "DiffServices = %i", hdr->DiffServices); @@ -116,7 +117,8 @@ void IPv4_int_GetPacket(tAdapter *Adapter, tMacAddr From, int Length, void *Buff Log_Log("IPv4", "Destination = %i.%i.%i.%i", hdr->Destination.B[0], hdr->Destination.B[1], hdr->Destination.B[2], hdr->Destination.B[3] ); - + #endif + // Check that the version IS IPv4 if(hdr->Version != 4) { Log_Log("IPv4", "hdr->Version(%i) != 4", hdr->Version); diff --git a/Modules/IPStack/ipv6.c b/Modules/IPStack/ipv6.c index b709dfa0..7ae927a4 100644 --- a/Modules/IPStack/ipv6.c +++ b/Modules/IPStack/ipv6.c @@ -38,14 +38,14 @@ void IPv6_int_GetPacket(tAdapter *Interface, tMacAddr From, int Length, void *Bu return; Log("[IPv6 ] hdr = {"); - Log("[IPv6 ] .Version = %i", (hdr->Head >> (20+8)) & 0xF ); - Log("[IPv6 ] .TrafficClass = %i", (hdr->Head >> (20)) & 0xFF ); - Log("[IPv6 ] .FlowLabel = %i", hdr->Head & 0xFFFFF ); + Log("[IPv6 ] .Version = %i", (hdr->Head >> (20+8)) & 0xF ); + Log("[IPv6 ] .TrafficClass = %i", (hdr->Head >> (20)) & 0xFF ); + Log("[IPv6 ] .FlowLabel = %i", hdr->Head & 0xFFFFF ); Log("[IPv6 ] .PayloadLength = 0x%04x", ntohs(hdr->PayloadLength) ); - Log("[IPv6 ] .NextHeader = 0x%02x", hdr->NextHeader ); - Log("[IPv6 ] .HopLimit = 0x%02x", hdr->HopLimit ); - Log("[IPv6 ] .Source = %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", hdr->Source ); - Log("[IPv6 ] .Destination = %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", hdr->Destination ); + Log("[IPv6 ] .NextHeader = 0x%02x", hdr->NextHeader ); + Log("[IPv6 ] .HopLimit = 0x%02x", hdr->HopLimit ); + Log("[IPv6 ] .Source = %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", hdr->Source ); + Log("[IPv6 ] .Destination = %04x:%04x:%04x:%04x:%04x:%04x:%04x:%04x", hdr->Destination ); Log("[IPv6 ] }"); } diff --git a/Usermode/Applications/Makefile.tpl b/Usermode/Applications/Makefile.tpl index d18e52e3..8aad2695 100644 --- a/Usermode/Applications/Makefile.tpl +++ b/Usermode/Applications/Makefile.tpl @@ -2,9 +2,11 @@ # # -CFLAGS += -Wall -fno-builtin -fno-stack-protector +CFLAGS += -Wall -fno-builtin -fno-stack-protector -g LDFLAGS += +DEPFILES := $(OBJ:%.o=%.d) + .PHONY : all clean install all: $(BIN) @@ -17,9 +19,12 @@ install: $(BIN) $(BIN): $(OBJ) @echo --- $(LD) -o $@ - @$(LD) $(LDFLAGS) -o $@ $(OBJ) -Map Map.txt - @objdump -d $(BIN) > $(BIN).dsm + @$(LD) -g $(LDFLAGS) -o $@ $(OBJ) -Map Map.txt + @objdump -d -S $(BIN) > $(BIN).dsm $(OBJ): %.o: %.c @echo --- GCC -o $@ - @$(CC) $(CFLAGS) $(CPPFLAGS) -c $? -o $@ + @$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ + @$(CC) -M -MT $@ $(CPPFLAGS) $< -o $*.d + +-include $(DEPFILES) diff --git a/Usermode/Applications/axwin2_src/WM/Makefile b/Usermode/Applications/axwin2_src/WM/Makefile index cce4a811..95ccd410 100644 --- a/Usermode/Applications/axwin2_src/WM/Makefile +++ b/Usermode/Applications/axwin2_src/WM/Makefile @@ -7,6 +7,6 @@ CPPFLAGS += -I../include DIR := Apps/AxWin/1.0 BIN := ../AxWinWM OBJ := main.o helpers.o commandline.o video.o -OBJ += messages.o interface.o wm.o +OBJ += messages.o interface.o wm.o decorator.o -include ../../Makefile.tpl diff --git a/Usermode/Applications/axwin2_src/WM/common.h b/Usermode/Applications/axwin2_src/WM/common.h index 7ec792ab..06ea61ce 100644 --- a/Usermode/Applications/axwin2_src/WM/common.h +++ b/Usermode/Applications/axwin2_src/WM/common.h @@ -24,7 +24,8 @@ extern int giMouseFD; // === Functions === extern void memset32(void *ptr, uint32_t val, size_t count); -extern void Video_FillRect(short X, short Y, short W, short H, uint32_t Color); extern void Video_Update(void); - +extern void Video_FillRect(short X, short Y, short W, short H, uint32_t Color); +extern void Video_DrawRect(short X, short Y, short W, short H, uint32_t Color); +extern void Video_DrawText(short X, short Y, short W, short H, void *Font, int Point, uint32_t Color, char *Text); #endif diff --git a/Usermode/Applications/axwin2_src/WM/decorator.c b/Usermode/Applications/axwin2_src/WM/decorator.c new file mode 100644 index 00000000..3ab88e82 --- /dev/null +++ b/Usermode/Applications/axwin2_src/WM/decorator.c @@ -0,0 +1,76 @@ +/* + * Acess GUI (AxWin) Version 2 + * By John Hodge (thePowersGang) + * + * Widget Decorator + */ +#include "common.h" +#include "wm.h" + +#define BOX_BGCOLOUR 0xC0C0C0 +#define BOX_BORDER 0xA0A0A0 +#define BUTTON_BGCOLOUR 0xD0D0D0 +#define BUTTON_BORDER 0xF0F0F0 +#define TEXT_COLOUR 0x000000 + +// === CODE === +void Decorator_RenderWidget(tElement *Element) +{ + _SysDebug("Decorator_RenderWidget: (Element={Type:%i,(%i,%i) %ix%i})", + Element->Type, + Element->CachedX, Element->CachedY, + Element->CachedW, Element->CachedH + ); + + switch(Element->Type) + { + case ELETYPE_NONE: + case ELETYPE_BOX: break; + + case ELETYPE_TABBAR: // TODO: Moar + case ELETYPE_TOOLBAR: + Video_DrawRect( + Element->CachedX, Element->CachedY, + Element->CachedW, Element->CachedH, + BOX_BORDER + ); + Video_FillRect( + Element->CachedX, Element->CachedY, + Element->CachedW-2, Element->CachedH-2, + BOX_BGCOLOUR + ); + break; + + case ELETYPE_SPACER: + Video_FillRect( + Element->CachedX+3, Element->CachedY+3, + Element->CachedW-6, Element->CachedH-6, + BOX_BORDER + ); + break; + + case ELETYPE_BUTTON: + Video_FillRect( + Element->CachedX+1, Element->CachedY+1, + Element->CachedW-2, Element->CachedH-2, + BUTTON_BORDER + ); + Video_DrawRect( + Element->CachedX, Element->CachedY, + Element->CachedW-1, Element->CachedH-1, + BUTTON_BORDER + ); + break; + + case ELETYPE_TEXT: + Video_DrawText( + Element->CachedX+1, Element->CachedY+1, + Element->CachedW-2, Element->CachedH-2, + NULL, + 10, + TEXT_COLOUR, + Element->Text + ); + break; + } +} diff --git a/Usermode/Applications/axwin2_src/WM/interface.c b/Usermode/Applications/axwin2_src/WM/interface.c index 1eec6b4e..3876b77d 100644 --- a/Usermode/Applications/axwin2_src/WM/interface.c +++ b/Usermode/Applications/axwin2_src/WM/interface.c @@ -15,40 +15,45 @@ tElement *gpInterface_TabContent; // === CODE === void Interface_Init(void) { + tElement *area; tElement *btn, *text; giInterface_Width = giScreenWidth/16; - WM_SetFlags(NULL, ELEFLAG_HORIZONTAL); + WM_SetFlags(NULL, 0); // Create Sidebar gpInterface_Sidebar = WM_CreateElement(NULL, ELETYPE_TOOLBAR, ELEFLAG_VERTICAL); WM_SetSize( gpInterface_Sidebar, giInterface_Width ); // Create Main Area and regions within gpInterface_MainArea = WM_CreateElement(NULL, ELETYPE_BOX, ELEFLAG_VERTICAL); - gpInterface_HeaderBar = WM_CreateElement(gpInterface_MainArea, ELETYPE_BOX, ELEFLAG_HORIZONTAL); + gpInterface_HeaderBar = WM_CreateElement(gpInterface_MainArea, ELETYPE_BOX, 0); gpInterface_TabBar = WM_CreateElement(gpInterface_MainArea, ELETYPE_TABBAR, 0); gpInterface_TabContent = WM_CreateElement(gpInterface_MainArea, ELETYPE_BOX, 0); + // Main segment of the "taskbar" + area = WM_CreateElement(gpInterface_Sidebar, ELETYPE_BOX, ELEFLAG_VERTICAL); // Menu Button - btn = WM_CreateElement(gpInterface_Sidebar, ELETYPE_BUTTON, 0); + btn = WM_CreateElement(area, ELETYPE_BUTTON, ELEFLAG_NOEXPAND); WM_SetSize(btn, giInterface_Width); //text = WM_CreateElement(btn, ELETYPE_IMAGE, ELEFLAG_SCALE); - //WM_SetText(text, "asset://LogoSmall.png"); + //WM_SetText(text, "asset://LogoSmall.sif"); text = WM_CreateElement(btn, ELETYPE_TEXT, 0); WM_SetText(text, "Acess"); // Plain
style spacer - WM_CreateElement(gpInterface_Sidebar, ELETYPE_SPACER, 0); + WM_CreateElement(area, ELETYPE_SPACER, 0); - // Create spacing gap (aligns the rest to the bottom/right) - WM_CreateElement(gpInterface_Sidebar, ELETYPE_GAP, 0); + // Windows Go Here + + // Bottom Segment + area = WM_CreateElement(gpInterface_Sidebar, ELETYPE_BOX, ELEFLAG_VERTICAL|ELEFLAG_ALIGN_END); // Plain
style spacer - WM_CreateElement(gpInterface_Sidebar, ELETYPE_SPACER, 0); + WM_CreateElement(area, ELETYPE_SPACER, 0); // Version String - text = WM_CreateElement(gpInterface_Sidebar, ELETYPE_TEXT, ELEFLAG_WRAP); + text = WM_CreateElement(area, ELETYPE_TEXT, ELEFLAG_WRAP); WM_SetText(text, "AxWin 1.0"); } diff --git a/Usermode/Applications/axwin2_src/WM/main.c b/Usermode/Applications/axwin2_src/WM/main.c index 1a68acb2..1234b662 100644 --- a/Usermode/Applications/axwin2_src/WM/main.c +++ b/Usermode/Applications/axwin2_src/WM/main.c @@ -8,6 +8,7 @@ // === IMPORTS === extern void ParseCommandline(int argc, char *argv[]); extern void Video_Setup(void); +extern void WM_Update(void); extern void Messages_PollIPC(void); // === GLOBALS === @@ -31,11 +32,13 @@ int main(int argc, char *argv[]) ParseCommandline(argc, argv); if( gsTerminalDevice == NULL ) { - gsTerminalDevice = "/Devices/VTerm/7"; + gsTerminalDevice = "/Devices/VTerm/6"; } Video_Setup(); - Interface_Render(); + Interface_Init(); + + WM_Update(); // Main Loop for(;;) diff --git a/Usermode/Applications/axwin2_src/WM/messages.c b/Usermode/Applications/axwin2_src/WM/messages.c index 01bd07c4..92137f07 100644 --- a/Usermode/Applications/axwin2_src/WM/messages.c +++ b/Usermode/Applications/axwin2_src/WM/messages.c @@ -60,14 +60,16 @@ void Messages_Handle(tAxWin_Message *Msg, tMessages_Handle_Callback *Respond, in { switch(Msg->ID) { + #if 0 case MSG_SREQ_PING: - Msg->ID = MSG_SRSP_PONG; + Msg->ID = MSG_SRSP_VERSION; Msg->Size = 2; - Msg->SRsp_Pong.Major = 0; - Msg->SRsp_Pong.Minor = 1; - Msg->SRsp_Pong.Build = -1; + Msg->Data[0] = 0; + Msg->Data[1] = 1; + *(uint16_t*)&Msg->Data[2] = -1; Messages_RespondIPC(ID, sizeof(Msg->ID), Msg); break; + #endif default: fprintf(stderr, "WARNING: Unknown message %i from %i (%p)\n", Msg->ID, ID, Respond); _SysDebug("WARNING: Unknown message %i from %i (%p)\n", Msg->ID, ID, Respond); diff --git a/Usermode/Applications/axwin2_src/WM/video.c b/Usermode/Applications/axwin2_src/WM/video.c index fb082085..80e13024 100644 --- a/Usermode/Applications/axwin2_src/WM/video.c +++ b/Usermode/Applications/axwin2_src/WM/video.c @@ -70,9 +70,31 @@ void Video_FillRect(short X, short Y, short W, short H, uint32_t Color) { uint32_t *buf = gpScreenBuffer + Y*giScreenWidth + X; + _SysDebug("Video_FillRect: (X=%i, Y=%i, W=%i, H=%i, Color=%08x)", + X, Y, W, H, Color); + + if(W < 0 || X < 0 || X >= giScreenWidth) return ; + if(X + W > giScreenWidth) W = giScreenWidth - X; + + if(H < 0 || H < 0 || H >= giScreenHeight) return ; + if(Y + H > giScreenHeight) H = giScreenHeight - Y; + while( H -- ) { memset32( buf, Color, W ); buf += giScreenWidth; } } + +void Video_DrawRect(short X, short Y, short W, short H, uint32_t Color) +{ + Video_FillRect(X, Y, W, 1, Color); + Video_FillRect(X, Y+H-1, W, 1, Color); + Video_FillRect(X, Y, 1, H, Color); + Video_FillRect(X+W-1, Y, 1, H, Color); +} + +void Video_DrawText(short X, short Y, short W, short H, void *Font, int Point, uint32_t Color, char *Text) +{ + // TODO! +} diff --git a/Usermode/Applications/axwin2_src/WM/wm.c b/Usermode/Applications/axwin2_src/WM/wm.c index 7763d3bf..b91c756f 100644 --- a/Usermode/Applications/axwin2_src/WM/wm.c +++ b/Usermode/Applications/axwin2_src/WM/wm.c @@ -9,26 +9,45 @@ #include #include "wm.h" -tElement gWM_RootElement; +// === IMPORTS === +extern void Decorator_RenderWidget(tElement *Element); // === PROTOTYPES === tElement *WM_CreateElement(tElement *Parent, int Type, int Flags); void WM_SetFlags(tElement *Element, int Flags); void WM_SetSize(tElement *Element, int Size); void WM_SetText(tElement *Element, char *Text); +void WM_UpdateDimensions(tElement *Element, int Pass); +void WM_UpdatePosition(tElement *Element); +void WM_RenderWidget(tElement *Element); +void WM_Update(void); + +// === GLOBALS === +tElement gWM_RootElement; +struct { + void (*Init)(tElement *This); + void (*UpdateFlags)(tElement *This); + void (*UpdateSize)(tElement *This); + void (*UpdateText)(tElement *This); +} gaWM_WidgetTypes[MAX_ELETYPES] = { + {NULL, NULL, NULL, NULL}, // NULL + {NULL, NULL, NULL, NULL} // Box +}; // === CODE === +// --- Widget Creation and Control --- tElement *WM_CreateElement(tElement *Parent, int Type, int Flags) { tElement *ret; - if(Type < 0 || Type >= NUM_ELETYPES) return NULL; + if(Type < 0 || Type > NUM_ELETYPES) return NULL; ret = calloc(sizeof(tElement), 1); if(!ret) return NULL; // Prepare ret->Type = Type; + if(Parent == NULL) Parent = &gWM_RootElement; ret->Parent = Parent; // Append to parent's list @@ -36,6 +55,11 @@ tElement *WM_CreateElement(tElement *Parent, int Type, int Flags) Parent->LastChild = ret; if(!Parent->FirstChild) Parent->FirstChild = ret; + ret->PaddingL = 2; + ret->PaddingR = 2; + ret->PaddingT = 2; + ret->PaddingB = 2; + return ret; } @@ -63,5 +87,402 @@ void WM_SetText(tElement *Element, char *Text) if(!Element) return ; if(Element->Text) free(Element->Text); Element->Text = strdup(Text); + + switch(Element->Type) + { + case ELETYPE_IMAGE: + if(Element->Data) free(Element->Data); + Element->Data = LoadImage( Element->Text ); + if(!Element->Data) { + Element->Flags &= ~ELEFLAG_FIXEDSIZE; + return ; + } + + Element->Flags |= ELEFLAG_FIXEDSIZE; + Element->CachedW = ((tImage*)Element->Data)->Width; + Element->CachedH = ((tImage*)Element->Data)->Height; + + if(Element->Parent && Element->Parent->Flags & ELEFLAG_VERTICAL) + Element->Size = Element->CachedH; + else + Element->Size = Element->CachedW; + break; + } + return ; } + +// --- Pre-Rendering --- +#if 0 +void WM_UpdateDimensions(tElement *Element, int Pass) +{ + // Pass zero intialises + if( Pass == 0 ) + { + // If not a fixed size element, initialise the sizes + if( !(Element->Flags & ELEFLAG_FIXEDSIZE) ) + { + Element->CachedH = 0; + Element->CachedW = 0; + if( Element->Size ) + { + if( Element->Parent->Flags & ELEFLAG_VERTICAL ) + Element->CachedH = Element->Size; + else + Element->CachedW = Element->Size; + } + } + } + + int fixedSize = 0, maxCross = 0; + int nFixed = 0, nChildren = 0; + for( child = Element->FirstChild; child; child = child->NextSibling ) + { + WM_UpdateDimensions( child, 0 ); + + if( Element->Flags & ELEFLAG_VERTICAL ) + { + if( child->CachedH ) { + fixedSize += child->CachedH; + nFixed ++; + } + if( maxCross < child->CachedW ) + maxCross = child->CachedW; + } + else + { + if( child->CachedW ) { + fixedSize += child->CachedW; + nFixed ++; + } + if( maxCross < child->CachedH ) + maxCross = child->CachedH; + } + nChildren ++; + } + + + // If we don't have our dimensions, get the child dimensions + if( Element->CachedW == 0 || Element->CachedH == 0 ) + { + if( Element->Flags & ELEFLAG_VERTICAL ) + { + if( Element->CachedW == 0 && maxCross ) + Element->CachedW = Element->PaddingL + + Element->PaddingR + maxCross; + + if( Element->CachedH == 0 && nFixed == nChildren ) + Element->CachedH = Element->PaddingT + + Element->PaddingB + fixedSize + + nChildren * Element->GapSize; + } + else + { + if( maxCross ) + Element->CachedH = Element->PaddingT + + Element->PaddingB + maxCross; + + if( Element->CachedW == 0 && nFixed == nChildren ) + Element->CachedW = Element->PaddingL + + Element->PaddingR + fixedSize + + nChildren * Element->GapSize; + } + } + + // Now, if we have the "length" of the widget, we can size the children + if( (Element->Flags & ELEFLAG_VERTICAL && Element->CachedH > 0) + || (!(Element->Flags & ELEFLAG_VERTICAL) && Element->CachedW > 0) ) + { + int dynSize; + + // Calculate the size of dynamically sized elements + if( Element->Flags & ELEFLAG_VERTICAL ) + dynSize = Element->CachedH - Element->PaddingT + - Element->PaddingB - fixedSize; + else + dynSize = Element->CachedW - Element->PaddingL + - Element->PaddingR - fixedSize; + dynSize /= nChildren - nFixed; + + // Itterate children again + for( child = Element->FirstChild; child; child = child->NextSibling ) + { + int tmp; + + // Get the size of them + if(child->Size) + tmp = child->Size; + else if(dynSize < Element->MinSize) + tmp = child->MinSize; + else + tmp = dynSize; + + if( Element->Flags & ELEFLAG_VERTICAL ) + child->CachedH = tmp; + else + child->CachedW = tmp; + + WM_UpdateDimensions(child, 1); + } + } +} + +#endif + +/** + * \brief Updates the dimensions of an element + * + * The dimensions of an element are calculated from the parent's + * cross dimension (the side at right angles to the alignment) sans some + * padding. + */ +void WM_UpdateDimensions(tElement *Element, int Pass) +{ + tElement *child; + int fixedChildSize = 0; + int dynamicSize; + int nChildren = 0; + int nFixed = 0; + + _SysDebug("WM_UpdateDimensions: (Element=%p{Flags:0x%x}, Pass=%i)", + Element, Element->Flags, + Pass); + + if( Pass == 0 ) + { + if( Element->Flags & ELEFLAG_NORENDER ) return ; + + if( !(Element->Flags & ELEFLAG_ABSOLUTEPOS) ) { + Element->CachedX = 0; + Element->CachedY = 0; + } + if( !(Element->Flags & ELEFLAG_FIXEDSIZE) ) { + Element->CachedW = 0; + Element->CachedH = 0; + } + } + + if( !(Element->Flags & ELEFLAG_FIXEDSIZE) ) { + // If the element is sized, fix its dimension(s) + if(Element->Size) + { + if(Element->Flags & ELEFLAG_NOEXPAND) + { + Element->CachedW = Element->Size; + Element->CachedH = Element->Size; + } + else { + if( Element->Parent->Flags & ELEFLAG_VERTICAL ) { + Element->CachedH = Element->Size; + Element->CachedW = Element->Parent->CachedW; + if(Element->CachedW) + Element->CachedW -= (Element->Parent->PaddingL + Element->Parent->PaddingR); + } + else { + Element->CachedW = Element->Size; + Element->CachedH = Element->Parent->CachedH; + if(Element->CachedH) + Element->CachedH -= (Element->Parent->PaddingT + Element->Parent->PaddingB); + } + } + } + else { + // Ok, so now we need to calculate the size of all child elements + // However, if ELEFLAG_NOEXPAND is not set, we can still set one + // dimension + if( !(Element->Flags & ELEFLAG_NOEXPAND) ) { + if( Element->Parent->Flags & ELEFLAG_VERTICAL ) { + Element->CachedW = Element->Parent->CachedW; + if(Element->CachedW) + Element->CachedW -= (Element->Parent->PaddingL + Element->Parent->PaddingR); + } + else { + Element->CachedH = Element->Parent->CachedH; + if(Element->CachedH) + Element->CachedH -= (Element->Parent->PaddingT + Element->Parent->PaddingB); + } + } + } + } + + // Process Children (first pass) + for( child = Element->FirstChild; child; child = child->NextSibling ) + { + if( child->Flags & ELEFLAG_NORENDER ) continue; + WM_UpdateDimensions(child, 0); + + // Children that don't inherit positions are ignored + if( child->Flags & ELEFLAG_ABSOLUTEPOS ) continue; + + fixedChildSize += child->Size; + if(child->Size > 0) + nFixed ++; + nChildren ++; + + // If we are wrapping the children, get the largest cross size + if( !(Element->Flags & ELEFLAG_FIXEDSIZE) + && Element->Flags & ELEFLAG_NOEXPAND + && Element->Size == 0 ) + { + if( Element->Flags & ELEFLAG_VERTICAL ) { + if( Element->CachedW < child->CachedW ) + Element->CachedW = child->CachedW; + } + else { + if( Element->CachedH < child->CachedH ) + Element->CachedH = child->CachedH; + } + } + } + + // Let's avoid a #DIV0 shall we? + if( nChildren > 0 ) + { + // Calculate the size of dynamically sized children + if( Element->Flags & ELEFLAG_VERTICAL ) { + if( Element->CachedH == 0 ) { + if( nFixed == nChildren ) + Element->CachedH = fixedChildSize; + else + return ; + } + dynamicSize = (Element->CachedH - (Element->PaddingT + Element->PaddingB) - fixedChildSize) / nChildren; + } + else { + if( Element->CachedW == 0 ) { + if( nFixed == nChildren ) + Element->CachedW = fixedChildSize; + else + return ; + } + dynamicSize = (Element->CachedW - (Element->PaddingL + Element->PaddingR) - fixedChildSize) / nChildren; + } + + // Process Children (second pass) + for( child = Element->FirstChild; child; child = child->NextSibling ) + { + if( child->Flags & ELEFLAG_NORENDER ) continue; + // Children that don't inherit positions are ignored + if( child->Flags & ELEFLAG_ABSOLUTEPOS ) continue; + + if(!child->Size) { + if(child->Flags & ELEFLAG_VERTICAL) + child->CachedH = dynamicSize; + else + child->CachedW = dynamicSize; + } + + WM_UpdateDimensions(child, 1); + + // If we are wrapping the children, get the largest cross size + if( Element->Flags & ELEFLAG_NOEXPAND ) { + if( Element->Flags & ELEFLAG_VERTICAL ) { + if( Element->CachedW < child->CachedW ) + Element->CachedW = child->CachedW; + } + else { + if( Element->CachedH < child->CachedH ) + Element->CachedH = child->CachedH; + } + } + } + } + + // Add the padding + //Element->CachedW += Element->PaddingL + Element->PaddingR; + //Element->CachedH += Element->PaddingT + Element->PaddingB; + + _SysDebug("Pass %i, Element %p %ix%i", + Pass, Element, Element->CachedW, Element->CachedH + ); + + // We should be done + // Next function will do the coordinates +} + + +/** + * \brief Updates the position of an element + * + * The parent element sets the positions of its children + */ +void WM_UpdatePosition(tElement *Element) +{ + tElement *child; + int x, y; + + if( Element->Flags & ELEFLAG_NORENDER ) return ; + + _SysDebug("Element=%p{PaddingL:%i, PaddingT:%i}", + Element, Element->PaddingL, Element->PaddingT); + + // Initialise + x = Element->CachedX + Element->PaddingL; + y = Element->CachedY + Element->PaddingT; + + // Update each child + for(child = Element->FirstChild; child; child = child->NextSibling) + { + child->CachedX = x; + child->CachedY = y; + + // Set Alignment + if( Element->Flags & ELEFLAG_ALIGN_CENTER ) { + if(Element->Flags & ELEFLAG_VERTICAL ) + child->CachedX += Element->CachedW/2 - child->CachedW/2; + else + child->CachedY += Element->CachedH/2 - child->CachedH/2; + } + else if( Element->Flags & ELEFLAG_ALIGN_END ) { + if(Element->Flags & ELEFLAG_VERTICAL ) + child->CachedX += Element->CachedW - child->CachedW; + else + child->CachedY += Element->CachedH - child->CachedH; + } + + // Update child's children positions + WM_UpdatePosition(child); + + // Increment + if(Element->Flags & ELEFLAG_VERTICAL ) { + y += child->CachedH + Element->GapSize; + } + else { + x += child->CachedW + Element->GapSize; + } + } + + _SysDebug("Element %p (%i,%i)", + Element, Element->CachedX, Element->CachedY + ); +} + +// --- Render --- +void WM_RenderWidget(tElement *Element) +{ + tElement *child; + + if( Element->Flags & ELEFLAG_NORENDER ) return ; + if( Element->Flags & ELEFLAG_INVISIBLE ) return ; + + Decorator_RenderWidget(Element); + + for(child = Element->FirstChild; child; child = child->NextSibling) + { + WM_RenderWidget(child); + } +} + +void WM_Update(void) +{ + gWM_RootElement.CachedX = 0; gWM_RootElement.CachedY = 0; + gWM_RootElement.CachedW = giScreenWidth; + gWM_RootElement.CachedH = giScreenHeight; + gWM_RootElement.Flags |= ELEFLAG_NOEXPAND|ELEFLAG_ABSOLUTEPOS|ELEFLAG_FIXEDSIZE; + + WM_UpdateDimensions( &gWM_RootElement, 0 ); + WM_UpdatePosition( &gWM_RootElement ); + WM_RenderWidget( &gWM_RootElement ); + + Video_Update(); +} diff --git a/Usermode/Applications/axwin2_src/WM/wm.h b/Usermode/Applications/axwin2_src/WM/wm.h index 38dc1ac5..82c022af 100644 --- a/Usermode/Applications/axwin2_src/WM/wm.h +++ b/Usermode/Applications/axwin2_src/WM/wm.h @@ -11,11 +11,9 @@ typedef struct sElement struct sElement *LastChild; struct sElement *NextSibling; - - short CachedX; - short CachedY; - short CachedW; - short CachedH; + short PaddingL, PaddingR; + short PaddingT, PaddingB; + short GapSize; short Size; // Size attribute @@ -23,6 +21,10 @@ typedef struct sElement void *Data; uint32_t Flags; + + // -- Render Cache + short CachedX, CachedY; + short CachedW, CachedH; } tElement; typedef struct sTab @@ -51,10 +53,57 @@ typedef struct sApplication // === CONSTANTS === enum eElementFlags { - ELEFLAG_VISIBLE = 0x001, ELEFLAG_INVISIBLE = 0x000, - ELEFLAG_VERTICAL = 0x002, ELEFLAG_HORIZONTAL = 0x000, - ELEFLAG_WRAP = 0x004, ELEFLAG_NOWRAP = 0x000, + /** + * \brief Rendered + * + * If set, the element will be ignored in calculating sizes and + * rendering. + */ + ELEFLAG_NORENDER = 0x001, + /** + * \brief Element visibility + * + * If set, the element is not drawn. + */ + ELEFLAG_INVISIBLE = 0x002, + + /** + * \brief Position an element absulutely + */ + ELEFLAG_ABSOLUTEPOS = 0x004, + + /** + * \brief Fixed size element + */ + ELEFLAG_FIXEDSIZE = 0x008, + + /** + * \brief Element "orientation" + */ + ELEFLAG_VERTICAL = 0x010,// ELEFLAG_HORIZONTAL = 0x000, + /** + * \brief Action for text that overflows + */ + ELEFLAG_WRAP = 0x020,// ELEFLAG_NOWRAP = 0x000, + /** + * \brief Cross size action + * + * If this flag is set, the element will only be as large (across + * its parent) as is needed to encase the contents of the element. + * Otherwise, the element will expand to fill all avaliable space. + */ + ELEFLAG_NOEXPAND = 0x040, // ELEFLAG_EXPAND = 0x000 + + /** + * \brief Center alignment + */ + ELEFLAG_ALIGN_CENTER= 0x080, + /** + * \brief Right/Bottom alignment + */ + ELEFLAG_ALIGN_END = 0x100 }; + /** */ enum eElementTypes @@ -67,11 +116,11 @@ enum eElementTypes ELETYPE_BUTTON, //!< Push Button ELETYPE_TEXT, //!< Text + ELETYPE_IMAGE, //!< Image ELETYPE_SPACER, //!< Visual Spacer - ELETYPE_GAP, //!< Alignment Gap - NUM_ELETYPES + MAX_ELETYPES = 0x100 }; // === FUNCTIONS === diff --git a/Usermode/Libraries/libc.so_src/fileIO.c b/Usermode/Libraries/libc.so_src/fileIO.c index 5fdac4cc..4a6a779d 100644 --- a/Usermode/Libraries/libc.so_src/fileIO.c +++ b/Usermode/Libraries/libc.so_src/fileIO.c @@ -150,20 +150,28 @@ EXPORT int vfprintf(FILE *fp, const char *format, va_list args) { va_list tmpList = args; int size; - char *buf; + char sbuf[1024]; + char *buf = sbuf; if(!fp || !format) return -1; - size = vsprintf(NULL, (char*)format, tmpList); + size = vsnprintf(sbuf, 1024, (char*)format, tmpList); - buf = (char*)malloc(size+1); - buf[size] = '\0'; + if( size >= 1024 ) + { + buf = (char*)malloc(size+1); + if(!buf) { + write(_stdout, 31, "vfprintf ERROR: malloc() failed"); + return 0; + } + buf[size] = '\0'; - // Print - vsprintf(buf, (char*)format, args); + // Print + vsnprintf(buf, size+1, (char*)format, args); + } // Write to stream - write(fp->FD, size+1, buf); + write(fp->FD, size, buf); // Free buffer free(buf); @@ -271,15 +279,20 @@ EXPORT int puts(const char *str) return len; } +EXPORT int vsprintf(char * __s, const char *__format, va_list __args) +{ + return vsnprintf(__s, 0x7FFFFFFF, __format, __args); +} + //sprintfv /** - \fn EXPORT void vsprintf(char *buf, const char *format, va_list args) + \fn EXPORT void vsnprintf(char *buf, const char *format, va_list args) \brief Prints a formatted string to a buffer \param buf Pointer - Destination Buffer \param format String - Format String \param args VarArgs List - Arguments */ -EXPORT int vsprintf(char *buf, const char *format, va_list args) +EXPORT int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list args) { char tmp[33]; int c, minSize; @@ -295,7 +308,7 @@ EXPORT int vsprintf(char *buf, const char *format, va_list args) { // Non-control character if (c != '%') { - if(buf) buf[pos] = c; + if(buf && pos < __maxlen) buf[pos] = c; pos ++; continue; } @@ -303,7 +316,7 @@ EXPORT int vsprintf(char *buf, const char *format, va_list args) // Control Character c = *format++; if(c == '%') { // Literal % - if(buf) buf[pos] = '%'; + if(buf && pos < __maxlen) buf[pos] = '%'; pos ++; continue; } @@ -358,7 +371,7 @@ EXPORT int vsprintf(char *buf, const char *format, va_list args) // Pointer case 'p': - if(buf) { + if(buf && pos+2 < __maxlen) { buf[pos] = '*'; buf[pos+1] = '0'; buf[pos+2] = 'x'; @@ -394,7 +407,8 @@ EXPORT int vsprintf(char *buf, const char *format, va_list args) if(!p) p = "(null)"; if(buf) { while(*p) { - buf[pos++] = *p++; + if(pos < __maxlen) buf[pos] = *p; + pos ++; p ++; } } else { @@ -407,12 +421,12 @@ EXPORT int vsprintf(char *buf, const char *format, va_list args) // Unknown, just treat it as a character default: arg = va_arg(args, uint32_t); - if(buf) buf[pos] = arg; + if(buf && pos < __maxlen) buf[pos] = arg; pos ++; break; } } - if(buf) buf[pos] = '\0'; + if(buf && pos < __maxlen) buf[pos] = '\0'; return pos; } @@ -463,22 +477,29 @@ EXPORT int printf(const char *format, ...) { #if 1 int size; - char *buf; + char sbuf[1024]; + char *buf = sbuf; va_list args; // Get final size va_start(args, format); - size = vsprintf(NULL, (char*)format, args); + size = vsnprintf(sbuf, 1024, (char*)format, args); va_end(args); - // Allocate buffer - buf = (char*)malloc(size+1); - buf[size] = '\0'; + if( size >= 1024 ) { + // Allocate buffer + buf = (char*)malloc(size+1); + if(buf) { + write(_stdout, 29, "PRINTF ERROR: malloc() failed"); + return 0; + } + buf[size] = '\0'; - // Fill Buffer - va_start(args, format); - vsprintf(buf, (char*)format, args); - va_end(args); + // Fill Buffer + va_start(args, format); + vsnprintf(buf, size+1, (char*)format, args); + va_end(args); + } // Send to stdout write(_stdout, size+1, buf); diff --git a/Usermode/include/axwin/messages.h b/Usermode/include/axwin/messages.h index 8a14223f..4d53ab5d 100644 --- a/Usermode/include/axwin/messages.h +++ b/Usermode/include/axwin/messages.h @@ -50,6 +50,7 @@ enum eAxWin_Messages MSG_SREQ_SETFONT, MSG_SREQ_PUTTEXT, // Server Responses + MSG_SRSP_VERSION, MSG_SRSP_RETURN, // {int RequestID, void[] Return Value} - Returns a value from a server request NUM_MSG @@ -79,7 +80,7 @@ struct sAxWin_SReq_NewWindow * \brief Server Response - Pong * \see eAxWin_Messages.MSG_SRSP_PONG */ -struct sAxWin_SRsp_Pong +struct sAxWin_SRsp_Version { uint8_t Major; uint8_t Minor; diff --git a/Usermode/include/stdio.h b/Usermode/include/stdio.h index 985f058c..1223fe8c 100644 --- a/Usermode/include/stdio.h +++ b/Usermode/include/stdio.h @@ -16,6 +16,7 @@ typedef struct sFILE FILE; // --- Standard IO --- extern int printf(const char *format, ...); +extern int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list args); extern int vsprintf(char *buf, const char *format, va_list args); extern int sprintf(char *buf, const char *format, ...); diff --git a/Usermode/include/string.h b/Usermode/include/string.h deleted file mode 100644 index 1e721974..00000000 --- a/Usermode/include/string.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * AcessOS LibC - * string.h - */ -#ifndef __STRING_H -#define __STRING_H - -#include - -// Strings -extern int strlen(const char *string); -extern int strcmp(const char *str1, const char *str2); -extern int strncmp(const char *str1, const char *str2, size_t len); -extern char *strcpy(char *dst, const char *src); -extern char *strncpy(char *dst, const char *src, size_t num); -extern char *strcat(char *dst, const char *src); -extern char *strdup(const char *src); -extern char *strchr(char *str, int character); -extern char *strrchr(char *str, int character); -extern char *strstr(char *str1, const char *str2); - -// Memory -extern void *memset(void *dest, int val, size_t count); -extern void *memcpy(void *dest, const void *src, size_t count); -extern void *memmove(void *dest, const void *src, size_t count); -extern int memcmp(const void *mem1, const void *mem2, size_t count); -extern void *memchr(void *ptr, int value, size_t num); - -#endif diff --git a/Usermode/include/sys/sys.h b/Usermode/include/sys/sys.h index 119bb6ab..d9e7ada3 100644 --- a/Usermode/include/sys/sys.h +++ b/Usermode/include/sys/sys.h @@ -40,5 +40,3 @@ extern int pollmsg(int *src, unsigned int *Data); extern int getmsg(int *src, unsigned int *Data); #endif - -#endif -- 2.20.1