blob: 667c33a200d91088e7f0a3d2cd8132946c2e062e [file] [log] [blame]
adamdunkelsa2f3c422004-09-12 20:24:53 +00001/*
2 * Copyright (c) 2004, Adam Dunkels.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * This file is part of the Contiki operating system.
30 *
31 * Author: Adam Dunkels <adam@sics.se>
32 *
33 * $Id: ctk-term-in.c,v 1.2 2004/09/12 20:24:55 adamdunkels Exp $
34 */
adamdunkelsb9614dc2004-08-09 20:33:51 +000035#include <string.h>
36#include "ctk.h"
37#include "ctk-term.h"
38#include "ctk-term-int.h"
39#include "ctk-term-ascii.h"
40
41#define PRINTF(x)
42
43/*-----------------------------------------------------------------------------------*/
44/*
45 * #defines and enums
46 */
47/*-----------------------------------------------------------------------------------*/
48
49/* Size of input key buffer */
50#define NUMKEYS 20
51
52/* ANSI character classes */
53enum {ACC_C0, ACC_INTERM, ACC_PARAM, ACC_LOWCASE, ACC_UPCASE,ACC_C1, ACC_G1, ACC_DEL, ACC_SPEC };
54
55/*-----------------------------------------------------------------------------------*/
56/*
57 * Structures
58 */
59/*-----------------------------------------------------------------------------------*/
60
61/* Structure for mapping a character sequence to a key */
62struct seqmap
63{
64 const char* seq;
65 const ctk_arch_key_t key;
66};
67
68/*-----------------------------------------------------------------------------------*/
69/*
70 * Local variables
71 */
72/*-----------------------------------------------------------------------------------*/
73
74static ctk_arch_key_t keys[NUMKEYS];
75static int firstkey, lastkey;
76
77/* Sequences starting with ESC [ .... */
78const static struct seqmap ctrlmap[] =
79{
80 {"A",CH_CURS_UP},
81 {"B",CH_CURS_DOWN},
82 {"C",CH_CURS_RIGHT},
83 {"D",CH_CURS_LEFT},
84
85 {"11~",CH_F1},
86 {"12~",CH_F2},
87 {"13~",CH_F3},
88 {"14~",CH_F4},
89 // linux console
90 {"[A",CH_F1},
91 {"[B",CH_F2},
92 {"[C",CH_F3},
93 {"[D",CH_F4},
94 {0,0}
95};
96
97/* Sequences starting with ESC O .... */
98const static struct seqmap ss3map[] =
99{
100 {"A",CH_CURS_UP},
101 {"B",CH_CURS_DOWN},
102 {"C",CH_CURS_RIGHT},
103 {"D",CH_CURS_LEFT},
104 {"P",CH_F1},
105 {"Q",CH_F2},
106 {"R",CH_F3},
107 {"S",CH_F4},
108 {0,0}
109};
110
111
112/*-----------------------------------------------------------------------------------*/
113/*
114 * Add a key to the input buffer
115 */
116/*-----------------------------------------------------------------------------------*/
117static void
118enqueue_key(ctk_arch_key_t k)
119{
120 keys[lastkey] = k;
121 ++lastkey;
122 if(lastkey >= NUMKEYS) {
123 lastkey = 0;
124 }
125}
126
127/*-----------------------------------------------------------------------------------*/
128/*
129 * Classify a character
130 */
131/*-----------------------------------------------------------------------------------*/
132static unsigned char
133classify(unsigned char c)
134{
135 if (0x00 <= c && c <=0x1f) return ACC_C0;
136 if (0x20 <= c && c <=0x2f) return ACC_INTERM;
137 if (0x30 <= c && c <=0x3f) return ACC_PARAM;
138 if (0x40 <= c && c <=0x5f) return ACC_UPCASE;
139 if (0x60 <= c && c <=0x7e) return ACC_LOWCASE;
140 if (c == 0x7f) return ACC_DEL;
141 if (0x90 <= c && c <=0x9f) return ACC_C1;
142 if (c == 0xa0) return ACC_SPEC;
143 if (0xA1 <= c && c <=0xfe) return ACC_G1;
144 if (0x90 <= c && c <=0x9f) return ACC_C1;
145 if (c == 0xff) return ACC_SPEC;
146 return ACC_SPEC;
147}
148
149/*-----------------------------------------------------------------------------------*/
150/*
151 * Lookup a key sequence in a sequencemap and queue the key if sequence found
152 */
153/*-----------------------------------------------------------------------------------*/
154static void
155lookup_seq(const char* str, const struct seqmap* map)
156{
157 while (map->seq != 0) {
158 if (strcmp(str,map->seq) == 0) {
159 enqueue_key(map->key);
160 return;
161 }
162 map++;
163 }
164}
165
166/*-----------------------------------------------------------------------------------*/
167/* \internal
168 * Parse a character stream
169 * Returns -1 if c is consumed by the state machine 1 else.
170 */
171/*-----------------------------------------------------------------------------------*/
172static int
173parse_input(struct ctk_term_state* st, unsigned char c)
174{
175 unsigned char cl = classify(c);
176 int ret = -1;
177 switch(st->inputstate) {
178 case ANS_IDLE:
179 switch(cl) {
180 case ACC_C0:
181 {
182 switch(c) {
183 case ASCII_ESC: st->inputstate = ANS_ESCSEQ; break;
184 case ASCII_BS: enqueue_key(CH_DEL); break;
185 case ASCII_HT: enqueue_key(CH_TAB); break;
186 case ASCII_FF: ctk_term_redraw(st); break;
187 case ASCII_CR: enqueue_key(CH_ENTER); break;
188 }
189 }
190 break;
191
192 case ACC_INTERM:
193 case ACC_PARAM:
194 case ACC_LOWCASE:
195 case ACC_UPCASE:
196 case ACC_G1:
197 ret = 1;
198 break;
199 case ACC_C1:
200 if (c == ASCII_CSI) {
201 st->inputstate = ANS_CTRLSEQ;
202 st->ctrlCnt = 0;
203 }
204 else if (c == ASCII_SS3) {
205 st->inputstate = ANS_SS3;
206 st->ctrlCnt = 0;
207 }
208 break;
209 case ACC_DEL:
210 enqueue_key(CH_DEL);
211 break;
212 case ACC_SPEC:
213 break;
214 }
215 break;
216
217 case ANS_ESCSEQ:
218 {
219 switch(cl) {
220 case ACC_C0:
221 case ACC_DEL:
222 break;
223 case ACC_INTERM:
224 st->inputstate = ANS_ESCSEQ_1;
225 break;
226 case ACC_UPCASE:
227 /* C1 control character */
228 if (c == '[') {
229 st->inputstate = ANS_CTRLSEQ;
230 st->ctrlCnt = 0;
231 }
232 else if (c == 'O') {
233 st->inputstate = ANS_SS3;
234 st->ctrlCnt = 0;
235 }
236 else {
237 st->inputstate = ANS_IDLE;
238 }
239 break;
240 case ACC_PARAM:
241 /* Private 2-character sequence */
242 case ACC_LOWCASE:
243 /* Standard 2-character sequence */
244 default:
245 st->inputstate = ANS_IDLE;
246 break;
247 }
248 }
249 break;
250
251 case ANS_ESCSEQ_1:
252 {
253 switch(cl) {
254 case ACC_C0:
255 case ACC_INTERM:
256 break;
257 case ACC_PARAM:
258 /* Private function*/
259 case ACC_LOWCASE:
260 case ACC_UPCASE:
261 /* Standard function */
262 default:
263 st->inputstate = ANS_IDLE;
264 break;
265 }
266 }
267 break;
268 case ANS_SS3:
269 {
270 switch(cl) {
271 case ACC_PARAM:
272 if (st->ctrlCnt < CTK_TERM_CTRLBUFLEN) st->ctrlbuf[st->ctrlCnt++]=c;
273 break;
274 case ACC_UPCASE:
275 /* VT100 PF seq */
276 if (st->ctrlCnt < CTK_TERM_CTRLBUFLEN) st->ctrlbuf[st->ctrlCnt++]=c;
277 st->inputstate = ANS_IDLE;
278 st->ctrlbuf[st->ctrlCnt] = 0;
279 lookup_seq((const char*)(st->ctrlbuf), ss3map);
280 break;
281 default:
282 st->inputstate = ANS_IDLE;
283 break;
284 }
285 }
286 break;
287 case ANS_CTRLSEQ:
288 {
289 switch(cl) {
290 case ACC_C0:
291 break;
292 case ACC_INTERM:
293 case ACC_PARAM:
294 if (st->ctrlCnt < CTK_TERM_CTRLBUFLEN) st->ctrlbuf[st->ctrlCnt++]=c;
295 break;
296 case ACC_LOWCASE:
297 case ACC_UPCASE:
298 /* Standard control sequence */
299 if (st->ctrlCnt < CTK_TERM_CTRLBUFLEN) st->ctrlbuf[st->ctrlCnt++]=c;
300 /* Cygwin console sends ESC [ [ A for function keys */
301 if (c != '[') {
302 st->ctrlbuf[st->ctrlCnt] = 0;
303 lookup_seq((const char*)(st->ctrlbuf), ctrlmap);
304 st->inputstate = ANS_IDLE;
305 }
306 break;
307 default:
308 st->inputstate = ANS_IDLE;
309 break;
310 }
311 }
312 break;
313 }
314 return ret;
315}
316
317/*-----------------------------------------------------------------------------------*/
318/*
319 * Initialize the input buffer
320 */
321/*-----------------------------------------------------------------------------------*/
322void ctk_term_input_init()
323{
324 firstkey = lastkey = 0;
325}
326
327/*-----------------------------------------------------------------------------------*/
328/**
329 * Handles an input character provided by the client
330 *
331 * \param ts State information
332 * \param b Input character
333 */
334/*-----------------------------------------------------------------------------------*/
335void ctk_term_input(struct ctk_term_state* ts, unsigned char b)
336{
337 int ret = parse_input(ts, b);
338 PRINTF(("terminput: 0x%02x\n", b));
339 if (ret > 0) {
340 enqueue_key((ctk_arch_key_t)b);
341 }
342}
343
344/*-----------------------------------------------------------------------------------*/
345/**
346 * Checks the key press input queue to see if there are pending
347 * keys. Called by the CTK module.
348 *
349 * \return Zero if no key presses are in buffer, non-zero if there are
350 * key presses in input buffer.
351 */
352/*-----------------------------------------------------------------------------------*/
353unsigned char
354ctk_arch_keyavail(void)
355{
356 return firstkey != lastkey;
357}
358/*-----------------------------------------------------------------------------------*/
359/**
360 * Retrieves key presses from the VNC client. Called by the CTK
361 * module.
362 *
363 * \return The next key in the input queue.
364 */
365/*-----------------------------------------------------------------------------------*/
366ctk_arch_key_t
367ctk_arch_getkey(void)
368{
369 ctk_arch_key_t key;
370 key = keys[firstkey];
371
372 if(firstkey != lastkey) {
373 ++firstkey;
374 if(firstkey >= NUMKEYS) {
375 firstkey = 0;
376 }
377 }
378
379 return key;
380}
381