teken_subr.h 31 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348
  1. /*-
  2. * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
  3. *
  4. * Copyright (c) 2008-2009 Ed Schouten <ed@FreeBSD.org>
  5. * All rights reserved.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following conditions
  9. * are met:
  10. * 1. Redistributions of source code must retain the above copyright
  11. * notice, this list of conditions and the following disclaimer.
  12. * 2. Redistributions in binary form must reproduce the above copyright
  13. * notice, this list of conditions and the following disclaimer in the
  14. * documentation and/or other materials provided with the distribution.
  15. *
  16. * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
  17. * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  18. * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  19. * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
  20. * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  21. * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  22. * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  23. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  24. * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  25. * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  26. * SUCH DAMAGE.
  27. *
  28. * $FreeBSD$
  29. */
  30. static void teken_subr_cursor_up(teken_t *, unsigned int);
  31. static void teken_subr_erase_line(const teken_t *, unsigned int);
  32. static void teken_subr_regular_character(teken_t *, teken_char_t);
  33. static void teken_subr_reset_to_initial_state(teken_t *);
  34. static void teken_subr_save_cursor(teken_t *);
  35. static inline int
  36. teken_tab_isset(const teken_t *t, unsigned int col)
  37. {
  38. unsigned int b, o;
  39. if (col >= T_NUMCOL)
  40. return ((col % 8) == 0);
  41. b = col / (sizeof(unsigned int) * 8);
  42. o = col % (sizeof(unsigned int) * 8);
  43. return (t->t_tabstops[b] & (1U << o));
  44. }
  45. static inline void
  46. teken_tab_clear(teken_t *t, unsigned int col)
  47. {
  48. unsigned int b, o;
  49. if (col >= T_NUMCOL)
  50. return;
  51. b = col / (sizeof(unsigned int) * 8);
  52. o = col % (sizeof(unsigned int) * 8);
  53. t->t_tabstops[b] &= ~(1U << o);
  54. }
  55. static inline void
  56. teken_tab_set(teken_t *t, unsigned int col)
  57. {
  58. unsigned int b, o;
  59. if (col >= T_NUMCOL)
  60. return;
  61. b = col / (sizeof(unsigned int) * 8);
  62. o = col % (sizeof(unsigned int) * 8);
  63. t->t_tabstops[b] |= 1U << o;
  64. }
  65. static void
  66. teken_tab_default(teken_t *t)
  67. {
  68. unsigned int i;
  69. memset(t->t_tabstops, 0, T_NUMCOL / 8);
  70. for (i = 8; i < T_NUMCOL; i += 8)
  71. teken_tab_set(t, i);
  72. }
  73. static void
  74. teken_subr_do_scroll(const teken_t *t, int amount)
  75. {
  76. teken_rect_t tr;
  77. teken_pos_t tp;
  78. teken_assert(t->t_cursor.tp_row <= t->t_winsize.tp_row);
  79. teken_assert(t->t_scrollreg.ts_end <= t->t_winsize.tp_row);
  80. teken_assert(amount != 0);
  81. /* Copy existing data 1 line up. */
  82. if (amount > 0) {
  83. /* Scroll down. */
  84. /* Copy existing data up. */
  85. if (t->t_scrollreg.ts_begin + amount < t->t_scrollreg.ts_end) {
  86. tr.tr_begin.tp_row = t->t_scrollreg.ts_begin + amount;
  87. tr.tr_begin.tp_col = 0;
  88. tr.tr_end.tp_row = t->t_scrollreg.ts_end;
  89. tr.tr_end.tp_col = t->t_winsize.tp_col;
  90. tp.tp_row = t->t_scrollreg.ts_begin;
  91. tp.tp_col = 0;
  92. teken_funcs_copy(t, &tr, &tp);
  93. tr.tr_begin.tp_row = t->t_scrollreg.ts_end - amount;
  94. } else {
  95. tr.tr_begin.tp_row = t->t_scrollreg.ts_begin;
  96. }
  97. /* Clear the last lines. */
  98. tr.tr_begin.tp_col = 0;
  99. tr.tr_end.tp_row = t->t_scrollreg.ts_end;
  100. tr.tr_end.tp_col = t->t_winsize.tp_col;
  101. teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
  102. } else {
  103. /* Scroll up. */
  104. amount = -amount;
  105. /* Copy existing data down. */
  106. if (t->t_scrollreg.ts_begin + amount < t->t_scrollreg.ts_end) {
  107. tr.tr_begin.tp_row = t->t_scrollreg.ts_begin;
  108. tr.tr_begin.tp_col = 0;
  109. tr.tr_end.tp_row = t->t_scrollreg.ts_end - amount;
  110. tr.tr_end.tp_col = t->t_winsize.tp_col;
  111. tp.tp_row = t->t_scrollreg.ts_begin + amount;
  112. tp.tp_col = 0;
  113. teken_funcs_copy(t, &tr, &tp);
  114. tr.tr_end.tp_row = t->t_scrollreg.ts_begin + amount;
  115. } else {
  116. tr.tr_end.tp_row = t->t_scrollreg.ts_end;
  117. }
  118. /* Clear the first lines. */
  119. tr.tr_begin.tp_row = t->t_scrollreg.ts_begin;
  120. tr.tr_begin.tp_col = 0;
  121. tr.tr_end.tp_col = t->t_winsize.tp_col;
  122. teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
  123. }
  124. }
  125. static ssize_t
  126. teken_subr_do_cpr(const teken_t *t, unsigned int cmd, char response[16])
  127. {
  128. switch (cmd) {
  129. case 5: /* Operating status. */
  130. strcpy(response, "0n");
  131. return (2);
  132. case 6: { /* Cursor position. */
  133. int len;
  134. len = snprintf(response, 16, "%u;%uR",
  135. (t->t_cursor.tp_row - t->t_originreg.ts_begin) + 1,
  136. t->t_cursor.tp_col + 1);
  137. if (len >= 16)
  138. return (-1);
  139. return (len);
  140. }
  141. case 15: /* Printer status. */
  142. strcpy(response, "13n");
  143. return (3);
  144. case 25: /* UDK status. */
  145. strcpy(response, "20n");
  146. return (3);
  147. case 26: /* Keyboard status. */
  148. strcpy(response, "27;1n");
  149. return (5);
  150. default:
  151. teken_printf("Unknown DSR\n");
  152. return (-1);
  153. }
  154. }
  155. static void
  156. teken_subr_alignment_test(teken_t *t)
  157. {
  158. teken_rect_t tr;
  159. t->t_cursor.tp_row = t->t_cursor.tp_col = 0;
  160. t->t_scrollreg.ts_begin = 0;
  161. t->t_scrollreg.ts_end = t->t_winsize.tp_row;
  162. t->t_originreg = t->t_scrollreg;
  163. t->t_stateflags &= ~(TS_WRAPPED|TS_ORIGIN);
  164. teken_funcs_cursor(t);
  165. tr.tr_begin.tp_row = 0;
  166. tr.tr_begin.tp_col = 0;
  167. tr.tr_end = t->t_winsize;
  168. teken_funcs_fill(t, &tr, 'E', &t->t_defattr);
  169. }
  170. static void
  171. teken_subr_backspace(teken_t *t)
  172. {
  173. if (t->t_stateflags & TS_CONS25) {
  174. if (t->t_cursor.tp_col == 0) {
  175. if (t->t_cursor.tp_row == t->t_originreg.ts_begin)
  176. return;
  177. t->t_cursor.tp_row--;
  178. t->t_cursor.tp_col = t->t_winsize.tp_col - 1;
  179. } else {
  180. t->t_cursor.tp_col--;
  181. }
  182. } else {
  183. if (t->t_cursor.tp_col == 0)
  184. return;
  185. t->t_cursor.tp_col--;
  186. t->t_stateflags &= ~TS_WRAPPED;
  187. }
  188. teken_funcs_cursor(t);
  189. }
  190. static void
  191. teken_subr_bell(const teken_t *t)
  192. {
  193. teken_funcs_bell(t);
  194. }
  195. static void
  196. teken_subr_carriage_return(teken_t *t)
  197. {
  198. t->t_cursor.tp_col = 0;
  199. t->t_stateflags &= ~TS_WRAPPED;
  200. teken_funcs_cursor(t);
  201. }
  202. static void
  203. teken_subr_cursor_backward(teken_t *t, unsigned int ncols)
  204. {
  205. if (ncols > t->t_cursor.tp_col)
  206. t->t_cursor.tp_col = 0;
  207. else
  208. t->t_cursor.tp_col -= ncols;
  209. t->t_stateflags &= ~TS_WRAPPED;
  210. teken_funcs_cursor(t);
  211. }
  212. static void
  213. teken_subr_cursor_backward_tabulation(teken_t *t, unsigned int ntabs)
  214. {
  215. do {
  216. /* Stop when we've reached the beginning of the line. */
  217. if (t->t_cursor.tp_col == 0)
  218. break;
  219. t->t_cursor.tp_col--;
  220. /* Tab marker set. */
  221. if (teken_tab_isset(t, t->t_cursor.tp_col))
  222. ntabs--;
  223. } while (ntabs > 0);
  224. teken_funcs_cursor(t);
  225. }
  226. static void
  227. teken_subr_cursor_down(teken_t *t, unsigned int nrows)
  228. {
  229. if (t->t_cursor.tp_row + nrows >= t->t_scrollreg.ts_end)
  230. t->t_cursor.tp_row = t->t_scrollreg.ts_end - 1;
  231. else
  232. t->t_cursor.tp_row += nrows;
  233. t->t_stateflags &= ~TS_WRAPPED;
  234. teken_funcs_cursor(t);
  235. }
  236. static void
  237. teken_subr_cursor_forward(teken_t *t, unsigned int ncols)
  238. {
  239. if (t->t_cursor.tp_col + ncols >= t->t_winsize.tp_col)
  240. t->t_cursor.tp_col = t->t_winsize.tp_col - 1;
  241. else
  242. t->t_cursor.tp_col += ncols;
  243. t->t_stateflags &= ~TS_WRAPPED;
  244. teken_funcs_cursor(t);
  245. }
  246. static void
  247. teken_subr_cursor_forward_tabulation(teken_t *t, unsigned int ntabs)
  248. {
  249. do {
  250. /* Stop when we've reached the end of the line. */
  251. if (t->t_cursor.tp_col == t->t_winsize.tp_col - 1)
  252. break;
  253. t->t_cursor.tp_col++;
  254. /* Tab marker set. */
  255. if (teken_tab_isset(t, t->t_cursor.tp_col))
  256. ntabs--;
  257. } while (ntabs > 0);
  258. teken_funcs_cursor(t);
  259. }
  260. static void
  261. teken_subr_cursor_next_line(teken_t *t, unsigned int ncols)
  262. {
  263. t->t_cursor.tp_col = 0;
  264. teken_subr_cursor_down(t, ncols);
  265. }
  266. static void
  267. teken_subr_cursor_position(teken_t *t, unsigned int row, unsigned int col)
  268. {
  269. row = (row - 1) + t->t_originreg.ts_begin;
  270. t->t_cursor.tp_row = row < t->t_originreg.ts_end ?
  271. row : t->t_originreg.ts_end - 1;
  272. col--;
  273. t->t_cursor.tp_col = col < t->t_winsize.tp_col ?
  274. col : t->t_winsize.tp_col - 1;
  275. t->t_stateflags &= ~TS_WRAPPED;
  276. teken_funcs_cursor(t);
  277. }
  278. static void
  279. teken_subr_cursor_position_report(const teken_t *t, unsigned int cmd)
  280. {
  281. char response[18] = "\x1B[";
  282. ssize_t len;
  283. len = teken_subr_do_cpr(t, cmd, response + 2);
  284. if (len < 0)
  285. return;
  286. teken_funcs_respond(t, response, len + 2);
  287. }
  288. static void
  289. teken_subr_cursor_previous_line(teken_t *t, unsigned int ncols)
  290. {
  291. t->t_cursor.tp_col = 0;
  292. teken_subr_cursor_up(t, ncols);
  293. }
  294. static void
  295. teken_subr_cursor_up(teken_t *t, unsigned int nrows)
  296. {
  297. if (t->t_scrollreg.ts_begin + nrows >= t->t_cursor.tp_row)
  298. t->t_cursor.tp_row = t->t_scrollreg.ts_begin;
  299. else
  300. t->t_cursor.tp_row -= nrows;
  301. t->t_stateflags &= ~TS_WRAPPED;
  302. teken_funcs_cursor(t);
  303. }
  304. static void
  305. teken_subr_set_cursor_style(teken_t *t __unused, unsigned int style __unused)
  306. {
  307. /* TODO */
  308. /*
  309. * CSI Ps SP q
  310. * Set cursor style (DECSCUSR), VT520.
  311. * Ps = 0 -> blinking block.
  312. * Ps = 1 -> blinking block (default).
  313. * Ps = 2 -> steady block.
  314. * Ps = 3 -> blinking underline.
  315. * Ps = 4 -> steady underline.
  316. * Ps = 5 -> blinking bar (xterm).
  317. * Ps = 6 -> steady bar (xterm).
  318. */
  319. }
  320. static void
  321. teken_subr_delete_character(const teken_t *t, unsigned int ncols)
  322. {
  323. teken_rect_t tr;
  324. tr.tr_begin.tp_row = t->t_cursor.tp_row;
  325. tr.tr_end.tp_row = t->t_cursor.tp_row + 1;
  326. tr.tr_end.tp_col = t->t_winsize.tp_col;
  327. if (t->t_cursor.tp_col + ncols >= t->t_winsize.tp_col) {
  328. tr.tr_begin.tp_col = t->t_cursor.tp_col;
  329. } else {
  330. /* Copy characters to the left. */
  331. tr.tr_begin.tp_col = t->t_cursor.tp_col + ncols;
  332. teken_funcs_copy(t, &tr, &t->t_cursor);
  333. tr.tr_begin.tp_col = t->t_winsize.tp_col - ncols;
  334. }
  335. /* Blank trailing columns. */
  336. teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
  337. }
  338. static void
  339. teken_subr_delete_line(const teken_t *t, unsigned int nrows)
  340. {
  341. teken_rect_t tr;
  342. /* Ignore if outside scrolling region. */
  343. if (t->t_cursor.tp_row < t->t_scrollreg.ts_begin ||
  344. t->t_cursor.tp_row >= t->t_scrollreg.ts_end)
  345. return;
  346. tr.tr_begin.tp_col = 0;
  347. tr.tr_end.tp_row = t->t_scrollreg.ts_end;
  348. tr.tr_end.tp_col = t->t_winsize.tp_col;
  349. if (t->t_cursor.tp_row + nrows >= t->t_scrollreg.ts_end) {
  350. tr.tr_begin.tp_row = t->t_cursor.tp_row;
  351. } else {
  352. teken_pos_t tp;
  353. /* Copy rows up. */
  354. tr.tr_begin.tp_row = t->t_cursor.tp_row + nrows;
  355. tp.tp_row = t->t_cursor.tp_row;
  356. tp.tp_col = 0;
  357. teken_funcs_copy(t, &tr, &tp);
  358. tr.tr_begin.tp_row = t->t_scrollreg.ts_end - nrows;
  359. }
  360. /* Blank trailing rows. */
  361. teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
  362. }
  363. static void
  364. teken_subr_device_control_string(teken_t *t)
  365. {
  366. teken_printf("Unsupported device control string\n");
  367. t->t_stateflags |= TS_INSTRING;
  368. }
  369. static void
  370. teken_subr_device_status_report(const teken_t *t, unsigned int cmd)
  371. {
  372. char response[19] = "\x1B[?";
  373. ssize_t len;
  374. len = teken_subr_do_cpr(t, cmd, response + 3);
  375. if (len < 0)
  376. return;
  377. teken_funcs_respond(t, response, len + 3);
  378. }
  379. static void
  380. teken_subr_double_height_double_width_line_top(const teken_t *t)
  381. {
  382. (void)t;
  383. teken_printf("double height double width top\n");
  384. }
  385. static void
  386. teken_subr_double_height_double_width_line_bottom(const teken_t *t)
  387. {
  388. (void)t;
  389. teken_printf("double height double width bottom\n");
  390. }
  391. static void
  392. teken_subr_erase_character(const teken_t *t, unsigned int ncols)
  393. {
  394. teken_rect_t tr;
  395. tr.tr_begin = t->t_cursor;
  396. tr.tr_end.tp_row = t->t_cursor.tp_row + 1;
  397. if (t->t_cursor.tp_col + ncols >= t->t_winsize.tp_col)
  398. tr.tr_end.tp_col = t->t_winsize.tp_col;
  399. else
  400. tr.tr_end.tp_col = t->t_cursor.tp_col + ncols;
  401. teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
  402. }
  403. static void
  404. teken_subr_erase_display(const teken_t *t, unsigned int mode)
  405. {
  406. teken_rect_t r;
  407. r.tr_begin.tp_col = 0;
  408. r.tr_end.tp_col = t->t_winsize.tp_col;
  409. switch (mode) {
  410. case 1: /* Erase from the top to the cursor. */
  411. teken_subr_erase_line(t, 1);
  412. /* Erase lines above. */
  413. if (t->t_cursor.tp_row == 0)
  414. return;
  415. r.tr_begin.tp_row = 0;
  416. r.tr_end.tp_row = t->t_cursor.tp_row;
  417. break;
  418. case 2: /* Erase entire display. */
  419. r.tr_begin.tp_row = 0;
  420. r.tr_end.tp_row = t->t_winsize.tp_row;
  421. break;
  422. default: /* Erase from cursor to the bottom. */
  423. teken_subr_erase_line(t, 0);
  424. /* Erase lines below. */
  425. if (t->t_cursor.tp_row == t->t_winsize.tp_row - 1)
  426. return;
  427. r.tr_begin.tp_row = t->t_cursor.tp_row + 1;
  428. r.tr_end.tp_row = t->t_winsize.tp_row;
  429. break;
  430. }
  431. teken_funcs_fill(t, &r, BLANK, &t->t_curattr);
  432. }
  433. static void
  434. teken_subr_erase_line(const teken_t *t, unsigned int mode)
  435. {
  436. teken_rect_t r;
  437. r.tr_begin.tp_row = t->t_cursor.tp_row;
  438. r.tr_end.tp_row = t->t_cursor.tp_row + 1;
  439. switch (mode) {
  440. case 1: /* Erase from the beginning of the line to the cursor. */
  441. r.tr_begin.tp_col = 0;
  442. r.tr_end.tp_col = t->t_cursor.tp_col + 1;
  443. break;
  444. case 2: /* Erase entire line. */
  445. r.tr_begin.tp_col = 0;
  446. r.tr_end.tp_col = t->t_winsize.tp_col;
  447. break;
  448. default: /* Erase from cursor to the end of the line. */
  449. r.tr_begin.tp_col = t->t_cursor.tp_col;
  450. r.tr_end.tp_col = t->t_winsize.tp_col;
  451. break;
  452. }
  453. teken_funcs_fill(t, &r, BLANK, &t->t_curattr);
  454. }
  455. static void
  456. teken_subr_g0_scs_special_graphics(teken_t *t)
  457. {
  458. t->t_scs[0] = teken_scs_special_graphics;
  459. }
  460. static void
  461. teken_subr_g0_scs_uk_national(teken_t *t)
  462. {
  463. t->t_scs[0] = teken_scs_uk_national;
  464. }
  465. static void
  466. teken_subr_g0_scs_us_ascii(teken_t *t)
  467. {
  468. t->t_scs[0] = teken_scs_us_ascii;
  469. }
  470. static void
  471. teken_subr_g1_scs_special_graphics(teken_t *t)
  472. {
  473. t->t_scs[1] = teken_scs_special_graphics;
  474. }
  475. static void
  476. teken_subr_g1_scs_uk_national(teken_t *t)
  477. {
  478. t->t_scs[1] = teken_scs_uk_national;
  479. }
  480. static void
  481. teken_subr_g1_scs_us_ascii(teken_t *t)
  482. {
  483. t->t_scs[1] = teken_scs_us_ascii;
  484. }
  485. static void
  486. teken_subr_horizontal_position_absolute(teken_t *t, unsigned int col)
  487. {
  488. col--;
  489. t->t_cursor.tp_col = col < t->t_winsize.tp_col ?
  490. col : t->t_winsize.tp_col - 1;
  491. t->t_stateflags &= ~TS_WRAPPED;
  492. teken_funcs_cursor(t);
  493. }
  494. static void
  495. teken_subr_horizontal_tab(teken_t *t)
  496. {
  497. teken_subr_cursor_forward_tabulation(t, 1);
  498. }
  499. static void
  500. teken_subr_horizontal_tab_set(teken_t *t)
  501. {
  502. teken_tab_set(t, t->t_cursor.tp_col);
  503. }
  504. static void
  505. teken_subr_index(teken_t *t)
  506. {
  507. if (t->t_cursor.tp_row < t->t_scrollreg.ts_end - 1) {
  508. t->t_cursor.tp_row++;
  509. t->t_stateflags &= ~TS_WRAPPED;
  510. teken_funcs_cursor(t);
  511. } else {
  512. teken_subr_do_scroll(t, 1);
  513. }
  514. }
  515. static void
  516. teken_subr_insert_character(const teken_t *t, unsigned int ncols)
  517. {
  518. teken_rect_t tr;
  519. tr.tr_begin = t->t_cursor;
  520. tr.tr_end.tp_row = t->t_cursor.tp_row + 1;
  521. if (t->t_cursor.tp_col + ncols >= t->t_winsize.tp_col) {
  522. tr.tr_end.tp_col = t->t_winsize.tp_col;
  523. } else {
  524. teken_pos_t tp;
  525. /* Copy characters to the right. */
  526. tr.tr_end.tp_col = t->t_winsize.tp_col - ncols;
  527. tp.tp_row = t->t_cursor.tp_row;
  528. tp.tp_col = t->t_cursor.tp_col + ncols;
  529. teken_funcs_copy(t, &tr, &tp);
  530. tr.tr_end.tp_col = t->t_cursor.tp_col + ncols;
  531. }
  532. /* Blank current location. */
  533. teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
  534. }
  535. static void
  536. teken_subr_insert_line(const teken_t *t, unsigned int nrows)
  537. {
  538. teken_rect_t tr;
  539. /* Ignore if outside scrolling region. */
  540. if (t->t_cursor.tp_row < t->t_scrollreg.ts_begin ||
  541. t->t_cursor.tp_row >= t->t_scrollreg.ts_end)
  542. return;
  543. tr.tr_begin.tp_row = t->t_cursor.tp_row;
  544. tr.tr_begin.tp_col = 0;
  545. tr.tr_end.tp_col = t->t_winsize.tp_col;
  546. if (t->t_cursor.tp_row + nrows >= t->t_scrollreg.ts_end) {
  547. tr.tr_end.tp_row = t->t_scrollreg.ts_end;
  548. } else {
  549. teken_pos_t tp;
  550. /* Copy lines down. */
  551. tr.tr_end.tp_row = t->t_scrollreg.ts_end - nrows;
  552. tp.tp_row = t->t_cursor.tp_row + nrows;
  553. tp.tp_col = 0;
  554. teken_funcs_copy(t, &tr, &tp);
  555. tr.tr_end.tp_row = t->t_cursor.tp_row + nrows;
  556. }
  557. /* Blank current location. */
  558. teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
  559. }
  560. static void
  561. teken_subr_keypad_application_mode(const teken_t *t)
  562. {
  563. teken_funcs_param(t, TP_KEYPADAPP, 1);
  564. }
  565. static void
  566. teken_subr_keypad_numeric_mode(const teken_t *t)
  567. {
  568. teken_funcs_param(t, TP_KEYPADAPP, 0);
  569. }
  570. static void
  571. teken_subr_newline(teken_t *t)
  572. {
  573. t->t_cursor.tp_row++;
  574. if (t->t_cursor.tp_row >= t->t_scrollreg.ts_end) {
  575. teken_subr_do_scroll(t, 1);
  576. t->t_cursor.tp_row = t->t_scrollreg.ts_end - 1;
  577. }
  578. t->t_stateflags &= ~TS_WRAPPED;
  579. teken_funcs_cursor(t);
  580. }
  581. static void
  582. teken_subr_newpage(teken_t *t)
  583. {
  584. if (t->t_stateflags & TS_CONS25) {
  585. teken_rect_t tr;
  586. /* Clear screen. */
  587. tr.tr_begin.tp_row = t->t_originreg.ts_begin;
  588. tr.tr_begin.tp_col = 0;
  589. tr.tr_end.tp_row = t->t_originreg.ts_end;
  590. tr.tr_end.tp_col = t->t_winsize.tp_col;
  591. teken_funcs_fill(t, &tr, BLANK, &t->t_curattr);
  592. /* Cursor at top left. */
  593. t->t_cursor.tp_row = t->t_originreg.ts_begin;
  594. t->t_cursor.tp_col = 0;
  595. t->t_stateflags &= ~TS_WRAPPED;
  596. teken_funcs_cursor(t);
  597. } else {
  598. teken_subr_newline(t);
  599. }
  600. }
  601. static void
  602. teken_subr_next_line(teken_t *t)
  603. {
  604. t->t_cursor.tp_col = 0;
  605. teken_subr_newline(t);
  606. }
  607. static void
  608. teken_subr_operating_system_command(teken_t *t)
  609. {
  610. teken_printf("Unsupported operating system command\n");
  611. t->t_stateflags |= TS_INSTRING;
  612. }
  613. static void
  614. teken_subr_pan_down(const teken_t *t, unsigned int nrows)
  615. {
  616. teken_subr_do_scroll(t, (int)nrows);
  617. }
  618. static void
  619. teken_subr_pan_up(const teken_t *t, unsigned int nrows)
  620. {
  621. teken_subr_do_scroll(t, -(int)nrows);
  622. }
  623. static void
  624. teken_subr_primary_device_attributes(const teken_t *t, unsigned int request)
  625. {
  626. if (request == 0) {
  627. const char response[] = "\x1B[?1;2c";
  628. teken_funcs_respond(t, response, sizeof response - 1);
  629. } else {
  630. teken_printf("Unknown DA1\n");
  631. }
  632. }
  633. static void
  634. teken_subr_do_putchar(teken_t *t, const teken_pos_t *tp, teken_char_t c,
  635. int width)
  636. {
  637. t->t_last = c;
  638. if (t->t_stateflags & TS_INSERT &&
  639. tp->tp_col < t->t_winsize.tp_col - width) {
  640. teken_rect_t ctr;
  641. teken_pos_t ctp;
  642. /* Insert mode. Move existing characters to the right. */
  643. ctr.tr_begin = *tp;
  644. ctr.tr_end.tp_row = tp->tp_row + 1;
  645. ctr.tr_end.tp_col = t->t_winsize.tp_col - width;
  646. ctp.tp_row = tp->tp_row;
  647. ctp.tp_col = tp->tp_col + width;
  648. teken_funcs_copy(t, &ctr, &ctp);
  649. }
  650. teken_funcs_putchar(t, tp, c, &t->t_curattr);
  651. if (width == 2 && tp->tp_col + 1 < t->t_winsize.tp_col) {
  652. teken_pos_t tp2;
  653. teken_attr_t attr;
  654. /* Print second half of CJK fullwidth character. */
  655. tp2.tp_row = tp->tp_row;
  656. tp2.tp_col = tp->tp_col + 1;
  657. attr = t->t_curattr;
  658. attr.ta_format |= TF_CJK_RIGHT;
  659. teken_funcs_putchar(t, &tp2, c, &attr);
  660. }
  661. }
  662. static void
  663. teken_subr_regular_character(teken_t *t, teken_char_t c)
  664. {
  665. int width;
  666. if (t->t_stateflags & TS_8BIT) {
  667. if (!(t->t_stateflags & TS_CONS25) && (c <= 0x1b || c == 0x7f))
  668. return;
  669. c = teken_scs_process(t, c);
  670. width = 1;
  671. } else {
  672. c = teken_scs_process(t, c);
  673. width = teken_wcwidth(c);
  674. /* XXX: Don't process zero-width characters yet. */
  675. if (width <= 0)
  676. return;
  677. }
  678. if (t->t_stateflags & TS_CONS25) {
  679. teken_subr_do_putchar(t, &t->t_cursor, c, width);
  680. t->t_cursor.tp_col += width;
  681. if (t->t_cursor.tp_col >= t->t_winsize.tp_col) {
  682. if (t->t_cursor.tp_row == t->t_scrollreg.ts_end - 1) {
  683. /* Perform scrolling. */
  684. teken_subr_do_scroll(t, 1);
  685. } else {
  686. /* No scrolling needed. */
  687. if (t->t_cursor.tp_row <
  688. t->t_winsize.tp_row - 1)
  689. t->t_cursor.tp_row++;
  690. }
  691. t->t_cursor.tp_col = 0;
  692. }
  693. } else if (t->t_stateflags & TS_AUTOWRAP &&
  694. ((t->t_stateflags & TS_WRAPPED &&
  695. t->t_cursor.tp_col + 1 == t->t_winsize.tp_col) ||
  696. t->t_cursor.tp_col + width > t->t_winsize.tp_col)) {
  697. teken_pos_t tp;
  698. /*
  699. * Perform line wrapping, if:
  700. * - Autowrapping is enabled, and
  701. * - We're in the wrapped state at the last column, or
  702. * - The character to be printed does not fit anymore.
  703. */
  704. if (t->t_cursor.tp_row == t->t_scrollreg.ts_end - 1) {
  705. /* Perform scrolling. */
  706. teken_subr_do_scroll(t, 1);
  707. tp.tp_row = t->t_scrollreg.ts_end - 1;
  708. } else {
  709. /* No scrolling needed. */
  710. tp.tp_row = t->t_cursor.tp_row + 1;
  711. if (tp.tp_row == t->t_winsize.tp_row) {
  712. /*
  713. * Corner case: regular character
  714. * outside scrolling region, but at the
  715. * bottom of the screen.
  716. */
  717. teken_subr_do_putchar(t, &t->t_cursor,
  718. c, width);
  719. return;
  720. }
  721. }
  722. tp.tp_col = 0;
  723. teken_subr_do_putchar(t, &tp, c, width);
  724. t->t_cursor.tp_row = tp.tp_row;
  725. t->t_cursor.tp_col = width;
  726. t->t_stateflags &= ~TS_WRAPPED;
  727. } else {
  728. /* No line wrapping needed. */
  729. teken_subr_do_putchar(t, &t->t_cursor, c, width);
  730. t->t_cursor.tp_col += width;
  731. if (t->t_cursor.tp_col >= t->t_winsize.tp_col) {
  732. t->t_stateflags |= TS_WRAPPED;
  733. t->t_cursor.tp_col = t->t_winsize.tp_col - 1;
  734. } else {
  735. t->t_stateflags &= ~TS_WRAPPED;
  736. }
  737. }
  738. teken_funcs_cursor(t);
  739. }
  740. static void
  741. teken_subr_reset_dec_mode(teken_t *t, unsigned int cmd)
  742. {
  743. switch (cmd) {
  744. case 1: /* Cursor keys mode. */
  745. t->t_stateflags &= ~TS_CURSORKEYS;
  746. break;
  747. case 2: /* DECANM: ANSI/VT52 mode. */
  748. teken_printf("DECRST VT52\n");
  749. break;
  750. case 3: /* 132 column mode. */
  751. teken_funcs_param(t, TP_132COLS, 0);
  752. teken_subr_reset_to_initial_state(t);
  753. break;
  754. case 5: /* Inverse video. */
  755. teken_printf("DECRST inverse video\n");
  756. break;
  757. case 6: /* Origin mode. */
  758. t->t_stateflags &= ~TS_ORIGIN;
  759. t->t_originreg.ts_begin = 0;
  760. t->t_originreg.ts_end = t->t_winsize.tp_row;
  761. t->t_cursor.tp_row = t->t_cursor.tp_col = 0;
  762. t->t_stateflags &= ~TS_WRAPPED;
  763. teken_funcs_cursor(t);
  764. break;
  765. case 7: /* Autowrap mode. */
  766. t->t_stateflags &= ~TS_AUTOWRAP;
  767. break;
  768. case 8: /* Autorepeat mode. */
  769. teken_funcs_param(t, TP_AUTOREPEAT, 0);
  770. break;
  771. case 25: /* Hide cursor. */
  772. teken_funcs_param(t, TP_SHOWCURSOR, 0);
  773. break;
  774. case 40: /* Disallow 132 columns. */
  775. teken_printf("DECRST allow 132\n");
  776. break;
  777. case 45: /* Disable reverse wraparound. */
  778. teken_printf("DECRST reverse wraparound\n");
  779. break;
  780. case 47: /* Switch to alternate buffer. */
  781. teken_printf("Switch to alternate buffer\n");
  782. break;
  783. case 1000: /* Mouse input. */
  784. teken_funcs_param(t, TP_MOUSE, 0);
  785. break;
  786. default:
  787. teken_printf("Unknown DECRST: %u\n", cmd);
  788. }
  789. }
  790. static void
  791. teken_subr_reset_mode(teken_t *t, unsigned int cmd)
  792. {
  793. switch (cmd) {
  794. case 4:
  795. t->t_stateflags &= ~TS_INSERT;
  796. break;
  797. default:
  798. teken_printf("Unknown reset mode: %u\n", cmd);
  799. }
  800. }
  801. static void
  802. teken_subr_do_resize(teken_t *t)
  803. {
  804. t->t_scrollreg.ts_begin = 0;
  805. t->t_scrollreg.ts_end = t->t_winsize.tp_row;
  806. t->t_originreg = t->t_scrollreg;
  807. }
  808. static void
  809. teken_subr_do_reset(teken_t *t)
  810. {
  811. t->t_curattr = t->t_defattr;
  812. t->t_cursor.tp_row = t->t_cursor.tp_col = 0;
  813. t->t_scrollreg.ts_begin = 0;
  814. t->t_scrollreg.ts_end = t->t_winsize.tp_row;
  815. t->t_originreg = t->t_scrollreg;
  816. t->t_stateflags &= TS_8BIT | TS_CONS25 | TS_CONS25KEYS;
  817. t->t_stateflags |= TS_AUTOWRAP;
  818. t->t_scs[0] = teken_scs_us_ascii;
  819. t->t_scs[1] = teken_scs_us_ascii;
  820. t->t_curscs = 0;
  821. teken_subr_save_cursor(t);
  822. teken_tab_default(t);
  823. }
  824. static void
  825. teken_subr_reset_to_initial_state(teken_t *t)
  826. {
  827. teken_subr_do_reset(t);
  828. teken_subr_erase_display(t, 2);
  829. teken_funcs_param(t, TP_SHOWCURSOR, 1);
  830. teken_funcs_cursor(t);
  831. }
  832. static void
  833. teken_subr_restore_cursor(teken_t *t)
  834. {
  835. t->t_cursor = t->t_saved_cursor;
  836. t->t_curattr = t->t_saved_curattr;
  837. t->t_scs[t->t_curscs] = t->t_saved_curscs;
  838. t->t_stateflags &= ~TS_WRAPPED;
  839. /* Get out of origin mode when the cursor is moved outside. */
  840. if (t->t_cursor.tp_row < t->t_originreg.ts_begin ||
  841. t->t_cursor.tp_row >= t->t_originreg.ts_end) {
  842. t->t_stateflags &= ~TS_ORIGIN;
  843. t->t_originreg.ts_begin = 0;
  844. t->t_originreg.ts_end = t->t_winsize.tp_row;
  845. }
  846. teken_funcs_cursor(t);
  847. }
  848. static void
  849. teken_subr_reverse_index(teken_t *t)
  850. {
  851. if (t->t_cursor.tp_row > t->t_scrollreg.ts_begin) {
  852. t->t_cursor.tp_row--;
  853. t->t_stateflags &= ~TS_WRAPPED;
  854. teken_funcs_cursor(t);
  855. } else {
  856. teken_subr_do_scroll(t, -1);
  857. }
  858. }
  859. static void
  860. teken_subr_save_cursor(teken_t *t)
  861. {
  862. t->t_saved_cursor = t->t_cursor;
  863. t->t_saved_curattr = t->t_curattr;
  864. t->t_saved_curscs = t->t_scs[t->t_curscs];
  865. }
  866. static void
  867. teken_subr_secondary_device_attributes(const teken_t *t, unsigned int request)
  868. {
  869. if (request == 0) {
  870. const char response[] = "\x1B[>0;10;0c";
  871. teken_funcs_respond(t, response, sizeof response - 1);
  872. } else {
  873. teken_printf("Unknown DA2\n");
  874. }
  875. }
  876. static void
  877. teken_subr_set_dec_mode(teken_t *t, unsigned int cmd)
  878. {
  879. switch (cmd) {
  880. case 1: /* Cursor keys mode. */
  881. t->t_stateflags |= TS_CURSORKEYS;
  882. break;
  883. case 2: /* DECANM: ANSI/VT52 mode. */
  884. teken_printf("DECSET VT52\n");
  885. break;
  886. case 3: /* 132 column mode. */
  887. teken_funcs_param(t, TP_132COLS, 1);
  888. teken_subr_reset_to_initial_state(t);
  889. break;
  890. case 5: /* Inverse video. */
  891. teken_printf("DECSET inverse video\n");
  892. break;
  893. case 6: /* Origin mode. */
  894. t->t_stateflags |= TS_ORIGIN;
  895. t->t_originreg = t->t_scrollreg;
  896. t->t_cursor.tp_row = t->t_scrollreg.ts_begin;
  897. t->t_cursor.tp_col = 0;
  898. t->t_stateflags &= ~TS_WRAPPED;
  899. teken_funcs_cursor(t);
  900. break;
  901. case 7: /* Autowrap mode. */
  902. t->t_stateflags |= TS_AUTOWRAP;
  903. break;
  904. case 8: /* Autorepeat mode. */
  905. teken_funcs_param(t, TP_AUTOREPEAT, 1);
  906. break;
  907. case 25: /* Display cursor. */
  908. teken_funcs_param(t, TP_SHOWCURSOR, 1);
  909. break;
  910. case 40: /* Allow 132 columns. */
  911. teken_printf("DECSET allow 132\n");
  912. break;
  913. case 45: /* Enable reverse wraparound. */
  914. teken_printf("DECSET reverse wraparound\n");
  915. break;
  916. case 47: /* Switch to alternate buffer. */
  917. teken_printf("Switch away from alternate buffer\n");
  918. break;
  919. case 1000: /* Mouse input. */
  920. teken_funcs_param(t, TP_MOUSE, 1);
  921. break;
  922. default:
  923. teken_printf("Unknown DECSET: %u\n", cmd);
  924. }
  925. }
  926. static void
  927. teken_subr_set_mode(teken_t *t, unsigned int cmd)
  928. {
  929. switch (cmd) {
  930. case 4:
  931. teken_printf("Insert mode\n");
  932. t->t_stateflags |= TS_INSERT;
  933. break;
  934. default:
  935. teken_printf("Unknown set mode: %u\n", cmd);
  936. }
  937. }
  938. static void
  939. teken_subr_set_graphic_rendition(teken_t *t, unsigned int ncmds,
  940. const unsigned int cmds[])
  941. {
  942. unsigned int i, n;
  943. /* No attributes means reset. */
  944. if (ncmds == 0) {
  945. t->t_curattr = t->t_defattr;
  946. return;
  947. }
  948. for (i = 0; i < ncmds; i++) {
  949. n = cmds[i];
  950. switch (n) {
  951. case 0: /* Reset. */
  952. t->t_curattr = t->t_defattr;
  953. break;
  954. case 1: /* Bold. */
  955. t->t_curattr.ta_format |= TF_BOLD;
  956. break;
  957. case 4: /* Underline. */
  958. t->t_curattr.ta_format |= TF_UNDERLINE;
  959. break;
  960. case 5: /* Blink. */
  961. t->t_curattr.ta_format |= TF_BLINK;
  962. break;
  963. case 7: /* Reverse. */
  964. t->t_curattr.ta_format |= TF_REVERSE;
  965. break;
  966. case 22: /* Remove bold. */
  967. t->t_curattr.ta_format &= ~TF_BOLD;
  968. break;
  969. case 24: /* Remove underline. */
  970. t->t_curattr.ta_format &= ~TF_UNDERLINE;
  971. break;
  972. case 25: /* Remove blink. */
  973. t->t_curattr.ta_format &= ~TF_BLINK;
  974. break;
  975. case 27: /* Remove reverse. */
  976. t->t_curattr.ta_format &= ~TF_REVERSE;
  977. break;
  978. case 30: /* Set foreground color: black */
  979. case 31: /* Set foreground color: red */
  980. case 32: /* Set foreground color: green */
  981. case 33: /* Set foreground color: brown */
  982. case 34: /* Set foreground color: blue */
  983. case 35: /* Set foreground color: magenta */
  984. case 36: /* Set foreground color: cyan */
  985. case 37: /* Set foreground color: white */
  986. t->t_curattr.ta_fgcolor = n - 30;
  987. break;
  988. case 38: /* Set foreground color: 256 color mode */
  989. if (i + 2 >= ncmds || cmds[i + 1] != 5)
  990. continue;
  991. t->t_curattr.ta_fgcolor = cmds[i + 2];
  992. i += 2;
  993. break;
  994. case 39: /* Set default foreground color. */
  995. t->t_curattr.ta_fgcolor = t->t_defattr.ta_fgcolor;
  996. break;
  997. case 40: /* Set background color: black */
  998. case 41: /* Set background color: red */
  999. case 42: /* Set background color: green */
  1000. case 43: /* Set background color: brown */
  1001. case 44: /* Set background color: blue */
  1002. case 45: /* Set background color: magenta */
  1003. case 46: /* Set background color: cyan */
  1004. case 47: /* Set background color: white */
  1005. t->t_curattr.ta_bgcolor = n - 40;
  1006. break;
  1007. case 48: /* Set background color: 256 color mode */
  1008. if (i + 2 >= ncmds || cmds[i + 1] != 5)
  1009. continue;
  1010. t->t_curattr.ta_bgcolor = cmds[i + 2];
  1011. i += 2;
  1012. break;
  1013. case 49: /* Set default background color. */
  1014. t->t_curattr.ta_bgcolor = t->t_defattr.ta_bgcolor;
  1015. break;
  1016. case 90: /* Set bright foreground color: black */
  1017. case 91: /* Set bright foreground color: red */
  1018. case 92: /* Set bright foreground color: green */
  1019. case 93: /* Set bright foreground color: brown */
  1020. case 94: /* Set bright foreground color: blue */
  1021. case 95: /* Set bright foreground color: magenta */
  1022. case 96: /* Set bright foreground color: cyan */
  1023. case 97: /* Set bright foreground color: white */
  1024. t->t_curattr.ta_fgcolor = (n - 90) + 8;
  1025. break;
  1026. case 100: /* Set bright background color: black */
  1027. case 101: /* Set bright background color: red */
  1028. case 102: /* Set bright background color: green */
  1029. case 103: /* Set bright background color: brown */
  1030. case 104: /* Set bright background color: blue */
  1031. case 105: /* Set bright background color: magenta */
  1032. case 106: /* Set bright background color: cyan */
  1033. case 107: /* Set bright background color: white */
  1034. t->t_curattr.ta_bgcolor = (n - 100) + 8;
  1035. break;
  1036. default:
  1037. teken_printf("unsupported attribute %u\n", n);
  1038. }
  1039. }
  1040. }
  1041. static void
  1042. teken_subr_set_top_and_bottom_margins(teken_t *t, unsigned int top,
  1043. unsigned int bottom)
  1044. {
  1045. /* Adjust top row number. */
  1046. if (top > 0)
  1047. top--;
  1048. /* Adjust bottom row number. */
  1049. if (bottom == 0 || bottom > t->t_winsize.tp_row)
  1050. bottom = t->t_winsize.tp_row;
  1051. /* Invalid arguments. */
  1052. if (top >= bottom - 1) {
  1053. top = 0;
  1054. bottom = t->t_winsize.tp_row;
  1055. }
  1056. /* Apply scrolling region. */
  1057. t->t_scrollreg.ts_begin = top;
  1058. t->t_scrollreg.ts_end = bottom;
  1059. if (t->t_stateflags & TS_ORIGIN)
  1060. t->t_originreg = t->t_scrollreg;
  1061. /* Home cursor to the top left of the scrolling region. */
  1062. t->t_cursor.tp_row = t->t_originreg.ts_begin;
  1063. t->t_cursor.tp_col = 0;
  1064. t->t_stateflags &= ~TS_WRAPPED;
  1065. teken_funcs_cursor(t);
  1066. }
  1067. static void
  1068. teken_subr_single_height_double_width_line(const teken_t *t)
  1069. {
  1070. (void)t;
  1071. teken_printf("single height double width???\n");
  1072. }
  1073. static void
  1074. teken_subr_single_height_single_width_line(const teken_t *t)
  1075. {
  1076. (void)t;
  1077. teken_printf("single height single width???\n");
  1078. }
  1079. static void
  1080. teken_subr_string_terminator(const teken_t *t)
  1081. {
  1082. (void)t;
  1083. /*
  1084. * Strings are already terminated in teken_input_char() when ^[
  1085. * is inserted.
  1086. */
  1087. }
  1088. static void
  1089. teken_subr_tab_clear(teken_t *t, unsigned int cmd)
  1090. {
  1091. switch (cmd) {
  1092. case 0:
  1093. teken_tab_clear(t, t->t_cursor.tp_col);
  1094. break;
  1095. case 3:
  1096. memset(t->t_tabstops, 0, T_NUMCOL / 8);
  1097. break;
  1098. default:
  1099. break;
  1100. }
  1101. }
  1102. static void
  1103. teken_subr_vertical_position_absolute(teken_t *t, unsigned int row)
  1104. {
  1105. row = (row - 1) + t->t_originreg.ts_begin;
  1106. t->t_cursor.tp_row = row < t->t_originreg.ts_end ?
  1107. row : t->t_originreg.ts_end - 1;
  1108. t->t_stateflags &= ~TS_WRAPPED;
  1109. teken_funcs_cursor(t);
  1110. }
  1111. static void
  1112. teken_subr_repeat_last_graphic_char(teken_t *t, unsigned int rpts)
  1113. {
  1114. unsigned int max_repetitions;
  1115. max_repetitions = t->t_winsize.tp_row * t->t_winsize.tp_col;
  1116. if (rpts > max_repetitions)
  1117. rpts = max_repetitions;
  1118. for (; t->t_last != 0 && rpts > 0; rpts--)
  1119. teken_subr_regular_character(t, t->t_last);
  1120. }