3 * - By John Hodge (thePowersGang)
6 * - Virtual Terminal - Input code
9 #include <api_drv_keyboard.h>
12 // --- Key States --- (Used for VT Switching/Magic Combos)
13 int gbVT_CtrlDown = 0;
15 int gbVT_SysrqDown = 0;
19 * \fn void VT_InitInput()
20 * \brief Initialises the input
24 giVT_InputDevHandle = VFS_Open(gsVT_InputDevice, VFS_OPENFLAG_READ);
25 if(giVT_InputDevHandle == -1) {
26 Log_Warning("VTerm", "Can't open the input device '%s'", gsVT_InputDevice);
29 VFS_IOCtl(giVT_InputDevHandle, KB_IOCTL_SETCALLBACK, VT_KBCallBack);
33 * \fn void VT_KBCallBack(Uint32 Codepoint)
34 * \brief Called on keyboard interrupt
35 * \param Codepoint Pseudo-UTF32 character
37 * Handles a key press and sends the key code to the user's buffer.
38 * If the code creates a kernel-magic sequence, it is not passed to the
39 * user and is handled in-kernel.
41 void VT_KBCallBack(Uint32 Codepoint)
43 tVTerm *term = gpVT_CurTerm;
46 switch( Codepoint & KEY_ACTION_MASK )
48 case KEY_ACTION_RELEASE:
49 switch(Codepoint & KEY_CODEPOINT_MASK)
51 case KEY_LALT: gbVT_AltDown &= ~1; break;
52 case KEY_RALT: gbVT_AltDown &= ~2; break;
53 case KEY_LCTRL: gbVT_CtrlDown &= ~1; break;
54 case KEY_RCTRL: gbVT_CtrlDown &= ~2; break;
58 case KEY_ACTION_PRESS:
59 switch(Codepoint & KEY_CODEPOINT_MASK)
61 case KEY_LALT: gbVT_AltDown |= 1; break;
62 case KEY_RALT: gbVT_AltDown |= 2; break;
63 case KEY_LCTRL: gbVT_CtrlDown |= 1; break;
64 case KEY_RCTRL: gbVT_CtrlDown |= 2; break;
67 if(!gbVT_AltDown || !gbVT_CtrlDown)
69 switch(Codepoint & KEY_CODEPOINT_MASK)
71 case KEY_F1: VT_SetTerminal(0); return;
72 case KEY_F2: VT_SetTerminal(1); return;
73 case KEY_F3: VT_SetTerminal(2); return;
74 case KEY_F4: VT_SetTerminal(3); return;
75 case KEY_F5: VT_SetTerminal(4); return;
76 case KEY_F6: VT_SetTerminal(5); return;
77 case KEY_F7: VT_SetTerminal(6); return;
78 case KEY_F8: VT_SetTerminal(7); return;
79 case KEY_F9: VT_SetTerminal(8); return;
80 case KEY_F10: VT_SetTerminal(9); return;
81 case KEY_F11: VT_SetTerminal(10); return;
82 case KEY_F12: VT_SetTerminal(11); return;
85 // Scrolling is only valid in text mode
86 if(gpVT_CurTerm->Mode != TERM_MODE_TEXT)
89 switch(Codepoint & KEY_CODEPOINT_MASK)
93 if( gpVT_CurTerm->Flags & VT_FLAG_ALTBUF )
95 gpVT_CurTerm->ViewPos = MAX(
97 gpVT_CurTerm->ViewPos - gpVT_CurTerm->Width
101 if( gpVT_CurTerm->Flags & VT_FLAG_ALTBUF )
103 gpVT_CurTerm->ViewPos = MIN(
104 gpVT_CurTerm->ViewPos + gpVT_CurTerm->Width,
105 gpVT_CurTerm->Width * gpVT_CurTerm->Height*giVT_Scrollback
113 if(term->Mode == TERM_MODE_TEXT)
118 // Ignore anything that isn't a press or refire
119 if( (Codepoint & KEY_ACTION_MASK) != KEY_ACTION_PRESS
120 && (Codepoint & KEY_ACTION_MASK) != KEY_ACTION_REFIRE
126 Codepoint &= KEY_CODEPOINT_MASK;
128 // Ignore Modifer Keys
129 if(Codepoint > KEY_MODIFIERS) return;
131 // Get UTF-8/ANSI Encoding
134 // 0: No translation, don't send to user
137 buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'D';
141 buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'C';
145 buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'A';
149 buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'B';
154 buf[0] = '\x1B'; buf[1] = '['; buf[2] = '5'; buf[3] = '~';
158 buf[0] = '\x1B'; buf[1] = '['; buf[2] = '6'; buf[3] = '~';
162 // Attempt to encode in UTF-8
164 len = WriteUTF8( buf, Codepoint );
166 Warning("Codepoint (%x) is unrepresentable in UTF-8", Codepoint);
172 // Unprintable / Don't Pass
177 // Handle meta characters
178 if( !(term->Flags & VT_FLAG_RAWIN) )
190 if( MAX_INPUT_CHARS8 - term->InputWrite >= len )
191 memcpy( &term->InputBuffer[term->InputWrite], buf, len );
193 memcpy( &term->InputBuffer[term->InputWrite], buf, MAX_INPUT_CHARS8 - term->InputWrite );
194 memcpy( &term->InputBuffer[0], buf, len - (MAX_INPUT_CHARS8 - term->InputWrite) );
196 // Roll the buffer over
197 term->InputWrite += len;
198 term->InputWrite %= MAX_INPUT_CHARS8;
199 if( (term->InputWrite - term->InputRead + MAX_INPUT_CHARS8)%MAX_INPUT_CHARS8 < len ) {
200 term->InputRead = term->InputWrite + 1;
201 term->InputRead %= MAX_INPUT_CHARS8;
206 // Encode the raw key event
207 Uint32 *raw_in = (void*)term->InputBuffer;
211 if( term->InputWrite == term->InputRead )
215 raw_in[ term->InputWrite ] = Codepoint;
217 if(term->InputWrite >= MAX_INPUT_CHARS32)
218 term->InputWrite -= MAX_INPUT_CHARS32;
221 // TODO: Should old or new be dropped?
222 if(term->InputRead == term->InputWrite) {
224 if( term->InputRead >= MAX_INPUT_CHARS32 )
225 term->InputRead -= MAX_INPUT_CHARS32;
230 VFS_MarkAvaliable(&term->Node, 1);