home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / UE311C.ZIP / SMG.C < prev    next >
C/C++ Source or Header  |  1991-10-04  |  32KB  |  1,098 lines

  1. /*
  2.  *  SMG terminal driver for VMS.
  3.  *
  4.  *  Consults the system's terminal tables for both DEC terminals,
  5.  *  foreign and user defined terminals.
  6.  *
  7.  *  Author:  Curtis Smith
  8.  *  Update history:
  9.  *    14-Jul-1987, first revision.
  10.  *    02-Jan-1988, by J. A. Lomicka: Code addition for interpreting
  11.  *        LK201 function keys, application keypad and cursor
  12.  *        position reports.
  13.  *    09-Apr-1988, second revision.
  14.  *        Major changes:
  15.  *        1) H files removed; replaced with globalvalues.
  16.  *        2) Terminal now left in ECHO mode. Read call
  17.  *        disables echo.
  18.  *        3) TYPAHD macro now performs correctly.
  19.  *        4) $sres variable now accepts NORMAL and WIDE.
  20.  *        5) Writes to screen now use QIO without waiting.
  21.  *        This gives a slight increase in performance.
  22.  *        Had to make some QIOW a different event flag number.
  23.  *        6) Function keys, special keys and arrow keys
  24.  *        are now bound using the following table:
  25.  *            FNN-DOWN            FNS-E1
  26.  *            FNB-LEFT            FNC-E2
  27.  *            FNF-RIGHT            FND-E3
  28.  *            FNP-UP                FN@-E4
  29.  *            FN^1-PF1            FNZ-E5
  30.  *            FN^2-PF2            FNV-E6
  31.  *            FN^3-PF3
  32.  *            FN^4-PF4
  33.  *
  34.  *            A-0 thru A-9: Keypad 0 thru 9
  35.  *            A-E: Enter
  36.  *            A-., A-, : Keypad . and ,
  37.  *
  38.  *            FN1 thru FN0 : Function keys 1 thru 10
  39.  *            S-FN1 thru S-FN0 : Function keys 11 thru 20
  40.  *            
  41.  *        See ebind.h for key bindings.
  42.  *    2-dec-88 Curtis Smith
  43.  *    - These have been rebound to the new machine independant bindings
  44.  *    27-March-1989    J.A.Lomicka    Separate VMS.C from SMG.C,
  45.  *                    This file is now SMG.C, and only
  46.  *                    contains the SMG stuff.
  47.  *
  48.  *
  49.  *    17-jul-89 : mike ward
  50.  *        Modifications for proper operation of special keys. Basically,
  51.  *        the changes are to deal with key values as ints rather rather
  52.  *        than characters so that when a character sequence is recognized
  53.  *        as a special key, the approriate value can be substituted for
  54.  *        the sequence directly (in inbuf).
  55.  *
  56.  *        1)    Use "int" rather than "char" to declare inbuf[],
  57.  *            *inbuft, and *inbufh since keys use more than 8-bits
  58.  *        2)    Change the parameter declaration "char ch" to "int ch"
  59.  *            in smgqin since we queue key values (not characters)
  60.  *        3)     Change calls "smgqin(ch)" to "smgqin((unsigned char)ch)"
  61.  *            in smggcook since we don't want sign extension
  62.  *        4)    Remove call "smgqin(0)" in smggcook. Instead of queuing
  63.  *            a sequence of chars to represent the key value, just
  64.  *            queue the final value instead - much cleaner.
  65.  *        5)    Change the declaration from "char ch" to "int ch" in
  66.  *            smggetc since ch now holds a key value rather than a
  67.  *            character.
  68.  *    11-dec-89:    Kevin A. Mitchell
  69.  *        Don't restore numeric keypad if the user had it set that way
  70.  *        in DCL.
  71.  */
  72.  
  73. /** Standard include files **/
  74. #include <stdio.h>            /* Standard I/O package        */
  75. #include "estruct.h"            /* Emacs' structures        */
  76.  
  77. /*
  78.     Empty routine make some compilers happy when SMG is not defined,
  79.     and is also used as a noop routine in the terminal dispatch table.
  80. */
  81. smg_noop()
  82. {
  83. }
  84.  
  85. #if    SMG
  86.  
  87. #include "eproto.h"
  88. #include "edef.h"            /* Emacs' definitions        */
  89. #include "elang.h"
  90. #include smgdef
  91. #include ssdef
  92. #include descrip
  93. #include string
  94. #include ttdef
  95. #include tt2def
  96.  
  97. /*
  98.     SMG constants from $$smgtrmptrdef
  99. */
  100. #define    SMG$K_ADVANCED_VIDEO        1
  101. #define    SMG$K_ANSI_CRT            2
  102. #define    SMG$K_AUTO_MARGIN        3
  103. #define    SMG$K_BACKSPACE            4
  104. #define    SMG$K_BLOCK_MODE        5
  105. #define    SMG$K_DEC_CRT            6
  106. #define    SMG$K_EDIT            7
  107. #define    SMG$K_EIGHT_BIT            8
  108. #define    SMG$K_FULLDUP            9
  109. #define    SMG$K_IGNORE_NEWLINE        10
  110. #define    SMG$K_INSERT_MODE_NULLS        11
  111. #define    SMG$K_LOWERCASE            12
  112. #define    SMG$K_NO_ERASE            13
  113. #define    SMG$K_NO_SCROLL            14
  114. #define    SMG$K_OVERSTRIKE        15
  115. #define    SMG$K_PRINTER_PORT        16
  116. #define    SMG$K_REGIS            17
  117. #define    SMG$K_SCOPE            18
  118. #define    SMG$K_SIXEL_GRAPHICS        19
  119. #define    SMG$K_SOFT_CHARACTERS        20
  120. #define    SMG$K_PHYSICAL_TABS        21
  121. #define    SMG$K_PHYSICAL_FF        22
  122. #define    SMG$K_UNDERLINE            23
  123. #define    SMG$K_CURSOR_REPORT_ANSI    24
  124. #define    SMG$K_DEC_CRT_2            25
  125. #define    SMG$K_DEC_CRT_3            26
  126. #define    SMG$K_SET_CURSOR_COL_ROW    27
  127. #define    SMG$K_PRIVATE_BOO_1        211
  128. #define    SMG$K_PRIVATE_BOO_2        212
  129. #define    SMG$K_PRIVATE_BOO_3        213
  130. #define    SMG$K_PRIVATE_BOO_4        214
  131. #define    SMG$K_PRIVATE_BOO_5        215
  132. #define    SMG$K_PRIVATE_BOO_6        216
  133. #define    SMG$K_PRIVATE_BOO_7        217
  134. #define    SMG$K_PRIVATE_BOO_8        218
  135. #define    SMG$K_PRIVATE_BOO_9        219
  136. #define    SMG$K_PRIVATE_BOO_10        220
  137. #define    SMG$K_MAX_BOOLEAN_CODE        220
  138. #define    SMG$K_COLUMNS            221
  139. #define    SMG$K_CR_FILL            222
  140. #define    SMG$K_FRAME            223
  141. #define    SMG$K_LF_FILL            224
  142. #define    SMG$K_NUMBER_FN_KEYS        225
  143. #define    SMG$K_ROWS            226
  144. #define    SMG$K_VMS_TERMINAL_NUMBER    227
  145. #define    SMG$K_WIDE_SCREEN_COLUMNS    228
  146. #define    SMG$K_PRIVATE_NUM_1        431
  147. #define    SMG$K_PRIVATE_NUM_2        432
  148. #define    SMG$K_PRIVATE_NUM_3        433
  149. #define    SMG$K_PRIVATE_NUM_4        434
  150. #define    SMG$K_PRIVATE_NUM_5        435
  151. #define    SMG$K_PRIVATE_NUM_6        436
  152. #define    SMG$K_PRIVATE_NUM_7        437
  153. #define    SMG$K_PRIVATE_NUM_8        438
  154. #define    SMG$K_PRIVATE_NUM_9        439
  155. #define    SMG$K_PRIVATE_NUM_10        440
  156. #define    SMG$K_MAX_NUMERIC_CODE        440
  157. #define    SMG$K_BEGIN_ALTERNATE_CHAR    441
  158. #define    SMG$K_BEGIN_BLINK        442
  159. #define    SMG$K_BEGIN_BOLD        443
  160. #define    SMG$K_BEGIN_DELETE_MODE        444
  161. #define    SMG$K_BEGIN_INSERT_MODE        445
  162. #define    SMG$K_BEGIN_LINE_DRAWING_CHAR    446
  163. #define    SMG$K_BEGIN_REVERSE        447
  164. #define    SMG$K_BEGIN_UNDERSCORE        448
  165. #define    SMG$K_BOTTOM_T_CHAR        449
  166. #define    SMG$K_CLEAR_TAB            450
  167. #define    SMG$K_CROSS_CHAR        451
  168. #define    SMG$K_CURSOR_DOWN        452
  169. #define    SMG$K_CURSOR_LEFT        453
  170. #define    SMG$K_CURSOR_RIGHT        454
  171. #define    SMG$K_CURSOR_UP            455
  172. #define    SMG$K_DARK_SCREEN        456
  173. #define    SMG$K_DELETE_CHAR        457
  174. #define    SMG$K_DELETE_LINE        458
  175. #define    SMG$K_DEVICE_ATTRIBUTES        459
  176. #define    SMG$K_DOUBLE_HIGH_BOTTOM    460
  177. #define    SMG$K_DOUBLE_HIGH_TOP        461
  178. #define    SMG$K_DOUBLE_WIDE        462
  179. #define    SMG$K_DUPLICATE            463
  180. #define    SMG$K_END_ALTERNATE_CHAR    464
  181. #define    SMG$K_END_BLINK            465
  182. #define    SMG$K_END_BOLD            466
  183. #define    SMG$K_END_DELETE_MODE        467
  184. #define    SMG$K_END_INSERT_MODE        468
  185. #define    SMG$K_END_LINE_DRAWING_CHAR    469
  186. #define    SMG$K_END_REVERSE        470
  187. #define    SMG$K_END_UNDERSCORE        471
  188. #define    SMG$K_ERASE_TO_END_DISPLAY    472
  189. #define    SMG$K_ERASE_TO_END_LINE        473
  190. #define    SMG$K_ERASE_WHOLE_DISPLAY    474
  191. #define    SMG$K_ERASE_WHOLE_LINE        475
  192. #define    SMG$K_HOME            476
  193. #define    SMG$K_HORIZONTAL_BAR        477
  194. #define    SMG$K_INIT_STRING        478
  195. #define    SMG$K_INSERT_CHAR        479
  196. #define    SMG$K_INSERT_LINE        480
  197. #define    SMG$K_INSERT_PAD        481
  198. #define    SMG$K_KEY_0            482
  199. #define    SMG$K_KEY_1            483
  200. #define    SMG$K_KEY_2            484
  201. #define    SMG$K_KEY_3            485
  202. #define    SMG$K_KEY_4            486
  203. #define    SMG$K_KEY_5            487
  204. #define    SMG$K_KEY_6            488
  205. #define    SMG$K_KEY_7            489
  206. #define    SMG$K_KEY_8            490
  207. #define    SMG$K_KEY_9            491
  208. #define    SMG$K_KEY_BACKSPACE        492
  209. #define    SMG$K_KEY_COMMA            493
  210. #define    SMG$K_KEY_DOWN_ARROW        494
  211. #define    SMG$K_KEY_E1            495
  212. #define    SMG$K_KEY_E2            496
  213. #define    SMG$K_KEY_E3            497
  214. #define    SMG$K_KEY_E4            498
  215. #define    SMG$K_KEY_E5            499
  216. #define    SMG$K_KEY_E6            500
  217. #define    SMG$K_KEY_ENTER            501
  218. #define    SMG$K_KEY_F1            502
  219. #define    SMG$K_KEY_F2            503
  220. #define    SMG$K_KEY_F3            504
  221. #define    SMG$K_KEY_F4            505
  222. #define    SMG$K_KEY_F5            506
  223. #define    SMG$K_KEY_F6            507
  224. #define    SMG$K_KEY_F7            508
  225. #define    SMG$K_KEY_F8            509
  226. #define    SMG$K_KEY_F9            510
  227. #define    SMG$K_KEY_F10            511
  228. #define    SMG$K_KEY_F11            512
  229. #define    SMG$K_KEY_F12            513
  230. #define    SMG$K_KEY_F13            514
  231. #define    SMG$K_KEY_F14            515
  232. #define    SMG$K_KEY_F15            516
  233. #define    SMG$K_KEY_F16            517
  234. #define    SMG$K_KEY_F17            518
  235. #define    SMG$K_KEY_F18            519
  236. #define    SMG$K_KEY_F19            520
  237. #define    SMG$K_KEY_F20            521
  238. #define    SMG$K_KEY_LEFT_ARROW        522
  239. #define    SMG$K_KEY_MINUS            523
  240. #define    SMG$K_KEY_PERIOD        524
  241. #define    SMG$K_KEY_PF1            525
  242. #define    SMG$K_KEY_PF2            526
  243. #define    SMG$K_KEY_PF3            527
  244. #define    SMG$K_KEY_PF4            528
  245. #define    SMG$K_KEY_RIGHT_ARROW        529
  246. #define    SMG$K_KEY_UP_ARROW        530
  247. #define    SMG$K_LABEL_F1            531
  248. #define    SMG$K_LABEL_F2            532
  249. #define    SMG$K_LABEL_F3            533
  250. #define    SMG$K_LABEL_F4            534
  251. #define    SMG$K_LABEL_F5            535
  252. #define    SMG$K_LABEL_F6            536
  253. #define    SMG$K_LABEL_F7            537
  254. #define    SMG$K_LABEL_F8            538
  255. #define    SMG$K_LABEL_F9            539
  256. #define    SMG$K_LABEL_F10            540
  257. #define    SMG$K_LABEL_F11            541
  258. #define    SMG$K_LABEL_F12            542
  259. #define    SMG$K_LABEL_F13            543
  260. #define    SMG$K_LABEL_F14            544
  261. #define    SMG$K_LABEL_F15            545
  262. #define    SMG$K_LABEL_F16            546
  263. #define    SMG$K_LABEL_F17            547
  264. #define    SMG$K_LABEL_F18            548
  265. #define    SMG$K_LABEL_F19            549
  266. #define    SMG$K_LABEL_F20            550
  267. #define    SMG$K_LEFT_T_CHAR        551
  268. #define    SMG$K_LIGHT_SCREEN        552
  269. #define    SMG$K_LOWER_LEFT_CORNER        553
  270. #define    SMG$K_LOWER_RIGHT_CORNER    554
  271. #define    SMG$K_NAME            555
  272. #define    SMG$K_NEWLINE_CHAR        556
  273. #define    SMG$K_PAD_CHAR            557
  274. #define    SMG$K_RESTORE_CURSOR        558
  275. #define    SMG$K_RIGHT_T_CHAR        559
  276. #define    SMG$K_SAVE_CURSOR        560
  277. #define    SMG$K_SCROLL_FORWARD        561
  278. #define    SMG$K_SCROLL_REVERSE        562
  279. #define    SMG$K_SEL_ERASE_TO_END_DISPLAY    563
  280. #define    SMG$K_SEL_ERASE_TO_END_LINE    564
  281. #define    SMG$K_SEL_ERASE_WHOLE_DISPLAY    565
  282. #define    SMG$K_SEL_ERASE_WHOLE_LINE    566
  283. #define    SMG$K_SET_APPLICATION_KEYPAD    567
  284. #define    SMG$K_SET_CHAR_NOT_SEL_ERASE    568
  285. #define    SMG$K_SET_CHAR_SEL_ERASE    569
  286. #define    SMG$K_SET_CURSOR_ABS        570
  287. #define    SMG$K_SET_NUMERIC_KEYPAD    571
  288. #define    SMG$K_SET_SCROLL_REGION        572
  289. #define    SMG$K_SET_TAB            573
  290. #define    SMG$K_SINGLE_HIGH        574
  291. #define    SMG$K_TAB_CHAR            575
  292. #define    SMG$K_TOP_T_CHAR        576
  293. #define    SMG$K_UNDERLINE_CHAR        577
  294. #define    SMG$K_UPPER_LEFT_CORNER        578
  295. #define    SMG$K_UPPER_RIGHT_CORNER    579
  296. #define    SMG$K_VERTICAL_BAR        580
  297. #define    SMG$K_WIDTH_NARROW        581
  298. #define    SMG$K_WIDTH_WIDE        582
  299. #define    SMG$K_CURSOR_POSITION_REPORT    583
  300. #define    SMG$K_REQUEST_CURSOR_POSITION    584
  301. #define    SMG$K_CR_GRAPHIC        585
  302. #define    SMG$K_FF_GRAPHIC        586
  303. #define    SMG$K_LF_GRAPHIC        587
  304. #define    SMG$K_HT_GRAPHIC        588
  305. #define    SMG$K_VT_GRAPHIC        589
  306. #define    SMG$K_TRUNCATION_ICON        590
  307. #define    SMG$K_CURSOR_NEXT_LINE        591
  308. #define    SMG$K_CURSOR_PRECEDING_LINE    592
  309. #define    SMG$K_INDEX            593
  310. #define    SMG$K_REVERSE_INDEX        594
  311. #define    SMG$K_BEGIN_NORMAL_RENDITION    595
  312. #define    SMG$K_BEGIN_AUTOWRAP_MODE    596
  313. #define    SMG$K_END_AUTOWRAP_MODE        597
  314. #define    SMG$K_BEGIN_AUTOREPEAT_MODE    598
  315. #define    SMG$K_END_AUTOREPEAT_MODE    599
  316. #define    SMG$K_SET_ORIGIN_RELATIVE    600
  317. #define    SMG$K_SET_ORIGIN_ABSOLUTE    601
  318. #define    SMG$K_ERASE_LINE_TO_CURSOR    602
  319. #define    SMG$K_NEXT_LINE            603
  320. #define    SMG$K_BEGIN_AUTOPRINT_MODE    604
  321. #define    SMG$K_END_AUTOPRINT_MODE    605
  322. #define    SMG$K_PRINT_SCREEN        606
  323. #define    SMG$K_SET_CURSOR_ON        607
  324. #define    SMG$K_SET_CURSOR_OFF        608
  325. #define    SMG$K_SET_PRINTER_OUTPUT    609
  326. #define    SMG$K_SET_SCREEN_OUTPUT        610
  327. #define    SMG$K_ERASE_DISPLAY_TO_CURSOR    611
  328. #define    SMG$K_REQUEST_PRINTER_STATUS    612
  329. #define    SMG$K_PRINTER_READY        613
  330. #define    SMG$K_PRINTER_NOT_READY        614
  331. #define    SMG$K_NO_PRINTER        615
  332. #define    SMG$K_SET_JUMP_SCROLL        616
  333. #define    SMG$K_SET_SMOOTH_SCROLL        617
  334. #define    SMG$K_ERROR_ICON        618
  335. #define    SMG$K_PAGE_LENGTH        619
  336. #define    SMG$K_PRIVATE_STR_1        651
  337. #define    SMG$K_PRIVATE_STR_2        652
  338. #define    SMG$K_PRIVATE_STR_3        653
  339. #define    SMG$K_PRIVATE_STR_4        654
  340. #define    SMG$K_PRIVATE_STR_5        655
  341. #define    SMG$K_PRIVATE_STR_6        656
  342. #define    SMG$K_PRIVATE_STR_7        657
  343. #define    SMG$K_PRIVATE_STR_8        658
  344. #define    SMG$K_PRIVATE_STR_9        659
  345. #define    SMG$K_PRIVATE_STR_10        660
  346. #define    SMG$K_MAX_STRING_CODE        660
  347. #define    SMG$K_BEGIN_USER1        661
  348. #define    SMG$K_BEGIN_USER2        662
  349. #define    SMG$K_BEGIN_USER3        663
  350. #define    SMG$K_BEGIN_USER4        664
  351. #define    SMG$K_BEGIN_USER5        665
  352. #define    SMG$K_BEGIN_USER6        666
  353. #define    SMG$K_BEGIN_USER7        667
  354. #define    SMG$K_BEGIN_USER8        668
  355. #define    SMG$K_END_USER1            669
  356. #define    SMG$K_END_USER2            670
  357. #define    SMG$K_END_USER3            671
  358. #define    SMG$K_END_USER4            672
  359. #define    SMG$K_END_USER5            673
  360. #define    SMG$K_END_USER6            674
  361. #define    SMG$K_END_USER7            675
  362. #define    SMG$K_END_USER8            676
  363. #define    SMG$K_BLACK_SCREEN        677
  364. #define    SMG$K_BLUE_SCREEN        678
  365. #define    SMG$K_CYAN_SCREEN        679
  366. #define    SMG$K_MAGENTA_SCREEN        680
  367. #define    SMG$K_GREEN_SCREEN        681
  368. #define    SMG$K_RED_SCREEN        682
  369. #define    SMG$K_WHITE_SCREEN        683
  370. #define    SMG$K_YELLOW_SCREEN        684
  371. #define    SMG$K_USER1_SCREEN        685
  372. #define    SMG$K_USER2_SCREEN        686
  373. #define    SMG$K_BEGIN_STATUS_LINE        687
  374. #define    SMG$K_END_STATUS_LINE        688
  375. #define    SMG$K_BEGIN_LOCATOR        689
  376. #define    SMG$K_END_LOCATOR        690
  377. #define    SMG$K_KEY_FIRST_DOWN        691
  378. #define    SMG$K_KEY_SECOND_DOWN        692
  379. #define    SMG$K_KEY_THIRD_DOWN        693
  380. #define    SMG$K_KEY_FOURTH_DOWN        694
  381. #define    SMG$K_KEY_FIRST_UP        695
  382. #define    SMG$K_KEY_SECOND_UP        696
  383. #define    SMG$K_KEY_THIRD_UP        697
  384. #define    SMG$K_KEY_FOURTH_UP        698
  385. #define    SMG$K_MAX_STRING2_CODE        880
  386.  
  387. /*
  388.     Parts of VMS.C that we'll want to access here
  389. */
  390. extern struct dsc$descriptor_s *descptr();
  391. extern struct dsc$descriptor_s *descrp();
  392. #define DESCPTR( s)    descrp( s, sizeof(s)-1)
  393. /*
  394.     These two structures, along with ttdef.h, are good for manipulating
  395.     terminal characteristics.
  396. */
  397. typedef struct
  398.     {/* Terminal characteristics buffer */
  399.     unsigned char class, type;
  400.     unsigned short width;
  401.     unsigned tt1 : 24;
  402.     unsigned char page;
  403.     unsigned long tt2;
  404.     } TTCHAR;
  405. extern NOSHARE TTCHAR orgchar;            /* Original characteristics */
  406. /*
  407.     test macro is used to signal errors from system services
  408. */
  409. #define test( s) {int st; st = (s); if( (st&1)==0) LIB$SIGNAL( st);}
  410. #define FAILURE( s) (!(s&1))
  411. #define SUCCESS( s) (s&1)
  412.  
  413. /** Parameters **/
  414. #define NKEYENT        128        /* Number of keymap entries    */
  415.  
  416. /** Type definitions **/
  417. struct keyent {                /* Key mapping entry        */
  418.     struct keyent * samlvl;        /* Character on same level    */
  419.     struct keyent * nxtlvl;        /* Character on next level    */
  420.     char ch;            /* Character            */
  421.     int code;            /* Resulting keycode        */
  422. };
  423.  
  424. /** Values to manage the screen **/
  425. static int termtype;            /* Handle to pass to SMG    */
  426. #if    KEYPAD
  427. static char * applic_keypad;        /* Put keypad in application mode.*/
  428. static char * numeric_keypad;        /* Put keypad in numeric mode.    */
  429. #endif
  430. static char * begin_reverse;        /* Begin reverse video        */
  431. static char * end_reverse;        /* End reverse video        */
  432. static char * begin_mouse;        /* Begin using mouse        */
  433. static char * end_mouse;        /* End using mouse        */
  434. static char * erase_to_end_line;    /* Erase to end of line        */
  435. static char * erase_whole_display;    /* Erase whole display        */
  436. static char * width_narrow;        /* Set narrow size screen    */
  437. static char * width_wide;        /* Set wide size screen        */
  438. static int narrow_char;            /* Number of characters narrow    */
  439. static int wide_char;            /* Number of characters wide    */
  440. static int inbuf[64];            /* Input buffer            */
  441. static int * inbufh = inbuf;        /* Head of input buffer        */
  442. static int * inbuft = inbuf;        /* Tail of input buffer        */
  443. static char keyseq[256];        /* Prefix escape sequence table    */
  444. static struct keyent keymap[NKEYENT];    /* Key map            */
  445. static struct keyent * nxtkey = keymap;    /* Next free key entry        */
  446.  
  447.  
  448. /* Forward references.          */
  449. extern int PASCAL NEAR smgmove();
  450. extern int PASCAL NEAR smgeeol();
  451. extern int PASCAL NEAR smgeeop();
  452. extern int PASCAL NEAR smgbeep();
  453. extern int PASCAL NEAR smgopen();
  454. extern int PASCAL NEAR smgrev();
  455. extern int PASCAL NEAR smgcres();
  456. extern int PASCAL NEAR smgparm();
  457. extern int PASCAL NEAR smggetc();
  458. extern int PASCAL NEAR smgclose();
  459.  
  460. /** Terminal dispatch table **/
  461. NOSHARE TERM term = {
  462.     72-1,                /* Max number of rows allowable */
  463.     0,                /* Current number of rows used    */
  464.     256,                /* Max number of columns    */
  465.     0,                /* Current number of columns    */
  466.     0, 0,                /* x/y origin of screen        */
  467.     64,                /* Min margin for extended lines*/
  468.     8,                /* Size of scroll region    */
  469.     100,                /* # times thru update to pause */
  470.     smgopen,            /* Open terminal at the start    */
  471.     smgclose,            /* Close terminal at end    */
  472.     smg_noop,            /* Open keyboard        */
  473.     smg_noop,            /* Close keyboard        */
  474.     smggetc,            /* Get character from keyboard    */
  475.     ttputc,                /* Put character to display    */
  476.     ttflush,            /* Flush output buffers        */
  477.     smgmove,            /* Move cursor, origin 0    */
  478.     smgeeol,            /* Erase to end of line        */
  479.     smgeeop,            /* Erase to end of page        */
  480.     smgbeep,            /* Beep                */
  481.     smgrev,                /* Set reverse video state    */
  482.     smgcres                /* Change screen resolution    */
  483. #if COLOR
  484.     ,
  485.     smg_noop,            /* Set forground color        */
  486.     smg_noop            /* Set background color        */
  487. #endif /* COLOR */
  488. };
  489.  
  490. /***
  491.  *  smgmove  -  Move the cursor (0 origin)
  492.  *
  493.  *  smgmove calls to the SMG run-time library to produce a character
  494.  *  sequence to position the cursor.  If the sequence cannot be made,
  495.  *  a string "OOPS" is produced instead, much like the termcap library
  496.  *  under UNIX.  In the case of "OOPS", the user will soon know that
  497.  *  his terminal entry is incorrect.
  498.  *
  499.  *  Nothing returned.
  500.  ***/
  501. smgmove(int row, int column)
  502. {
  503.     char buffer[32];
  504.     int rlen, status;
  505.     
  506.     static int code = SMG$K_SET_CURSOR_ABS;
  507.     static int len = sizeof(buffer);
  508.     static int arg[3] = { 2 };
  509.  
  510.     /* SMG assumes the row/column positions    are 1 based. */
  511.     arg[1] = row + 1;
  512.     arg[2] = column + 1;
  513.  
  514.     /* Call to SMG for the sequence */
  515.     status = SMG$GET_TERM_DATA(&termtype, &code, &len, &rlen, buffer, arg);
  516.     if (SUCCESS(status)) {
  517.         buffer[rlen] = '\0';
  518.         smgputs(buffer);
  519.     } else
  520.         smgputs("OOPS");
  521. }
  522.  
  523. /***
  524.  *  smgcres  -  Change screen resolution
  525.  *
  526.  *  smgcres changes the screen resolution of the current window.
  527.  *  Allowable sizes are NORMAL and WIDE.
  528.  *
  529.  *  Nothing returned
  530.  ***/
  531. smgcres(char *value)
  532. {
  533.     int width;
  534.  
  535.     /* Skip if not supported */
  536.     if (width_wide == NULL || width_narrow == NULL)
  537.         return;
  538.  
  539.     /* Check value */
  540.     if (strcmp(value, "WIDE") == 0) {
  541.         width = wide_char;
  542.         smgputs(width_wide);
  543.     } else if (strcmp(value, "NORMAL") == 0) {
  544.         width = narrow_char;
  545.         smgputs(width_narrow);
  546.     }
  547.  
  548.     /* Change width */
  549.     orgchar.width = width;
  550.     newwidth(TRUE, width);
  551.  
  552.     /* Set resolution variable */
  553.     strcpy(sres, value);
  554. }
  555.  
  556. /***
  557.  *  smgrev  -  Set the reverse video status
  558.  *
  559.  *  smgrev either sets or resets the reverse video state, based on the
  560.  *  boolean argument.  This function is only called if the revexist
  561.  *  boolean variable is set to TRUE.  Otherwise there is no reverse
  562.  *  video available.
  563.  *
  564.  *  Nothing returned.
  565.  ***/
  566. smgrev(int status)
  567. {
  568.     smgputs(status ? begin_reverse : end_reverse);
  569. }
  570.  
  571. /***
  572.  *  smgeeol  -  Erase to end of line
  573.  *
  574.  *  When this function is called, the lines worth of text after the
  575.  *  cursor is erased.  This function is only called if the eolexist
  576.  *  boolean variable is set to TRUE.  Otherwise the display manager
  577.  *  will produce enough spaces to erase the line.
  578.  *
  579.  *  Nothing returned.
  580.  ***/
  581. smgeeol()
  582. {
  583.     smgputs(erase_to_end_line);
  584. }
  585.  
  586. /***
  587.  *  smgeeop  -  Erase to end of page (clear screen)
  588.  *
  589.  *  smgeeop really should be called smgclear because it really should
  590.  *  be an erase screen function.  When called, this routine will send
  591.  *  the erase entire screen sequence to the output.
  592.  *
  593.  *  Nothing returned.
  594.  ***/
  595. smgeeop()
  596. {
  597.     smgputs(erase_whole_display);
  598. }
  599.  
  600. /***
  601.  *  smgbeep  -  Ring the bell
  602.  *
  603.  *  smgbeep send a bell character to the output.  It might be possible
  604.  *  in the future to include the NOISY definition and attempt to flash
  605.  *  the screen, perhaps using LIGHT_SCREEN and DARK_SCREEN.
  606.  *
  607.  *  Nothing returned.
  608.  ***/
  609. smgbeep()
  610. {
  611.     ttputc('\007');
  612. }
  613.  
  614. /***
  615.  *  smggetstr  -  Get an SMG string capability by name
  616.  *
  617.  *  smggetstr attempts to obtain the escape sequence for a particular
  618.  *  job from the SMG library.  Most sequences do not require a parameter
  619.  *  with the sequence, others do.  In order to obtain the definition
  620.  *  without knowing ahead of time whether ornot the definition has a
  621.  *  parameter, we call SMG once with a parameter and if that fails, we
  622.  *  try again without one.  If both attempts fail, we will return the
  623.  *  NULL string.
  624.  *
  625.  *  Storage for the sequence comes from a local pool.
  626.  *
  627.  *  Returns:    Escape sequence
  628.  *        NULL    No escape sequence available
  629.  ***/ 
  630. char * smggetstr(int code)    /* Request code            */
  631. {
  632.     char * result;
  633.     int rlen, status;
  634.     
  635.     static char seq[1024];
  636.     static char * buffer = seq;
  637.     static int len = sizeof(seq);
  638.     static int arg[2] = { 1, 1 };
  639.  
  640.     /* Get sequence with one parameter */
  641.     status = SMG$GET_TERM_DATA(&termtype, &code, &len, &rlen, buffer, arg);
  642.     if (FAILURE(status)) {
  643.         /* Try again with zero parameters */
  644.         status = SMG$GET_TERM_DATA(&termtype, &code, &len, &rlen, buffer);
  645.         if (FAILURE(status))
  646.             return NULL;
  647.     }
  648.  
  649.     /* Check for empty result */
  650.     if (rlen == 0)
  651.         return NULL;
  652.     
  653.     /* Save current position so we can return it to caller */
  654.     result = buffer;
  655.     buffer[rlen++] = '\0';
  656.     buffer += rlen;
  657.  
  658.     /* Return capability to user */
  659.     return result;
  660. }
  661.  
  662. /***
  663.  *  smggetnum  -  Get numerical constant from SMG
  664.  *
  665.  *  smggetnum attempts to get a numerical constant from the SMG package.
  666.  *  If the constant cannot be found, -1 is returned.
  667.  *
  668.  *  code - SMG code
  669.  ***/
  670. int smggetnum(int code)
  671. {
  672.     int status, result;
  673.  
  674.     /* Call SMG for code translation */
  675.     status = SMG$GET_NUMERIC_DATA(&termtype, &code, &result);
  676.     return FAILURE(status) ? -1 : result;
  677. }
  678.  
  679. /***
  680.  *  smgaddkey  -  Add key to key map
  681.  *
  682.  *  smgaddkey adds a new escape sequence to the sequence table.
  683.  *  I am not going to try to explain this table to you in detail.
  684.  *  However, in short, it creates a tree which can easily be transversed
  685.  *  to see if input is in a sequence which can be translated to a
  686.  *  function key (arrows and find/select/do etc. are treated like
  687.  *  function keys).  If the sequence is ambiguous or duplicated,
  688.  *  it is silently ignored.
  689.  *
  690.  *  Nothing returned
  691.  *
  692.  *  code - SMG key code
  693.  *  fn   - Resulting keycode
  694.  ***/
  695. smgaddkey(int code, int fn)
  696. {
  697.     char * seq;
  698.     int first;
  699.     struct keyent * cur, * nxtcur;
  700.     
  701.     /* Skip on NULL sequence */
  702.     seq = smggetstr(code);
  703.     if (seq == NULL)
  704.         return;
  705.     
  706.     /* If no keys defined, go directly to insert mode */
  707.     first = 1;
  708.     if (nxtkey != keymap) {
  709.         
  710.         /* Start at top of key map */
  711.         cur = keymap;
  712.         
  713.         /* Loop until matches exhast */
  714.         while (*seq) {
  715.             
  716.             /* Do we match current character */
  717.             if (*seq == cur->ch) {
  718.                 
  719.                 /* Advance to next level */
  720.                 seq++;
  721.                 cur = cur->nxtlvl;
  722.                 first = 0;
  723.             } else {
  724.                 
  725.                 /* Try next character on same level */
  726.                 nxtcur = cur->samlvl;
  727.                 
  728.                 /* Stop if no more */
  729.                 if (nxtcur)
  730.                     cur = nxtcur;
  731.                 else
  732.                     break;
  733.             }
  734.         }
  735.     }
  736.     
  737.     /* Check for room in keymap */
  738.     if (strlen(seq) > NKEYENT - (nxtkey - keymap))
  739.         return;
  740.         
  741.     /* If first character if sequence is inserted, add to prefix table */
  742.     if (first)
  743.         keyseq[(unsigned char) *seq] = 1;
  744.         
  745.     /* If characters are left over, insert them into list */
  746.     for (first = 1; *seq; first = 0) {
  747.         
  748.         /* Make new entry */
  749.         nxtkey->ch = *seq++;
  750.         nxtkey->code = fn;
  751.         
  752.         /* If root, nothing to do */
  753.         if (nxtkey != keymap) {
  754.             
  755.             /* Set first to samlvl, others to nxtlvl */
  756.             if (first)
  757.                 cur->samlvl = nxtkey;
  758.             else
  759.                 cur->nxtlvl = nxtkey;
  760.         }
  761.  
  762.         /* Advance to next key */
  763.         cur = nxtkey++;
  764.     }
  765. }
  766.  
  767. /***
  768.  *  smgcap  -  Get capabilities from VMS's SMG library
  769.  *
  770.  *  smgcap retrives all the necessary capabilities from the SMG
  771.  *  library to operate microEmacs.  If an insufficent number of
  772.  *  capabilities are found for the particular terminal, an error
  773.  *  status is returned.
  774.  *
  775.  *  Returns:    0 if okay, <>0 if error
  776.  ***/
  777. int smgcap()
  778. {
  779.     char * set_cursor_abs;
  780.     int status;
  781.     
  782.     /* Start SMG package */
  783.     status = SMG$INIT_TERM_TABLE_BY_TYPE( &orgchar.type, &termtype);
  784.     if (FAILURE(status)) {
  785.         printf(TEXT189);
  786. /*                     "Cannot find entry for terminal type.\n" */
  787.         printf(TEXT190);
  788. /*                     "Check terminal type with \"SHOW TERMINAL\" or\n" */
  789.         printf(TEXT191);
  790. /*                     "try setting with \"SET TERMINAL/INQUIRE\"\n" */
  791.         return 1;
  792.     }
  793.         
  794.     /* Get reverse video */
  795.     begin_reverse = smggetstr(SMG$K_BEGIN_REVERSE);
  796.     end_reverse = smggetstr(SMG$K_END_REVERSE);
  797. #if    KEYPAD
  798.     applic_keypad = smggetstr(SMG$K_SET_APPLICATION_KEYPAD);
  799.     numeric_keypad = smggetstr(SMG$K_SET_NUMERIC_KEYPAD);
  800. #endif
  801.     begin_mouse = smggetstr(SMG$K_BEGIN_LOCATOR);
  802.     end_mouse = smggetstr(SMG$K_END_LOCATOR);
  803.     revexist = begin_reverse != NULL && end_reverse != NULL;
  804.     
  805.     /* Get erase to end of line */
  806.     erase_to_end_line = smggetstr(SMG$K_ERASE_TO_END_LINE);
  807.     eolexist = erase_to_end_line != NULL;
  808.     
  809.     /* Get more neat stuff */
  810.     erase_whole_display = smggetstr(SMG$K_ERASE_WHOLE_DISPLAY);
  811.     width_wide = smggetstr(SMG$K_WIDTH_WIDE);
  812.     width_narrow = smggetstr(SMG$K_WIDTH_NARROW);
  813.     narrow_char = smggetnum(SMG$K_COLUMNS);
  814.     wide_char = smggetnum(SMG$K_WIDE_SCREEN_COLUMNS);
  815.     set_cursor_abs = smggetstr(SMG$K_SET_CURSOR_ABS);
  816.  
  817.     /* Disable resoultion if unreasonable */
  818.     if (narrow_char < 10 || wide_char < 10) {
  819.         width_wide = width_narrow = NULL;
  820.         strcpy(sres, "NORMAL");
  821.     } else
  822.         /* Kludge resolution */
  823.         strcpy(sres, orgchar.width == wide_char ? "WIDE" : "NORMAL");
  824.  
  825.     /* Check for minimal operations */
  826.     if (set_cursor_abs == NULL || erase_whole_display == NULL) {
  827.         printf(TEXT192);
  828. /*                     "The terminal type does not have enough power to run\n" */
  829.         printf(TEXT193);
  830. /*                     "MicroEMACS.  Try a different terminal or check\n" */
  831.         printf(TEXT194);
  832. /*                     "type with \"SHOW TERMINAL\".\n" */
  833.         return 1;
  834.     }
  835.     
  836.     /* Add function keys to keymapping table */
  837.     smgaddkey(SMG$K_KEY_DOWN_ARROW,        SPEC | 'N');
  838.     smgaddkey(SMG$K_KEY_LEFT_ARROW,        SPEC | 'B');
  839.     smgaddkey(SMG$K_KEY_RIGHT_ARROW,    SPEC | 'F');
  840.     smgaddkey(SMG$K_KEY_UP_ARROW,        SPEC | 'P');
  841.  
  842.     smgaddkey(SMG$K_KEY_PF1,    CTRL | SPEC | '1');
  843.     smgaddkey(SMG$K_KEY_PF2,    CTRL | SPEC | '2');
  844.     smgaddkey(SMG$K_KEY_PF3,    CTRL | SPEC | '3');
  845.     smgaddkey(SMG$K_KEY_PF4,    CTRL | SPEC | '4');
  846.  
  847.     smgaddkey(SMG$K_KEY_0,        ALTD | '0');
  848.     smgaddkey(SMG$K_KEY_1,        ALTD | '1');
  849.     smgaddkey(SMG$K_KEY_2,        ALTD | '2');
  850.     smgaddkey(SMG$K_KEY_3,        ALTD | '3');
  851.     smgaddkey(SMG$K_KEY_4,        ALTD | '4');
  852.     smgaddkey(SMG$K_KEY_5,        ALTD | '5');
  853.     smgaddkey(SMG$K_KEY_6,        ALTD | '6');
  854.     smgaddkey(SMG$K_KEY_7,        ALTD | '7');
  855.     smgaddkey(SMG$K_KEY_8,        ALTD | '8');
  856.     smgaddkey(SMG$K_KEY_9,        ALTD | '9');
  857.     smgaddkey(SMG$K_KEY_PERIOD,    ALTD | '.');
  858.     smgaddkey(SMG$K_KEY_ENTER,     ALTD | 'E');
  859.     smgaddkey(SMG$K_KEY_COMMA,     ALTD | ',');
  860.     smgaddkey(SMG$K_KEY_MINUS,     ALTD | '-');
  861.  
  862.     smgaddkey(SMG$K_KEY_F1,        SPEC | '1');
  863.     smgaddkey(SMG$K_KEY_F2,        SPEC | '2');
  864.     smgaddkey(SMG$K_KEY_F3,        SPEC | '3');
  865.     smgaddkey(SMG$K_KEY_F4,        SPEC | '4');
  866.     smgaddkey(SMG$K_KEY_F5,        SPEC | '5');
  867.     smgaddkey(SMG$K_KEY_F6,        SPEC | '6');
  868.     smgaddkey(SMG$K_KEY_F7,        SPEC | '7');
  869.     smgaddkey(SMG$K_KEY_F8,        SPEC | '8');
  870.     smgaddkey(SMG$K_KEY_F9,        SPEC | '9');
  871.     smgaddkey(SMG$K_KEY_F10,    SPEC | '0');
  872.     smgaddkey(SMG$K_KEY_F11,    SHFT | SPEC | '1');
  873.     smgaddkey(SMG$K_KEY_F12,    SHFT | SPEC | '2');
  874.     smgaddkey(SMG$K_KEY_F13,    SHFT | SPEC | '3');
  875.     smgaddkey(SMG$K_KEY_F14,    SHFT | SPEC | '4');
  876.     smgaddkey(SMG$K_KEY_F15,    SHFT | SPEC | '5');
  877.     smgaddkey(SMG$K_KEY_F16,    SHFT | SPEC | '6');
  878.     smgaddkey(SMG$K_KEY_F17,    SHFT | SPEC | '7');
  879.     smgaddkey(SMG$K_KEY_F18,    SHFT | SPEC | '8');
  880.     smgaddkey(SMG$K_KEY_F19,    SHFT | SPEC | '9');
  881.     smgaddkey(SMG$K_KEY_F20,    SHFT | SPEC | '0');
  882.  
  883.     smgaddkey(SMG$K_KEY_E1,        SPEC | 'S');
  884.     smgaddkey(SMG$K_KEY_E2,        SPEC | 'C');
  885.     smgaddkey(SMG$K_KEY_E3,        SPEC | 'D');
  886.     smgaddkey(SMG$K_KEY_E4,        SPEC | '@');
  887.     smgaddkey(SMG$K_KEY_E5,        SPEC | 'Z');
  888.     smgaddkey(SMG$K_KEY_E6,        SPEC | 'V');
  889.  
  890.     smgaddkey(SMG$K_KEY_FIRST_DOWN,        MOUS | 'a');
  891.     smgaddkey(SMG$K_KEY_FIRST_UP,        MOUS | 'b');
  892.     smgaddkey(SMG$K_KEY_SECOND_DOWN,    MOUS | 'c');
  893.     smgaddkey(SMG$K_KEY_SECOND_UP,        MOUS | 'd');
  894.     smgaddkey(SMG$K_KEY_THIRD_DOWN,        MOUS | 'e');
  895.     smgaddkey(SMG$K_KEY_THIRD_UP,        MOUS | 'f');
  896.     smgaddkey(SMG$K_KEY_FOURTH_DOWN,    MOUS | 'g');
  897.     smgaddkey(SMG$K_KEY_FOURTH_UP,        MOUS | 'h');
  898.     /* Everything okay */
  899.     return 0;
  900. }
  901.  
  902. /***
  903.  *  smgopen  -  Get terminal type and open terminal
  904.  *
  905.  *  Nothing returned
  906.  ***/
  907. smgopen()
  908. {
  909.     static int first_time = 1;
  910.     
  911.     /* Open channel to terminal (also sets sizes in TERM structure) */
  912.     ttopen();
  913.  
  914.     /* Get SMG */
  915.     if (first_time)
  916.     {
  917.         first_time = 0;
  918.         if (smgcap())
  919.             meexit( 1);
  920.     }
  921.  
  922. #if    KEYPAD
  923.     smgputs(applic_keypad);
  924. #endif
  925. #ifdef NEVER
  926.     smgputs( begin_mouse);
  927. #endif
  928. }
  929.  
  930. smgclose()
  931. {
  932. #ifdef NEVER
  933.     smgputs( end_mouse);
  934. #endif
  935. #if    KEYPAD
  936.     if ((orgchar.tt2 & TT2$M_APP_KEYPAD)==0)
  937.         smgputs(numeric_keypad);
  938. #endif
  939.     ttclose();
  940. }
  941.  
  942. /***
  943.  *  smgputs  -  Send a string to ttputc
  944.  *
  945.  *  smgputs is a short-cut routine to handle sending a string of characters
  946.  *  to the character output routine.  A check is made for a NULL string,
  947.  *  while is considered valid.  A NULL string will produce no output.
  948.  *
  949.  *  Nothing returned.
  950.  ***/
  951. smgputs(string)
  952. char * string;                /* String to write        */
  953. {
  954.     if (string)
  955.         while (*string)
  956.             ttputc(*string++);
  957. }
  958.  
  959. /***
  960.  *  smgqin  -  Queue character for input
  961.  *
  962.  *  smgqin queues the character into the input buffer for later
  963.  *  reading.  This routine will mostly be used by mouse support
  964.  *  and other escape sequence processing.
  965.  *
  966.  *  Nothing returned.
  967.  *
  968.  *  ch  - (Extended) character to add
  969.  ***/
  970. smgqin(int ch)
  971. {
  972.     /* Check for overflow */
  973.     if (inbuft == &inbuf[sizeof(inbuf)]) {
  974.         
  975.         /* Annoy user */
  976.         smgbeep();
  977.         return;
  978.     }
  979.     
  980.     /* Add character */
  981.     *inbuft++ = ch;
  982. }
  983.  
  984. /***
  985.  *  smggcook  -  Get characters from input device
  986.  *
  987.  *  smggcook "cooks" input from the input device and places them into
  988.  *  the input queue.
  989.  *
  990.  *  Nothing returned.
  991.  ***/
  992. smggcook()
  993. {
  994.     char ch;
  995.     struct keyent * cur;
  996.     
  997.     /* Get first character untimed */
  998.     ch = ttgetc();
  999.     smgqin((unsigned char)ch);
  1000.     
  1001.     /* Skip if the key isn't a special leading escape sequence */
  1002.     if (keyseq[(unsigned char)ch] == 0)
  1003.         return;
  1004.  
  1005.     /* Start translating */
  1006.     cur = keymap;
  1007.     while (cur) {
  1008.         if (cur->ch == ch) {
  1009.             /* Is this the end */
  1010.             if (cur->nxtlvl == NULL) {
  1011.                 /* Replace all character with new sequence */
  1012.                 inbuft = inbuf;
  1013.                 smgqin(cur->code);
  1014.                 return;
  1015.             } else {
  1016.                 /* Advance to next level */
  1017.                 cur = cur->nxtlvl;
  1018.             
  1019.                 /* Get next character, timed */
  1020.                 ch = ttgetc_shortwait();
  1021.                 if (ch < 0)
  1022.                     return;
  1023.  
  1024.                 /* Queue character */
  1025.                 smgqin((unsigned char)ch);
  1026.             }
  1027.         } else
  1028.             /* Try next character on same level */
  1029.             cur = cur->samlvl;
  1030.     }
  1031. }
  1032.  
  1033. /***
  1034.  *  smggetc  -  Get a character
  1035.  *
  1036.  *  smggetc obtains input from the character input queue.  If the queue
  1037.  *  is empty, a call to smggcook() is called to fill the input queue.
  1038.  *
  1039.  *  Returns:    character
  1040.  ***/
  1041. int smggetc()
  1042. {
  1043.     int ch;
  1044.  
  1045.     /* Loop until character found */
  1046.     while (1) {
  1047.     
  1048.         /* Get input from buffer, if available */
  1049.         if (inbufh != inbuft) {
  1050.             ch = *inbufh++;
  1051.             if (inbufh == inbuft)
  1052.                 inbufh = inbuft = inbuf;
  1053.             break;
  1054.         } else
  1055.     
  1056.             /* Fill input buffer */
  1057.             smggcook();
  1058.     }
  1059.     
  1060.     /* Return next character */
  1061.     return (int) ch;
  1062. }
  1063.  
  1064. /***
  1065.  *  spal  -  Set palette type
  1066.  *
  1067.  *  spal sets the palette colors for the 8 colors available.  Currently,
  1068.  *  there is nothing here, but some DEC terminals, (VT240 and VT340) have
  1069.  *  a color palette which is available under the graphics modes.
  1070.  *  Further, a foreign terminal could also change color registers.
  1071.  *
  1072.  *  Nothing returned
  1073.  ***/
  1074. spal()
  1075. {
  1076.     /* Nothing */
  1077. }
  1078.  
  1079. #if FLABEL
  1080. /***
  1081.  *  fnclabel  -  Label function keys
  1082.  *
  1083.  *  Currently, smg does not have function key labeling.
  1084.  *
  1085.  *  Returns:    status.
  1086.  *
  1087.  *  flag - TRUE if default
  1088.  *  n    - Numerical argument
  1089.  ***/
  1090. int fnclabel(int flag, int n)
  1091. {
  1092.     /* On machines with no function keys...don't bother */
  1093.     return TRUE;
  1094. }
  1095. #endif /* FLABEL */
  1096.  
  1097. #endif    /* End of SMG terminal type */
  1098.