Kernel/VTerm - Replace offset WritePos with Row,Col pair
[tpg/acess2.git] / KernelLand / Kernel / drv / vterm_input.c
1 /*
2  * Acess2 Kernel
3  * - By John Hodge (thePowersGang)
4  *
5  * drv/vterm_input.c
6  * - Virtual Terminal - Input code
7  */
8 #include "vterm.h"
9 #include <api_drv_keyboard.h>
10 #define DEBUG   1
11
12 // === GLOBALS ===
13 // --- Key States --- (Used for VT Switching/Magic Combos)
14  int    gbVT_CtrlDown = 0;
15  int    gbVT_AltDown = 0;
16  int    gbVT_SysrqDown = 0;
17
18 // === CODE ===
19 /**
20  * \fn void VT_InitInput()
21  * \brief Initialises the input
22  */
23 void VT_InitInput()
24 {
25         giVT_InputDevHandle = VFS_Open(gsVT_InputDevice, VFS_OPENFLAG_READ);
26         if(giVT_InputDevHandle == -1) {
27                 Log_Warning("VTerm", "Can't open the input device '%s'", gsVT_InputDevice);
28                 return ;
29         }
30         VFS_IOCtl(giVT_InputDevHandle, KB_IOCTL_SETCALLBACK, VT_KBCallBack);
31         LOG("VTerm input initialised");
32 }
33
34 /**
35  * \fn void VT_KBCallBack(Uint32 Codepoint)
36  * \brief Called on keyboard interrupt
37  * \param Codepoint     Pseudo-UTF32 character
38  * 
39  * Handles a key press and sends the key code to the user's buffer.
40  * If the code creates a kernel-magic sequence, it is not passed to the
41  * user and is handled in-kernel.
42  */
43 void VT_KBCallBack(Uint32 Codepoint)
44 {
45         tVTerm  *term = gpVT_CurTerm;
46
47         // Catch VT binds
48         switch( Codepoint & KEY_ACTION_MASK )
49         {
50         case KEY_ACTION_RAWSYM:
51                 term->RawScancode = Codepoint & KEY_CODEPOINT_MASK;
52                 break;
53         case KEY_ACTION_RELEASE:
54                 switch(term->RawScancode)
55                 {
56                 case KEYSYM_LEFTALT:    gbVT_AltDown &= ~1;     break;
57                 case KEYSYM_RIGHTALT:   gbVT_AltDown &= ~2;     break;
58                 case KEYSYM_LEFTCTRL:   gbVT_CtrlDown &= ~1;    break;
59                 case KEYSYM_RIGHTCTRL:  gbVT_CtrlDown &= ~2;    break;
60                 }
61                 break;
62         
63         case KEY_ACTION_PRESS:
64                 switch(term->RawScancode)
65                 {
66                 case KEYSYM_LEFTALT:    gbVT_AltDown |= 1;      break;
67                 case KEYSYM_RIGHTALT:   gbVT_AltDown |= 2;      break;
68                 case KEYSYM_LEFTCTRL:   gbVT_CtrlDown |= 1;     break;
69                 case KEYSYM_RIGHTCTRL:  gbVT_CtrlDown |= 2;     break;
70                 }
71                 
72                 // Check if the magic keys are held
73                 if(!gbVT_AltDown || !gbVT_CtrlDown)
74                         break;
75                 
76                 switch(term->RawScancode)
77                 {
78                 case KEYSYM_F1 :        VT_SetTerminal(0);      return;
79                 case KEYSYM_F2 :        VT_SetTerminal(1);      return;
80                 case KEYSYM_F3 :        VT_SetTerminal(2);      return;
81                 case KEYSYM_F4 :        VT_SetTerminal(3);      return;
82                 case KEYSYM_F5 :        VT_SetTerminal(4);      return;
83                 case KEYSYM_F6 :        VT_SetTerminal(5);      return;
84                 case KEYSYM_F7 :        VT_SetTerminal(6);      return;
85                 case KEYSYM_F8 :        VT_SetTerminal(7);      return;
86                 case KEYSYM_F9 :        VT_SetTerminal(8);      return;
87                 case KEYSYM_F10:        VT_SetTerminal(9);      return;
88                 case KEYSYM_F11:        VT_SetTerminal(10);     return;
89                 case KEYSYM_F12:        VT_SetTerminal(11);     return;
90                 }
91                 
92                 // Scrolling is only valid in text mode
93                 if(term->Mode != TERM_MODE_TEXT)
94                         break;
95                 
96 //              Log_Debug("VTerm", "Magic Ctrl-Alt-0x%x", term->RawScancode);   
97
98                 switch(term->RawScancode)
99                 {
100                 // Scrolling
101                 case KEYSYM_PGUP:
102                         if( term->Flags & VT_FLAG_ALTBUF )
103                                 return ;
104                         term->ViewTopRow = MAX(0, term->ViewTopRow - 1);
105                         VT_int_UpdateScreen(term, 1);
106                         return;
107                 case KEYSYM_PGDN:
108                         if( term->Flags & VT_FLAG_ALTBUF )
109                                 return ;
110                         // Note the lack of giVT_Scrollback+1, view top can't go above size-onescreen
111                         term->ViewTopRow = MIN(term->ViewTopRow + 1, term->Height * giVT_Scrollback);
112                         VT_int_UpdateScreen(term, 1);
113                         return;
114                 }
115                 break;
116         }
117         
118         // Encode key
119         if(term->Mode == PTYBUFFMT_TEXT)
120         {
121                 Uint8   buf[6] = {0};
122                  int    len = 0;
123         
124                 // Ignore anything that isn't a press or refire
125                 if( (Codepoint & KEY_ACTION_MASK) != KEY_ACTION_PRESS
126                  && (Codepoint & KEY_ACTION_MASK) != KEY_ACTION_REFIRE
127                     )
128                 {
129                         return ;
130                 }
131         
132                 Codepoint &= KEY_CODEPOINT_MASK;
133
134                 // Get UTF-8/ANSI Encoding
135                 if( Codepoint == 0 )
136                 {
137                         // Non-printable keys
138                         switch(term->RawScancode)
139                         {
140                         case KEYSYM_LEFTARROW:
141                         case KEYSYM_KP4:
142                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'D';
143                                 len = 3;
144                                 break;
145                         case KEYSYM_RIGHTARROW:
146                         case KEYSYM_KP6:
147                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'C';
148                                 len = 3;
149                                 break;
150                         case KEYSYM_UPARROW:
151                         case KEYSYM_KP8:
152                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'A';
153                                 len = 3;
154                                 break;
155                         case KEYSYM_DOWNARROW:
156                         case KEYSYM_KP2:
157                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'B';
158                                 len = 3;
159                                 break;
160                         
161                         case KEYSYM_PGUP:
162                         case KEYSYM_KP9:        // If Codepoint=0, It's page up
163                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = '5'; buf[3] = '~';
164                                 len = 4;
165                                 break;
166                         case KEYSYM_PGDN:
167                         case KEYSYM_KP3:        // If Codepoint=0, It's page down
168                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = '6'; buf[3] = '~';
169                                 len = 4;
170                                 break;
171                         
172                         case KEYSYM_HOME:
173                         case KEYSYM_KP7:        // Codepoint==0, then it's home (not translated)
174                                 buf[0] = '\x1B'; buf[1] = 'O'; buf[2] = 'H';
175                                 len = 3;
176                                 break;
177                         case KEYSYM_END:
178                         case KEYSYM_KP1:        // You get the drill
179                                 buf[0] = '\x1B'; buf[1] = 'O'; buf[2] = 'F';
180                                 len = 3;
181                                 break;
182                         
183                         case KEYSYM_INSERT:
184                         case KEYSYM_KP0:        // See above
185                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = '2'; buf[3] = '~';
186                                 len = 4;
187                                 break;
188                         case KEYSYM_DELETE:
189                         case KEYSYM_KPPERIOD:   // Are you that dumb? Look up
190                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = '3'; buf[3] = '~';
191                                 len = 4;
192                                 break;
193                         }
194                 }
195                 else if( gbVT_CtrlDown )
196                 {
197                         len = 1;
198                         switch( term->RawScancode )
199                         {
200                         case KEYSYM_2:
201                                 buf[0] = '\0';
202                                 break;
203                         case KEYSYM_3 ... KEYSYM_7:
204                                 buf[0] = 0x1b + (term->RawScancode - KEYSYM_3);
205                                 break;
206                         case KEYSYM_8:
207                                 buf[0] = 0x7f;
208                                 break;
209                         // - Ctrl-A = \1, Ctrl-Z = \x1a
210                         case KEYSYM_a ... KEYSYM_z:
211                                 buf[0] = 0x01 + (term->RawScancode - KEYSYM_a);
212                                 break;
213                         default:
214                                 goto utf_encode;
215                         }
216                 }
217                 else
218                 {
219                 utf_encode:
220                         // Attempt to encode in UTF-8
221                         len = WriteUTF8( buf, Codepoint );
222                         if(len == 0) {
223                                 Warning("Codepoint (%x) is unrepresentable in UTF-8", Codepoint);
224                         }
225                 }
226                 
227                 if(len == 0) {
228                         // Unprintable / Don't Pass
229                         return;
230                 }
231
232                 PTY_SendInput(term->PTY, (void*)buf, len);
233         }
234         else
235         {
236                 PTY_SendInput(term->PTY, (void*)&Codepoint, sizeof(Codepoint));
237         }
238 }
239

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