1 /* TN5250 - An implementation of the 5250 telnet protocol.
2  * Copyright (C) 1997-2008 Michael Madore
3  *
4  * This file is part of TN5250.
5  *
6  * TN5250 is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1, or (at your option)
9  * any later version.
10  *
11  * TN5250 is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this software; see the file COPYING.  If not, write to
18  * the Free Software Foundation, Inc., 59 Temple Place, Suite 330,
19  * Boston, MA 02111-1307 USA
20  *
21  */
22 #define _TN5250_TERMINAL_PRIVATE_DEFINED
23 #include "tn5250-private.h"
24 #include "slangterm.h"
25 
26 #if USE_SLANG
27 
28 /* Mapping of 5250 colors to curses colors */
29 #define A_5250_WHITE    0x100
30 #define A_5250_RED      0x200
31 #define A_5250_TURQ     0x300
32 #define A_5250_YELLOW   0x400
33 #define A_5250_PINK     0x500
34 #define A_5250_BLUE     0x600
35 #define A_5250_BLACK	0x700
36 #define A_5250_GREEN    0x800
37 
38 #define A_COLOR_MASK	0xf00
39 
40 #define A_REVERSE	0x1000
41 #define A_UNDERLINE	0x2000
42 #define A_BLINK		0x4000
43 #define A_VERTICAL	0x8000
44 
45 static int attribute_map[] =
46 {A_5250_GREEN,
47  A_5250_GREEN | A_REVERSE,
48  A_5250_WHITE,
49  A_5250_WHITE | A_REVERSE,
50  A_5250_GREEN | A_UNDERLINE,
51  A_5250_GREEN | A_UNDERLINE | A_REVERSE,
52  A_5250_WHITE | A_UNDERLINE,
53  0x00,
54  A_5250_RED,
55  A_5250_RED | A_REVERSE,
56  A_5250_RED | A_BLINK,
57  A_5250_RED | A_BLINK | A_REVERSE,
58  A_5250_RED | A_UNDERLINE,
59  A_5250_RED | A_UNDERLINE | A_REVERSE,
60  A_5250_RED | A_UNDERLINE | A_BLINK,
61  0x00,
62  A_5250_TURQ | A_VERTICAL,
63  A_5250_TURQ | A_VERTICAL | A_REVERSE,
64  A_5250_YELLOW | A_VERTICAL,
65  A_5250_YELLOW | A_VERTICAL | A_REVERSE,
66  A_5250_TURQ | A_UNDERLINE | A_VERTICAL,
67  A_5250_TURQ | A_UNDERLINE | A_REVERSE | A_VERTICAL,
68  A_5250_YELLOW | A_UNDERLINE | A_VERTICAL,
69  0x00,
70  A_5250_PINK,
71  A_5250_PINK | A_REVERSE,
72  A_5250_BLUE,
73  A_5250_BLUE | A_REVERSE,
74  A_5250_PINK | A_UNDERLINE,
75  A_5250_PINK | A_UNDERLINE | A_REVERSE,
76  A_5250_BLUE | A_UNDERLINE,
77  0x00};
78 
79 static void slang_terminal_init(Tn5250Terminal * This);
80 static void slang_terminal_term(Tn5250Terminal * This);
81 static void slang_terminal_destroy(Tn5250Terminal /*@only@*/ * This);
82 static int slang_terminal_width(Tn5250Terminal * This);
83 static int slang_terminal_height(Tn5250Terminal * This);
84 static int slang_terminal_flags(Tn5250Terminal * This);
85 static void slang_terminal_update(Tn5250Terminal * This,
86 				   Tn5250Display * display);
87 static void slang_terminal_update_indicators(Tn5250Terminal * This,
88 					      Tn5250Display *display);
89 static int slang_terminal_waitevent(Tn5250Terminal * This);
90 static int slang_terminal_getkey(Tn5250Terminal * This);
91 static void slang_terminal_beep(Tn5250Terminal * This);
92 static int slang_terminal_enhanced (Tn5250Terminal * This);
93 static int slang_terminal_get_esc_key(Tn5250Terminal * This, int is_esc);
94 static void slang_terminal_set_attrs (Tn5250Terminal * This, int attrs);
95 
96 struct _Tn5250TerminalPrivate {
97    int quit_flag;
98    int last_width, last_height;
99    int attrs;
100 };
101 
102 /****f* lib5250/tn5250_slang_terminal_new
103  * NAME
104  *    tn5250_slang_terminal_new
105  * SYNOPSIS
106  *    ret = tn5250_slang_terminal_new ();
107  * INPUTS
108  *    None
109  * DESCRIPTION
110  *    Create a new curses terminal object.
111  *****/
tn5250_slang_terminal_new()112 Tn5250Terminal *tn5250_slang_terminal_new()
113 {
114    Tn5250Terminal *r = tn5250_new(Tn5250Terminal, 1);
115    if (r == NULL)
116       return NULL;
117 
118    r->data = tn5250_new(struct _Tn5250TerminalPrivate, 1);
119    if (r->data == NULL) {
120       free(r);
121       return NULL;
122    }
123 
124    r->data->quit_flag = 0;
125    r->data->last_width = 0;
126    r->data->last_height = 0;
127    r->data->attrs = 0;
128 
129    r->conn_fd = -1;
130    r->init = slang_terminal_init;
131    r->term = slang_terminal_term;
132    r->destroy = slang_terminal_destroy;
133    r->width = slang_terminal_width;
134    r->height = slang_terminal_height;
135    r->flags = slang_terminal_flags;
136    r->update = slang_terminal_update;
137    r->update_indicators = slang_terminal_update_indicators;
138    r->waitevent = slang_terminal_waitevent;
139    r->getkey = slang_terminal_getkey;
140    r->putkey = NULL;
141    r->beep = slang_terminal_beep;
142    r->flags = slang_terminal_enhanced;
143    return r;
144 }
145 
146 /****i* lib5250/slang_terminal_init
147  * NAME
148  *    slang_terminal_init
149  * SYNOPSIS
150  *    slang_terminal_init (This);
151  * INPUTS
152  *    Tn5250Terminal *     This       -
153  * DESCRIPTION
154  *    DOCUMENT ME!!!
155  *****/
slang_terminal_init(Tn5250Terminal * This)156 static void slang_terminal_init(Tn5250Terminal * This)
157 {
158    SLtt_get_terminfo ();
159    if (-1 == SLkp_init ()) {
160       SLang_doerror ("SLkp_init failed.");
161       exit (255);
162    }
163    if (-1 == SLang_init_tty (K_CTRL('Q'), 1, 0)) {
164       SLang_doerror ("SLang_init_tty failed.");
165       exit (255);
166    }
167    SLang_set_abort_signal (NULL);
168    if (-1 == SLsmg_init_smg ()) {
169       SLang_doerror ("SLsmg_init_smg failed.");
170       exit (255);
171    }
172 
173    SLtt_set_color_fgbg (1, SLSMG_COLOR_BRIGHT_WHITE, SLSMG_COLOR_BLACK);
174    SLtt_set_color_fgbg (2, SLSMG_COLOR_RED, SLSMG_COLOR_BLACK);
175    SLtt_set_color_fgbg (3, SLSMG_COLOR_BLUE, SLSMG_COLOR_BLACK);
176    SLtt_set_color_fgbg (4, SLSMG_COLOR_BRIGHT_BROWN, SLSMG_COLOR_BLACK);
177    SLtt_set_color_fgbg (5, SLSMG_COLOR_BRIGHT_MAGENTA, SLSMG_COLOR_BLACK);
178    SLtt_set_color_fgbg (6, SLSMG_COLOR_BRIGHT_BLUE, SLSMG_COLOR_BLACK);
179    SLtt_set_color_fgbg (7, SLSMG_COLOR_BLACK, SLSMG_COLOR_BLACK);
180    SLtt_set_color_fgbg (8, SLSMG_COLOR_GREEN, SLSMG_COLOR_BLACK);
181 
182    SLsmg_cls ();
183    SLsmg_refresh ();
184    This->data->quit_flag = 0;
185 }
186 
187 /****i* lib5250/slang_terminal_term
188  * NAME
189  *    slang_terminal_term
190  * SYNOPSIS
191  *    slang_terminal_term (This);
192  * INPUTS
193  *    Tn5250Terminal *     This       -
194  * DESCRIPTION
195  *    DOCUMENT ME!!!
196  *****/
slang_terminal_term(Tn5250Terminal * This)197 static void slang_terminal_term(Tn5250Terminal * This)
198 {
199    SLsmg_reset_smg ();
200    SLang_reset_tty ();
201 }
202 
203 /****i* lib5250/slang_terminal_destroy
204  * NAME
205  *    slang_terminal_destroy
206  * SYNOPSIS
207  *    slang_terminal_destroy (This);
208  * INPUTS
209  *    Tn5250Terminal *     This       -
210  * DESCRIPTION
211  *    DOCUMENT ME!!!
212  *****/
slang_terminal_destroy(Tn5250Terminal * This)213 static void slang_terminal_destroy(Tn5250Terminal * This)
214 {
215    if (This->data != NULL)
216       free(This->data);
217    free(This);
218 }
219 
220 /****i* lib5250/slang_terminal_width
221  * NAME
222  *    slang_terminal_width
223  * SYNOPSIS
224  *    ret = slang_terminal_width (This);
225  * INPUTS
226  *    Tn5250Terminal  *    This       -
227  * DESCRIPTION
228  *    DOCUMENT ME!!!
229  *****/
slang_terminal_width(Tn5250Terminal * This)230 static int slang_terminal_width(Tn5250Terminal /*@unused@*/ * This)
231 {
232    SLtt_get_screen_size();
233    return SLtt_Screen_Cols;
234 }
235 
236 /****i* lib5250/slang_terminal_height
237  * NAME
238  *    slang_terminal_height
239  * SYNOPSIS
240  *    ret = slang_terminal_height (This);
241  * INPUTS
242  *    Tn5250Terminal  *    This       -
243  * DESCRIPTION
244  *    DOCUMENT ME!!!
245  *****/
slang_terminal_height(Tn5250Terminal * This)246 static int slang_terminal_height(Tn5250Terminal /*@unused@*/ * This)
247 {
248    SLtt_get_screen_size();
249    return SLtt_Screen_Rows;
250 }
251 
252 /****i* lib5250/slang_terminal_flags
253  * NAME
254  *    slang_terminal_flags
255  * SYNOPSIS
256  *    ret = slang_terminal_flags (This);
257  * INPUTS
258  *    Tn5250Terminal  *    This       -
259  * DESCRIPTION
260  *    DOCUMENT ME!!!
261  *****/
slang_terminal_flags(Tn5250Terminal * This)262 static int slang_terminal_flags(Tn5250Terminal /*@unused@*/ * This)
263 {
264    int f = 0;
265    if (SLtt_Use_Ansi_Colors)
266       f |= TN5250_TERMINAL_HAS_COLOR;
267    return f;
268 }
269 
270 /****i* lib5250/slang_terminal_update
271  * NAME
272  *    slang_terminal_update
273  * SYNOPSIS
274  *    slang_terminal_update (This, display);
275  * INPUTS
276  *    Tn5250Terminal *     This       -
277  *    Tn5250Display *      display    -
278  * DESCRIPTION
279  *    DOCUMENT ME!!!
280  *****/
slang_terminal_update(Tn5250Terminal * This,Tn5250Display * display)281 static void slang_terminal_update(Tn5250Terminal * This, Tn5250Display * display)
282 {
283    int my, mx;
284    int y, x;
285    int curs_attr, temp_attr;
286    unsigned char a = 0x20, c;
287 
288    if (This->data->last_width != tn5250_display_width(display)
289        || This->data->last_height != tn5250_display_height(display)) {
290       SLsmg_cls ();
291       This->data->last_width = tn5250_display_width(display);
292       This->data->last_height = tn5250_display_height(display);
293       slang_terminal_update_indicators(This, display);
294    }
295    SLsmg_normal_video ();
296    my = SLtt_Screen_Rows - 1;
297    mx = SLtt_Screen_Cols - 1;
298    for (y = 0; y < tn5250_display_height(display); y++) {
299       if (y > my)
300 	 break;
301 
302       SLsmg_gotorc (y, 0);
303       for (x = 0; x < tn5250_display_width(display); x++) {
304 	 c = tn5250_display_char_at(display, y, x);
305 	 if ((c & 0xe0) == 0x20) {	/* ATTRIBUTE */
306 	    a = (c & 0xff);
307 	    temp_attr = This->data->attrs;
308 	    slang_terminal_set_attrs (This, attribute_map[0]);
309 	    SLsmg_write_char (' ');
310 	    slang_terminal_set_attrs (This, temp_attr);
311 	 } else {		/* DATA */
312 	    curs_attr = attribute_map[a - 0x20];
313 	    if (curs_attr == 0x00) {	/* NONDISPLAY */
314 	       temp_attr = This->data->attrs;
315 	       slang_terminal_set_attrs (This, attribute_map[0]);
316 	       SLsmg_write_char (' ');
317 	       slang_terminal_set_attrs (This, temp_attr);
318 	    } else {
319 	       c = tn5250_char_map_to_local (tn5250_display_char_map (display), c);
320 	       if ((c < 0x20 && c > 0x00) || c >= 0x7f) { /* UNPRINTABLE */
321 		  c = ' ';
322 		  curs_attr ^= A_REVERSE;
323 	       }
324 	       if ((curs_attr & A_VERTICAL) != 0) {
325 		  curs_attr |= A_UNDERLINE;
326 		  curs_attr &= ~A_VERTICAL;
327 	       }
328 	       /* This is a kludge since vga hardware doesn't support under-
329 	        * lining characters.  It's pretty ugly. */
330 	       if ((curs_attr & A_UNDERLINE) != 0) {
331 		  curs_attr &= ~A_UNDERLINE;
332 		  if (c == ' ')
333 		     c = '_';
334 	       }
335 	       slang_terminal_set_attrs (This, curs_attr);
336 	       SLsmg_write_char (c);
337 	    }
338 	 }			/* if ((c & 0xe0) ... */
339       }				/* for (int x ... */
340    }				/* for (int y ... */
341 
342    SLsmg_gotorc (tn5250_display_cursor_y(display), tn5250_display_cursor_x(display));
343    SLsmg_refresh();
344 }
345 
346 /****i* lib5250/slang_terminal_update_indicators
347  * NAME
348  *    slang_terminal_update_indicators
349  * SYNOPSIS
350  *    slang_terminal_update_indicators (This, display);
351  * INPUTS
352  *    Tn5250Terminal *     This       -
353  *    Tn5250Display *      display    -
354  * DESCRIPTION
355  *    DOCUMENT ME!!!
356  *****/
slang_terminal_update_indicators(Tn5250Terminal * This,Tn5250Display * display)357 static void slang_terminal_update_indicators(Tn5250Terminal * This, Tn5250Display * display)
358 {
359    int inds = tn5250_display_indicators(display);
360    char ind_buf[80];
361 
362    memset(ind_buf, ' ', sizeof(ind_buf));
363    memcpy(ind_buf, "5250", 4);
364    if ((inds & TN5250_DISPLAY_IND_MESSAGE_WAITING) != 0) {
365       memcpy(ind_buf + 23, "MW", 2);
366    }
367    if ((inds & TN5250_DISPLAY_IND_INHIBIT) != 0) {
368       memcpy(ind_buf + 9, "X II", 4);
369    } else if ((inds & TN5250_DISPLAY_IND_X_CLOCK) != 0) {
370       memcpy(ind_buf + 9, "X CLOCK", 7);
371    } else if ((inds & TN5250_DISPLAY_IND_X_SYSTEM) != 0) {
372       memcpy(ind_buf + 9, "X SYSTEM", 8);
373    }
374    if ((inds & TN5250_DISPLAY_IND_INSERT) != 0) {
375       memcpy(ind_buf + 30, "IM", 2);
376    }
377    if ((inds & TN5250_DISPLAY_IND_MACRO) != 0) {
378       memcpy(ind_buf + 54, tn5250_macro_printstate (display), 11);
379    }
380    SLsmg_normal_video ();
381    SLsmg_gotorc (tn5250_display_height (display), 0);
382    SLsmg_write_nchars (ind_buf, 80);
383    SLsmg_gotorc (tn5250_display_cursor_y(display), tn5250_display_cursor_x(display));
384    SLsmg_refresh();
385 }
386 
387 /****i* lib5250/slang_terminal_waitevent
388  * NAME
389  *    slang_terminal_waitevent
390  * SYNOPSIS
391  *    ret = slang_terminal_waitevent (This);
392  * INPUTS
393  *    Tn5250Terminal *     This       -
394  * DESCRIPTION
395  *    DOCUMENT ME!!!
396  *****/
slang_terminal_waitevent(Tn5250Terminal * This)397 static int slang_terminal_waitevent(Tn5250Terminal * This)
398 {
399 #if !defined(WIN32) && !defined(WINE)
400    fd_set fdr;
401    int result = 0;
402    int sm;
403 
404    if (SLang_Error == USER_BREAK)
405       This->data->quit_flag = 1;
406    if (This->data->quit_flag)
407       return TN5250_TERMINAL_EVENT_QUIT;
408 
409    FD_ZERO(&fdr);
410    FD_SET(0, &fdr);
411    sm = 1;
412    if (This->conn_fd >= 0) {
413       FD_SET(This->conn_fd, &fdr);
414       sm = This->conn_fd + 1;
415    }
416 
417    select(sm, &fdr, NULL, NULL, NULL);
418 
419    if (FD_ISSET(0, &fdr))
420       result |= TN5250_TERMINAL_EVENT_KEY;
421 
422    if (This->conn_fd >= 0 && FD_ISSET(This->conn_fd, &fdr))
423       result |= TN5250_TERMINAL_EVENT_DATA;
424 
425    return result;
426 #else
427    /* XXX: WIN32/WINE - need to do this using WaitForMultipleObjects */
428 #endif
429 }
430 
431 /****i* lib5250/slang_terminal_getkey
432  * NAME
433  *    slang_terminal_getkey
434  * SYNOPSIS
435  *    ret = slang_terminal_getkey (This);
436  * INPUTS
437  *    Tn5250Terminal *     This       -
438  * DESCRIPTION
439  *    DOCUMENT ME!!!
440  *****/
slang_terminal_getkey(Tn5250Terminal * This)441 static int slang_terminal_getkey(Tn5250Terminal * This)
442 {
443    unsigned int key;
444 
445    if (!SLang_input_pending (0))
446       return -1;
447 
448    key = SLkp_getkey ();
449    while (1) {
450       switch (key) {
451       case 0x0d:
452       case 0x0a:
453 	 return K_ENTER;
454 
455       case 0x1b:
456 	 if ((key = slang_terminal_get_esc_key(This, 1)) != SL_KEY_ERR)
457 	    return key;
458 	 break;
459 
460       case K_CTRL('A'):
461 	 return K_ATTENTION;
462       case K_CTRL('B'):
463 	 return K_ROLLDN;
464       case K_CTRL('C'):
465 	 return K_SYSREQ;
466       case K_CTRL('D'):
467 	 return K_ROLLUP;
468       case K_CTRL('E'):
469 	 return K_ERASE;
470       case K_CTRL('F'):
471 	 return K_ROLLUP;
472       case K_CTRL('K'):
473 	 return K_FIELDEXIT;
474       case K_CTRL('L'):
475 	 return K_REFRESH;
476       case K_CTRL('O'):
477 	 return K_HOME;
478       case K_CTRL('P'):
479 	 return K_PRINT;
480       case K_CTRL('R'):
481 	 return K_RESET;	/* Error Reset */
482       case K_CTRL('S'):
483 	 return K_MEMO;
484       case K_CTRL('T'):
485 	 return K_TESTREQ;
486       case K_CTRL('U'):
487 	 return K_ROLLDN;
488       case K_CTRL('W'):
489 	 return K_EXEC;
490       case K_CTRL('X'):
491 	 return K_FIELDEXIT;
492 
493       case K_CTRL('Q'):
494 	 This->data->quit_flag = 1;
495 	 return -1;
496 
497       case K_CTRL('G'):	/* C-g <function-key-shortcut> */
498 	 if ((key = slang_terminal_get_esc_key(This, 0)) != SL_KEY_ERR)
499 	    return key;
500 	 break;
501 
502       case SL_KEY_ERR:
503 	 if (SLang_Error == USER_BREAK)
504 	    This->data->quit_flag = 1;
505 	 return -1;
506 
507       case SL_KEY_DELETE:
508 	 return K_DELETE;
509 
510       case SL_KEY_F(1):
511 	 return K_F1;
512       case SL_KEY_F(2):
513 	 return K_F2;
514       case SL_KEY_F(3):
515 	 return K_F3;
516       case SL_KEY_F(4):
517 	 return K_F4;
518       case SL_KEY_F(5):
519 	 return K_F5;
520       case SL_KEY_F(6):
521 	 return K_F6;
522       case SL_KEY_F(7):
523 	 return K_F7;
524       case SL_KEY_F(8):
525 	 return K_F8;
526       case SL_KEY_F(9):
527 	 return K_F9;
528       case SL_KEY_F(10):
529 	 return K_F10;
530       case SL_KEY_F(11):
531 	 return K_F11;
532       case SL_KEY_F(12):
533 	 return K_F12;
534       case SL_KEY_F(13):
535 	 return K_F13;
536       case SL_KEY_F(14):
537 	 return K_F14;
538       case SL_KEY_F(15):
539 	 return K_F15;
540       case SL_KEY_F(16):
541 	 return K_F16;
542       case SL_KEY_F(17):
543 	 return K_F17;
544       case SL_KEY_F(18):
545 	 return K_F18;
546       case SL_KEY_F(19):
547 	 return K_F19;
548       case SL_KEY_F(20):
549 	 return K_F20;
550       case SL_KEY_F(21):
551 	 return K_F21;
552       case SL_KEY_F(22):
553 	 return K_F22;
554       case SL_KEY_F(23):
555 	 return K_F23;
556       case SL_KEY_F(24):
557 	 return K_F24;
558       case SL_KEY_BACKSPACE:
559 	 return K_BACKSPACE;
560       case SL_KEY_IC:
561 	 return K_INSERT;
562 
563       case SL_KEY_HOME:
564       case SL_KEY_A1:
565 	 return K_HOME;
566 
567       case SL_KEY_PPAGE:
568       case SL_KEY_A3:
569 	 return K_ROLLDN;
570 
571       case SL_KEY_END:
572       case SL_KEY_C1:
573 	 return K_END;
574 
575       case SL_KEY_NPAGE:
576       case SL_KEY_C3:
577 	 return K_ROLLUP;
578 
579       case SL_KEY_ENTER:
580 	 return K_FIELDEXIT;
581 
582       case SL_KEY_UP:
583 	 return K_UP;
584 
585       case SL_KEY_DOWN:
586 	 return K_DOWN;
587 
588       case SL_KEY_LEFT:
589 	 return K_LEFT;
590 
591       case SL_KEY_RIGHT:
592 	 return K_RIGHT;
593 
594       default:
595 	 return key;
596       }
597    }
598 }
599 
600 /****i* lib5250/slang_terminal_beep
601  * NAME
602  *    slang_terminal_beep
603  * SYNOPSIS
604  *    slang_terminal_beep (This);
605  * INPUTS
606  *    Tn5250Terminal *     This       -
607  * DESCRIPTION
608  *    DOCUMENT ME!!!
609  *****/
slang_terminal_beep(Tn5250Terminal * This)610 static void slang_terminal_beep (Tn5250Terminal * This)
611 {
612    SLtt_beep ();
613 }
614 
615 
616 /***** lib5250/slang_terminal_enhanced
617  * NAME
618  *    slang_terminal_enhanced
619  * SYNOPSIS
620  *    ret = slang_terminal_enhanced (This);
621  * INPUTS
622  *    Tn5250Terminal  *    This       -
623  * DESCRIPTION
624  *    Return 1 if we support the enhanced 5250 protocol, 0 otherwise.
625  *****/
626 static int
slang_terminal_enhanced(Tn5250Terminal * This)627 slang_terminal_enhanced (Tn5250Terminal * This)
628 {
629   return (0);
630 }
631 
632 
633 /****i* lib5250/slang_terminal_get_esc_key
634  * NAME
635  *    slang_terminal_get_esc_key
636  * SYNOPSIS
637  *    ret = slang_terminal_get_esc_key (This, is_esc);
638  * INPUTS
639  *    Tn5250Terminal *     This       -
640  *    int                  is_esc     -
641  * DESCRIPTION
642  *    If a vt100 escape key sequence was introduced (using either
643  *    <Esc> or <Ctrl+g>), handle the next key in the sequence.
644  *****/
slang_terminal_get_esc_key(Tn5250Terminal * This,int is_esc)645 static int slang_terminal_get_esc_key(Tn5250Terminal * This, int is_esc)
646 {
647    int y, x, key, display_key;
648 
649    y = SLsmg_get_row ();
650    x = SLsmg_get_column ();
651    SLsmg_normal_video ();
652    SLsmg_gotorc (This->data->last_height, 60);
653    if (is_esc)
654       SLsmg_write_string ("Esc ");
655    else
656       SLsmg_write_string ("C-g ");
657    SLsmg_gotorc (y, x);
658    SLsmg_refresh();
659 
660 #if !defined(WIN32) && !defined(WINE)
661    {
662       fd_set fdr;
663       FD_ZERO(&fdr);
664       FD_SET(0, &fdr);
665       select(1, &fdr, NULL, NULL, NULL);
666    }
667 #else
668    /* XXX: What do we need that for? */
669 #endif
670    key = SLkp_getkey ();
671 
672    if (isalpha(key))
673       key = toupper(key);
674 
675    display_key = key;
676    switch (key) {
677 
678       /* Function keys */
679    case '1':
680       key = K_F1;
681       break;
682    case '2':
683       key = K_F2;
684       break;
685    case '3':
686       key = K_F3;
687       break;
688    case '4':
689       key = K_F4;
690       break;
691    case '5':
692       key = K_F5;
693       break;
694    case '6':
695       key = K_F6;
696       break;
697    case '7':
698       key = K_F7;
699       break;
700    case '8':
701       key = K_F8;
702       break;
703    case '9':
704       key = K_F9;
705       break;
706    case '0':
707       key = K_F10;
708       break;
709    case '-':
710       key = K_F11;
711       break;
712    case '=':
713       key = K_F12;
714       break;
715    case '!':
716       key = K_F13;
717       break;
718    case '@':
719       key = K_F14;
720       break;
721    case '#':
722       key = K_F15;
723       break;
724    case '$':
725       key = K_F16;
726       break;
727    case '%':
728       key = K_F17;
729       break;
730    case '^':
731       key = K_F18;
732       break;
733    case '&':
734       key = K_F19;
735       break;
736    case '*':
737       key = K_F20;
738       break;
739    case '(':
740       key = K_F21;
741       break;
742    case ')':
743       key = K_F22;
744       break;
745    case '_':
746       key = K_F23;
747       break;
748    case '+':
749       key = K_F24;
750       break;
751 
752       /* AS/400 strangeness */
753    case 'A':
754       key = K_ATTENTION;
755       break;
756    case 'C':
757       key = K_CLEAR;
758       break;
759    case 'D':
760       key = K_DUPLICATE;
761       break;
762    case 'H':
763       key = K_HELP;
764       break;
765    case 'I':
766       key = K_INSERT;
767       break;
768    case 'L':
769       key = K_REFRESH;
770       break;
771    case 'M':
772       key = K_FIELDMINUS;
773       break;
774    case 'P':
775       key = K_PRINT;
776       break;
777    case 'R':
778       key = K_RESET;
779       break;
780    case 'S':
781       key = K_SYSREQ;
782       break;
783    case 'T':
784       key = K_TOGGLE;
785       break;
786    case 'X':
787       key = K_FIELDEXIT;
788       break;
789 
790    case 127:
791       key = K_INSERT;
792       break;			/* ESC DEL */
793    case SL_KEY_DELETE:
794       key = K_INSERT;
795       break;			/* ESC DEL, also */
796    case K_CTRL('J'):
797       key = K_NEWLINE;
798       break;
799 
800    case 'Q':
801       This->data->quit_flag = 1;
802       key = SL_KEY_ERR;
803       break;
804 
805    default:
806       SLtt_beep();
807       key = SL_KEY_ERR;
808       break;
809    }
810 
811    SLsmg_gotorc (This->data->last_height, 64);
812    if (key == SL_KEY_ERR)
813       SLsmg_write_string ("???");
814    else
815       SLsmg_write_char (display_key);
816    SLsmg_gotorc (y, x);
817    SLsmg_refresh ();
818    return key;
819 }
820 
821 /****i* lib5250/slang_terminal_set_attrs
822  * NAME
823  *    slang_terminal_set_attrs
824  * SYNOPSIS
825  *    slang_terminal_set_attrs (This, attrs);
826  * INPUTS
827  *    Tn5250Terminal *     This       -
828  *    int                  attrs      -
829  * DESCRIPTION
830  *    DOCUMENT ME!!!
831  *****/
slang_terminal_set_attrs(Tn5250Terminal * This,int attrs)832 static void slang_terminal_set_attrs (Tn5250Terminal * This, int attrs)
833 {
834    if (attrs == This->data->attrs)
835       return;
836    SLsmg_normal_video ();
837    SLsmg_set_color ((attrs & A_COLOR_MASK) >> 8);
838    if ((attrs & A_REVERSE) != 0)
839       SLsmg_reverse_video ();
840    /* FIXME: Handle A_BLINK */
841    This->data->attrs = attrs;
842 }
843 
844 #else /* USE_SLANG */
845 
846 /* When compiled with -Wall -pedantic: ANSI C forbids empty source file. */
847 struct NoSlang {
848    long dummy;
849 };
850 
851 #endif /* USE_SLANG */
852 
853 /* vi:set cindent sts=3 sw=3: */
854