*/
#include "vterm.h"
#include <api_drv_keyboard.h>
+#define DEBUG 1
// === GLOBALS ===
// --- Key States --- (Used for VT Switching/Magic Combos)
return ;
}
VFS_IOCtl(giVT_InputDevHandle, KB_IOCTL_SETCALLBACK, VT_KBCallBack);
+ LOG("VTerm input initialised");
}
/**
// Catch VT binds
switch( Codepoint & KEY_ACTION_MASK )
{
+ case KEY_ACTION_RAWSYM:
+ term->RawScancode = Codepoint & KEY_CODEPOINT_MASK;
+ break;
case KEY_ACTION_RELEASE:
- switch(Codepoint & KEY_CODEPOINT_MASK)
+ switch(term->RawScancode)
{
- 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;
+ case KEYSYM_LEFTALT: gbVT_AltDown &= ~1; break;
+ case KEYSYM_RIGHTALT: gbVT_AltDown &= ~2; break;
+ case KEYSYM_LEFTCTRL: gbVT_CtrlDown &= ~1; break;
+ case KEYSYM_RIGHTCTRL: gbVT_CtrlDown &= ~2; break;
}
break;
case KEY_ACTION_PRESS:
- switch(Codepoint & KEY_CODEPOINT_MASK)
+ switch(term->RawScancode)
{
- 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;
+ case KEYSYM_LEFTALT: gbVT_AltDown |= 1; break;
+ case KEYSYM_RIGHTALT: gbVT_AltDown |= 2; break;
+ case KEYSYM_LEFTCTRL: gbVT_CtrlDown |= 1; break;
+ case KEYSYM_RIGHTCTRL: gbVT_CtrlDown |= 2; break;
}
+ // Check if the magic keys are held
if(!gbVT_AltDown || !gbVT_CtrlDown)
break;
- switch(Codepoint & KEY_CODEPOINT_MASK)
+
+ switch(term->RawScancode)
{
- 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 KEYSYM_DELETE:
+ // TODO: Reboot, or poke secure registered app
+ return;
+ case KEYSYM_F1 : VT_SetTerminal(0); return;
+ case KEYSYM_F2 : VT_SetTerminal(1); return;
+ case KEYSYM_F3 : VT_SetTerminal(2); return;
+ case KEYSYM_F4 : VT_SetTerminal(3); return;
+ case KEYSYM_F5 : VT_SetTerminal(4); return;
+ case KEYSYM_F6 : VT_SetTerminal(5); return;
+ case KEYSYM_F7 : VT_SetTerminal(6); return;
+ case KEYSYM_F8 : VT_SetTerminal(7); return;
+ case KEYSYM_F9 : VT_SetTerminal(8); return;
+ case KEYSYM_F10: VT_SetTerminal(9); return;
+ case KEYSYM_F11: VT_SetTerminal(10); return;
+ case KEYSYM_F12: VT_SetTerminal(11); return;
}
// Scrolling is only valid in text mode
- if(gpVT_CurTerm->Mode != TERM_MODE_TEXT)
+ if(term->Mode != TERM_MODE_TEXT)
break;
- switch(Codepoint & KEY_CODEPOINT_MASK)
+// Log_Debug("VTerm", "Magic Ctrl-Alt-0x%x", term->RawScancode);
+
+ const unsigned int scroll_step = term->TextHeight / 2;
+ // Note the lack of giVT_Scrollback+1, view top can't go above size-onescreen
+ const unsigned int scroll_max = term->TextHeight * giVT_Scrollback;
+ switch(term->RawScancode)
{
- // Scrolling
- case KEY_PGUP:
- if( gpVT_CurTerm->Flags & VT_FLAG_ALTBUF )
+ // VTerm scrolling
+ // - Scrolls half a screen at a time
+ // - View up (text goes down)
+ case KEYSYM_PGUP:
+ if( term->Flags & VT_FLAG_ALTBUF )
return ;
- gpVT_CurTerm->ViewPos = MAX(
- 0,
- gpVT_CurTerm->ViewPos - gpVT_CurTerm->Width
- );
+ term->ViewTopRow = (term->ViewTopRow > scroll_step ? term->ViewTopRow - scroll_step : 0);
+ VT_int_UpdateScreen(term, 1);
return;
- case KEY_PGDOWN:
- if( gpVT_CurTerm->Flags & VT_FLAG_ALTBUF )
+ // - View down (text goes up)
+ case KEYSYM_PGDN:
+ if( term->Flags & VT_FLAG_ALTBUF )
return ;
- gpVT_CurTerm->ViewPos = MIN(
- gpVT_CurTerm->ViewPos + gpVT_CurTerm->Width,
- gpVT_CurTerm->Width * gpVT_CurTerm->Height*giVT_Scrollback
- );
+
+ term->ViewTopRow = MIN(term->ViewTopRow + scroll_step, scroll_max);
+ VT_int_UpdateScreen(term, 1);
return;
}
break;
}
// Encode key
- if(term->Mode == TERM_MODE_TEXT)
+ if(term->Mode == PTYBUFFMT_TEXT)
{
Uint8 buf[6] = {0};
int len = 0;
Codepoint &= KEY_CODEPOINT_MASK;
- // Ignore Modifer Keys
- if(Codepoint > KEY_MODIFIERS) return;
-
// Get UTF-8/ANSI Encoding
- switch(Codepoint)
+ if( Codepoint == 0 )
{
- // 0: No translation, don't send to user
- case 0: break;
- 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;
- case KEY_UP:
- buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'A';
- len = 3;
- break;
- case KEY_DOWN:
- buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'B';
- len = 3;
- break;
-
- case KEY_PGUP:
- buf[0] = '\x1B'; buf[1] = '['; buf[2] = '5'; buf[3] = '~';
- len = 4;
- break;
- case KEY_PGDOWN:
- buf[0] = '\x1B'; buf[1] = '['; buf[2] = '6'; buf[3] = '~';
- len = 4;
- break;
-
- // Attempt to encode in UTF-8
- default:
+ // Non-printable keys
+ switch(term->RawScancode)
+ {
+ case KEYSYM_LEFTARROW:
+ case KEYSYM_KP4:
+ buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'D';
+ len = 3;
+ break;
+ case KEYSYM_RIGHTARROW:
+ case KEYSYM_KP6:
+ buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'C';
+ len = 3;
+ break;
+ case KEYSYM_UPARROW:
+ case KEYSYM_KP8:
+ buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'A';
+ len = 3;
+ break;
+ case KEYSYM_DOWNARROW:
+ case KEYSYM_KP2:
+ buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'B';
+ len = 3;
+ break;
+
+ case KEYSYM_PGUP:
+ case KEYSYM_KP9: // If Codepoint=0, It's page up
+ buf[0] = '\x1B'; buf[1] = '['; buf[2] = '5'; buf[3] = '~';
+ len = 4;
+ break;
+ case KEYSYM_PGDN:
+ case KEYSYM_KP3: // If Codepoint=0, It's page down
+ buf[0] = '\x1B'; buf[1] = '['; buf[2] = '6'; buf[3] = '~';
+ len = 4;
+ break;
+
+ case KEYSYM_HOME:
+ case KEYSYM_KP7: // Codepoint==0, then it's home (not translated)
+ buf[0] = '\x1B'; buf[1] = 'O'; buf[2] = 'H';
+ len = 3;
+ break;
+ case KEYSYM_END:
+ case KEYSYM_KP1: // You get the drill
+ buf[0] = '\x1B'; buf[1] = 'O'; buf[2] = 'F';
+ len = 3;
+ break;
+
+ case KEYSYM_INSERT:
+ case KEYSYM_KP0: // See above
+ buf[0] = '\x1B'; buf[1] = '['; buf[2] = '2'; buf[3] = '~';
+ len = 4;
+ break;
+ case KEYSYM_DELETE:
+ case KEYSYM_KPPERIOD: // Are you that dumb? Look up
+ buf[0] = '\x1B'; buf[1] = '['; buf[2] = '3'; buf[3] = '~';
+ len = 4;
+ break;
+ }
+ }
+ else if( gbVT_CtrlDown )
+ {
+ len = 1;
+ switch( term->RawScancode )
+ {
+ case KEYSYM_2:
+ buf[0] = '\0';
+ break;
+ case KEYSYM_3 ... KEYSYM_7:
+ buf[0] = 0x1b + (term->RawScancode - KEYSYM_3);
+ break;
+ case KEYSYM_8:
+ buf[0] = 0x7f;
+ break;
+ // - Ctrl-A = \1, Ctrl-Z = \x1a
+ case KEYSYM_a ... KEYSYM_z:
+ buf[0] = 0x01 + (term->RawScancode - KEYSYM_a);
+ break;
+ default:
+ goto utf_encode;
+ }
+ }
+ else
+ {
+ utf_encode:
+ // Attempt to encode in UTF-8
len = WriteUTF8( buf, Codepoint );
if(len == 0) {
Warning("Codepoint (%x) is unrepresentable in UTF-8", Codepoint);
}
- break;
}
if(len == 0) {
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 )
- 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;
- }
+ PTY_SendInput(term->PTY, (void*)buf, len);
}
else
{
- // Encode the raw key event
- Uint32 *raw_in = (void*)term->InputBuffer;
-
- #if 0
- // Drop new keys
- if( term->InputWrite == term->InputRead )
- return ;
- #endif
-
- raw_in[ term->InputWrite ] = Codepoint;
- term->InputWrite ++;
- if(term->InputWrite >= MAX_INPUT_CHARS32)
- term->InputWrite -= MAX_INPUT_CHARS32;
-
- #if 1
- // TODO: Should old or new be dropped?
- if(term->InputRead == term->InputWrite) {
- term->InputRead ++;
- if( term->InputRead >= MAX_INPUT_CHARS32 )
- term->InputRead -= MAX_INPUT_CHARS32;
- }
- #endif
+ PTY_SendInput(term->PTY, (void*)&Codepoint, sizeof(Codepoint));
}
-
- VFS_MarkAvaliable(&term->Node, 1);
}