sldisply.c 62 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727
  1. /* Copyright (c) 1992, 1999, 2001, 2002, 2003 John E. Davis
  2. * This file is part of the S-Lang library.
  3. *
  4. * You may distribute under the terms of either the GNU General Public
  5. * License or the Perl Artistic License.
  6. */
  7. #include "slinclud.h"
  8. #include <time.h>
  9. #include <ctype.h>
  10. #if !defined(VMS) || (__VMS_VER >= 70000000)
  11. # include <sys/time.h>
  12. # ifdef __QNX__
  13. # include <sys/select.h>
  14. # endif
  15. # include <sys/types.h>
  16. #endif
  17. #ifdef __BEOS__
  18. /* Prototype for select */
  19. # include <net/socket.h>
  20. #endif
  21. #ifdef HAVE_TERMIOS_H
  22. # include <termios.h>
  23. #endif
  24. #ifdef VMS
  25. # include <unixlib.h>
  26. # include <unixio.h>
  27. # include <dvidef.h>
  28. # include <descrip.h>
  29. # include <lib$routines.h>
  30. # include <starlet.h>
  31. #else
  32. # if !defined(sun)
  33. # include <sys/ioctl.h>
  34. # endif
  35. #endif
  36. #ifdef SYSV
  37. # include <sys/termio.h>
  38. # include <sys/stream.h>
  39. # include <sys/ptem.h>
  40. # include <sys/tty.h>
  41. #endif
  42. #if defined (_AIX) && !defined (FD_SET)
  43. # include <sys/select.h> /* for FD_ISSET, FD_SET, FD_ZERO */
  44. #endif
  45. #include <errno.h>
  46. #if defined(__DECC) && defined(VMS)
  47. /* These get prototypes for write an sleep */
  48. # include <unixio.h>
  49. #endif
  50. #include <signal.h>
  51. #include "slang.h"
  52. #include "_slang.h"
  53. /* Colors: These definitions are used for the display. However, the
  54. * application only uses object handles which get mapped to this
  55. * internal representation. The mapping is performed by the Color_Map
  56. * structure below. */
  57. #define CHAR_MASK 0x000000FF
  58. #define FG_MASK 0x0000FF00
  59. #define BG_MASK 0x00FF0000
  60. #define ATTR_MASK 0x1F000000
  61. #define BGALL_MASK 0x0FFF0000
  62. /* The 0x10000000 bit represents the alternate character set. BGALL_MASK does
  63. * not include this attribute.
  64. */
  65. #define GET_FG(color) ((color & FG_MASK) >> 8)
  66. #define GET_BG(color) ((color & BG_MASK) >> 16)
  67. #define MAKE_COLOR(fg, bg) (((fg) | ((bg) << 8)) << 8)
  68. int SLtt_Screen_Cols;
  69. int SLtt_Screen_Rows;
  70. int SLtt_Term_Cannot_Insert;
  71. int SLtt_Term_Cannot_Scroll;
  72. int SLtt_Use_Ansi_Colors;
  73. int SLtt_Blink_Mode = 1;
  74. int SLtt_Use_Blink_For_ACS = 0;
  75. int SLtt_Newline_Ok = 0;
  76. int SLtt_Has_Alt_Charset = 0;
  77. int SLtt_Force_Keypad_Init = 0;
  78. void (*_SLtt_color_changed_hook)(void);
  79. #if SLTT_HAS_NON_BCE_SUPPORT
  80. static int Bce_Color_Offset = 0;
  81. #endif
  82. static int Can_Background_Color_Erase = 1;
  83. /* -1 means unknown */
  84. int SLtt_Has_Status_Line = -1; /* hs */
  85. int SLang_TT_Write_FD = -1;
  86. static int Automatic_Margins;
  87. /* static int No_Move_In_Standout; */
  88. static int Worthless_Highlight;
  89. #define HP_GLITCH_CODE
  90. #ifdef HP_GLITCH_CODE
  91. /* This glitch is exclusive to HP term. Basically it means that to clear
  92. * attributes, one has to erase to the end of the line.
  93. */
  94. static int Has_HP_Glitch;
  95. #endif
  96. static char *Reset_Color_String;
  97. static int Is_Color_Terminal = 0;
  98. static int Linux_Console;
  99. static int QANSI_Console;
  100. /* It is crucial that JMAX_COLORS must be less than 128 since the high bit
  101. * is used to indicate a character from the ACS (alt char set). The exception
  102. * to this rule is if SLtt_Use_Blink_For_ACS is true. This means that of
  103. * the highbit is set, we interpret that as a blink character. This is
  104. * exploited by DOSemu.
  105. */
  106. #define JMAX_COLORS 256
  107. #define JNORMAL_COLOR 0
  108. typedef struct
  109. {
  110. SLtt_Char_Type fgbg;
  111. SLtt_Char_Type mono;
  112. char *custom_esc;
  113. }
  114. Ansi_Color_Type;
  115. #define RGB1(r, g, b) ((r) | ((g) << 1) | ((b) << 2))
  116. #define RGB(r, g, b, br, bg, bb) ((RGB1(r, g, b) << 8) | (RGB1(br, bg, bb) << 16))
  117. static Ansi_Color_Type Ansi_Color_Map[JMAX_COLORS] =
  118. {
  119. {RGB(1, 1, 1, 0, 0, 0), 0x00000000, NULL}, /* white/black */
  120. {RGB(0, 1, 0, 0, 0, 0), SLTT_REV_MASK, NULL}, /* green/black */
  121. {RGB(1, 0, 1, 0, 0, 0), SLTT_REV_MASK, NULL}, /* magenta/black */
  122. {RGB(0, 1, 1, 0, 0, 0), SLTT_REV_MASK, NULL}, /* cyan/black */
  123. {RGB(1, 0, 0, 0, 0, 0), SLTT_REV_MASK, NULL},
  124. {RGB(0, 1, 0, 0, 0, 1), SLTT_REV_MASK, NULL},
  125. {RGB(1, 0, 0, 0, 0, 1), SLTT_REV_MASK, NULL},
  126. {RGB(1, 0, 0, 0, 1, 0), SLTT_REV_MASK, NULL},
  127. {RGB(0, 0, 1, 1, 0, 0), SLTT_REV_MASK, NULL},
  128. {RGB(0, 1, 0, 1, 0, 0), SLTT_REV_MASK, NULL},
  129. {RGB(0, 1, 1, 1, 1, 1), SLTT_REV_MASK, NULL},
  130. {RGB(1, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
  131. {RGB(1, 0, 1, 1, 1, 1), SLTT_REV_MASK, NULL},
  132. {RGB(0, 0, 0, 0, 1, 1), SLTT_REV_MASK, NULL},
  133. {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
  134. {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
  135. {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
  136. {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL}
  137. };
  138. /* 0 if least significant bit is blue, not red */
  139. static int Is_Fg_BGR = 0;
  140. static int Is_Bg_BGR = 0;
  141. #define COLOR_ARG(color, is_bgr) ((is_bgr) ? RGB_to_BGR[(color)&0x7] : (color))
  142. static const int RGB_to_BGR[] =
  143. {
  144. 0, 4, 2, 6, 1, 5, 3, 7
  145. };
  146. static char *Color_Fg_Str = "\033[3%dm";
  147. static char *Color_Bg_Str = "\033[4%dm";
  148. static char *Default_Color_Fg_Str = "\033[39m";
  149. static char *Default_Color_Bg_Str = "\033[49m";
  150. static int Max_Terminfo_Colors = 8; /* termcap Co */
  151. char *SLtt_Graphics_Char_Pairs; /* ac termcap string -- def is vt100 */
  152. /* 1 if terminal lacks the ability to go into insert mode or into delete
  153. mode. Currently controlled by S-Lang but later perhaps termcap. */
  154. static char *UnderLine_Vid_Str;
  155. static char *Blink_Vid_Str;
  156. static char *Bold_Vid_Str;
  157. static char *Ins_Mode_Str; /* = "\033[4h"; */ /* ins mode (im) */
  158. static char *Eins_Mode_Str; /* = "\033[4l"; */ /* end ins mode (ei) */
  159. static char *Scroll_R_Str; /* = "\033[%d;%dr"; */ /* scroll region */
  160. static char *Cls_Str; /* = "\033[2J\033[H"; */ /* cl termcap STR for ansi terminals */
  161. static char *Rev_Vid_Str; /* = "\033[7m"; */ /* mr,so termcap string */
  162. static char *Norm_Vid_Str; /* = "\033[m"; */ /* me,se termcap string */
  163. static char *Del_Eol_Str; /* = "\033[K"; */ /* ce */
  164. static char *Del_Bol_Str; /* = "\033[1K"; */ /* cb */
  165. static char *Del_Char_Str; /* = "\033[P"; */ /* dc */
  166. static char *Del_N_Lines_Str; /* = "\033[%dM"; */ /* DL */
  167. static char *Add_N_Lines_Str; /* = "\033[%dL"; */ /* AL */
  168. static char *Rev_Scroll_Str;
  169. static char *Curs_Up_Str;
  170. static char *Curs_F_Str; /* RI termcap string */
  171. static char *Cursor_Visible_Str; /* ve termcap string */
  172. static char *Cursor_Invisible_Str; /* vi termcap string */
  173. #if 0
  174. static char *Start_Mouse_Rpt_Str; /* Start mouse reporting mode */
  175. static char *End_Mouse_Rpt_Str; /* End mouse reporting mode */
  176. #endif
  177. static char *Start_Alt_Chars_Str; /* as */
  178. static char *End_Alt_Chars_Str; /* ae */
  179. static char *Enable_Alt_Char_Set; /* eA */
  180. static char *Term_Init_Str;
  181. static char *Keypad_Init_Str;
  182. static char *Term_Reset_Str;
  183. static char *Keypad_Reset_Str;
  184. /* status line functions */
  185. static char *Disable_Status_line_Str; /* ds */
  186. static char *Return_From_Status_Line_Str; /* fs */
  187. static char *Goto_Status_Line_Str; /* ts */
  188. static int Num_Status_Line_Columns; /* ws */
  189. /* static int Status_Line_Esc_Ok; */ /* es */
  190. /* static int Len_Curs_F_Str = 5; */
  191. /* cm string has %i%d since termcap numbers columns from 0 */
  192. /* char *CURS_POS_STR = "\033[%d;%df"; ansi-- hor and vert pos */
  193. static char *Curs_Pos_Str; /* = "\033[%i%d;%dH";*/ /* cm termcap string */
  194. /* scrolling region */
  195. static int Scroll_r1 = 0, Scroll_r2 = 23;
  196. static int Cursor_r, Cursor_c; /* 0 based */
  197. /* current attributes --- initialized to impossible value */
  198. static SLtt_Char_Type Current_Fgbg = 0xFFFFFFFFU;
  199. static int Cursor_Set; /* 1 if cursor position known, 0
  200. * if not. -1 if only row is known
  201. */
  202. #define MAX_OUTPUT_BUFFER_SIZE 4096
  203. static unsigned char Output_Buffer[MAX_OUTPUT_BUFFER_SIZE];
  204. static unsigned char *Output_Bufferp = Output_Buffer;
  205. unsigned long SLtt_Num_Chars_Output;
  206. int _SLusleep (unsigned long usecs)
  207. {
  208. #if !defined(VMS) || (__VMS_VER >= 70000000)
  209. struct timeval tv;
  210. tv.tv_sec = usecs / 1000000;
  211. tv.tv_usec = usecs % 1000000;
  212. return select(0, NULL, NULL, NULL, &tv);
  213. #else
  214. return 0;
  215. #endif
  216. }
  217. int SLtt_flush_output (void)
  218. {
  219. int nwrite = 0;
  220. unsigned int total;
  221. int n = (int) (Output_Bufferp - Output_Buffer);
  222. SLtt_Num_Chars_Output += n;
  223. total = 0;
  224. while (n > 0)
  225. {
  226. nwrite = write (SLang_TT_Write_FD, (char *) Output_Buffer + total, n);
  227. if (nwrite == -1)
  228. {
  229. nwrite = 0;
  230. #ifdef EAGAIN
  231. if (errno == EAGAIN)
  232. {
  233. _SLusleep (100000); /* 1/10 sec */
  234. continue;
  235. }
  236. #endif
  237. #ifdef EWOULDBLOCK
  238. if (errno == EWOULDBLOCK)
  239. {
  240. _SLusleep (100000);
  241. continue;
  242. }
  243. #endif
  244. #ifdef EINTR
  245. if (errno == EINTR) continue;
  246. #endif
  247. break;
  248. }
  249. n -= nwrite;
  250. total += nwrite;
  251. }
  252. Output_Bufferp = Output_Buffer;
  253. return n;
  254. }
  255. int SLtt_Baud_Rate;
  256. static void tt_write(char *str, unsigned int n)
  257. {
  258. static unsigned long last_time;
  259. static int total;
  260. unsigned long now;
  261. unsigned int ndiff;
  262. if ((str == NULL) || (n == 0)) return;
  263. total += n;
  264. while (1)
  265. {
  266. ndiff = MAX_OUTPUT_BUFFER_SIZE - (int) (Output_Bufferp - Output_Buffer);
  267. if (ndiff < n)
  268. {
  269. SLMEMCPY ((char *) Output_Bufferp, str, ndiff);
  270. Output_Bufferp += ndiff;
  271. SLtt_flush_output ();
  272. n -= ndiff;
  273. str += ndiff;
  274. }
  275. else
  276. {
  277. SLMEMCPY ((char *) Output_Bufferp, str, n);
  278. Output_Bufferp += n;
  279. break;
  280. }
  281. }
  282. if (((SLtt_Baud_Rate > 150) && (SLtt_Baud_Rate <= 9600))
  283. && (10 * total > SLtt_Baud_Rate))
  284. {
  285. total = 0;
  286. if ((now = (unsigned long) time(NULL)) - last_time <= 1)
  287. {
  288. SLtt_flush_output ();
  289. sleep((unsigned) 1);
  290. }
  291. last_time = now;
  292. }
  293. }
  294. static void tt_write_string (char *str)
  295. {
  296. if (str != NULL) tt_write(str, strlen(str));
  297. }
  298. void SLtt_write_string (char *str)
  299. {
  300. tt_write_string (str);
  301. Cursor_Set = 0;
  302. }
  303. void SLtt_putchar (char ch)
  304. {
  305. SLtt_normal_video ();
  306. if (Cursor_Set == 1)
  307. {
  308. if (ch >= ' ') Cursor_c++;
  309. else if (ch == '\b') Cursor_c--;
  310. else if (ch == '\r') Cursor_c = 0;
  311. else Cursor_Set = 0;
  312. if ((Cursor_c + 1 == SLtt_Screen_Cols)
  313. && Automatic_Margins) Cursor_Set = 0;
  314. }
  315. if (Output_Bufferp < Output_Buffer + MAX_OUTPUT_BUFFER_SIZE)
  316. {
  317. *Output_Bufferp++ = (unsigned char) ch;
  318. }
  319. else tt_write (&ch, 1);
  320. }
  321. static unsigned int tt_sprintf(char *buf, unsigned int buflen, char *fmt, int x, int y)
  322. {
  323. char *fmt_max;
  324. unsigned char *b, *bmax, ch;
  325. int offset;
  326. int z, z1, parse_level;
  327. int zero_pad;
  328. int field_width;
  329. int variables [26];
  330. int stack [64];
  331. unsigned int stack_len;
  332. int parms [10];
  333. #define STACK_POP (stack_len ? stack[--stack_len] : 0)
  334. if (fmt == NULL)
  335. {
  336. *buf = 0;
  337. return 0;
  338. }
  339. stack [0] = y; /* pushed for termcap */
  340. stack [1] = x;
  341. stack_len = 2;
  342. parms [1] = x; /* p1 */
  343. parms [2] = y; /* p2 */
  344. offset = 0;
  345. zero_pad = 0;
  346. field_width = 0;
  347. b = (unsigned char *) buf;
  348. bmax = b + buflen;
  349. fmt_max = fmt + strlen (fmt);
  350. while ((fmt < fmt_max) && (b < bmax))
  351. {
  352. ch = *fmt++;
  353. if (ch != '%')
  354. {
  355. *b++ = ch;
  356. continue;
  357. }
  358. if (fmt == fmt_max) break;
  359. ch = *fmt++;
  360. switch (ch)
  361. {
  362. default:
  363. *b++ = ch;
  364. break;
  365. case 'p':
  366. if (fmt == fmt_max) break;
  367. ch = *fmt++;
  368. if ((ch >= '0') && (ch <= '9'))
  369. stack [stack_len++] = parms [ch - '0'];
  370. break;
  371. case '\'': /* 'x' */
  372. if (fmt == fmt_max) break;
  373. stack [stack_len++] = *fmt++;
  374. if (fmt < fmt_max) fmt++; /* skip ' */
  375. break;
  376. case '{': /* literal constant, e.g. {30} */
  377. z = 0;
  378. while ((fmt < fmt_max) && ((ch = *fmt) <= '9') && (ch >= '0'))
  379. {
  380. z = z * 10 + (ch - '0');
  381. fmt++;
  382. }
  383. stack [stack_len++] = z;
  384. if ((ch == '}') && (fmt < fmt_max)) fmt++;
  385. break;
  386. case '0':
  387. if (fmt == fmt_max) break;
  388. ch = *fmt;
  389. if ((ch != '2') && (ch != '3'))
  390. break;
  391. zero_pad = 1;
  392. fmt++;
  393. /* drop */
  394. case '2':
  395. case '3':
  396. if (fmt == fmt_max) break;
  397. if (*fmt == 'x')
  398. {
  399. char x_fmt_buf [4];
  400. char *x_fmt_buf_ptr;
  401. x_fmt_buf_ptr = x_fmt_buf;
  402. if (zero_pad) *x_fmt_buf_ptr++ = '0';
  403. *x_fmt_buf_ptr++ = ch;
  404. *x_fmt_buf_ptr++ = 'X';
  405. *x_fmt_buf_ptr = 0;
  406. z = STACK_POP;
  407. z += offset;
  408. sprintf ((char *)b, x_fmt_buf, z);
  409. b += strlen ((char *)b);
  410. zero_pad = 0;
  411. break;
  412. }
  413. field_width = (ch - '0');
  414. /* drop */
  415. case 'd':
  416. z = STACK_POP;
  417. z += offset;
  418. if (z >= 100)
  419. {
  420. *b++ = z / 100 + '0';
  421. z = z % 100;
  422. zero_pad = 1;
  423. field_width = 2;
  424. }
  425. else if (zero_pad && (field_width == 3))
  426. *b++ = '0';
  427. if (z >= 10)
  428. {
  429. *b++ = z / 10 + '0';
  430. z = z % 10;
  431. }
  432. else if (zero_pad && (field_width >= 2))
  433. *b++ = '0';
  434. if (b == bmax) break;
  435. *b++ = z + '0';
  436. field_width = zero_pad = 0;
  437. break;
  438. case 'x':
  439. z = STACK_POP;
  440. z += offset;
  441. if (b + 16 >= bmax)
  442. break;
  443. sprintf ((char *) b, "%X", z);
  444. b += strlen ((char *)b);
  445. break;
  446. case 'i':
  447. offset = 1;
  448. break;
  449. case '+':
  450. /* Handling this depends upon whether or not we are parsing
  451. * terminfo. Terminfo requires the stack so use it as an
  452. * indicator.
  453. */
  454. if (stack_len > 2)
  455. {
  456. z = STACK_POP;
  457. stack [stack_len - 1] += z;
  458. }
  459. else if (fmt < fmt_max)
  460. {
  461. ch = *fmt++;
  462. if ((unsigned char) ch == 128) ch = 0;
  463. ch = ch + (unsigned char) STACK_POP;
  464. if (ch == '\n') ch++;
  465. *b++ = ch;
  466. }
  467. break;
  468. /* Binary operators */
  469. case '-':
  470. case '*':
  471. case '/':
  472. case 'm':
  473. case '&':
  474. case '|':
  475. case '^':
  476. case '=':
  477. case '>':
  478. case '<':
  479. case 'A':
  480. case 'O':
  481. z1 = STACK_POP;
  482. z = STACK_POP;
  483. switch (ch)
  484. {
  485. case '-': z = (z - z1); break;
  486. case '*': z = (z * z1); break;
  487. case '/': z = (z / z1); break;
  488. case 'm': z = (z % z1); break;
  489. case '&': z = (z & z1); break;
  490. case '|': z = (z | z1); break;
  491. case '^': z = (z ^ z1); break;
  492. case '=': z = (z == z1); break;
  493. case '>': z = (z > z1); break;
  494. case '<': z = (z < z1); break;
  495. case 'A': z = (z && z1); break;
  496. case 'O': z = (z || z1); break;
  497. }
  498. stack [stack_len++] = z;
  499. break;
  500. /* unary */
  501. case '!':
  502. z = STACK_POP;
  503. stack [stack_len++] = !z;
  504. break;
  505. case '~':
  506. z = STACK_POP;
  507. stack [stack_len++] = ~z;
  508. break;
  509. case 'r': /* termcap -- swap parameters */
  510. z = stack [0];
  511. stack [0] = stack [1];
  512. stack [1] = z;
  513. break;
  514. case '.': /* termcap */
  515. case 'c':
  516. ch = (unsigned char) STACK_POP;
  517. if (ch == '\n') ch++;
  518. *b++ = ch;
  519. break;
  520. case 'g':
  521. if (fmt == fmt_max) break;
  522. ch = *fmt++;
  523. if ((ch >= 'a') && (ch <= 'z'))
  524. stack [stack_len++] = variables [ch - 'a'];
  525. break;
  526. case 'P':
  527. if (fmt == fmt_max) break;
  528. ch = *fmt++;
  529. if ((ch >= 'a') && (ch <= 'z'))
  530. variables [ch - 'a'] = STACK_POP;
  531. break;
  532. /* If then else parsing. Actually, this is rather easy. The
  533. * key is to notice that 'then' does all the work. 'if' simply
  534. * there to indicate the start of a test and endif indicates
  535. * the end of tests. If 'else' is seen, then skip to
  536. * endif.
  537. */
  538. case '?': /* if */
  539. case ';': /* endif */
  540. break;
  541. case 't': /* then */
  542. z = STACK_POP;
  543. if (z != 0)
  544. break; /* good. Continue parsing. */
  545. /* z == 0 and test has failed. So, skip past this entire if
  546. * expression to the matching else or matching endif.
  547. */
  548. /* drop */
  549. case 'e': /* else */
  550. parse_level = 0;
  551. while (fmt < fmt_max)
  552. {
  553. unsigned char ch1;
  554. ch1 = *fmt++;
  555. if ((ch1 != '%') || (fmt == fmt_max))
  556. continue;
  557. ch1 = *fmt++;
  558. if (ch1 == '?') parse_level++; /* new if */
  559. else if (ch1 == 'e')
  560. {
  561. if ((ch != 'e') && (parse_level == 0))
  562. break;
  563. }
  564. else if (ch1 == ';')
  565. {
  566. if (parse_level == 0)
  567. break;
  568. parse_level--;
  569. }
  570. }
  571. break;
  572. }
  573. }
  574. if (b >= bmax)
  575. b = bmax - 1;
  576. *b = 0;
  577. return (unsigned int) (b - (unsigned char *) buf);
  578. }
  579. static void tt_printf(char *fmt, int x, int y)
  580. {
  581. char buf[1024];
  582. unsigned int n;
  583. if (fmt == NULL) return;
  584. n = tt_sprintf(buf, sizeof (buf), fmt, x, y);
  585. tt_write(buf, n);
  586. }
  587. void SLtt_set_scroll_region (int r1, int r2)
  588. {
  589. Scroll_r1 = r1;
  590. Scroll_r2 = r2;
  591. tt_printf (Scroll_R_Str, Scroll_r1, Scroll_r2);
  592. Cursor_Set = 0;
  593. }
  594. void SLtt_reset_scroll_region (void)
  595. {
  596. SLtt_set_scroll_region(0, SLtt_Screen_Rows - 1);
  597. }
  598. int SLtt_set_cursor_visibility (int show)
  599. {
  600. if ((Cursor_Visible_Str == NULL) || (Cursor_Invisible_Str == NULL))
  601. return -1;
  602. tt_write_string (show ? Cursor_Visible_Str : Cursor_Invisible_Str);
  603. return 0;
  604. }
  605. /* the goto_rc function moves to row relative to scrolling region */
  606. void SLtt_goto_rc(int r, int c)
  607. {
  608. char *s = NULL;
  609. int n;
  610. char buf[6];
  611. if ((c < 0) || (r < 0))
  612. {
  613. Cursor_Set = 0;
  614. return;
  615. }
  616. /* if (No_Move_In_Standout && Current_Fgbg) SLtt_normal_video (); */
  617. r += Scroll_r1;
  618. if ((Cursor_Set > 0) || ((Cursor_Set < 0) && !Automatic_Margins))
  619. {
  620. n = r - Cursor_r;
  621. if ((n == -1) && (Cursor_Set > 0) && (Cursor_c == c)
  622. && (Curs_Up_Str != NULL))
  623. {
  624. s = Curs_Up_Str;
  625. }
  626. else if ((n >= 0) && (n <= 4))
  627. {
  628. if ((n == 0) && (Cursor_Set == 1)
  629. && ((c > 1) || (c == Cursor_c)))
  630. {
  631. if (Cursor_c == c) return;
  632. if (Cursor_c == c + 1)
  633. {
  634. /* cursor movement optimizations, like backspace
  635. doesn't work as needed on qansi-m consoles when
  636. current table is not a G0, so we'll disable it. */
  637. if (!QANSI_Console)
  638. {
  639. s = "\b";
  640. }
  641. else
  642. {
  643. /* do the generic cursor positioning,
  644. without an optimization */
  645. s = NULL;
  646. }
  647. }
  648. }
  649. else if ((c == 0) && (!QANSI_Console)) /* the same things
  650. for the qansi-m console limitation */
  651. {
  652. s = buf;
  653. if ((Cursor_Set != 1) || (Cursor_c != 0)) *s++ = '\r';
  654. while (n--) *s++ = '\n';
  655. #ifdef VMS
  656. /* Need to add this after \n to start a new record. Sheesh. */
  657. *s++ = '\r';
  658. #endif
  659. *s = 0;
  660. s = buf;
  661. }
  662. /* Will fail on VMS */
  663. #ifndef VMS
  664. else if ((SLtt_Newline_Ok && (Cursor_Set == 1) &&
  665. (Cursor_c >= c) && (c + 3 > Cursor_c)) &&
  666. (!QANSI_Console))
  667. {
  668. s = buf;
  669. while (n--) *s++ = '\n';
  670. n = Cursor_c - c;
  671. while (n--) *s++ = '\b';
  672. *s = 0;
  673. s = buf;
  674. }
  675. #endif
  676. }
  677. }
  678. if (s != NULL) tt_write_string(s);
  679. else tt_printf(Curs_Pos_Str, r, c);
  680. Cursor_c = c; Cursor_r = r;
  681. Cursor_Set = 1;
  682. }
  683. void SLtt_begin_insert (void)
  684. {
  685. tt_write_string(Ins_Mode_Str);
  686. }
  687. void SLtt_end_insert (void)
  688. {
  689. tt_write_string(Eins_Mode_Str);
  690. }
  691. void SLtt_delete_char (void)
  692. {
  693. SLtt_normal_video ();
  694. tt_write_string(Del_Char_Str);
  695. }
  696. void SLtt_erase_line (void)
  697. {
  698. tt_write ("\r", 1);
  699. Cursor_Set = 1; Cursor_c = 0;
  700. SLtt_del_eol();
  701. /* Put the cursor back at the beginning of the line */
  702. tt_write ("\r", 1);
  703. Cursor_Set = 1; Cursor_c = 0;
  704. }
  705. /* It appears that the Linux console, and most likely others do not
  706. * like scrolling regions that consist of one line. So I have to
  707. * resort to this stupidity to make up for that stupidity.
  708. */
  709. static void delete_line_in_scroll_region (void)
  710. {
  711. SLtt_goto_rc (Cursor_r - Scroll_r1, 0);
  712. SLtt_del_eol ();
  713. }
  714. void SLtt_delete_nlines (int n)
  715. {
  716. int r1, curs;
  717. char buf[132];
  718. if (n <= 0) return;
  719. SLtt_normal_video ();
  720. if (Scroll_r1 == Scroll_r2)
  721. {
  722. delete_line_in_scroll_region ();
  723. return;
  724. }
  725. if (Del_N_Lines_Str != NULL) tt_printf(Del_N_Lines_Str,n, 0);
  726. else
  727. /* get a new terminal */
  728. {
  729. int t = n;
  730. r1 = Scroll_r1;
  731. curs = Cursor_r;
  732. SLtt_set_scroll_region(curs, Scroll_r2);
  733. SLtt_goto_rc(Scroll_r2 - Scroll_r1, 0);
  734. if (n > sizeof (buf))
  735. t = sizeof (buf);
  736. SLMEMSET (buf, '\n', t);
  737. do {
  738. tt_write (buf, (n < t) ? n : t);
  739. n -= t;
  740. } while (n > 0);
  741. /* while (n--) tt_putchar('\n'); */
  742. SLtt_set_scroll_region(r1, Scroll_r2);
  743. SLtt_goto_rc(curs, 0);
  744. }
  745. }
  746. void SLtt_cls (void)
  747. {
  748. /* If the terminal is a color terminal but the user wants black and
  749. * white, then make sure that the colors are reset. This appears to be
  750. * necessary.
  751. */
  752. if ((SLtt_Use_Ansi_Colors == 0) && Is_Color_Terminal)
  753. {
  754. if (Reset_Color_String != NULL)
  755. tt_write_string (Reset_Color_String);
  756. else
  757. tt_write ("\033[0m\033[m", 7);
  758. }
  759. SLtt_normal_video();
  760. SLtt_reset_scroll_region ();
  761. tt_write_string(Cls_Str);
  762. }
  763. void SLtt_reverse_index (int n)
  764. {
  765. if (!n) return;
  766. SLtt_normal_video();
  767. if (Scroll_r1 == Scroll_r2)
  768. {
  769. delete_line_in_scroll_region ();
  770. return;
  771. }
  772. if (Add_N_Lines_Str != NULL) tt_printf(Add_N_Lines_Str,n, 0);
  773. else
  774. {
  775. while(n--) tt_write_string(Rev_Scroll_Str);
  776. }
  777. }
  778. int SLtt_Ignore_Beep = 1;
  779. static char *Visible_Bell_Str;
  780. void SLtt_beep (void)
  781. {
  782. if (SLtt_Ignore_Beep & 0x1) SLtt_putchar('\007');
  783. if (SLtt_Ignore_Beep & 0x2)
  784. {
  785. if (Visible_Bell_Str != NULL) tt_write_string (Visible_Bell_Str);
  786. #ifdef __linux__
  787. else if (Linux_Console)
  788. {
  789. tt_write ("\033[?5h", 5);
  790. SLtt_flush_output ();
  791. _SLusleep (50000);
  792. tt_write ("\033[?5l", 5);
  793. }
  794. #endif
  795. }
  796. SLtt_flush_output ();
  797. }
  798. static void write_string_with_care (char *);
  799. static void del_eol (void)
  800. {
  801. #if 0
  802. int c;
  803. #endif
  804. if ((Del_Eol_Str != NULL)
  805. && (Can_Background_Color_Erase || ((Current_Fgbg & ~0xFF) == 0)))
  806. {
  807. tt_write_string(Del_Eol_Str);
  808. return;
  809. }
  810. #if 0
  811. c = Cursor_c;
  812. /* Avoid writing to the lower right corner. If the terminal does not
  813. * have Del_Eol_Str, then it probably does not have what it takes to play
  814. * games with insert-mode to "push" the desired character into that corner.
  815. */
  816. if (Cursor_r + 1 < SLtt_Screen_Rows)
  817. c++;
  818. while (c < SLtt_Screen_Cols)
  819. {
  820. tt_write (" ", 1);
  821. c++;
  822. }
  823. Cursor_c = (SLtt_Screen_Cols-1);
  824. #else
  825. while (Cursor_c < SLtt_Screen_Cols)
  826. {
  827. write_string_with_care (" ");
  828. Cursor_c++;
  829. }
  830. Cursor_c = SLtt_Screen_Cols - 1;
  831. Cursor_Set = 0;
  832. #endif
  833. }
  834. void SLtt_del_eol (void)
  835. {
  836. if (Current_Fgbg != 0xFFFFFFFFU) SLtt_normal_video ();
  837. del_eol ();
  838. }
  839. typedef const struct
  840. {
  841. char *name;
  842. SLtt_Char_Type color;
  843. }
  844. Color_Def_Type;
  845. #define MAX_COLOR_NAMES 17
  846. static Color_Def_Type Color_Defs [MAX_COLOR_NAMES] =
  847. {
  848. {"black", SLSMG_COLOR_BLACK},
  849. {"red", SLSMG_COLOR_RED},
  850. {"green", SLSMG_COLOR_GREEN},
  851. {"brown", SLSMG_COLOR_BROWN},
  852. {"blue", SLSMG_COLOR_BLUE},
  853. {"magenta", SLSMG_COLOR_MAGENTA},
  854. {"cyan", SLSMG_COLOR_CYAN},
  855. {"lightgray", SLSMG_COLOR_LGRAY},
  856. {"gray", SLSMG_COLOR_GRAY},
  857. {"brightred", SLSMG_COLOR_BRIGHT_RED},
  858. {"brightgreen", SLSMG_COLOR_BRIGHT_GREEN},
  859. {"yellow", SLSMG_COLOR_BRIGHT_BROWN},
  860. {"brightblue", SLSMG_COLOR_BRIGHT_BLUE},
  861. {"brightmagenta", SLSMG_COLOR_BRIGHT_CYAN},
  862. {"brightcyan", SLSMG_COLOR_BRIGHT_MAGENTA},
  863. {"white", SLSMG_COLOR_BRIGHT_WHITE},
  864. #define SLSMG_COLOR_DEFAULT 0xFF
  865. {"default", SLSMG_COLOR_DEFAULT}
  866. };
  867. void SLtt_set_mono (int obj, char *what, SLtt_Char_Type mask)
  868. {
  869. (void) what;
  870. if ((obj < 0) || (obj >= JMAX_COLORS))
  871. {
  872. return;
  873. }
  874. Ansi_Color_Map[obj].mono = mask & ATTR_MASK;
  875. }
  876. static char *check_color_for_digit_form (char *color)
  877. {
  878. unsigned int i, ich;
  879. unsigned char *s = (unsigned char *) color;
  880. i = 0;
  881. while ((ich = (unsigned int) *s) != 0)
  882. {
  883. if ((ich < '0') || (ich > '9'))
  884. return color;
  885. i = i * 10 + (ich - '0');
  886. s++;
  887. }
  888. if (i < MAX_COLOR_NAMES)
  889. color = Color_Defs[i].name;
  890. return color;
  891. }
  892. static int get_default_colors (char **fgp, char **bgp)
  893. {
  894. static char fg_buf[16], bg_buf[16], *bg, *fg;
  895. static int already_parsed;
  896. char *p, *pmax;
  897. if (already_parsed == -1)
  898. return -1;
  899. if (already_parsed)
  900. {
  901. *fgp = fg;
  902. *bgp = bg;
  903. return 0;
  904. }
  905. already_parsed = -1;
  906. bg = getenv ("COLORFGBG");
  907. if (bg == NULL)
  908. {
  909. bg = getenv ("DEFAULT_COLORS");
  910. if (bg == NULL)
  911. return -1;
  912. }
  913. p = fg_buf;
  914. pmax = p + (sizeof (fg_buf) - 1);
  915. while ((*bg != 0) && (*bg != ';'))
  916. {
  917. if (p < pmax) *p++ = *bg;
  918. bg++;
  919. }
  920. *p = 0;
  921. if (*bg) bg++;
  922. p = bg_buf;
  923. pmax = p + (sizeof (bg_buf) - 1);
  924. /* Mark suggested allowing for extra application specific stuff following
  925. * the background color. That is what the check for the semi-colon is for.
  926. */
  927. while ((*bg != 0) && (*bg != ';'))
  928. {
  929. if (p < pmax) *p++ = *bg;
  930. bg++;
  931. }
  932. *p = 0;
  933. if (!strcmp (fg_buf, "default") || !strcmp(bg_buf, "default"))
  934. {
  935. *fgp = *bgp = fg = bg = "default";
  936. }
  937. else
  938. {
  939. *fgp = fg = check_color_for_digit_form (fg_buf);
  940. *bgp = bg = check_color_for_digit_form (bg_buf);
  941. }
  942. already_parsed = 1;
  943. return 0;
  944. }
  945. static unsigned char FgBg_Stats[JMAX_COLORS];
  946. static int Color_0_Modified = 0;
  947. void SLtt_set_color_object (int obj, SLtt_Char_Type attr)
  948. {
  949. char *cust_esc;
  950. if ((obj < 0) || (obj >= JMAX_COLORS)) return;
  951. cust_esc = Ansi_Color_Map[obj].custom_esc;
  952. if (cust_esc != NULL)
  953. {
  954. SLfree (cust_esc);
  955. FgBg_Stats[(Ansi_Color_Map[obj].fgbg >> 8) & 0x7F] -= 1;
  956. Ansi_Color_Map[obj].custom_esc = NULL;
  957. }
  958. Ansi_Color_Map[obj].fgbg = attr;
  959. if (obj == 0) Color_0_Modified = 1;
  960. if (_SLtt_color_changed_hook != NULL)
  961. (*_SLtt_color_changed_hook)();
  962. }
  963. SLtt_Char_Type SLtt_get_color_object (int obj)
  964. {
  965. if ((obj < 0) || (obj >= JMAX_COLORS)) return 0;
  966. return Ansi_Color_Map[obj].fgbg;
  967. }
  968. void SLtt_add_color_attribute (int obj, SLtt_Char_Type attr)
  969. {
  970. if ((obj < 0) || (obj >= JMAX_COLORS)) return;
  971. Ansi_Color_Map[obj].fgbg |= (attr & ATTR_MASK);
  972. if (obj == 0) Color_0_Modified = 1;
  973. if (_SLtt_color_changed_hook != NULL)
  974. (*_SLtt_color_changed_hook)();
  975. }
  976. static SLtt_Char_Type fb_to_fgbg (SLtt_Char_Type f, SLtt_Char_Type b)
  977. {
  978. SLtt_Char_Type attr;
  979. if (Max_Terminfo_Colors != 8)
  980. {
  981. if (f != SLSMG_COLOR_DEFAULT) f %= Max_Terminfo_Colors;
  982. if (b != SLSMG_COLOR_DEFAULT) b %= Max_Terminfo_Colors;
  983. return ((f << 8) | (b << 16));
  984. }
  985. /* Otherwise we have 8 ansi colors. Try to get bright versions
  986. * by using the BOLD and BLINK attributes.
  987. */
  988. attr = 0;
  989. /* Note: If f represents default, it will have the value 0xFF */
  990. if (f != SLSMG_COLOR_DEFAULT)
  991. {
  992. if (f & 0x8) attr = SLTT_BOLD_MASK;
  993. f &= 0x7;
  994. }
  995. if (b != SLSMG_COLOR_DEFAULT)
  996. {
  997. if (b & 0x8) attr |= SLTT_BLINK_MASK;
  998. b &= 0x7;
  999. }
  1000. return ((f << 8) | (b << 16) | attr);
  1001. }
  1002. /* This looks for colors with name form 'colorN'. If color is of this
  1003. * form, N is passed back via parameter list.
  1004. */
  1005. static int parse_color_digit_name (char *color, SLtt_Char_Type *f)
  1006. {
  1007. unsigned int i;
  1008. unsigned char ch;
  1009. if (strncmp (color, "color", 5))
  1010. return -1;
  1011. color += 5;
  1012. if (*color == 0)
  1013. return -1;
  1014. i = 0;
  1015. while (1)
  1016. {
  1017. unsigned int j;
  1018. ch = (unsigned char) *color++;
  1019. if (ch == 0)
  1020. break;
  1021. if ((ch > '9') || (ch < '0'))
  1022. return -1;
  1023. if (i > 0xFFFFFFFFU / 10)
  1024. return -1;
  1025. j = (i *= 10);
  1026. i += (ch - '0');
  1027. if (i < j)
  1028. return -1;
  1029. }
  1030. *f = (SLtt_Char_Type) i;
  1031. return 0;
  1032. }
  1033. static int make_color_fgbg (char *fg, char *bg, SLtt_Char_Type *fgbg)
  1034. {
  1035. SLtt_Char_Type f = 0xFFFFFFFFU, b = 0xFFFFFFFFU;
  1036. char *dfg, *dbg;
  1037. unsigned int i;
  1038. if ((fg != NULL) && (*fg == 0)) fg = NULL;
  1039. if ((bg != NULL) && (*bg == 0)) bg = NULL;
  1040. if ((fg == NULL) || (bg == NULL))
  1041. {
  1042. if (-1 == get_default_colors (&dfg, &dbg))
  1043. return -1;
  1044. if (fg == NULL) fg = dfg;
  1045. if (bg == NULL) bg = dbg;
  1046. }
  1047. if (-1 == parse_color_digit_name (fg, &f))
  1048. {
  1049. for (i = 0; i < MAX_COLOR_NAMES; i++)
  1050. {
  1051. if (strcmp(fg, Color_Defs[i].name)) continue;
  1052. f = Color_Defs[i].color;
  1053. break;
  1054. }
  1055. }
  1056. if (-1 == parse_color_digit_name (bg, &b))
  1057. {
  1058. for (i = 0; i < MAX_COLOR_NAMES; i++)
  1059. {
  1060. if (strcmp(bg, Color_Defs[i].name)) continue;
  1061. b = Color_Defs[i].color;
  1062. break;
  1063. }
  1064. }
  1065. if ((f == 0xFFFFFFFFU) || (b == 0xFFFFFFFFU))
  1066. return -1;
  1067. *fgbg = fb_to_fgbg (f, b);
  1068. return 0;
  1069. }
  1070. void SLtt_set_color (int obj, char *what, char *fg, char *bg)
  1071. {
  1072. SLtt_Char_Type fgbg;
  1073. (void) what;
  1074. if ((obj < 0) || (obj >= JMAX_COLORS))
  1075. return;
  1076. if (-1 != make_color_fgbg (fg, bg, &fgbg))
  1077. SLtt_set_color_object (obj, fgbg);
  1078. }
  1079. void SLtt_set_color_fgbg (int obj, SLtt_Char_Type f, SLtt_Char_Type b)
  1080. {
  1081. SLtt_set_color_object (obj, fb_to_fgbg (f, b));
  1082. }
  1083. void SLtt_set_color_esc (int obj, char *esc)
  1084. {
  1085. char *cust_esc;
  1086. SLtt_Char_Type fgbg = 0;
  1087. int i;
  1088. if ((obj < 0) || (obj >= JMAX_COLORS))
  1089. {
  1090. return;
  1091. }
  1092. cust_esc = Ansi_Color_Map[obj].custom_esc;
  1093. if (cust_esc != NULL)
  1094. {
  1095. SLfree (cust_esc);
  1096. FgBg_Stats[(Ansi_Color_Map[obj].fgbg >> 8) & 0x7F] -= 1;
  1097. }
  1098. cust_esc = (char *) SLmalloc (strlen(esc) + 1);
  1099. if (cust_esc != NULL) strcpy (cust_esc, esc);
  1100. Ansi_Color_Map[obj].custom_esc = cust_esc;
  1101. if (cust_esc == NULL) fgbg = 0;
  1102. else
  1103. {
  1104. /* The whole point of this is to generate a unique fgbg */
  1105. for (i = 0; i < JMAX_COLORS; i++)
  1106. {
  1107. if (FgBg_Stats[i] == 0) fgbg = i;
  1108. if (obj == i) continue;
  1109. if ((Ansi_Color_Map[i].custom_esc) == NULL) continue;
  1110. if (!strcmp (Ansi_Color_Map[i].custom_esc, cust_esc))
  1111. {
  1112. fgbg = (Ansi_Color_Map[i].fgbg >> 8) & 0x7F;
  1113. break;
  1114. }
  1115. }
  1116. FgBg_Stats[fgbg] += 1;
  1117. }
  1118. fgbg |= 0x80;
  1119. Ansi_Color_Map[obj].fgbg = (fgbg | (fgbg << 8)) << 8;
  1120. if (obj == 0) Color_0_Modified = 1;
  1121. if (_SLtt_color_changed_hook != NULL)
  1122. (*_SLtt_color_changed_hook)();
  1123. }
  1124. void SLtt_set_alt_char_set (int i)
  1125. {
  1126. static int last_i;
  1127. if (SLtt_Has_Alt_Charset == 0) return;
  1128. i = (i != 0);
  1129. if (i == last_i) return;
  1130. tt_write_string (i ? Start_Alt_Chars_Str : End_Alt_Chars_Str );
  1131. last_i = i;
  1132. }
  1133. static void write_attributes (SLtt_Char_Type fgbg)
  1134. {
  1135. int bg0, fg0;
  1136. int unknown_attributes;
  1137. if (Worthless_Highlight) return;
  1138. if (fgbg == Current_Fgbg) return;
  1139. unknown_attributes = 0;
  1140. /* Before spitting out colors, fix attributes */
  1141. if ((fgbg & ATTR_MASK) != (Current_Fgbg & ATTR_MASK))
  1142. {
  1143. if (Current_Fgbg & ATTR_MASK)
  1144. {
  1145. tt_write_string(Norm_Vid_Str);
  1146. /* In case normal video turns off ALL attributes: */
  1147. if (fgbg & SLTT_ALTC_MASK)
  1148. Current_Fgbg &= ~SLTT_ALTC_MASK;
  1149. SLtt_set_alt_char_set (0);
  1150. }
  1151. if ((fgbg & SLTT_ALTC_MASK)
  1152. != (Current_Fgbg & SLTT_ALTC_MASK))
  1153. {
  1154. SLtt_set_alt_char_set ((int) (fgbg & SLTT_ALTC_MASK));
  1155. }
  1156. if (fgbg & SLTT_ULINE_MASK) tt_write_string (UnderLine_Vid_Str);
  1157. if (fgbg & SLTT_BOLD_MASK) SLtt_bold_video ();
  1158. if (fgbg & SLTT_REV_MASK) tt_write_string (Rev_Vid_Str);
  1159. if (fgbg & SLTT_BLINK_MASK)
  1160. {
  1161. /* Someday Linux will have a blink mode that set high intensity
  1162. * background. Lets be prepared.
  1163. */
  1164. if (SLtt_Blink_Mode) tt_write_string (Blink_Vid_Str);
  1165. }
  1166. unknown_attributes = 1;
  1167. }
  1168. if (SLtt_Use_Ansi_Colors)
  1169. {
  1170. fg0 = (int) GET_FG(fgbg);
  1171. bg0 = (int) GET_BG(fgbg);
  1172. if (unknown_attributes
  1173. || (fg0 != (int)GET_FG(Current_Fgbg)))
  1174. {
  1175. if (fg0 == SLSMG_COLOR_DEFAULT)
  1176. tt_write_string (Default_Color_Fg_Str);
  1177. else
  1178. tt_printf (Color_Fg_Str, COLOR_ARG(fg0, Is_Bg_BGR), 0);
  1179. }
  1180. if (unknown_attributes
  1181. || (bg0 != (int)GET_BG(Current_Fgbg)))
  1182. {
  1183. if (bg0 == SLSMG_COLOR_DEFAULT)
  1184. tt_write_string (Default_Color_Bg_Str);
  1185. else
  1186. tt_printf (Color_Bg_Str, COLOR_ARG(bg0, Is_Bg_BGR), 0);
  1187. }
  1188. }
  1189. Current_Fgbg = fgbg;
  1190. }
  1191. static int Video_Initialized;
  1192. void SLtt_reverse_video (int color)
  1193. {
  1194. SLtt_Char_Type fgbg;
  1195. char *esc;
  1196. if (Worthless_Highlight) return;
  1197. if ((color < 0) || (color >= JMAX_COLORS)) return;
  1198. if (Video_Initialized == 0)
  1199. {
  1200. if (color == JNORMAL_COLOR)
  1201. {
  1202. tt_write_string (Norm_Vid_Str);
  1203. }
  1204. else tt_write_string (Rev_Vid_Str);
  1205. Current_Fgbg = 0xFFFFFFFFU;
  1206. return;
  1207. }
  1208. if (SLtt_Use_Ansi_Colors)
  1209. {
  1210. fgbg = Ansi_Color_Map[color].fgbg;
  1211. if ((esc = Ansi_Color_Map[color].custom_esc) != NULL)
  1212. {
  1213. if (fgbg != Current_Fgbg)
  1214. {
  1215. Current_Fgbg = fgbg;
  1216. tt_write_string (esc);
  1217. return;
  1218. }
  1219. }
  1220. }
  1221. else fgbg = Ansi_Color_Map[color].mono;
  1222. if (fgbg == Current_Fgbg) return;
  1223. write_attributes (fgbg);
  1224. }
  1225. void SLtt_normal_video (void)
  1226. {
  1227. SLtt_reverse_video(JNORMAL_COLOR);
  1228. }
  1229. void SLtt_narrow_width (void)
  1230. {
  1231. tt_write ("\033[?3l", 5);
  1232. }
  1233. void SLtt_wide_width (void)
  1234. {
  1235. tt_write ("\033[?3h", 5);
  1236. }
  1237. /* Highest bit represents the character set. */
  1238. #define COLOR_MASK 0x7F00
  1239. #define COLOR_OF(x) (((x)&COLOR_MASK)>>8)
  1240. #define CHAR_OF(x) ((x)&0x80FF)
  1241. #if SLTT_HAS_NON_BCE_SUPPORT
  1242. static int bce_color_eqs (unsigned int a, unsigned int b)
  1243. {
  1244. a = COLOR_OF(a);
  1245. b = COLOR_OF(b);
  1246. if (a == b)
  1247. return 1;
  1248. if (SLtt_Use_Ansi_Colors == 0)
  1249. return Ansi_Color_Map[a].mono == Ansi_Color_Map[b].mono;
  1250. if (Bce_Color_Offset == 0)
  1251. return Ansi_Color_Map[a].fgbg == Ansi_Color_Map[b].fgbg;
  1252. /* If either are color 0, then we do not know what that means since the
  1253. * terminal does not support BCE */
  1254. if ((a == 0) || (b == 0))
  1255. return 0;
  1256. return Ansi_Color_Map[a-1].fgbg == Ansi_Color_Map[b-1].fgbg;
  1257. }
  1258. #define COLOR_EQS(a,b) bce_color_eqs (a,b)
  1259. #else
  1260. # define COLOR_EQS(a, b) \
  1261. (SLtt_Use_Ansi_Colors \
  1262. ? (Ansi_Color_Map[COLOR_OF(a)].fgbg == Ansi_Color_Map[COLOR_OF(b)].fgbg)\
  1263. : (Ansi_Color_Map[COLOR_OF(a)].mono == Ansi_Color_Map[COLOR_OF(b)].mono))
  1264. #endif
  1265. #define CHAR_EQS(a, b) (((a) == (b))\
  1266. || ((CHAR_OF(a)==CHAR_OF(b)) && COLOR_EQS(a,b)))
  1267. /* The whole point of this routine is to prevent writing to the last column
  1268. * and last row on terminals with automatic margins.
  1269. */
  1270. static void write_string_with_care (char *str)
  1271. {
  1272. unsigned int len;
  1273. if (str == NULL) return;
  1274. len = strlen (str);
  1275. if (Automatic_Margins && (Cursor_r + 1 == SLtt_Screen_Rows))
  1276. {
  1277. if (len + (unsigned int) Cursor_c >= (unsigned int) SLtt_Screen_Cols)
  1278. {
  1279. /* For now, just do not write there. Later, something more
  1280. * sophisticated will be implemented.
  1281. */
  1282. if (SLtt_Screen_Cols > Cursor_c)
  1283. len = SLtt_Screen_Cols - Cursor_c - 1;
  1284. else
  1285. len = 0;
  1286. }
  1287. }
  1288. tt_write (str, len);
  1289. }
  1290. static void send_attr_str (SLsmg_Char_Type *s)
  1291. {
  1292. unsigned char out[SLTT_MAX_SCREEN_COLS], ch, *p;
  1293. register SLtt_Char_Type attr;
  1294. register SLsmg_Char_Type sh;
  1295. int color, last_color = -1;
  1296. p = out;
  1297. while (0 != (sh = *s++))
  1298. {
  1299. ch = sh & 0xFF;
  1300. color = ((int) sh & 0xFF00) >> 8;
  1301. #if SLTT_HAS_NON_BCE_SUPPORT
  1302. if (Bce_Color_Offset
  1303. && (color >= Bce_Color_Offset))
  1304. color -= Bce_Color_Offset;
  1305. #endif
  1306. if (color != last_color)
  1307. {
  1308. if (SLtt_Use_Ansi_Colors) attr = Ansi_Color_Map[color & 0x7F].fgbg;
  1309. else attr = Ansi_Color_Map[color & 0x7F].mono;
  1310. if (sh & 0x8000) /* alternate char set */
  1311. {
  1312. if (SLtt_Use_Blink_For_ACS)
  1313. {
  1314. if (SLtt_Blink_Mode) attr |= SLTT_BLINK_MASK;
  1315. }
  1316. else attr |= SLTT_ALTC_MASK;
  1317. }
  1318. if (attr != Current_Fgbg)
  1319. {
  1320. if ((ch != ' ') ||
  1321. /* it is a space so only consider it different if it
  1322. * has different attributes.
  1323. */
  1324. (attr != Current_Fgbg))
  1325. /* The previous line was: */
  1326. /* (attr & BGALL_MASK) != (Current_Fgbg & BGALL_MASK)) */
  1327. /* However, it does not account for ACS */
  1328. {
  1329. if (p != out)
  1330. {
  1331. *p = 0;
  1332. write_string_with_care ((char *) out);
  1333. Cursor_c += (int) (p - out);
  1334. p = out;
  1335. }
  1336. if (SLtt_Use_Ansi_Colors && (NULL != Ansi_Color_Map[color & 0x7F].custom_esc))
  1337. {
  1338. tt_write_string (Ansi_Color_Map[color & 0x7F].custom_esc);
  1339. /* Just in case the custom escape sequence screwed up
  1340. * the alt character set state...
  1341. */
  1342. if ((attr & SLTT_ALTC_MASK) != (Current_Fgbg & SLTT_ALTC_MASK))
  1343. SLtt_set_alt_char_set ((int) (attr & SLTT_ALTC_MASK));
  1344. Current_Fgbg = attr;
  1345. }
  1346. else write_attributes (attr);
  1347. last_color = color;
  1348. }
  1349. }
  1350. }
  1351. *p++ = ch;
  1352. }
  1353. *p = 0;
  1354. if (p != out) write_string_with_care ((char *) out);
  1355. Cursor_c += (int) (p - out);
  1356. }
  1357. static void forward_cursor (unsigned int n, int row)
  1358. {
  1359. char buf [1024];
  1360. /* if (Current_Fgbg & ~0xFF) */
  1361. /* { */
  1362. /* unsigned int num = 0; */
  1363. /* while (num < n) */
  1364. /* { */
  1365. /* write_string_with_care (" "); */
  1366. /* num++; */
  1367. /* } */
  1368. /* Cursor_c += n; */
  1369. /* return; */
  1370. /* } */
  1371. if (n <= 4)
  1372. {
  1373. SLtt_normal_video ();
  1374. SLMEMSET (buf, ' ', n);
  1375. buf[n] = 0;
  1376. write_string_with_care (buf);
  1377. Cursor_c += n;
  1378. }
  1379. else if (Curs_F_Str != NULL)
  1380. {
  1381. Cursor_c += n;
  1382. n = tt_sprintf(buf, sizeof (buf), Curs_F_Str, (int) n, 0);
  1383. tt_write(buf, n);
  1384. }
  1385. else SLtt_goto_rc (row, (int) (Cursor_c + n));
  1386. }
  1387. /* FIXME!! If the terminal does not support color, then this route has
  1388. * problems of color object 0 has been assigned some monochrome attribute
  1389. * such as reverse video. In such a case, space_char=' ' is not a simple
  1390. * space character as is assumed below.
  1391. */
  1392. void SLtt_smart_puts(SLsmg_Char_Type *neww, SLsmg_Char_Type *oldd, int len, int row)
  1393. {
  1394. register SLsmg_Char_Type *p, *q, *qmax, *pmax, *buf;
  1395. SLsmg_Char_Type buffer[SLTT_MAX_SCREEN_COLS+1];
  1396. unsigned int n_spaces;
  1397. SLsmg_Char_Type *space_match, *last_buffered_match;
  1398. #ifdef HP_GLITCH_CODE
  1399. int handle_hp_glitch = 0;
  1400. #endif
  1401. SLsmg_Char_Type space_char;
  1402. #define SLTT_USE_INSERT_HACK 1
  1403. #if SLTT_USE_INSERT_HACK
  1404. SLsmg_Char_Type insert_hack_prev = 0;
  1405. SLsmg_Char_Type insert_hack_char = 0;
  1406. if ((row + 1 == SLtt_Screen_Rows)
  1407. && (len == SLtt_Screen_Cols)
  1408. && (len > 1)
  1409. && (SLtt_Term_Cannot_Insert == 0)
  1410. && Automatic_Margins)
  1411. {
  1412. insert_hack_char = neww[len-1];
  1413. if (oldd[len-1] == insert_hack_char)
  1414. insert_hack_char = 0;
  1415. else
  1416. insert_hack_prev = neww[len-2];
  1417. }
  1418. #endif
  1419. if (len > SLTT_MAX_SCREEN_COLS)
  1420. len = SLTT_MAX_SCREEN_COLS;
  1421. q = oldd; p = neww;
  1422. qmax = oldd + len;
  1423. pmax = p + len;
  1424. /* Find out where to begin --- while they match, we are ok */
  1425. while (1)
  1426. {
  1427. if (q == qmax) return;
  1428. #if SLANG_HAS_KANJI_SUPPORT
  1429. if (*p & 0x80)
  1430. { /* new is kanji */
  1431. if ((*q & 0x80) && ((q + 1) < qmax))
  1432. { /* old is also kanji */
  1433. if (((0xFF & *q) != (0xFF & *p))
  1434. || ((0xFF & q[1]) != (0xFF & p[1])))
  1435. break; /* both kanji, but not match */
  1436. else
  1437. { /* kanji match ! */
  1438. if (!COLOR_EQS(*q, *p)) break;
  1439. q++; p++;
  1440. if (!COLOR_EQS(*q, *p)) break;
  1441. /* really match! */
  1442. q++; p++;
  1443. continue;
  1444. }
  1445. }
  1446. else break; /* old is not kanji */
  1447. }
  1448. else
  1449. { /* new is not kanji */
  1450. if (*q & 0x80) break; /* old is kanji */
  1451. }
  1452. #endif
  1453. if (!CHAR_EQS(*q, *p)) break;
  1454. q++; p++;
  1455. }
  1456. #ifdef HP_GLITCH_CODE
  1457. if (Has_HP_Glitch)
  1458. {
  1459. SLsmg_Char_Type *qq = q;
  1460. SLtt_goto_rc (row, (int) (p - neww));
  1461. while (qq < qmax)
  1462. {
  1463. if (*qq & 0xFF00)
  1464. {
  1465. SLtt_normal_video ();
  1466. SLtt_del_eol ();
  1467. qmax = q;
  1468. handle_hp_glitch = 1;
  1469. break;
  1470. }
  1471. qq++;
  1472. }
  1473. }
  1474. #endif
  1475. /* Find where the last non-blank character on old/new screen is */
  1476. space_char = ' ';
  1477. if (CHAR_EQS(*(pmax-1), ' '))
  1478. {
  1479. /* If we get here, then we can erase to the end of the line to create
  1480. * the final space. However, this will only work _if_ erasing will
  1481. * get us the correct color. If the terminal supports BCE, then this
  1482. * is easy. If it does not, then we can only perform this operation
  1483. * if the color is known via something like COLORFGBG. For now,
  1484. * I just will not perform the optimization for such terminals.
  1485. */
  1486. if ((Can_Background_Color_Erase)
  1487. && SLtt_Use_Ansi_Colors)
  1488. space_char = *(pmax - 1);
  1489. while (pmax > p)
  1490. {
  1491. pmax--;
  1492. if (!CHAR_EQS(*pmax, space_char))
  1493. {
  1494. pmax++;
  1495. break;
  1496. }
  1497. }
  1498. }
  1499. while (qmax > q)
  1500. {
  1501. qmax--;
  1502. if (!CHAR_EQS(*qmax, space_char))
  1503. {
  1504. qmax++;
  1505. break;
  1506. }
  1507. }
  1508. last_buffered_match = buf = buffer; /* buffer is empty */
  1509. #ifdef HP_GLITCH_CODE
  1510. if (handle_hp_glitch)
  1511. {
  1512. while (p < pmax)
  1513. {
  1514. *buf++ = *p++;
  1515. }
  1516. }
  1517. #endif
  1518. #ifdef HP_GLITCH_CODE
  1519. if (Has_HP_Glitch == 0)
  1520. {
  1521. #endif
  1522. /* Try use use erase to bol if possible */
  1523. if ((Del_Bol_Str != NULL) && (CHAR_OF(*neww) == ' '))
  1524. {
  1525. SLsmg_Char_Type *p1;
  1526. SLsmg_Char_Type blank;
  1527. p1 = neww;
  1528. if ((Can_Background_Color_Erase)
  1529. && SLtt_Use_Ansi_Colors)
  1530. blank = *p1;
  1531. /* black+white attributes do not support bce */
  1532. else
  1533. blank = ' ';
  1534. while ((p1 < pmax) && (CHAR_EQS (*p1, blank)))
  1535. p1++;
  1536. /* Is this optimization worth it? Assume Del_Bol_Str is ESC [ 1 K
  1537. * It costs 4 chars + the space needed to properly position the
  1538. * cursor, e.g., ESC [ 10;10H. So, it costs at least 13 characters.
  1539. */
  1540. if ((p1 > neww + 13)
  1541. && (p1 >= p)
  1542. /* Avoid erasing from the end of the line */
  1543. && ((p1 != pmax) || (pmax < neww + len)))
  1544. {
  1545. int ofs = (int) (p1 - neww);
  1546. q = oldd + ofs;
  1547. p = p1;
  1548. SLtt_goto_rc (row, ofs - 1);
  1549. SLtt_reverse_video (COLOR_OF(blank));
  1550. tt_write_string (Del_Bol_Str);
  1551. tt_write (" ", 1);
  1552. Cursor_c += 1;
  1553. }
  1554. else
  1555. SLtt_goto_rc (row, (int) (p - neww));
  1556. }
  1557. else
  1558. SLtt_goto_rc (row, (int) (p - neww));
  1559. #ifdef HP_GLITCH_CODE
  1560. }
  1561. #endif
  1562. /* loop using overwrite then skip algorithm until done */
  1563. while (1)
  1564. {
  1565. /* while they do not match and we do not hit a space, buffer them up */
  1566. n_spaces = 0;
  1567. while (p < pmax)
  1568. {
  1569. if (CHAR_EQS(*q, ' ') && CHAR_EQS(*p, ' '))
  1570. {
  1571. /* If *q is not a space, we would have to overwrite it.
  1572. * However, if *q is a space, then while *p is also one,
  1573. * we only need to skip over the blank field.
  1574. */
  1575. space_match = p;
  1576. p++; q++;
  1577. while ((p < pmax)
  1578. && CHAR_EQS(*q, ' ')
  1579. && CHAR_EQS(*p, ' '))
  1580. {
  1581. p++;
  1582. q++;
  1583. }
  1584. n_spaces = (unsigned int) (p - space_match);
  1585. break;
  1586. }
  1587. #if SLANG_HAS_KANJI_SUPPORT
  1588. if ((*p & 0x80) && ((p + 1) < pmax))
  1589. { /* new is kanji */
  1590. if (*q & 0x80)
  1591. { /* old is also kanji */
  1592. if (((0xFF & *q) != (0xFF & *p))
  1593. || ((0xFF & q[1]) != (0xFF & p[1])))
  1594. {
  1595. /* both kanji, but not match */
  1596. *buf++ = *p++;
  1597. *buf++ = *p++;
  1598. q += 2;
  1599. continue;
  1600. }
  1601. else
  1602. { /* kanji match ? */
  1603. if (!COLOR_EQS(*q, *p) || !COLOR_EQS(*(q+1), *(p+1)))
  1604. {
  1605. /* code is match, but color is diff */
  1606. *buf++ = *p++;
  1607. *buf++ = *p++;
  1608. q += 2;
  1609. continue;
  1610. }
  1611. /* really match ! */
  1612. break;
  1613. }
  1614. }
  1615. else
  1616. { /* old is not kanji */
  1617. *buf++ = *p++;
  1618. *buf++ = *p++;
  1619. q += 2;
  1620. continue;
  1621. }
  1622. }
  1623. else
  1624. { /* new is not kanji */
  1625. if (*q & 0x80)
  1626. { /* old is kanji */
  1627. *buf++ = *p++;
  1628. q++;
  1629. continue;
  1630. }
  1631. }
  1632. #endif
  1633. if (CHAR_EQS(*q, *p)) break;
  1634. *buf++ = *p++;
  1635. q++;
  1636. }
  1637. *buf = 0;
  1638. /* At this point, the buffer contains characters that do not match */
  1639. if (buf != buffer) send_attr_str (buffer);
  1640. buf = buffer;
  1641. if (n_spaces
  1642. && ((p < pmax) /* erase to eol will achieve this effect*/
  1643. || (space_char != ' ')))/* unless space_char is not a simple space */
  1644. {
  1645. forward_cursor (n_spaces, row);
  1646. }
  1647. /* Now we overwrote what we could and cursor is placed at position
  1648. * of a possible match of new and old. If this is the case, skip
  1649. * some more.
  1650. */
  1651. /* Note that from here on, the buffer will contain matched characters */
  1652. #if !SLANG_HAS_KANJI_SUPPORT
  1653. while ((p < pmax) && CHAR_EQS(*p, *q))
  1654. {
  1655. *buf++ = *p++;
  1656. q++;
  1657. }
  1658. #else
  1659. /* Kanji */
  1660. while (p < pmax)
  1661. {
  1662. if ((*p & 0x80) && ((p + 1) < pmax))
  1663. { /* new is kanji */
  1664. if (*q & 0x80)
  1665. { /* old is also kanji */
  1666. if (((0xFF & *q) == (0xFF & *p))
  1667. && ((0xFF & q[1]) == (0xFF & p[1])))
  1668. {
  1669. /* kanji match ? */
  1670. if (!COLOR_EQS(*q, *p)
  1671. || !COLOR_EQS(q[1], p[1]))
  1672. break;
  1673. *buf++ = *p++;
  1674. q++;
  1675. if (p >= pmax)
  1676. {
  1677. *buf++ = 32;
  1678. p++;
  1679. break;
  1680. }
  1681. else
  1682. {
  1683. *buf++ = *p++;
  1684. q++;
  1685. continue;
  1686. }
  1687. }
  1688. else break; /* both kanji, but not match */
  1689. }
  1690. else break; /* old is not kanji */
  1691. }
  1692. else
  1693. { /* new is not kanji */
  1694. if (*q & 0x80) break; /* old is kanji */
  1695. if (!CHAR_EQS(*q, *p)) break;
  1696. *buf++ = *p++;
  1697. q++;
  1698. }
  1699. }
  1700. #endif
  1701. last_buffered_match = buf;
  1702. if (p >= pmax) break;
  1703. /* jump to new position is it is greater than 5 otherwise
  1704. * let it sit in the buffer and output it later.
  1705. */
  1706. if ((int) (buf - buffer) >= 5)
  1707. {
  1708. forward_cursor ((unsigned int) (buf - buffer), row);
  1709. last_buffered_match = buf = buffer;
  1710. }
  1711. }
  1712. /* At this point we have reached the end of the new string with the
  1713. * exception of space_chars hanging off the end of it, but we may not have
  1714. * reached the end of the old string if they did not match.
  1715. */
  1716. /* Here the buffer will consist only of characters that have matched */
  1717. if (buf != buffer)
  1718. {
  1719. if (q < qmax)
  1720. {
  1721. if ((buf == last_buffered_match)
  1722. && ((int) (buf - buffer) >= 5))
  1723. {
  1724. forward_cursor ((unsigned int) (buf - buffer), row);
  1725. }
  1726. else
  1727. {
  1728. *buf = 0;
  1729. send_attr_str (buffer);
  1730. }
  1731. }
  1732. }
  1733. if (q < qmax)
  1734. {
  1735. SLtt_reverse_video (COLOR_OF(space_char));
  1736. del_eol ();
  1737. }
  1738. #if SLTT_USE_INSERT_HACK
  1739. else if (insert_hack_char)
  1740. {
  1741. SLtt_goto_rc (SLtt_Screen_Rows-1, SLtt_Screen_Cols-2);
  1742. buffer[0] = insert_hack_char;
  1743. buffer[1] = 0;
  1744. send_attr_str (buffer);
  1745. SLtt_goto_rc (SLtt_Screen_Rows-1, SLtt_Screen_Cols-2);
  1746. buffer[0] = insert_hack_prev;
  1747. SLtt_begin_insert ();
  1748. send_attr_str (buffer);
  1749. SLtt_end_insert ();
  1750. }
  1751. #endif
  1752. if (Automatic_Margins && (Cursor_c + 1 >= SLtt_Screen_Cols)) Cursor_Set = 0;
  1753. }
  1754. static void get_color_info (void)
  1755. {
  1756. char *fg, *bg;
  1757. /* Allow easy mechanism to override inadequate termcap/terminfo files. */
  1758. if (SLtt_Use_Ansi_Colors == 0)
  1759. SLtt_Use_Ansi_Colors = (NULL != getenv ("COLORTERM"));
  1760. if (SLtt_Use_Ansi_Colors)
  1761. Is_Color_Terminal = 1;
  1762. #if SLTT_HAS_NON_BCE_SUPPORT
  1763. if (Can_Background_Color_Erase == 0)
  1764. Can_Background_Color_Erase = (NULL != getenv ("COLORTERM_BCE"));
  1765. #endif
  1766. if (-1 == get_default_colors (&fg, &bg))
  1767. return;
  1768. /* Check to see if application has already set them. */
  1769. if (Color_0_Modified)
  1770. return;
  1771. SLtt_set_color (0, NULL, fg, bg);
  1772. SLtt_set_color (1, NULL, bg, fg);
  1773. }
  1774. /* termcap stuff */
  1775. #ifdef __unix__
  1776. static int Termcap_Initalized = 0;
  1777. #ifdef USE_TERMCAP
  1778. /* Termcap based system */
  1779. static char Termcap_Buf[4096];
  1780. static char Termcap_String_Buf[4096];
  1781. static char *Termcap_String_Ptr;
  1782. extern char *tgetstr(char *, char **);
  1783. extern int tgetent(char *, char *);
  1784. extern int tgetnum(char *);
  1785. extern int tgetflag(char *);
  1786. #else
  1787. /* Terminfo */
  1788. static SLterminfo_Type *Terminfo;
  1789. #endif
  1790. #define TGETFLAG(x) (SLtt_tgetflag(x) > 0)
  1791. static char *fixup_tgetstr (char *what)
  1792. {
  1793. register char *w, *w1;
  1794. char *wsave;
  1795. if (what == NULL)
  1796. return NULL;
  1797. /* Check for AIX brain-damage */
  1798. if (*what == '@')
  1799. return NULL;
  1800. /* lose pad info --- with today's technology, term is a loser if
  1801. it is really needed */
  1802. while ((*what == '.') ||
  1803. ((*what >= '0') && (*what <= '9'))) what++;
  1804. if (*what == '*') what++;
  1805. /* lose terminfo padding--- looks like $<...> */
  1806. w = what;
  1807. while (*w) if ((*w++ == '$') && (*w == '<'))
  1808. {
  1809. w1 = w - 1;
  1810. while (*w && (*w != '>')) w++;
  1811. if (*w == 0) break;
  1812. w++;
  1813. wsave = w1;
  1814. while ((*w1++ = *w++) != 0);
  1815. w = wsave;
  1816. }
  1817. if (*what == 0) what = NULL;
  1818. return what;
  1819. }
  1820. char *SLtt_tgetstr (char *cap)
  1821. {
  1822. char *s;
  1823. if (Termcap_Initalized == 0)
  1824. return NULL;
  1825. #ifdef USE_TERMCAP
  1826. s = tgetstr (cap, &Termcap_String_Ptr);
  1827. #else
  1828. s = _SLtt_tigetstr (Terminfo, cap);
  1829. #endif
  1830. /* Do not strip pad info for alternate character set. I need to make
  1831. * this more general.
  1832. */
  1833. /* FIXME: Priority=low; */
  1834. if (0 == strcmp (cap, "ac"))
  1835. return s;
  1836. return fixup_tgetstr (s);
  1837. }
  1838. int SLtt_tgetnum (char *s)
  1839. {
  1840. if (Termcap_Initalized == 0)
  1841. return -1;
  1842. #ifdef USE_TERMCAP
  1843. return tgetnum (s);
  1844. #else
  1845. return _SLtt_tigetnum (Terminfo, s);
  1846. #endif
  1847. }
  1848. int SLtt_tgetflag (char *s)
  1849. {
  1850. if (Termcap_Initalized == 0)
  1851. return -1;
  1852. #ifdef USE_TERMCAP
  1853. return tgetflag (s);
  1854. #else
  1855. return _SLtt_tigetflag (Terminfo, s);
  1856. #endif
  1857. }
  1858. static int Vt100_Like = 0;
  1859. void SLtt_get_terminfo (void)
  1860. {
  1861. char *term;
  1862. int status;
  1863. term = getenv ("TERM");
  1864. if (term == NULL)
  1865. SLang_exit_error("TERM environment variable needs set.");
  1866. if (0 == (status = SLtt_initialize (term)))
  1867. return;
  1868. if (status == -1)
  1869. {
  1870. SLang_exit_error ("Unknown terminal: %s\n\
  1871. Check the TERM environment variable.\n\
  1872. Also make sure that the terminal is defined in the terminfo database.\n\
  1873. Alternatively, set the TERMCAP environment variable to the desired\n\
  1874. termcap entry.",
  1875. term);
  1876. }
  1877. if (status == -2)
  1878. {
  1879. SLang_exit_error ("\
  1880. Your terminal lacks the ability to clear the screen or position the cursor.\n");
  1881. }
  1882. }
  1883. /* Returns 0 if all goes well, -1 if terminal capabilities cannot be deduced,
  1884. * or -2 if terminal cannot position the cursor.
  1885. */
  1886. int SLtt_initialize (char *term)
  1887. {
  1888. char *t, ch;
  1889. int is_xterm;
  1890. int almost_vtxxx;
  1891. if (SLang_TT_Write_FD == -1)
  1892. {
  1893. /* Apparantly, this cannot fail according to the man pages. */
  1894. SLang_TT_Write_FD = fileno (stdout);
  1895. }
  1896. if (term == NULL)
  1897. {
  1898. term = getenv ("TERM");
  1899. if (term == NULL)
  1900. return -1;
  1901. }
  1902. #if 0
  1903. if (_SLsecure_issetugid ()
  1904. && ((term[0] == '.') || (NULL != strchr(term, '/'))))
  1905. return -1;
  1906. #endif
  1907. Linux_Console = (!strncmp (term, "linux", 5)
  1908. # ifdef linux
  1909. || !strncmp(term, "con", 3)
  1910. # endif
  1911. );
  1912. QANSI_Console = !strncmp (term, "qansi-m", 7);
  1913. t = term;
  1914. if (strcmp(t, "vt52") && (*t++ == 'v') && (*t++ == 't')
  1915. && (ch = *t, (ch >= '1') && (ch <= '9'))) Vt100_Like = 1;
  1916. is_xterm = ((0 == strncmp (term, "xterm", 5))
  1917. || (0 == strncmp (term, "rxvt", 4))
  1918. || (0 == strncmp (term, "Eterm", 5)));
  1919. almost_vtxxx = (Vt100_Like
  1920. || Linux_Console
  1921. || is_xterm
  1922. || !strcmp (term, "screen"));
  1923. # ifndef USE_TERMCAP
  1924. if (NULL == (Terminfo = _SLtt_tigetent (term)))
  1925. {
  1926. if (almost_vtxxx) /* Special cases. */
  1927. {
  1928. int vt102 = 1;
  1929. if (!strcmp (term, "vt100")) vt102 = 0;
  1930. get_color_info ();
  1931. SLtt_set_term_vtxxx (&vt102);
  1932. (void) SLtt_get_screen_size ();
  1933. return 0;
  1934. }
  1935. return -1;
  1936. }
  1937. # else /* USE_TERMCAP */
  1938. if (1 != tgetent(Termcap_Buf, term))
  1939. return -1;
  1940. Termcap_String_Ptr = Termcap_String_Buf;
  1941. # endif /* NOT USE_TERMCAP */
  1942. Termcap_Initalized = 1;
  1943. Cls_Str = SLtt_tgetstr ("cl");
  1944. Curs_Pos_Str = SLtt_tgetstr ("cm");
  1945. if ((NULL == (Ins_Mode_Str = SLtt_tgetstr("im")))
  1946. || ( NULL == (Eins_Mode_Str = SLtt_tgetstr("ei")))
  1947. || ( NULL == (Del_Char_Str = SLtt_tgetstr("dc"))))
  1948. SLtt_Term_Cannot_Insert = 1;
  1949. Visible_Bell_Str = SLtt_tgetstr ("vb");
  1950. Curs_Up_Str = SLtt_tgetstr ("up");
  1951. Rev_Scroll_Str = SLtt_tgetstr("sr");
  1952. Del_N_Lines_Str = SLtt_tgetstr("DL");
  1953. Add_N_Lines_Str = SLtt_tgetstr("AL");
  1954. /* Actually these are used to initialize terminals that use cursor
  1955. * addressing. Hard to believe.
  1956. */
  1957. Term_Init_Str = SLtt_tgetstr ("ti");
  1958. Term_Reset_Str = SLtt_tgetstr ("te");
  1959. /* If I do this for vtxxx terminals, arrow keys start sending ESC O A,
  1960. * which I do not want. This is mainly for HP terminals.
  1961. */
  1962. if ((almost_vtxxx == 0) || SLtt_Force_Keypad_Init)
  1963. {
  1964. Keypad_Init_Str = SLtt_tgetstr ("ks");
  1965. Keypad_Reset_Str = SLtt_tgetstr ("ke");
  1966. }
  1967. /* Make up for defective termcap/terminfo databases */
  1968. if ((Vt100_Like && (term[2] != '1'))
  1969. || Linux_Console
  1970. || is_xterm
  1971. )
  1972. {
  1973. if (Del_N_Lines_Str == NULL) Del_N_Lines_Str = "\033[%dM";
  1974. if (Add_N_Lines_Str == NULL) Add_N_Lines_Str = "\033[%dL";
  1975. }
  1976. Scroll_R_Str = SLtt_tgetstr("cs");
  1977. SLtt_get_screen_size ();
  1978. if ((Scroll_R_Str == NULL)
  1979. || (((NULL == Del_N_Lines_Str) || (NULL == Add_N_Lines_Str))
  1980. && (NULL == Rev_Scroll_Str)))
  1981. {
  1982. if (is_xterm
  1983. || Linux_Console
  1984. )
  1985. {
  1986. /* Defective termcap mode!!!! */
  1987. SLtt_set_term_vtxxx (NULL);
  1988. }
  1989. else SLtt_Term_Cannot_Scroll = 1;
  1990. }
  1991. Del_Eol_Str = SLtt_tgetstr("ce");
  1992. Del_Bol_Str = SLtt_tgetstr("cb");
  1993. if (is_xterm && (Del_Bol_Str == NULL))
  1994. Del_Bol_Str = "\033[1K";
  1995. if (is_xterm && (Del_Eol_Str == NULL))
  1996. Del_Eol_Str = "\033[K";
  1997. Rev_Vid_Str = SLtt_tgetstr("mr");
  1998. if (Rev_Vid_Str == NULL) Rev_Vid_Str = SLtt_tgetstr("so");
  1999. Bold_Vid_Str = SLtt_tgetstr("md");
  2000. /* Although xterm cannot blink, it does display the blinking characters
  2001. * as bold ones. Some Rxvt will display the background as high intensity.
  2002. */
  2003. if ((NULL == (Blink_Vid_Str = SLtt_tgetstr("mb")))
  2004. && is_xterm)
  2005. Blink_Vid_Str = "\033[5m";
  2006. UnderLine_Vid_Str = SLtt_tgetstr("us");
  2007. Start_Alt_Chars_Str = SLtt_tgetstr ("as"); /* smacs */
  2008. End_Alt_Chars_Str = SLtt_tgetstr ("ae"); /* rmacs */
  2009. Enable_Alt_Char_Set = SLtt_tgetstr ("eA"); /* enacs */
  2010. SLtt_Graphics_Char_Pairs = SLtt_tgetstr ("ac");
  2011. if (NULL == SLtt_Graphics_Char_Pairs)
  2012. {
  2013. /* make up for defective termcap/terminfo */
  2014. if (Vt100_Like)
  2015. {
  2016. Start_Alt_Chars_Str = "\016";
  2017. End_Alt_Chars_Str = "\017";
  2018. Enable_Alt_Char_Set = "\033)0";
  2019. }
  2020. }
  2021. /* aixterm added by willi */
  2022. if (is_xterm || !strncmp (term, "aixterm", 7))
  2023. {
  2024. Start_Alt_Chars_Str = "\016";
  2025. End_Alt_Chars_Str = "\017";
  2026. Enable_Alt_Char_Set = "\033(B\033)0";
  2027. }
  2028. if ((SLtt_Graphics_Char_Pairs == NULL) &&
  2029. ((Start_Alt_Chars_Str == NULL) || (End_Alt_Chars_Str == NULL)))
  2030. {
  2031. SLtt_Has_Alt_Charset = 0;
  2032. Enable_Alt_Char_Set = NULL;
  2033. }
  2034. else SLtt_Has_Alt_Charset = 1;
  2035. #ifdef AMIGA
  2036. Enable_Alt_Char_Set = Start_Alt_Chars_Str = End_Alt_Chars_Str = NULL;
  2037. #endif
  2038. /* status line capabilities */
  2039. if ((SLtt_Has_Status_Line == -1)
  2040. && (0 != (SLtt_Has_Status_Line = TGETFLAG ("hs"))))
  2041. {
  2042. Disable_Status_line_Str = SLtt_tgetstr ("ds");
  2043. Return_From_Status_Line_Str = SLtt_tgetstr ("fs");
  2044. Goto_Status_Line_Str = SLtt_tgetstr ("ts");
  2045. /* Status_Line_Esc_Ok = TGETFLAG("es"); */
  2046. Num_Status_Line_Columns = SLtt_tgetnum ("ws");
  2047. if (Num_Status_Line_Columns < 0) Num_Status_Line_Columns = 0;
  2048. }
  2049. if (NULL == (Norm_Vid_Str = SLtt_tgetstr("me")))
  2050. {
  2051. Norm_Vid_Str = SLtt_tgetstr("se");
  2052. }
  2053. Cursor_Invisible_Str = SLtt_tgetstr("vi");
  2054. Cursor_Visible_Str = SLtt_tgetstr("ve");
  2055. Curs_F_Str = SLtt_tgetstr("RI");
  2056. # if 0
  2057. if (NULL != Curs_F_Str)
  2058. {
  2059. Len_Curs_F_Str = strlen(Curs_F_Str);
  2060. }
  2061. else Len_Curs_F_Str = strlen(Curs_Pos_Str);
  2062. # endif
  2063. Automatic_Margins = TGETFLAG ("am");
  2064. /* No_Move_In_Standout = !TGETFLAG ("ms"); */
  2065. # ifdef HP_GLITCH_CODE
  2066. Has_HP_Glitch = TGETFLAG ("xs");
  2067. # else
  2068. Worthless_Highlight = TGETFLAG ("xs");
  2069. # endif
  2070. if (Worthless_Highlight == 0)
  2071. { /* Magic cookie glitch */
  2072. Worthless_Highlight = (SLtt_tgetnum ("sg") > 0);
  2073. }
  2074. if (Worthless_Highlight)
  2075. SLtt_Has_Alt_Charset = 0;
  2076. Reset_Color_String = SLtt_tgetstr ("op");
  2077. /* Apparantly the difference between "AF" and "Sf" is that AF uses RGB,
  2078. * but Sf uses BGR.
  2079. */
  2080. Color_Fg_Str = SLtt_tgetstr ("AF"); /* ANSI setaf */
  2081. if (Color_Fg_Str == NULL)
  2082. {
  2083. Color_Fg_Str = SLtt_tgetstr ("Sf"); /* setf */
  2084. Is_Fg_BGR = (Color_Fg_Str != NULL);
  2085. }
  2086. Color_Bg_Str = SLtt_tgetstr ("AB"); /* ANSI setbf */
  2087. if (Color_Bg_Str == NULL)
  2088. {
  2089. Color_Bg_Str = SLtt_tgetstr ("Sb"); /* setb */
  2090. Is_Bg_BGR = (Color_Bg_Str != NULL);
  2091. }
  2092. if ((Max_Terminfo_Colors = SLtt_tgetnum ("Co")) < 0)
  2093. Max_Terminfo_Colors = 8;
  2094. if ((Color_Bg_Str != NULL) && (Color_Fg_Str != NULL))
  2095. SLtt_Use_Ansi_Colors = 1;
  2096. else
  2097. {
  2098. #if 0
  2099. Color_Fg_Str = "%?%p1%{7}%>%t\033[1;3%p1%{8}%m%dm%e\033[3%p1%dm%;";
  2100. Color_Bg_Str = "%?%p1%{7}%>%t\033[5;4%p1%{8}%m%dm%e\033[4%p1%dm%;";
  2101. Max_Terminfo_Colors = 16;
  2102. #else
  2103. Color_Fg_Str = "\033[3%dm";
  2104. Color_Bg_Str = "\033[4%dm";
  2105. Max_Terminfo_Colors = 8;
  2106. #endif
  2107. }
  2108. #if SLTT_HAS_NON_BCE_SUPPORT
  2109. Can_Background_Color_Erase = TGETFLAG ("ut"); /* bce */
  2110. /* Modern xterms have the BCE capability as well as the linux console */
  2111. if (Can_Background_Color_Erase == 0)
  2112. {
  2113. Can_Background_Color_Erase = (Linux_Console
  2114. # if SLTT_XTERM_ALWAYS_BCE
  2115. || is_xterm
  2116. # endif
  2117. );
  2118. }
  2119. #endif
  2120. get_color_info ();
  2121. if ((Cls_Str == NULL)
  2122. || (Curs_Pos_Str == NULL))
  2123. return -2;
  2124. return 0;
  2125. }
  2126. #endif
  2127. /* Unix */
  2128. /* specific to vtxxx only */
  2129. void SLtt_enable_cursor_keys (void)
  2130. {
  2131. #ifdef __unix__
  2132. if (Vt100_Like)
  2133. #endif
  2134. tt_write_string("\033=\033[?1l");
  2135. }
  2136. #ifdef VMS
  2137. int SLtt_initialize (char *term)
  2138. {
  2139. SLtt_get_terminfo ();
  2140. return 0;
  2141. }
  2142. void SLtt_get_terminfo ()
  2143. {
  2144. int zero = 0;
  2145. /* Apparantly, this cannot fail according to the man pages. */
  2146. if (SLang_TT_Write_FD == -1)
  2147. SLang_TT_Write_FD = fileno (stdout);
  2148. Can_Background_Color_Erase = 0;
  2149. Color_Fg_Str = "\033[3%dm";
  2150. Color_Bg_Str = "\033[4%dm";
  2151. Max_Terminfo_Colors = 8;
  2152. get_color_info ();
  2153. SLtt_set_term_vtxxx(&zero);
  2154. Start_Alt_Chars_Str = "\016";
  2155. End_Alt_Chars_Str = "\017";
  2156. SLtt_Has_Alt_Charset = 1;
  2157. SLtt_Graphics_Char_Pairs = "aaffgghhjjkkllmmnnooqqssttuuvvwwxx";
  2158. Enable_Alt_Char_Set = "\033(B\033)0";
  2159. SLtt_get_screen_size ();
  2160. }
  2161. #endif
  2162. /* This sets term for vt102 terminals it parameter vt100 is 0. If vt100
  2163. * is non-zero, set terminal appropriate for a only vt100
  2164. * (no add line capability). */
  2165. void SLtt_set_term_vtxxx(int *vt100)
  2166. {
  2167. Norm_Vid_Str = "\033[m";
  2168. Scroll_R_Str = "\033[%i%d;%dr";
  2169. Cls_Str = "\033[2J\033[H";
  2170. Rev_Vid_Str = "\033[7m";
  2171. Bold_Vid_Str = "\033[1m";
  2172. Blink_Vid_Str = "\033[5m";
  2173. UnderLine_Vid_Str = "\033[4m";
  2174. Del_Eol_Str = "\033[K";
  2175. Del_Bol_Str = "\033[1K";
  2176. Rev_Scroll_Str = "\033M";
  2177. Curs_F_Str = "\033[%dC";
  2178. /* Len_Curs_F_Str = 5; */
  2179. Curs_Pos_Str = "\033[%i%d;%dH";
  2180. if ((vt100 == NULL) || (*vt100 == 0))
  2181. {
  2182. Ins_Mode_Str = "\033[4h";
  2183. Eins_Mode_Str = "\033[4l";
  2184. Del_Char_Str = "\033[P";
  2185. Del_N_Lines_Str = "\033[%dM";
  2186. Add_N_Lines_Str = "\033[%dL";
  2187. SLtt_Term_Cannot_Insert = 0;
  2188. }
  2189. else
  2190. {
  2191. Del_N_Lines_Str = NULL;
  2192. Add_N_Lines_Str = NULL;
  2193. SLtt_Term_Cannot_Insert = 1;
  2194. }
  2195. SLtt_Term_Cannot_Scroll = 0;
  2196. /* No_Move_In_Standout = 0; */
  2197. }
  2198. int SLtt_init_video (void)
  2199. {
  2200. /* send_string_to_term("\033[?6h"); */
  2201. /* relative origin mode */
  2202. tt_write_string (Term_Init_Str);
  2203. tt_write_string (Keypad_Init_Str);
  2204. SLtt_reset_scroll_region();
  2205. SLtt_end_insert();
  2206. tt_write_string (Enable_Alt_Char_Set);
  2207. Video_Initialized = 1;
  2208. return 0;
  2209. }
  2210. int SLtt_reset_video (void)
  2211. {
  2212. SLtt_goto_rc (SLtt_Screen_Rows - 1, 0);
  2213. Cursor_Set = 0;
  2214. SLtt_normal_video (); /* MSKermit requires this */
  2215. tt_write_string(Norm_Vid_Str);
  2216. Current_Fgbg = 0xFFFFFFFFU;
  2217. SLtt_set_alt_char_set (0);
  2218. if (SLtt_Use_Ansi_Colors)
  2219. {
  2220. if (Reset_Color_String == NULL)
  2221. {
  2222. SLtt_Char_Type attr;
  2223. if (-1 != make_color_fgbg (NULL, NULL, &attr))
  2224. write_attributes (attr);
  2225. else tt_write_string ("\033[0m\033[m");
  2226. }
  2227. else tt_write_string (Reset_Color_String);
  2228. Current_Fgbg = 0xFFFFFFFFU;
  2229. }
  2230. SLtt_erase_line ();
  2231. tt_write_string (Keypad_Reset_Str);
  2232. tt_write_string (Term_Reset_Str);
  2233. SLtt_flush_output ();
  2234. Video_Initialized = 0;
  2235. return 0;
  2236. }
  2237. void SLtt_bold_video (void)
  2238. {
  2239. tt_write_string (Bold_Vid_Str);
  2240. }
  2241. int SLtt_set_mouse_mode (int mode, int force)
  2242. {
  2243. char *term;
  2244. if (force == 0)
  2245. {
  2246. if (NULL == (term = (char *) getenv("TERM"))) return -1;
  2247. if (strncmp ("xterm", term, 5))
  2248. return -1;
  2249. }
  2250. if (mode)
  2251. tt_write_string ("\033[?9h");
  2252. else
  2253. tt_write_string ("\033[?9l");
  2254. return 0;
  2255. }
  2256. void SLtt_disable_status_line (void)
  2257. {
  2258. if (SLtt_Has_Status_Line > 0)
  2259. {
  2260. tt_write_string (Disable_Status_line_Str);
  2261. SLtt_flush_output ();
  2262. }
  2263. }
  2264. int SLtt_write_to_status_line (char *s, int col)
  2265. {
  2266. if ((SLtt_Has_Status_Line <= 0)
  2267. || (Goto_Status_Line_Str == NULL)
  2268. || (Return_From_Status_Line_Str == NULL))
  2269. return -1;
  2270. tt_printf (Goto_Status_Line_Str, col, 0);
  2271. tt_write_string (s);
  2272. tt_write_string (Return_From_Status_Line_Str);
  2273. return 0;
  2274. }
  2275. void SLtt_get_screen_size (void)
  2276. {
  2277. #ifdef VMS
  2278. int status, code;
  2279. unsigned short chan;
  2280. $DESCRIPTOR(dev_dsc, "SYS$INPUT:");
  2281. #endif
  2282. int r = 0, c = 0;
  2283. #ifdef TIOCGWINSZ
  2284. struct winsize wind_struct;
  2285. do
  2286. {
  2287. if ((ioctl(1,TIOCGWINSZ,&wind_struct) == 0)
  2288. || (ioctl(0, TIOCGWINSZ, &wind_struct) == 0)
  2289. || (ioctl(2, TIOCGWINSZ, &wind_struct) == 0))
  2290. {
  2291. c = (int) wind_struct.ws_col;
  2292. r = (int) wind_struct.ws_row;
  2293. break;
  2294. }
  2295. }
  2296. while (errno == EINTR);
  2297. #endif
  2298. #ifdef VMS
  2299. status = sys$assign(&dev_dsc,&chan,0,0,0);
  2300. if (status & 1)
  2301. {
  2302. code = DVI$_DEVBUFSIZ;
  2303. status = lib$getdvi(&code, &chan,0, &c, 0,0);
  2304. if (!(status & 1))
  2305. c = 80;
  2306. code = DVI$_TT_PAGE;
  2307. status = lib$getdvi(&code, &chan,0, &r, 0,0);
  2308. if (!(status & 1))
  2309. r = 24;
  2310. sys$dassgn(chan);
  2311. }
  2312. #endif
  2313. if (r <= 0)
  2314. {
  2315. char *s = getenv ("LINES");
  2316. if (s != NULL) r = atoi (s);
  2317. }
  2318. if (c <= 0)
  2319. {
  2320. char *s = getenv ("COLUMNS");
  2321. if (s != NULL) c = atoi (s);
  2322. }
  2323. if ((r <= 0) || (r > SLTT_MAX_SCREEN_ROWS)) r = 24;
  2324. if ((c <= 0) || (c > SLTT_MAX_SCREEN_COLS)) c = 80;
  2325. SLtt_Screen_Rows = r;
  2326. SLtt_Screen_Cols = c;
  2327. }
  2328. #if SLTT_HAS_NON_BCE_SUPPORT
  2329. int _SLtt_get_bce_color_offset (void)
  2330. {
  2331. if ((SLtt_Use_Ansi_Colors == 0)
  2332. || Can_Background_Color_Erase
  2333. || SLtt_Use_Blink_For_ACS) /* in this case, we cannot lose a color */
  2334. Bce_Color_Offset = 0;
  2335. else
  2336. {
  2337. if (GET_BG(Ansi_Color_Map[0].fgbg) == SLSMG_COLOR_DEFAULT)
  2338. Bce_Color_Offset = 0;
  2339. else
  2340. Bce_Color_Offset = 1;
  2341. }
  2342. return Bce_Color_Offset;
  2343. }
  2344. #endif