sldisply.c 59 KB

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