X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Fdrv%2Fvterm.c;h=09f85ff6c658dd0b3f32129923b3efaf41f05994;hb=77ed20ce9d7e25654215980d0f89e63b8dd366f0;hp=45ac6bd0fe9b4258687f70d6bc486b5ca205afa2;hpb=ed9e279c18ed6ac86bd38b090f4faec637c205bf;p=tpg%2Facess2.git diff --git a/Kernel/drv/vterm.c b/Kernel/drv/vterm.c index 45ac6bd0..09f85ff6 100644 --- a/Kernel/drv/vterm.c +++ b/Kernel/drv/vterm.c @@ -6,40 +6,49 @@ #include #include #include +#include +#include // === CONSTANTS === -#define NUM_VTS 4 -#define MAX_INPUT_CHARS 64 -#define VT_SCROLLBACK 4 // 4 Screens of text -#define DEFAULT_OUTPUT "/Devices/VGA" -#define DEFAULT_INPUT "/Devices/PS2Keyboard" +#define VERSION ((0<<8)|(50)) + +#define NUM_VTS 7 +#define MAX_INPUT_CHARS32 64 +#define MAX_INPUT_CHARS8 (MAX_INPUT_CHARS32*4) +#define VT_SCROLLBACK 1 // 2 Screens of text +#define DEFAULT_OUTPUT "VGA" +//#define DEFAULT_OUTPUT "BochsGA" +#define DEFAULT_INPUT "PS2Keyboard" #define DEFAULT_WIDTH 80 #define DEFAULT_HEIGHT 25 -#define DEFAULT_COLOUR (VT_COL_BLACK|(VT_COL_WHITE<<16)) +#define DEFAULT_COLOUR (VT_COL_BLACK|(0xAAA<<16)) #define VT_FLAG_HIDECSR 0x01 +#define VT_FLAG_HASFB 0x10 //!< Set if the VTerm has requested the Framebuffer -enum eVT_Modes { - VT_MODE_TEXT8, // UTF-8 Text Mode (VT100 Emulation) - VT_MODE_TEXT32, // UTF-32 Text Mode (Acess Native) - VT_MODE_8BPP, // 256 Colour Mode - VT_MODE_16BPP, // 16 bit Colour Mode - VT_MODE_24BPP, // 24 bit Colour Mode - VT_MODE_32BPP, // 32 bit Colour Mode - NUM_VT_MODES +enum eVT_InModes { + VT_INMODE_TEXT8, // UTF-8 Text Mode (VT100 Emulation) + VT_INMODE_TEXT32, // UTF-32 Text Mode (Acess Native) + NUM_VT_INMODES }; // === TYPES === typedef struct { - int Mode; - int Flags; - int Width, Height; - int ViewPos, WritePos; - Uint32 CurColour; - char Name[2]; - int InputRead; - int InputWrite; - Uint32 InputBuffer[MAX_INPUT_CHARS]; + int Mode; //!< Current Mode (see ::eTplTerminal_Modes) + int Flags; //!< Flags (see VT_FLAG_*) + short Width; //!< Virtual Width + short Height; //!< Virtual Height + short RealWidth; //!< Real Width + short RealHeight; //!< Real Height + + int ViewPos; //!< View Buffer Offset (Text Only) + int WritePos; //!< Write Buffer Offset (Text Only) + Uint32 CurColour; //!< Current Text Colour + char Name[2]; //!< Name of the terminal + + int InputRead; //!< Input buffer read position + int InputWrite; //!< Input buffer write position + char InputBuffer[MAX_INPUT_CHARS8]; union { tVT_Char *Text; Uint32 *Buffer; @@ -47,43 +56,57 @@ typedef struct { tVFS_Node Node; } tVTerm; +// === IMPORTS === +extern void Debug_SetKTerminal(char *File); + // === PROTOTYPES === int VT_Install(char **Arguments); char *VT_ReadDir(tVFS_Node *Node, int Pos); tVFS_Node *VT_FindDir(tVFS_Node *Node, char *Name); + int VT_Root_IOCtl(tVFS_Node *Node, int Id, void *Data); 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_IOCtl(tVFS_Node *Node, int Id, void *Data); + int VT_Terminal_IOCtl(tVFS_Node *Node, int Id, void *Data); +void VT_SetTerminal(int ID); void VT_KBCallBack(Uint32 Codepoint); void VT_int_PutString(tVTerm *Term, Uint8 *Buffer, Uint Count); int VT_int_ParseEscape(tVTerm *Term, char *Buffer); void VT_int_PutChar(tVTerm *Term, Uint32 Ch); void VT_int_UpdateScreen( tVTerm *Term, int UpdateAll ); +void VT_int_ChangeMode(tVTerm *Term, int NewMode); // === CONSTANTS === const Uint16 caVT100Colours[] = { - VT_COL_BLACK, 0x700, 0x070, 0x770, 0x007, 0x707, 0x077, VT_COL_LTGREY, + VT_COL_BLACK, 0x700, 0x070, 0x770, 0x007, 0x707, 0x077, 0xAAA, VT_COL_GREY, 0xF00, 0x0F0, 0xFF0, 0x00F, 0xF0F, 0x0FF, VT_COL_WHITE }; // === GLOBALS === -MODULE_DEFINE(0, 0x0032, VTerm, VT_Install, NULL, NULL); +MODULE_DEFINE(0, VERSION, VTerm, VT_Install, NULL, DEFAULT_OUTPUT, DEFAULT_INPUT, NULL); tDevFS_Driver gVT_DrvInfo = { NULL, "VTerm", { .Flags = VFS_FFLAG_DIRECTORY, + .Size = NUM_VTS, .Inode = -1, .NumACLs = 0, .ReadDir = VT_ReadDir, - .FindDir = VT_FindDir + .FindDir = VT_FindDir, + .IOCtl = VT_Root_IOCtl } }; +// --- Terminals --- tVTerm gVT_Terminals[NUM_VTS]; + int giVT_CurrentTerminal = 0; +// --- Driver Handles --- char *gsVT_OutputDevice = NULL; char *gsVT_InputDevice = NULL; int giVT_OutputDevHandle = -2; int giVT_InputDevHandle = -2; - int giVT_CurrentTerminal = 0; +// --- Key States --- (Used for VT Switching/Magic Combos) + int gbVT_CtrlDown = 0; + int gbVT_AltDown = 0; + int gbVT_SysrqDown = 0; // === CODE === /** @@ -128,8 +151,8 @@ int VT_Install(char **Arguments) } // Apply Defaults - if(!gsVT_OutputDevice) gsVT_OutputDevice = DEFAULT_OUTPUT; - if(!gsVT_InputDevice) gsVT_InputDevice = DEFAULT_INPUT; + if(!gsVT_OutputDevice) gsVT_OutputDevice = "/Devices/"DEFAULT_OUTPUT; + if(!gsVT_InputDevice) gsVT_InputDevice = "/Devices/"DEFAULT_INPUT; LOG("Using '%s' as output", gsVT_OutputDevice); LOG("Using '%s' as input", gsVT_InputDevice); @@ -137,7 +160,7 @@ int VT_Install(char **Arguments) // Create Nodes for( i = 0; i < NUM_VTS; i++ ) { - gVT_Terminals[i].Mode = VT_MODE_TEXT8; + gVT_Terminals[i].Mode = TERM_MODE_TEXT; gVT_Terminals[i].Flags = 0; gVT_Terminals[i].Width = DEFAULT_WIDTH; gVT_Terminals[i].Height = DEFAULT_HEIGHT; @@ -145,22 +168,25 @@ int VT_Install(char **Arguments) gVT_Terminals[i].WritePos = 0; gVT_Terminals[i].ViewPos = 0; - gVT_Terminals[i].Buffer = malloc( DEFAULT_WIDTH*DEFAULT_HEIGHT*sizeof(tVT_Char) ); - memset( gVT_Terminals[i].Buffer, 0, DEFAULT_WIDTH*DEFAULT_HEIGHT*sizeof(tVT_Char) ); + gVT_Terminals[i].Buffer = calloc( DEFAULT_WIDTH*DEFAULT_HEIGHT*VT_SCROLLBACK, sizeof(tVT_Char) ); gVT_Terminals[i].Name[0] = '0'+i; gVT_Terminals[i].Name[1] = '\0'; gVT_Terminals[i].Node.Inode = i; + gVT_Terminals[i].Node.ImplPtr = &gVT_Terminals[i]; gVT_Terminals[i].Node.NumACLs = 0; // Only root can open virtual terminals gVT_Terminals[i].Node.Read = VT_Read; gVT_Terminals[i].Node.Write = VT_Write; - gVT_Terminals[i].Node.IOCtl = VT_IOCtl; + gVT_Terminals[i].Node.IOCtl = VT_Terminal_IOCtl; } // Add to DevFS DevFS_AddDevice( &gVT_DrvInfo ); + // Set kernel output to VT0 + Debug_SetKTerminal("/Devices/VTerm/0"); + return 0; } @@ -172,6 +198,7 @@ void VT_InitOutput() { giVT_OutputDevHandle = VFS_Open(gsVT_OutputDevice, VFS_OPENFLAG_WRITE); LOG("giVT_OutputDevHandle = %x\n", giVT_OutputDevHandle); + VT_SetTerminal( 0 ); } /** @@ -194,7 +221,7 @@ char *VT_ReadDir(tVFS_Node *Node, int Pos) { if(Pos < 0) return NULL; if(Pos >= NUM_VTS) return NULL; - return gVT_Terminals[Pos].Name; + return strdup( gVT_Terminals[Pos].Name ); } /** @@ -227,6 +254,44 @@ tVFS_Node *VT_FindDir(tVFS_Node *Node, char *Name) return &gVT_Terminals[num].Node; } +/** + * \fn int VT_Root_IOCtl(tVFS_Node *Node, int Id, void *Data) + * \brief Control the VTerm Driver + */ +int VT_Root_IOCtl(tVFS_Node *Node, int Id, void *Data) +{ + int len; + switch(Id) + { + case DRV_IOCTL_TYPE: return DRV_TYPE_MISC; + case DRV_IOCTL_IDENT: memcpy(Data, "VT\0\0", 4); return 0; + case DRV_IOCTL_VERSION: return VERSION; + case DRV_IOCTL_LOOKUP: return 0; + + case 4: // Get Video Driver + if(Data) strcpy(Data, gsVT_OutputDevice); + return strlen(gsVT_OutputDevice); + + case 5: // Set Video Driver + if(!Data) return -EINVAL; + if(Threads_GetUID() != 0) return -EACCES; + + len = strlen(Data); + + free(gsVT_OutputDevice); + + gsVT_OutputDevice = malloc(len+1); + strcpy(gsVT_OutputDevice, Data); + + VFS_Close(giVT_OutputDevHandle); + giVT_OutputDevHandle = -1; + + VT_InitOutput(); + return 1; + } + return 0; +} + /** * \fn Uint64 VT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) * \brief Read from a virtual terminal @@ -239,31 +304,27 @@ Uint64 VT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) // Check current mode switch(term->Mode) { - case VT_MODE_TEXT8: + case TERM_MODE_TEXT: while(pos < Length) { - while(term->InputRead == term->InputWrite) Proc_Yield(); - while(term->InputRead != term->InputWrite) - { - LOG("WriteUTF8(%p, 0x%x)", Buffer+pos, term->InputBuffer[term->InputRead]); - pos += WriteUTF8(Buffer+pos, term->InputBuffer[term->InputRead]); - term->InputRead ++; - term->InputRead %= MAX_INPUT_CHARS; - } + while(term->InputRead == term->InputWrite) Threads_Yield(); + + ((char*)Buffer)[pos] = term->InputBuffer[term->InputRead]; + pos ++; + term->InputRead ++; + term->InputRead %= MAX_INPUT_CHARS8; } break; - case VT_MODE_TEXT32: + case TERM_MODE_FB: + case TERM_MODE_OPENGL: while(pos < Length) { - while(term->InputRead == term->InputWrite) Proc_Yield(); - while(term->InputRead != term->InputWrite) - { - ((Uint32*)Buffer)[pos] = term->InputBuffer[term->InputRead]; - pos ++; - term->InputRead ++; - term->InputRead %= MAX_INPUT_CHARS; - } + while(term->InputRead == term->InputWrite) Threads_Yield(); + ((Uint32*)Buffer)[pos] = ((Uint32*)term->InputBuffer)[term->InputRead]; + pos ++; + term->InputRead ++; + term->InputRead %= MAX_INPUT_CHARS32; } break; } @@ -283,12 +344,9 @@ Uint64 VT_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) // Write switch( term->Mode ) { - case VT_MODE_TEXT8: + case TERM_MODE_TEXT: VT_int_PutString(term, Buffer, Length); break; - case VT_MODE_TEXT32: - //VT_int_PutString32(term, Buffer, Length); - break; } //LEAVE('i', 0); @@ -296,14 +354,89 @@ Uint64 VT_Write(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) } /** - * \fn int VT_IOCtl(tVFS_Node *Node, int Id, void *Data) + * \fn int VT_Terminal_IOCtl(tVFS_Node *Node, int Id, void *Data) * \brief Call an IO Control on a virtual terminal */ -int VT_IOCtl(tVFS_Node *Node, int Id, void *Data) +int VT_Terminal_IOCtl(tVFS_Node *Node, int Id, void *Data) { + int *iData = Data; + tVTerm *term = Node->ImplPtr; + switch(Id) + { + case DRV_IOCTL_TYPE: return DRV_TYPE_TERMINAL; + case DRV_IOCTL_IDENT: memcpy(Data, "VT\0\0", 4); return 0; + case DRV_IOCTL_VERSION: return VERSION; + case DRV_IOCTL_LOOKUP: return 0; + + // Get/Set the mode (and apply any changes) + case TERM_IOCTL_MODETYPE: + if(Data == NULL) return term->Mode; + + if(term->Mode != *iData) { + VT_int_ChangeMode(term, *iData); + } + + // Update the screen dimensions + if(giVT_CurrentTerminal == Node->Inode) + VT_SetTerminal( giVT_CurrentTerminal ); + break; + + // Get/set the terminal width + case TERM_IOCTL_WIDTH: + if(Data == NULL) return term->Width; + term->Width = *iData; + break; + + // Get/set the terminal height + case TERM_IOCTL_HEIGHT: + if(Data == NULL) return term->Height; + term->Height = *iData; + break; + + default: + return -1; + } return 0; } +/** + * \fn void VT_SetTerminal(int ID) + * \brief Set the current terminal + */ +void VT_SetTerminal(int ID) +{ + tVideo_IOCtl_Mode mode = {0}; + int modeNum; + + // Create the video mode + mode.width = gVT_Terminals[ ID ].Width; + mode.height = gVT_Terminals[ ID ].Height; + // - Text Mode + if(gVT_Terminals[ ID ].Mode == TERM_MODE_TEXT) { + mode.bpp = 12; + mode.flags = VIDEO_FLAG_TEXT; + } + // - Framebuffer or 3D + else { + mode.bpp = 32; + mode.flags = 0; + } + + // Set video mode + VFS_IOCtl( giVT_OutputDevHandle, VIDEO_IOCTL_FINDMODE, &mode ); + modeNum = mode.id; + gVT_Terminals[ ID ].RealWidth = mode.width; + gVT_Terminals[ ID ].RealHeight = mode.height; + VFS_IOCtl( giVT_OutputDevHandle, VIDEO_IOCTL_SETMODE, &modeNum ); + + // Update current terminal ID + Log("Changed terminal from %i to %i", giVT_CurrentTerminal, ID); + giVT_CurrentTerminal = ID; + + // Update the screen + VT_int_UpdateScreen( &gVT_Terminals[ ID ], 1 ); +} + /** * \fn void VT_KBCallBack(Uint32 Codepoint) * \brief Called on keyboard interrupt @@ -312,12 +445,116 @@ void VT_KBCallBack(Uint32 Codepoint) { tVTerm *term = &gVT_Terminals[giVT_CurrentTerminal]; - term->InputBuffer[ term->InputWrite ] = Codepoint; - term->InputWrite ++; - term->InputWrite %= MAX_INPUT_CHARS; - if(term->InputRead == term->InputWrite) { - term->InputRead ++; - term->InputRead %= MAX_INPUT_CHARS; + // How the hell did we get a Codepoint of zero? + if(Codepoint == 0) return; + + // Key Up + if( Codepoint & 0x80000000 ) + { + Codepoint &= 0x7FFFFFFF; + switch(Codepoint) + { + case KEY_LALT: + case KEY_RALT: + gbVT_AltDown = 0; + break; + case KEY_LCTRL: + case KEY_RCTRL: + gbVT_CtrlDown = 0; + break; + } + return; + } + + switch(Codepoint) + { + case KEY_LALT: + case KEY_RALT: + gbVT_AltDown = 1; + break; + case KEY_LCTRL: + case KEY_RCTRL: + gbVT_CtrlDown = 1; + break; + + default: + if(!gbVT_AltDown || !gbVT_CtrlDown) + break; + switch(Codepoint) + { + case KEY_F1: VT_SetTerminal(0); return; + case KEY_F2: VT_SetTerminal(1); return; + case KEY_F3: VT_SetTerminal(2); return; + case KEY_F4: VT_SetTerminal(3); return; + case KEY_F5: VT_SetTerminal(4); return; + case KEY_F6: VT_SetTerminal(5); return; + case KEY_F7: VT_SetTerminal(6); return; + case KEY_F8: VT_SetTerminal(7); return; + case KEY_F9: VT_SetTerminal(8); return; + case KEY_F10: VT_SetTerminal(9); return; + case KEY_F11: VT_SetTerminal(10); return; + case KEY_F12: VT_SetTerminal(11); return; + case KEY_PGUP: + break; + case KEY_PGDOWN: + break; + } + } + + // Encode key + if(term->Mode == TERM_MODE_TEXT) + { + Uint8 buf[6] = {0}; + int len; + + // Ignore Modifer Keys + if(Codepoint > KEY_MODIFIERS) return; + + // Get UTF-8/ANSI Encoding + switch(Codepoint) + { + case KEY_LEFT: + buf[0] = '\x1B'; buf[1] = '['; + buf[2] = 'D'; len = 3; + break; + case KEY_RIGHT: + buf[0] = '\x1B'; buf[1] = '['; + buf[2] = 'C'; len = 3; + break; + default: + len = WriteUTF8( buf, Codepoint ); + //Log("Codepoint = 0x%x", Codepoint); + break; + } + + //Log("len = %i, buf = %s", len, buf); + + // Write + if( MAX_INPUT_CHARS8 - term->InputWrite >= len ) + memcpy( &term->InputBuffer[term->InputWrite], buf, len ); + else { + memcpy( &term->InputBuffer[term->InputWrite], buf, MAX_INPUT_CHARS8 - term->InputWrite ); + memcpy( &term->InputBuffer[0], buf, len - (MAX_INPUT_CHARS8 - term->InputWrite) ); + } + // Roll the buffer over + term->InputWrite += len; + term->InputWrite %= MAX_INPUT_CHARS8; + if( (term->InputWrite - term->InputRead + MAX_INPUT_CHARS8)%MAX_INPUT_CHARS8 < len ) { + term->InputRead = term->InputWrite + 1; + term->InputRead %= MAX_INPUT_CHARS8; + } + + } + else + { + // Encode the raw UTF-32 Key + ((Uint32*)term->InputBuffer)[ term->InputWrite ] = Codepoint; + term->InputWrite ++; + term->InputWrite %= MAX_INPUT_CHARS32; + if(term->InputRead == term->InputWrite) { + term->InputRead ++; + term->InputRead %= MAX_INPUT_CHARS32; + } } } @@ -356,6 +593,22 @@ void VT_int_PutString(tVTerm *Term, Uint8 *Buffer, Uint Count) } } +/** + * \fn void VT_int_ClearLine(tVTerm *Term, int Num) + * \brief Clears a line in a virtual terminal + */ +void VT_int_ClearLine(tVTerm *Term, int Num) +{ + int i; + //ENTER("pTerm iNum", Term, Num); + for( i = Term->Width; i--; ) + { + Term->Text[ Num*Term->Width + i ].Ch = 0; + Term->Text[ Num*Term->Width + i ].Colour = Term->CurColour; + } + //LEAVE('-'); +} + /** * \fn int VT_int_ParseEscape(tVTerm *Term, char *Buffer) * \brief Parses a VT100 Escape code @@ -364,6 +617,7 @@ int VT_int_ParseEscape(tVTerm *Term, char *Buffer) { char c; int argc = 0, j = 1; + int tmp; int args[4] = {0,0,0,0}; switch(Buffer[0]) { @@ -377,7 +631,7 @@ int VT_int_ParseEscape(tVTerm *Term, char *Buffer) args[argc] += c-'0'; c = Buffer[++j]; } - argc ++; + if( j != 1 ) argc ++; } while(c == ';'); // Get string (what does this do?) @@ -390,15 +644,44 @@ int VT_int_ParseEscape(tVTerm *Term, char *Buffer) // Get Command if( ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) { - switch(c) { - //Clear By Line + switch(c) + { + // Left + case 'D': + if(argc == 1) tmp = args[0]; + else tmp = 1; + + if( Term->WritePos-(tmp-1) % Term->Width == 0 ) + Term->WritePos -= Term->WritePos % Term->Width; + else + Term->WritePos -= tmp; + break; + + // Right + case 'C': + if(argc == 1) tmp = args[0]; + else tmp = 1; + if( (Term->WritePos + tmp) % Term->Width == 0 ) { + Term->WritePos -= Term->WritePos % Term->Width; + Term->WritePos += Term->Width - 1; + } else + Term->WritePos += tmp; + break; + + // Clear By Line case 'J': // Clear Screen - if(args[0] == 2) { - memset(Term->Text, 0, Term->Width*Term->Height*VT_SCROLLBACK*sizeof(tVT_Char)); + switch(args[0]) + { + case 2: + { + int i = Term->Height * VT_SCROLLBACK; + while( i-- ) VT_int_ClearLine(Term, i); Term->WritePos = 0; Term->ViewPos = 0; VT_int_UpdateScreen(Term, 1); + } + break; } break; // Set Font flags @@ -450,7 +733,7 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch) switch(Ch) { - case 0: return; // Ignore NULL byte + case '\0': return; // Ignore NULL byte case '\n': Term->WritePos += Term->Width; case '\r': @@ -459,7 +742,7 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch) case '\t': do { - Term->Text[ Term->WritePos ].Ch = '\t'; + Term->Text[ Term->WritePos ].Ch = '\0'; Term->Text[ Term->WritePos ].Colour = Term->CurColour; Term->WritePos ++; } while(Term->WritePos & 7); @@ -471,7 +754,7 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch) Term->WritePos --; // Singe Character - if(Term->Text[ Term->WritePos ].Ch != '\t') { + if(Term->Text[ Term->WritePos ].Ch != '\0') { Term->Text[ Term->WritePos ].Ch = 0; Term->Text[ Term->WritePos ].Colour = Term->CurColour; break; @@ -482,7 +765,9 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch) Term->Text[ Term->WritePos ].Ch = 0; Term->Text[ Term->WritePos ].Colour = Term->CurColour; Term->WritePos --; - } while(Term->WritePos && i-- && Term->Text[ Term->WritePos ].Ch == '\t'); + } while(Term->WritePos && i-- && Term->Text[ Term->WritePos ].Ch == '\0'); + if(Term->Text[ Term->WritePos ].Ch != '\0') + Term->WritePos ++; break; default: @@ -508,7 +793,11 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch) base = Term->Width*(Term->Height*VT_SCROLLBACK-1); // Scroll Back - memcpy( Term->Text, &Term->Text[Term->Width], base*sizeof(tVT_Char) ); + memcpy( + Term->Text, + &Term->Text[Term->Width], + Term->Width*(Term->Height-1)*VT_SCROLLBACK*sizeof(tVT_Char) + ); // Clear last row for( i = 0; i < Term->Width; i ++ ) @@ -536,24 +825,62 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch) */ void VT_int_UpdateScreen( tVTerm *Term, int UpdateAll ) { - if(UpdateAll) { + // Only update if this is the current terminal + if( Term != &gVT_Terminals[giVT_CurrentTerminal] ) return; + + if( Term->Mode == TERM_MODE_TEXT ) + { + if(UpdateAll) { + VFS_WriteAt( + giVT_OutputDevHandle, + 0, + Term->Width*Term->Height*sizeof(tVT_Char), + &Term->Text[Term->ViewPos] + ); + } else { + int pos = Term->WritePos - Term->WritePos % Term->Width; + VFS_WriteAt( + giVT_OutputDevHandle, + (pos - Term->ViewPos)*sizeof(tVT_Char), + Term->Width*sizeof(tVT_Char), + &Term->Text[pos] + ); + } + } + else + { VFS_WriteAt( giVT_OutputDevHandle, 0, - Term->Width*Term->Height*sizeof(tVT_Char), - &Term->Text[Term->ViewPos] - ); - } else { - int pos = Term->WritePos - Term->WritePos % Term->Width; - VFS_WriteAt( - giVT_OutputDevHandle, - (pos - Term->ViewPos)*sizeof(tVT_Char), - Term->Width*sizeof(tVT_Char), - &Term->Text[pos] + Term->Width*Term->Height*sizeof(Uint32), + &Term->Buffer ); } } +/** + * \fn void VT_int_ChangeMode(tVTerm *Term, int NewMode) + * \brief Change the mode of a VTerm + */ +void VT_int_ChangeMode(tVTerm *Term, int NewMode) +{ + switch(NewMode) + { + case TERM_MODE_TEXT: + free(Term->Buffer); + Term->Text = calloc( Term->Width*Term->Height*VT_SCROLLBACK, sizeof(tVT_Char) ); + break; + case TERM_MODE_FB: + free(Term->Text); + Term->Buffer = calloc( Term->Width*Term->Height, sizeof(Uint32) ); + break; + case TERM_MODE_OPENGL: + return; + } + + Term->Mode = NewMode; +} + // --- // Font Render // --- @@ -565,20 +892,54 @@ void VT_int_UpdateScreen( tVTerm *Term, int UpdateAll ) # include "vterm_font_8x16.h" #endif +// === PROTOTYPES === +Uint8 *VT_Font_GetChar(Uint32 Codepoint); -int VT_Font_GetWidth(Uint32 Codepoint) -{ - return FONT_WIDTH; -} -int VT_Font_GetHeight(Uint32 Codepoint) +// === GLOBALS === +int giVT_CharWidth = FONT_WIDTH; +int giVT_CharHeight = FONT_HEIGHT; + +// === CODE === +/** + * \fn void VT_Font_Render(Uint32 Codepoint, void *Buffer, int Pitch, Uint32 BGC, Uint32 FGC) + * \brief Render a font character + */ +void VT_Font_Render(Uint32 Codepoint, void *Buffer, int Pitch, Uint32 BGC, Uint32 FGC) { - return FONT_HEIGHT; + Uint8 *font; + Uint32 *buf = Buffer; + int x, y; + font = VT_Font_GetChar(Codepoint); + + for(y = 0; y < FONT_HEIGHT; y ++) + { + for(x = 0; x < FONT_WIDTH; x ++) + { + if(*font & (1 << (FONT_WIDTH-x))) + buf[x] = FGC; + else + buf[x] = BGC; + } + buf += Pitch; + font ++; + } } -void VT_Font_Render(Uint32 Codepoint, void *Buffer, Uint32 BGC, Uint32 FGC) +/** + * \fn Uint32 VT_Colour12to24(Uint16 Col12) + * \brief Converts a + */ +Uint32 VT_Colour12to24(Uint16 Col12) { -// Uint8 *font; - + Uint32 ret; + int tmp; + tmp = Col12 & 0xF; + ret = (tmp << 0) | (tmp << 4); + tmp = (Col12 & 0xF0) >> 4; + ret |= (tmp << 8) | (tmp << 12); + tmp = (Col12 & 0xF00) >> 8; + ret |= (tmp << 16) | (tmp << 20); + return ret; } /** @@ -613,3 +974,8 @@ Uint8 *VT_Font_GetChar(Uint32 Codepoint) return &VTermFont[index*FONT_HEIGHT]; } + +EXPORTAS(&giVT_CharWidth, giVT_CharWidth); +EXPORTAS(&giVT_CharHeight, giVT_CharHeight); +EXPORT(VT_Font_Render); +EXPORT(VT_Colour12to24);