20e47db053031f00cd1d901ad950731ab07d0882
[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
11 // === GLOBALS ===
12 // --- Key States --- (Used for VT Switching/Magic Combos)
13  int    gbVT_CtrlDown = 0;
14  int    gbVT_AltDown = 0;
15  int    gbVT_SysrqDown = 0;
16
17 // === CODE ===
18 /**
19  * \fn void VT_InitInput()
20  * \brief Initialises the input
21  */
22 void VT_InitInput()
23 {
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);
27                 return ;
28         }
29         VFS_IOCtl(giVT_InputDevHandle, KB_IOCTL_SETCALLBACK, VT_KBCallBack);
30 }
31
32 /**
33  * \fn void VT_KBCallBack(Uint32 Codepoint)
34  * \brief Called on keyboard interrupt
35  * \param Codepoint     Pseudo-UTF32 character
36  * 
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.
40  */
41 void VT_KBCallBack(Uint32 Codepoint)
42 {
43         tVTerm  *term = gpVT_CurTerm;
44
45         // Catch VT binds
46         switch( Codepoint & KEY_ACTION_MASK )
47         {
48         case KEY_ACTION_RAWSYM:
49                 term->RawScancode = Codepoint & KEY_CODEPOINT_MASK;
50                 break;
51         case KEY_ACTION_RELEASE:
52                 switch(term->RawScancode)
53                 {
54                 case KEYSYM_LEFTALT:    gbVT_AltDown &= ~1;     break;
55                 case KEYSYM_RIGHTALT:   gbVT_AltDown &= ~2;     break;
56                 case KEYSYM_LEFTCTRL:   gbVT_CtrlDown &= ~1;    break;
57                 case KEYSYM_RIGHTCTRL:  gbVT_CtrlDown &= ~2;    break;
58                 }
59                 break;
60         
61         case KEY_ACTION_PRESS:
62                 switch(term->RawScancode)
63                 {
64                 case KEYSYM_LEFTALT:    gbVT_AltDown |= 1;      break;
65                 case KEYSYM_RIGHTALT:   gbVT_AltDown |= 2;      break;
66                 case KEYSYM_LEFTCTRL:   gbVT_CtrlDown |= 1;     break;
67                 case KEYSYM_RIGHTCTRL:  gbVT_CtrlDown |= 2;     break;
68                 }
69                 
70                 // Check if the magic keys are held
71                 if(!gbVT_AltDown || !gbVT_CtrlDown)
72                         break;
73                 
74                 switch(term->RawScancode)
75                 {
76                 case KEYSYM_F1 :        VT_SetTerminal(0);      return;
77                 case KEYSYM_F2 :        VT_SetTerminal(1);      return;
78                 case KEYSYM_F3 :        VT_SetTerminal(2);      return;
79                 case KEYSYM_F4 :        VT_SetTerminal(3);      return;
80                 case KEYSYM_F5 :        VT_SetTerminal(4);      return;
81                 case KEYSYM_F6 :        VT_SetTerminal(5);      return;
82                 case KEYSYM_F7 :        VT_SetTerminal(6);      return;
83                 case KEYSYM_F8 :        VT_SetTerminal(7);      return;
84                 case KEYSYM_F9 :        VT_SetTerminal(8);      return;
85                 case KEYSYM_F10:        VT_SetTerminal(9);      return;
86                 case KEYSYM_F11:        VT_SetTerminal(10);     return;
87                 case KEYSYM_F12:        VT_SetTerminal(11);     return;
88                 }
89                 
90                 // Scrolling is only valid in text mode
91                 if(term->Mode != TERM_MODE_TEXT)
92                         break;
93                 
94 //              Log_Debug("VTerm", "Magic Ctrl-Alt-0x%x", term->RawScancode);   
95
96                 switch(term->RawScancode)
97                 {
98                 // Scrolling
99                 case KEYSYM_PGUP:
100                         if( term->Flags & VT_FLAG_ALTBUF )
101                                 return ;
102                         term->ViewPos = MAX( 0, term->ViewPos - term->Width );
103                         VT_int_UpdateScreen(term, 1);
104                         return;
105                 case KEYSYM_PGDN:
106                         if( term->Flags & VT_FLAG_ALTBUF )
107                                 return ;
108                         term->ViewPos = MIN(
109                                 term->ViewPos + term->Width,
110                                 term->Width * term->Height * giVT_Scrollback
111                                 );
112                         VT_int_UpdateScreen(term, 1);
113                         return;
114                 }
115                 break;
116         }
117         
118         // Encode key
119         if(term->Mode == TERM_MODE_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                 // Ignore Modifer Keys
135                 if(Codepoint > KEY_MODIFIERS)   return;
136                 
137                 // Get UTF-8/ANSI Encoding
138                 if( Codepoint == 0 )
139                 {
140                         // Non-printable keys
141                         switch(term->RawScancode)
142                         {
143                         case KEYSYM_LEFTARROW:
144                         case KEYSYM_KP4:
145                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'D';
146                                 len = 3;
147                                 break;
148                         case KEYSYM_RIGHTARROW:
149                         case KEYSYM_KP6:
150                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'C';
151                                 len = 3;
152                                 break;
153                         case KEYSYM_UPARROW:
154                         case KEYSYM_KP8:
155                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'A';
156                                 len = 3;
157                                 break;
158                         case KEYSYM_DOWNARROW:
159                         case KEYSYM_KP2:
160                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'B';
161                                 len = 3;
162                                 break;
163                         
164                         case KEYSYM_PGUP:
165                         case KEYSYM_KP9:        // If Codepoint=0, It's page up
166                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = '5'; buf[3] = '~';
167                                 len = 4;
168                                 break;
169                         case KEYSYM_PGDN:
170                         case KEYSYM_KP3:        // If Codepoint=0, It's page down
171                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = '6'; buf[3] = '~';
172                                 len = 4;
173                                 break;
174                         
175                         case KEYSYM_HOME:
176                         case KEYSYM_KP7:
177                                 buf[0] = '\x1B'; buf[1] = 'O'; buf[2] = 'H';
178                                 len = 3;
179                                 break;
180                         case KEYSYM_END:
181                         case KEYSYM_KP1:
182                                 buf[0] = '\x1B'; buf[1] = 'O'; buf[2] = 'F';
183                                 len = 3;
184                                 break;
185                         
186                         case KEYSYM_INSERT:
187                         case KEYSYM_KP0:
188                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = '2'; buf[3] = '~';
189                                 len = 4;
190                                 break;
191                         case KEYSYM_DELETE:
192                         case KEYSYM_KPPERIOD:
193                                 buf[0] = '\x1B'; buf[1] = '['; buf[2] = '3'; buf[3] = '~';
194                                 len = 4;
195                                 break;
196                         }
197                 }
198                 else
199                 {
200                         // Attempt to encode in UTF-8
201                         len = WriteUTF8( buf, Codepoint );
202                         if(len == 0) {
203                                 Warning("Codepoint (%x) is unrepresentable in UTF-8", Codepoint);
204                         }
205                 }
206                 
207                 if(len == 0) {
208                         // Unprintable / Don't Pass
209                         return;
210                 }
211
212                 // TODO: Implement Ctrl-C etc
213 #if 0
214                 // Handle meta characters
215                 if( !(term->Flags & VT_FLAG_RAWIN) )
216                 {
217                         switch(buf[0])
218                         {
219                         case '\3':      // ^C
220                                 
221                                 break;
222                         }
223                 }
224 #endif
225                 
226                 // Write
227                 if( MAX_INPUT_CHARS8 - term->InputWrite >= len )
228                         memcpy( &term->InputBuffer[term->InputWrite], buf, len );
229                 else {
230                         memcpy( &term->InputBuffer[term->InputWrite], buf, MAX_INPUT_CHARS8 - term->InputWrite );
231                         memcpy( &term->InputBuffer[0], buf, len - (MAX_INPUT_CHARS8 - term->InputWrite) );
232                 }
233                 // Roll the buffer over
234                 term->InputWrite += len;
235                 term->InputWrite %= MAX_INPUT_CHARS8;
236                 if( (term->InputWrite - term->InputRead + MAX_INPUT_CHARS8)%MAX_INPUT_CHARS8 < len ) {
237                         term->InputRead = term->InputWrite + 1;
238                         term->InputRead %= MAX_INPUT_CHARS8;
239                 }
240         }
241         else
242         {
243                 // Encode the raw key event
244                 Uint32  *raw_in = (void*)term->InputBuffer;
245         
246                 #if 0
247                 // Drop new keys
248                 if( term->InputWrite == term->InputRead )
249                         return ;                
250                 #endif
251
252                 raw_in[ term->InputWrite ] = Codepoint;
253                 term->InputWrite ++;
254                 if(term->InputWrite >= MAX_INPUT_CHARS32)
255                         term->InputWrite -= MAX_INPUT_CHARS32;
256                 
257                 #if 1
258                 // TODO: Should old or new be dropped?
259                 if(term->InputRead == term->InputWrite) {
260                         term->InputRead ++;
261                         if( term->InputRead >= MAX_INPUT_CHARS32 )
262                                 term->InputRead -= MAX_INPUT_CHARS32;
263                 }
264                 #endif
265         }
266         
267         VFS_MarkAvaliable(&term->Node, 1);
268 }
269

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