7 |
7 |
8 from tuikit.driver import Driver |
8 from tuikit.driver import Driver |
9 |
9 |
10 |
10 |
11 class DriverCurses(Driver): |
11 class DriverCurses(Driver): |
12 xterm_codes = ( |
12 key_codes = ( |
13 (0x09, 'tab' ), |
13 (0x09, 'tab' ), |
14 (0x0a, 'enter' ), |
14 (0x0a, 'enter' ), |
15 (0x7f, 'backspace' ), |
15 (0x7f, 'backspace' ), |
16 (0x1b, 'escape' ), |
16 (0x1b, 'escape' ), |
17 (0x1b,0x4f,0x50, 'f1' ), |
17 (0x1b,0x4f,0x50, 'f1' ), # xterm |
18 (0x1b,0x4f,0x51, 'f2' ), |
18 (0x1b,0x4f,0x51, 'f2' ), # xterm |
19 (0x1b,0x4f,0x52, 'f3' ), |
19 (0x1b,0x4f,0x52, 'f3' ), # xterm |
20 (0x1b,0x4f,0x53, 'f4' ), |
20 (0x1b,0x4f,0x53, 'f4' ), # xterm |
21 (0x1b,0x5b,0x31,0x35,0x7e, 'f5' ), |
21 (0x1b,0x5b, 'CSI' ), # see csi_codes |
22 (0x1b,0x5b,0x31,0x37,0x7e, 'f6' ), |
22 ) |
23 (0x1b,0x5b,0x31,0x38,0x7e, 'f7' ), |
23 |
24 (0x1b,0x5b,0x31,0x39,0x7e, 'f8' ), |
24 # http://en.wikipedia.org/wiki/ANSI_escape_code |
25 (0x1b,0x5b,0x31,0x7e, 'home' ), # linux |
25 csi_codes = ( |
26 (0x1b,0x5b,0x32,0x30,0x7e, 'f9' ), |
26 # code param key name |
27 (0x1b,0x5b,0x32,0x31,0x7e, 'f10' ), |
27 (0x7e, 1, 'home' ), # linux |
28 (0x1b,0x5b,0x32,0x33,0x7e, 'f11' ), |
28 (0x7e, 2, 'insert' ), |
29 (0x1b,0x5b,0x32,0x34,0x7e, 'f12' ), |
29 (0x7e, 3, 'delete' ), |
30 (0x1b,0x5b,0x32,0x7e, 'insert' ), |
30 (0x7e, 4, 'end' ), # linux |
31 (0x1b,0x5b,0x33,0x7e, 'delete' ), |
31 (0x7e, 5, 'pageup' ), |
32 (0x1b,0x5b,0x34,0x7e, 'end' ), # linux |
32 (0x7e, 6, 'pagedown' ), |
33 (0x1b,0x5b,0x35,0x7e, 'pageup' ), |
33 (0x7e, 15, 'f5' ), |
34 (0x1b,0x5b,0x36,0x7e, 'pagedown' ), |
34 (0x7e, 17, 'f6' ), |
35 (0x1b,0x5b,0x41, 'up' ), |
35 (0x7e, 18, 'f7' ), |
36 (0x1b,0x5b,0x42, 'down' ), |
36 (0x7e, 19, 'f8' ), |
37 (0x1b,0x5b,0x43, 'right' ), |
37 (0x7e, 20, 'f9' ), |
38 (0x1b,0x5b,0x44, 'left' ), |
38 (0x7e, 21, 'f10' ), |
39 (0x1b,0x5b,0x46, 'end' ), |
39 (0x7e, 23, 'f11' ), |
40 (0x1b,0x5b,0x48, 'home' ), |
40 (0x7e, 24, 'f12' ), |
41 (0x1b,0x5b,0x4d, 'mouse' ), |
41 (0x41, 1, 'up' ), |
42 (0x1b,0x5b,0x5b,0x41, 'f1' ), # linux |
42 (0x42, 1, 'down' ), |
43 (0x1b,0x5b,0x5b,0x42, 'f2' ), # linux |
43 (0x43, 1, 'right' ), |
44 (0x1b,0x5b,0x5b,0x43, 'f3' ), # linux |
44 (0x44, 1, 'left' ), |
45 (0x1b,0x5b,0x5b,0x44, 'f4' ), # linux |
45 (0x46, 1, 'end' ), # xterm |
46 (0x1b,0x5b,0x5b,0x45, 'f5' ), # linux |
46 (0x48, 1, 'home' ), # xterm |
|
47 (0x4d, None, 'mouse' ), |
|
48 (0x5b,0x41, 1, 'f1' ), # linux |
|
49 (0x5b,0x42, 1, 'f2' ), # linux |
|
50 (0x5b,0x43, 1, 'f3' ), # linux |
|
51 (0x5b,0x44, 1, 'f4' ), # linux |
|
52 (0x5b,0x45, 1, 'f5' ), # linux |
47 ) |
53 ) |
48 |
54 |
49 color_map = { |
55 color_map = { |
50 'black' : curses.COLOR_BLACK, |
56 'black' : curses.COLOR_BLACK, |
51 'blue' : curses.COLOR_BLUE, |
57 'blue' : curses.COLOR_BLUE, |
411 else: |
416 else: |
412 raise Exception('Unknown mouse event: %x' % t) |
417 raise Exception('Unknown mouse event: %x' % t) |
413 |
418 |
414 return out |
419 return out |
415 |
420 |
|
421 def process_control_sequence(self): |
|
422 codes = self.csi_codes |
|
423 debug_seq = [0x1b, 0x5b] |
|
424 c = self.inputqueue_get_wait() |
|
425 debug_seq.append(c) |
|
426 |
|
427 # numeric parameters? |
|
428 params = [] |
|
429 if chr(c).isdigit(): |
|
430 params.append(chr(c)) |
|
431 while True: |
|
432 c = self.inputqueue_get_wait() |
|
433 debug_seq.append(c) |
|
434 if chr(c).isdigit(): |
|
435 params[-1] += chr(c) |
|
436 elif chr(c) == ';': |
|
437 params.append('') |
|
438 else: |
|
439 break |
|
440 params = [int(x) for x in params] |
|
441 if len(params) == 0: |
|
442 params = [1] |
|
443 |
|
444 # filter codes using |
|
445 while True: |
|
446 matching_codes = [] |
|
447 for code in codes: |
|
448 if len(code) > 2 and code[0] == c: |
|
449 matching_codes.append(code[1:]) |
|
450 codes = matching_codes |
|
451 |
|
452 if len(codes) == 0: |
|
453 # no match -> unknown code |
|
454 seq = ','.join(['0x%x' % x for x in debug_seq]) |
|
455 self.log.debug('Unknown control sequence: %s', seq) |
|
456 return [('keypress', 'Unknown:' + seq, None)] |
|
457 elif len(codes) == 1: |
|
458 # one match -> we got the winner |
|
459 break |
|
460 elif len(codes[0]) == 2: |
|
461 # more than one matching, but no more chars to check |
|
462 # will be sorted out using parameters |
|
463 break |
|
464 else: |
|
465 # more than one matching -> continue loop |
|
466 c = self.inputqueue_get_wait() |
|
467 debug_seq.append(c) |
|
468 |
|
469 # filter codes using first parameter |
|
470 matching_codes = [] |
|
471 for code in codes: |
|
472 if params[0] == code[0] or params[0] is None: |
|
473 matching_codes.append(code) |
|
474 |
|
475 if len(matching_codes) == 0: |
|
476 # no match -> unknown code |
|
477 seq = ','.join(['0x%x' % x for x in debug_seq]) |
|
478 self.log.debug('Unknown control sequence: %s', seq) |
|
479 return [('keypress', 'Unknown:' + seq, None)] |
|
480 |
|
481 if len(matching_codes) > 1: |
|
482 raise Exception('Internal error: invalid csi_codes, more than one matching') |
|
483 |
|
484 keyname = matching_codes[0][1] |
|
485 |
|
486 if keyname == 'mouse': |
|
487 return self.process_xterm_mouse() |
|
488 |
|
489 # modifiers |
|
490 mod = 0 |
|
491 if len(params) > 1: |
|
492 mod = params[1] - 1 |
|
493 |
|
494 return [('keypress', keyname, None, mod)] |
|
495 |
416 |
496 |
417 driverclass = DriverCurses |
497 driverclass = DriverCurses |
418 |
498 |