sldisply.c 64 KB

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