teken_subr.h 31 KB

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