Renamed tpl_drv_* to api_drv_* (a more fitting name)
[tpg/acess2.git] / Kernel / drv / vterm.c
index bb658f2..85ab0e1 100644 (file)
@@ -5,14 +5,12 @@
 #include <acess.h>
 #include <fs_devfs.h>
 #include <modules.h>
-#include <tpl_drv_video.h>
-#include <tpl_drv_keyboard.h>
-#include <tpl_drv_terminal.h>
+#include <api_drv_video.h>
+#include <api_drv_keyboard.h>
+#include <api_drv_terminal.h>
 #include <errno.h>
 #include <semaphore.h>
 
-#define        USE_CTRL_ALT    1
-
 // === CONSTANTS ===
 #define VERSION        ((0<<8)|(50))
 
@@ -21,6 +19,7 @@
 #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
@@ -29,6 +28,7 @@
 
 #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
 
 enum eVT_InModes {
@@ -109,7 +109,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, FALLBACK_OUTPUT, NULL);
 tDevFS_Driver  gVT_DrvInfo = {
        NULL, "VTerm",
        {
@@ -169,11 +169,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 +189,21 @@ 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(!gsVT_InputDevice)   gsVT_InputDevice = (char*)DEFAULT_INPUT;
+       else if( Module_EnsureLoaded( gsVT_InputDevice ) )      gsVT_InputDevice = (char*)DEFAULT_INPUT;
        
-       // Create paths
+       // 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);
@@ -245,7 +250,6 @@ int VT_Install(char **Arguments)
        // Set kernel output to VT0
        Debug_SetKTerminal("/Devices/VTerm/0");
        
-       Log_Log("VTerm", "Returning %i", MODULE_ERR_OK);
        return MODULE_ERR_OK;
 }
 
@@ -319,12 +323,15 @@ void VT_SetResolution(int Width, int Height)
                // 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 +433,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)
@@ -465,7 +471,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;
@@ -752,30 +758,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)
@@ -865,6 +861,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 )
@@ -984,6 +993,9 @@ int VT_int_ParseEscape(tVTerm *Term, char *Buffer)
                                                break;
                                        }
                                        break;
+                               default:
+                                       Log_Warning("VTerm", "Unknown control sequence '\\x1B[?%c'", c);
+                                       break;
                                }
                        }
                        else
@@ -1044,22 +1056,83 @@ int VT_int_ParseEscape(tVTerm *Term, char *Buffer)
                                                break;
                                        }
                                        break;
+                               
+                               // Erase in line
+                               case 'K':
+                                       switch(args[0])
+                                       {
+                                       case 0: // Erase to right
+                                               if( Term->Flags & VT_FLAG_ALTBUF )
+                                               {
+                                                        int    i, max;
+                                                       max = Term->Width - Term->AltWritePos % Term->Width;
+                                                       for( i = 0; i < max; i ++ )
+                                                               Term->AltBuf[Term->AltWritePos+i].Ch = 0;
+                                               }
+                                               else
+                                               {
+                                                        int    i, max;
+                                                       max = Term->Width - Term->WritePos % Term->Width;
+                                                       for( i = 0; i < max; i ++ )
+                                                               Term->Text[Term->WritePos+i].Ch = 0;
+                                               }
+                                               VT_int_UpdateScreen(Term, 0);
+                                               break;
+                                       case 1: // Erase to left
+                                               if( Term->Flags & VT_FLAG_ALTBUF )
+                                               {
+                                                        int    i = Term->AltWritePos % Term->Width;
+                                                       while( i -- )
+                                                               Term->AltBuf[Term->AltWritePos++].Ch = 0;
+                                               }
+                                               else
+                                               {
+                                                        int    i = Term->WritePos % Term->Width;
+                                                       while( i -- )
+                                                               Term->Text[Term->WritePos++].Ch = 0;
+                                               }
+                                               VT_int_UpdateScreen(Term, 0);
+                                               break;
+                                       case 2: // Erase all
+                                               if( Term->Flags & VT_FLAG_ALTBUF )
+                                               {
+                                                       VT_int_ClearLine(Term, Term->AltWritePos / Term->Width);
+                                               }
+                                               else
+                                               {
+                                                       VT_int_ClearLine(Term, Term->WritePos / Term->Width);
+                                               }
+                                               VT_int_UpdateScreen(Term, 0);
+                                               break;
+                                       }
+                                       break;
+                               
                                // Set cursor position
                                case 'H':
                                        if( Term->Flags & VT_FLAG_ALTBUF )
                                                Term->AltWritePos = args[0] + args[1]*Term->TextWidth;
                                        else
                                                Term->WritePos = args[0] + args[1]*Term->TextWidth;
-                                       Log_Debug("VTerm", "args = {%i, %i}", args[0], args[1]);
+                                       //Log_Debug("VTerm", "args = {%i, %i}", args[0], args[1]);
                                        break;
                                
                                // Scroll up `n` lines
                                case 'S':
                                        tmp = -1;
                                // Scroll down `n` lines
-                               case 'P':
+                               case 'T':
                                        if(argc == 1)   tmp *= args[0];
-                                       
+                                       if( Term->Flags & VT_FLAG_ALTBUF )
+                                               VT_int_ScrollText(Term, tmp);
+                                       else
+                                       {
+                                               if(Term->ViewPos/Term->TextWidth + tmp < 0)
+                                                       break;
+                                               if(Term->ViewPos/Term->TextWidth + tmp  > Term->TextHeight * (giVT_Scrollback + 1))
+                                                       break;
+                                               
+                                               Term->ViewPos += Term->TextWidth*tmp;
+                                       }
                                        break;
                                
                                // Set Font flags
@@ -1097,7 +1170,7 @@ int VT_int_ParseEscape(tVTerm *Term, char *Buffer)
                                        break;
                                
                                default:
-                                       Log_Warning("VTerm", "Unknown control sequence");
+                                       Log_Warning("VTerm", "Unknown control sequence '\\x1B[%c'", c);
                                        break;
                                }
                        }
@@ -1183,13 +1256,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
@@ -1264,8 +1339,11 @@ void VT_int_PutChar(tVTerm *Term, Uint32 Ch)
                        // Update the last line
                        Term->WritePos -= Term->TextWidth;
                        VT_int_UpdateScreen( Term, 0 );
+                       Term->WritePos += Term->TextWidth;
                        
                        VT_int_ScrollText(Term, 1);
+                       
+                       Term->ViewPos += Term->TextWidth;
                }
        }
        
@@ -1276,43 +1354,53 @@ void VT_int_ScrollText(tVTerm *Term, int Count)
 {
        tVT_Char        *buf;
         int    height, init_write_pos;
-        int    base, len, i;
+        int    len, i;
+        int    scroll_top, scroll_height;
        
        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;
                init_write_pos = Term->WritePos;
+               scroll_top = 0;
+               scroll_height = height;
        }
        
        if( Count > 0 )
        {
-               if(Count > Term->ScrollHeight)  Count = Term->ScrollHeight;
-               base = Term->TextWidth*(Term->ScrollTop + Term->ScrollHeight - Count);
-               len = Term->TextWidth*(height - Term->ScrollHeight - Count - Term->ScrollTop);
+                int    base;
+               if(Count > scroll_height)       Count = scroll_height;
+//             Debug("Scroll: Count = %i", Count);
+               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)],
+                       &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 );
-               Term->WritePos = Term->ViewPos + Term->ScrollTop + (Term->ScrollHeight - Count);
+               if( Term->Flags & VT_FLAG_ALTBUF )
+                       Term->AltWritePos = base;
+               else
+                       Term->WritePos = Term->ViewPos + Term->TextWidth*(Term->TextHeight - Count);
                for( i = 0; i < Count; i ++ )
                {
                        VT_int_UpdateScreen( Term, 0 );
@@ -1325,25 +1413,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*(height - Term->ScrollHeight - Count - Term->ScrollTop);
+               len = Term->TextWidth*(scroll_height - Count);
                
                // Scroll terminal cache
                memcpy(
-                       &buf[Term->TextWidth*(Term->ScrollTop+Count)],
-                       &buf[Term->TextWidth*Term->ScrollTop],
+                       &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 );
-               Term->WritePos = Term->ViewPos + Term->ScrollTop;
+               if( Term->Flags & VT_FLAG_ALTBUF )
+                       Term->AltWritePos = Term->TextWidth*scroll_top;
+               else
+                       Term->WritePos = Term->ViewPos;
                for( i = 0; i < Count; i ++ )
                {
                        VT_int_UpdateScreen( Term, 0 );
@@ -1387,19 +1478,20 @@ 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 )
        {
                buf.SrcY = (Term->ScrollTop+Count) * giVT_CharHeight;
                buf.DstY = Term->ScrollTop * giVT_CharHeight;
-               buf.H = (Term->ScrollHeight-Count) * giVT_CharHeight;
        }
        else    // Scroll up, move text down
        {
+               Count = -Count;
                buf.SrcY = Term->ScrollTop * giVT_CharHeight;
                buf.DstY = (Term->ScrollTop+Count) * giVT_CharHeight;
-               buf.H = (Term->ScrollHeight+Count) * giVT_CharHeight;
        }
+       buf.H = (Term->ScrollHeight-Count) * giVT_CharHeight;
        VFS_WriteAt(giVT_OutputDevHandle, 0, sizeof(buf), &buf);
        
        // Restore old mode (this function is only called during text mode)
@@ -1558,6 +1650,7 @@ void VT_int_ToggleAltBuffer(tVTerm *Term, int Enabled)
                Term->Flags |= VT_FLAG_ALTBUF;
        else
                Term->Flags &= ~VT_FLAG_ALTBUF;
+       VT_int_UpdateScreen(Term, 1);
 }
 
 // ---

UCC git Repository :: git.ucc.asn.au