TermBuffer.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335
  1. /*
  2. * CDE - Common Desktop Environment
  3. *
  4. * Copyright (c) 1993-2012, The Open Group. All rights reserved.
  5. *
  6. * These libraries and programs are free software; you can
  7. * redistribute them and/or modify them under the terms of the GNU
  8. * Lesser General Public License as published by the Free Software
  9. * Foundation; either version 2 of the License, or (at your option)
  10. * any later version.
  11. *
  12. * These libraries and programs are distributed in the hope that
  13. * they will be useful, but WITHOUT ANY WARRANTY; without even the
  14. * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  15. * PURPOSE. See the GNU Lesser General Public License for more
  16. * details.
  17. *
  18. * You should have received a copy of the GNU Lesser General Public
  19. * License along with these libraries and programs; if not, write
  20. * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
  21. * Floor, Boston, MA 02110-1301 USA
  22. */
  23. /* *
  24. * (c) Copyright 1993, 1994, 1996 Hewlett-Packard Company *
  25. * (c) Copyright 1993, 1994, 1996 International Business Machines Corp. *
  26. * (c) Copyright 1993, 1994, 1996 Sun Microsystems, Inc. *
  27. * (c) Copyright 1993, 1994, 1996 Novell, Inc. *
  28. * (c) Copyright 1996 Digital Equipment Corporation. *
  29. * (c) Copyright 1996 FUJITSU LIMITED. *
  30. * (c) Copyright 1996 Hitachi. *
  31. */
  32. #define USE_MEMCPY /* use memcpy for line movement... */
  33. #include <Xm/Xm.h>
  34. #include "TermPrim.h"
  35. #include "TermHeader.h" /* for MIN/MAX */
  36. #include "TermBufferP.h"
  37. #include "TermEnhance.h"
  38. /*
  39. ** clear "count" enhancements starting at startCol
  40. */
  41. static void
  42. clearEnhancements
  43. (
  44. TermBuffer tb,
  45. short row,
  46. short startCol,
  47. short count
  48. );
  49. static void
  50. insertEnhancements
  51. (
  52. TermBuffer tb,
  53. short row,
  54. short col,
  55. short insertCount
  56. );
  57. static void
  58. deleteEnhancement
  59. (
  60. TermBuffer tb,
  61. short row,
  62. short col
  63. );
  64. static void
  65. _DtTermClearEnhancements
  66. (
  67. TermBuffer tb,
  68. short row,
  69. short col,
  70. short count
  71. );
  72. static int
  73. _DtTermSetEnhancement
  74. (
  75. TermBuffer tb,
  76. short row,
  77. short col,
  78. unsigned char id,
  79. enhValue value
  80. );
  81. static Boolean
  82. _DtTermGetEnhancement
  83. (
  84. const TermBuffer tb,
  85. const short row,
  86. const short col,
  87. enhValue **enhancements,
  88. short *count,
  89. const countSpec countWhich
  90. );
  91. static termChar *
  92. _DtTermGetCharacterPointer
  93. (
  94. TermBuffer tb,
  95. short row,
  96. short col
  97. );
  98. static void
  99. _DtTermInsertEnhancements
  100. (
  101. const TermBuffer tb,
  102. const short row,
  103. const short col,
  104. short insertCount,
  105. const Boolean insertFlag
  106. );
  107. static Boolean
  108. _DtTermBufferCreateEnhancement
  109. (
  110. TermBuffer tb,
  111. short row,
  112. short col
  113. );
  114. static void
  115. _DtTermBufferResize
  116. (
  117. TermBuffer newTb,
  118. short *newRows,
  119. short *newCols
  120. );
  121. static void
  122. _DtTermDeleteEnhancement
  123. (
  124. TermBuffer tb,
  125. short row,
  126. short col,
  127. short width
  128. );
  129. static short
  130. _DtTermInsert
  131. (
  132. TermBuffer tb,
  133. short row,
  134. short col,
  135. termChar *newChars,
  136. short numChars,
  137. Boolean insertFlag, /* if TRUE, insert, else overwrite */
  138. termChar **returnChars, /* pointer to overflow buffer */
  139. short *returnCount /* count of characters in overflow buffer */
  140. );
  141. static Boolean
  142. _DtTermSetLineLength
  143. (
  144. TermBuffer tb,
  145. short row,
  146. short newLength
  147. );
  148. static short
  149. _DtTermGetLineLength
  150. (
  151. TermBuffer tb,
  152. short row
  153. );
  154. static Boolean
  155. _DtTermClearLine
  156. (
  157. TermBuffer tb,
  158. short row,
  159. short newLength
  160. );
  161. #if (defined(TEST) || defined(__CODECENTER__) || defined(VALIDATE_ENH))
  162. static void
  163. validateEnhancements
  164. (
  165. TermBuffer tb,
  166. short row
  167. );
  168. # define VALIDATE_ENHANCEMENTS(tb, row) validateEnhancements((tb), (row))
  169. #else
  170. # define VALIDATE_ENHANCEMENTS(tb, row)
  171. #endif /* TEST || __CODECENTER__ || VALIDATE_ENH */
  172. /*
  173. ** A blank enhancement structure, it will come in handy.
  174. */
  175. static DtTermEnhPart blankEnh = {0, 0, 0, 0, 0};
  176. /*
  177. ** Create and initialize the Dt-specific parts of the term buffer.
  178. */
  179. TermBuffer
  180. _DtTermBufferCreateBuffer
  181. (
  182. const Widget w,
  183. const short rows,
  184. const short cols,
  185. const short sizeOfBuffer,
  186. const short sizeOfLine,
  187. const short sizeOfEnh
  188. )
  189. {
  190. int i;
  191. TermBuffer newTB;
  192. DtLine *lines;
  193. newTB = _DtTermPrimBufferCreateBuffer(w, rows, cols,
  194. sizeOfBuffer, sizeOfLine, sizeOfEnh);
  195. if (newTB)
  196. {
  197. VALUE_LIST(newTB) = (enhValues) malloc(NUM_ENHANCEMENT_FIELDS *
  198. sizeof(enhValue));
  199. if (!VALUE_LIST(newTB))
  200. {
  201. _DtTermPrimBufferFreeBuffer(newTB);
  202. return((TermBuffer) NULL);
  203. }
  204. NUM_ENH_FIELDS(newTB) = NUM_ENHANCEMENT_FIELDS;
  205. for (lines = DT_LINES(newTB);
  206. lines < DT_LINES(newTB) + ROWS(newTB);
  207. lines++)
  208. {
  209. DT_ENH(*lines) = (DtEnh) NULL;
  210. }
  211. DT_ENH_STATE(newTB) = blankEnh;
  212. DT_ENH_DIRTY(newTB) = 0;
  213. ENH_PROC(newTB) = _DtTermEnhProc;
  214. BUFFER_CREATE(newTB) = _DtTermBufferCreateBuffer;
  215. BUFFER_FREE(newTB) = _DtTermBufferFreeBuffer;
  216. BUFFER_RESIZE(newTB) = _DtTermBufferResize;
  217. CLEAR_ENH(newTB) = _DtTermClearEnhancements;
  218. INSERT_ENH(newTB) = _DtTermInsertEnhancements;
  219. DELETE_ENH(newTB) = _DtTermDeleteEnhancement;
  220. SET_ENH(newTB) = _DtTermSetEnhancement;
  221. GET_ENH(newTB) = _DtTermGetEnhancement;
  222. SET_LINE_LENGTH(newTB) = _DtTermSetLineLength;
  223. CLEAR_LINE(newTB) = _DtTermClearLine;
  224. }
  225. return(newTB);
  226. }
  227. /*
  228. ** Resize buffer, this is a helper function, if malloc fails, then the
  229. ** appropriate dimensions are forced to the current maximums
  230. */
  231. static void
  232. _DtTermBufferResize
  233. (
  234. TermBuffer tb,
  235. short *newRows,
  236. short *newCols
  237. )
  238. {
  239. short i;
  240. DtEnh enh;
  241. DtLine *lines;
  242. /*
  243. ** make any necessary width adjustments first...
  244. **
  245. ** NOTE:
  246. ** We do not take any action if the new column width is less
  247. ** than the current column width. It is the responsibility of
  248. ** the rendering code to make sure that two column characters
  249. ** are handled properly if the second column falls past the last
  250. ** column in the window.
  251. */
  252. if (*newCols > MAX_COLS(tb))
  253. {
  254. termChar *newLineBuffer;
  255. /*
  256. ** now extend the line buffers and enhancements for all lines,
  257. ** (even lines that are not being used at the moment
  258. ** (ROWS < MAX_ROWS))...
  259. */
  260. lines = DT_LINES(tb);
  261. for (i = 0; i < MAX_ROWS(tb); i++)
  262. {
  263. /*
  264. ** only copy the enhancement information when it exists
  265. */
  266. if (DT_ENH(lines[i]))
  267. {
  268. enh = (DtEnh) malloc(*newCols * sizeof(DtTermEnhPart));
  269. if (enh)
  270. {
  271. /*
  272. ** copy the enhancment info for all characters on
  273. ** the line, zero out the rest
  274. */
  275. (void) memcpy(enh, DT_ENH(lines[i]),
  276. WIDTH(lines[i]) * sizeof(DtTermEnhPart));
  277. (void) memset(&enh[WIDTH(lines[i])], 0,
  278. (*newCols - WIDTH(lines[i])) *
  279. sizeof(DtTermEnhPart));
  280. free(DT_ENH(lines[i]));
  281. DT_ENH(lines[i]) = enh;
  282. }
  283. else
  284. {
  285. /*
  286. ** the malloc failed, revert back to MAX_COLS
  287. */
  288. *newCols = MAX_COLS(tb);
  289. *newRows = MIN(*newRows, MAX_ROWS(tb));
  290. break;
  291. }
  292. }
  293. newLineBuffer = (termChar *) malloc((unsigned)
  294. *newCols * BYTES_PER_CHAR(tb));
  295. if (newLineBuffer == NULL)
  296. {
  297. /*
  298. ** line buffer malloc failed, we can only increase the
  299. ** width to the current maximum...
  300. */
  301. *newCols = MAX_COLS(tb);
  302. *newRows = MIN(*newRows, MAX_ROWS(tb));
  303. break;
  304. }
  305. memcpy(newLineBuffer, BUFFER(lines[i]), LENGTH(lines[i]) *
  306. BYTES_PER_CHAR(tb));
  307. free(BUFFER(lines[i]));
  308. BUFFER(lines[i]) = newLineBuffer;
  309. WRAPPED(lines[i]) = False;
  310. }
  311. MAX_COLS(tb) = *newCols;
  312. }
  313. COLS(tb) = *newCols;
  314. /*
  315. ** now adjust the length of the buffer as necessary...
  316. */
  317. if (*newRows > MAX_ROWS(tb))
  318. {
  319. /*
  320. ** the number of rows is increasing
  321. */
  322. lines = (DtLine *) malloc((unsigned) *newRows * sizeof(DtLine));
  323. if (lines != NULL)
  324. {
  325. /*
  326. ** the malloc succeeded, copy the old information, and then
  327. ** free it...
  328. */
  329. memcpy(lines, DT_LINES(tb), sizeof(DtLine) * MAX_ROWS(tb));
  330. free(DT_LINES(tb));
  331. LINES(tb) = (TermLine *)lines;
  332. /*
  333. ** now initialize the new lines...
  334. **
  335. ** NOTE:
  336. ** If we are unable to malloc any part of a line, adjust
  337. ** "newRows" and break.
  338. */
  339. for (i = MAX_ROWS(tb); i < *newRows; i++)
  340. {
  341. lines[i] = (DtLine) malloc(SIZE_OF_LINE(tb));
  342. if (lines[i])
  343. {
  344. DT_ENH(lines[i]) = NULL;
  345. BUFFER(lines[i]) = (termChar *) malloc((unsigned) COLS(tb) *
  346. BYTES_PER_CHAR(tb));
  347. if (BUFFER(lines[i]))
  348. {
  349. LENGTH(lines[i]) = 0;
  350. WIDTH(lines[i]) = 0;
  351. WRAPPED(lines[i]) = False;
  352. }
  353. else
  354. {
  355. /*
  356. ** the line buffer malloc failed...
  357. */
  358. *newRows = i;
  359. break;
  360. }
  361. }
  362. else
  363. {
  364. /*
  365. ** we couldn't malloc this line...
  366. */
  367. *newRows = i;
  368. break;
  369. }
  370. }
  371. MAX_ROWS(tb) = *newRows;
  372. }
  373. else
  374. {
  375. /*
  376. ** the malloc for the row buffer failed, revert back to MAX_ROWS
  377. */
  378. *newRows = MAX_ROWS(tb);
  379. }
  380. }
  381. ROWS(tb) = *newRows;
  382. }
  383. /*
  384. ** Free the buffer.
  385. **
  386. ** NOTE: This is a helper function, and should only be called by
  387. ** TermPrimBufferFreeBuffer.
  388. */
  389. void
  390. _DtTermBufferFreeBuffer
  391. (
  392. const TermBuffer tb
  393. )
  394. {
  395. DtLine *lines;
  396. /*
  397. ** Free the Dt-specific buffer info...
  398. */
  399. for (lines = DT_LINES(tb); lines < DT_LINES(tb) + ROWS(tb); lines++)
  400. {
  401. if (DT_ENH(*lines))
  402. {
  403. (void) free(DT_ENH(*lines));
  404. }
  405. }
  406. if (VALUE_LIST(tb))
  407. {
  408. (void) free(VALUE_LIST(tb));
  409. }
  410. }
  411. /*
  412. ** clear all the enhancements from startCol through stopCol
  413. */
  414. static void
  415. clearEnhancements
  416. (
  417. TermBuffer tb,
  418. short row,
  419. short col,
  420. short count
  421. )
  422. {
  423. DtEnh enh;
  424. int i;
  425. enh = DT_ENH(DT_LINE_OF_TBUF(tb, row));
  426. if (enh)
  427. {
  428. enh += col;
  429. for(i = 0; i < count; i++)
  430. {
  431. /*
  432. ** Clear all of the enhancement information.
  433. */
  434. *enh = blankEnh;
  435. enh++;
  436. }
  437. }
  438. }
  439. /*
  440. ** Clear "count" enhancement blocks, starting at the specified row and column.
  441. */
  442. static void
  443. _DtTermClearEnhancements
  444. (
  445. TermBuffer tb,
  446. short row,
  447. short col,
  448. short count
  449. )
  450. {
  451. clearEnhancements(tb, row, col, count);
  452. }
  453. /*
  454. ** Insert the desired number of enhancements at the specified
  455. ** position...
  456. **
  457. ** NOTE:
  458. ** We depend on the calling function to insure that insertCount
  459. ** has been properly clipped to insure that we don't go out of
  460. ** bounds.
  461. ** Results are undefined if this function is called when the specified
  462. ** column is at the end of the line.
  463. */
  464. static void
  465. _DtTermInsertEnhancements
  466. (
  467. const TermBuffer tb,
  468. const short row,
  469. const short col,
  470. short insertCount,
  471. const Boolean insertFlag
  472. )
  473. {
  474. DtTermEnhPart fillEnh;
  475. DtEnh enh;
  476. DtLine line;
  477. int i;
  478. int copyCount;
  479. line = DT_LINE_OF_TBUF(tb, row);
  480. enh = DT_ENH(line);
  481. /*
  482. ** There's nothing to do if we're past the end of the line or
  483. ** the dirty bit is clear and there are no ehancements on
  484. ** this line...
  485. */
  486. if ((col < WIDTH(line)) && ((DT_ENH_DIRTY(tb)) || (enh != NULL)))
  487. {
  488. if ((enh == NULL))
  489. {
  490. /*
  491. ** there are currently no enhancements on this line,
  492. ** allocate an enhancement buffer, and reset 'enh'...
  493. */
  494. _DtTermBufferCreateEnhancement(tb, row, col);
  495. enh = DT_ENH(line);
  496. }
  497. /*
  498. ** get a copy of the current enhancement (we'll insert 'copyCount'
  499. ** copies of it into the enhancement buffer)
  500. */
  501. fillEnh = DT_ENH_STATE(tb);
  502. if (insertFlag)
  503. {
  504. /*
  505. ** we're in insert mode, move any existing enhancements...
  506. */
  507. copyCount = MIN((WIDTH(line) - col),
  508. (COLS(tb) - col - insertCount));
  509. copyCount = MAX(0, copyCount);
  510. memmove(enh + col + insertCount, enh + col,
  511. copyCount * sizeof(DtTermEnhPart));
  512. }
  513. #ifdef NOCODE
  514. /*
  515. ** insert insertCount copies of fillEnh into the enhancement buffer
  516. ** starting at line->enh[col + 1]...
  517. */
  518. enh += col + 1;
  519. for (i = 0; i < insertCount; i++)
  520. {
  521. *enh = fillEnh;
  522. enh++;
  523. }
  524. #else /* NOCODE */
  525. /*
  526. ** insert insertCount copies of fillEnh into the enhancement buffer
  527. ** starting at line->enh[col + 1]...
  528. */
  529. enh += col;
  530. for (i = 0; i < insertCount; i++)
  531. {
  532. *enh = fillEnh;
  533. enh++;
  534. }
  535. #endif /* NOCODE */
  536. }
  537. }
  538. void
  539. _DtTermBufferDelete
  540. (
  541. TermBuffer tb,
  542. short *row,
  543. short *col,
  544. short *count /* number of columns to delete */
  545. )
  546. {
  547. _DtTermPrimBufferDelete(tb, row, col, count, NULL, NULL);
  548. }
  549. /*
  550. ** delete the desired enhancements starting the specified position...
  551. */
  552. static void
  553. _DtTermDeleteEnhancement
  554. (
  555. TermBuffer tb,
  556. short row,
  557. short col,
  558. short width
  559. )
  560. {
  561. DtEnh enh;
  562. DtTermEnhPart fillEnh;
  563. DtLine line;
  564. int copyCount;
  565. line = DT_LINE_OF_TBUF(tb, row);
  566. enh = DT_ENH(line);
  567. if ((enh == NULL) || (WIDTH(line) <= col))
  568. {
  569. /*
  570. ** no enhancements, or at (or past) the end of the line, return
  571. */
  572. return;
  573. }
  574. /*
  575. ** move all of the enhancement blocks between col + width and the
  576. ** end of the line to col
  577. */
  578. copyCount = WIDTH(line) - (col + width);
  579. memmove(enh + col , enh + col + width,
  580. copyCount * sizeof(DtTermEnhPart));
  581. }
  582. /*
  583. ** Create an enhancement block at the specified row and column.
  584. **
  585. ** NOTE: For the time being, we simply allocate an entire row's worth
  586. ** of enhancement blocks if it doesn't exist already. We may
  587. ** get smarter later on.
  588. */
  589. /*ARGSUSED*/
  590. static Boolean
  591. _DtTermBufferCreateEnhancement
  592. (
  593. TermBuffer tb,
  594. short row,
  595. short col
  596. )
  597. {
  598. DtLine line;
  599. DtEnh *enh;
  600. if (!VALID_ROW(tb, row) || !VALID_COL(tb, col))
  601. {
  602. return(False);
  603. }
  604. line = DT_LINE_OF_TBUF(tb, row);
  605. enh = &(DT_ENH(line));
  606. /*
  607. ** If this row already has enhancement blocks allocated, return.
  608. */
  609. if (*enh == NULL)
  610. {
  611. /*
  612. ** Otherwise, allocate and initialize a row of enhancement blocks.
  613. */
  614. *enh = (DtEnh) malloc(MAX_COLS(tb) * sizeof(DtTermEnhPart));
  615. if (*enh == NULL)
  616. {
  617. return(False);
  618. }
  619. /*
  620. ** Clear all the enhancements...
  621. */
  622. (void) memset(*enh, 0, MAX_COLS(tb) * sizeof(DtTermEnhPart));
  623. }
  624. return(True);
  625. }
  626. /*
  627. ** Free the enhancement block at the specified row and column.
  628. **
  629. ** NOTE: We may get smarter later on.
  630. */
  631. Boolean
  632. _DtTermBufferFreeEnhancement
  633. (
  634. TermBuffer tb,
  635. short row,
  636. short col
  637. )
  638. {
  639. return(True);
  640. }
  641. /*
  642. ** Set the desired enhancement.
  643. **
  644. ** This function does the right thing (as far as I can tell regarding
  645. ** propagating enhancements).
  646. **
  647. ** Return:
  648. ** -1 : the enhancement was not set
  649. ** >= 0 : the number of characters (as opposed to character positions)
  650. ** that the enhancement affects
  651. */
  652. static int
  653. _DtTermSetEnhancement
  654. (
  655. TermBuffer tb,
  656. short row,
  657. short col,
  658. unsigned char id,
  659. enhValue value
  660. )
  661. {
  662. int i;
  663. DtEnh enhState;
  664. enhState = (DtEnh) &(DT_ENH_STATE(tb));
  665. /*
  666. ** Set the value.
  667. */
  668. switch (id)
  669. {
  670. case enhVideo:
  671. enhState->video = value & VIDEO_MASK;
  672. break;
  673. case enhField:
  674. enhState->field = value & FIELD_MASK;
  675. break;
  676. case enhFgColor:
  677. enhState->fgColor = value & COLOR_MASK;
  678. break;
  679. case enhBgColor:
  680. enhState->bgColor = value & COLOR_MASK;
  681. break;
  682. case enhFont:
  683. enhState->font = value & FONT_MASK;
  684. break;
  685. default:
  686. return(-1);
  687. }
  688. /*
  689. ** We've set the value, now decide if this anything but the blank
  690. ** enhancement.
  691. */
  692. DT_ENH_DIRTY(tb) = ((enhState->video != blankEnh.video ) ||
  693. (enhState->field != blankEnh.field ) ||
  694. (enhState->fgColor != blankEnh.fgColor) ||
  695. (enhState->bgColor != blankEnh.bgColor) ||
  696. (enhState->font != blankEnh.font ));
  697. /*
  698. ** return the correct count (which in this case will always be 0)
  699. */
  700. return(0);
  701. }
  702. /*
  703. ** Get the enhancements for the desired row and column.
  704. **
  705. ** enhValues:
  706. ** a pointer to an array of the current enhancement values
  707. **
  708. ** count:
  709. ** the number of columns for which the enhancements are
  710. ** valid, or the number of columns until the enhancements
  711. ** were modified by an escape sequence (see 'countWhich' below)
  712. **
  713. ** countWhich:
  714. ** if 'countWhich' is countAll then count until any enhancement value
  715. ** changes
  716. ** if 'countAll' is countNew then count until a new enhancement value
  717. ** starts (regardless of whether it is the same or not).
  718. **
  719. ** Return:
  720. ** True if row and col are valid
  721. */
  722. static Boolean
  723. _DtTermGetEnhancement
  724. (
  725. const TermBuffer tb,
  726. const short row,
  727. const short col,
  728. enhValue **values,
  729. short *count,
  730. const countSpec countWhich
  731. )
  732. {
  733. /*
  734. ** store the current enhancement values here
  735. */
  736. int i;
  737. DtLine line;
  738. DtEnh enh;
  739. /*
  740. ** First we do some simple bounds checking
  741. */
  742. VALIDATE_ENHANCEMENTS(tb, row);
  743. if (!VALID_ROW(tb, row) || !VALID_COL(tb, col))
  744. {
  745. return(False);
  746. }
  747. line = DT_LINE_OF_TBUF(tb, row);
  748. /*
  749. ** point to the correct enhancement chunk.
  750. */
  751. if (DT_ENH(line) == NULL || (WIDTH(line) <= col))
  752. {
  753. /*
  754. ** There are either no enhancements allocated for this line,
  755. ** or we're past the end of the line, in either case return
  756. ** a blank enhancement.
  757. */
  758. enh = &blankEnh;
  759. }
  760. else
  761. {
  762. /*
  763. ** We're in the line get the current enhancement values
  764. */
  765. enh = &(DT_ENH(line)[col]);
  766. }
  767. /*
  768. ** Shove the enhancement values into their correct locations...
  769. */
  770. *values = (VALUE_LIST(tb));
  771. (*values)[(int)enhVideo ] = (enh->video & VIDEO_MASK);
  772. (*values)[(int)enhField ] = (enh->field & FIELD_MASK);
  773. (*values)[(int)enhFgColor] = (enh->fgColor & COLOR_MASK);
  774. (*values)[(int)enhBgColor] = (enh->bgColor & COLOR_MASK);
  775. (*values)[(int)enhFont ] = (enh->font & FONT_MASK );
  776. /*
  777. ** Now count how many characters are affected by the enhancements.
  778. */
  779. if (DT_ENH(line) == NULL)
  780. {
  781. /*
  782. ** There no enhancements allocated for this line, the default
  783. ** enhancement is active for the remainder of the line.
  784. ** NOTE: Make sure count >= 0.
  785. */
  786. *count = MAX(0, WIDTH(line) - col);
  787. }
  788. else if (WIDTH(line) <= col)
  789. {
  790. /*
  791. ** We're past the end of the line, count will always == 0;
  792. */
  793. *count = 0;
  794. }
  795. else
  796. {
  797. /*
  798. ** We're in the line, determine the number of characters that
  799. ** these enhancements apply to.
  800. */
  801. switch (countWhich)
  802. {
  803. case countNew:
  804. /*
  805. ** For Vt220 emulation, countNew is the same as countAll...
  806. ** JRM 08/30/93
  807. */
  808. case countAll:
  809. /*
  810. ** count until an enhancement value changes
  811. */
  812. for (i = 0; i < (WIDTH(line) - col); i++)
  813. {
  814. if (((*values)[(int)enhVideo ] != (enh->video & VIDEO_MASK))||
  815. ((*values)[(int)enhField ] != (enh->field & FIELD_MASK))||
  816. ((*values)[(int)enhFgColor] != (enh->fgColor & COLOR_MASK))||
  817. ((*values)[(int)enhBgColor] != (enh->bgColor & COLOR_MASK))||
  818. ((*values)[(int)enhFont ] != (enh->font & FONT_MASK )) )
  819. {
  820. /*
  821. ** the enhancements differ; break out
  822. */
  823. break;
  824. }
  825. enh++;
  826. }
  827. break;
  828. default:
  829. VALIDATE_ENHANCEMENTS(tb, row);
  830. return(False);
  831. }
  832. *count = i;
  833. }
  834. VALIDATE_ENHANCEMENTS(tb, row);
  835. return(True);
  836. }
  837. /*
  838. ** This is a vt-specific helper function for setting the line length.
  839. ** By the time the function is called, termBufferSetLineLength()
  840. ** as already validated the newLength, the row, and insured that the
  841. ** new length is > the current length
  842. **
  843. ** This function propagates the correct enhancement to the new end of line.
  844. */
  845. static Boolean
  846. _DtTermSetLineLength
  847. (
  848. TermBuffer tb,
  849. short row,
  850. short newLength
  851. )
  852. {
  853. return(True);
  854. }
  855. /*
  856. ** _DtTermPrimBufferClearLine will reset the line width, this is
  857. ** our chance to clear any enhancements that may exist on this line...
  858. */
  859. static Boolean
  860. _DtTermClearLine
  861. (
  862. TermBuffer tb,
  863. short row,
  864. short newWidth
  865. )
  866. {
  867. DtLine line;
  868. DtEnh enh;
  869. line = DT_LINE_OF_TBUF(tb, row);
  870. enh = DT_ENH(line);
  871. if (enh != NULL)
  872. {
  873. /*
  874. ** We have enhancements, clear all those between the current
  875. ** and the new length...
  876. */
  877. (void) memset(&enh[newWidth], 0,
  878. (WIDTH(line) - newWidth) * sizeof(DtTermEnhPart));
  879. }
  880. return(True);
  881. }
  882. /*
  883. ** Erase characters on the specified row (and clear the enhancements) with
  884. ** the appropriate semantics. For VT class emulators, there are several
  885. ** ways to erase characters:
  886. ** - from the active position to the end of line
  887. ** - erase the specified number of characters starting at the current
  888. ** cursor position
  889. ** - from the start of the line to the active position
  890. ** - erase the entire line
  891. ** - from the active position to the end of the buffer
  892. ** - erase the specified number of lines starting at the current
  893. ** cursor position
  894. ** - from the start of the buffer to the active position
  895. ** - erase the entire buffer
  896. */
  897. void
  898. _DtTermBufferErase
  899. (
  900. TermBuffer tb,
  901. short row,
  902. short col,
  903. short count,
  904. DtEraseMode eraseSwitch
  905. )
  906. {
  907. short startCol = 0;
  908. short lastCol = 0;
  909. switch(eraseSwitch)
  910. {
  911. case eraseFromCol0:
  912. /*
  913. ** erase from col 0 to the current cursor position
  914. */
  915. startCol = 0;
  916. lastCol = MIN(col, WIDTH(DT_LINE_OF_TBUF(tb, row)) - 1);
  917. break;
  918. case eraseCharCount:
  919. /*
  920. ** erase "count" characters from the current cursor position
  921. */
  922. startCol = col;
  923. lastCol = MIN(col + count - 1, WIDTH(DT_LINE_OF_TBUF(tb, row)) - 1);
  924. break;
  925. case eraseLineCount:
  926. case eraseToEOL:
  927. case eraseLine:
  928. case eraseBuffer:
  929. case eraseFromRow0Col0:
  930. case eraseToEOB:
  931. /*
  932. ** These cases should have been handled by _DtTermFuncErase()
  933. */
  934. return;
  935. }
  936. _DtTermPrimBufferErase(tb, row, startCol, lastCol);
  937. /*
  938. ** now clear the corresponding enhancements...
  939. */
  940. clearEnhancements(tb, row, startCol, lastCol - startCol + 1);
  941. }
  942. #if (defined(TEST) || defined(__CODECENTER__) || defined(VALIDATE_ENH))
  943. static void
  944. _DtTermValidateEnhancements
  945. (
  946. TermBuffer tb,
  947. short row
  948. )
  949. {
  950. DtTermEnhPart refEnh;
  951. DtEnh thisEnh;
  952. DtLine thisLine;
  953. short col;
  954. Boolean validatePassed;
  955. validatePassed = True;
  956. thisLine = DT_LINE_OF_TBUF(tb, row);
  957. if (DT_ENH(thisLine))
  958. {
  959. /*
  960. ** Initialize the reference enhancement
  961. */
  962. refEnh = blankEnh;
  963. refEnh.videoStart = 0;
  964. refEnh.fieldStart = 0;
  965. refEnh.colorStart = 0;
  966. refEnh.fontStart = 0;
  967. for(col = 0, thisEnh = DT_ENH(thisLine);
  968. col < WIDTH(thisLine) +
  969. (DANGLE(thisLine) >= 0 ? 1 : 0);
  970. col++, thisEnh++)
  971. {
  972. if (thisEnh->videoStart)
  973. {
  974. refEnh.video = thisEnh->video;
  975. }
  976. else if (refEnh.video != thisEnh->video)
  977. {
  978. fprintf(stderr, "Video enhancements don't match:");
  979. fprintf(stderr, " row : %3.3d, col : %3.3d\n", row, col);
  980. fprintf(stderr, " refEnh.video : %d\n", (int)(refEnh.video & VIDEO_MASK));
  981. fprintf(stderr, " thisEnh->video: %d\n", (int)(thisEnh->video & VIDEO_MASK));
  982. validatePassed = False;
  983. }
  984. if (thisEnh->fieldStart)
  985. {
  986. refEnh.field = thisEnh->field;
  987. }
  988. else if (refEnh.field != thisEnh->field)
  989. {
  990. fprintf(stderr, "Field enhancements don't match:");
  991. fprintf(stderr, " row : %3.3d, col : %3.3d\n", row, col);
  992. fprintf(stderr, " refEnh.field : %d\n", (int)(refEnh.field & FIELD_MASK));
  993. fprintf(stderr, " thisEnh->field: %d\n", (int)(thisEnh->field & FIELD_MASK));
  994. validatePassed = False;
  995. }
  996. if (thisEnh->colorStart)
  997. {
  998. refEnh.color = thisEnh->color;
  999. }
  1000. else if (refEnh.color != thisEnh->color)
  1001. {
  1002. fprintf(stderr, "Color enhancements don't match:");
  1003. fprintf(stderr, " row : %3.3d, col : %3.3d\n", row, col);
  1004. fprintf(stderr, " refEnh.color : %d\n", (int)(refEnh.color & COLOR_MASK));
  1005. fprintf(stderr, " thisEnh->color: %d\n", (int)(thisEnh->color & COLOR_MASK));
  1006. validatePassed = False;
  1007. }
  1008. if (thisEnh->font <= 2)
  1009. {
  1010. if (thisEnh->fontStart)
  1011. {
  1012. refEnh.font = thisEnh->font;
  1013. }
  1014. else if (refEnh.font != thisEnh->font)
  1015. {
  1016. fprintf(stderr, "Font enhancements don't match:");
  1017. fprintf(stderr, " row : %3.3d, col : %3.3d\n", row, col);
  1018. fprintf(stderr, " refEnh.font : %d\n", (int)(refEnh.font & FONT_MASK));
  1019. fprintf(stderr, " thisEnh->font: %d\n", (int)(thisEnh->font & FONT_MASK));
  1020. validatePassed = False;
  1021. }
  1022. }
  1023. else
  1024. {
  1025. fprintf(stderr, "Font enhancement out of range:");
  1026. fprintf(stderr, " row : %3.3d, col : %3.3d\n", row, col);
  1027. fprintf(stderr, " thisEnh->font: %d\n", (int)(thisEnh->font & FONT_MASK));
  1028. validatePassed = False;
  1029. }
  1030. }
  1031. }
  1032. if (validatePassed == False)
  1033. {
  1034. fprintf(stderr, "validateEnhancement failed\n");
  1035. }
  1036. }
  1037. #endif /* TEST || __CODECENTER__ || DEBUG || VALIDATE_ENH */
  1038. #if (defined(TEST) || defined(__CODECENTER__) || defined(DEBUG))
  1039. #ifdef NOCODE
  1040. static void
  1041. _printLine
  1042. (
  1043. TermBuffer tb,
  1044. short row
  1045. )
  1046. {
  1047. DtLine line;
  1048. termChar *pChar;
  1049. short j;
  1050. printf("Line: %d\n", row);
  1051. line = tb->lines[row];
  1052. printf(" length: %3d\n", line->length);
  1053. if (line->length > 0)
  1054. {
  1055. printf(" buffer: <");
  1056. pChar = line->buffer;
  1057. for (j = 0; j < line->length; j++)
  1058. {
  1059. printf("%X", *pChar++);
  1060. }
  1061. printf(">\n");
  1062. }
  1063. }
  1064. static int
  1065. _DtTermPrintEnhancement
  1066. (
  1067. TermBuffer tb,
  1068. short row,
  1069. short col
  1070. )
  1071. {
  1072. enhValue enhancements[NUM_ENHANCEMENT_FIELDS];
  1073. short enhCount;
  1074. _DtTermPrimBufferGetEnhancement(tb, row, col, enhancements, &enhCount, countNew);
  1075. printf(" col : %d\n", col);
  1076. printf(" Count: %d\n", enhCount);
  1077. printf(" Video: '_");
  1078. printf("%s", IS_BOLD(enhancements[enhVideo]) != 0 ? "B":"b");
  1079. printf("_");
  1080. printf("%s", IS_SECURE(enhancements[enhVideo]) != 0 ? "S":"s");
  1081. printf("_");
  1082. printf("%s", IS_HALF_BRIGHT(enhancements[enhVideo]) != 0 ? "H":"h");
  1083. printf("_");
  1084. printf("%s", IS_UNDERLINE(enhancements[enhVideo]) != 0 ? "U":"u");
  1085. printf("_");
  1086. printf("%s", IS_INVERSE(enhancements[enhVideo]) != 0 ? "I":"i");
  1087. printf("_");
  1088. printf("%s", IS_BLINK(enhancements[enhVideo]) != 0 ? "B":"b");
  1089. printf("_'\n");
  1090. /*
  1091. ** Field type
  1092. */
  1093. printf(" Field: ");
  1094. switch (enhancements[enhField])
  1095. {
  1096. case FIELD_PROTECT:
  1097. printf("PROTECT");
  1098. break;
  1099. case FIELD_UNPROTECT:
  1100. printf("UNPROTECT");
  1101. break;
  1102. case FIELD_TRANSMIT:
  1103. printf("TRANSMIT");
  1104. break;
  1105. case FIELD_END:
  1106. printf("END");
  1107. break;
  1108. }
  1109. printf("\n");
  1110. /*
  1111. ** Color id
  1112. */
  1113. printf(" Color: %1d\n", enhancements[enhFont]);
  1114. /*
  1115. ** Font id
  1116. */
  1117. printf(" Font : ");
  1118. switch (enhancements[enhFont])
  1119. {
  1120. case FONT_NORMAL:
  1121. printf("NORMAL");
  1122. break;
  1123. case FONT_LINEDRAW:
  1124. printf("LINEDRAW");
  1125. break;
  1126. }
  1127. printf("\n");
  1128. return(enhCount);
  1129. }
  1130. #endif /* NOCODE */
  1131. static void
  1132. printEnh
  1133. (
  1134. DtEnh enh
  1135. )
  1136. {
  1137. printf(" video : %d\n", enh->video);
  1138. printf(" field : %d\n", enh->field);
  1139. printf(" fgColor: %d\n", enh->fgColor);
  1140. printf(" bgColor: %d\n", enh->bgColor);
  1141. printf(" font : %d\n", enh->font);
  1142. }
  1143. /*
  1144. ** Print the contents of the TermBuffer.
  1145. */
  1146. static void
  1147. _DtTermPrintBuffer
  1148. (
  1149. DtTermBuffer tb
  1150. )
  1151. {
  1152. short i;
  1153. short j;
  1154. short k;
  1155. if (tb == NULL) {
  1156. printf("TermBuffer has been freed.\n");
  1157. return;
  1158. }
  1159. printf("TermBuffer dimensions:\n");
  1160. printf(" rows: %d\n", ROWS(tb));
  1161. printf(" cols: %d\n", COLS(tb));
  1162. printf(" enhDirty: %d\n", DT_ENH_DIRTY(tb));
  1163. printf(" enhState:\n");
  1164. printEnh(&(DT_ENH_STATE(tb)));
  1165. #ifdef NOCODE
  1166. for (i = 0; i < ROWS(tb); i++)
  1167. {
  1168. _printLine(tb, i);
  1169. j = 0;
  1170. do
  1171. {
  1172. k = _termBufferPrintEnhancement(tb, i, j);
  1173. if (k == 0)
  1174. {
  1175. break;
  1176. }
  1177. j += k;
  1178. } while (j < COLS(tb));
  1179. }
  1180. #endif /* NOCODE */
  1181. }
  1182. #endif /* (defined(TEST) || defined(__CODECENTER__)) */
  1183. #ifdef TEST
  1184. /*
  1185. ** Some simple tests of the termBuffer.
  1186. */
  1187. /* the following is to allow for a single main function in the code... */
  1188. #define termBufMain main
  1189. termBufMain()
  1190. {
  1191. TermBuffer myTB;
  1192. printf("Sizeof DtTermEnhPart : %d\n", sizeof(struct _DtTermEnhPart));
  1193. printf("Sizeof termBufferRec : %d\n", sizeof(struct _TermBufferRec));
  1194. myTB = _DtTermPrimBufferCreateBuffer(12, 80);
  1195. _termBufferPrintBuffer(myTB);
  1196. printf("[0,0] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 0, enhVideo, BLINK));
  1197. _termBufferPrintEnhancement(myTB, 0, 0);
  1198. printf("[0,1] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 1, enhVideo, INVERSE));
  1199. _termBufferPrintEnhancement(myTB, 0, 0);
  1200. _termBufferPrintEnhancement(myTB, 0, 1);
  1201. printf("[0,9] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 9, enhVideo, UNDERLINE));
  1202. _termBufferPrintEnhancement(myTB, 0, 0);
  1203. _termBufferPrintEnhancement(myTB, 0, 1);
  1204. _termBufferPrintEnhancement(myTB, 0, 9);
  1205. printf("[0,6] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 6, enhVideo, HALF_BRIGHT));
  1206. _termBufferPrintEnhancement(myTB, 0, 0);
  1207. _termBufferPrintEnhancement(myTB, 0, 1);
  1208. _termBufferPrintEnhancement(myTB, 0, 6);
  1209. _termBufferPrintEnhancement(myTB, 0, 9);
  1210. _termBufferPrintBuffer(myTB);
  1211. _DtTermPrimBufferSetEnhancement(myTB, 10, 10, enhVideo, BLINK);
  1212. _DtTermPrimBufferSetEnhancement(myTB, 10, 20, enhColor, 3);
  1213. _termBufferPrintBuffer(myTB);
  1214. _DtTermPrimBufferResizeBuffer(&myTB, 6, 40);
  1215. _termBufferPrintBuffer(myTB);
  1216. _DtTermPrimBufferSetEnhancement(myTB, 10, 10, enhVideo, BLINK);
  1217. _DtTermPrimBufferResizeBuffer(&myTB, 12, 80);
  1218. _termBufferPrintBuffer(myTB);
  1219. _DtTermPrimBufferFreeBuffer(myTB);
  1220. }
  1221. #endif /* TEST */