Kernel - Slight reworks to timer code
[tpg/acess2.git] / 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_RELEASE:
49                 switch(Codepoint & KEY_CODEPOINT_MASK)
50                 {
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;
55                 }
56                 break;
57         
58         case KEY_ACTION_PRESS:
59                 switch(Codepoint & KEY_CODEPOINT_MASK)
60                 {
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;
65                 }
66                 
67                 if(!gbVT_AltDown || !gbVT_CtrlDown)
68                         break;
69                 switch(Codepoint & KEY_CODEPOINT_MASK)
70                 {
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;
83                 }
84                 
85                 // Scrolling is only valid in text mode
86                 if(gpVT_CurTerm->Mode != TERM_MODE_TEXT)
87                         break;
88                 
89                 switch(Codepoint & KEY_CODEPOINT_MASK)
90                 {
91                 // Scrolling
92                 case KEY_PGUP:
93                         if( gpVT_CurTerm->Flags & VT_FLAG_ALTBUF )
94                                 return ;
95                         gpVT_CurTerm->ViewPos = MAX(
96                                 0,
97                                 gpVT_CurTerm->ViewPos - gpVT_CurTerm->Width
98                                 );
99                         return;
100                 case KEY_PGDOWN:
101                         if( gpVT_CurTerm->Flags & VT_FLAG_ALTBUF )
102                                 return ;
103                         gpVT_CurTerm->ViewPos = MIN(
104                                 gpVT_CurTerm->ViewPos + gpVT_CurTerm->Width,
105                                 gpVT_CurTerm->Width * gpVT_CurTerm->Height*giVT_Scrollback
106                                 );
107                         return;
108                 }
109                 break;
110         }
111         
112         // Encode key
113         if(term->Mode == TERM_MODE_TEXT)
114         {
115                 Uint8   buf[6] = {0};
116                  int    len = 0;
117         
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
121                     )
122                 {
123                         return ;
124                 }
125         
126                 Codepoint &= KEY_CODEPOINT_MASK;
127
128                 // Ignore Modifer Keys
129                 if(Codepoint > KEY_MODIFIERS)   return;
130                 
131                 // Get UTF-8/ANSI Encoding
132                 switch(Codepoint)
133                 {
134                 // 0: No translation, don't send to user
135                 case 0: break;
136                 case KEY_LEFT:
137                         buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'D';
138                         len = 3;
139                         break;
140                 case KEY_RIGHT:
141                         buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'C';
142                         len = 3;
143                         break;
144                 case KEY_UP:
145                         buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'A';
146                         len = 3;
147                         break;
148                 case KEY_DOWN:
149                         buf[0] = '\x1B'; buf[1] = '['; buf[2] = 'B';
150                         len = 3;
151                         break;
152                 
153                 case KEY_PGUP:
154                         buf[0] = '\x1B'; buf[1] = '['; buf[2] = '5'; buf[3] = '~';
155                         len = 4;
156                         break;
157                 case KEY_PGDOWN:
158                         buf[0] = '\x1B'; buf[1] = '['; buf[2] = '6'; buf[3] = '~';
159                         len = 4;
160                         break;
161                 
162                 // Attempt to encode in UTF-8
163                 default:
164                         len = WriteUTF8( buf, Codepoint );
165                         if(len == 0) {
166                                 Warning("Codepoint (%x) is unrepresentable in UTF-8", Codepoint);
167                         }
168                         break;
169                 }
170                 
171                 if(len == 0) {
172                         // Unprintable / Don't Pass
173                         return;
174                 }
175
176 #if 0
177                 // Handle meta characters
178                 if( !(term->Flags & VT_FLAG_RAWIN) )
179                 {
180                         switch(buf[0])
181                         {
182                         case '\3':      // ^C
183                                 
184                                 break;
185                         }
186                 }
187 #endif
188                 
189                 // Write
190                 if( MAX_INPUT_CHARS8 - term->InputWrite >= len )
191                         memcpy( &term->InputBuffer[term->InputWrite], buf, len );
192                 else {
193                         memcpy( &term->InputBuffer[term->InputWrite], buf, MAX_INPUT_CHARS8 - term->InputWrite );
194                         memcpy( &term->InputBuffer[0], buf, len - (MAX_INPUT_CHARS8 - term->InputWrite) );
195                 }
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;
202                 }
203         }
204         else
205         {
206                 // Encode the raw key event
207                 Uint32  *raw_in = (void*)term->InputBuffer;
208         
209                 #if 0
210                 // Drop new keys
211                 if( term->InputWrite == term->InputRead )
212                         return ;                
213                 #endif
214
215                 raw_in[ term->InputWrite ] = Codepoint;
216                 term->InputWrite ++;
217                 if(term->InputWrite >= MAX_INPUT_CHARS32)
218                         term->InputWrite -= MAX_INPUT_CHARS32;
219                 
220                 #if 1
221                 // TODO: Should old or new be dropped?
222                 if(term->InputRead == term->InputWrite) {
223                         term->InputRead ++;
224                         if( term->InputRead >= MAX_INPUT_CHARS32 )
225                                 term->InputRead -= MAX_INPUT_CHARS32;
226                 }
227                 #endif
228         }
229         
230         VFS_MarkAvaliable(&term->Node, 1);
231 }
232

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