-BUILD_NUM = 2072
+BUILD_NUM = 2138
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);
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)
// 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 );
+}
// === 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))
#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
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);
// === 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
};
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;
*/
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 );
}
}
}
{
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';
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 );
}
/**
switch(Id)
{
+ // --- Core Defined
case DRV_IOCTL_TYPE:
LEAVE('i', DRV_TYPE_TERMINAL);
return DRV_TYPE_TERMINAL;
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);
// 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;
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;
// 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 );
}
/**
}
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 );
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;
}
}
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'))
{
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;
}
}
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;
}
/**
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;
}
}
// 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
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,
*/
// === FUNCTIONS ===
-// --- Core ---
-extern void System_Init(char *ArgString);
-
// --- IRQs ---
extern int IRQ_AddHandler(int Num, void (*Callback)(int));
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);
* Writes to the driver's file while in component colour modes\r
* must correspond to a change of the contents of the screen. The framebuffer\r
* must start at offset 0 in the file.\r
- * In pallete colour modes the LFB is preceded by a 1024 byte pallete (allowing\r
- * room for 256 entries of 32-bits each)\r
* Reading from the screen must either return zero, or read from the\r
* framebuffer.\r
* \r
*/\r
VIDEO_2DOP_BLIT,\r
\r
+\r
+ /**\r
+ * \brief Copy a region from video memory to the framebuffer\r
+ */\r
+ VIDEO_2DOP_BLITBUF,\r
+\r
+ /**\r
+ * \brief Copy and scale a region from video memory to the framebuffer\r
+ */\r
+ VIDEO_2DOP_BLITSCALEBUF,\r
+\r
NUM_VIDEO_2DOPS\r
};\r
\r
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);
EXPORT(strcmp);
EXPORT(strncmp);
EXPORT(strdup);
-EXPORT(DivUp);
+EXPORT(str_split);
EXPORT(strpos8);
+EXPORT(DivUp);
EXPORT(ReadUTF8);
EXPORT(WriteUTF8);
EXPORT(timestamp);
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')
c = *__format++;
}
}
+ else
+ minSize = 1;
// - Default, Long or LongLong?
isLongLong = 0;
case 'C': // Non-Null Terminated Character Array
p = (char*)(Uint)val;
if(!p) goto printString;
+ //while(minSize--) PUTCH(*p++);
while(minSize--) PUTCH(*p++);
break;
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
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
*/
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,
#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);
tModule *gLoadedModules = NULL;
tModuleLoader *gModule_Loaders = NULL;
tModule *gLoadingModules = NULL;
+char **gasBuiltinModuleArgs;
// === CODE ===
/**
* \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);
}
// 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
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)
{
/**
* \brief Initialises builtin modules
*/
-int Modules_LoadBuiltins()
+void Modules_LoadBuiltins()
{
int i;
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);
}
/**
}
#if 1
- if( Module_int_Initialise( info ) )
+ if( Module_int_Initialise( info, ArgString ) )
{
Binary_Unload(base);
return 0;
} 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}}
};
// === 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...");
*/
void System_ParseCommandLine(char *ArgString)
{
- char *argv[32];
- int argc;
int i;
char *str;
// 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
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;
+ }
}
}
}
}
+/**
+ * \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)
*/
/**
* \fn void System_ExecuteScript()
+ * \brief Reads and parses the boot configuration script
*/
-void System_ExecuteScript()
+void System_ExecuteScript(void)
{
int fp;
int fLen = 0;
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';
}
free( file->Lines[i].Parts );
}
+
+ // Free data
free( file );
free( fData );
}
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)
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);
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);
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 ] }");
}
#
#
-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)
$(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)
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
// === 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
--- /dev/null
+/*
+ * 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;
+ }
+}
// === 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 <hr/> 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 <hr/> 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");
}
// === IMPORTS ===
extern void ParseCommandline(int argc, char *argv[]);
extern void Video_Setup(void);
+extern void WM_Update(void);
extern void Messages_PollIPC(void);
// === GLOBALS ===
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(;;)
{
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);
{
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!
+}
#include <strings.h>
#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
Parent->LastChild = ret;
if(!Parent->FirstChild) Parent->FirstChild = ret;
+ ret->PaddingL = 2;
+ ret->PaddingR = 2;
+ ret->PaddingT = 2;
+ ret->PaddingB = 2;
+
return ret;
}
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();
+}
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
void *Data;
uint32_t Flags;
+
+ // -- Render Cache
+ short CachedX, CachedY;
+ short CachedW, CachedH;
} tElement;
typedef struct sTab
// === 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
ELETYPE_BUTTON, //!< Push Button
ELETYPE_TEXT, //!< Text
+ ELETYPE_IMAGE, //!< Image
ELETYPE_SPACER, //!< Visual Spacer
- ELETYPE_GAP, //!< Alignment Gap
- NUM_ELETYPES
+ MAX_ELETYPES = 0x100
};
// === FUNCTIONS ===
{\r
va_list tmpList = args;\r
int size;\r
- char *buf;\r
+ char sbuf[1024];\r
+ char *buf = sbuf;\r
\r
if(!fp || !format) return -1;\r
\r
- size = vsprintf(NULL, (char*)format, tmpList);\r
+ size = vsnprintf(sbuf, 1024, (char*)format, tmpList);\r
\r
- buf = (char*)malloc(size+1);\r
- buf[size] = '\0';\r
+ if( size >= 1024 )\r
+ {\r
+ buf = (char*)malloc(size+1);\r
+ if(!buf) {\r
+ write(_stdout, 31, "vfprintf ERROR: malloc() failed");\r
+ return 0;\r
+ }\r
+ buf[size] = '\0';\r
\r
- // Print\r
- vsprintf(buf, (char*)format, args);\r
+ // Print\r
+ vsnprintf(buf, size+1, (char*)format, args);\r
+ }\r
\r
// Write to stream\r
- write(fp->FD, size+1, buf);\r
+ write(fp->FD, size, buf);\r
\r
// Free buffer\r
free(buf);\r
return len;\r
}\r
\r
+EXPORT int vsprintf(char * __s, const char *__format, va_list __args)\r
+{\r
+ return vsnprintf(__s, 0x7FFFFFFF, __format, __args);\r
+}\r
+\r
//sprintfv\r
/**\r
- \fn EXPORT void vsprintf(char *buf, const char *format, va_list args)\r
+ \fn EXPORT void vsnprintf(char *buf, const char *format, va_list args)\r
\brief Prints a formatted string to a buffer\r
\param buf Pointer - Destination Buffer\r
\param format String - Format String\r
\param args VarArgs List - Arguments\r
*/\r
-EXPORT int vsprintf(char *buf, const char *format, va_list args)\r
+EXPORT int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list args)\r
{\r
char tmp[33];\r
int c, minSize;\r
{\r
// Non-control character\r
if (c != '%') {\r
- if(buf) buf[pos] = c;\r
+ if(buf && pos < __maxlen) buf[pos] = c;\r
pos ++;\r
continue;\r
}\r
// Control Character\r
c = *format++;\r
if(c == '%') { // Literal %\r
- if(buf) buf[pos] = '%';\r
+ if(buf && pos < __maxlen) buf[pos] = '%';\r
pos ++;\r
continue;\r
}\r
\r
// Pointer\r
case 'p':\r
- if(buf) {\r
+ if(buf && pos+2 < __maxlen) {\r
buf[pos] = '*';\r
buf[pos+1] = '0';\r
buf[pos+2] = 'x';\r
if(!p) p = "(null)";\r
if(buf) {\r
while(*p) {\r
- buf[pos++] = *p++;\r
+ if(pos < __maxlen) buf[pos] = *p;\r
+ pos ++; p ++;\r
}\r
}\r
else {\r
// Unknown, just treat it as a character\r
default:\r
arg = va_arg(args, uint32_t);\r
- if(buf) buf[pos] = arg;\r
+ if(buf && pos < __maxlen) buf[pos] = arg;\r
pos ++;\r
break;\r
}\r
}\r
- if(buf) buf[pos] = '\0';\r
+ if(buf && pos < __maxlen) buf[pos] = '\0';\r
\r
return pos;\r
}\r
{\r
#if 1\r
int size;\r
- char *buf;\r
+ char sbuf[1024];\r
+ char *buf = sbuf;\r
va_list args;\r
\r
// Get final size\r
va_start(args, format);\r
- size = vsprintf(NULL, (char*)format, args);\r
+ size = vsnprintf(sbuf, 1024, (char*)format, args);\r
va_end(args);\r
\r
- // Allocate buffer\r
- buf = (char*)malloc(size+1);\r
- buf[size] = '\0';\r
+ if( size >= 1024 ) {\r
+ // Allocate buffer\r
+ buf = (char*)malloc(size+1);\r
+ if(buf) {\r
+ write(_stdout, 29, "PRINTF ERROR: malloc() failed");\r
+ return 0;\r
+ }\r
+ buf[size] = '\0';\r
\r
- // Fill Buffer\r
- va_start(args, format);\r
- vsprintf(buf, (char*)format, args);\r
- va_end(args);\r
+ // Fill Buffer\r
+ va_start(args, format);\r
+ vsnprintf(buf, size+1, (char*)format, args);\r
+ va_end(args);\r
+ }\r
\r
// Send to stdout\r
write(_stdout, size+1, buf);\r
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
* \brief Server Response - Pong
* \see eAxWin_Messages.MSG_SRSP_PONG
*/
-struct sAxWin_SRsp_Pong
+struct sAxWin_SRsp_Version
{
uint8_t Major;
uint8_t Minor;
\r
// --- Standard IO ---\r
extern int printf(const char *format, ...);\r
+extern int vsnprintf(char *buf, size_t __maxlen, const char *format, va_list args);\r
extern int vsprintf(char *buf, const char *format, va_list args);\r
extern int sprintf(char *buf, const char *format, ...);\r
\r
+++ /dev/null
-/*
- * AcessOS LibC
- * string.h
- */
-#ifndef __STRING_H
-#define __STRING_H
-
-#include <stddef.h>
-
-// 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
extern int getmsg(int *src, unsigned int *Data);\r
\r
#endif\r
-\r
-#endif\r