slsmg.c 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165
  1. /* SLang Screen management routines */
  2. #include "slinclud.h"
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include "slang.h"
  6. #include "_slang.h"
  7. typedef struct
  8. {
  9. int n; /* number of chars written last time */
  10. int flags; /* line untouched, etc... */
  11. SLsmg_Char_Type *old, *neew;
  12. #ifndef IBMPC_SYSTEM
  13. unsigned long old_hash, new_hash;
  14. #endif
  15. }
  16. Screen_Type;
  17. #define TOUCHED 0x1
  18. #define TRASHED 0x2
  19. static int Screen_Trashed;
  20. static Screen_Type SL_Screen[SLTT_MAX_SCREEN_ROWS];
  21. static int Start_Col, Start_Row;
  22. static unsigned int Screen_Cols, Screen_Rows;
  23. static int This_Row, This_Col;
  24. static SLsmg_Color_Type This_Color;
  25. static int UTF8_Mode = -1;
  26. #if SLTT_HAS_NON_BCE_SUPPORT && !defined(IBMPC_SYSTEM)
  27. #define REQUIRES_NON_BCE_SUPPORT 1
  28. static int Bce_Color_Offset;
  29. #endif
  30. int SLsmg_Newline_Behavior = SLSMG_NEWLINE_IGNORED;
  31. int SLsmg_Backspace_Moves = 0;
  32. #if SLSMG_HAS_EMBEDDED_ESCAPE
  33. /* If non-zero, interpret escape sequences ESC [ x m as an embedded set color
  34. * sequence. The 'x' is a decimal integer that specifies the color. The sequence
  35. * ends at m. Examples: \e[3m --> set color 3. \e[272m --> color=272.
  36. * Note: These escape sequences are NOT ANSI, though similar. ANSI permits
  37. * sequences such as \e[32;44m to set the foreground to green/blue. This interface
  38. * will support such sequences, _but_ in will map such squences to the sum of
  39. * the colors: \e[32;44m --> color (32+44)=76.
  40. *
  41. * In addition to 'm', ']' is also supported.
  42. */
  43. static int Embedded_Escape_Mode = 0;
  44. int SLsmg_embedded_escape_mode (int mode)
  45. {
  46. int old_mode = Embedded_Escape_Mode;
  47. Embedded_Escape_Mode = mode;
  48. return old_mode;
  49. }
  50. /* This function gets called with u pointing at what may be '['. If it sucessfully
  51. * parses the escape sequence, *up and the color will be updated.
  52. */
  53. static int parse_embedded_escape (SLuchar_Type *u, SLuchar_Type *umax,
  54. SLsmg_Color_Type default_color,
  55. SLuchar_Type **up, SLsmg_Color_Type *colorp)
  56. {
  57. unsigned int val;
  58. SLuchar_Type ch;
  59. if ((u < umax) && (*u != '['))
  60. return -1;
  61. u++;
  62. if ((u < umax) && ((*u == 'm') || (*u == ']')))
  63. {
  64. *colorp = default_color; /* ESC[m */
  65. *up = u+1;
  66. return 0;
  67. }
  68. val = 0;
  69. while ((u < umax)
  70. && (((ch = *u) >= '0') && (ch <= '9')))
  71. {
  72. val = 10*val + (ch - '0');
  73. u++;
  74. }
  75. if ((u < umax) && ((*u == 'm') || (*u == ']')) && (val <= SLSMG_MAX_COLORS))
  76. {
  77. # ifdef REQUIRES_NON_BCE_SUPPORT
  78. val += Bce_Color_Offset;
  79. #endif
  80. *colorp = (SLsmg_Color_Type) val;
  81. *up = u + 1;
  82. return 0;
  83. }
  84. return -1;
  85. }
  86. static void parse_embedded_set_color (SLuchar_Type *u, SLuchar_Type *umax,
  87. SLsmg_Color_Type default_color)
  88. {
  89. SLsmg_Color_Type color = default_color;
  90. while (u < umax)
  91. {
  92. if (*u++ == 033)
  93. (void) parse_embedded_escape (u, umax, default_color, &u, &color);
  94. }
  95. if (color == default_color)
  96. return;
  97. #ifdef REQUIRES_NON_BCE_SUPPORT
  98. color -= Bce_Color_Offset;
  99. #endif
  100. SLsmg_set_color (color);
  101. }
  102. #endif
  103. /* Backward compatibility. Not used. */
  104. /* int SLsmg_Newline_Moves; */
  105. static int *tt_Screen_Rows = NULL;
  106. static int *tt_Screen_Cols = NULL;
  107. static int *tt_unicode_ok;
  108. static void (*tt_normal_video)(void);
  109. static void (*tt_goto_rc)(int, int);
  110. static void (*tt_cls) (void);
  111. static void (*tt_del_eol) (void);
  112. static void (*tt_smart_puts) (SLsmg_Char_Type *, SLsmg_Char_Type *, int, int);
  113. static int (*tt_flush_output) (void);
  114. static int (*tt_reset_video) (void);
  115. static int (*tt_init_video) (void);
  116. #ifndef IBMPC_SYSTEM
  117. static void (*tt_set_scroll_region)(int, int);
  118. static void (*tt_reverse_index)(int);
  119. static void (*tt_reset_scroll_region)(void);
  120. static void (*tt_delete_nlines)(int);
  121. #endif
  122. #ifndef IBMPC_SYSTEM
  123. static int *tt_Term_Cannot_Scroll;
  124. static int *tt_Has_Alt_Charset;
  125. static char **tt_Graphics_Char_Pairs;
  126. #else
  127. static int *tt_Has_Alt_Charset = NULL;
  128. static char **tt_Graphics_Char_Pairs = NULL;
  129. #endif
  130. static int Smg_Inited;
  131. /* This is necessary because the windoze run-time linker cannot perform
  132. * relocations on its own.
  133. */
  134. static void init_tt_symbols (void)
  135. {
  136. tt_Screen_Rows = &SLtt_Screen_Rows;
  137. tt_Screen_Cols = &SLtt_Screen_Cols;
  138. tt_unicode_ok = &_pSLtt_UTF8_Mode;
  139. tt_normal_video = SLtt_normal_video;
  140. tt_goto_rc = SLtt_goto_rc;
  141. tt_cls = SLtt_cls;
  142. tt_del_eol = SLtt_del_eol;
  143. tt_smart_puts = SLtt_smart_puts;
  144. tt_flush_output = SLtt_flush_output;
  145. tt_reset_video = SLtt_reset_video;
  146. tt_init_video = SLtt_init_video;
  147. #ifndef IBMPC_SYSTEM
  148. tt_set_scroll_region = SLtt_set_scroll_region;
  149. tt_reverse_index = SLtt_reverse_index;
  150. tt_reset_scroll_region = SLtt_reset_scroll_region;
  151. tt_delete_nlines = SLtt_delete_nlines;
  152. #endif
  153. #ifndef IBMPC_SYSTEM
  154. tt_Term_Cannot_Scroll = &SLtt_Term_Cannot_Scroll;
  155. tt_Has_Alt_Charset = &SLtt_Has_Alt_Charset;
  156. tt_Graphics_Char_Pairs = &SLtt_Graphics_Char_Pairs;
  157. #else
  158. tt_Has_Alt_Charset = NULL;
  159. tt_Graphics_Char_Pairs = NULL;
  160. #endif
  161. }
  162. /* Unicode box drawing characters */
  163. /* This lookup table is indexed by the vt100 characters */
  164. static SLwchar_Type ACS_Map[128];
  165. typedef struct
  166. {
  167. unsigned char vt100_char;
  168. unsigned char ascii;
  169. SLwchar_Type unicode;
  170. }
  171. ACS_Def_Type;
  172. static SLCONST ACS_Def_Type UTF8_ACS_Map[] =
  173. {
  174. {'+', '>', 0x2192 }, /* RIGHTWARDS ARROW */
  175. {',', '<', 0x2190 }, /* LEFTWARDS ARROW */
  176. {'-', '^', 0x2191 }, /* UPWARDS ARROW */
  177. {'.', 'v', 0x2193 }, /* DOWNWARDS ARROW */
  178. {'0', '#', 0x25AE }, /* BLACK VERTICAL RECTANGLE */
  179. {'`', '+', 0x25C6 }, /* BLACK DIAMOND */
  180. {'a', ':', 0x2592 }, /* MEDIUM SHADE */
  181. {'f', '\'', 0x00B0 },/* DEGREE SIGN */
  182. {'g', '#', 0x00B1 }, /* PLUS-MINUS SIGN */
  183. {'h', '#', 0x2592 }, /* MEDIUM SHADE */
  184. {'i', '#', 0x2603 }, /* SNOWMAN */
  185. {'j', '+', 0x2518 }, /* BOX DRAWINGS LIGHT UP AND LEFT */
  186. {'k', '+', 0x2510 }, /* BOX DRAWINGS LIGHT DOWN AND LEFT */
  187. {'l', '+', 0x250c }, /* BOX DRAWINGS LIGHT DOWN AND RIGHT */
  188. {'m', '+', 0x2514 }, /* BOX DRAWINGS LIGHT UP AND RIGHT */
  189. {'n', '+', 0x253C }, /* BOX DRAWINGS LIGHT VERTICAL AND HORIZONTAL */
  190. {'o', '~', 0x23BA }, /* HORIZONTAL SCAN LINE-1 */
  191. {'p', '-', 0x23BB }, /* HORIZONTAL SCAN LINE-3 (ncurses addition) */
  192. {'q', '-', 0x2500 }, /* BOX DRAWINGS LIGHT HORIZONTAL */
  193. {'r', '-', 0x23BC }, /* HORIZONTAL SCAN LINE-7 (ncurses addition) */
  194. {'s', '_', 0x23BD }, /* HORIZONTAL SCAN LINE-9 */
  195. {'t', '+', 0x251C }, /* BOX DRAWINGS LIGHT VERTICAL AND RIGHT */
  196. {'u', '+', 0x2524 }, /* BOX DRAWINGS LIGHT VERTICAL AND LEFT */
  197. {'v', '+', 0x2534 }, /* BOX DRAWINGS LIGHT UP AND HORIZONTAL */
  198. {'w', '+', 0x252C }, /* BOX DRAWINGS LIGHT DOWN AND HORIZONTAL */
  199. {'x', '|', 0x2502 }, /* BOX DRAWINGS LIGHT VERTICAL */
  200. {'y', '<', 0x2264 }, /* LESS-THAN OR EQUAL TO (ncurses addition) */
  201. {'z', '>', 0x2265 }, /* GREATER-THAN OR EQUAL TO (ncurses addition) */
  202. {'{', '*', 0x03C0 }, /* GREEK SMALL LETTER PI (ncurses addition) */
  203. {'|', '!', 0x2260 }, /* NOT EQUAL TO (ncurses addition) */
  204. {'}', 'f', 0x00A3 }, /* POUND SIGN (ncurses addition) */
  205. {'~', 'o', 0x00B7 }, /* MIDDLE DOT */
  206. {0, 0, 0}
  207. };
  208. #define ACS_MODE_NONE -1
  209. #define ACS_MODE_AUTO 0
  210. #define ACS_MODE_UNICODE 1
  211. #define ACS_MODE_TERMINFO 2
  212. #define ACS_MODE_ASCII 3
  213. static int Current_ACS_Mode = ACS_MODE_NONE;
  214. static void init_acs (int mode)
  215. {
  216. unsigned int i;
  217. SLCONST ACS_Def_Type *acs;
  218. if (Current_ACS_Mode == mode)
  219. return;
  220. for (i = 0; i < 0x80; i++)
  221. ACS_Map[i] = ' ';
  222. if (mode == ACS_MODE_AUTO)
  223. {
  224. if (UTF8_Mode &&
  225. (tt_unicode_ok != NULL) && (*tt_unicode_ok > 0))
  226. mode = ACS_MODE_UNICODE;
  227. else
  228. mode = ACS_MODE_TERMINFO;
  229. }
  230. switch (mode)
  231. {
  232. case ACS_MODE_UNICODE:
  233. SLsmg_Display_Eight_Bit = 0xA0;
  234. acs = UTF8_ACS_Map;
  235. while (acs->vt100_char != 0)
  236. {
  237. ACS_Map[acs->vt100_char] = acs->unicode;
  238. acs++;
  239. }
  240. break;
  241. case ACS_MODE_TERMINFO:
  242. if ((tt_Has_Alt_Charset != NULL)
  243. && *tt_Has_Alt_Charset
  244. && (tt_Graphics_Char_Pairs != NULL)
  245. && (*tt_Graphics_Char_Pairs != NULL))
  246. {
  247. unsigned char *p = (unsigned char *) *tt_Graphics_Char_Pairs;
  248. unsigned char *pmax = p + strlen ((char *) p);
  249. while (p < pmax)
  250. {
  251. unsigned char ch = *p++;
  252. ACS_Map[ch & 0x7F] = *p++;
  253. }
  254. break;
  255. }
  256. mode = ACS_MODE_ASCII;
  257. /* drop */
  258. case ACS_MODE_ASCII:
  259. default:
  260. acs = UTF8_ACS_Map;
  261. while (acs->vt100_char != 0)
  262. {
  263. ACS_Map[acs->vt100_char] = acs->ascii;
  264. acs++;
  265. }
  266. break;
  267. }
  268. Current_ACS_Mode = mode;
  269. }
  270. static void blank_line (SLsmg_Char_Type *c, unsigned int n, SLwchar_Type wch)
  271. {
  272. SLsmg_Char_Type *cmax = c + n;
  273. SLsmg_Color_Type color = This_Color;
  274. memset ((char *)c, 0, n*sizeof(SLsmg_Char_Type));
  275. while (c < cmax)
  276. {
  277. c->nchars = 1;
  278. c->wchars[0] = wch;
  279. c->color = color;
  280. c++;
  281. }
  282. }
  283. static void clear_region (int row, int n, SLwchar_Type ch)
  284. {
  285. int i;
  286. int imax = row + n;
  287. if (imax > (int) Screen_Rows) imax = (int) Screen_Rows;
  288. if (row < 0)
  289. row = 0;
  290. for (i = row; i < imax; i++)
  291. {
  292. blank_line (SL_Screen[i].neew, Screen_Cols, ch);
  293. SL_Screen[i].flags |= TOUCHED;
  294. }
  295. }
  296. void SLsmg_erase_eol (void)
  297. {
  298. int r, c;
  299. if (Smg_Inited == 0) return;
  300. c = This_Col - Start_Col;
  301. r = This_Row - Start_Row;
  302. if ((r < 0) || (r >= (int)Screen_Rows)) return;
  303. if (c < 0) c = 0; else if (c >= (int)Screen_Cols) return;
  304. blank_line (SL_Screen[This_Row].neew + c , Screen_Cols - c, 0x20);
  305. SL_Screen[This_Row].flags |= TOUCHED;
  306. }
  307. static void scroll_up (void)
  308. {
  309. unsigned int i, imax;
  310. SLsmg_Char_Type *neew;
  311. neew = SL_Screen[0].neew;
  312. imax = Screen_Rows - 1;
  313. for (i = 0; i < imax; i++)
  314. {
  315. SL_Screen[i].neew = SL_Screen[i + 1].neew;
  316. SL_Screen[i].flags |= TOUCHED;
  317. }
  318. SL_Screen[i].neew = neew;
  319. SL_Screen[i].flags |= TOUCHED;
  320. blank_line (neew, Screen_Cols, 0x20);
  321. This_Row--;
  322. }
  323. void SLsmg_gotorc (int r, int c)
  324. {
  325. This_Row = r;
  326. This_Col = c;
  327. }
  328. int SLsmg_get_row (void)
  329. {
  330. return This_Row;
  331. }
  332. int SLsmg_get_column (void)
  333. {
  334. return This_Col;
  335. }
  336. void SLsmg_erase_eos (void)
  337. {
  338. if (Smg_Inited == 0) return;
  339. SLsmg_erase_eol ();
  340. clear_region (This_Row + 1, (int)Screen_Rows, 0x20);
  341. }
  342. static int This_Alt_Char;
  343. void SLsmg_set_char_set (int i)
  344. {
  345. #ifdef IBMPC_SYSTEM
  346. (void) i;
  347. #else
  348. if (i != 0)
  349. This_Alt_Char = SLSMG_ACS_MASK;
  350. else This_Alt_Char = 0;
  351. This_Color &= SLSMG_COLOR_MASK;
  352. This_Color |= This_Alt_Char;
  353. #endif
  354. }
  355. void SLsmg_set_color (SLsmg_Color_Type color)
  356. {
  357. #ifdef REQUIRES_NON_BCE_SUPPORT
  358. color += Bce_Color_Offset;
  359. #endif
  360. This_Color = color | This_Alt_Char;
  361. }
  362. void SLsmg_reverse_video (void)
  363. {
  364. SLsmg_set_color (1);
  365. }
  366. void SLsmg_normal_video (void)
  367. {
  368. SLsmg_set_color (0);
  369. }
  370. static int point_visible (int col_too)
  371. {
  372. return ((This_Row >= Start_Row) && (This_Row < Start_Row + (int)Screen_Rows)
  373. && ((col_too == 0)
  374. || ((This_Col >= Start_Col)
  375. && (This_Col < Start_Col + (int)Screen_Cols))));
  376. }
  377. #define NEXT_CHAR_CELL \
  378. { \
  379. if (p < pmax) \
  380. { \
  381. if ((p->nchars != i) || (p->color != color)) flags |= TOUCHED; \
  382. p->nchars = i; \
  383. p->color = color; \
  384. p++; \
  385. } \
  386. i = 0; \
  387. col++; \
  388. } (void) 0
  389. #define ADD_TO_CHAR_CELL(wc) \
  390. { \
  391. if ((p < pmax) && (p->wchars[i] != wc)) \
  392. { \
  393. p->wchars[i] = wc; \
  394. flags |= TOUCHED; \
  395. } \
  396. i++; \
  397. } (void) 0
  398. #define ADD_CHAR_OR_BREAK(ch) \
  399. if (col >= start_col) \
  400. { \
  401. if (i != 0) NEXT_CHAR_CELL; \
  402. if (last_was_double_width) \
  403. { \
  404. last_was_double_width = 0; \
  405. NEXT_CHAR_CELL; \
  406. } \
  407. if (col >= max_col) break; \
  408. ADD_TO_CHAR_CELL(ch); \
  409. } \
  410. else col++
  411. void SLsmg_write_chars (unsigned char *u, unsigned char *umax)
  412. {
  413. SLsmg_Char_Type *p, *pmax;
  414. SLsmg_Color_Type color;
  415. int flags;
  416. int col, start_col, max_col;
  417. int newline_flag;
  418. int utf8_mode = UTF8_Mode;
  419. unsigned char display_8bit;
  420. int last_was_double_width = 0;
  421. int alt_char_set_flag;
  422. unsigned int i;
  423. #if SLSMG_HAS_EMBEDDED_ESCAPE
  424. SLsmg_Color_Type default_color;
  425. #endif
  426. if (Smg_Inited == 0) return;
  427. display_8bit = (unsigned char) SLsmg_Display_Eight_Bit;
  428. if (utf8_mode)
  429. display_8bit = 0xA0;
  430. color = This_Color;
  431. /* If we are using unicode characters for the line drawing characters, then
  432. * do not attempt to use the terminals alternate character set
  433. */
  434. alt_char_set_flag = (color & SLSMG_ACS_MASK);
  435. if (Current_ACS_Mode == ACS_MODE_UNICODE)
  436. color = color & ~SLSMG_ACS_MASK;
  437. #if SLSMG_HAS_EMBEDDED_ESCAPE
  438. default_color = color; /* used for ESC[m */
  439. #endif
  440. top: /* get here only on newline */
  441. newline_flag = 0;
  442. start_col = Start_Col;
  443. if (point_visible (0) == 0) return;
  444. col = This_Col;
  445. max_col = start_col + Screen_Cols;
  446. p = SL_Screen[This_Row - Start_Row].neew;
  447. pmax = p + Screen_Cols;
  448. if (col >= start_col)
  449. {
  450. p += (col - start_col);
  451. if ((p < pmax) && (p->nchars == 0))
  452. {
  453. /* It looks like we are about to overwrite the right side of a
  454. * double width character.
  455. */
  456. if (col > start_col)
  457. {
  458. p--;
  459. p->nchars = 1;
  460. p->wchars[0] = ' ';
  461. p++;
  462. }
  463. }
  464. }
  465. flags = SL_Screen[This_Row - Start_Row].flags;
  466. i = 0;
  467. while (u < umax)
  468. {
  469. SLwchar_Type wc;
  470. unsigned int width, nconsumed;
  471. if (*u < (SLuchar_Type) 0x80) /* ASCII */
  472. {
  473. unsigned char ch;
  474. ch = (unsigned char) *u++;
  475. if (alt_char_set_flag)
  476. {
  477. wc = ACS_Map[ch];
  478. ADD_CHAR_OR_BREAK(wc);
  479. continue;
  480. }
  481. if ((ch >= (SLuchar_Type)0x20) && (ch < (SLuchar_Type)0x7F))
  482. {
  483. ADD_CHAR_OR_BREAK(ch);
  484. continue;
  485. }
  486. if ((ch == '\t') && (SLsmg_Tab_Width > 0))
  487. {
  488. do
  489. {
  490. if (col < start_col)
  491. col++;
  492. else
  493. {
  494. ADD_CHAR_OR_BREAK(' ');
  495. NEXT_CHAR_CELL;
  496. }
  497. }
  498. while (col % SLsmg_Tab_Width);
  499. continue;
  500. }
  501. if ((ch == '\n')
  502. && (SLsmg_Newline_Behavior != SLSMG_NEWLINE_PRINTABLE))
  503. {
  504. newline_flag = 1;
  505. break;
  506. }
  507. if ((ch == 0x8) && SLsmg_Backspace_Moves)
  508. {
  509. if (col != 0)
  510. {
  511. if (i != 0)
  512. {
  513. NEXT_CHAR_CELL;
  514. col--;
  515. p--;
  516. }
  517. col--;
  518. p--;
  519. }
  520. continue;
  521. }
  522. #if SLSMG_HAS_EMBEDDED_ESCAPE
  523. if ((ch == 033) && Embedded_Escape_Mode)
  524. {
  525. SLsmg_Color_Type next_color;
  526. if (0 == parse_embedded_escape (u, umax, default_color, &u, &next_color))
  527. {
  528. if (i != 0)
  529. NEXT_CHAR_CELL;
  530. color = next_color;
  531. continue;
  532. }
  533. }
  534. #endif
  535. ADD_CHAR_OR_BREAK('^');
  536. if (ch == 127) ch = '?'; else ch = ch + '@';
  537. ADD_CHAR_OR_BREAK (ch);
  538. continue;
  539. }
  540. nconsumed = 1;
  541. if ((utf8_mode == 0)
  542. || (NULL == SLutf8_decode (u, umax, &wc, &nconsumed)))
  543. {
  544. unsigned int ii, jj;
  545. unsigned char hexbuf[8];
  546. if ((utf8_mode == 0)
  547. && display_8bit && (*u >= display_8bit))
  548. {
  549. ADD_CHAR_OR_BREAK(*u);
  550. }
  551. else for (ii = 0; ii < nconsumed; ii++)
  552. {
  553. sprintf ((char *)hexbuf, "<%02X>", u[ii]);
  554. for (jj = 0; jj < 4; jj++)
  555. {
  556. ADD_CHAR_OR_BREAK (hexbuf[jj]);
  557. }
  558. }
  559. u += nconsumed;
  560. continue;
  561. }
  562. u += nconsumed;
  563. if (wc < (SLwchar_Type)display_8bit)
  564. {
  565. unsigned char hexbuf[8];
  566. unsigned int jj;
  567. sprintf ((char *)hexbuf, "<%02X>", (unsigned char) wc);
  568. for (jj = 0; jj < 4; jj++)
  569. {
  570. ADD_CHAR_OR_BREAK (hexbuf[jj]);
  571. }
  572. continue;
  573. }
  574. width = SLwchar_wcwidth (wc);
  575. if (width == 0)
  576. {
  577. /* Combining character--- must follow non-zero width char */
  578. if (i == 0)
  579. continue;
  580. if (i < SLSMG_MAX_CHARS_PER_CELL)
  581. {
  582. ADD_TO_CHAR_CELL (wc);
  583. }
  584. continue;
  585. }
  586. if (width == 2)
  587. {
  588. if (col + 2 <= start_col)
  589. {
  590. col += 2;
  591. continue;
  592. }
  593. if (col + 2 > max_col)
  594. {
  595. ADD_CHAR_OR_BREAK('>');
  596. break;
  597. }
  598. if (col == start_col - 1)
  599. {
  600. /* double width character is clipped at left part of screen.
  601. * So, display right edge as a space */
  602. col++;
  603. ADD_CHAR_OR_BREAK('<');
  604. continue;
  605. }
  606. ADD_CHAR_OR_BREAK(wc);
  607. last_was_double_width = 1;
  608. continue;
  609. }
  610. ADD_CHAR_OR_BREAK(wc);
  611. }
  612. if (i != 0)
  613. {
  614. NEXT_CHAR_CELL;
  615. }
  616. if (last_was_double_width)
  617. {
  618. if (col < max_col)
  619. NEXT_CHAR_CELL;
  620. last_was_double_width = 0;
  621. }
  622. else if ((col < max_col) && (p->nchars == 0))
  623. {
  624. /* The left side of a double with character was overwritten */
  625. p->nchars = 1;
  626. p->wchars[0] = ' ';
  627. }
  628. SL_Screen[This_Row - Start_Row].flags = flags;
  629. This_Col = col;
  630. /* Why would u be NULL here?? */
  631. if (SLsmg_Newline_Behavior == SLSMG_NEWLINE_IGNORED)
  632. {
  633. #if SLSMG_HAS_EMBEDDED_ESCAPE
  634. if (Embedded_Escape_Mode && (u != NULL))
  635. parse_embedded_set_color (u, umax, default_color);
  636. #endif
  637. return;
  638. }
  639. if (newline_flag == 0)
  640. {
  641. #if SLSMG_HAS_EMBEDDED_ESCAPE
  642. SLuchar_Type *usave = u;
  643. #endif
  644. if (u == NULL)
  645. return;
  646. while (u < umax)
  647. {
  648. if (*u == '\n') break;
  649. u++;
  650. }
  651. if (u >= umax)
  652. {
  653. #if SLSMG_HAS_EMBEDDED_ESCAPE
  654. if (Embedded_Escape_Mode)
  655. parse_embedded_set_color (usave, umax, default_color);
  656. #endif
  657. return;
  658. }
  659. u++;
  660. }
  661. This_Row++;
  662. This_Col = 0;
  663. if (This_Row == Start_Row + (int)Screen_Rows)
  664. {
  665. if (SLsmg_Newline_Behavior == SLSMG_NEWLINE_SCROLLS) scroll_up ();
  666. }
  667. goto top;
  668. }
  669. void SLsmg_write_nchars (char *str, unsigned int len)
  670. {
  671. SLsmg_write_chars ((unsigned char *) str, (unsigned char *)str + len);
  672. }
  673. void SLsmg_write_string (char *str)
  674. {
  675. SLsmg_write_chars ((unsigned char *)str,
  676. (unsigned char *)str + strlen (str));
  677. }
  678. void SLsmg_write_nstring (char *str, unsigned int n)
  679. {
  680. unsigned int width;
  681. unsigned char *blank = (unsigned char *)" ";
  682. unsigned char *u = (unsigned char *)str;
  683. /* Avoid a problem if a user accidently passes a negative value */
  684. if ((int) n < 0)
  685. return;
  686. if (u == NULL) width = 0;
  687. else
  688. {
  689. unsigned char *umax;
  690. width = strlen ((char *)u);
  691. if (UTF8_Mode)
  692. umax = SLutf8_skip_chars (u, u+width, n, &width, 0);
  693. else
  694. {
  695. if (width > n) width = n;
  696. umax = u + width;
  697. }
  698. SLsmg_write_chars (u, umax);
  699. }
  700. while (width++ < n) SLsmg_write_chars (blank, blank+1);
  701. }
  702. void SLsmg_write_wrapped_string (SLuchar_Type *u, int r, int c,
  703. unsigned int dr, unsigned int dc,
  704. int fill)
  705. {
  706. int maxc = (int) dc;
  707. unsigned char *p, *pmax;
  708. int utf8_mode = UTF8_Mode;
  709. if ((dr == 0) || (dc == 0)) return;
  710. p = u;
  711. pmax = u + strlen ((char *)u);
  712. dc = 0;
  713. while (1)
  714. {
  715. unsigned char ch = *p;
  716. if ((ch == 0) || (ch == '\n'))
  717. {
  718. int diff;
  719. diff = maxc - (int) dc;
  720. SLsmg_gotorc (r, c);
  721. SLsmg_write_chars (u, p);
  722. if (fill && (diff > 0))
  723. {
  724. unsigned char *blank = (unsigned char *)" ";
  725. while (diff--) SLsmg_write_chars (blank, blank+1);
  726. }
  727. if ((ch == 0) || (dr == 1)) break;
  728. r++;
  729. dc = 0;
  730. dr--;
  731. p++;
  732. u = p;
  733. continue;
  734. }
  735. if ((int) dc == maxc)
  736. {
  737. SLsmg_gotorc (r, c);
  738. SLsmg_write_chars (u, p);
  739. if (dr == 1) break;
  740. r++;
  741. dc = 0;
  742. dr--;
  743. u = p;
  744. continue;
  745. }
  746. dc++;
  747. if (utf8_mode)
  748. p = SLutf8_skip_chars (p, pmax, 1, NULL, 0);
  749. else
  750. p++;
  751. }
  752. }
  753. int SLsmg_Tab_Width = 8;
  754. /* Minimum value for which eight bit char is displayed as is. */
  755. #ifndef IBMPC_SYSTEM
  756. int SLsmg_Display_Eight_Bit = 160;
  757. #else
  758. int SLsmg_Display_Eight_Bit = 128;
  759. #endif
  760. void SLsmg_write_char (SLwchar_Type ch)
  761. {
  762. unsigned char u[SLUTF8_MAX_MBLEN];
  763. unsigned char *umax;
  764. if ((ch < 0x80) || (UTF8_Mode == 0))
  765. {
  766. u[0] = (unsigned char) ch;
  767. SLsmg_write_chars (u, u+1);
  768. return;
  769. }
  770. if (NULL == (umax = SLutf8_encode (ch, u, SLUTF8_MAX_MBLEN)))
  771. return;
  772. SLsmg_write_chars (u, umax);
  773. }
  774. static int Cls_Flag;
  775. void SLsmg_cls (void)
  776. {
  777. int tac;
  778. if (Smg_Inited == 0) return;
  779. tac = This_Alt_Char; This_Alt_Char = 0;
  780. SLsmg_set_color (0);
  781. clear_region (0, (int)Screen_Rows, 0x20);
  782. This_Alt_Char = tac;
  783. SLsmg_set_color (0);
  784. Cls_Flag = 1;
  785. }
  786. #if 0
  787. static void do_copy (SLsmg_Char_Type *a, SLsmg_Char_Type *b)
  788. {
  789. SLsmg_Char_Type *amax = a + Screen_Cols;
  790. while (a < amax) *a++ = *b++;
  791. }
  792. #endif
  793. #ifndef IBMPC_SYSTEM
  794. int SLsmg_Scroll_Hash_Border = 0;
  795. static unsigned long compute_hash (SLsmg_Char_Type *c, unsigned int n)
  796. {
  797. SLsmg_Char_Type *csave, *cmax;
  798. int is_blank = 2;
  799. c += SLsmg_Scroll_Hash_Border;
  800. csave = c;
  801. cmax = c + (n - SLsmg_Scroll_Hash_Border);
  802. while ((c < cmax) && is_blank)
  803. {
  804. if ((c->wchars[0] != 32) || (c->nchars != 1))
  805. is_blank--;
  806. c++;
  807. }
  808. if (is_blank) return 0;
  809. return _pSLstring_hash ((unsigned char *)csave, (unsigned char *)cmax);
  810. }
  811. static unsigned long Blank_Hash;
  812. static int try_scroll_down (int rmin, int rmax)
  813. {
  814. int i, r1, r2, di, j;
  815. unsigned long hash;
  816. int did_scroll;
  817. SLsmg_Color_Type color;
  818. SLsmg_Char_Type *tmp;
  819. int ignore;
  820. did_scroll = 0;
  821. for (i = rmax; i > rmin; i--)
  822. {
  823. hash = SL_Screen[i].new_hash;
  824. if (hash == Blank_Hash) continue;
  825. if ((hash == SL_Screen[i].old_hash)
  826. #if 0
  827. || ((i + 1 < Screen_Rows) && (hash == SL_Screen[i + 1].old_hash))
  828. || ((i - 1 > rmin) && (SL_Screen[i].old_hash == SL_Screen[i - 1].new_hash))
  829. #endif
  830. )
  831. continue;
  832. for (j = i - 1; j >= rmin; j--)
  833. {
  834. if (hash == SL_Screen[j].old_hash) break;
  835. }
  836. if (j < rmin) continue;
  837. r2 = i; /* end scroll region */
  838. di = i - j;
  839. j--;
  840. ignore = 0;
  841. while ((j >= rmin) && (SL_Screen[j].old_hash == SL_Screen[j + di].new_hash))
  842. {
  843. if (SL_Screen[j].old_hash == Blank_Hash) ignore++;
  844. j--;
  845. }
  846. r1 = j + 1;
  847. /* If this scroll only scrolls this line into place, don't do it.
  848. */
  849. if ((di > 1) && (r1 + di + ignore == r2)) continue;
  850. /* If there is anything in the scrolling region that is ok, abort the
  851. * scroll.
  852. */
  853. for (j = r1; j <= r2; j++)
  854. {
  855. if ((SL_Screen[j].old_hash != Blank_Hash)
  856. && (SL_Screen[j].old_hash == SL_Screen[j].new_hash))
  857. {
  858. /* See if the scroll is happens to scroll this one into place. */
  859. if ((j + di > r2) || (SL_Screen[j].old_hash != SL_Screen[j + di].new_hash))
  860. break;
  861. }
  862. }
  863. if (j <= r2) continue;
  864. color = This_Color; This_Color = 0;
  865. did_scroll = 1;
  866. (*tt_normal_video) ();
  867. (*tt_set_scroll_region) (r1, r2);
  868. (*tt_goto_rc) (0, 0);
  869. (*tt_reverse_index) (di);
  870. (*tt_reset_scroll_region) ();
  871. /* Now we have a hole in the screen.
  872. * Make the virtual screen look like it.
  873. *
  874. * Note that if the terminal does not support BCE, then we have
  875. * no idea what color the hole is. So, for this case, we do not
  876. * want to add Bce_Color_Offset to This_Color since if Bce_Color_Offset
  877. * is non-zero, then This_Color = 0 does not match any valid color
  878. * obtained by adding Bce_Color_Offset.
  879. */
  880. for (j = r1; j <= r2; j++) SL_Screen[j].flags = TOUCHED;
  881. while (di--)
  882. {
  883. tmp = SL_Screen[r2].old;
  884. for (j = r2; j > r1; j--)
  885. {
  886. SL_Screen[j].old = SL_Screen[j - 1].old;
  887. SL_Screen[j].old_hash = SL_Screen[j - 1].old_hash;
  888. }
  889. SL_Screen[r1].old = tmp;
  890. blank_line (SL_Screen[r1].old, Screen_Cols, 0x20);
  891. SL_Screen[r1].old_hash = Blank_Hash;
  892. r1++;
  893. }
  894. This_Color = color;
  895. }
  896. return did_scroll;
  897. }
  898. static int try_scroll_up (int rmin, int rmax)
  899. {
  900. int i, r1, r2, di, j;
  901. unsigned long hash;
  902. int did_scroll;
  903. SLsmg_Color_Type color;
  904. SLsmg_Char_Type *tmp;
  905. int ignore;
  906. did_scroll = 0;
  907. for (i = rmin; i < rmax; i++)
  908. {
  909. hash = SL_Screen[i].new_hash;
  910. if (hash == Blank_Hash) continue;
  911. if (hash == SL_Screen[i].old_hash)
  912. continue;
  913. /* find a match further down screen */
  914. for (j = i + 1; j <= rmax; j++)
  915. {
  916. if (hash == SL_Screen[j].old_hash) break;
  917. }
  918. if (j > rmax) continue;
  919. r1 = i; /* beg scroll region */
  920. di = j - i; /* number of lines to scroll */
  921. j++; /* since we know this is a match */
  922. /* find end of scroll region */
  923. ignore = 0;
  924. while ((j <= rmax) && (SL_Screen[j].old_hash == SL_Screen[j - di].new_hash))
  925. {
  926. if (SL_Screen[j].old_hash == Blank_Hash) ignore++;
  927. j++;
  928. }
  929. r2 = j - 1; /* end of scroll region */
  930. /* If this scroll only scrolls this line into place, don't do it.
  931. */
  932. if ((di > 1) && (r1 + di + ignore == r2)) continue;
  933. /* If there is anything in the scrolling region that is ok, abort the
  934. * scroll.
  935. */
  936. for (j = r1; j <= r2; j++)
  937. {
  938. if ((SL_Screen[j].old_hash != Blank_Hash)
  939. && (SL_Screen[j].old_hash == SL_Screen[j].new_hash))
  940. {
  941. if ((j - di < r1) || (SL_Screen[j].old_hash != SL_Screen[j - di].new_hash))
  942. break;
  943. }
  944. }
  945. if (j <= r2) continue;
  946. did_scroll = 1;
  947. /* See the above comments about BCE */
  948. color = This_Color; This_Color = 0;
  949. (*tt_normal_video) ();
  950. (*tt_set_scroll_region) (r1, r2);
  951. (*tt_goto_rc) (0, 0); /* relative to scroll region */
  952. (*tt_delete_nlines) (di);
  953. (*tt_reset_scroll_region) ();
  954. /* Now we have a hole in the screen. Make the virtual screen look
  955. * like it.
  956. */
  957. for (j = r1; j <= r2; j++) SL_Screen[j].flags = TOUCHED;
  958. while (di--)
  959. {
  960. tmp = SL_Screen[r1].old;
  961. for (j = r1; j < r2; j++)
  962. {
  963. SL_Screen[j].old = SL_Screen[j + 1].old;
  964. SL_Screen[j].old_hash = SL_Screen[j + 1].old_hash;
  965. }
  966. SL_Screen[r2].old = tmp;
  967. blank_line (SL_Screen[r2].old, Screen_Cols, ' ');
  968. SL_Screen[r2].old_hash = Blank_Hash;
  969. r2--;
  970. }
  971. This_Color = color;
  972. }
  973. return did_scroll;
  974. }
  975. static void try_scroll (void)
  976. {
  977. int r1, rmin, rmax;
  978. int num_up, num_down;
  979. /* find region limits. */
  980. for (rmax = Screen_Rows - 1; rmax > 0; rmax--)
  981. {
  982. if (SL_Screen[rmax].new_hash != SL_Screen[rmax].old_hash)
  983. {
  984. r1 = rmax - 1;
  985. if ((r1 == 0)
  986. || (SL_Screen[r1].new_hash != SL_Screen[r1].old_hash))
  987. break;
  988. rmax = r1;
  989. }
  990. }
  991. for (rmin = 0; rmin < rmax; rmin++)
  992. {
  993. if (SL_Screen[rmin].new_hash != SL_Screen[rmin].old_hash)
  994. {
  995. r1 = rmin + 1;
  996. if ((r1 == rmax)
  997. || (SL_Screen[r1].new_hash != SL_Screen[r1].old_hash))
  998. break;
  999. rmin = r1;
  1000. }
  1001. }
  1002. /* Below, we have two scrolling algorithms. The first has the effect of
  1003. * scrolling lines down. This is usually appropriate when one moves
  1004. * up the display, e.g., with the UP arrow. The second algorithm is
  1005. * appropriate for going the other way. It is important to choose the
  1006. * correct one.
  1007. */
  1008. num_up = 0;
  1009. for (r1 = rmin; r1 < rmax; r1++)
  1010. {
  1011. if (SL_Screen[r1].new_hash == SL_Screen[r1 + 1].old_hash)
  1012. num_up++;
  1013. }
  1014. num_down = 0;
  1015. for (r1 = rmax; r1 > rmin; r1--)
  1016. {
  1017. if (SL_Screen[r1 - 1].old_hash == SL_Screen[r1].new_hash)
  1018. num_down++;
  1019. }
  1020. if (num_up > num_down)
  1021. {
  1022. if (try_scroll_up (rmin, rmax))
  1023. return;
  1024. (void) try_scroll_down (rmin, rmax);
  1025. }
  1026. else
  1027. {
  1028. if (try_scroll_down (rmin, rmax))
  1029. return;
  1030. (void) try_scroll_up (rmin, rmax);
  1031. }
  1032. }
  1033. #endif /* NOT IBMPC_SYSTEM */
  1034. #ifdef REQUIRES_NON_BCE_SUPPORT
  1035. static void adjust_colors (void)
  1036. {
  1037. int bce;
  1038. unsigned int i;
  1039. bce = Bce_Color_Offset;
  1040. Bce_Color_Offset = _pSLtt_get_bce_color_offset ();
  1041. if (bce == Bce_Color_Offset)
  1042. return;
  1043. for (i = 0; i < Screen_Rows; i++)
  1044. {
  1045. SLsmg_Char_Type *s, *smax;
  1046. SL_Screen[i].flags |= TRASHED;
  1047. s = SL_Screen[i].neew;
  1048. smax = s + Screen_Cols;
  1049. while (s < smax)
  1050. {
  1051. SLsmg_Color_Type color = s->color;
  1052. int acs = color & SLSMG_ACS_MASK;
  1053. color = (color & SLSMG_COLOR_MASK) + (Bce_Color_Offset - bce);
  1054. if (color < SLSMG_MAX_COLORS)
  1055. s->color = color | acs;
  1056. s++;
  1057. }
  1058. }
  1059. }
  1060. #endif
  1061. void SLsmg_refresh (void)
  1062. {
  1063. unsigned int i;
  1064. #ifndef IBMPC_SYSTEM
  1065. int trashed = 0;
  1066. #endif
  1067. int r, c;
  1068. if (Smg_Inited == 0) return;
  1069. if (Screen_Trashed)
  1070. {
  1071. Cls_Flag = 1;
  1072. for (i = 0; i < Screen_Rows; i++)
  1073. SL_Screen[i].flags |= TRASHED;
  1074. #ifdef REQUIRES_NON_BCE_SUPPORT
  1075. adjust_colors ();
  1076. #endif
  1077. }
  1078. #ifndef IBMPC_SYSTEM
  1079. for (i = 0; i < Screen_Rows; i++)
  1080. {
  1081. if (SL_Screen[i].flags == 0) continue;
  1082. SL_Screen[i].new_hash = compute_hash (SL_Screen[i].neew, Screen_Cols);
  1083. trashed = 1;
  1084. }
  1085. #endif
  1086. if (Cls_Flag)
  1087. {
  1088. (*tt_normal_video) (); (*tt_cls) ();
  1089. }
  1090. #ifndef IBMPC_SYSTEM
  1091. else if (trashed && (*tt_Term_Cannot_Scroll == 0)) try_scroll ();
  1092. #endif
  1093. for (i = 0; i < Screen_Rows; i++)
  1094. {
  1095. if (SL_Screen[i].flags == 0) continue;
  1096. if (Cls_Flag || SL_Screen[i].flags & TRASHED)
  1097. {
  1098. SLsmg_Color_Type color = This_Color;
  1099. if (Cls_Flag == 0)
  1100. {
  1101. (*tt_goto_rc) (i, 0);
  1102. (*tt_del_eol) ();
  1103. }
  1104. This_Color = 0;
  1105. blank_line (SL_Screen[i].old, Screen_Cols, 0x20);
  1106. This_Color = color;
  1107. }
  1108. (*tt_smart_puts) (SL_Screen[i].neew, SL_Screen[i].old, Screen_Cols, i);
  1109. memcpy ((char *) SL_Screen[i].old, (char *) SL_Screen[i].neew,
  1110. Screen_Cols * sizeof (SLsmg_Char_Type));
  1111. SL_Screen[i].flags = 0;
  1112. #ifndef IBMPC_SYSTEM
  1113. SL_Screen[i].old_hash = SL_Screen[i].new_hash;
  1114. #endif
  1115. }
  1116. r = This_Row - Start_Row;
  1117. c = This_Col - Start_Col;
  1118. if (r < 0)
  1119. {
  1120. r = 0;
  1121. c = 0;
  1122. }
  1123. else if (r >= (int)Screen_Rows)
  1124. {
  1125. r = (int)Screen_Rows;
  1126. c = (int)Screen_Cols-1;
  1127. }
  1128. if (c < 0)
  1129. c = 0;
  1130. else if (c >= (int)Screen_Cols)
  1131. c = (int)Screen_Cols-1;
  1132. (*tt_goto_rc) (r,c);
  1133. (void) (*tt_flush_output) ();
  1134. Cls_Flag = 0;
  1135. Screen_Trashed = 0;
  1136. }
  1137. static int compute_clip (int row, int n, int box_start, int box_end,
  1138. int *rmin, int *rmax)
  1139. {
  1140. int row_max;
  1141. if (n < 0) return 0;
  1142. if (row >= box_end) return 0;
  1143. row_max = row + n;
  1144. if (row_max <= box_start) return 0;
  1145. if (row < box_start) row = box_start;
  1146. if (row_max >= box_end) row_max = box_end;
  1147. *rmin = row;
  1148. *rmax = row_max;
  1149. return 1;
  1150. }
  1151. void SLsmg_touch_lines (int row, unsigned int n)
  1152. {
  1153. int i;
  1154. int r1, r2;
  1155. /* Allow this function to be called even when we are not initialied.
  1156. * Calling this function is useful after calling SLtt_set_color
  1157. * to force the display to be redrawn
  1158. */
  1159. if (Smg_Inited == 0)
  1160. return;
  1161. if (0 == compute_clip (row, (int) n, Start_Row, Start_Row + Screen_Rows, &r1, &r2))
  1162. return;
  1163. r1 -= Start_Row;
  1164. r2 -= Start_Row;
  1165. for (i = r1; i < r2; i++)
  1166. {
  1167. SL_Screen[i].flags |= TRASHED;
  1168. }
  1169. }
  1170. void SLsmg_touch_screen (void)
  1171. {
  1172. Screen_Trashed = 1;
  1173. }
  1174. #ifndef IBMPC_SYSTEM
  1175. # define BLOCK_SIGNALS SLsig_block_signals ()
  1176. # define UNBLOCK_SIGNALS SLsig_unblock_signals ()
  1177. #else
  1178. # define BLOCK_SIGNALS (void)0
  1179. # define UNBLOCK_SIGNALS (void)0
  1180. #endif
  1181. static int Smg_Suspended;
  1182. int SLsmg_suspend_smg (void)
  1183. {
  1184. BLOCK_SIGNALS;
  1185. if (Smg_Suspended == 0)
  1186. {
  1187. (*tt_reset_video) ();
  1188. Smg_Suspended = 1;
  1189. }
  1190. UNBLOCK_SIGNALS;
  1191. return 0;
  1192. }
  1193. int SLsmg_resume_smg (void)
  1194. {
  1195. BLOCK_SIGNALS;
  1196. if (Smg_Suspended == 0)
  1197. {
  1198. UNBLOCK_SIGNALS;
  1199. return 0;
  1200. }
  1201. Smg_Suspended = 0;
  1202. if (-1 == (*tt_init_video) ())
  1203. {
  1204. UNBLOCK_SIGNALS;
  1205. return -1;
  1206. }
  1207. Cls_Flag = 1;
  1208. SLsmg_touch_screen ();
  1209. SLsmg_refresh ();
  1210. UNBLOCK_SIGNALS;
  1211. return 0;
  1212. }
  1213. static void reset_smg (void)
  1214. {
  1215. unsigned int i;
  1216. if (Smg_Inited == 0)
  1217. return;
  1218. for (i = 0; i < Screen_Rows; i++)
  1219. {
  1220. SLfree ((char *)SL_Screen[i].old);
  1221. SLfree ((char *)SL_Screen[i].neew);
  1222. SL_Screen[i].old = SL_Screen[i].neew = NULL;
  1223. }
  1224. This_Alt_Char = This_Color = 0;
  1225. Smg_Inited = 0;
  1226. }
  1227. static int init_smg (void)
  1228. {
  1229. unsigned int i, len;
  1230. SLsmg_Char_Type *old, *neew;
  1231. Smg_Inited = 0;
  1232. #ifdef REQUIRES_NON_BCE_SUPPORT
  1233. Bce_Color_Offset = _pSLtt_get_bce_color_offset ();
  1234. #endif
  1235. Screen_Rows = *tt_Screen_Rows;
  1236. if (Screen_Rows > SLTT_MAX_SCREEN_ROWS)
  1237. Screen_Rows = SLTT_MAX_SCREEN_ROWS;
  1238. Screen_Cols = *tt_Screen_Cols;
  1239. This_Col = This_Row = Start_Col = Start_Row = 0;
  1240. This_Alt_Char = 0;
  1241. SLsmg_set_color (0);
  1242. Cls_Flag = 1;
  1243. init_acs (ACS_MODE_AUTO);
  1244. len = Screen_Cols + 3;
  1245. for (i = 0; i < Screen_Rows; i++)
  1246. {
  1247. if ((NULL == (old = (SLsmg_Char_Type *) SLmalloc (sizeof(SLsmg_Char_Type) * len)))
  1248. || ((NULL == (neew = (SLsmg_Char_Type *) SLmalloc (sizeof(SLsmg_Char_Type) * len)))))
  1249. {
  1250. SLfree ((char *) old);
  1251. return -1;
  1252. }
  1253. blank_line (old, len, ' ');
  1254. blank_line (neew, len, ' ');
  1255. SL_Screen[i].old = old;
  1256. SL_Screen[i].neew = neew;
  1257. SL_Screen[i].flags = 0;
  1258. #ifndef IBMPC_SYSTEM
  1259. Blank_Hash = compute_hash (old, Screen_Cols);
  1260. SL_Screen[i].new_hash = SL_Screen[i].old_hash = Blank_Hash;
  1261. #endif
  1262. }
  1263. _pSLtt_color_changed_hook = SLsmg_touch_screen;
  1264. Screen_Trashed = 1;
  1265. Smg_Inited = 1;
  1266. return 0;
  1267. }
  1268. int SLsmg_init_smg (void)
  1269. {
  1270. int ret;
  1271. BLOCK_SIGNALS;
  1272. if (tt_Screen_Rows == NULL)
  1273. init_tt_symbols ();
  1274. if (Smg_Inited)
  1275. SLsmg_reset_smg ();
  1276. if (UTF8_Mode == -1)
  1277. UTF8_Mode = _pSLutf8_mode;
  1278. if (-1 == (*tt_init_video) ())
  1279. {
  1280. UNBLOCK_SIGNALS;
  1281. return -1;
  1282. }
  1283. if (-1 == (ret = init_smg ()))
  1284. (void) (*tt_reset_video)();
  1285. UNBLOCK_SIGNALS;
  1286. return ret;
  1287. }
  1288. int SLsmg_reinit_smg (void)
  1289. {
  1290. int ret;
  1291. if (Smg_Inited == 0)
  1292. return SLsmg_init_smg ();
  1293. BLOCK_SIGNALS;
  1294. reset_smg ();
  1295. ret = init_smg ();
  1296. UNBLOCK_SIGNALS;
  1297. return ret;
  1298. }
  1299. void SLsmg_reset_smg (void)
  1300. {
  1301. if (Smg_Inited == 0)
  1302. return;
  1303. BLOCK_SIGNALS;
  1304. reset_smg ();
  1305. (*tt_reset_video)();
  1306. UNBLOCK_SIGNALS;
  1307. }
  1308. void SLsmg_vprintf (char *fmt, va_list ap)
  1309. {
  1310. char buf[1024];
  1311. if (Smg_Inited == 0) return;
  1312. (void) SLvsnprintf (buf, sizeof (buf), fmt, ap);
  1313. SLsmg_write_string (buf);
  1314. }
  1315. void SLsmg_printf (char *fmt, ...)
  1316. {
  1317. va_list ap;
  1318. char *f;
  1319. if (Smg_Inited == 0) return;
  1320. va_start(ap, fmt);
  1321. f = fmt;
  1322. while (*f && (*f != '%'))
  1323. f++;
  1324. if (f != fmt)
  1325. SLsmg_write_chars ((SLuchar_Type *)fmt, (SLuchar_Type *)f);
  1326. if (*f != 0)
  1327. SLsmg_vprintf (f, ap);
  1328. va_end (ap);
  1329. }
  1330. void SLsmg_set_screen_start (int *r, int *c)
  1331. {
  1332. int orow = Start_Row, oc = Start_Col;
  1333. if (Smg_Inited == 0) return;
  1334. if (c == NULL) Start_Col = 0;
  1335. else
  1336. {
  1337. Start_Col = *c;
  1338. *c = oc;
  1339. }
  1340. if (r == NULL) Start_Row = 0;
  1341. else
  1342. {
  1343. Start_Row = *r;
  1344. *r = orow;
  1345. }
  1346. }
  1347. void SLsmg_draw_object (int r, int c, SLwchar_Type object)
  1348. {
  1349. This_Row = r; This_Col = c;
  1350. if (Smg_Inited == 0) return;
  1351. if (point_visible (1))
  1352. {
  1353. int color = This_Color;
  1354. This_Color |= SLSMG_ACS_MASK;
  1355. SLsmg_write_char (object);
  1356. This_Color = color;
  1357. }
  1358. This_Col = c + 1;
  1359. }
  1360. void SLsmg_draw_hline (unsigned int n)
  1361. {
  1362. static unsigned char hbuf[16];
  1363. int cmin, cmax;
  1364. int final_col = This_Col + (int) n;
  1365. int save_color;
  1366. if (Smg_Inited == 0) return;
  1367. if ((This_Row < Start_Row) || (This_Row >= Start_Row + (int)Screen_Rows)
  1368. || (0 == compute_clip (This_Col, n, Start_Col, Start_Col + (int)Screen_Cols,
  1369. &cmin, &cmax)))
  1370. {
  1371. This_Col = final_col;
  1372. return;
  1373. }
  1374. n = (unsigned int)(cmax - cmin);
  1375. save_color = This_Color;
  1376. This_Color |= SLSMG_ACS_MASK;
  1377. This_Col = cmin;
  1378. if (hbuf[0] == 0)
  1379. {
  1380. SLMEMSET ((char *) hbuf, SLSMG_HLINE_CHAR, 16);
  1381. }
  1382. while (n)
  1383. {
  1384. SLsmg_write_char (SLSMG_HLINE_CHAR);
  1385. n--;
  1386. }
  1387. This_Color = save_color;
  1388. This_Col = final_col;
  1389. }
  1390. void SLsmg_draw_vline (int n)
  1391. {
  1392. int c = This_Col, rmin, rmax;
  1393. int final_row = This_Row + n;
  1394. int save_color;
  1395. if (Smg_Inited == 0) return;
  1396. if (((c < Start_Col) || (c >= Start_Col + (int)Screen_Cols))
  1397. || (0 == compute_clip (This_Row, n, Start_Row,
  1398. Start_Row + (int)Screen_Rows,
  1399. &rmin, &rmax)))
  1400. {
  1401. This_Row = final_row;
  1402. return;
  1403. }
  1404. save_color = This_Color;
  1405. This_Color |= SLSMG_ACS_MASK;
  1406. for (This_Row = rmin; This_Row < rmax; This_Row++)
  1407. {
  1408. This_Col = c;
  1409. SLsmg_write_char (SLSMG_VLINE_CHAR);
  1410. }
  1411. This_Col = c; This_Row = final_row;
  1412. This_Color = save_color;
  1413. }
  1414. void SLsmg_draw_box (int r, int c, unsigned int dr, unsigned int dc)
  1415. {
  1416. if (Smg_Inited == 0) return;
  1417. if (!dr || !dc) return;
  1418. This_Row = r; This_Col = c;
  1419. dr--; dc--;
  1420. SLsmg_draw_hline (dc);
  1421. SLsmg_draw_vline (dr);
  1422. This_Row = r; This_Col = c;
  1423. SLsmg_draw_vline (dr);
  1424. SLsmg_draw_hline (dc);
  1425. SLsmg_draw_object (r, c, SLSMG_ULCORN_CHAR);
  1426. SLsmg_draw_object (r, c + (int) dc, SLSMG_URCORN_CHAR);
  1427. SLsmg_draw_object (r + (int) dr, c, SLSMG_LLCORN_CHAR);
  1428. SLsmg_draw_object (r + (int) dr, c + (int) dc, SLSMG_LRCORN_CHAR);
  1429. This_Row = r; This_Col = c;
  1430. }
  1431. void SLsmg_fill_region (int r, int c, unsigned int dr, unsigned int dc, SLwchar_Type wch)
  1432. {
  1433. static unsigned char buf[16];
  1434. unsigned char ubuf[16*SLUTF8_MAX_MBLEN];
  1435. unsigned char *b, *bmax;
  1436. int count;
  1437. int dcmax, rmax;
  1438. unsigned int wchlen;
  1439. if (Smg_Inited == 0) return;
  1440. SLsmg_gotorc (r, c);
  1441. r = This_Row; c = This_Col;
  1442. dcmax = Screen_Cols - This_Col;
  1443. if (dcmax < 0)
  1444. return;
  1445. if (dc > (unsigned int) dcmax) dc = (unsigned int) dcmax;
  1446. rmax = This_Row + (int)dr;
  1447. if (rmax > (int)Screen_Rows) rmax = (int)Screen_Rows;
  1448. if ((wch < 0x80)
  1449. || (UTF8_Mode == 0))
  1450. {
  1451. if (buf[0] != (unsigned char) wch)
  1452. memset ((char *) buf, (unsigned char) wch, sizeof(buf));
  1453. b = buf;
  1454. bmax = buf + sizeof (buf);
  1455. wchlen = 1;
  1456. }
  1457. else
  1458. {
  1459. unsigned int i;
  1460. b = ubuf;
  1461. bmax = SLutf8_encode (wch, b, SLUTF8_MAX_MBLEN);
  1462. if (bmax == NULL)
  1463. {
  1464. bmax = ubuf;
  1465. *bmax++ = '?';
  1466. }
  1467. wchlen = (unsigned int) (bmax - b);
  1468. for (i = 1; i < 16; i++)
  1469. {
  1470. memcpy (bmax, b, wchlen);
  1471. bmax += wchlen;
  1472. }
  1473. }
  1474. for (This_Row = r; This_Row < rmax; This_Row++)
  1475. {
  1476. This_Col = c;
  1477. count = dc / 16;
  1478. SLsmg_write_chars (b, b + wchlen * (dc % 16));
  1479. while (count-- > 0)
  1480. {
  1481. SLsmg_write_chars (b, bmax);
  1482. }
  1483. }
  1484. This_Row = r;
  1485. }
  1486. void SLsmg_forward (int n)
  1487. {
  1488. This_Col += n;
  1489. }
  1490. void
  1491. SLsmg_set_color_in_region (int color, int r, int c, unsigned int dr, unsigned int dc)
  1492. {
  1493. int cmax, rmax;
  1494. if (Smg_Inited == 0) return;
  1495. c -= Start_Col;
  1496. r -= Start_Row;
  1497. cmax = c + (int) dc;
  1498. rmax = r + (int) dr;
  1499. if (cmax > (int)Screen_Cols) cmax = (int)Screen_Cols;
  1500. if (rmax > (int)Screen_Rows) rmax = (int)Screen_Rows;
  1501. if (c < 0) c = 0;
  1502. if (r < 0) r = 0;
  1503. #ifdef REQUIRES_NON_BCE_SUPPORT
  1504. if (Bce_Color_Offset)
  1505. color += Bce_Color_Offset;
  1506. #endif
  1507. while (r < rmax)
  1508. {
  1509. SLsmg_Char_Type *cell, *cell_max;
  1510. SL_Screen[r].flags |= TOUCHED;
  1511. cell = SL_Screen[r].neew;
  1512. cell_max = cell + cmax;
  1513. cell += c;
  1514. while (cell < cell_max)
  1515. {
  1516. int acs = cell->color & SLSMG_ACS_MASK;
  1517. cell->color = color | acs;
  1518. cell++;
  1519. }
  1520. r++;
  1521. }
  1522. }
  1523. void SLsmg_set_terminal_info (SLsmg_Term_Type *tt)
  1524. {
  1525. if (tt == NULL) /* use default */
  1526. return;
  1527. if ((tt->tt_normal_video == NULL)
  1528. || (tt->tt_goto_rc == NULL)
  1529. || (tt->tt_cls == NULL)
  1530. || (tt->tt_del_eol == NULL)
  1531. || (tt->tt_smart_puts == NULL)
  1532. || (tt->tt_flush_output == NULL)
  1533. || (tt->tt_reset_video == NULL)
  1534. || (tt->tt_init_video == NULL)
  1535. #ifndef IBMPC_SYSTEM
  1536. || (tt->tt_set_scroll_region == NULL)
  1537. || (tt->tt_reverse_index == NULL)
  1538. || (tt->tt_reset_scroll_region == NULL)
  1539. || (tt->tt_delete_nlines == NULL)
  1540. /* Variables */
  1541. || (tt->tt_term_cannot_scroll == NULL)
  1542. || (tt->tt_has_alt_charset == NULL)
  1543. #if 0 /* These can be NULL */
  1544. || (tt->tt_use_blink_for_acs == NULL)
  1545. || (tt->tt_graphic_char_pairs == NULL)
  1546. #endif
  1547. || (tt->tt_screen_cols == NULL)
  1548. || (tt->tt_screen_rows == NULL)
  1549. #endif
  1550. )
  1551. SLang_exit_error ("The Terminal not powerful enough for S-Lang's SLsmg interface");
  1552. tt_normal_video = tt->tt_normal_video;
  1553. tt_goto_rc = tt->tt_goto_rc;
  1554. tt_cls = tt->tt_cls;
  1555. tt_del_eol = tt->tt_del_eol;
  1556. tt_smart_puts = tt->tt_smart_puts;
  1557. tt_flush_output = tt->tt_flush_output;
  1558. tt_reset_video = tt->tt_reset_video;
  1559. tt_init_video = tt->tt_init_video;
  1560. #ifndef IBMPC_SYSTEM
  1561. tt_set_scroll_region = tt->tt_set_scroll_region;
  1562. tt_reverse_index = tt->tt_reverse_index;
  1563. tt_reset_scroll_region = tt->tt_reset_scroll_region;
  1564. tt_delete_nlines = tt->tt_delete_nlines;
  1565. tt_Term_Cannot_Scroll = tt->tt_term_cannot_scroll;
  1566. #endif
  1567. tt_Has_Alt_Charset = tt->tt_has_alt_charset;
  1568. tt_Screen_Cols = tt->tt_screen_cols;
  1569. tt_Screen_Rows = tt->tt_screen_rows;
  1570. tt_unicode_ok = tt->unicode_ok;
  1571. }
  1572. /* The following routines are partially supported. */
  1573. void SLsmg_write_color_chars (SLsmg_Char_Type *s, unsigned int len)
  1574. {
  1575. #if 1
  1576. SLsmg_write_raw (s, len);
  1577. #else
  1578. SLsmg_Char_Type *smax, sh;
  1579. char buf[32], *b, *bmax;
  1580. int color, save_color;
  1581. if (Smg_Inited == 0) return;
  1582. smax = s + len;
  1583. b = buf;
  1584. bmax = b + sizeof (buf);
  1585. save_color = This_Color;
  1586. while (s < smax)
  1587. {
  1588. sh = *s++;
  1589. color = SLSMG_EXTRACT_COLOR(sh);
  1590. #ifdef REQUIRES_NON_BCE_SUPPORT
  1591. if (Bce_Color_Offset)
  1592. {
  1593. if (color & 0x80)
  1594. color = ((color & 0x7F) + Bce_Color_Offset) | 0x80;
  1595. else
  1596. color = ((color & 0x7F) + Bce_Color_Offset) & 0x7F;
  1597. }
  1598. #endif
  1599. if ((color != This_Color) || (b == bmax))
  1600. {
  1601. if (b != buf)
  1602. {
  1603. SLsmg_write_nchars (buf, (int) (b - buf));
  1604. b = buf;
  1605. }
  1606. This_Color = color;
  1607. }
  1608. *b++ = (char) SLSMG_EXTRACT_CHAR(sh);
  1609. }
  1610. if (b != buf)
  1611. SLsmg_write_nchars (buf, (unsigned int) (b - buf));
  1612. This_Color = save_color;
  1613. #endif
  1614. }
  1615. unsigned int SLsmg_strwidth (SLuchar_Type *u, SLuchar_Type *umax)
  1616. {
  1617. unsigned char display_8bit;
  1618. int utf8_mode = UTF8_Mode;
  1619. int col;
  1620. if (u == NULL)
  1621. return 0;
  1622. display_8bit = (unsigned char) SLsmg_Display_Eight_Bit;
  1623. if (utf8_mode)
  1624. display_8bit = 0xA0;
  1625. col = This_Col;
  1626. while (u < umax)
  1627. {
  1628. SLuchar_Type ch;
  1629. unsigned int nconsumed;
  1630. SLwchar_Type wc;
  1631. ch = *u;
  1632. if (ch < 0x80)
  1633. {
  1634. u++;
  1635. if ((ch >= 0x20) && (ch != 0x7F))
  1636. {
  1637. col++;
  1638. continue;
  1639. }
  1640. if ((ch == '\t') && (SLsmg_Tab_Width > 0))
  1641. {
  1642. if (col >= 0)
  1643. col = (1 + col/SLsmg_Tab_Width) * SLsmg_Tab_Width;
  1644. else
  1645. col = ((col + 1)/SLsmg_Tab_Width) * SLsmg_Tab_Width;
  1646. continue;
  1647. }
  1648. if ((ch == '\n')
  1649. && (SLsmg_Newline_Behavior != SLSMG_NEWLINE_PRINTABLE))
  1650. break;
  1651. if ((ch == 0x8) && SLsmg_Backspace_Moves)
  1652. {
  1653. col--;
  1654. continue;
  1655. }
  1656. #if SLSMG_HAS_EMBEDDED_ESCAPE
  1657. if ((ch == 033) && Embedded_Escape_Mode)
  1658. {
  1659. SLsmg_Color_Type color;
  1660. if (0 == parse_embedded_escape (u, umax, 0, &u, &color))
  1661. continue;
  1662. }
  1663. #endif
  1664. col += 2;
  1665. continue;
  1666. }
  1667. nconsumed = 1;
  1668. if ((utf8_mode == 0)
  1669. || (NULL == SLutf8_decode (u, umax, &wc, &nconsumed)))
  1670. {
  1671. if ((utf8_mode == 0)
  1672. && (display_8bit && (*u >= display_8bit)))
  1673. col++;
  1674. else
  1675. col += 4*nconsumed;
  1676. u += nconsumed;
  1677. continue;
  1678. }
  1679. u += nconsumed;
  1680. if (wc < (SLwchar_Type)display_8bit)
  1681. {
  1682. col += 4;
  1683. continue;
  1684. }
  1685. col += SLwchar_wcwidth (wc);
  1686. }
  1687. if (col < This_Col)
  1688. return 0;
  1689. return (unsigned int) (col - This_Col);
  1690. }
  1691. /* If the string u were written at the current positition, this function
  1692. * returns the number of bytes necessary to reach the specified width.
  1693. */
  1694. unsigned int SLsmg_strbytes (SLuchar_Type *u, SLuchar_Type *umax, unsigned int width)
  1695. {
  1696. SLuchar_Type *ustart;
  1697. unsigned char display_8bit;
  1698. int utf8_mode = UTF8_Mode;
  1699. int col, col_max;
  1700. if (u == NULL)
  1701. return 0;
  1702. display_8bit = (unsigned char) SLsmg_Display_Eight_Bit;
  1703. if (utf8_mode)
  1704. display_8bit = 0xA0;
  1705. col = This_Col;
  1706. col_max = col + width;
  1707. ustart = u;
  1708. while (u < umax)
  1709. {
  1710. SLuchar_Type ch;
  1711. SLwchar_Type wc;
  1712. unsigned int nconsumed = 1;
  1713. ch = *u;
  1714. if (ch < 0x80)
  1715. {
  1716. if ((ch >= 0x20) && (ch != 0x7F))
  1717. col++;
  1718. else if ((ch == '\t') && (SLsmg_Tab_Width > 0))
  1719. {
  1720. if (col >= 0)
  1721. col = (1 + col/SLsmg_Tab_Width) * SLsmg_Tab_Width;
  1722. else
  1723. col = ((col + 1)/SLsmg_Tab_Width) * SLsmg_Tab_Width;
  1724. }
  1725. else if ((ch == '\n')
  1726. && (SLsmg_Newline_Behavior != SLSMG_NEWLINE_PRINTABLE))
  1727. break;
  1728. else if ((ch == 0x8) && SLsmg_Backspace_Moves)
  1729. col--;
  1730. #if SLSMG_HAS_EMBEDDED_ESCAPE
  1731. else if ((ch == 033) && Embedded_Escape_Mode)
  1732. {
  1733. SLsmg_Color_Type color;
  1734. SLuchar_Type *u1 = u+1;
  1735. if (-1 == parse_embedded_escape (u1, umax, 0, &u1, &color))
  1736. col += 2;
  1737. nconsumed = (u1 - u);
  1738. }
  1739. #endif
  1740. else col += 2;
  1741. }
  1742. else if ((utf8_mode == 0)
  1743. || (NULL == SLutf8_decode (u, umax, &wc, &nconsumed)))
  1744. {
  1745. if ((utf8_mode == 0)
  1746. && (display_8bit && (*u >= display_8bit)))
  1747. col++;
  1748. else
  1749. col += 4*nconsumed; /* <XX> */
  1750. }
  1751. else if (wc < (SLwchar_Type)display_8bit)
  1752. col += 4;
  1753. else col += SLwchar_wcwidth (wc);
  1754. if (col >= col_max)
  1755. break;
  1756. u += nconsumed;
  1757. }
  1758. return (unsigned int) (u - ustart);
  1759. }
  1760. unsigned int SLsmg_read_raw (SLsmg_Char_Type *buf, unsigned int len)
  1761. {
  1762. unsigned int r, c;
  1763. if (Smg_Inited == 0) return 0;
  1764. if (0 == point_visible (1)) return 0;
  1765. r = (unsigned int) (This_Row - Start_Row);
  1766. c = (unsigned int) (This_Col - Start_Col);
  1767. if (c + len > (unsigned int) Screen_Cols)
  1768. len = (unsigned int) Screen_Cols - c;
  1769. memcpy ((char *) buf, (char *) (SL_Screen[r].neew + c), len * sizeof (SLsmg_Char_Type));
  1770. return len;
  1771. }
  1772. unsigned int SLsmg_write_raw (SLsmg_Char_Type *buf, unsigned int len)
  1773. {
  1774. unsigned int r, c;
  1775. SLsmg_Char_Type *dest;
  1776. if (Smg_Inited == 0) return 0;
  1777. if (0 == point_visible (1)) return 0;
  1778. r = (unsigned int) (This_Row - Start_Row);
  1779. c = (unsigned int) (This_Col - Start_Col);
  1780. if (c + len > (unsigned int) Screen_Cols)
  1781. len = (unsigned int) Screen_Cols - c;
  1782. dest = SL_Screen[r].neew + c;
  1783. if (0 != memcmp ((char *) dest, (char *) buf, len * sizeof (SLsmg_Char_Type)))
  1784. {
  1785. memcpy ((char *) dest, (char *) buf, len * sizeof (SLsmg_Char_Type));
  1786. SL_Screen[r].flags |= TOUCHED;
  1787. }
  1788. return len;
  1789. }
  1790. int SLsmg_char_at (SLsmg_Char_Type *cp)
  1791. {
  1792. if (Smg_Inited == 0) return -1;
  1793. if (point_visible (1))
  1794. {
  1795. SLsmg_Char_Type *c = &SL_Screen[This_Row - Start_Row].neew[This_Col - Start_Col];
  1796. if (c->nchars == 0)
  1797. return -1;
  1798. *cp = *c;
  1799. return 0;
  1800. }
  1801. return -1;
  1802. }
  1803. int SLsmg_utf8_enable (int mode)
  1804. {
  1805. if (mode == -1)
  1806. mode = _pSLutf8_mode;
  1807. return UTF8_Mode = mode;
  1808. }
  1809. int SLsmg_is_utf8_mode (void)
  1810. {
  1811. int mode = UTF8_Mode;
  1812. if (mode == -1)
  1813. mode = _pSLutf8_mode;
  1814. return mode;
  1815. }