ecurcvr.c 51 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187
  1. /* #define DEBUG_RAWLOG */
  2. /* #define DEFENSIVE */
  3. /* #define ANSI_DEBUG */
  4. /* #define ANSI_DEBUG_AAS */
  5. /* #define ANSI_DEBUG_TEXT */
  6. /* #define ANSI_DEBUG_SEQ */
  7. /* #define ANSI_DEBUG_NOBUF */
  8. /* #define ANSI_DEBUG_LOGFILE "/dev/tty2f" */
  9. /* #define CURSOR_DEBUG */
  10. #ifndef LIMIT_BELL
  11. #define LIMIT_BELL
  12. #endif
  13. #if defined(WHT) && defined(WHT_CONFUSED)
  14. #define ANSI_DEBUG
  15. #define ANSI_DEBUG_AAS /* show "aas:" accumulation */
  16. #define ANSI_DEBUG_TEXT /** show text */
  17. #define ANSI_DEBUG_SEQ
  18. #define ANSI_DEBUG_NOBUF
  19. #define ANSI_DEBUG_LOGFILE "./ansi.log"
  20. #endif
  21. /*+-------------------------------------------------------------------------
  22. ecurcvr.c - rcvr process + ANSI filter + non-ANSI<->ANSI hoop jumping
  23. wht@wht.net
  24. Defined functions:
  25. accumulate_ansi_sequence(rchar)
  26. ansi_CNL()
  27. ansi_CPL()
  28. ansi_CUB()
  29. ansi_CUD()
  30. ansi_CUF()
  31. ansi_CUP()
  32. ansi_CUU()
  33. ansi_DCH()
  34. ansi_DL()
  35. ansi_DSR()
  36. ansi_ECH()
  37. ansi_ED()
  38. ansi_EL()
  39. ansi_HPA()
  40. ansi_ICH()
  41. ansi_IL()
  42. ansi_SD()
  43. ansi_SGR()
  44. ansi_SU()
  45. ansi_VPA()
  46. is_ansi_terminator(rchar)
  47. lgetc_rcvr()
  48. lgetc_rcvr_raw()
  49. need_rcvr_restart()
  50. process_ansi_sequence()
  51. process_rcvd_char(rchar)
  52. rcvd_ESC()
  53. rcvr()
  54. rcvr_ansi_filter(rchar)
  55. rcvr_ansi_filter_control(on_off, display)
  56. rcvr_conditional_restart(restart_flag, display_flag)
  57. rcvr_log_open()
  58. rcvrdisp(buf, buflen)
  59. rcvrdisp_actual()
  60. rcvrdisp_actual2()
  61. rcvrdisp_p()
  62. rcvrdisp_v()
  63. redisplay_rcvr_screen()
  64. saved_cursor_restore_cursor()
  65. saved_cursor_save_cursor()
  66. spaces(buf, buflen)
  67. spaces_trap(code, buf, buflen)
  68. start_rcvr_process(notify_flag)
  69. xmtr_wfp_debug_hack()
  70. Any perceptible delay will eventually get on your nerves. --Bob Hyers
  71. --------------------------------------------------------------------------*/
  72. /*+:EDITS:*/
  73. /*:04-26-2000-11:15-wht@bob-RELEASE 4.42 */
  74. /*:01-24-1997-02:37-wht@yuriatin-SOURCE RELEASE 4.00 */
  75. /*:09-28-1996-23:52-wht@yuriatin-shmr_notify_xmtr_of_telnet_close */
  76. /*:09-24-1996-15:24-wht@yuriatin-fix rcvrdisp/ff-stderr synch */
  77. /*:09-11-1996-20:00-wht@yuriatin-3.48-major telnet,curses,structural overhaul */
  78. /*:08-11-1996-02:10-wht@kepler-rename ecu_log_event to logevent */
  79. /*:12-12-1995-14:22-wht@kepler-[no line attached] on such rcvr start */
  80. /*:11-23-1995-11:20-wht@kepler-source control 3.37 for tsx-11 */
  81. /*:11-14-1995-10:23-wht@kepler-3.37.80-source control point: SOCKETS */
  82. /*:11-13-1995-12:26-wht@kepler-start_rcvr_process moved ecusighdl.c */
  83. /*:11-13-1995-12:22-wht@kepler-need_rcvr_restart checks Liofd for open line */
  84. /*:11-13-1995-12:21-wht@kepler-need_rcvr_restart was a macro in ecu.h */
  85. /*:11-04-1995-21:02-wht@kepler-if telnet_cmd called, rtn 0 to lgetc caller */
  86. /*:11-03-1995-16:54-wht@wwtp1-use CFG_TelnetOption */
  87. /*:10-09-1995-15:41-wht@kepler-SU newlines were sent to stderr not rcvrdisp */
  88. /*:10-09-1995-15:03-wht@kepler-label ease case in process_ansi_sequence */
  89. /*:09-16-1995-15:06-root@kepler-rename specific ANSI_DEBUG partitions */
  90. /*:01-12-1995-15:19-wht@n4hgf-apply Andrew Chernov 8-bit clean+FreeBSD patch */
  91. /*:05-04-1994-04:39-wht@n4hgf-ECU release 3.30 */
  92. /*:10-03-1993-20:09-wht@n4hgf-document read errors w/fd on screen */
  93. /*:08-18-1993-05:49-wht@n4hgf-rcvr seems ready for release */
  94. /*:08-07-1993-20:38-wht@n4hgf-add xmtr_wfp_debug_hack */
  95. /*:07-23-1993-15:42-wht@n4hgf-detect/ignore ESC = or ESC > VT100 keypad */
  96. /*:07-17-1993-12:36-wht@n4hgf-no more rcvrdisp_actual2_xmtr_buffer junk */
  97. /*:12-31-1992-15:34-wht@n4hgf-handle VT100 save/restore cursor */
  98. /*:12-03-1992-14:24-wht@n4hgf-differentiate between type 5 and other DSR */
  99. /*:09-10-1992-13:58-wht@n4hgf-ECU release 3.20 */
  100. /*:09-06-1992-13:29-wht@n4hgf-add receiver process buffered screen write */
  101. /*:08-22-1992-15:38-wht@n4hgf-ECU release 3.20 BETA */
  102. /*:05-29-1992-13:28-wht@n4hgf-no banner - phone numbers are security risk */
  103. /*:11-11-1991-14:25-wht@n4hgf-lzero_length_read_detected code */
  104. /*:11-11-1991-12:45-wht@n4hgf-add LIMIT_BELL code */
  105. /*:08-26-1991-16:39-wht@n4hgf2-SD was still hopelessly manic */
  106. /*:07-25-1991-12:56-wht@n4hgf-ECU release 3.10 */
  107. /*:07-05-1991-06:13-wht@n4hgf-SD was in baaaaadd shape */
  108. /*:01-09-1991-22:31-wht@n4hgf-ISC port */
  109. /*:12-26-1990-14:32-wht@n4hgf-use memset in spaces() */
  110. /*:12-21-1990-21:06-wht@n4hgf-CUF and CUB set non-ansi cursor incorrectly */
  111. /*:12-20-1990-16:27-wht@n4hgf-had SU and SD swapped */
  112. /*:11-30-1990-18:39-wht@n4hgf-non-ansi console rcvr appears to be working */
  113. /*:11-28-1990-14:13-wht@n4hgf-start non-ansi console support */
  114. /*:08-14-1990-20:40-wht@n4hgf-ecu3.00-flush old edit history */
  115. #include "ecu.h"
  116. #include "ecukey.h"
  117. #if defined(CFG_TelnetOption)
  118. #include <arpa/telnet.h>
  119. #endif /* defined(CFG_TelnetOption) */
  120. #ifdef CFG_SemWithShm
  121. #include <sys/ipc.h>
  122. #include <sys/sem.h>
  123. #endif /* CVRDISP_PV */
  124. extern int errno;
  125. extern char rcvr_log_file[]; /* if rcvr_log!= 0,log filename */
  126. extern int rcvr_log; /* rcvr log active if != 0 */
  127. extern FILE *rcvr_log_fp; /* rcvr log file */
  128. extern int rcvr_log_raw; /* if true, log all, else filter ctl chrs */
  129. extern int rcvr_log_append; /* if true, append, else scratch */
  130. extern int rcvr_log_flusheach; /* if true, flush log on each char */
  131. extern int rcvr_log_gen_title;
  132. extern UINT tcap_LINES; /* terminal line quantity - see ecutcap.c */
  133. extern UINT tcap_COLS; /* terminal column quantity - see ecutcap.c */
  134. extern UINT LINESxCOLS;
  135. static char esc = ESC;
  136. #define MAX_ANSI_LEN 30 /* generous */
  137. char ansibuf[MAX_ANSI_LEN];
  138. char *ansi;
  139. int ansilen = 0;
  140. int in_ansi_accumulation = 0;
  141. int saved_cursor_y;
  142. int saved_cursor_x;
  143. #define RCVR_RDQUAN 250
  144. uchar lgetc_buf[RCVR_RDQUAN];
  145. uchar *lgetc_ptr;
  146. int lgetc_count;
  147. uchar autorz_frame[] =
  148. {SUB, 'B', '0', '0'};
  149. #ifdef ANSI_DEBUG
  150. FILE *wfp = (FILE *) 0;
  151. #endif
  152. /*
  153. * the main purpose of this is to map ruling characters, but as a
  154. * side effect, also map others to reasonable, near, amusing, or
  155. * random printing characters as well
  156. */
  157. uchar non_multiscreen_hi_map[128] =
  158. {
  159. /* 80 */ 'c', 'u', 'e', 'a', 'a', 'a', 'a', 'c',
  160. /* 88 */ 'e', 'e', 'e', 'i', 'i', 'i', 'a', 'a',
  161. /* 90 */ 'e', 'e', 'a', 'a', 'a', 'o', 'u', 'u',
  162. /* 98 */ 'y', 'o', 'u', 'X', '#', 'Y', 'P', 'f',
  163. /* A0 */ 'a', 'i', 'o', 'u', 'n', 'n', 'a', 'o',
  164. /* A8 */ '?', '-', '-', '%', '%', '|', '<', '>',
  165. /* B0 */ '#', '#', '#', '|', '+', '+', '+', '.',
  166. /* B8 */ '.', '+', '|', '.', '\'', '\'', '\'', '.',
  167. /* C0 */ '`', '+', '+', '+', '-', '+', '+', '+',
  168. /* C8 */ '`', '.', '+', '+', '+', '=', '+', '+',
  169. /* D0 */ '+', '+', '+', '`', '`', '.', '.', '+',
  170. /* D8 */ '+', '\'', '.', '#', '_', '|', '|', '-',
  171. /* E0 */ 'a', 'b', 'F', 'T', 'E', 'o', 'u', 't',
  172. /* E8 */ 'I', '0', 'O', 'o', 'o', 'o', 'e', 'n',
  173. /* F0 */ '=', '+', '>', '<', 'f', 'j', '%', '=',
  174. /* F8 */ 'o', '.', '.', 'V', 'n', '2', '*', ' '
  175. };
  176. /*
  177. * prototypes for ansi filter code gaggled at bottom
  178. * of this module
  179. */
  180. #if (__STDC__ == 1)
  181. #define pp(s) s
  182. #else
  183. #define pp(s) ()
  184. #endif
  185. #if !defined(CFG_NoAnsiEmulation)
  186. void redisplay_rcvr_screen pp((void));
  187. void spaces_trap pp((int code, uchar * buf, UINT buflen));
  188. void spaces pp((uchar * buf, UINT buflen));
  189. void ansi_SGR pp((void));
  190. void ansi_CUP pp((void));
  191. void ansi_CUU pp((void));
  192. void ansi_CUD pp((void));
  193. void ansi_CUF pp((void));
  194. void ansi_CUB pp((void));
  195. void ansi_DSR pp((void));
  196. void ansi_ED pp((void));
  197. void ansi_EL pp((void));
  198. void ansi_ECH pp((void));
  199. void ansi_SU pp((void));
  200. void ansi_SD pp((void));
  201. void ansi_HPA pp((void));
  202. void ansi_VPA pp((void));
  203. void ansi_IL pp((void));
  204. void ansi_ICH pp((void));
  205. void ansi_DL pp((void));
  206. void ansi_DCH pp((void));
  207. void ansi_CPL pp((void));
  208. void ansi_CNL pp((void));
  209. void saved_cursor_save_cursor pp((void));
  210. void saved_cursor_restore_cursor pp((void));
  211. void rcvd_ESC pp((void));
  212. int is_ansi_terminator pp((UINT rchar));
  213. void accumulate_ansi_sequence pp((UINT rchar));
  214. void process_ansi_sequence pp((void));
  215. int rcvr_ansi_filter pp((int rchar));
  216. #endif /* !defined(CFG_NoAnsiEmulation) */
  217. void rcvrdisp pp((char *buf, int buflen));
  218. void rcvrdisp_actual pp((void));
  219. void rcvrdisp_actual2 pp((void));
  220. void rcvrdisp_p pp((void));
  221. void rcvrdisp_v pp((void));
  222. void rcvr();
  223. void rcvr_notify();
  224. #undef pp
  225. /*+-----------------------------------------------------------------------
  226. start_rcvr_process(notify_flag) - start RCVR process if not extant
  227. ------------------------------------------------------------------------*/
  228. void
  229. start_rcvr_process(notify_flag)
  230. int notify_flag;
  231. {
  232. extern UINT32 colors_current;
  233. extern int xmtr_killed_rcvr;
  234. CFG_PidType rcvr_pid;
  235. fflush(so);
  236. fflush(se);
  237. if (shm->Liofd <= 0)
  238. {
  239. UINT32 colors_at_entry = colors_current;
  240. setcolor(colors_notify);
  241. ff(se, "[no line attached]");
  242. setcolor(colors_at_entry);
  243. ff(se, "\r\n");
  244. return;
  245. }
  246. if (shm->rcvr_pid > 0) /* if process already active, just ... */
  247. return;
  248. if (rcvr_log && rcvr_log_file[0] && rcvr_log_fp)
  249. {
  250. fclose(rcvr_log_fp);
  251. rcvr_log_fp = 0;
  252. }
  253. xmtr_killed_rcvr = 0;
  254. rcvr_pid = smart_fork();
  255. if (!rcvr_pid) /* if we are the (spawned) rcvr process */
  256. {
  257. if (notify_flag)
  258. {
  259. char *text = "[interactive mode]";
  260. UINT32 colors_at_entry = colors_current;
  261. setcolor(colors_notify);
  262. rcvrdisp(text, strlen(text));
  263. setcolor(colors_at_entry);
  264. rcvrdisp("\r\n", 2);
  265. rcvrdisp_actual();
  266. }
  267. #if defined(FORK_DEBUG)
  268. vlogevent(getppid(), "RCVR-START pid %d", getpid());
  269. #endif
  270. rcvr(); /* run until killed */
  271. /* NOTREACHED */
  272. }
  273. else if (rcvr_pid > 0) /* we are the father (xmtr) process */
  274. {
  275. shm->rcvr_pid = rcvr_pid;
  276. #if defined(FORK_DEBUG)
  277. sleep(2);
  278. #endif
  279. if (rcvr_log)
  280. rcvr_log_append = 1; /* until next %log -s */
  281. xmtr_signals();
  282. return;
  283. }
  284. shm->rcvr_pid = -1; /* no receiver active */
  285. pprintf("\n\nECU could not fork for receive process\n");
  286. termecu(TERMECU_NO_FORK_FOR_RCVR);
  287. /* NOTREACHED */
  288. } /* end of _start_rcvr_process */
  289. /*+-------------------------------------------------------------------------
  290. rcvr_conditional_restart(restart_flag,display_flag)
  291. This function is called by the XMTR to decide if the receiver
  292. should be restarted (yes if line open, no if not)
  293. --------------------------------------------------------------------------*/
  294. void
  295. rcvr_conditional_restart(restart_flag, display_flag)
  296. int restart_flag;
  297. int display_flag;
  298. {
  299. if (restart_flag)
  300. {
  301. if (shm->Liofd == -1)
  302. {
  303. if (display_flag)
  304. {
  305. UINT32 colors_at_entry = colors_current;
  306. extern UINT32 colors_current;
  307. setcolor(colors_notify);
  308. ff(se, "[no line attached]");
  309. setcolor(colors_at_entry);
  310. ff(se, "\r\n");
  311. }
  312. return;
  313. }
  314. start_rcvr_process(display_flag);
  315. }
  316. } /* end of rcvr_conditional_restart */
  317. /*+-------------------------------------------------------------------------
  318. need_rcvr_restart() - will rcvr need restart?
  319. We want to kill the receiver to get it out of the picture
  320. for a while. If it is already dead, we do not want to
  321. start it up when we are done.
  322. If shm->rcvr_pid == -2, the receiver is not active, but queued restart
  323. has been requested by some function.
  324. We don't want to do it if a procedure is executing or if no line is open.
  325. --------------------------------------------------------------------------*/
  326. int
  327. need_rcvr_restart()
  328. {
  329. return ((shm->rcvr_pid > 0) || ((shm->rcvr_pid == -2) &&
  330. !proc_level)); /* && (shm->Liofd >= 0)); */
  331. } /* end of need_rcvr_restart */
  332. /*+-------------------------------------------------------------------------
  333. rcvrdisp_p() - lock rcvrdisp mechanism
  334. --------------------------------------------------------------------------*/
  335. #ifdef CFG_SemWithShm
  336. void
  337. rcvrdisp_p()
  338. {
  339. int retn;
  340. struct sembuf sembuf;
  341. sembuf.sem_num = 0;
  342. sembuf.sem_op = -1;
  343. sembuf.sem_flg = 0;
  344. while (1)
  345. {
  346. if (((retn = semop(shm->rcvrdisp_semid, &sembuf, 1)) >= 0) ||
  347. (errno != EINTR))
  348. {
  349. break;
  350. }
  351. }
  352. if ((retn < 0) && (errno != EINVAL))
  353. {
  354. strcpy(lopen_err_str, "rcvrdisp_p failed: SysV IPC error");
  355. termecu(TERMECU_IPC_ERROR);
  356. }
  357. } /* end of rcvrdisp_p */
  358. #endif /* CFG_SemWithShm */
  359. /*+-------------------------------------------------------------------------
  360. rcvrdisp_v() - unlock rcvrdisp mechanism
  361. --------------------------------------------------------------------------*/
  362. #ifdef CFG_SemWithShm
  363. void
  364. rcvrdisp_v()
  365. {
  366. int retn;
  367. struct sembuf sembuf;
  368. sembuf.sem_num = 0;
  369. sembuf.sem_op = 1;
  370. sembuf.sem_flg = 0;
  371. while (1)
  372. {
  373. if (((retn = semop(shm->rcvrdisp_semid, &sembuf, 1)) >= 0) ||
  374. (errno != EINTR))
  375. {
  376. break;
  377. }
  378. }
  379. if ((retn < 0) && (errno != EINVAL))
  380. {
  381. strcpy(lopen_err_str, "rcvrdisp_v failed: SysV IPC error");
  382. termecu(TERMECU_IPC_ERROR);
  383. }
  384. } /* end of rcvrdisp_v */
  385. #endif /* CFG_SemWithShm */
  386. /*+-------------------------------------------------------------------------
  387. rcvrdisp_actual() - actual write to screen
  388. --------------------------------------------------------------------------*/
  389. void
  390. rcvrdisp_actual()
  391. {
  392. #ifdef CFG_SemWithShm
  393. rcvrdisp_p();
  394. #endif /* CFG_SemWithShm */
  395. if (shm->rcvrdisp_count)
  396. write(TTYOUT, shm->rcvrdisp_buffer, shm->rcvrdisp_count);
  397. shm->rcvrdisp_ptr = shm->rcvrdisp_buffer;
  398. shm->rcvrdisp_count = 0;
  399. #ifdef CFG_SemWithShm
  400. rcvrdisp_v();
  401. #endif /* CFG_SemWithShm */
  402. } /* end of rcvrdisp_actual */
  403. /*+-------------------------------------------------------------------------
  404. rcvrdisp_actual2() - for tcap, flush only if not receiver
  405. --------------------------------------------------------------------------*/
  406. void
  407. rcvrdisp_actual2()
  408. {
  409. if (getpid() == shm->rcvr_pid)
  410. return;
  411. #ifdef CFG_SemWithShm
  412. rcvrdisp_p();
  413. #endif /* CFG_SemWithShm */
  414. if (shm->rcvrdisp_count)
  415. write(TTYOUT, shm->rcvrdisp_buffer, shm->rcvrdisp_count);
  416. shm->rcvrdisp_ptr = shm->rcvrdisp_buffer;
  417. shm->rcvrdisp_count = 0;
  418. #ifdef CFG_SemWithShm
  419. rcvrdisp_v();
  420. #endif /* CFG_SemWithShm */
  421. } /* end of rcvrdisp_actual2 */
  422. /*+-------------------------------------------------------------------------
  423. rcvrdisp(buf,buflen) - logical write to screen
  424. --------------------------------------------------------------------------*/
  425. void
  426. rcvrdisp(buf, buflen)
  427. char *buf;
  428. int buflen;
  429. {
  430. if ((unsigned)(buflen + shm->rcvrdisp_count) >
  431. (unsigned)sizeof(shm->rcvrdisp_buffer))
  432. {
  433. rcvrdisp_actual();
  434. }
  435. if (((unsigned)buflen + shm->rcvrdisp_count) >
  436. (unsigned)sizeof(shm->rcvrdisp_buffer))
  437. {
  438. write(TTYOUT, buf, buflen);
  439. return;
  440. }
  441. #ifdef CFG_SemWithShm
  442. rcvrdisp_p();
  443. #endif /* CFG_SemWithShm */
  444. memcpy(shm->rcvrdisp_ptr, buf, buflen);
  445. shm->rcvrdisp_ptr += buflen;
  446. shm->rcvrdisp_count += buflen;
  447. #ifdef CFG_SemWithShm
  448. rcvrdisp_v();
  449. #endif /* CFG_SemWithShm */
  450. } /* end of rcvrdisp */
  451. /*+-------------------------------------------------------------------------
  452. lgetc_rcvr_raw() - rcvr_raw version of get char from line
  453. --------------------------------------------------------------------------*/
  454. UINT
  455. lgetc_rcvr_raw()
  456. {
  457. extern int errno;
  458. #ifdef DEBUG_RAWLOG
  459. static int fd_rawlog;
  460. if (!fd_rawlog)
  461. {
  462. char *fnm = "/tmp/ecurcvr_raw.log";
  463. #if 1
  464. fd_rawlog = open(fnm, O_WRONLY | O_APPEND | O_CREAT, 0666);
  465. #else
  466. creat(fnm, 0666);
  467. fd_rawlog = open(fnm, O_WRONLY | O_APPEND, 0);
  468. #endif
  469. }
  470. #endif
  471. if (!lgetc_count)
  472. {
  473. rcvrdisp_actual();
  474. while (lgetc_count <= 0)
  475. {
  476. errno = 0;
  477. if ((lgetc_count =
  478. read(shm->Liofd, lgetc_buf, RCVR_RDQUAN)) < 0)
  479. {
  480. if (errno == EINTR) /* if signal interrupted, ... */
  481. continue;/* ... read again */
  482. termecu(TERMECU_LINE_READ_ERROR);
  483. }
  484. if (!lgetc_count)
  485. {
  486. if (shm->Ltelnet) /* remote reject or disconnect */
  487. shmr_notify_xmtr_of_telnet_close(); /* never return */
  488. lzero_length_read_detected(); /* maybe terminate program
  489. * ... */
  490. continue; /* ... but if not, read again */
  491. }
  492. #ifdef DEBUG_RAWLOG
  493. if (fd_rawlog)
  494. write(fd_rawlog, lgetc_buf, lgetc_count);
  495. #endif
  496. }
  497. shm->rcvd_chars += lgetc_count;
  498. shm->rcvd_chars_this_connect += lgetc_count;
  499. lgetc_ptr = lgetc_buf;
  500. }
  501. lgetc_count--;
  502. return (*lgetc_ptr++);
  503. } /* end of lgetc_rcvr_raw */
  504. /*+-------------------------------------------------------------------------
  505. lgetc_rcvr() - rcvr version of get char from line
  506. --------------------------------------------------------------------------*/
  507. UINT
  508. lgetc_rcvr()
  509. {
  510. UINT char_rtnd = lgetc_rcvr_raw();
  511. #if defined(CFG_TelnetOption)
  512. if ((shm->Ltelnet) && !shm->Ltelnet_raw && (char_rtnd == IAC))
  513. {
  514. telnet_cmd(1);
  515. char_rtnd = 0;
  516. }
  517. #endif /* defined(CFG_TelnetOption) */
  518. if (shm->Lparity)
  519. return (char_rtnd & 0x7F);
  520. else
  521. return (char_rtnd);
  522. } /* end of lgetc_rcvr */
  523. /*+-------------------------------------------------------------------------
  524. rcvr_log_open()
  525. --------------------------------------------------------------------------*/
  526. void
  527. rcvr_log_open()
  528. {
  529. if (rcvr_log) /* if xmtr set us up for logging */
  530. {
  531. rcvr_log_fp = fopen(rcvr_log_file, rcvr_log_append ? "a" : "w");
  532. rcvr_log_append = 1; /* until next %log -s */
  533. if (!rcvr_log_fp)
  534. {
  535. ff(se, "ecu RCVR: Could not open log file: %s\r\n", rcvr_log_file);
  536. ff(se, "recording aborted.\r\n");
  537. rcvr_log = 0;
  538. }
  539. rcvr_log_gen_title = 0;
  540. }
  541. } /* end of rcvr_log_open */
  542. /*+-------------------------------------------------------------------------
  543. process_rcvd_char(rchar) - process a received character
  544. return 0 if char should be written to console, 1 otherwise
  545. --------------------------------------------------------------------------*/
  546. int
  547. process_rcvd_char(rchar)
  548. UINT rchar;
  549. {
  550. register int itmp;
  551. #ifdef LIMIT_BELL
  552. long now;
  553. static long last_bell_time = -1L;
  554. #endif
  555. /*
  556. * automatic ZMODEM frame detection (expensive CPU burners for lazy
  557. * folks)
  558. */
  559. if (shm->autorz)
  560. {
  561. if ((uchar) rchar == autorz_frame[shm->autorz_pos])
  562. {
  563. itmp = shm->autorz_pos; /* copy to register trying to be quick */
  564. if (++itmp == sizeof(autorz_frame))
  565. {
  566. if (lgetc_count)
  567. {
  568. rcvrdisp(lgetc_ptr, lgetc_count);
  569. lgetc_count = 0;
  570. }
  571. shmr_notify_zmodem_frame();
  572. pause(); /* wait for death */
  573. itmp = 0; /* in case something starts us up */
  574. }
  575. shm->autorz_pos = itmp;
  576. return (!itmp); /* don't try to print ^X */
  577. }
  578. else
  579. shm->autorz_pos = 0;
  580. }
  581. /*
  582. * BEL and alarm-on-incoming-data processing
  583. */
  584. if (shm->bell_notify_state == 2)
  585. {
  586. shm->bell_notify_state = 1;
  587. bell_notify(XBELL_3T);
  588. }
  589. else if (rchar == BEL)
  590. {
  591. #ifdef LIMIT_BELL
  592. time(&now);
  593. if ((now - last_bell_time) < 2L)
  594. return (1);
  595. last_bell_time = now;
  596. #endif
  597. bell_notify(XBELL_ATTENTION);
  598. return (0);
  599. }
  600. #ifdef TANDEM_ENQ_ACK /* for my friend John Dashner at Tandem */
  601. else if (rchar == ENQ)
  602. {
  603. lputc(ACK);
  604. return (0);
  605. }
  606. #endif
  607. /*
  608. * receiver logging
  609. */
  610. if (rcvr_log && rcvr_log_fp)
  611. {
  612. /* if raw mode or character not excluded from "cooked" logging */
  613. if (rcvr_log_raw || isprint(rchar) ||
  614. (rchar == NL) || (rchar == TAB))
  615. {
  616. LOGPUTC(rchar, rcvr_log_fp);
  617. }
  618. /* back if log file if not raw and char is backspace */
  619. else if (!rcvr_log_raw && (rchar == BS))
  620. {
  621. long logpos = 0;
  622. if (logpos = ftell(rcvr_log_fp))
  623. fseek(rcvr_log_fp, logpos - 1, 0);
  624. }
  625. if (rcvr_log_flusheach)
  626. fflush(rcvr_log_fp);
  627. }
  628. #if !defined(CFG_NoAnsiEmulation)
  629. if (shm->rcvr_ansi_filter)
  630. return (rcvr_ansi_filter(rchar));
  631. #endif
  632. return (0);
  633. } /* end of process_rcvd_char */
  634. /*+-----------------------------------------------------------------------
  635. rcvr() - copy characters from remote line to screen
  636. ------------------------------------------------------------------------*/
  637. void
  638. rcvr()
  639. {
  640. uchar rchar;
  641. uchar nlchar = NL;
  642. char *get_ttyname();
  643. #if defined(ANSI_DEBUG)
  644. char s80[80];
  645. #endif /* ANSI_DEBUG */
  646. #ifdef ANSI_DEBUG
  647. wfp = fopen(ANSI_DEBUG_LOGFILE, "a");
  648. if (ulindex(ANSI_DEBUG_LOGFILE, "/dev/tty") != -1)
  649. {
  650. sprintf(s80, "stty opost ocrnl < %s", ANSI_DEBUG_LOGFILE);
  651. system(s80);
  652. }
  653. #ifdef ANSI_DEBUG_NOBUF
  654. setbuf(wfp, NULL);
  655. #endif /* ANSI_DEBUG_NOBUF */
  656. fprintf(wfp, "******** %s tty_is_multiscreen=%d\n",
  657. get_ttyname(), tty_is_multiscreen);
  658. #endif /* ANSI_DEBUG */
  659. /*
  660. * remember receiver pid
  661. */
  662. shm->rcvr_pid = getpid();
  663. /*
  664. * reset autorz detector
  665. */
  666. shm->autorz_pos = 0;
  667. /*
  668. * reset line read function
  669. */
  670. lgetc_count = 0;
  671. lgetc_ptr = lgetc_buf;
  672. in_ansi_accumulation = 0;
  673. ansi = ansibuf;
  674. *ansi = 0;
  675. ansilen = 0;
  676. shm->rcvrdisp_ptr = shm->rcvrdisp_buffer;
  677. shm->rcvrdisp_count = 0;
  678. /*
  679. * yetch - magic number gretching for lines and columns
  680. */
  681. if (!tcap_LINES || !tcap_COLS)
  682. {
  683. tcap_LINES = 25;
  684. tcap_COLS = 80;
  685. }
  686. if (tcap_LINES > CFG_ScreenLinesMax)
  687. tcap_LINES = CFG_ScreenLinesMax;
  688. if (tcap_COLS > CFG_ScreenColsMax)
  689. tcap_COLS = CFG_ScreenColsMax;
  690. LINESxCOLS = tcap_LINES * tcap_COLS;
  691. rcvr_signals();
  692. rcvr_log_open();
  693. saved_cursor_y = shm->cursor_y;
  694. saved_cursor_x = shm->cursor_x;
  695. /*
  696. * finally! - the receive loop
  697. */
  698. while (1)
  699. {
  700. rchar = lgetc_rcvr();
  701. if (!tty_is_multiscreen && (rchar >= 0x80))
  702. rchar = non_multiscreen_hi_map[rchar - 0x80];
  703. if (process_rcvd_char(rchar))
  704. continue;
  705. rcvrdisp((char *)&rchar, 1);
  706. if (shm->Ladd_nl_incoming && (rchar == CRET))
  707. rcvrdisp((char *)&nlchar, 1);
  708. }
  709. /* NOTREACHED */
  710. } /* end of rcvr */
  711. /*+-------------------------------------------------------------------------
  712. xmtr_wfp_debug_hack() - keep xmtr use of rcvr code from bombing
  713. This function is called once by xmtr() before it does much else.
  714. This is a horrible hack only necessary when the chips are down.
  715. If ANSI_DEBUG has wfp open in rcvr, this opens it in the xmtr too.
  716. The function has scope in the production binary only so ecu.c
  717. has no need to know the ANSI debug status. This is the kind of
  718. hack you never find out about in binary programs you buy :->.
  719. --------------------------------------------------------------------------*/
  720. void
  721. xmtr_wfp_debug_hack()
  722. {
  723. #ifdef ANSI_DEBUG
  724. wfp = fopen("/dev/null", "w");
  725. #endif
  726. } /* end of xmtr_wfp_debug_hack */
  727. /*+-------------------------------------------------------------------------
  728. rcvr_ansi_filter_control(on_off,display)
  729. does nothing meaningful if no emulation configured
  730. --------------------------------------------------------------------------*/
  731. void
  732. rcvr_ansi_filter_control(on_off, display)
  733. int on_off;
  734. int display;
  735. {
  736. #if defined(CFG_NoAnsiEmulation)
  737. if (display)
  738. pprintf("ignored ... ANSI filter not configured\n");
  739. #else
  740. if (on_off)
  741. {
  742. spaces((char *)shm->screen, LINESxCOLS);
  743. shm->cursor_y = 0;
  744. shm->cursor_x = 0;
  745. shm->rcvr_ansi_filter = 1;
  746. }
  747. else
  748. {
  749. shm->rcvr_ansi_filter = 0;
  750. }
  751. if (display)
  752. {
  753. int pointless = 0;
  754. if (tty_not_char_special)
  755. pointless = 1;
  756. if (pointless)
  757. pprintf("although pointless, ");
  758. pprintf("ANSI filter set to %s\n",
  759. (shm->rcvr_ansi_filter) ? "ON" : "off");
  760. }
  761. #endif /* ndefined(CFG_NoAnsiEmulation) */
  762. } /* end of rcvr_ansi_filter_control */
  763. /***************************************************************************
  764. * R E C E I V E R A N S I F I L T E R
  765. *
  766. * The code below is included only in versions which have an "ANSI filter"
  767. * (which may or may not be enabled with shm->rcvr_ansi_filter)
  768. ***************************************************************************/
  769. #if !defined(CFG_NoAnsiEmulation)
  770. /*+-------------------------------------------------------------------------
  771. redisplay_rcvr_screen() - redisplay logical receiver screen
  772. As of writing, this function is called only by the XMTR process
  773. --------------------------------------------------------------------------*/
  774. void
  775. redisplay_rcvr_screen()
  776. {
  777. UINT y;
  778. extern int tty_not_char_special;
  779. if (!shm->rcvr_ansi_filter || tty_not_char_special)
  780. return;
  781. setcolor(colors_current);
  782. tcap_stand_end();
  783. rcvrdisp_actual();
  784. for (y = 0; y < tcap_LINES; y++)
  785. {
  786. tcap_cursor(y, 0);
  787. fwrite(&shm->screen[y][0],
  788. ((y != tcap_LINES - 1) ? tcap_COLS : tcap_COLS - 1), 1, se);
  789. }
  790. tcap_eeol();
  791. tcap_cursor(shm->cursor_y, shm->cursor_x);
  792. rcvrdisp_actual();
  793. } /* end of redisplay_rcvr_screen */
  794. /*+-------------------------------------------------------------------------
  795. spaces_trap(code,buf,buflen)
  796. --------------------------------------------------------------------------*/
  797. #ifdef CURSOR_DEBUG
  798. void
  799. spaces_trap(code, buf, buflen)
  800. int code;
  801. uchar *buf;
  802. UINT buflen;
  803. {
  804. char *xyz = (char *)0x90000000;
  805. ff(se, "rcvr 'spaces trap' code %d: cursor x,y=%d,%d\r\n",
  806. code, shm->cursor_y, shm->cursor_x);
  807. ff(se, "buf=%08lx len=%08lx offs=%08lx\r\n", buf, buflen,
  808. (UINT32) buf - (UINT32) shm->screen);
  809. *xyz = 0;
  810. abort();
  811. } /* end of spaces_trap */
  812. #endif
  813. /*+-------------------------------------------------------------------------
  814. spaces(buf,buflen) - fill with spaces
  815. --------------------------------------------------------------------------*/
  816. void
  817. spaces(buf, buflen)
  818. uchar *buf;
  819. UINT buflen;
  820. {
  821. #ifdef CURSOR_DEBUG
  822. if ((UINT32) buf > (((UINT32) shm->screen) + LINESxCOLS))
  823. spaces_trap(1, buf, buflen);
  824. if ((UINT32) buf < (UINT32) shm->screen)
  825. spaces_trap(2, buf, buflen);
  826. if ((UINT32) (buf + buflen) > (((UINT32) shm->screen) + LINESxCOLS))
  827. spaces_trap(3, buf, buflen);
  828. if ((UINT32) (buf + buflen) < (UINT32) shm->screen)
  829. spaces_trap(4, buf, buflen);
  830. #endif
  831. if (!buflen)
  832. return;
  833. #ifdef DEFENSIVE
  834. if ((UINT32) buf < (UINT32) shm->screen)
  835. {
  836. ff(se,">< defensive 1\r\n");
  837. return;
  838. }
  839. if ((UINT32) (buf + buflen) > (((UINT32) shm->screen) + LINESxCOLS))
  840. {
  841. ff(se,">< defensive 2\r\n");
  842. return;
  843. }
  844. #endif
  845. memset(buf, SPACE, buflen);
  846. } /* end of spaces */
  847. /*+-------------------------------------------------------------------------
  848. ansi_SGR() - Set Graphics Rendition
  849. The DOS ANSI world expects to be able to be able to chain 0,1 and
  850. 3x,4x params together with semicolons.
  851. Supported modifiers for non-ansi terminals
  852. 0 normal
  853. 1 bold
  854. 4 underscore
  855. 5 blink
  856. 7 reverse video
  857. --------------------------------------------------------------------------*/
  858. void
  859. ansi_SGR()
  860. {
  861. int itmp;
  862. char *cp;
  863. char SGRstr[MAX_ANSI_LEN];
  864. char *token;
  865. char *str_token();
  866. #ifdef ANSI_DEBUG_SEQ
  867. if (wfp)
  868. ff(wfp, "SGR\n");
  869. #endif
  870. if (!tty_is_multiscreen)
  871. {
  872. ansibuf[ansilen - 1] = 0; /* get rid of 'm' */
  873. cp = ansibuf + 1; /* get rid of '[' */
  874. if (!strlen(cp))
  875. goto SGR_0;
  876. while (token = str_token(cp, ";"))
  877. {
  878. cp = (char *)0; /* further calls to str_token need NULL */
  879. switch (atoi(token))
  880. {
  881. default:
  882. case 0: /* normal */
  883. SGR_0:
  884. tcap_stand_end();
  885. tcap_blink_off();
  886. tcap_underscore_off();
  887. tcap_bold_off();
  888. break;
  889. case 1: /* bold */
  890. tcap_bold_on();
  891. break;
  892. case 4: /* underscore */
  893. tcap_underscore_on();
  894. break;
  895. case 5: /* blink */
  896. tcap_blink_on();
  897. break;
  898. case 7: /* reverse video */
  899. tcap_stand_out();
  900. break;
  901. }
  902. }
  903. return;
  904. }
  905. if (ansilen <= 3) /* 'ESC[<0-9>m' and 'ESC[m' - quickly handled */
  906. {
  907. rcvrdisp(&esc, 1);
  908. rcvrdisp(ansibuf, ansilen);
  909. return;
  910. }
  911. /* check XENIX 'ESC[<2,3,7>m' extensions */
  912. switch (itmp = atoi(ansibuf + 1))
  913. {
  914. case 7: /* XENIX 'ESC[7;<0-15>;<0-15>m' set
  915. * fore/background color */
  916. itmp = atoi(ansibuf + 3); /* second parameter */
  917. if (itmp > 15) /* not XENIX extension */
  918. break;
  919. /* fall through */
  920. case 2: /* XENIX 'ESC[2;<0-15>;<0-15>m' set
  921. * fore/background color */
  922. case 3: /* XENIX 'ESC[3;<0-1>m' color only set/clear
  923. * blink */
  924. rcvrdisp(&esc, 1);
  925. rcvrdisp(ansibuf, ansilen);
  926. return;
  927. default:
  928. break;
  929. }
  930. /* not XENIX extension */
  931. ansibuf[ansilen - 1] = 0;/* get rid of 'm' */
  932. cp = ansibuf + 1; /* get rid of '[' */
  933. while (token = str_token(cp, ";"))
  934. {
  935. cp = (char *)0; /* further calls to str_token need NULL */
  936. sprintf(SGRstr, "\033[%sm", token);
  937. rcvrdisp(SGRstr, strlen(SGRstr));
  938. }
  939. } /* end of ansi_SGR */
  940. /*+-------------------------------------------------------------------------
  941. ansi_CUP() - cursor position (also HVP horiz/vertical position)
  942. --------------------------------------------------------------------------*/
  943. void
  944. ansi_CUP()
  945. {
  946. UINT param_count = 0;
  947. char ansicopy[MAX_ANSI_LEN];
  948. char *cp = ansicopy;
  949. char *token;
  950. char *str_token();
  951. strcpy(cp, ansibuf + 1);
  952. *(cp + ansilen - 2) = 0;
  953. while (token = str_token(cp, ";"))
  954. {
  955. cp = (char *)0; /* further calls to str_token need NULL */
  956. switch (++param_count)
  957. {
  958. case 1:
  959. shm->cursor_y = atoi(token) - 1;
  960. break;
  961. case 2:
  962. shm->cursor_x = atoi(token) - 1;
  963. break;
  964. }
  965. }
  966. #ifdef ANSI_DEBUG_SEQ
  967. if (wfp)
  968. {
  969. ff(wfp, "CUP: param_count=%u p1=%u p2=%u\n", param_count,
  970. shm->cursor_y + 1, shm->cursor_x + 1);
  971. }
  972. #endif
  973. switch (param_count)
  974. {
  975. case 0:
  976. shm->cursor_y = 0;
  977. case 1:
  978. shm->cursor_x = 0;
  979. }
  980. if (shm->cursor_x >= tcap_COLS)
  981. shm->cursor_x = tcap_COLS - 1;
  982. if (shm->cursor_y >= tcap_LINES)
  983. shm->cursor_y = tcap_LINES - 1;
  984. if (!tty_is_multiscreen)
  985. tcap_cursor(shm->cursor_y, shm->cursor_x);
  986. } /* end of ansi_CUP */
  987. /*+-------------------------------------------------------------------------
  988. ansi_CUU() - cursor up
  989. --------------------------------------------------------------------------*/
  990. void
  991. ansi_CUU()
  992. {
  993. UINT param;
  994. UINT y;
  995. if (ansilen == 2) /* no param */
  996. param = 1;
  997. else
  998. param = atoi(ansibuf + 1);
  999. #ifdef ANSI_DEBUG_SEQ
  1000. if (wfp)
  1001. ff(wfp, "CU: param=%u\n", param);
  1002. #endif
  1003. y = shm->cursor_y - param;
  1004. if (y >= tcap_LINES) /* unsigned comparison */
  1005. y = 0;
  1006. if (y != shm->cursor_y)
  1007. {
  1008. shm->cursor_y = y;
  1009. if (!tty_is_multiscreen)
  1010. tcap_cursor(shm->cursor_y, shm->cursor_x);
  1011. }
  1012. } /* end of ansi_CUU */
  1013. /*+-------------------------------------------------------------------------
  1014. ansi_CUD() - cursor down (also VPR vertical position relative)
  1015. --------------------------------------------------------------------------*/
  1016. void
  1017. ansi_CUD()
  1018. {
  1019. UINT param;
  1020. UINT y;
  1021. if (ansilen == 2) /* no param */
  1022. param = 1;
  1023. else
  1024. param = atoi(ansibuf + 1);
  1025. #ifdef ANSI_DEBUG_SEQ
  1026. if (wfp)
  1027. ff(wfp, "CUD: param=%u\n", param);
  1028. #endif
  1029. y = shm->cursor_y + param;
  1030. if (y >= tcap_LINES)
  1031. {
  1032. y = tcap_LINES - 1;
  1033. if ((shm->cursor_y == tcap_LINES - 1) && !tty_is_multiscreen)
  1034. {
  1035. process_rcvd_char(0x0A);
  1036. return;
  1037. }
  1038. }
  1039. if (y != shm->cursor_y)
  1040. {
  1041. shm->cursor_y = y;
  1042. if (!tty_is_multiscreen)
  1043. tcap_cursor(shm->cursor_y, shm->cursor_x);
  1044. }
  1045. } /* end of ansi_CUD */
  1046. /*+-------------------------------------------------------------------------
  1047. ansi_CUF() - cursor forward (also HPR horizontal position relative)
  1048. --------------------------------------------------------------------------*/
  1049. void
  1050. ansi_CUF()
  1051. {
  1052. UINT param;
  1053. UINT x;
  1054. if (ansilen == 2) /* no param */
  1055. param = 1;
  1056. else
  1057. param = atoi(ansibuf + 1);
  1058. #ifdef ANSI_DEBUG_SEQ
  1059. if (wfp)
  1060. ff(wfp, "CUF: param=%u\n", param);
  1061. #endif
  1062. x = shm->cursor_x + param;
  1063. if (x >= tcap_COLS)
  1064. x = tcap_COLS - 1;
  1065. if (x != shm->cursor_x)
  1066. {
  1067. shm->cursor_x = x;
  1068. if (!tty_is_multiscreen)
  1069. tcap_cursor(shm->cursor_y, shm->cursor_x);
  1070. }
  1071. } /* end of ansi_CUF */
  1072. /*+-------------------------------------------------------------------------
  1073. ansi_CUB() - cursor forward
  1074. --------------------------------------------------------------------------*/
  1075. void
  1076. ansi_CUB()
  1077. {
  1078. UINT param;
  1079. UINT x;
  1080. if (ansilen == 2) /* no param */
  1081. param = 1;
  1082. else
  1083. param = atoi(ansibuf + 1);
  1084. #ifdef ANSI_DEBUG_SEQ
  1085. if (wfp)
  1086. ff(wfp, "CUB: param=%u\n", param);
  1087. #endif
  1088. x = shm->cursor_x - param;
  1089. if (x >= tcap_COLS) /* unsigned comparison */
  1090. x = 0;
  1091. if (x != shm->cursor_x)
  1092. {
  1093. shm->cursor_x = x;
  1094. if (!tty_is_multiscreen)
  1095. tcap_cursor(shm->cursor_y, shm->cursor_x);
  1096. }
  1097. } /* end of ansi_CUB */
  1098. /*+-------------------------------------------------------------------------
  1099. ansi_DSR() - device status report
  1100. ESC [ Ps n - Device Status Report (DSR) ECU Response
  1101. Ps = 5 -> Status Report ESC [ 0 n
  1102. Ps = 6 -> Report Cursor Position (CPR) ESC [ r ; c R
  1103. --------------------------------------------------------------------------*/
  1104. void
  1105. ansi_DSR()
  1106. {
  1107. UINT param;
  1108. char response_buf[MAX_ANSI_LEN];
  1109. char *response = 0;
  1110. if (ansilen < 2) /* no param */
  1111. param = 0;
  1112. else
  1113. param = atoi(ansibuf + 1);
  1114. #ifdef ANSI_DEBUG_SEQ
  1115. if (wfp)
  1116. {
  1117. ff(wfp, "DSR: param=%u ", param);
  1118. if (!param && (ansilen == 3))
  1119. ff(wfp, ": ignoring \"ESC 0 ] n\"");
  1120. ff(wfp, "\n");
  1121. }
  1122. #endif
  1123. switch (param)
  1124. {
  1125. case 0: /* sanity */
  1126. case 5: /* sanity */
  1127. response = "\033[0n";
  1128. break;
  1129. case 6: /* report cursor position */
  1130. sprintf(response_buf, "\033[%d;%dR",
  1131. shm->cursor_y + 1, shm->cursor_x + 1);
  1132. response = response_buf;
  1133. break;
  1134. }
  1135. if (response)
  1136. {
  1137. Nap(300L);
  1138. write(shm->Liofd, response, strlen(response));
  1139. }
  1140. #ifdef ANSI_DEBUG_SEQ
  1141. if (response)
  1142. {
  1143. char s80[80];
  1144. sprintf(s80, "strlen(DSR response) = %d", strlen(response));
  1145. hex_dump_fp(wfp, response, strlen(response), s80, 0);
  1146. }
  1147. #endif
  1148. } /* end of ansi_DSR */
  1149. /*+-------------------------------------------------------------------------
  1150. ansi_ED() - erase in display
  1151. --------------------------------------------------------------------------*/
  1152. void
  1153. ansi_ED()
  1154. {
  1155. UINT param;
  1156. UINT y;
  1157. if (ansilen == 2) /* no param */
  1158. param = 0;
  1159. else
  1160. param = atoi(ansibuf + 1);
  1161. #ifdef ANSI_DEBUG_SEQ
  1162. if (wfp)
  1163. ff(wfp, "ED: param=%u LINESxCOLS=%d\n", param,LINESxCOLS);
  1164. #endif
  1165. switch (param)
  1166. {
  1167. case 0: /* erase to end of display */
  1168. spaces(&shm->screen[shm->cursor_y][shm->cursor_x],
  1169. LINESxCOLS - ((shm->cursor_y * tcap_COLS) + shm->cursor_x));
  1170. if (!tty_is_multiscreen)
  1171. tcap_eeod();
  1172. break;
  1173. case 1: /* erase from beginning of display */
  1174. spaces((char *)shm->screen, (shm->cursor_y * tcap_COLS) +
  1175. shm->cursor_x);
  1176. if (!tty_is_multiscreen)
  1177. {
  1178. for (y = 0; y < shm->cursor_y - 1; y++)
  1179. {
  1180. tcap_cursor(y, 0);
  1181. tcap_eeol();
  1182. }
  1183. if (shm->cursor_x)
  1184. {
  1185. tcap_cursor(shm->cursor_y, 0);
  1186. tcap_clear_area_char(shm->cursor_x, ' ');
  1187. }
  1188. else
  1189. tcap_cursor(shm->cursor_y, shm->cursor_x);
  1190. }
  1191. break;
  1192. case 2: /* clear display */
  1193. shm->cursor_y = 0;
  1194. shm->cursor_x = 0;
  1195. spaces((char *)shm->screen, LINESxCOLS);
  1196. if (!tty_is_multiscreen)
  1197. {
  1198. tcap_clear_screen();
  1199. tcap_cursor(shm->cursor_y, shm->cursor_x);
  1200. }
  1201. break;
  1202. }
  1203. } /* end of ansi_ED */
  1204. /*+-------------------------------------------------------------------------
  1205. ansi_EL() - erase in line
  1206. --------------------------------------------------------------------------*/
  1207. void
  1208. ansi_EL()
  1209. {
  1210. UINT param;
  1211. char cr = CRET;
  1212. if (ansilen == 2) /* no param */
  1213. param = 0;
  1214. else
  1215. param = atoi(ansibuf + 1);
  1216. #ifdef ANSI_DEBUG_SEQ
  1217. if (wfp)
  1218. ff(wfp, "EL: param=%u\n", param);
  1219. #endif
  1220. switch (param)
  1221. {
  1222. case 2: /* clear line */
  1223. shm->cursor_x = 0;
  1224. if (!tty_is_multiscreen)
  1225. rcvrdisp(&cr, 1);
  1226. /* fall thru */
  1227. case 0: /* erase to end of line */
  1228. spaces(&shm->screen[shm->cursor_y][shm->cursor_x],
  1229. tcap_COLS - shm->cursor_x);
  1230. if (!tty_is_multiscreen)
  1231. tcap_eeol();
  1232. break;
  1233. case 1: /* erase from beginning of line */
  1234. spaces(&shm->screen[shm->cursor_y][0], shm->cursor_x);
  1235. if (!tty_is_multiscreen && shm->cursor_x)
  1236. {
  1237. rcvrdisp(&cr, 1);
  1238. tcap_clear_area_char(shm->cursor_x, ' ');
  1239. }
  1240. break;
  1241. }
  1242. } /* end of ansi_EL */
  1243. /*+-------------------------------------------------------------------------
  1244. ansi_ECH() - erase characters
  1245. --------------------------------------------------------------------------*/
  1246. void
  1247. ansi_ECH()
  1248. {
  1249. UINT param;
  1250. UINT screen_pos;
  1251. if (ansilen == 2) /* no param */
  1252. param = 1;
  1253. else
  1254. param = atoi(ansibuf + 1);
  1255. #ifdef ANSI_DEBUG_SEQ
  1256. if (wfp)
  1257. ff(wfp, "ECH: param=%u\n", param);
  1258. #endif
  1259. if ((shm->cursor_x + param) >= tcap_COLS)
  1260. return;
  1261. screen_pos = (shm->cursor_y * tcap_COLS) + shm->cursor_x;
  1262. mem_cpy((char *)shm->screen + screen_pos,
  1263. (char *)shm->screen + screen_pos + param, param);
  1264. spaces((char *)shm->screen + ((shm->cursor_y + 1) * tcap_COLS) -
  1265. param, param);
  1266. if (!tty_is_multiscreen)
  1267. tcap_delete_chars(param);
  1268. } /* end of ansi_ECH */
  1269. /*+-------------------------------------------------------------------------
  1270. ansi_SU() - scroll up (new blank lines at the bottom)
  1271. --------------------------------------------------------------------------*/
  1272. void
  1273. ansi_SU()
  1274. {
  1275. UINT param;
  1276. UINT count;
  1277. if (ansilen == 2) /* no param */
  1278. param = 1;
  1279. else
  1280. param = atoi(ansibuf + 1);
  1281. if (param > tcap_LINES)
  1282. param = tcap_LINES;
  1283. #ifdef ANSI_DEBUG_SEQ
  1284. if (wfp)
  1285. ff(wfp, "SU: param=%u\n", param);
  1286. #endif
  1287. if (!param)
  1288. return;
  1289. #ifdef ANSI_DEBUG_SEQ
  1290. if (wfp)
  1291. {
  1292. fprintf(wfp, "SU: param=%u y,x=%d,%d\n", param,
  1293. shm->cursor_y, shm->cursor_x);
  1294. }
  1295. #endif
  1296. count = tcap_COLS * param;
  1297. mem_cpy((char *)shm->screen, (char *)shm->screen + count,
  1298. LINESxCOLS - count);
  1299. spaces((char *)shm->screen + LINESxCOLS - count, count);
  1300. if (!tty_is_multiscreen)
  1301. {
  1302. tcap_cursor(tcap_LINES - 1, 0);
  1303. while (param--)
  1304. rcvrdisp("\n", 1);
  1305. tcap_cursor(shm->cursor_y, shm->cursor_x);
  1306. }
  1307. } /* end of ansi_SU */
  1308. /*+-------------------------------------------------------------------------
  1309. ansi_SD() - scroll down (new blank lines at the top)
  1310. --------------------------------------------------------------------------*/
  1311. void
  1312. ansi_SD()
  1313. {
  1314. UINT param;
  1315. UINT count;
  1316. if (ansilen == 2) /* no param */
  1317. param = 1;
  1318. else
  1319. param = atoi(ansibuf + 1);
  1320. if (param > tcap_LINES)
  1321. param = tcap_LINES;
  1322. #ifdef ANSI_DEBUG_SEQ
  1323. if (wfp)
  1324. ff(wfp, "SD: param=%u\n", param);
  1325. #endif
  1326. if (!param)
  1327. return;
  1328. #ifdef ANSI_DEBUG_SEQ
  1329. if (wfp)
  1330. {
  1331. fprintf(wfp, "SU: param=%u y,x=%d,%d\n", param,
  1332. shm->cursor_y, shm->cursor_x);
  1333. }
  1334. #endif
  1335. count = tcap_COLS * param;
  1336. mem_cpy((char *)shm->screen, (char *)shm->screen + count,
  1337. LINESxCOLS - count);
  1338. spaces((char *)shm->screen + LINESxCOLS - count, count);
  1339. if (!tty_is_multiscreen)
  1340. {
  1341. tcap_cursor(0, 0);
  1342. tcap_insert_lines(param);
  1343. tcap_cursor(shm->cursor_y, shm->cursor_x);
  1344. }
  1345. } /* end of ansi_SD */
  1346. /*+-------------------------------------------------------------------------
  1347. ansi_HPA() - horizontal position absolute
  1348. --------------------------------------------------------------------------*/
  1349. void
  1350. ansi_HPA()
  1351. {
  1352. UINT param;
  1353. if (ansilen == 2) /* no param */
  1354. param = 1;
  1355. else
  1356. param = atoi(ansibuf + 1);
  1357. #ifdef ANSI_DEBUG_SEQ
  1358. if (wfp)
  1359. ff(wfp, "HPA: param=%u\n", param);
  1360. #endif
  1361. if (param >= tcap_LINES)
  1362. return;
  1363. if ((unsigned)(shm->cursor_x = param) >= (unsigned)tcap_COLS)
  1364. shm->cursor_x = tcap_COLS - 1;
  1365. if (!tty_is_multiscreen)
  1366. tcap_cursor(shm->cursor_y, shm->cursor_x);
  1367. } /* end of ansi_HPA */
  1368. /*+-------------------------------------------------------------------------
  1369. ansi_VPA() - vertical position absolute
  1370. --------------------------------------------------------------------------*/
  1371. void
  1372. ansi_VPA()
  1373. {
  1374. UINT param;
  1375. if (ansilen == 2) /* no param */
  1376. param = 1;
  1377. else
  1378. param = atoi(ansibuf + 1);
  1379. #ifdef ANSI_DEBUG_SEQ
  1380. if (wfp)
  1381. ff(wfp, "VPA: param=%u\n", param);
  1382. #endif
  1383. if (param >= tcap_COLS)
  1384. return;
  1385. if ((unsigned)(shm->cursor_y = param) >= (unsigned)tcap_LINES)
  1386. shm->cursor_y = tcap_LINES - 1;
  1387. if (!tty_is_multiscreen)
  1388. tcap_cursor(shm->cursor_y, shm->cursor_x);
  1389. } /* end of ansi_VPA */
  1390. /*+-------------------------------------------------------------------------
  1391. ansi_IL() - insert lines
  1392. --------------------------------------------------------------------------*/
  1393. void
  1394. ansi_IL()
  1395. {
  1396. UINT param;
  1397. UINT count;
  1398. UINT screen_pos;
  1399. if (ansilen == 2) /* no param */
  1400. param = 1;
  1401. else
  1402. param = atoi(ansibuf + 1);
  1403. #ifdef ANSI_DEBUG_SEQ
  1404. if (wfp)
  1405. ff(wfp, "IL: param=%u\n", param);
  1406. #endif
  1407. if ((shm->cursor_y + param) >= tcap_LINES)
  1408. return;
  1409. count = tcap_COLS * param;
  1410. screen_pos = shm->cursor_y * tcap_COLS;
  1411. mem_cpy((char *)shm->screen + screen_pos + count,
  1412. (char *)shm->screen + screen_pos,
  1413. LINESxCOLS - screen_pos - count);
  1414. spaces((char *)shm->screen + screen_pos, count);
  1415. if (!tty_is_multiscreen)
  1416. tcap_insert_lines(param);
  1417. } /* end of ansi_IL */
  1418. /*+-------------------------------------------------------------------------
  1419. ansi_ICH() - insert characters
  1420. --------------------------------------------------------------------------*/
  1421. void
  1422. ansi_ICH()
  1423. {
  1424. UINT param;
  1425. UINT count;
  1426. UINT screen_pos;
  1427. if (ansilen == 2) /* no param */
  1428. param = 1;
  1429. else
  1430. param = atoi(ansibuf + 1);
  1431. if (param > tcap_COLS - shm->cursor_x)
  1432. param = tcap_COLS - shm->cursor_x;
  1433. #ifdef ANSI_DEBUG_SEQ
  1434. if (wfp)
  1435. ff(wfp, "ICH: param=%u\n", param);
  1436. #endif
  1437. if (!param)
  1438. return;
  1439. screen_pos = (shm->cursor_y * tcap_COLS) + shm->cursor_x;
  1440. count = tcap_COLS - shm->cursor_x - param;
  1441. mem_cpy((char *)shm->screen + screen_pos + param,
  1442. (char *)shm->screen + screen_pos, count);
  1443. spaces((char *)shm->screen + screen_pos, param);
  1444. if (!tty_is_multiscreen)
  1445. tcap_insert_chars(param);
  1446. } /* end of ansi_ICH */
  1447. /*+-------------------------------------------------------------------------
  1448. ansi_DL() - delete lines
  1449. --------------------------------------------------------------------------*/
  1450. void
  1451. ansi_DL()
  1452. {
  1453. UINT param;
  1454. UINT count;
  1455. UINT screen_pos;
  1456. if (ansilen == 2) /* no param */
  1457. param = 1;
  1458. else
  1459. param = atoi(ansibuf + 1);
  1460. if (param > (tcap_LINES - shm->cursor_y))
  1461. param = tcap_LINES - shm->cursor_y;
  1462. #ifdef ANSI_DEBUG_SEQ
  1463. if (wfp)
  1464. ff(wfp, "DL: param=%u\n", param);
  1465. #endif
  1466. if (!param)
  1467. return;
  1468. count = tcap_COLS * param;
  1469. screen_pos = shm->cursor_y * tcap_COLS;
  1470. mem_cpy((char *)shm->screen + screen_pos,
  1471. (char *)shm->screen + screen_pos + count,
  1472. LINESxCOLS - screen_pos - count);
  1473. spaces((char *)shm->screen + LINESxCOLS - count, count);
  1474. if (!tty_is_multiscreen)
  1475. tcap_delete_lines(param);
  1476. } /* end of ansi_DL */
  1477. /*+-------------------------------------------------------------------------
  1478. ansi_DCH() - delete characters
  1479. --------------------------------------------------------------------------*/
  1480. void
  1481. ansi_DCH()
  1482. {
  1483. UINT param;
  1484. UINT count;
  1485. UINT screen_pos;
  1486. if (ansilen == 2) /* no param */
  1487. param = 1;
  1488. else
  1489. param = atoi(ansibuf + 1);
  1490. if (ansilen == 2) /* no param */
  1491. param = 1;
  1492. else
  1493. param = atoi(ansibuf + 1);
  1494. if (param > tcap_COLS - shm->cursor_x)
  1495. param = tcap_COLS - shm->cursor_x;
  1496. #ifdef ANSI_DEBUG_SEQ
  1497. if (wfp)
  1498. ff(wfp, "DCH: param=%u\n", param);
  1499. #endif
  1500. if (!param)
  1501. return;
  1502. screen_pos = (shm->cursor_y * tcap_COLS) + shm->cursor_x;
  1503. count = tcap_COLS - shm->cursor_x - param;
  1504. mem_cpy((char *)shm->screen + screen_pos,
  1505. (char *)shm->screen + screen_pos + param, count);
  1506. screen_pos = ((shm->cursor_y + 1) * tcap_COLS) - param;
  1507. spaces((char *)shm->screen + screen_pos, param);
  1508. if (!tty_is_multiscreen)
  1509. tcap_delete_chars(param);
  1510. } /* end of ansi_DCH */
  1511. /*+-------------------------------------------------------------------------
  1512. ansi_CPL() - cursor to previous line
  1513. --------------------------------------------------------------------------*/
  1514. void
  1515. ansi_CPL()
  1516. {
  1517. UINT param;
  1518. if (ansilen == 2) /* no param */
  1519. param = 1;
  1520. else
  1521. param = atoi(ansibuf + 1);
  1522. if ((shm->cursor_y -= param) >= tcap_LINES) /* unsigned comparison */
  1523. shm->cursor_y = 0;
  1524. shm->cursor_x = 0;
  1525. #ifdef ANSI_DEBUG_SEQ
  1526. if (wfp)
  1527. ff(wfp, "CPL: param=%u\n", param);
  1528. #endif
  1529. if (!tty_is_multiscreen)
  1530. tcap_cursor(shm->cursor_y, shm->cursor_x);
  1531. } /* end of ansi_CPL */
  1532. /*+-------------------------------------------------------------------------
  1533. ansi_CNL() - cursor to next line
  1534. --------------------------------------------------------------------------*/
  1535. void
  1536. ansi_CNL()
  1537. {
  1538. UINT param;
  1539. if (ansilen == 2) /* no param */
  1540. param = 1;
  1541. else
  1542. param = atoi(ansibuf + 1);
  1543. if ((shm->cursor_y += param) >= tcap_LINES)
  1544. shm->cursor_y = tcap_LINES - 1;
  1545. shm->cursor_x = 0;
  1546. #ifdef ANSI_DEBUG_SEQ
  1547. if (wfp)
  1548. ff(wfp, "CNL: param=%u\n", param);
  1549. #endif
  1550. if (!tty_is_multiscreen)
  1551. tcap_cursor(shm->cursor_y, shm->cursor_x);
  1552. } /* end of ansi_CNL */
  1553. /*+-------------------------------------------------------------------------
  1554. saved_cursor_save_cursor() - nice but unfortunate IBM extension
  1555. I can't find this used anywhere but in the DOS world. Supporting this
  1556. pair of sequences is what started this whole complex mess.
  1557. --------------------------------------------------------------------------*/
  1558. void
  1559. saved_cursor_save_cursor()
  1560. {
  1561. saved_cursor_y = shm->cursor_y;
  1562. saved_cursor_x = shm->cursor_x;
  1563. } /* end of saved_cursor_save_cursor */
  1564. /*+-------------------------------------------------------------------------
  1565. saved_cursor_restore_cursor() - nice but unfortunate IBM extension
  1566. I can't find this used anywhere but in the DOS world. Supporting this
  1567. pair of sequences is what started this whole complex mess.
  1568. --------------------------------------------------------------------------*/
  1569. void
  1570. saved_cursor_restore_cursor()
  1571. {
  1572. shm->cursor_y = saved_cursor_y;
  1573. shm->cursor_x = saved_cursor_x;
  1574. tcap_cursor(shm->cursor_y, shm->cursor_x);
  1575. } /* end of saved_cursor_restore_cursor */
  1576. /*+-------------------------------------------------------------------------
  1577. rcvd_ESC() - ESC seen-prepare to accumulate ansi sequence
  1578. --------------------------------------------------------------------------*/
  1579. void
  1580. rcvd_ESC()
  1581. {
  1582. #ifdef ANSI_DEBUG
  1583. if (wfp)
  1584. fprintf(wfp, "ESC ");
  1585. #endif
  1586. ansi = ansibuf;
  1587. *ansi = 0;
  1588. ansilen = 0;
  1589. in_ansi_accumulation = 1;
  1590. } /* end of rcvd_ESC */
  1591. /*+-------------------------------------------------------------------------
  1592. is_ansi_terminator(rchar) - is character terminator for ansi sequence?
  1593. --------------------------------------------------------------------------*/
  1594. int
  1595. is_ansi_terminator(rchar)
  1596. UINT rchar;
  1597. {
  1598. return (isalpha(rchar) || strchr("@>=", rchar));
  1599. } /* end of is_ansi_terminator */
  1600. /*+-------------------------------------------------------------------------
  1601. accumulate_ansi_sequence(rchar)
  1602. --------------------------------------------------------------------------*/
  1603. void
  1604. accumulate_ansi_sequence(rchar)
  1605. UINT rchar;
  1606. {
  1607. if (ansilen == (MAX_ANSI_LEN - 2))
  1608. {
  1609. in_ansi_accumulation = 0;
  1610. return;
  1611. }
  1612. #ifdef ANSI_DEBUG_AAS
  1613. if (wfp)
  1614. {
  1615. fprintf(wfp, "\naas: %02x %c ansilen=%d",
  1616. rchar, (rchar & 0x7F < SPACE) ? '.' : (rchar & 0x7F), ansilen);
  1617. }
  1618. #endif
  1619. *ansi++ = (uchar) rchar;
  1620. *ansi = 0;
  1621. ansilen++;
  1622. } /* end of accumulate_ansi_sequence */
  1623. /*+-------------------------------------------------------------------------
  1624. process_ansi_sequence() - a full ansi sequence is to be decoded
  1625. --------------------------------------------------------------------------*/
  1626. void
  1627. process_ansi_sequence()
  1628. {
  1629. int itmp;
  1630. #ifdef ANSI_DEBUG
  1631. if (wfp)
  1632. {
  1633. fprintf(wfp, "\nANSI SEQUENCE: '%s' len=%d y,x=%d,%d:: ",
  1634. ansibuf, ansilen, shm->cursor_y, shm->cursor_x);
  1635. }
  1636. #endif
  1637. if (!in_ansi_accumulation)
  1638. return;
  1639. in_ansi_accumulation = 0;
  1640. itmp = 1; /* assume write needed */
  1641. if (ansibuf[0] == '[')
  1642. {
  1643. switch (ansibuf[ansilen - 1])
  1644. {
  1645. case '@':
  1646. ansi_ICH(); /* insert characters */
  1647. break;
  1648. case 'A':
  1649. ansi_CUU(); /* cursor up */
  1650. break;
  1651. case 'B':
  1652. ansi_CUD(); /* cursor down */
  1653. break;
  1654. case 'C':
  1655. ansi_CUF(); /* cursor forward */
  1656. break;
  1657. case 'D':
  1658. ansi_CUB(); /* cursor backward */
  1659. break;
  1660. case 'E':
  1661. ansi_CNL(); /* cursor to next line */
  1662. break;
  1663. case 'F':
  1664. ansi_CPL(); /* cursor to previous line */
  1665. break;
  1666. case 'H':
  1667. ansi_CUP(); /* cursor position */
  1668. break;
  1669. case 'J':
  1670. ansi_ED(); /* erase in display */
  1671. break;
  1672. case 'K':
  1673. ansi_EL(); /* erase in line */
  1674. break;
  1675. case 'L':
  1676. ansi_IL(); /* insert lines */
  1677. break;
  1678. case 'M':
  1679. ansi_DL(); /* delete lines */
  1680. break;
  1681. case 'P':
  1682. ansi_DCH(); /* delete characters */
  1683. break;
  1684. case 'S':
  1685. ansi_SU(); /* scroll up */
  1686. break;
  1687. case 'T':
  1688. ansi_SD(); /* scroll down */
  1689. break;
  1690. case 'X':
  1691. ansi_ECH(); /* erase characters */
  1692. break;
  1693. case '`':
  1694. ansi_HPA(); /* horizontal position absolute */
  1695. break;
  1696. case 'a':
  1697. ansi_CUF(); /* HPR - horizontal position relative */
  1698. break;
  1699. case 'd':
  1700. ansi_VPA(); /* vertical position absolute */
  1701. break;
  1702. case 'e':
  1703. ansi_CUD(); /* VPR - vertical position relative */
  1704. break;
  1705. case 'f':
  1706. ansi_CUP(); /* HVP - horizontal vertical position */
  1707. break;
  1708. case 'm':
  1709. ansi_SGR(); /* set graphics rendition */
  1710. itmp = 0;
  1711. break;
  1712. case 'n':
  1713. ansi_DSR(); /* device status report */
  1714. itmp = 0;
  1715. break;
  1716. case 's':
  1717. saved_cursor_save_cursor();
  1718. itmp = 0;
  1719. break;
  1720. case 'u':
  1721. saved_cursor_restore_cursor();
  1722. itmp = 0;
  1723. break;
  1724. #ifdef FUTURES
  1725. case 'h':
  1726. ansi_SM(); /* Set Mode: SCO: lock keybd MSDOS: lots */
  1727. break;
  1728. case 'i':
  1729. ansi_MC(); /* Media Copy: send screen to line */
  1730. break;
  1731. case 'l':
  1732. ansi_RM(); /* Reset Mode: SCO: unlock keybd MSDOS:lots */
  1733. break;
  1734. #endif /* FUTURES */
  1735. default:
  1736. break;
  1737. }
  1738. }
  1739. /* if proper ansi console and indicated, write the buffer to the screen */
  1740. if (tty_is_multiscreen && itmp)
  1741. {
  1742. rcvrdisp(&esc, 1);
  1743. rcvrdisp(ansibuf, ansilen);
  1744. }
  1745. #ifdef ANSI_DEBUG
  1746. if (wfp)
  1747. {
  1748. fprintf(wfp, "pas: new cursor y,x=%d,%d\n",
  1749. shm->cursor_y, shm->cursor_x);
  1750. }
  1751. #endif
  1752. } /* end of process_ansi_sequence */
  1753. /*+-------------------------------------------------------------------------
  1754. rcvr_ansi_filter(rchar)
  1755. --------------------------------------------------------------------------*/
  1756. int
  1757. rcvr_ansi_filter(rchar)
  1758. int rchar;
  1759. {
  1760. int itmp;
  1761. /*
  1762. * video control sequences
  1763. */
  1764. if (rchar == ESC)
  1765. {
  1766. rcvd_ESC();
  1767. return (1);
  1768. }
  1769. else if (in_ansi_accumulation)
  1770. {
  1771. /*
  1772. * we handle some VT-100 two character sequences (ESC + one
  1773. * character)
  1774. */
  1775. int consumed = 0;
  1776. if (!ansilen)
  1777. {
  1778. switch (rchar & 0x7F)
  1779. {
  1780. case '7': /* VT100 save cursor position */
  1781. consumed = 1;
  1782. saved_cursor_save_cursor();
  1783. break;
  1784. case '8': /* VT100 save cursor position */
  1785. consumed = 1;
  1786. saved_cursor_restore_cursor();
  1787. break;
  1788. }
  1789. if (consumed)
  1790. {
  1791. #ifdef ANSI_DEBUG
  1792. if (wfp)
  1793. fprintf(wfp, "single: '%c'\n", rchar);
  1794. #endif
  1795. in_ansi_accumulation = 0;
  1796. return (1);
  1797. }
  1798. }
  1799. /*
  1800. * other sequences go through the ANSI decode path
  1801. */
  1802. accumulate_ansi_sequence(rchar);
  1803. if (is_ansi_terminator(rchar))
  1804. process_ansi_sequence();
  1805. return (1);
  1806. }
  1807. /*
  1808. * the bread and butter of the receiver: print printable characters
  1809. * and obey formatting characters
  1810. */
  1811. if (rchar < SPACE)
  1812. {
  1813. switch (rchar)
  1814. {
  1815. case CTL_L:
  1816. spaces((char *)shm->screen, LINESxCOLS);
  1817. shm->cursor_y = 0;
  1818. shm->cursor_x = 0;
  1819. break;
  1820. case BS:
  1821. if (shm->cursor_x)
  1822. shm->cursor_x--;
  1823. break;
  1824. case NL:
  1825. if (shm->cursor_y != tcap_LINES - 1)
  1826. shm->cursor_y++;
  1827. else
  1828. {
  1829. mem_cpy((char *)shm->screen,
  1830. (char *)shm->screen + tcap_COLS,
  1831. LINESxCOLS - tcap_COLS);
  1832. spaces(&shm->screen[shm->cursor_y][0], tcap_COLS);
  1833. }
  1834. break;
  1835. case CRET:
  1836. shm->cursor_x = 0;
  1837. break;
  1838. case TAB:
  1839. itmp = 8 - (shm->cursor_x % 8);
  1840. shm->cursor_x += itmp;
  1841. if (shm->cursor_x >= tcap_COLS)
  1842. {
  1843. shm->cursor_x = 0;
  1844. if (++shm->cursor_y >= tcap_LINES)
  1845. shm->cursor_y = tcap_LINES - 1;
  1846. }
  1847. spaces(&shm->screen[shm->cursor_y][shm->cursor_x], itmp);
  1848. break;
  1849. }
  1850. }
  1851. else
  1852. {
  1853. shm->screen[shm->cursor_y][shm->cursor_x++] = (uchar) rchar;
  1854. if (shm->cursor_x >= tcap_COLS)
  1855. {
  1856. shm->cursor_x = 0;
  1857. if (shm->cursor_y != tcap_LINES - 1)
  1858. shm->cursor_y++;
  1859. else
  1860. {
  1861. mem_cpy((char *)shm->screen, (char *)shm->screen + tcap_COLS,
  1862. LINESxCOLS - tcap_COLS);
  1863. spaces(&shm->screen[shm->cursor_y][shm->cursor_x], tcap_COLS);
  1864. }
  1865. }
  1866. }
  1867. #ifdef ANSI_DEBUG_TEXT
  1868. if (wfp)
  1869. {
  1870. if ((rchar & 0x7F) == NL)
  1871. fputs("\n", wfp);
  1872. else
  1873. fputc(((rchar & 0x7F) < SPACE) ? '.' : (rchar & 0x7F), wfp);
  1874. }
  1875. #endif
  1876. return (0);
  1877. } /* end of rcvr_ansi_filter */
  1878. #endif /* CFG_NoAnsiEmulation */
  1879. /* end of ecurcvr.c */
  1880. /* vi: set tabstop=4 shiftwidth=4: */