X-Git-Url: https://git.ucc.asn.au/?a=blobdiff_plain;f=Kernel%2Fdrv%2Fvterm.c;h=ee32016b1bc60b00e29f9d17f19c63e56ef2a786;hb=9c7a9ee011e74509cc4ecbd7182f601403bc3d3e;hp=2b9f6562f17d11b23fcec047cfd7b6f2a31da37f;hpb=abe6c6cf7fac39102e20cd28687b24c67f4952f8;p=tpg%2Facess2.git diff --git a/Kernel/drv/vterm.c b/Kernel/drv/vterm.c index 2b9f6562..ee32016b 100644 --- a/Kernel/drv/vterm.c +++ b/Kernel/drv/vterm.c @@ -5,14 +5,12 @@ #include #include #include -#include -#include -#include +#include +#include +#include #include #include -#define USE_CTRL_ALT 1 - // === CONSTANTS === #define VERSION ((0<<8)|(50)) @@ -21,15 +19,19 @@ #define MAX_INPUT_CHARS8 (MAX_INPUT_CHARS32*4) //#define DEFAULT_OUTPUT "BochsGA" #define DEFAULT_OUTPUT "Vesa" +#define FALLBACK_OUTPUT "x86_VGAText" #define DEFAULT_INPUT "PS2Keyboard" #define DEFAULT_WIDTH 640 #define DEFAULT_HEIGHT 480 #define DEFAULT_SCROLLBACK 2 // 2 Screens of text + current screen +//#define DEFAULT_SCROLLBACK 0 #define DEFAULT_COLOUR (VT_COL_BLACK|(0xAAA<<16)) #define VT_FLAG_HIDECSR 0x01 #define VT_FLAG_ALTBUF 0x02 //!< Alternate screen buffer +#define VT_FLAG_RAWIN 0x04 //!< Don't handle ^Z/^C/^V #define VT_FLAG_HASFB 0x10 //!< Set if the VTerm has requested the Framebuffer +#define VT_FLAG_SHOWCSR 0x20 //!< Always show the text cursor enum eVT_InModes { VT_INMODE_TEXT8, // UTF-8 Text Mode (VT100/xterm Emulation) @@ -59,6 +61,9 @@ typedef struct { int AltWritePos; //!< Alternate write position short ScrollTop; //!< Top of scrolling region (smallest) short ScrollHeight; //!< Length of scrolling region + + int VideoCursorX; + int VideoCursorY; tMutex ReadingLock; //!< Lock the VTerm when a process is reading from it tTID ReadingThread; //!< Owner of the lock @@ -68,6 +73,11 @@ typedef struct { // tSemaphore InputSemaphore; Uint32 *Buffer; + + // TODO: Do I need to keep this about? + // When should it be deallocated? on move to text mode, or some other time + // Call set again, it's freed, and if NULL it doesn't get reallocated. + tVideo_IOCtl_Bitmap *VideoCursor; char Name[2]; //!< Name of the terminal tVFS_Node Node; @@ -96,6 +106,7 @@ void VT_int_ClearLine(tVTerm *Term, int Num); void VT_int_PutChar(tVTerm *Term, Uint32 Ch); void VT_int_ScrollText(tVTerm *Term, int Count); void VT_int_ScrollFramebuffer( tVTerm *Term, int Count ); +void VT_int_UpdateCursor( tVTerm *Term, int bShow ); void VT_int_UpdateScreen( tVTerm *Term, int UpdateAll ); void VT_int_ChangeMode(tVTerm *Term, int NewMode, int NewWidth, int NewHeight); void VT_int_ToggleAltBuffer(tVTerm *Term, int Enabled); @@ -109,7 +120,7 @@ const Uint16 caVT100Colours[] = { }; // === GLOBALS === -MODULE_DEFINE(0, VERSION, VTerm, VT_Install, NULL, DEFAULT_OUTPUT, DEFAULT_INPUT, NULL); +MODULE_DEFINE(0, VERSION, VTerm, VT_Install, NULL, DEFAULT_INPUT, NULL); tDevFS_Driver gVT_DrvInfo = { NULL, "VTerm", { @@ -169,11 +180,11 @@ int VT_Install(char **Arguments) Log_Debug("VTerm", "Argument '%s'", arg); if( strcmp(opt, "Video") == 0 ) { - if( !gsVT_OutputDevice && Modules_InitialiseBuiltin( val ) == 0 ) + if( !gsVT_OutputDevice ) gsVT_OutputDevice = strdup(val); } else if( strcmp(opt, "Input") == 0 ) { - if( !gsVT_InputDevice && Modules_InitialiseBuiltin( val ) == 0 ) + if( !gsVT_InputDevice ) gsVT_InputDevice = strdup(val); } else if( strcmp(opt, "Width") == 0 ) { @@ -189,16 +200,25 @@ int VT_Install(char **Arguments) } // Apply Defaults - if(!gsVT_OutputDevice) gsVT_OutputDevice = strdup(DEFAULT_OUTPUT); - if(!gsVT_InputDevice) gsVT_InputDevice = strdup(DEFAULT_INPUT); + if(!gsVT_OutputDevice) gsVT_OutputDevice = (char*)DEFAULT_OUTPUT; + else if( Module_EnsureLoaded( gsVT_OutputDevice ) ) gsVT_OutputDevice = (char*)DEFAULT_OUTPUT; + if( Module_EnsureLoaded( gsVT_OutputDevice ) ) gsVT_OutputDevice = (char*)FALLBACK_OUTPUT; + if( Module_EnsureLoaded( gsVT_OutputDevice ) ) { + Log_Error("VTerm", "Fallback video '%s' is not avaliable, giving up", FALLBACK_OUTPUT); + return MODULE_ERR_MISC; + } - // Create paths + if(!gsVT_InputDevice) gsVT_InputDevice = (char*)DEFAULT_INPUT; + else if( Module_EnsureLoaded( gsVT_InputDevice ) ) gsVT_InputDevice = (char*)DEFAULT_INPUT; + + // Create device paths { char *tmp; tmp = malloc( 9 + strlen(gsVT_OutputDevice) + 1 ); strcpy(tmp, "/Devices/"); strcpy(&tmp[9], gsVT_OutputDevice); gsVT_OutputDevice = tmp; + tmp = malloc( 9 + strlen(gsVT_InputDevice) + 1 ); strcpy(tmp, "/Devices/"); strcpy(&tmp[9], gsVT_InputDevice); @@ -208,6 +228,9 @@ int VT_Install(char **Arguments) Log_Log("VTerm", "Using '%s' as output", gsVT_OutputDevice); Log_Log("VTerm", "Using '%s' as input", gsVT_InputDevice); + VT_InitOutput(); + VT_InitInput(); + // Create Nodes for( i = 0; i < NUM_VTS; i++ ) { @@ -239,13 +262,9 @@ int VT_Install(char **Arguments) // Add to DevFS DevFS_AddDevice( &gVT_DrvInfo ); - VT_InitOutput(); - VT_InitInput(); - // Set kernel output to VT0 Debug_SetKTerminal("/Devices/VTerm/0"); - Log_Log("VTerm", "Returning %i", MODULE_ERR_OK); return MODULE_ERR_OK; } @@ -306,25 +325,28 @@ void VT_SetResolution(int Width, int Height) giVT_RealWidth, giVT_RealHeight, mode.width, mode.height ); + giVT_RealWidth = mode.width; + giVT_RealHeight = mode.height; } VFS_IOCtl( giVT_OutputDevHandle, VIDEO_IOCTL_GETSETMODE, &tmp ); // Resize text terminals if needed - if( giVT_RealWidth != mode.width || giVT_RealHeight != mode.height ) + if( gVT_Terminals[0].Text && (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; + Log_Debug("VTerm", "Resizing terminals to %ix%i", + giVT_RealWidth/giVT_CharWidth, giVT_RealHeight/giVT_CharHeight); for( i = 0; i < NUM_VTS; i ++ ) { if( gVT_Terminals[i].Mode != TERM_MODE_TEXT ) continue; gVT_Terminals[i].TextWidth = giVT_RealWidth/giVT_CharWidth; gVT_Terminals[i].TextHeight = giVT_RealHeight/giVT_CharHeight; + gVT_Terminals[i].ScrollHeight = gVT_Terminals[i].TextHeight; gVT_Terminals[i].Text = realloc( gVT_Terminals[i].Text, @@ -426,7 +448,6 @@ int VT_Root_IOCtl(tVFS_Node *Node, int Id, void *Data) } /** - * \fn Uint64 VT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) * \brief Read from a virtual terminal */ Uint64 VT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) @@ -439,6 +460,9 @@ Uint64 VT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) Mutex_Acquire( &term->ReadingLock ); + // Update cursor + VT_int_UpdateCursor(term, 1); + // Check current mode switch(term->Mode) { @@ -457,7 +481,8 @@ Uint64 VT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) ((char*)Buffer)[pos] = term->InputBuffer[term->InputRead]; pos ++; term->InputRead ++; - term->InputRead %= MAX_INPUT_CHARS8; + while(term->InputRead > MAX_INPUT_CHARS8) + term->InputRead -= MAX_INPUT_CHARS8; } break; @@ -465,7 +490,7 @@ Uint64 VT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) // Other - UCS-4 default: VFS_SelectNode(Node, VFS_SELECT_READ, NULL, "VT_Read (UCS-4)"); - + avail = term->InputWrite - term->InputRead; if(avail < 0) avail += MAX_INPUT_CHARS32; @@ -480,7 +505,8 @@ Uint64 VT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) codepoint_buf[pos] = codepoint_in[term->InputRead]; pos ++; term->InputRead ++; - term->InputRead %= MAX_INPUT_CHARS32; + while(term->InputRead > MAX_INPUT_CHARS32) + term->InputRead -= MAX_INPUT_CHARS32; } pos *= 4; break; @@ -491,7 +517,9 @@ Uint64 VT_Read(tVFS_Node *Node, Uint64 Offset, Uint64 Length, void *Buffer) VFS_MarkAvaliable(&term->Node, 0); term->ReadingThread = -1; - + +// VT_int_UpdateCursor(term, term->Mode == TERM_MODE_TEXT); + Mutex_Release( &term->ReadingLock ); return pos; @@ -621,9 +649,7 @@ int VT_Terminal_IOCtl(tVFS_Node *Node, int Id, void *Data) Log_Log("VTerm", "VTerm %i mode set to %i", (int)Node->Inode, *iData); // Update mode if needed - if( term->Mode != *iData - || term->NewWidth - || term->NewHeight) + if( term->Mode != *iData || term->NewWidth || term->NewHeight) { // Adjust for text mode if( *iData == TERM_MODE_TEXT ) { @@ -690,10 +716,84 @@ int VT_Terminal_IOCtl(tVFS_Node *Node, int Id, void *Data) LEAVE('i', 1); return 1; - case TERM_IOCTL_GETCURSOR: + case TERM_IOCTL_GETSETCURSOR: + if(Data != NULL) + { + tVideo_IOCtl_Pos *pos = Data; + if( !CheckMem(Data, sizeof(*pos)) ) { + errno = -EINVAL; + LEAVE('i', -1); + return -1; + } + + if( term->Mode == TERM_MODE_TEXT ) + { + if(term->Flags & VT_FLAG_ALTBUF) + term->AltWritePos = pos->x + pos->y * term->TextWidth; + else + term->WritePos = pos->x + pos->y * term->TextWidth + term->ViewPos; + VT_int_UpdateCursor(term, 0); + } + else + { + term->VideoCursorX = pos->x; + term->VideoCursorY = pos->y; + VT_int_UpdateCursor(term, 1); + } + } ret = (term->Flags & VT_FLAG_ALTBUF) ? term->AltWritePos : term->WritePos-term->ViewPos; LEAVE('i', ret); return ret; + + case TERM_IOCTL_SETCURSORBITMAP: { + tVideo_IOCtl_Bitmap *bmp = Data; + if( Data == NULL ) + { + free( term->VideoCursor ); + term->VideoCursor = NULL; + LEAVE('i', 0); + return 0; + } + + // Sanity check bitmap + if( !CheckMem(bmp, sizeof(tVideo_IOCtl_Bitmap)) ) { + Log_Notice("VTerm", "%p in TERM_IOCTL_SETCURSORBITMAP invalid", bmp); + errno = -EINVAL; + LEAVE_RET('i', -1); + } + if( !CheckMem(bmp->Data, bmp->W*bmp->H*sizeof(Uint32)) ) { + Log_Notice("VTerm", "%p in TERM_IOCTL_SETCURSORBITMAP invalid", bmp); + errno = -EINVAL; + LEAVE_RET('i', -1); + } + + // Reallocate if needed + if(term->VideoCursor) + { + if(bmp->W * bmp->H != term->VideoCursor->W * term->VideoCursor->H) { + free(term->VideoCursor); + term->VideoCursor = NULL; + } + } + if(!term->VideoCursor) { + term->VideoCursor = malloc(sizeof(tVideo_IOCtl_Pos) + bmp->W*bmp->H*sizeof(Uint32)); + if(!term->VideoCursor) { + Log_Error("VTerm", "Unable to allocate memory for cursor"); + errno = -ENOMEM; + LEAVE_RET('i', -1); + } + } + + memcpy(term->VideoCursor, bmp, sizeof(tVideo_IOCtl_Pos) + bmp->W*bmp->H*sizeof(Uint32)); + + Log_Debug("VTerm", "Set VT%i's cursor to %p %ix%i", + (int)term->Node.Inode, bmp, bmp->W, bmp->H); + + if(gpVT_CurTerm == term) + VFS_IOCtl(giVT_OutputDevHandle, VIDEO_IOCTL_SETCURSORBITMAP, term->VideoCursor); + + LEAVE('i', 0); + return 0; } } LEAVE('i', -1); return -1; @@ -710,24 +810,23 @@ void VT_SetTerminal(int ID) giVT_CurrentTerminal = ID; gpVT_CurTerm = &gVT_Terminals[ID]; - // Update cursor - if( gpVT_CurTerm->Mode == TERM_MODE_TEXT && !(gpVT_CurTerm->Flags & VT_FLAG_HIDECSR) ) - { - tVideo_IOCtl_Pos pos; - int offset = (gpVT_CurTerm->Flags & VT_FLAG_ALTBUF) ? gpVT_CurTerm->AltWritePos : gpVT_CurTerm->WritePos - gpVT_CurTerm->ViewPos; - pos.x = offset % gpVT_CurTerm->TextWidth; - pos.y = offset / gpVT_CurTerm->TextWidth; - if( 0 <= pos.y && pos.y < gpVT_CurTerm->TextHeight ) - VFS_IOCtl(giVT_OutputDevHandle, VIDEO_IOCTL_SETCURSOR, &pos); - } if( gpVT_CurTerm->Mode == TERM_MODE_TEXT ) + { VT_SetMode( VIDEO_BUFFMT_TEXT ); + } else + { + // Update the cursor image + if(gpVT_CurTerm->VideoCursor) + VFS_IOCtl(giVT_OutputDevHandle, VIDEO_IOCTL_SETCURSORBITMAP, gpVT_CurTerm->VideoCursor); VT_SetMode( VIDEO_BUFFMT_FRAMEBUFFER ); + } + + VT_int_UpdateCursor(gpVT_CurTerm, 1); // Update the screen - VT_int_UpdateScreen( &gVT_Terminals[ ID ], 1 ); + VT_int_UpdateScreen( gpVT_CurTerm, 1 ); } /** @@ -752,30 +851,20 @@ void VT_KBCallBack(Uint32 Codepoint) Codepoint &= 0x7FFFFFFF; switch(Codepoint) { - #if !USE_CTRL_ALT - case KEY_RSHIFT: gbVT_CtrlDown = 0; break; - case KEY_LSHIFT: gbVT_AltDown = 0; break; - #else case KEY_LALT: gbVT_AltDown &= ~1; break; case KEY_RALT: gbVT_AltDown &= ~2; break; case KEY_LCTRL: gbVT_CtrlDown &= ~1; break; case KEY_RCTRL: gbVT_CtrlDown &= ~2; break; - #endif } return; } switch(Codepoint) { - #if !USE_CTRL_ALT // HACK: Use both shifts instead of Ctrl-Alt - case KEY_RSHIFT: gbVT_CtrlDown = 1; break; - case KEY_LSHIFT: gbVT_AltDown = 1; break; - #else case KEY_LALT: gbVT_AltDown |= 1; break; case KEY_RALT: gbVT_AltDown |= 2; break; case KEY_LCTRL: gbVT_CtrlDown |= 1; break; case KEY_RCTRL: gbVT_CtrlDown |= 2; break; - #endif default: if(!gbVT_AltDown || !gbVT_CtrlDown) @@ -806,10 +895,10 @@ void VT_KBCallBack(Uint32 Codepoint) case KEY_PGDOWN: if( gpVT_CurTerm->Flags & VT_FLAG_ALTBUF ) return ; - if( gpVT_CurTerm->ViewPos < gpVT_CurTerm->Width*gpVT_CurTerm->Height*(giVT_Scrollback-1) ) + if( gpVT_CurTerm->ViewPos < gpVT_CurTerm->Width*gpVT_CurTerm->Height*(giVT_Scrollback) ) gpVT_CurTerm->ViewPos += gpVT_CurTerm->Width; else - gpVT_CurTerm->ViewPos = gpVT_CurTerm->Width*gpVT_CurTerm->Height*(giVT_Scrollback-1); + gpVT_CurTerm->ViewPos = gpVT_CurTerm->Width*gpVT_CurTerm->Height*(giVT_Scrollback); return; } } @@ -865,6 +954,19 @@ void VT_KBCallBack(Uint32 Codepoint) // Unprintable / Don't Pass return; } + +#if 0 + // Handle meta characters + if( !(term->Flags & VT_FLAG_RAWIN) ) + { + switch(buf[0]) + { + case '\3': // ^C + + break; + } + } +#endif // Write if( MAX_INPUT_CHARS8 - term->InputWrite >= len ) @@ -895,11 +997,6 @@ void VT_KBCallBack(Uint32 Codepoint) } VFS_MarkAvaliable(&term->Node, 1); - - // Wake up the thread waiting on us - //if( term->ReadingThread >= 0 ) { - // Threads_WakeTID(term->ReadingThread); - //} } /** @@ -959,7 +1056,7 @@ int VT_int_ParseEscape(tVTerm *Term, char *Buffer) } // Get Command - if( ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) + if( ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z')) { if( bQuestionMark ) { @@ -1205,17 +1302,6 @@ void VT_int_PutString(tVTerm *Term, Uint8 *Buffer, Uint Count) } // Update Screen VT_int_UpdateScreen( Term, 0 ); - - // Update cursor - if( Term == gpVT_CurTerm && !(Term->Flags & VT_FLAG_HIDECSR) ) - { - tVideo_IOCtl_Pos pos; - int offset = (gpVT_CurTerm->Flags & VT_FLAG_ALTBUF) ? gpVT_CurTerm->AltWritePos : gpVT_CurTerm->WritePos - gpVT_CurTerm->ViewPos; - pos.x = offset % gpVT_CurTerm->TextWidth; - pos.y = offset / gpVT_CurTerm->TextWidth; - if( 0 <= pos.y && pos.y < gpVT_CurTerm->TextHeight ) - VFS_IOCtl(giVT_OutputDevHandle, VIDEO_IOCTL_SETCURSOR, &pos); - } } /** @@ -1247,13 +1333,15 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch) write_pos -= write_pos % Term->TextWidth; break; - case '\t': + case '\t': { int tmp = write_pos / Term->TextWidth; + write_pos %= Term->TextWidth; do { buffer[ write_pos ].Ch = '\0'; buffer[ write_pos ].Colour = Term->CurColour; write_pos ++; } while(write_pos & 7); - break; + write_pos += tmp * Term->TextWidth; + break; } case '\b': // Backspace is invalid at Offset 0 @@ -1344,47 +1432,55 @@ void VT_int_ScrollText(tVTerm *Term, int Count) tVT_Char *buf; int height, init_write_pos; int len, i; - + int scroll_top, scroll_height; + + // Get buffer pointer and attributes if( Term->Flags & VT_FLAG_ALTBUF ) { buf = Term->AltBuf; height = Term->TextHeight; init_write_pos = Term->AltWritePos; + scroll_top = Term->ScrollTop; + scroll_height = Term->ScrollHeight; } else { buf = Term->Text; - height = Term->TextHeight*giVT_Scrollback; + height = Term->TextHeight*(giVT_Scrollback+1); init_write_pos = Term->WritePos; + scroll_top = 0; + scroll_height = height; } - + + // Scroll text downwards if( Count > 0 ) { int base; - if(Count > Term->ScrollHeight) Count = Term->ScrollHeight; - base = Term->TextWidth*(Term->ScrollTop + Term->ScrollHeight - Count); - len = Term->TextWidth*(Term->ScrollHeight - Count); + + // Set up + if(Count > scroll_height) Count = scroll_height; + base = Term->TextWidth*(scroll_top + scroll_height - Count); + len = Term->TextWidth*(scroll_height - Count); // Scroll terminal cache - memcpy( - &buf[Term->TextWidth*Term->ScrollTop], - &buf[Term->TextWidth*(Term->ScrollTop+Count)], + memmove( + &buf[Term->TextWidth*scroll_top], + &buf[Term->TextWidth*(scroll_top+Count)], len*sizeof(tVT_Char) ); // Clear last rows for( i = 0; i < Term->TextWidth*Count; i ++ ) { - Term->AltBuf[ base + i ].Ch = 0; - Term->AltBuf[ base + i ].Colour = Term->CurColour; + buf[ base + i ].Ch = 0; + buf[ base + i ].Colour = Term->CurColour; } // Update Screen VT_int_ScrollFramebuffer( Term, Count ); if( Term->Flags & VT_FLAG_ALTBUF ) - Term->AltWritePos = Term->TextWidth*(Term->ScrollTop + Term->ScrollHeight - Count); + Term->AltWritePos = base; else - Term->WritePos = Term->ViewPos + Term->TextWidth*(Term->ScrollTop + Term->ScrollHeight - Count); -// Log_Debug("VTerm", "Term->WritePos = %i/%i = %i", Term->WritePos, Term->TextWidth, Term->WritePos/Term->TextWidth); + Term->WritePos = Term->ViewPos + Term->TextWidth*(Term->TextHeight - Count); for( i = 0; i < Count; i ++ ) { VT_int_UpdateScreen( Term, 0 ); @@ -1397,28 +1493,28 @@ void VT_int_ScrollText(tVTerm *Term, int Count) else { Count = -Count; - if(Count > Term->ScrollHeight) Count = Term->ScrollHeight; + if(Count > scroll_height) Count = scroll_height; - len = Term->TextWidth*(Term->ScrollHeight - Count); + len = Term->TextWidth*(scroll_height - Count); // Scroll terminal cache - memcpy( - &buf[Term->TextWidth*(Term->ScrollTop+Count)], - &buf[Term->TextWidth*Term->ScrollTop], + memmove( + &buf[Term->TextWidth*(scroll_top+Count)], + &buf[Term->TextWidth*scroll_top], len*sizeof(tVT_Char) ); // Clear preceding rows for( i = 0; i < Term->TextWidth*Count; i ++ ) { - Term->AltBuf[ i ].Ch = 0; - Term->AltBuf[ i ].Colour = Term->CurColour; + buf[ i ].Ch = 0; + buf[ i ].Colour = Term->CurColour; } VT_int_ScrollFramebuffer( Term, -Count ); if( Term->Flags & VT_FLAG_ALTBUF ) - Term->AltWritePos = Term->TextWidth*Term->ScrollTop; + Term->AltWritePos = Term->TextWidth*scroll_top; else - Term->WritePos = Term->ViewPos + Term->TextWidth*Term->ScrollTop; + Term->WritePos = Term->ViewPos; for( i = 0; i < Count; i ++ ) { VT_int_UpdateScreen( Term, 0 ); @@ -1462,6 +1558,7 @@ void VT_int_ScrollFramebuffer( tVTerm *Term, int Count ) // BLIT to 0,0 from 0,giVT_CharHeight buf.Op = VIDEO_2DOP_BLIT; buf.SrcX = 0; buf.DstX = 0; + // TODO: Don't assume character dimensions buf.W = Term->TextWidth * giVT_CharWidth; if( Count > 0 ) { @@ -1482,6 +1579,50 @@ void VT_int_ScrollFramebuffer( tVTerm *Term, int Count ) VFS_IOCtl(giVT_OutputDevHandle, VIDEO_IOCTL_SETBUFFORMAT, &tmp); } +void VT_int_UpdateCursor( tVTerm *Term, int bShow ) +{ + tVideo_IOCtl_Pos csr_pos; + + if( Term != gpVT_CurTerm ) return ; + + if( !bShow ) + { + csr_pos.x = -1; + csr_pos.y = -1; + } + else if( Term->Mode == TERM_MODE_TEXT ) + { + int offset; + +// if( !(Term->Flags & VT_FLAG_SHOWCSR) +// && ( (Term->Flags & VT_FLAG_HIDECSR) || !Term->Node.ReadThreads) +// ) + if( !Term->Text || Term->Flags & VT_FLAG_HIDECSR ) + { + csr_pos.x = -1; + csr_pos.y = -1; + } + else + { + if(Term->Flags & VT_FLAG_ALTBUF) + offset = Term->AltWritePos; + else + offset = Term->WritePos - Term->ViewPos; + + csr_pos.x = offset % Term->TextWidth; + csr_pos.y = offset / Term->TextWidth; + if( 0 > csr_pos.y || csr_pos.y >= Term->TextHeight ) + csr_pos.y = -1, csr_pos.x = -1; + } + } + else + { + csr_pos.x = Term->VideoCursorX; + csr_pos.y = Term->VideoCursorY; + } + VFS_IOCtl(giVT_OutputDevHandle, VIDEO_IOCTL_SETCURSOR, &csr_pos); +} + /** * \fn void VT_int_UpdateScreen( tVTerm *Term, int UpdateAll ) * \brief Updates the video framebuffer @@ -1528,6 +1669,8 @@ void VT_int_UpdateScreen( tVTerm *Term, int UpdateAll ) ); break; } + + VT_int_UpdateCursor(Term, 1); } /** @@ -1539,13 +1682,12 @@ void VT_int_UpdateScreen( tVTerm *Term, int UpdateAll ) */ void VT_int_ChangeMode(tVTerm *Term, int NewMode, int NewWidth, int NewHeight) { - // TODO: Increase RealWidth/RealHeight when this happens if(NewWidth > giVT_RealWidth) NewWidth = giVT_RealWidth; if(NewHeight > giVT_RealHeight) NewHeight = giVT_RealHeight; Term->Mode = NewMode; - + if(NewWidth != Term->Width || NewHeight != Term->Height) { int oldW = Term->Width; @@ -1606,24 +1748,24 @@ void VT_int_ChangeMode(tVTerm *Term, int NewMode, int NewWidth, int NewHeight) } free(oldFB); } + + // Debug + switch(NewMode) + { + case TERM_MODE_TEXT: + Log_Log("VTerm", "Set VT %p to text mode (%ix%i)", + Term, Term->TextWidth, Term->TextHeight); + break; + case TERM_MODE_FB: + Log_Log("VTerm", "Set VT %p to framebuffer mode (%ix%i)", + Term, Term->Width, Term->Height); + break; + //case TERM_MODE_2DACCEL: + //case TERM_MODE_3DACCEL: + // return; + } } - - // Debug - switch(NewMode) - { - case TERM_MODE_TEXT: - Log_Log("VTerm", "Set VT %p to text mode (%ix%i)", - Term, Term->TextWidth, Term->TextHeight); - break; - case TERM_MODE_FB: - Log_Log("VTerm", "Set VT %p to framebuffer mode (%ix%i)", - Term, Term->Width, Term->Height); - break; - //case TERM_MODE_2DACCEL: - //case TERM_MODE_3DACCEL: - // return; - } }