sldisply.c 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239
  1. /* Copyright (c) 1992, 1995 John E. Davis
  2. * All rights reserved.
  3. *
  4. * You may distribute under the terms of either the GNU General Public
  5. * License or the Perl Artistic License.
  6. */
  7. /*
  8. * SLTT_TRANSP_ACS_PATCH (#define/#undef):
  9. *
  10. * The problem: some terminals (e.g. QNX/qansi*) map the whole upper half of
  11. * the ASCII table to the lower half, when alt-char-set is activated with
  12. * the smacs/as string-sequence. This means, that if 0 <= ch < 128 written
  13. * to the terminal, it will be translated to (ch+128) automatically by the
  14. * terminal: so not only the line-drawing characters can be written, when
  15. * the alt-char-set is activated. It implicitly means, that space, NL, CR,
  16. * etc. characters (exactly: anything besides the "standard" line drawing
  17. * characters) can not be written directly to the terminal, when the
  18. * alt-char-set is activated, because writing these characters doesn't cause
  19. * an implicit/temporary switching-back to the standard char-set!
  20. *
  21. * The original code in SLang assumes that space, NL, CR, etc. can be
  22. * printed when alt-char-set is activated. If SLTT_TRANSP_ACS_PATCH is
  23. * defined, the modified code will not use this assumption.
  24. * [Remark: the patch-code is not the most exact solution, but works...]
  25. */
  26. /*#define SLTT_TRANSP_ACS_PATCH 1*/
  27. /*
  28. * QNX_QANSI_SLANG_COMPAT_ACS (#define/#undef):
  29. *
  30. * A more OS/terminal-specific solution for the problem mentioned above
  31. * (->SLTT_TRANSP_ACS_PATCH).
  32. *
  33. * If QNX_QANSI_SLANG_COMPAT_ACS is defined, the default smacs/sa, rmacs/ae,
  34. * acsc/ac [and sgr/sa, if it would be used!] command sequences will be
  35. * replaced internally with the "old style" (pre-QNX 4.23) sequences in case
  36. * of QNX/qansi terminals. Using these optional command sequences the terminal
  37. * remains compatible with the original SLang code (without using the
  38. * workaround-code enabled by defining SLTT_TRANSP_ACS_PATCH).
  39. */
  40. /*#define QNX_QANSI_SLANG_COMPAT_ACS 1*/
  41. /* auto-configuration */
  42. #ifdef SLTT_TRANSP_ACS_PATCH
  43. # if defined(__QNX__) && defined(QNX_QANSI_SLANG_COMPAT_ACS)
  44. # undef SLTT_TRANSP_ACS_PATCH
  45. # endif
  46. #else
  47. # if defined(__QNX__) && !defined(QNX_QANSI_SLANG_COMPAT_ACS)
  48. # define QNX_QANSI_SLANG_COMPAT_ACS 1
  49. # endif
  50. #endif
  51. #include "sl-feat.h"
  52. #include "config.h"
  53. #include <stdio.h>
  54. #include <string.h>
  55. #ifdef SCO_FLAVOR
  56. # include <sys/types.h>
  57. # include <sys/timeb.h> /* for struct timeb, used in time.h */
  58. #endif
  59. #include <time.h>
  60. #include <ctype.h>
  61. #ifndef VMS
  62. # include <sys/time.h>
  63. # ifdef __QNX__
  64. # include <sys/select.h>
  65. # endif
  66. # include <sys/types.h>
  67. #endif
  68. #ifdef __BEOS__
  69. /* Prototype for select */
  70. # include <net/socket.h>
  71. #endif
  72. #ifdef HAVE_TERMIOS_H
  73. # include <termios.h>
  74. #endif
  75. #ifdef VMS
  76. # include <unixlib.h>
  77. # include <unixio.h>
  78. # include <dvidef.h>
  79. # include <descrip.h>
  80. # include <lib$routines.h>
  81. # include <starlet.h>
  82. #else
  83. # if !defined(sun)
  84. # include <sys/ioctl.h>
  85. # endif
  86. #endif
  87. #ifdef SYSV
  88. # include <sys/termio.h>
  89. # include <sys/stream.h>
  90. # include <sys/ptem.h>
  91. # include <sys/tty.h>
  92. #endif
  93. #if defined (_AIX) && !defined (FD_SET)
  94. # include <sys/select.h> /* for FD_ISSET, FD_SET, FD_ZERO */
  95. #endif
  96. #include <errno.h>
  97. #include "_slang.h"
  98. #ifdef HAVE_STDLIB_H
  99. # include <stdlib.h>
  100. #endif
  101. #ifdef HAVE_UNISTD_H
  102. # include <unistd.h>
  103. #endif
  104. #if defined(__DECC) && defined(VMS)
  105. /* These get prototypes for write an sleep */
  106. # include <unixio.h>
  107. #endif
  108. #include <signal.h>
  109. /* Colors: These definitions are used for the display. However, the
  110. * application only uses object handles which get mapped to this
  111. * internal representation. The mapping is performed by the Color_Map
  112. * structure below. */
  113. #define CHAR_MASK 0x000000FF
  114. #define FG_MASK 0x0000FF00
  115. #define BG_MASK 0x00FF0000
  116. #define ATTR_MASK 0x1F000000
  117. #define BGALL_MASK 0x0FFF0000
  118. /* The 0x10000000 bit represents the alternate character set. BGALL_MASK does
  119. * not include this attribute.
  120. */
  121. #define GET_FG(color) ((color & FG_MASK) >> 8)
  122. #define GET_BG(color) ((color & BG_MASK) >> 16)
  123. #define MAKE_COLOR(fg, bg) (((fg) | ((bg) << 8)) << 8)
  124. int SLtt_Screen_Cols;
  125. int SLtt_Screen_Rows;
  126. int SLtt_Term_Cannot_Insert;
  127. int SLtt_Term_Cannot_Scroll;
  128. int SLtt_Use_Ansi_Colors;
  129. int SLtt_Blink_Mode = 1;
  130. int SLtt_Use_Blink_For_ACS = 0;
  131. int SLtt_Newline_Ok = 0;
  132. int SLtt_Has_Alt_Charset = 0;
  133. int SLtt_Force_Keypad_Init = 0;
  134. /* -1 means unknown */
  135. int SLtt_Has_Status_Line = -1; /* hs */
  136. static int Automatic_Margins;
  137. /* static int No_Move_In_Standout; */
  138. static int Worthless_Highlight;
  139. #define HP_GLITCH_CODE
  140. #ifdef HP_GLITCH_CODE
  141. /* This glitch is exclusive to HP term. Basically it means that to clear
  142. * attributes, one has to erase to the end of the line.
  143. */
  144. static int Has_HP_Glitch;
  145. #endif
  146. static char *Reset_Color_String;
  147. static int Linux_Console;
  148. /* It is crucial that JMAX_COLORS must be less than 128 since the high bit
  149. * is used to indicate a character from the ACS (alt char set). The exception
  150. * to this rule is if SLtt_Use_Blink_For_ACS is true. This means that of
  151. * the highbit is set, we interpret that as a blink character. This is
  152. * exploited by DOSemu.
  153. */
  154. #define JMAX_COLORS 256
  155. #define JNORMAL_COLOR 0
  156. typedef struct
  157. {
  158. SLtt_Char_Type fgbg;
  159. SLtt_Char_Type mono;
  160. char *custom_esc;
  161. } Ansi_Color_Type;
  162. #define RGB1(r, g, b) ((r) | ((g) << 1) | ((b) << 2))
  163. #define RGB(r, g, b, br, bg, bb) ((RGB1(r, g, b) << 8) | (RGB1(br, bg, bb) << 16))
  164. static Ansi_Color_Type Ansi_Color_Map[JMAX_COLORS] =
  165. {
  166. {RGB(1, 1, 1, 0, 0, 0), 0x00000000, NULL}, /* white/black */
  167. {RGB(0, 1, 0, 0, 0, 0), SLTT_REV_MASK, NULL}, /* green/black */
  168. {RGB(1, 0, 1, 0, 0, 0), SLTT_REV_MASK, NULL}, /* magenta/black */
  169. {RGB(0, 1, 1, 0, 0, 0), SLTT_REV_MASK, NULL}, /* cyan/black */
  170. {RGB(1, 0, 0, 0, 0, 0), SLTT_REV_MASK, NULL},
  171. {RGB(0, 1, 0, 0, 0, 1), SLTT_REV_MASK, NULL},
  172. {RGB(1, 0, 0, 0, 0, 1), SLTT_REV_MASK, NULL},
  173. {RGB(1, 0, 0, 0, 1, 0), SLTT_REV_MASK, NULL},
  174. {RGB(0, 0, 1, 1, 0, 0), SLTT_REV_MASK, NULL},
  175. {RGB(0, 1, 0, 1, 0, 0), SLTT_REV_MASK, NULL},
  176. {RGB(0, 1, 1, 1, 1, 1), SLTT_REV_MASK, NULL},
  177. {RGB(1, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
  178. {RGB(1, 0, 1, 1, 1, 1), SLTT_REV_MASK, NULL},
  179. {RGB(0, 0, 0, 0, 1, 1), SLTT_REV_MASK, NULL},
  180. {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
  181. {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
  182. {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL},
  183. {RGB(0, 1, 0, 1, 1, 1), SLTT_REV_MASK, NULL}
  184. };
  185. /* This is the string to use to use when outputting color information.
  186. */
  187. #ifdef M_UNIX
  188. /* work around for sco console bug that can't handle combined sequences */
  189. static char *Color_Escape_Sequence = "\033[3%dm\033[4%dm";
  190. #else
  191. /* Believe it or not, this is what is in the linux terminfo database. It
  192. * produces the same escape sequence but it is much more CPU intensive.
  193. * Why not just encode it as "\033[3%p1%dm\033[4%p2%dm" ???
  194. */
  195. /* static char *Color_Escape_Sequence = "\033[%p1%{30}%+%dm\033[%p2%{40}%+%dm"; */
  196. static char *Color_Escape_Sequence = "\033[3%d;4%dm";
  197. #endif
  198. char *SLtt_Graphics_Char_Pairs; /* ac termcap string -- def is vt100 */
  199. /* 1 if terminal lacks the ability to do into insert mode or into delete
  200. mode. Currently controlled by S-Lang but later perhaps termcap. */
  201. static char *UnderLine_Vid_Str;
  202. static char *Blink_Vid_Str;
  203. static char *Bold_Vid_Str;
  204. static char *Ins_Mode_Str; /* = "\033[4h"; */ /* ins mode (im) */
  205. static char *Eins_Mode_Str; /* = "\033[4l"; */ /* end ins mode (ei) */
  206. static char *Scroll_R_Str; /* = "\033[%d;%dr"; */ /* scroll region */
  207. static char *Cls_Str; /* = "\033[2J\033[H"; */ /* cl termcap STR for ansi terminals */
  208. static char *Rev_Vid_Str; /* = "\033[7m"; */ /* mr,so termcap string */
  209. static char *Norm_Vid_Str; /* = "\033[m"; */ /* me,se termcap string */
  210. static char *Del_Eol_Str; /* = "\033[K"; */ /* ce */
  211. static char *Del_Char_Str; /* = "\033[P"; */ /* dc */
  212. static char *Del_N_Lines_Str; /* = "\033[%dM"; */ /* DL */
  213. static char *Add_N_Lines_Str; /* = "\033[%dL"; */ /* AL */
  214. static char *Rev_Scroll_Str;
  215. static char *Curs_Up_Str;
  216. static char *Curs_F_Str; /* RI termcap string */
  217. static char *Cursor_Visible_Str; /* ve termcap string */
  218. static char *Cursor_Invisible_Str; /* vi termcap string */
  219. static char *Start_Alt_Chars_Str; /* as */
  220. static char *End_Alt_Chars_Str; /* ae */
  221. static char *Enable_Alt_Char_Set; /* eA */
  222. static char *Term_Init_Str;
  223. static char *Keypad_Init_Str;
  224. static char *Term_Reset_Str;
  225. static char *Keypad_Reset_Str;
  226. /* status line functions */
  227. static char *Disable_Status_line_Str; /* ds */
  228. static char *Return_From_Status_Line_Str; /* fs */
  229. static char *Goto_Status_Line_Str; /* ts */
  230. static int Num_Status_Line_Columns; /* ws */
  231. static int Status_Line_Esc_Ok; /* es */
  232. /* static int Len_Curs_F_Str = 5; */
  233. /* cm string has %i%d since termcap numbers columns from 0 */
  234. /* char *CURS_POS_STR = "\033[%d;%df"; ansi-- hor and vert pos */
  235. static char *Curs_Pos_Str; /* = "\033[%i%d;%dH";*/ /* cm termcap string */
  236. /* scrolling region */
  237. static int Scroll_r1 = 0, Scroll_r2 = 23;
  238. static int Cursor_r, Cursor_c; /* 0 based */
  239. /* current attributes --- initialized to impossible value */
  240. static SLtt_Char_Type Current_Fgbg = 0xFFFFFFFFU;
  241. static int Cursor_Set; /* 1 if cursor position known, 0
  242. * if not. -1 if only row is known
  243. */
  244. #define MAX_OUTPUT_BUFFER_SIZE 4096
  245. static unsigned char Output_Buffer[MAX_OUTPUT_BUFFER_SIZE];
  246. static unsigned char *Output_Bufferp = Output_Buffer;
  247. unsigned long SLtt_Num_Chars_Output;
  248. #ifdef SLTT_TRANSP_ACS_PATCH
  249. static int SLtt_ACS_Active = 0;
  250. #endif
  251. static int sl_usleep (unsigned long usecs)
  252. {
  253. #ifndef VMS
  254. struct timeval tv;
  255. tv.tv_sec = usecs / 1000000;
  256. tv.tv_usec = usecs % 1000000;
  257. return select(0, NULL, NULL, NULL, &tv);
  258. #else
  259. return 0;
  260. #endif
  261. }
  262. int SLtt_flush_output (void)
  263. {
  264. int nwrite = 0;
  265. unsigned int total;
  266. int n = (int) (Output_Bufferp - Output_Buffer);
  267. SLtt_Num_Chars_Output += n;
  268. total = 0;
  269. while (n > 0)
  270. {
  271. nwrite = write (fileno(stdout), (char *) Output_Buffer + total, n);
  272. if (nwrite == -1)
  273. {
  274. nwrite = 0;
  275. #ifdef EAGAIN
  276. if (errno == EAGAIN)
  277. {
  278. sl_usleep (100000); /* 1/10 sec */
  279. continue;
  280. }
  281. #endif
  282. #ifdef EWOULDBLOCK
  283. if (errno == EWOULDBLOCK)
  284. {
  285. sl_usleep (100000);
  286. continue;
  287. }
  288. #endif
  289. #ifdef EINTR
  290. if (errno == EINTR) continue;
  291. #endif
  292. break;
  293. }
  294. n -= nwrite;
  295. total += nwrite;
  296. }
  297. Output_Bufferp = Output_Buffer;
  298. return n;
  299. }
  300. int SLtt_Baud_Rate;
  301. static void tt_write(char *str, unsigned int n)
  302. {
  303. static unsigned long last_time;
  304. static int total;
  305. unsigned long now;
  306. unsigned int ndiff;
  307. if ((str == NULL) || (n == 0)) return;
  308. total += n;
  309. while (1)
  310. {
  311. ndiff = MAX_OUTPUT_BUFFER_SIZE - (int) (Output_Bufferp - Output_Buffer);
  312. if (ndiff < n)
  313. {
  314. SLMEMCPY ((char *) Output_Bufferp, (char *) str, ndiff);
  315. Output_Bufferp += ndiff;
  316. SLtt_flush_output ();
  317. n -= ndiff;
  318. str += ndiff;
  319. }
  320. else
  321. {
  322. SLMEMCPY ((char *) Output_Bufferp, str, n);
  323. Output_Bufferp += n;
  324. break;
  325. }
  326. }
  327. if (((SLtt_Baud_Rate > 150) && (SLtt_Baud_Rate <= 9600))
  328. && (10 * total > SLtt_Baud_Rate))
  329. {
  330. total = 0;
  331. if ((now = (unsigned long) time(NULL)) - last_time <= 1)
  332. {
  333. SLtt_flush_output ();
  334. sleep((unsigned) 1);
  335. }
  336. last_time = now;
  337. }
  338. }
  339. void SLtt_write_string (char *str)
  340. {
  341. if (str != NULL) tt_write(str, strlen(str));
  342. }
  343. void SLtt_putchar (char ch)
  344. {
  345. #ifdef SLTT_TRANSP_ACS_PATCH
  346. int restore_acs = 0;
  347. #endif
  348. SLtt_normal_video ();
  349. if (Cursor_Set == 1)
  350. {
  351. if (ch >= ' ') Cursor_c++;
  352. #ifndef SLTT_TRANSP_ACS_PATCH
  353. else if (ch == '\b') Cursor_c--;
  354. #else
  355. if (ch <= ' ' && SLtt_ACS_Active)
  356. {
  357. SLtt_set_alt_char_set (0);
  358. restore_acs = 1;
  359. }
  360. if (ch == '\b') Cursor_c--;
  361. #endif
  362. else if (ch == '\r') Cursor_c = 0;
  363. else Cursor_Set = 0;
  364. if ((Cursor_c + 1 == SLtt_Screen_Cols)
  365. && Automatic_Margins) Cursor_Set = 0;
  366. }
  367. if (Output_Bufferp < Output_Buffer + MAX_OUTPUT_BUFFER_SIZE)
  368. {
  369. *Output_Bufferp++ = (unsigned char) ch;
  370. }
  371. else tt_write (&ch, 1);
  372. #ifdef SLTT_TRANSP_ACS_PATCH
  373. if (restore_acs)
  374. {
  375. SLtt_set_alt_char_set (1);
  376. }
  377. #endif
  378. }
  379. /* this is supposed to be fast--- also handles
  380. termcap: %d, &i, %., %+, %r strings as well as terminfo stuff */
  381. static unsigned int tt_sprintf(char *buf, char *fmt, int x, int y)
  382. {
  383. register unsigned char *f = (unsigned char *) fmt, *b, ch;
  384. int offset = 0, tinfo = 0;
  385. int stack[10];
  386. int i = 0, z;
  387. stack[0] = y; stack[1] = x; i = 2;
  388. b = (unsigned char *) buf;
  389. if (fmt != NULL) while ((ch = *f++) != 0)
  390. {
  391. if (ch != '%') *b++ = ch;
  392. else
  393. {
  394. ch = *f++;
  395. if (tinfo)
  396. {
  397. if ((ch <= '3') && (ch >= '0'))
  398. {
  399. /* map it to termcap. Since this is terminfo,
  400. * it must be one of:
  401. * %2d, %3d, %02d, %03d
  402. *
  403. * I am assuming that a terminal that understands
  404. * %2d form will also understand the %02d form. These
  405. * only differ by a space padding the field.
  406. */
  407. /* skip the 'd'-- hope it is there */
  408. if (ch == '0')
  409. {
  410. ch = *f;
  411. f += 2;
  412. }
  413. else f++;
  414. }
  415. }
  416. switch (ch)
  417. {
  418. case 'p':
  419. tinfo = 1;
  420. ch = *f++;
  421. if (ch == '1') stack[i++] = x; else stack[i++] = y;
  422. break;
  423. case '\'': /* 'x' */
  424. stack[i++] = *f++;
  425. f++;
  426. break;
  427. case '{': /* literal constant, e.g. {30} */
  428. z = 0;
  429. while (((ch = *f) <= '9') && (ch >= '0'))
  430. {
  431. z = z * 10 + (ch - '0');
  432. f++;
  433. }
  434. stack[i++] = z;
  435. if (ch == '}') f++;
  436. break;
  437. case 'd':
  438. case '2':
  439. case '3':
  440. z = stack[--i];
  441. z += offset;
  442. if (z >= 100)
  443. {
  444. *b++ = z / 100 + '0';
  445. z = z % 100;
  446. goto ten;
  447. }
  448. else if (ch == 3)
  449. {
  450. *b++ = '0';
  451. ch = '2';
  452. }
  453. if (z >= 10)
  454. {
  455. ten:
  456. *b++ = z / 10 + '0';
  457. z = z % 10;
  458. }
  459. else if (ch == 2) *b++ = '0';
  460. *b++ = z + '0';
  461. break;
  462. case 'i':
  463. offset = 1;
  464. break;
  465. case '+':
  466. if (tinfo)
  467. {
  468. z = stack[--i];
  469. stack[i-1] += z;
  470. }
  471. else
  472. {
  473. ch = *f++;
  474. if ((unsigned char) ch == 128) ch = 0;
  475. ch = ch + (unsigned char) stack[--i];
  476. if (ch == '\n') ch++;
  477. *b++ = ch;
  478. }
  479. break;
  480. case 'r':
  481. stack[0] = x;
  482. stack[1] = y;
  483. break;
  484. case '.':
  485. case 'c':
  486. ch = (unsigned char) stack[--i];
  487. if (ch == '\n') ch++;
  488. *b++ = ch;
  489. break;
  490. default:
  491. *b++ = ch;
  492. }
  493. }
  494. }
  495. *b = 0;
  496. return((unsigned int) (b - (unsigned char *) buf));
  497. }
  498. static void tt_printf(char *fmt, int x, int y)
  499. {
  500. char buf[256];
  501. unsigned int n;
  502. if (fmt == NULL) return;
  503. n = tt_sprintf(buf, fmt, x, y);
  504. tt_write(buf, n);
  505. }
  506. void SLtt_set_scroll_region (int r1, int r2)
  507. {
  508. Scroll_r1 = r1;
  509. Scroll_r2 = r2;
  510. tt_printf (Scroll_R_Str, Scroll_r1, Scroll_r2);
  511. Cursor_Set = 0;
  512. }
  513. void SLtt_reset_scroll_region (void)
  514. {
  515. SLtt_set_scroll_region(0, SLtt_Screen_Rows - 1);
  516. }
  517. int SLtt_set_cursor_visibility (int show)
  518. {
  519. if ((Cursor_Visible_Str == NULL) || (Cursor_Invisible_Str == NULL))
  520. return -1;
  521. SLtt_write_string (show ? Cursor_Visible_Str : Cursor_Invisible_Str);
  522. return 0;
  523. }
  524. /* the goto_rc function moves to row relative to scrolling region */
  525. void SLtt_goto_rc(int r, int c)
  526. {
  527. char *s = NULL;
  528. int n;
  529. char buf[6];
  530. #ifdef SLTT_TRANSP_ACS_PATCH
  531. int check_alt_acs = 0;
  532. #endif
  533. if (c < 0)
  534. {
  535. c = -c - 1;
  536. Cursor_Set = 0;
  537. }
  538. /* if (No_Move_In_Standout && Current_Fgbg) SLtt_normal_video (); */
  539. r += Scroll_r1;
  540. if ((Cursor_Set > 0) || ((Cursor_Set < 0) && !Automatic_Margins))
  541. {
  542. n = r - Cursor_r;
  543. if ((n == -1) && (Cursor_Set > 0) && (Cursor_c == c)
  544. && (Curs_Up_Str != NULL))
  545. {
  546. s = Curs_Up_Str;
  547. }
  548. else if ((n >= 0) && (n <= 4))
  549. {
  550. if ((n == 0) && (Cursor_Set == 1)
  551. && ((c > 1) || (c == Cursor_c)))
  552. {
  553. if (Cursor_c == c) return;
  554. if (Cursor_c == c + 1)
  555. {
  556. s = buf;
  557. *s++ = '\b'; *s = 0;
  558. s = buf;
  559. #ifdef SLTT_TRANSP_ACS_PATCH
  560. check_alt_acs = 1;
  561. #endif
  562. }
  563. }
  564. else if (c == 0)
  565. {
  566. s = buf;
  567. if ((Cursor_Set != 1) || (Cursor_c != 0)) *s++ = '\r';
  568. while (n--) *s++ = '\n';
  569. #ifdef VMS
  570. /* Need to add this after \n to start a new record. Sheesh. */
  571. *s++ = '\r';
  572. #endif
  573. *s = 0;
  574. s = buf;
  575. #ifdef SLTT_TRANSP_ACS_PATCH
  576. check_alt_acs = 1;
  577. #endif
  578. }
  579. /* Will fail on VMS */
  580. #ifndef VMS
  581. else if (SLtt_Newline_Ok && (Cursor_Set == 1) &&
  582. (Cursor_c >= c) && (c + 3 > Cursor_c))
  583. {
  584. s = buf;
  585. while (n--) *s++ = '\n';
  586. n = Cursor_c - c;
  587. while (n--) *s++ = '\b';
  588. *s = 0;
  589. s = buf;
  590. #ifdef SLTT_TRANSP_ACS_PATCH
  591. check_alt_acs = 1;
  592. #endif
  593. }
  594. #endif
  595. }
  596. }
  597. #ifndef SLTT_TRANSP_ACS_PATCH
  598. if (s != NULL) SLtt_write_string(s);
  599. #else
  600. if (s != NULL)
  601. {
  602. if (check_alt_acs && SLtt_ACS_Active)
  603. {
  604. SLtt_set_alt_char_set (0);
  605. SLtt_write_string(s);
  606. SLtt_set_alt_char_set (1);
  607. }
  608. else SLtt_write_string(s);
  609. }
  610. #endif
  611. else tt_printf(Curs_Pos_Str, r, c);
  612. Cursor_c = c; Cursor_r = r;
  613. Cursor_Set = 1;
  614. }
  615. void SLtt_begin_insert (void)
  616. {
  617. SLtt_write_string(Ins_Mode_Str);
  618. }
  619. void SLtt_end_insert (void)
  620. {
  621. SLtt_write_string(Eins_Mode_Str);
  622. }
  623. void SLtt_delete_char (void)
  624. {
  625. SLtt_normal_video ();
  626. SLtt_write_string(Del_Char_Str);
  627. }
  628. void SLtt_erase_line (void)
  629. {
  630. SLtt_write_string("\r");
  631. Cursor_Set = 1; Cursor_c = 0;
  632. SLtt_del_eol();
  633. }
  634. void SLtt_delete_nlines (int n)
  635. {
  636. int r1, curs;
  637. char buf[132];
  638. #ifdef SLTT_TRANSP_ACS_PATCH
  639. int restore_acs = 0;
  640. #endif
  641. if (n <= 0) return;
  642. SLtt_normal_video ();
  643. if (Del_N_Lines_Str != NULL) tt_printf(Del_N_Lines_Str,n, 0);
  644. else
  645. /* get a new terminal */
  646. {
  647. r1 = Scroll_r1;
  648. curs = Cursor_r;
  649. SLtt_set_scroll_region(curs, Scroll_r2);
  650. SLtt_goto_rc(Scroll_r2 - Scroll_r1, 0);
  651. #ifdef SLTT_TRANSP_ACS_PATCH
  652. if (SLtt_ACS_Active)
  653. {
  654. SLtt_set_alt_char_set (0);
  655. restore_acs = 1;
  656. }
  657. #endif
  658. SLMEMSET(buf, '\n', (unsigned int) n);
  659. tt_write(buf, (unsigned int) n);
  660. #ifdef SLTT_TRANSP_ACS_PATCH
  661. if (restore_acs) SLtt_set_alt_char_set (1);
  662. #endif
  663. /* while (n--) tt_putchar('\n'); */
  664. SLtt_set_scroll_region(r1, Scroll_r2);
  665. SLtt_goto_rc(curs, 0);
  666. }
  667. }
  668. void SLtt_cls (void)
  669. {
  670. SLtt_normal_video();
  671. SLtt_reset_scroll_region ();
  672. SLtt_write_string(Cls_Str);
  673. }
  674. void SLtt_reverse_index (int n)
  675. {
  676. if (!n) return;
  677. SLtt_normal_video();
  678. if (Add_N_Lines_Str != NULL) tt_printf(Add_N_Lines_Str,n, 0);
  679. else
  680. {
  681. while(n--) SLtt_write_string(Rev_Scroll_Str);
  682. }
  683. }
  684. int SLtt_Ignore_Beep = 1;
  685. static char *Visible_Bell_Str;
  686. void SLtt_beep (void)
  687. {
  688. if (SLtt_Ignore_Beep & 0x1) SLtt_putchar('\007');
  689. if (SLtt_Ignore_Beep & 0x2)
  690. {
  691. if (Visible_Bell_Str != NULL) SLtt_write_string (Visible_Bell_Str);
  692. #ifdef __linux__
  693. else if (Linux_Console)
  694. {
  695. SLtt_write_string ("\033[?5h");
  696. SLtt_flush_output ();
  697. sl_usleep (50000);
  698. SLtt_write_string ("\033[?5l");
  699. }
  700. #endif
  701. }
  702. SLtt_flush_output ();
  703. }
  704. void SLtt_del_eol (void)
  705. {
  706. if (Current_Fgbg != 0xFFFFFFFFU) SLtt_normal_video ();
  707. SLtt_write_string(Del_Eol_Str);
  708. }
  709. typedef const struct
  710. {
  711. char *name;
  712. SLtt_Char_Type color;
  713. }
  714. Color_Def_Type;
  715. #define MAX_COLOR_NAMES 17
  716. static Color_Def_Type Color_Defs [MAX_COLOR_NAMES] =
  717. {
  718. {"black", SLSMG_COLOR_BLACK},
  719. {"red", SLSMG_COLOR_RED},
  720. {"green", SLSMG_COLOR_GREEN},
  721. {"brown", SLSMG_COLOR_BROWN},
  722. {"blue", SLSMG_COLOR_BLUE},
  723. {"magenta", SLSMG_COLOR_MAGENTA},
  724. {"cyan", SLSMG_COLOR_CYAN},
  725. {"lightgray", SLSMG_COLOR_LGRAY},
  726. {"gray", SLSMG_COLOR_GRAY},
  727. {"brightred", SLSMG_COLOR_BRIGHT_RED},
  728. {"brightgreen", SLSMG_COLOR_BRIGHT_GREEN},
  729. {"yellow", SLSMG_COLOR_BRIGHT_BROWN},
  730. {"brightblue", SLSMG_COLOR_BRIGHT_BLUE},
  731. {"brightmagenta", SLSMG_COLOR_BRIGHT_CYAN},
  732. {"brightcyan", SLSMG_COLOR_BRIGHT_MAGENTA},
  733. {"white", SLSMG_COLOR_BRIGHT_WHITE},
  734. {"default", 25}
  735. };
  736. void SLtt_set_mono (int obj, char *what, SLtt_Char_Type mask)
  737. {
  738. (void) what;
  739. if ((obj < 0) || (obj >= JMAX_COLORS))
  740. {
  741. return;
  742. }
  743. Ansi_Color_Map[obj].mono = mask & ATTR_MASK;
  744. }
  745. static char *check_color_for_digit_form (char *color)
  746. {
  747. unsigned int i, ich;
  748. char *s = color;
  749. i = 0;
  750. while ((ich = (int) *s) != 0)
  751. {
  752. if ((ich < '0') || (ich > '9'))
  753. return color;
  754. i = i * 10 + (ich - '0');
  755. s++;
  756. }
  757. if (i < MAX_COLOR_NAMES)
  758. color = Color_Defs[i].name;
  759. return color;
  760. }
  761. static int get_default_colors (char **fgp, char **bgp)
  762. {
  763. static char fg_buf[16], bg_buf[16], *bg, *fg;
  764. static int already_parsed;
  765. char *p, *pmax;
  766. if (already_parsed == -1)
  767. return -1;
  768. if (already_parsed)
  769. {
  770. *fgp = fg;
  771. *bgp = bg;
  772. return 0;
  773. }
  774. already_parsed = -1;
  775. bg = getenv ("COLORFGBG");
  776. if (bg == NULL)
  777. {
  778. bg = getenv ("DEFAULT_COLORS");
  779. if (bg == NULL)
  780. return -1;
  781. }
  782. p = fg_buf;
  783. pmax = p + (sizeof (fg_buf) - 1);
  784. while ((*bg != 0) && (*bg != ';'))
  785. {
  786. if (p < pmax) *p++ = *bg;
  787. bg++;
  788. }
  789. *p = 0;
  790. if (*bg) bg++;
  791. p = bg_buf;
  792. pmax = p + (sizeof (bg_buf) - 1);
  793. /* Mark suggested allowing for extra spplication specific stuff following
  794. * the background color. That is what the check for the semi-colon is for.
  795. */
  796. while ((*bg != 0) && (*bg != ';'))
  797. {
  798. if (p < pmax) *p++ = *bg;
  799. bg++;
  800. }
  801. *p = 0;
  802. if (!strcmp (fg_buf, "default") || !strcmp(bg_buf, "default"))
  803. {
  804. *fgp = *bgp = fg = bg = "default";
  805. }
  806. else
  807. {
  808. *fgp = fg = check_color_for_digit_form (fg_buf);
  809. *bgp = bg = check_color_for_digit_form (bg_buf);
  810. }
  811. already_parsed = 1;
  812. return 0;
  813. }
  814. static unsigned char FgBg_Stats[JMAX_COLORS];
  815. static int Color_0_Modified = 0;
  816. void SLtt_set_color_object (int obj, SLtt_Char_Type attr)
  817. {
  818. char *cust_esc;
  819. if ((obj < 0) || (obj >= JMAX_COLORS)) return;
  820. cust_esc = Ansi_Color_Map[obj].custom_esc;
  821. if (cust_esc != NULL)
  822. {
  823. SLFREE (cust_esc);
  824. FgBg_Stats[(Ansi_Color_Map[obj].fgbg >> 8) & 0x7F] -= 1;
  825. Ansi_Color_Map[obj].custom_esc = NULL;
  826. }
  827. Ansi_Color_Map[obj].fgbg = attr;
  828. if (obj == 0) Color_0_Modified = 1;
  829. }
  830. SLtt_Char_Type SLtt_get_color_object (int obj)
  831. {
  832. if ((obj < 0) || (obj >= JMAX_COLORS)) return 0;
  833. return Ansi_Color_Map[obj].fgbg;
  834. }
  835. void SLtt_add_color_attribute (int obj, SLtt_Char_Type attr)
  836. {
  837. if ((obj < 0) || (obj >= JMAX_COLORS)) return;
  838. Ansi_Color_Map[obj].fgbg |= (attr & ATTR_MASK);
  839. if (obj == 0) Color_0_Modified = 1;
  840. }
  841. static SLtt_Char_Type fb_to_fgbg (SLtt_Char_Type f, SLtt_Char_Type b)
  842. {
  843. SLtt_Char_Type attr = 0;
  844. if ((f & 0xF0) == 0)
  845. {
  846. if (f & 0x8) attr = SLTT_BOLD_MASK;
  847. f &= 0x7;
  848. }
  849. else f = 9;
  850. if ((b & 0xF0) == 0)
  851. {
  852. if (b & 0x8) attr |= SLTT_BLINK_MASK;
  853. b &= 0x7;
  854. }
  855. else b = 9;
  856. return ((f << 8) | (b << 16) | attr);
  857. }
  858. static int make_color_fgbg (char *fg, char *bg, SLtt_Char_Type *fgbg)
  859. {
  860. SLtt_Char_Type f = 0xFFFFFFFFU, b = 0xFFFFFFFFU;
  861. char *dfg, *dbg;
  862. unsigned int i;
  863. if ((fg != NULL) && (*fg == 0)) fg = NULL;
  864. if ((bg != NULL) && (*bg == 0)) bg = NULL;
  865. if ((fg == NULL) || (bg == NULL))
  866. {
  867. if (-1 == get_default_colors (&dfg, &dbg))
  868. return -1;
  869. if (fg == NULL) fg = dfg;
  870. if (bg == NULL) bg = dbg;
  871. }
  872. for (i = 0; i < MAX_COLOR_NAMES; i++)
  873. {
  874. if (strcmp(fg, Color_Defs[i].name)) continue;
  875. f = Color_Defs[i].color;
  876. break;
  877. }
  878. for (i = 0; i < MAX_COLOR_NAMES; i++)
  879. {
  880. if (strcmp(bg, Color_Defs[i].name)) continue;
  881. b = Color_Defs[i].color;
  882. break;
  883. }
  884. if ((f == 0xFFFFFFFFU) || (b == 0xFFFFFFFFU))
  885. return -1;
  886. *fgbg = fb_to_fgbg (f, b);
  887. return 0;
  888. }
  889. void SLtt_set_color (int obj, char *what, char *fg, char *bg)
  890. {
  891. SLtt_Char_Type fgbg;
  892. (void) what;
  893. if ((obj < 0) || (obj >= JMAX_COLORS))
  894. return;
  895. if (-1 != make_color_fgbg (fg, bg, &fgbg))
  896. SLtt_set_color_object (obj, fgbg);
  897. }
  898. void SLtt_set_color_fgbg (int obj, SLtt_Char_Type f, SLtt_Char_Type b)
  899. {
  900. SLtt_set_color_object (obj, fb_to_fgbg (f, b));
  901. }
  902. void SLtt_set_color_esc (int obj, char *esc)
  903. {
  904. char *cust_esc;
  905. SLtt_Char_Type fgbg = 0;
  906. int i;
  907. if ((obj < 0) || (obj >= JMAX_COLORS))
  908. {
  909. return;
  910. }
  911. cust_esc = Ansi_Color_Map[obj].custom_esc;
  912. if (cust_esc != NULL)
  913. {
  914. SLFREE (cust_esc);
  915. FgBg_Stats[(Ansi_Color_Map[obj].fgbg >> 8) & 0x7F] -= 1;
  916. }
  917. cust_esc = (char *) SLMALLOC (strlen(esc) + 1);
  918. if (cust_esc != NULL) strcpy (cust_esc, esc);
  919. Ansi_Color_Map[obj].custom_esc = cust_esc;
  920. if (cust_esc == NULL) fgbg = 0;
  921. else
  922. {
  923. /* The whole point of this is to generate a unique fgbg */
  924. for (i = 0; i < JMAX_COLORS; i++)
  925. {
  926. if (FgBg_Stats[i] == 0) fgbg = i;
  927. if (obj == i) continue;
  928. if ((Ansi_Color_Map[i].custom_esc) == NULL) continue;
  929. if (!strcmp (Ansi_Color_Map[i].custom_esc, cust_esc))
  930. {
  931. fgbg = (Ansi_Color_Map[i].fgbg >> 8) & 0x7F;
  932. break;
  933. }
  934. }
  935. FgBg_Stats[fgbg] += 1;
  936. }
  937. fgbg |= 0x80;
  938. Ansi_Color_Map[obj].fgbg = (fgbg | (fgbg << 8)) << 8;
  939. if (obj == 0) Color_0_Modified = 1;
  940. }
  941. void SLtt_set_alt_char_set (int i)
  942. {
  943. #ifndef SLTT_TRANSP_ACS_PATCH
  944. static int last_i;
  945. #else
  946. #define last_i SLtt_ACS_Active
  947. #endif
  948. if (SLtt_Has_Alt_Charset == 0) return;
  949. if (i == last_i) return;
  950. SLtt_write_string (i ? Start_Alt_Chars_Str : End_Alt_Chars_Str );
  951. /* if (i) Current_Fgbg |= SLTT_ALTC_MASK;
  952. else Current_Fgbg &= ~SLTT_ALTC_MASK; */
  953. last_i = i;
  954. #ifdef SLTT_TRANSP_ACS_PATCH
  955. #undef last_i
  956. #endif
  957. }
  958. static void write_attributes (SLtt_Char_Type fgbg)
  959. {
  960. int bg0, fg0;
  961. if (Worthless_Highlight) return;
  962. if (fgbg == Current_Fgbg) return;
  963. /* Before spitting out colors, fix attributes */
  964. if ((fgbg & ATTR_MASK) != (Current_Fgbg & ATTR_MASK))
  965. {
  966. if (Current_Fgbg & ATTR_MASK)
  967. {
  968. SLtt_write_string(Norm_Vid_Str);
  969. /* In case normal video turns off ALL attributes: */
  970. if (fgbg & SLTT_ALTC_MASK)
  971. Current_Fgbg &= ~SLTT_ALTC_MASK;
  972. SLtt_set_alt_char_set (0);
  973. }
  974. if ((fgbg & SLTT_ALTC_MASK)
  975. != (Current_Fgbg & SLTT_ALTC_MASK))
  976. {
  977. SLtt_set_alt_char_set ((int) (fgbg & SLTT_ALTC_MASK));
  978. }
  979. if (fgbg & SLTT_ULINE_MASK) SLtt_write_string (UnderLine_Vid_Str);
  980. if (fgbg & SLTT_BOLD_MASK) SLtt_bold_video ();
  981. if (fgbg & SLTT_REV_MASK) SLtt_write_string (Rev_Vid_Str);
  982. if (fgbg & SLTT_BLINK_MASK)
  983. {
  984. /* Someday Linux will have a blink mode that set high intensity
  985. * background. Lets be prepared.
  986. */
  987. if (SLtt_Blink_Mode) SLtt_write_string (Blink_Vid_Str);
  988. }
  989. }
  990. if (SLtt_Use_Ansi_Colors)
  991. {
  992. fg0 = (int) GET_FG(fgbg);
  993. bg0 = (int) GET_BG(fgbg);
  994. tt_printf(Color_Escape_Sequence, fg0, bg0);
  995. }
  996. Current_Fgbg = fgbg;
  997. }
  998. static int Video_Initialized;
  999. void SLtt_reverse_video (int color)
  1000. {
  1001. SLtt_Char_Type fgbg;
  1002. char *esc;
  1003. if (Worthless_Highlight) return;
  1004. if ((color < 0) || (color >= JMAX_COLORS)) return;
  1005. if (Video_Initialized == 0)
  1006. {
  1007. if (color == JNORMAL_COLOR)
  1008. {
  1009. SLtt_write_string (Norm_Vid_Str);
  1010. }
  1011. else SLtt_write_string (Rev_Vid_Str);
  1012. Current_Fgbg = 0xFFFFFFFFU;
  1013. return;
  1014. }
  1015. if (SLtt_Use_Ansi_Colors)
  1016. {
  1017. fgbg = Ansi_Color_Map[color].fgbg;
  1018. if ((esc = Ansi_Color_Map[color].custom_esc) != NULL)
  1019. {
  1020. if (fgbg != Current_Fgbg)
  1021. {
  1022. Current_Fgbg = fgbg;
  1023. SLtt_write_string (esc);
  1024. return;
  1025. }
  1026. }
  1027. }
  1028. else fgbg = Ansi_Color_Map[color].mono;
  1029. if (fgbg == Current_Fgbg) return;
  1030. write_attributes (fgbg);
  1031. }
  1032. void SLtt_normal_video (void)
  1033. {
  1034. SLtt_reverse_video(JNORMAL_COLOR);
  1035. }
  1036. void SLtt_narrow_width (void)
  1037. {
  1038. SLtt_write_string("\033[?3l");
  1039. }
  1040. void SLtt_wide_width (void)
  1041. {
  1042. SLtt_write_string("\033[?3h");
  1043. }
  1044. /* Highest bit represents the character set. */
  1045. #define COLOR_MASK 0x7F00
  1046. #define COLOR_OF(x) (((unsigned int)(x) & COLOR_MASK) >> 8)
  1047. /*
  1048. #define COLOR_EQS(a, b) \
  1049. (Ansi_Color_Map[COLOR_OF(a)].fgbg == Ansi_Color_Map[COLOR_OF(b)].fgbg)
  1050. */
  1051. #define COLOR_EQS(a, b) \
  1052. (SLtt_Use_Ansi_Colors \
  1053. ? (Ansi_Color_Map[COLOR_OF(a)].fgbg == Ansi_Color_Map[COLOR_OF(b)].fgbg)\
  1054. : (Ansi_Color_Map[COLOR_OF(a)].mono == Ansi_Color_Map[COLOR_OF(b)].mono))
  1055. #define CHAR_EQS(a, b) (((a) == (b))\
  1056. || ((((a) & ~COLOR_MASK) == ((b) & ~COLOR_MASK))\
  1057. && COLOR_EQS((a), (b))))
  1058. /* The whole point of this routine is to prevent writing to the last column
  1059. * and last row on terminals with automatic margins.
  1060. */
  1061. static void write_string_with_care (char *str)
  1062. {
  1063. unsigned int len;
  1064. if (str == NULL) return;
  1065. len = strlen (str);
  1066. if (Automatic_Margins && (Cursor_r + 1 == SLtt_Screen_Rows))
  1067. {
  1068. if (len + (unsigned int) Cursor_c >= (unsigned int) SLtt_Screen_Cols)
  1069. {
  1070. /* For now, just do not write there. Later, something more
  1071. * sophisticated will be implemented.
  1072. */
  1073. if (SLtt_Screen_Cols > Cursor_c)
  1074. len = SLtt_Screen_Cols - Cursor_c - 1;
  1075. else len = 0;
  1076. }
  1077. }
  1078. tt_write (str, len);
  1079. }
  1080. static void send_attr_str (unsigned short *s)
  1081. {
  1082. unsigned char out[256], ch, *p;
  1083. register SLtt_Char_Type attr;
  1084. register unsigned short sh;
  1085. int color, last_color = -1;
  1086. p = out;
  1087. while (0 != (sh = *s++))
  1088. {
  1089. ch = sh & 0xFF;
  1090. color = ((int) sh & 0xFF00) >> 8;
  1091. #ifdef SLTT_TRANSP_ACS_PATCH
  1092. if (ch <= ' ' && (color & 0x80)) color &= ~0x80;
  1093. #endif
  1094. if (color != last_color)
  1095. {
  1096. if (SLtt_Use_Ansi_Colors) attr = Ansi_Color_Map[color & 0x7F].fgbg;
  1097. else attr = Ansi_Color_Map[color & 0x7F].mono;
  1098. /* sh => color */
  1099. if (color & 0x80) /* alternate char set */
  1100. {
  1101. if (SLtt_Use_Blink_For_ACS)
  1102. {
  1103. if (SLtt_Blink_Mode) attr |= SLTT_BLINK_MASK;
  1104. }
  1105. else attr |= SLTT_ALTC_MASK;
  1106. }
  1107. if (attr != Current_Fgbg)
  1108. {
  1109. #ifndef SLTT_TRANSP_ACS_PATCH
  1110. if ((ch != ' ') ||
  1111. /* it is a space so only consider it different if it
  1112. * has different attributes.
  1113. */
  1114. (attr & BGALL_MASK) != (Current_Fgbg & BGALL_MASK))
  1115. #endif
  1116. {
  1117. if (p != out)
  1118. {
  1119. *p = 0;
  1120. write_string_with_care ((char *) out);
  1121. Cursor_c += (int) (p - out);
  1122. p = out;
  1123. }
  1124. if (SLtt_Use_Ansi_Colors && (NULL != Ansi_Color_Map[color & 0x7F].custom_esc))
  1125. {
  1126. SLtt_write_string (Ansi_Color_Map[color & 0x7F].custom_esc);
  1127. /* Just in case the custom escape sequence screwed up
  1128. * the alt character set state...
  1129. */
  1130. if ((attr & SLTT_ALTC_MASK) != (Current_Fgbg & SLTT_ALTC_MASK))
  1131. SLtt_set_alt_char_set ((int) (attr & SLTT_ALTC_MASK));
  1132. Current_Fgbg = attr;
  1133. }
  1134. else write_attributes (attr);
  1135. last_color = color;
  1136. }
  1137. }
  1138. }
  1139. *p++ = ch;
  1140. }
  1141. *p = 0;
  1142. if (p != out) write_string_with_care ((char *) out);
  1143. Cursor_c += (int) (p - out);
  1144. }
  1145. static void forward_cursor (unsigned int n, int row)
  1146. {
  1147. char buf[30];
  1148. if (n <= 4)
  1149. {
  1150. SLtt_normal_video ();
  1151. SLMEMSET (buf, ' ', n);
  1152. buf[n] = 0;
  1153. write_string_with_care (buf);
  1154. Cursor_c += n;
  1155. }
  1156. else if (Curs_F_Str != NULL)
  1157. {
  1158. Cursor_c += n;
  1159. n = tt_sprintf(buf, Curs_F_Str, (int) n, 0);
  1160. tt_write(buf, n);
  1161. }
  1162. else SLtt_goto_rc (row, (int) (Cursor_c + n));
  1163. }
  1164. #define SPACE_CHAR (0x20 | (JNORMAL_COLOR << 8))
  1165. void SLtt_smart_puts(unsigned short *neww, unsigned short *oldd, int len, int row)
  1166. {
  1167. register unsigned short *p, *q, *qmax, *pmax, *buf;
  1168. unsigned short buffer[256];
  1169. unsigned int n_spaces;
  1170. unsigned short *space_match, *last_buffered_match;
  1171. #ifdef HP_GLITCH_CODE
  1172. int handle_hp_glitch = 0;
  1173. #endif
  1174. q = oldd; p = neww;
  1175. qmax = oldd + len;
  1176. pmax = p + len;
  1177. /* Find out where to begin --- while they match, we are ok */
  1178. while (1)
  1179. {
  1180. if (q == qmax) return;
  1181. #if SLANG_HAS_KANJI_SUPPORT
  1182. if (*p & 0x80)
  1183. { /* new is kanji */
  1184. if ((*q & 0x80) && ((q + 1) < qmax))
  1185. { /* old is also kanji */
  1186. if (((0xFF & *q) != (0xFF & *p))
  1187. || ((0xFF & q[1]) != (0xFF & p[1])))
  1188. break; /* both kanji, but not match */
  1189. else
  1190. { /* kanji match ! */
  1191. if (!COLOR_EQS(*q, *p)) break;
  1192. q++; p++;
  1193. if (!COLOR_EQS(*q, *p)) break;
  1194. /* really match! */
  1195. q++; p++;
  1196. continue;
  1197. }
  1198. }
  1199. else break; /* old is not kanji */
  1200. }
  1201. else
  1202. { /* new is not kanji */
  1203. if (*q & 0x80) break; /* old is kanji */
  1204. }
  1205. #endif
  1206. if (!CHAR_EQS(*q, *p)) break;
  1207. q++; p++;
  1208. }
  1209. /*position the cursor */
  1210. SLtt_goto_rc (row, (int) (p - neww));
  1211. #ifdef HP_GLITCH_CODE
  1212. if (Has_HP_Glitch)
  1213. {
  1214. unsigned short *qq = q;
  1215. while (qq < qmax)
  1216. {
  1217. if (*qq & 0xFF00)
  1218. {
  1219. SLtt_normal_video ();
  1220. SLtt_del_eol ();
  1221. qmax = q;
  1222. handle_hp_glitch = 1;
  1223. break;
  1224. }
  1225. qq++;
  1226. }
  1227. }
  1228. #endif
  1229. /* Find where the last non-blank character on old/new screen is */
  1230. while (qmax > q)
  1231. {
  1232. qmax--;
  1233. if (!CHAR_EQS(*qmax, SPACE_CHAR))
  1234. {
  1235. qmax++;
  1236. break;
  1237. }
  1238. }
  1239. while (pmax > p)
  1240. {
  1241. pmax--;
  1242. if (!CHAR_EQS(*pmax, SPACE_CHAR))
  1243. {
  1244. pmax++;
  1245. break;
  1246. }
  1247. }
  1248. last_buffered_match = buf = buffer; /* buffer is empty */
  1249. #ifdef HP_GLITCH_CODE
  1250. if (handle_hp_glitch)
  1251. {
  1252. while (p < pmax)
  1253. {
  1254. *buf++ = *p++;
  1255. }
  1256. }
  1257. #endif
  1258. /* loop using overwrite then skip algorithm until done */
  1259. while (1)
  1260. {
  1261. /* while they do not match and we do not hit a space, buffer them up */
  1262. n_spaces = 0;
  1263. while (p < pmax)
  1264. {
  1265. if (CHAR_EQS(*q,SPACE_CHAR) && CHAR_EQS(*p, SPACE_CHAR))
  1266. {
  1267. /* If *q is not a space, we would have to overwrite it.
  1268. * However, if *q is a space, then while *p is also one,
  1269. * we only need to skip over the blank field.
  1270. */
  1271. space_match = p;
  1272. p++; q++;
  1273. while ((p < pmax)
  1274. && CHAR_EQS(*q,SPACE_CHAR)
  1275. && CHAR_EQS(*p, SPACE_CHAR))
  1276. {
  1277. p++;
  1278. q++;
  1279. }
  1280. n_spaces = (unsigned int) (p - space_match);
  1281. break;
  1282. }
  1283. #if SLANG_HAS_KANJI_SUPPORT
  1284. if ((*p & 0x80) && ((p + 1) < pmax))
  1285. { /* new is kanji */
  1286. if (*q & 0x80)
  1287. { /* old is also kanji */
  1288. if (((0xFF & *q) != (0xFF & *p))
  1289. || ((0xFF & q[1]) != (0xFF & p[1])))
  1290. {
  1291. /* both kanji, but not match */
  1292. *buf++ = *p++;
  1293. *buf++ = *p++;
  1294. q += 2;
  1295. continue;
  1296. }
  1297. else
  1298. { /* kanji match ? */
  1299. if (!COLOR_EQS(*q, *p) || !COLOR_EQS(*(q+1), *(p+1)))
  1300. {
  1301. /* code is match ,but color is diff */
  1302. *buf++ = *p++;
  1303. *buf++ = *p++;
  1304. continue;
  1305. }
  1306. /* really match ! */
  1307. break;
  1308. }
  1309. }
  1310. else
  1311. { /* old is not kanji */
  1312. *buf++ = *p++;
  1313. *buf++ = *p++;
  1314. q += 2;
  1315. continue;
  1316. }
  1317. }
  1318. else
  1319. { /* new is not kanji */
  1320. if (*q & 0x80)
  1321. { /* old is kanji */
  1322. *buf++ = *p++;
  1323. q++;
  1324. continue;
  1325. }
  1326. }
  1327. #endif
  1328. if (CHAR_EQS(*q, *p)) break;
  1329. *buf++ = *p++;
  1330. q++;
  1331. }
  1332. *buf = 0;
  1333. if (buf != buffer) send_attr_str (buffer);
  1334. buf = buffer;
  1335. if (n_spaces && (p < pmax))
  1336. {
  1337. forward_cursor (n_spaces, row);
  1338. }
  1339. /* Now we overwrote what we could and cursor is placed at position
  1340. * of a possible match of new and old. If this is the case, skip
  1341. * some more.
  1342. */
  1343. #if !SLANG_HAS_KANJI_SUPPORT
  1344. while ((p < pmax) && CHAR_EQS(*p, *q))
  1345. {
  1346. *buf++ = *p++;
  1347. q++;
  1348. }
  1349. #else
  1350. /* Kanji */
  1351. while (p < pmax)
  1352. {
  1353. if ((*p & 0x80) && ((p + 1) < pmax))
  1354. { /* new is kanji */
  1355. if (*q & 0x80)
  1356. { /* old is also kanji */
  1357. if (((0xFF & *q) == (0xFF & *p))
  1358. && ((0xFF & q[1]) == (0xFF & p[1])))
  1359. {
  1360. /* kanji match ? */
  1361. if (!COLOR_EQS(*q, *p)
  1362. || !COLOR_EQS(q[1], p[1]))
  1363. break;
  1364. *buf++ = *p++;
  1365. q++;
  1366. if (p >= pmax)
  1367. {
  1368. *buf++ = SPACE_CHAR;
  1369. p++;
  1370. break;
  1371. }
  1372. else
  1373. {
  1374. *buf++ = *p++;
  1375. q++;
  1376. continue;
  1377. }
  1378. }
  1379. else break; /* both kanji, but not match */
  1380. }
  1381. else break; /* old is not kanji */
  1382. }
  1383. else
  1384. { /* new is not kanji */
  1385. if (*q & 0x80) break; /* old is kanji */
  1386. if (!CHAR_EQS(*q, *p)) break;
  1387. *buf++ = *p++;
  1388. q++;
  1389. }
  1390. }
  1391. #endif
  1392. last_buffered_match = buf;
  1393. if (p >= pmax) break;
  1394. /* jump to new position is it is greater than 5 otherwise
  1395. * let it sit in the buffer and output it later.
  1396. */
  1397. if ((int) (buf - buffer) >= 5)
  1398. {
  1399. forward_cursor ((unsigned int) (buf - buffer), row);
  1400. last_buffered_match = buf = buffer;
  1401. }
  1402. }
  1403. if (buf != buffer)
  1404. {
  1405. if (q < qmax)
  1406. {
  1407. if ((buf == last_buffered_match)
  1408. && ((int) (buf - buffer) >= 5))
  1409. {
  1410. forward_cursor ((unsigned int) (buf - buffer), row);
  1411. }
  1412. else
  1413. {
  1414. *buf = 0;
  1415. send_attr_str (buffer);
  1416. }
  1417. }
  1418. }
  1419. if (q < qmax) SLtt_del_eol ();
  1420. if (Automatic_Margins && (Cursor_c + 1 >= SLtt_Screen_Cols)) Cursor_Set = 0;
  1421. }
  1422. static void get_color_info (void)
  1423. {
  1424. char *fg, *bg;
  1425. SLtt_Use_Ansi_Colors = (NULL != getenv ("COLORTERM"));
  1426. if (-1 == get_default_colors (&fg, &bg))
  1427. return;
  1428. /* Check to see if application has already set them. */
  1429. if (Color_0_Modified)
  1430. return;
  1431. SLtt_set_color (0, NULL, fg, bg);
  1432. SLtt_set_color (1, NULL, bg, fg);
  1433. }
  1434. /* termcap stuff */
  1435. #ifdef __unix__
  1436. #ifndef USE_TERMCAP
  1437. static char *Tbuf;
  1438. static char *Tstr_Buf;
  1439. #define tgetstr SLtt_tigetstr
  1440. #define tgetent SLtt_tigetent
  1441. #define TGETNUM(x) SLtt_tigetnum((x), &Tbuf)
  1442. #define TGETFLAG(x) SLtt_tigetflag((x), &Tbuf)
  1443. #else
  1444. extern char *tgetstr(char *, char **);
  1445. extern int tgetent(char *, char *);
  1446. extern int tgetnum(char *);
  1447. extern int tgetflag(char *);
  1448. static char Tstr_Buf[1024];
  1449. static char Tbuf[4096];
  1450. #define TGETNUM tgetnum
  1451. #define TGETFLAG tgetflag
  1452. #endif
  1453. static char *my_tgetstr(char *what, char **p)
  1454. {
  1455. register char *w, *w1;
  1456. char *wsave;
  1457. what = tgetstr(what, p);
  1458. if (what != NULL)
  1459. {
  1460. /* Check for AIX brain-damage */
  1461. if (*what == '@')
  1462. return NULL;
  1463. /* lose pad info --- with today's technology, term is a loser if
  1464. it is really needed */
  1465. while ((*what == '.') ||
  1466. ((*what >= '0') && (*what <= '9'))) what++;
  1467. if (*what == '*') what++;
  1468. /* lose terminfo padding--- looks like $<...> */
  1469. w = what;
  1470. while (*w) if ((*w++ == '$') && (*w == '<'))
  1471. {
  1472. w1 = w - 1;
  1473. while (*w && (*w != '>')) w++;
  1474. if (*w == 0) break;
  1475. w++;
  1476. wsave = w1;
  1477. while ((*w1++ = *w++) != 0);
  1478. w = wsave;
  1479. }
  1480. if (*what == 0) what = NULL;
  1481. }
  1482. return(what);
  1483. }
  1484. char *SLtt_tgetstr (char *s)
  1485. {
  1486. #ifdef USE_TERMCAP
  1487. static
  1488. #endif
  1489. char *p = Tstr_Buf;
  1490. return my_tgetstr (s, &p);
  1491. }
  1492. int SLtt_tgetnum (char *s)
  1493. {
  1494. return TGETNUM (s);
  1495. }
  1496. int SLtt_tgetflag (char *s)
  1497. {
  1498. return TGETFLAG (s);
  1499. }
  1500. static int Vt100_Like = 0;
  1501. void SLtt_get_terminfo (void)
  1502. {
  1503. char *term, *t, ch;
  1504. int is_xterm;
  1505. int almost_vtxxx;
  1506. get_color_info ();
  1507. if (NULL == (term = (char *) getenv("TERM")))
  1508. {
  1509. SLang_exit_error("TERM environment variable needs set.");
  1510. }
  1511. Linux_Console = (!strncmp (term, "linux", 5)
  1512. #ifdef linux
  1513. || !strncmp(term, "con", 3)
  1514. #endif
  1515. );
  1516. t = term;
  1517. if (strcmp(t, "vt52") && (*t++ == 'v') && (*t++ == 't')
  1518. && (ch = *t, (ch >= '1') && (ch <= '9'))) Vt100_Like = 1;
  1519. is_xterm = !strncmp (term, "xterm", 5);
  1520. almost_vtxxx = (Vt100_Like
  1521. || Linux_Console
  1522. || is_xterm
  1523. || !strcmp (term, "screen"));
  1524. #ifndef USE_TERMCAP
  1525. if (NULL == (Tbuf = tgetent (term)))
  1526. {
  1527. char err_buf[512];
  1528. if (almost_vtxxx) /* Special cases. */
  1529. {
  1530. int vt102 = 1;
  1531. if (!strcmp (term, "vt100")) vt102 = 0;
  1532. SLtt_set_term_vtxxx (&vt102);
  1533. return;
  1534. }
  1535. g_snprintf (err_buf, sizeof (err_buf), "Unknown terminal: %s\n\
  1536. Check the TERM environment variable.\n\
  1537. Also make sure that the terminal is defined in the terminfo database.\n\
  1538. Alternatively, set the TERMCAP environment variable to the desired\n\
  1539. termcap entry.", term);
  1540. SLang_exit_error(err_buf);
  1541. }
  1542. Tstr_Buf = Tbuf;
  1543. #else /* USE_TERMCAP */
  1544. if (1 != tgetent(Tbuf, term)) SLang_exit_error("Unknown terminal.");
  1545. #endif /* NOT USE_TERMCAP */
  1546. if ((NULL == (Cls_Str = SLtt_tgetstr("cl")))
  1547. || (NULL == (Curs_Pos_Str = SLtt_tgetstr("cm"))))
  1548. {
  1549. SLang_exit_error("Terminal not powerful enough for SLang.");
  1550. }
  1551. if ((NULL == (Ins_Mode_Str = SLtt_tgetstr("im")))
  1552. || ( NULL == (Eins_Mode_Str = SLtt_tgetstr("ei")))
  1553. || ( NULL == (Del_Char_Str = SLtt_tgetstr("dc"))))
  1554. SLtt_Term_Cannot_Insert = 1;
  1555. Visible_Bell_Str = SLtt_tgetstr ("vb");
  1556. Curs_Up_Str = SLtt_tgetstr ("up");
  1557. Rev_Scroll_Str = SLtt_tgetstr("sr");
  1558. Del_N_Lines_Str = SLtt_tgetstr("DL");
  1559. Add_N_Lines_Str = SLtt_tgetstr("AL");
  1560. /* Actually these are used to initialize terminals that use cursor
  1561. * addressing. Hard to believe.
  1562. */
  1563. Term_Init_Str = SLtt_tgetstr ("ti");
  1564. Term_Reset_Str = SLtt_tgetstr ("te");
  1565. /* If I do this for vtxxx terminals, arrow keys start sending ESC O A,
  1566. * which I do not want. This is mainly for HP terminals.
  1567. */
  1568. if ((almost_vtxxx == 0) || SLtt_Force_Keypad_Init)
  1569. {
  1570. Keypad_Init_Str = SLtt_tgetstr ("ks");
  1571. Keypad_Reset_Str = SLtt_tgetstr ("ke");
  1572. }
  1573. /* Make up for defective termcap/terminfo databases */
  1574. if ((Vt100_Like && (term[2] != '1'))
  1575. || Linux_Console
  1576. || is_xterm
  1577. )
  1578. {
  1579. if (Del_N_Lines_Str == NULL) Del_N_Lines_Str = "\033[%dM";
  1580. if (Add_N_Lines_Str == NULL) Add_N_Lines_Str = "\033[%dL";
  1581. }
  1582. Scroll_R_Str = SLtt_tgetstr("cs");
  1583. SLtt_get_screen_size ();
  1584. if ((Scroll_R_Str == NULL)
  1585. || (((NULL == Del_N_Lines_Str) || (NULL == Add_N_Lines_Str))
  1586. && (NULL == Rev_Scroll_Str)))
  1587. {
  1588. if (is_xterm
  1589. || Linux_Console
  1590. )
  1591. {
  1592. /* Defective termcap mode!!!! */
  1593. SLtt_set_term_vtxxx (NULL);
  1594. }
  1595. else SLtt_Term_Cannot_Scroll = 1;
  1596. }
  1597. Del_Eol_Str = SLtt_tgetstr("ce");
  1598. Rev_Vid_Str = SLtt_tgetstr("mr");
  1599. if (Rev_Vid_Str == NULL) Rev_Vid_Str = SLtt_tgetstr("so");
  1600. Bold_Vid_Str = SLtt_tgetstr("md");
  1601. /* Although xterm cannot blink, it does display the blinking characters
  1602. * as bold ones. Some Rxvt will display the background as high intensity.
  1603. */
  1604. if ((NULL == (Blink_Vid_Str = SLtt_tgetstr("mb")))
  1605. && is_xterm)
  1606. Blink_Vid_Str = "\033[5m";
  1607. UnderLine_Vid_Str = SLtt_tgetstr("us");
  1608. Start_Alt_Chars_Str = SLtt_tgetstr ("as"); /* smacs */
  1609. End_Alt_Chars_Str = SLtt_tgetstr ("ae"); /* rmacs */
  1610. Enable_Alt_Char_Set = SLtt_tgetstr ("eA"); /* enacs */
  1611. SLtt_Graphics_Char_Pairs = SLtt_tgetstr ("ac");
  1612. #ifndef NCURSES_BRAIN_DAMAGE_CONTROL
  1613. # define NCURSES_BRAIN_DAMAGE_CONTROL 0
  1614. #endif
  1615. #if NCURSES_BRAIN_DAMAGE_CONTROL
  1616. if (Linux_Console)
  1617. {
  1618. # if 0
  1619. char *lgcp = "l\332m\300k\277j\331u\264t\303v\301w\302q\304x\263n\053o\176s\137`\004a\260f\370g\361~\011,\020+\021.\031-\030h\261i\0250\333";
  1620. SLtt_Graphics_Char_Pairs = lgcp;
  1621. Start_Alt_Chars_Str = "\033(B\033)U\016";
  1622. End_Alt_Chars_Str = "\033(B\033)0\017";
  1623. Enable_Alt_Char_Set = NULL;
  1624. # else
  1625. char *lgcp = "`\004a\261f\370g\361h\260j\331k\277l\332m\300n\305o\302q\304r\362s_t\303u\264v\301w\302x\263y\371z\372{\373|\374}\375~";
  1626. SLtt_Graphics_Char_Pairs = lgcp;
  1627. Start_Alt_Chars_Str = "\033[11m";
  1628. End_Alt_Chars_Str = "\033[10m";
  1629. Enable_Alt_Char_Set = NULL;
  1630. # endif
  1631. }
  1632. #endif
  1633. if (NULL == SLtt_Graphics_Char_Pairs)
  1634. {
  1635. /* make up for defective termcap/terminfo */
  1636. if (Vt100_Like)
  1637. {
  1638. Start_Alt_Chars_Str = "\016";
  1639. End_Alt_Chars_Str = "\017";
  1640. Enable_Alt_Char_Set = "\033)0";
  1641. }
  1642. }
  1643. /* aixterm added by willi */
  1644. if (is_xterm || !strncmp (term, "aixterm", 7))
  1645. {
  1646. Start_Alt_Chars_Str = "\016";
  1647. End_Alt_Chars_Str = "\017";
  1648. Enable_Alt_Char_Set = "\033(B\033)0";
  1649. }
  1650. if ((SLtt_Graphics_Char_Pairs == NULL) &&
  1651. ((Start_Alt_Chars_Str == NULL) || (End_Alt_Chars_Str == NULL)))
  1652. {
  1653. SLtt_Has_Alt_Charset = 0;
  1654. Enable_Alt_Char_Set = NULL;
  1655. }
  1656. else SLtt_Has_Alt_Charset = 1;
  1657. /* status line capabilities */
  1658. if ((SLtt_Has_Status_Line == -1)
  1659. && (0 != (SLtt_Has_Status_Line = TGETFLAG ("hs"))))
  1660. {
  1661. Disable_Status_line_Str = SLtt_tgetstr ("ds");
  1662. Return_From_Status_Line_Str = SLtt_tgetstr ("fs");
  1663. Goto_Status_Line_Str = SLtt_tgetstr ("ts");
  1664. Status_Line_Esc_Ok = TGETFLAG("es");
  1665. Num_Status_Line_Columns = TGETNUM("ws");
  1666. if (Num_Status_Line_Columns < 0) Num_Status_Line_Columns = 0;
  1667. }
  1668. if (NULL == (Norm_Vid_Str = SLtt_tgetstr("me")))
  1669. {
  1670. Norm_Vid_Str = SLtt_tgetstr("se");
  1671. }
  1672. Cursor_Invisible_Str = SLtt_tgetstr("vi");
  1673. Cursor_Visible_Str = SLtt_tgetstr("ve");
  1674. Curs_F_Str = SLtt_tgetstr("RI");
  1675. #if 0
  1676. if (NULL != Curs_F_Str)
  1677. {
  1678. Len_Curs_F_Str = strlen(Curs_F_Str);
  1679. }
  1680. else Len_Curs_F_Str = strlen(Curs_Pos_Str);
  1681. #endif
  1682. Automatic_Margins = TGETFLAG ("am");
  1683. /* No_Move_In_Standout = !TGETFLAG ("ms"); */
  1684. #ifdef HP_GLITCH_CODE
  1685. Has_HP_Glitch = TGETFLAG ("xs");
  1686. #else
  1687. Worthless_Highlight = TGETFLAG ("xs");
  1688. #endif
  1689. if (Worthless_Highlight == 0)
  1690. { /* Magic cookie glitch */
  1691. Worthless_Highlight = (TGETNUM ("sg") > 0);
  1692. }
  1693. if (Worthless_Highlight)
  1694. SLtt_Has_Alt_Charset = 0;
  1695. /* Check for color information in the termcap. A program should not
  1696. * rely on this information being accurate.
  1697. */
  1698. if (SLtt_Use_Ansi_Colors == 0)
  1699. {
  1700. Reset_Color_String = SLtt_tgetstr ("op");
  1701. SLtt_Use_Ansi_Colors = ((NULL != Reset_Color_String)
  1702. || (NULL != SLtt_tgetstr ("Sf"))
  1703. || (NULL != SLtt_tgetstr ("Sb"))
  1704. || (NULL != SLtt_tgetstr ("AF"))
  1705. || (NULL != SLtt_tgetstr ("AB"))
  1706. || (-1 != SLtt_tgetnum ("Co"))
  1707. || (-1 != SLtt_tgetnum ("pa")));
  1708. }
  1709. #if defined(__QNX__) && defined(QNX_QANSI_SLANG_COMPAT_ACS)
  1710. /*
  1711. * Override the alt-char-set handling string in case of a
  1712. * QNX/qansi terminal: use the "old style" strings in order
  1713. * to be compatible with S-Lang without the SLTT_TRANSP_ACS_PATCH
  1714. * code...
  1715. */
  1716. if (SLtt_Has_Alt_Charset &&
  1717. strncmp(term, "qansi", 5) == 0 &&
  1718. Start_Alt_Chars_Str[0] != '\016')
  1719. {
  1720. Start_Alt_Chars_Str = "\016"; /* smacs/as (^N) */
  1721. End_Alt_Chars_Str = "\017"; /* rmacs/ae (^O) */
  1722. SLtt_Graphics_Char_Pairs = /* acsc/ac */
  1723. "``aaffggjjkkllmmnnooppqqrrssttuuvvwwxxyyzz{{||}}~~O\141";
  1724. /*
  1725. * it would be required to modify the sgr/sa entry also, if it
  1726. * would be used (->embedded as/ae sequences)...
  1727. */
  1728. }
  1729. #endif /* __QNX__ && QNX_QANSI_SLANG_COMPAT_ACS */
  1730. }
  1731. #endif
  1732. /* Unix */
  1733. /* specific to vtxxx only */
  1734. void SLtt_enable_cursor_keys (void)
  1735. {
  1736. #ifdef __unix__
  1737. if (Vt100_Like)
  1738. #endif
  1739. SLtt_write_string("\033=\033[?1l");
  1740. }
  1741. #ifdef VMS
  1742. void SLtt_get_terminfo ()
  1743. {
  1744. int zero = 0;
  1745. get_color_info ();
  1746. SLtt_set_term_vtxxx(&zero);
  1747. Start_Alt_Chars_Str = "\016";
  1748. End_Alt_Chars_Str = "\017";
  1749. SLtt_Has_Alt_Charset = 1;
  1750. SLtt_Graphics_Char_Pairs = "aaffgghhjjkkllmmnnooqqssttuuvvwwxx";
  1751. Enable_Alt_Char_Set = "\033(B\033)0";
  1752. SLtt_get_screen_size ();
  1753. }
  1754. #endif
  1755. /* This sets term for vt102 terminals it parameter vt100 is 0. If vt100
  1756. * is non-zero, set terminal appropriate for a only vt100
  1757. * (no add line capability). */
  1758. void SLtt_set_term_vtxxx(int *vt100)
  1759. {
  1760. Norm_Vid_Str = "\033[m";
  1761. Scroll_R_Str = "\033[%i%d;%dr";
  1762. Cls_Str = "\033[2J\033[H";
  1763. Rev_Vid_Str = "\033[7m";
  1764. Bold_Vid_Str = "\033[1m";
  1765. Blink_Vid_Str = "\033[5m";
  1766. UnderLine_Vid_Str = "\033[4m";
  1767. Del_Eol_Str = "\033[K";
  1768. Rev_Scroll_Str = "\033M";
  1769. Curs_F_Str = "\033[%dC";
  1770. /* Len_Curs_F_Str = 5; */
  1771. Curs_Pos_Str = "\033[%i%d;%dH";
  1772. if ((vt100 == NULL) || (*vt100 == 0))
  1773. {
  1774. Ins_Mode_Str = "\033[4h";
  1775. Eins_Mode_Str = "\033[4l";
  1776. Del_Char_Str = "\033[P";
  1777. Del_N_Lines_Str = "\033[%dM";
  1778. Add_N_Lines_Str = "\033[%dL";
  1779. SLtt_Term_Cannot_Insert = 0;
  1780. }
  1781. else
  1782. {
  1783. Del_N_Lines_Str = NULL;
  1784. Add_N_Lines_Str = NULL;
  1785. SLtt_Term_Cannot_Insert = 1;
  1786. }
  1787. SLtt_Term_Cannot_Scroll = 0;
  1788. /* No_Move_In_Standout = 0; */
  1789. }
  1790. void SLtt_init_video (void)
  1791. {
  1792. /* send_string_to_term("\033[?6h"); */
  1793. /* relative origin mode */
  1794. SLtt_write_string (Term_Init_Str);
  1795. SLtt_write_string (Keypad_Init_Str);
  1796. SLtt_reset_scroll_region();
  1797. SLtt_end_insert();
  1798. SLtt_write_string (Enable_Alt_Char_Set);
  1799. Video_Initialized = 1;
  1800. }
  1801. void SLtt_reset_video (void)
  1802. {
  1803. SLtt_goto_rc (SLtt_Screen_Rows - 1, 0);
  1804. Cursor_Set = 0;
  1805. SLtt_normal_video (); /* MSKermit requires this */
  1806. SLtt_write_string(Norm_Vid_Str);
  1807. Current_Fgbg = 0xFFFFFFFFU;
  1808. SLtt_set_alt_char_set (0);
  1809. if (SLtt_Use_Ansi_Colors)
  1810. {
  1811. if (Reset_Color_String == NULL)
  1812. {
  1813. SLtt_Char_Type attr;
  1814. if (-1 != make_color_fgbg (NULL, NULL, &attr))
  1815. write_attributes (attr);
  1816. else SLtt_write_string ("\033[0m\033[m");
  1817. }
  1818. else SLtt_write_string (Reset_Color_String);
  1819. Current_Fgbg = 0xFFFFFFFFU;
  1820. }
  1821. SLtt_erase_line ();
  1822. SLtt_write_string (Keypad_Reset_Str);
  1823. SLtt_write_string (Term_Reset_Str);
  1824. SLtt_flush_output ();
  1825. Video_Initialized = 0;
  1826. }
  1827. void SLtt_bold_video (void)
  1828. {
  1829. SLtt_write_string (Bold_Vid_Str);
  1830. }
  1831. int SLtt_set_mouse_mode (int mode, int force)
  1832. {
  1833. char *term;
  1834. if (force == 0)
  1835. {
  1836. if (NULL == (term = (char *) getenv("TERM"))) return -1;
  1837. if (strncmp ("xterm", term, 5))
  1838. return -1;
  1839. }
  1840. if (mode)
  1841. SLtt_write_string ("\033[?9h");
  1842. else
  1843. SLtt_write_string ("\033[?9l");
  1844. return 0;
  1845. }
  1846. void SLtt_disable_status_line (void)
  1847. {
  1848. if (SLtt_Has_Status_Line > 0)
  1849. SLtt_write_string (Disable_Status_line_Str);
  1850. }
  1851. int SLtt_write_to_status_line (char *s, int col)
  1852. {
  1853. if ((SLtt_Has_Status_Line <= 0)
  1854. || (Goto_Status_Line_Str == NULL)
  1855. || (Return_From_Status_Line_Str == NULL))
  1856. return -1;
  1857. tt_printf (Goto_Status_Line_Str, col, 0);
  1858. SLtt_write_string (s);
  1859. SLtt_write_string (Return_From_Status_Line_Str);
  1860. return 0;
  1861. }
  1862. void SLtt_get_screen_size (void)
  1863. {
  1864. #ifdef VMS
  1865. int status, code;
  1866. unsigned short chan;
  1867. $DESCRIPTOR(dev_dsc, "SYS$INPUT:");
  1868. #endif
  1869. #ifdef __os2__
  1870. VIOMODEINFO vioModeInfo;
  1871. #endif
  1872. int r = 0, c = 0;
  1873. #if defined(TIOCGWINSZ) && !defined(SCO_FLAVOR)
  1874. struct winsize wind_struct;
  1875. do
  1876. {
  1877. if ((ioctl(1,TIOCGWINSZ,&wind_struct) == 0)
  1878. || (ioctl(0, TIOCGWINSZ, &wind_struct) == 0)
  1879. || (ioctl(2, TIOCGWINSZ, &wind_struct) == 0))
  1880. {
  1881. c = (int) wind_struct.ws_col;
  1882. r = (int) wind_struct.ws_row;
  1883. break;
  1884. }
  1885. }
  1886. while (errno == EINTR);
  1887. #endif
  1888. #ifdef VMS
  1889. status = sys$assign(&dev_dsc,&chan,0,0,0);
  1890. if (status & 1)
  1891. {
  1892. code = DVI$_DEVBUFSIZ;
  1893. status = lib$getdvi(&code, &chan,0, &c, 0,0);
  1894. if (!(status & 1))
  1895. c = 80;
  1896. code = DVI$_TT_PAGE;
  1897. status = lib$getdvi(&code, &chan,0, &r, 0,0);
  1898. if (!(status & 1))
  1899. r = 24;
  1900. sys$dassgn(chan);
  1901. }
  1902. #endif
  1903. #ifdef __os2__
  1904. vioModeInfo.cb = sizeof(vioModeInfo);
  1905. VioGetMode (&vioModeInfo, 0);
  1906. c = vioModeInfo.col;
  1907. r = vioModeInfo.row;
  1908. #endif
  1909. if (r <= 0)
  1910. {
  1911. char *s = getenv ("LINES");
  1912. if (s != NULL) r = atoi (s);
  1913. }
  1914. if (c <= 0)
  1915. {
  1916. char *s = getenv ("COLUMNS");
  1917. if (s != NULL) c = atoi (s);
  1918. }
  1919. if ((r <= 0) || (r > 200)) r = 24;
  1920. if ((c <= 0) || (c > 250)) c = 80;
  1921. SLtt_Screen_Rows = r;
  1922. SLtt_Screen_Cols = c;
  1923. }