TermPrimBuffer.c 57 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381
  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 <stdlib.h>
  34. #include <wchar.h>
  35. #include <Xm/Xm.h>
  36. #include "TermHeader.h" /* for MIN/MAX */
  37. #include "TermPrim.h"
  38. #include "TermPrimBuffer.h"
  39. #include "TermPrimBufferP.h"
  40. #include "TermPrimSelect.h"
  41. #include "TermPrimDebug.h"
  42. /*
  43. ** Allocate and initialize a new terminal buffer.
  44. */
  45. TermBuffer
  46. _DtTermPrimBufferCreateBuffer
  47. (
  48. const Widget w,
  49. const short rows,
  50. const short cols,
  51. const short sizeOfBuffer,
  52. const short sizeOfLine,
  53. const short sizeOfEnh
  54. )
  55. {
  56. int i;
  57. TermLine *newTL;
  58. TermBuffer newTB;
  59. Boolean *tabs;
  60. int sizeOfChar;
  61. /*
  62. ** malloc new a TermBuffer and an array of TermLine pointers
  63. */
  64. newTB = (TermBuffer) malloc(sizeOfBuffer);
  65. /* the following MIN ensures that on systems where malloc of 0 returns
  66. * NULL, we won't confuse a 0 size buffer with a malloc failure and an
  67. * invalid buffer...
  68. */
  69. newTL = (TermLine *) malloc((unsigned) MAX(rows, 1) * sizeof(TermLine));
  70. if (!newTB || !newTL)
  71. {
  72. /*
  73. ** clean up and leave if either of the previous malloc's failed.
  74. */
  75. if (newTB)
  76. {
  77. free(newTB);
  78. }
  79. if (newTL)
  80. {
  81. free(newTL);
  82. }
  83. return((TermBuffer)NULL);
  84. }
  85. /*
  86. ** malloc a tabs array...
  87. */
  88. tabs = (Boolean *) malloc((unsigned) cols * sizeof(Boolean));
  89. if (!tabs)
  90. {
  91. free(newTB);
  92. free(newTL);
  93. /*
  94. ** clean up and leave if either of the previous malloc's failed.
  95. */
  96. return((TermBuffer)NULL);
  97. }
  98. /*
  99. ** initialize the tabs...
  100. */
  101. for (i = 0; i < cols; i++) {
  102. tabs[i] = 0 == i % 8;
  103. }
  104. /*
  105. ** decide how many bytes to allocate per character...
  106. */
  107. BYTES_PER_CHAR(newTB) = MB_CUR_MAX == 1 ? 1 : sizeof(wchar_t);
  108. /*
  109. ** setting debug flag m:1 forces us into wide char mode...
  110. */
  111. DebugF('m', 1, BYTES_PER_CHAR(newTB) = sizeof(wchar_t));
  112. /*
  113. ** now malloc the individual lines...
  114. */
  115. for (i = 0; i < rows; i++)
  116. {
  117. newTL[i] = (TermLine) malloc(sizeOfLine);
  118. if (newTL[i])
  119. {
  120. BUFFER(newTL[i]) = (termChar *)
  121. malloc((unsigned)
  122. cols * BYTES_PER_CHAR(newTB));
  123. if (BUFFER(newTL[i]) == NULL)
  124. {
  125. /*
  126. ** we couldn't malloc a line buffer
  127. */
  128. break;
  129. }
  130. LENGTH(newTL[i]) = 0;
  131. WIDTH(newTL[i]) = 0;
  132. WRAPPED(newTL[i]) = False;
  133. START_SELECTION(newTL[i]) = NON_SELECTION_COL;
  134. END_SELECTION(newTL[i]) = NON_SELECTION_COL;
  135. }
  136. else
  137. {
  138. /*
  139. ** we couldn't malloc a line
  140. */
  141. break;
  142. }
  143. }
  144. /*
  145. ** If we were unable to malloc a full set of lines (i != rows),
  146. ** then cleanup and leave.
  147. */
  148. if (i != rows)
  149. {
  150. int j;
  151. for (j = 0; j < i; j++)
  152. {
  153. free(BUFFER(newTL[j]));
  154. free(newTL[j]);
  155. }
  156. free(newTL);
  157. free(newTB);
  158. free(tabs);
  159. return((TermBuffer)NULL);
  160. }
  161. /*
  162. ** Initialize the new TermBuffer.
  163. */
  164. LINES(newTB) = newTL;
  165. TABS(newTB) = tabs;
  166. ROWS(newTB) = rows;
  167. COLS(newTB) = cols;
  168. MAX_ROWS(newTB) = rows;
  169. MAX_COLS(newTB) = cols;
  170. SIZE_OF_BUFFER(newTB) = sizeOfBuffer;
  171. SIZE_OF_LINE(newTB) = sizeOfLine;
  172. SIZE_OF_ENH(newTB) = sizeOfEnh;
  173. BUFFER_CREATE(newTB) = _DtTermPrimBufferCreateBuffer;
  174. BUFFER_FREE(newTB) = NULL;
  175. BUFFER_RESIZE(newTB) = NULL;
  176. ENH_PROC(newTB) = NULL;
  177. CLEAR_ENH(newTB) = NULL;
  178. INSERT_ENH(newTB) = NULL;
  179. DELETE_ENH(newTB) = NULL;
  180. SET_ENH(newTB) = NULL;
  181. GET_ENH(newTB) = NULL;
  182. SET_LINE_WIDTH(newTB) = NULL;
  183. CLEAR_LINE(newTB) = NULL;
  184. NEXT_BUFFER(newTB) = NULL;
  185. PREV_BUFFER(newTB) = NULL;
  186. BUFFER_SELECT_INFO(newTB) = NULL;
  187. WIDGET(newTB) = w;
  188. return (newTB);
  189. }
  190. void
  191. _DtTermPrimBufferFreeBuffer
  192. (
  193. const TermBuffer tb
  194. )
  195. {
  196. int i;
  197. /* check for null buffer... */
  198. if (!tb) {
  199. return;
  200. }
  201. /*
  202. ** Free any buffer-specific info first...
  203. */
  204. if (BUFFER_FREE(tb))
  205. {
  206. (*BUFFER_FREE(tb))(tb);
  207. }
  208. /*
  209. ** free the old buffer...
  210. */
  211. for (i = 0; i < MAX_ROWS(tb); i++)
  212. {
  213. (void) free(BUFFER(LINES(tb)[i]));
  214. (void) free(LINES(tb)[i]);
  215. }
  216. (void) free(TABS(tb));
  217. (void) free(LINES(tb));
  218. (void) free(tb);
  219. }
  220. /*
  221. ** Resize the terminal buffer, and try to be smart about it. If the buffer
  222. ** shrinks, then simply adjust the size, no reallocs necessary (that way if
  223. ** the user returns to the previous size, no data is lost).
  224. **
  225. ** NOTE:
  226. ** Given this implementation, the memory allocated to the buffer will
  227. ** never decrease it simply increases to accommodate the largest size
  228. ** that has ever been requested.
  229. */
  230. void
  231. _DtTermPrimBufferResizeBuffer
  232. (
  233. TermBuffer *oldTB,
  234. short *newRows,
  235. short *newCols
  236. )
  237. {
  238. int i;
  239. short thisTabWidth;
  240. short tabWidth;
  241. TermLine *newTL;
  242. Boolean *tabs;
  243. /*
  244. ** enforce some minimum size constraints...
  245. */
  246. *newRows = MAX(*newRows, 1);
  247. *newCols = MAX(*newCols, 1);
  248. /*
  249. ** the number of cols is increasing, start small and adjust the tab
  250. ** stops first...
  251. */
  252. if (*newCols > MAX_COLS(*oldTB))
  253. {
  254. tabs = (Boolean *) malloc((unsigned) *newCols * sizeof(Boolean));
  255. if (tabs)
  256. {
  257. /* copy over the tab stops... */
  258. (void) memcpy(tabs, TABS(*oldTB), COLS(*oldTB) * sizeof(Boolean));
  259. free(TABS(*oldTB));
  260. TABS(*oldTB) = tabs;
  261. /*
  262. ** we need to extend the tab stops...
  263. **
  264. ** when tabWidth == 0, it has not been initialized. When
  265. ** it is < 0, we have encountered unequal tab stops...
  266. */
  267. tabWidth = 0;
  268. for (i = 0, thisTabWidth = 0; i < COLS(*oldTB); i++, thisTabWidth++)
  269. {
  270. if (TABS(*oldTB)[i])
  271. {
  272. if (tabWidth == 0)
  273. {
  274. /* first tab stop, set tabWidth... */
  275. tabWidth = thisTabWidth;
  276. }
  277. else if (tabWidth != thisTabWidth)
  278. {
  279. /* tab stops differ, set tabWidth to -1... */
  280. tabWidth = -1;
  281. }
  282. /* reset for next tab stop... */
  283. thisTabWidth = 0;
  284. }
  285. }
  286. if (tabWidth > 0)
  287. {
  288. /*
  289. ** we have consistent tab stops. Extend the buffer...
  290. */
  291. for (i = COLS(*oldTB); i < *newCols; i++)
  292. {
  293. TABS(*oldTB)[i] = (0 == (i % tabWidth));
  294. }
  295. }
  296. else
  297. {
  298. /*
  299. ** we don't have consistent tab stops, so clear the rest...
  300. */
  301. (void) memset(&(TABS(*oldTB)[COLS(*oldTB)]), '\0',
  302. (*newCols - COLS(*oldTB)) * sizeof(Boolean));
  303. }
  304. }
  305. else
  306. {
  307. /*
  308. ** the malloc failed, adjust newCols and newRows and leave...
  309. */
  310. *newCols = MAX_COLS(*oldTB);
  311. *newRows = MIN(*newRows, MAX_ROWS(*oldTB));
  312. COLS(*oldTB) = *newCols;
  313. ROWS(*oldTB) = *newRows;
  314. return;
  315. }
  316. }
  317. else
  318. {
  319. /*
  320. ** take care of any shrinkage...
  321. */
  322. COLS(*oldTB) = *newCols;
  323. }
  324. /*
  325. ** Now give the resize helper a shot at resizing the buffer
  326. */
  327. if (BUFFER_RESIZE(*oldTB))
  328. {
  329. /*
  330. ** Call the resize helper function if it exists...
  331. */
  332. (*BUFFER_RESIZE(*oldTB))(*oldTB, newRows, newCols);
  333. }
  334. else
  335. {
  336. /*
  337. ** There is no helper function, do it ourselves...
  338. ** NOTE:
  339. ** This might cause some duplication of code, but due
  340. ** to time constraints, it is the most expeditious route.
  341. */
  342. /*
  343. ** make any necessary width adjustments first...
  344. **
  345. ** NOTE:
  346. ** We do not take any action if the new column width is less
  347. ** than the current column width. It is the responsibility of
  348. ** the rendering code to make sure that two column characters
  349. ** are handled properly if the second column falls past the last
  350. ** column in the window.
  351. */
  352. if (*newCols > MAX_COLS(*oldTB))
  353. {
  354. termChar *newLineBuffer;
  355. /*
  356. ** now extend the line buffers for all lines, (even lines that
  357. ** are not being used at the moment (ROWS < MAX_ROWS))...
  358. */
  359. newTL = LINES(*oldTB);
  360. for (i = 0; i < MAX_ROWS(*oldTB); i++)
  361. {
  362. newLineBuffer = (termChar *) malloc((unsigned)
  363. *newCols * BYTES_PER_CHAR(*oldTB));
  364. if (newLineBuffer == NULL)
  365. {
  366. /*
  367. ** line buffer malloc failed, we can only increase the
  368. ** width to the current maximum...
  369. */
  370. *newCols = MAX_COLS(*oldTB);
  371. *newRows = MIN(*newRows, MAX_ROWS(*oldTB));
  372. break;
  373. }
  374. memcpy(newLineBuffer, BUFFER(newTL[i]), LENGTH(newTL[i]));
  375. free(BUFFER(newTL[i]));
  376. BUFFER(newTL[i]) = newLineBuffer;
  377. WRAPPED(newTL[i]) = False;
  378. }
  379. MAX_COLS(*oldTB) = *newCols;
  380. }
  381. COLS(*oldTB) = *newCols;
  382. /*
  383. ** now adjust the length of the buffer as necessary...
  384. */
  385. if (*newRows > MAX_ROWS(*oldTB))
  386. {
  387. /*
  388. ** the number of rows is increasing
  389. */
  390. newTL = (TermLine *) malloc((unsigned) *newRows *
  391. sizeof(TermLine));
  392. if (newTL != NULL)
  393. {
  394. /*
  395. ** the malloc succeeded, copy the old information, and
  396. ** then free it...
  397. */
  398. memcpy(newTL, LINES(*oldTB), sizeof(TermLine) *
  399. ROWS(*oldTB));
  400. free(LINES(*oldTB));
  401. LINES(*oldTB) = newTL;
  402. /*
  403. ** now initialize the new lines...
  404. */
  405. for (i = ROWS(*oldTB); i < *newRows; i++)
  406. {
  407. newTL[i] = (TermLine) malloc(SIZE_OF_LINE(*oldTB));
  408. if (newTL[i])
  409. {
  410. BUFFER(newTL[i]) = (termChar *)
  411. malloc((unsigned) COLS(*oldTB) *
  412. BYTES_PER_CHAR(*oldTB));
  413. if (BUFFER(newTL[i]) == NULL)
  414. {
  415. /*
  416. ** line buffer malloc failed...
  417. */
  418. *newRows = i;
  419. break;
  420. }
  421. LENGTH(newTL[i]) = 0;
  422. WIDTH(newTL[i]) = 0;
  423. WRAPPED(newTL[i]) = False;
  424. START_SELECTION(newTL[i]) = NON_SELECTION_COL;
  425. END_SELECTION(newTL[i]) = NON_SELECTION_COL;
  426. }
  427. else
  428. {
  429. /*
  430. ** line malloc failed, lets limit the
  431. ** number of rows
  432. */
  433. *newRows = i;
  434. break;
  435. }
  436. }
  437. /*
  438. ** its conceivable that MAX_ROWS could actually decrease if
  439. ** we are low on memory...
  440. */
  441. MAX_ROWS(*oldTB) = MIN(MAX_ROWS(*oldTB), *newRows);
  442. }
  443. else
  444. {
  445. /*
  446. ** the row buffer malloc failed, revert back to MAX_ROWS
  447. */
  448. *newRows = MAX_ROWS(*oldTB);
  449. }
  450. }
  451. ROWS(*oldTB) = *newRows;
  452. }
  453. }
  454. #ifdef NOCODE
  455. /*
  456. ** Create an enhancement block at the specified row and column.
  457. **
  458. ** NOTE: For the time being, we simply allocate an entire row's worth
  459. ** of enhancement blocks if it doesn't exist already. We may
  460. ** get smarter later on.
  461. */
  462. /*ARGSUSED*/
  463. Boolean
  464. _DtTermPrimBufferCreateEnhancement
  465. (
  466. const TermBuffer tb,
  467. const short row,
  468. const short col
  469. )
  470. {
  471. return(True);
  472. }
  473. /*
  474. ** Clear the enhancement block at the specified row and column.
  475. */
  476. static
  477. void
  478. clearEnhancement
  479. (
  480. const TermBuffer tb,
  481. const short row,
  482. const short col
  483. )
  484. {
  485. }
  486. #endif /* NOCODE */
  487. /*
  488. ** Call the emulations specific function to insert the desired number of
  489. ** enhancements at the specified position...
  490. **
  491. ** Assumptions:
  492. ** - insertCount has been properly clipped to insure that we don't go
  493. ** out of bounds
  494. **
  495. ** Notes:
  496. ** - results are undefined if this function is called when the specified
  497. ** column is at the end of the line.
  498. */
  499. static void
  500. insertEnhancements
  501. (
  502. const TermBuffer tb,
  503. const short row,
  504. const short col,
  505. const short insertCount,
  506. const Boolean insertFlag
  507. )
  508. {
  509. /*
  510. ** call the insert function only when it exists and we're in
  511. ** insert mode...
  512. */
  513. if (INSERT_ENH(tb))
  514. {
  515. (*INSERT_ENH(tb))(tb, row, col, insertCount, insertFlag);
  516. }
  517. }
  518. /*
  519. ** Free the enhancement block at the specified row and column.
  520. **
  521. ** NOTE: We may get smarter later on.
  522. */
  523. Boolean
  524. _DtTermPrimBufferFreeEnhancement
  525. (
  526. const TermBuffer tb,
  527. const short row,
  528. const short col
  529. )
  530. {
  531. return(True);
  532. }
  533. #ifdef BBA
  534. #pragma BBA_IGNORE
  535. #endif /*BBA*/
  536. static void
  537. RememberTermBuffer
  538. (
  539. const TermBuffer tb,
  540. TermLine **referenceLines,
  541. int *referenceLineCount
  542. )
  543. {
  544. int i1;
  545. int i2;
  546. *referenceLineCount = ROWS(tb);
  547. *referenceLines = (TermLine *) XtMalloc(ROWS(tb) * sizeof(TermLine));
  548. /* copy over the lines...
  549. */
  550. for (i1 = 0; i1 < ROWS(tb); i1++) {
  551. (*referenceLines)[i1] = LINE_OF_TBUF(tb, i1);
  552. }
  553. /* verify that they are all unique...
  554. */
  555. /* do a brute force check... */
  556. for (i1 = 0; i1 < ROWS(tb) - 1; i1++) {
  557. for (i2 = i1 + 1; i2 < ROWS(tb); i2++) {
  558. if ((*referenceLines)[i1] == (*referenceLines)[i2]) {
  559. (void) fprintf(stderr,
  560. ">>RememberTermBuffer: dup ptrs lines %d and %d\n",
  561. i1, i2);
  562. }
  563. }
  564. }
  565. }
  566. #ifdef BBA
  567. #pragma BBA_IGNORE
  568. #endif /*BBA*/
  569. static void
  570. CheckTermBuffer
  571. (
  572. const TermBuffer tb,
  573. TermLine *referenceLines,
  574. int referenceLineCount
  575. )
  576. {
  577. int i1;
  578. int i2;
  579. int matchedLine;
  580. if (referenceLineCount != ROWS(tb)) {
  581. for (i1 = 0; i1 < ROWS(tb); i1++) {
  582. matchedLine = -1;
  583. for (i2 = 0; i2 < ROWS(tb); i2++) {
  584. if (referenceLines[i1] == LINE_OF_TBUF(tb, i2)) {
  585. if (matchedLine == -1) {
  586. matchedLine = i2;
  587. } else {
  588. /* duplicate pointer... */
  589. fprintf(stderr,
  590. ">>CheckTermBuffer: duplicate pointer src=%d, dest=%d and %d\n",
  591. i1, matchedLine, i2);
  592. }
  593. }
  594. }
  595. if (matchedLine == -1) {
  596. fprintf(stderr,
  597. ">>CheckTermBuffer: dropped pointer src=%d\n", i1);
  598. }
  599. }
  600. }
  601. if (referenceLines) {
  602. XtFree((char *) referenceLines);
  603. }
  604. }
  605. short
  606. _DtTermPrimBufferGetText
  607. (
  608. const TermBuffer tb,
  609. const short row,
  610. const short col,
  611. const short width,
  612. char *buffer,
  613. const Boolean needWideChar
  614. )
  615. {
  616. short retLen;
  617. short colWidth;
  618. short mbLen;
  619. char *pChar;
  620. wchar_t *pwc;
  621. TermCharInfoRec charInfoFirst;
  622. TermCharInfoRec charInfoLast;
  623. if (!VALID_ROW(tb, row) || !VALID_COL(tb, col))
  624. {
  625. return(0);
  626. }
  627. colWidth = MIN(width, WIDTH(LINE_OF_TBUF(tb, row)) - col);
  628. if (colWidth > 0)
  629. {
  630. _DtTermPrimGetCharacterInfo(tb, row, col, &charInfoFirst);
  631. _DtTermPrimGetCharacterInfo(tb, row, col + colWidth - 1, &charInfoLast);
  632. if ((BYTES_PER_CHAR(tb) > 1) && !needWideChar)
  633. {
  634. /*
  635. ** our caller wants multi-byte characters...
  636. */
  637. retLen = 0;
  638. pChar = buffer;
  639. for (pwc = charInfoFirst.u.pwc; pwc <= charInfoLast.u.pwc; pwc++)
  640. {
  641. mbLen = wctomb(pChar, *pwc);
  642. if (mbLen > 0)
  643. {
  644. pChar += mbLen;
  645. retLen += mbLen;
  646. }
  647. else
  648. {
  649. fprintf(stderr, "_DtTermPrimBufferGetText: invalid wide char.\n");
  650. }
  651. }
  652. }
  653. else
  654. {
  655. retLen = charInfoLast.idx - charInfoFirst.idx + 1;
  656. memcpy(buffer, charInfoFirst.u.pc, retLen);
  657. }
  658. }
  659. else
  660. {
  661. /*
  662. ** colWidth == 0, there is nothing to return
  663. */
  664. retLen = 0;
  665. }
  666. return(retLen);
  667. }
  668. short
  669. _DtTermPrimBufferGetRows
  670. (
  671. const TermBuffer tb
  672. )
  673. {
  674. return(ROWS(tb));
  675. }
  676. short
  677. _DtTermPrimBufferGetCols
  678. (
  679. const TermBuffer tb
  680. )
  681. {
  682. return(COLS(tb));
  683. }
  684. void
  685. _DtTermPrimBufferSetLinks
  686. (
  687. const TermBuffer tb,
  688. const TermBuffer prev,
  689. const TermBuffer next
  690. )
  691. {
  692. PREV_BUFFER(tb) = prev;
  693. NEXT_BUFFER(tb) = next;
  694. }
  695. void
  696. _DtTermPrimBufferSetSelectInfo
  697. (
  698. const TermBuffer tb,
  699. const TermSelectInfo si
  700. )
  701. {
  702. BUFFER_SELECT_INFO(tb) = si;
  703. }
  704. /*
  705. ** Set the desired enhancement; simply call the emulator specific
  706. ** function.
  707. */
  708. int
  709. _DtTermPrimBufferSetEnhancement
  710. (
  711. const TermBuffer tb,
  712. const short row,
  713. const short col,
  714. const unsigned char id,
  715. const enhValue value
  716. )
  717. {
  718. if (SET_ENH(tb))
  719. {
  720. return((*SET_ENH(tb))(tb, row, col, id, value));
  721. }
  722. else
  723. {
  724. return(0);
  725. }
  726. }
  727. /*
  728. ** Get the enhancements for the desired row and column by calling the
  729. ** emulator specific routine.
  730. */
  731. Boolean
  732. _DtTermPrimBufferGetEnhancement
  733. (
  734. const TermBuffer tb,
  735. const short row,
  736. const short col,
  737. enhValue **values,
  738. short *count,
  739. const countSpec countWhich
  740. )
  741. {
  742. if (GET_ENH(tb))
  743. {
  744. return((*GET_ENH(tb))(tb, row, col, values, count, countWhich));
  745. }
  746. else
  747. {
  748. *count = WIDTH(LINE_OF_TBUF(tb, row));
  749. return(True);
  750. }
  751. }
  752. /*
  753. ** Return a pointer to the character at the specified row,col.
  754. */
  755. termChar *
  756. _DtTermPrimBufferGetCharacterPointer
  757. (
  758. const TermBuffer tb,
  759. const short row,
  760. const short col
  761. )
  762. {
  763. TermCharInfoRec charInfo;
  764. if (VALID_ROW(tb, row) && VALID_COL(tb, col))
  765. {
  766. _DtTermPrimGetCharacterInfo(tb, row, col, &charInfo);
  767. return((termChar *)charInfo.u.pc);
  768. }
  769. else
  770. {
  771. return(NULL);
  772. }
  773. }
  774. /*
  775. ** Get the character info for the specified character. If the
  776. ** specified column exceeds the width of the line, then make up
  777. ** some reasonable information, allowing the calling routine to
  778. ** continue in a reasonable fashion.
  779. **
  780. ** XXX: this doesn't get the emulator specific information yet (like
  781. ** enhancements
  782. */
  783. Boolean
  784. _DtTermPrimGetCharacterInfo
  785. (
  786. TermBuffer tb,
  787. short row,
  788. short col,
  789. TermCharInfo charInfo
  790. )
  791. {
  792. wchar_t *pwc;
  793. short charWidth;
  794. TermLine line;
  795. short totalWidth;
  796. if (!VALID_ROW(tb, row))
  797. {
  798. return(False);
  799. }
  800. line = LINE_OF_TBUF(tb, row);
  801. /*
  802. ** handle the easy cases first...
  803. */
  804. if (col >= WIDTH(line))
  805. {
  806. /*
  807. ** make up some reasonable values when col equals or
  808. ** exceeds the width of the line
  809. */
  810. charInfo->u.ptc = NULL;
  811. charInfo->idx = LENGTH(line);
  812. charInfo->len = BYTES_PER_CHAR(tb);
  813. charInfo->startCol = col;
  814. charInfo->width = 1;
  815. charInfo->enh = 0;
  816. charInfo->enhLen = 0;
  817. }
  818. else if (BYTES_PER_CHAR(tb) == 1)
  819. {
  820. /*
  821. ** this is easy in a 1 byte locale...
  822. */
  823. charInfo->u.ptc = BUFFER(line) + col;
  824. charInfo->idx = col;
  825. charInfo->len = BYTES_PER_CHAR(tb);
  826. charInfo->startCol = col;
  827. charInfo->width = 1;
  828. charInfo->enh = 0;
  829. charInfo->enhLen = 0;
  830. }
  831. else if (col == 0)
  832. {
  833. charInfo->u.pwc = (wchar_t *)BUFFER(line);
  834. charInfo->idx = 0;
  835. charInfo->len = BYTES_PER_CHAR(tb);
  836. charInfo->startCol = 0;
  837. charInfo->width = MAX(1, wcwidth(*((wchar_t *)BUFFER(line))));
  838. charInfo->enh = 0;
  839. charInfo->enhLen = 0;
  840. }
  841. else
  842. {
  843. /*
  844. ** not so easy when we're dealing with wchars...
  845. */
  846. if (col <= WIDTH(line) / 2)
  847. {
  848. /*
  849. ** work from left to right
  850. */
  851. totalWidth = 0;
  852. for (pwc = (wchar_t *)BUFFER(line);
  853. pwc < (wchar_t *)BUFFER(line) + LENGTH(line);
  854. pwc++)
  855. {
  856. charWidth = MAX(1, wcwidth(*pwc));
  857. totalWidth += charWidth;
  858. if (col < totalWidth)
  859. {
  860. /*
  861. ** we've found the character, now fill in the info...
  862. */
  863. charInfo->u.pwc = pwc;
  864. charInfo->idx = pwc - (wchar_t *)BUFFER(line);
  865. charInfo->startCol = totalWidth - charWidth;
  866. charInfo->width = charWidth;
  867. break;
  868. }
  869. }
  870. }
  871. else
  872. {
  873. /*
  874. ** work from right to left
  875. */
  876. totalWidth = WIDTH(line);
  877. for (pwc = (wchar_t *)BUFFER(line) + (LENGTH(line) - 1);
  878. pwc >= (wchar_t *)BUFFER(line);
  879. pwc--)
  880. {
  881. charWidth = MAX(1, wcwidth(*pwc));
  882. totalWidth -= charWidth;
  883. if (totalWidth <= col)
  884. {
  885. /*
  886. ** we've found the character, now fill in the info...
  887. */
  888. charInfo->u.pwc = pwc;
  889. charInfo->idx = pwc - (wchar_t *)BUFFER(line);
  890. if (totalWidth == col)
  891. {
  892. charInfo->startCol = col;
  893. }
  894. else
  895. {
  896. charInfo->startCol = col - 1;
  897. }
  898. charInfo->width = charWidth;
  899. break;
  900. }
  901. }
  902. }
  903. charInfo->len = BYTES_PER_CHAR(tb);
  904. charInfo->enh = 0;
  905. charInfo->enhLen = 0;
  906. }
  907. return(True);
  908. }
  909. /*
  910. ** Insert as many characters as possible at the specified row,col
  911. ** return a count of the number of characters bumped off the end of the line
  912. ** in 'returnCount' and a pointer to a buffer containing those characters
  913. ** 'returnChars'.
  914. **
  915. ** The the new width of the line is returned as the value of the function.
  916. */
  917. short
  918. _DtTermPrimBufferInsert
  919. (
  920. const TermBuffer tb,
  921. const short row,
  922. const short col,
  923. const termChar *newChars,
  924. short numChars,
  925. Boolean insertFlag, /* if TRUE, insert, else overwrite */
  926. termChar **returnChars, /* pointer to overflow buffer */
  927. short *returnCount /* count of characters in overflow buffer */
  928. )
  929. {
  930. short insertCount;
  931. short newWidth;
  932. short insertOverflow; /* # of newChars that would overflow */
  933. TermLine line;
  934. termChar *start;
  935. short copyCount; /* number of bytes to copy */
  936. if (!VALID_ROW(tb, row) || !VALID_COL(tb, col))
  937. {
  938. *returnCount = 0;
  939. return(0);
  940. }
  941. line = LINE_OF_TBUF(tb, row);
  942. #ifdef OLD_CODE
  943. /* before we modify the buffer, disown the selection... */
  944. (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
  945. #endif /* OLD_CODE */
  946. /* if this line is part of the selection, disown the selection... */
  947. if (IS_IN_SELECTION(line, col, MAX_SELECTION_COL)) {
  948. (void) _DtTermPrimSelectDisown(WIDGET(tb));
  949. }
  950. if (BYTES_PER_CHAR(tb) > 1)
  951. {
  952. /*
  953. ** we do not handle multibyte characters here...
  954. */
  955. _DtTermPrimBufferInsertWc(tb, row, col, (wchar_t *)newChars,
  956. numChars, insertFlag,
  957. returnChars, returnCount);
  958. return 0;
  959. }
  960. if (WIDTH(line) < col)
  961. {
  962. /*
  963. ** We're adding characters past the current end of line,
  964. ** pad it out.
  965. */
  966. _DtTermPrimBufferPadLine(tb, row, col);
  967. }
  968. insertCount = MIN(numChars, COLS(tb) - col);
  969. copyCount = insertCount * BYTES_PER_CHAR(tb);
  970. start = BUFFER(line) + col;
  971. /*
  972. ** It doesn't matter if we're overwriting, or inserting at the end
  973. ** of the line, the result is the same...
  974. */
  975. if (col == WIDTH(line))
  976. {
  977. insertFlag = False;
  978. }
  979. if (insertFlag == False)
  980. {
  981. /*
  982. ** We're overwriting:
  983. ** - determine the new line width
  984. ** - put any extra new characters into the overflow buffer
  985. **
  986. ** The following will be done later:
  987. ** - copy the newChars into the line buffer
  988. ** - adjust line width (_DtTermPrimBufferSetLineWidth won't
  989. ** let the line get shorter)...
  990. */
  991. newWidth = MAX(WIDTH(line), col + insertCount);
  992. *returnCount = numChars - insertCount;
  993. if (*returnCount > 0)
  994. {
  995. memcpy(*returnChars, newChars + insertCount,
  996. *returnCount * BYTES_PER_CHAR(tb));
  997. }
  998. }
  999. else
  1000. {
  1001. /*
  1002. ** we're inserting text in the middle of the line...
  1003. */
  1004. *returnCount = MAX(0, (WIDTH(line) + numChars) - COLS(tb));
  1005. if (*returnCount > 0)
  1006. {
  1007. /*
  1008. ** we'll have some overflow, figure out how many (if any)
  1009. ** of the new characters will overflow and put them into
  1010. ** the overflow buffer...
  1011. */
  1012. insertOverflow = numChars - insertCount;
  1013. memcpy(*returnChars, newChars + insertCount,
  1014. insertOverflow * BYTES_PER_CHAR(tb));
  1015. /*
  1016. ** copy the displaced characters from the line to the
  1017. ** overflow buffer as well...
  1018. */
  1019. memcpy(*returnChars + insertOverflow, BUFFER(line) +
  1020. (WIDTH(line) - MAX(0, *returnCount - insertOverflow)),
  1021. MAX(0, *returnCount - insertOverflow)
  1022. * BYTES_PER_CHAR(tb));
  1023. }
  1024. /*
  1025. ** Any overflow has been taken care of, now it's time to make
  1026. ** room for the new characters...
  1027. */
  1028. memmove(start + insertCount, start,
  1029. MAX(0, WIDTH(line) - col - *returnCount));
  1030. /*
  1031. ** Compute the new line width...
  1032. */
  1033. newWidth = WIDTH(line) + insertCount;
  1034. }
  1035. /*
  1036. ** Everything's ready:
  1037. ** - put the characters into the line
  1038. ** - adjust the line width (_DtTermPrimBufferSetLineWidth won't
  1039. ** let the line get shorter)...
  1040. ** - update the enhancements
  1041. */
  1042. memcpy(start, newChars, copyCount);
  1043. _DtTermPrimBufferSetLineWidth(tb, row, newWidth);
  1044. insertEnhancements(tb, row, col, insertCount, insertFlag);
  1045. return(WIDTH(line));
  1046. }
  1047. /*
  1048. ** Delete enough characters from the buffer to exceed width.
  1049. **
  1050. ** If returnChars != NULL then the deleted characters are returned
  1051. ** in a buffer pointed to by returnChars. It is the responsibility
  1052. ** of the calling function to XtFree the buffer containing returned
  1053. ** characters when they are no longer needed.
  1054. */
  1055. void
  1056. _DtTermPrimBufferDelete
  1057. (
  1058. TermBuffer tb,
  1059. short *row,
  1060. short *col,
  1061. short *width,
  1062. termChar **returnChars, /* pointer to delete buffer */
  1063. short *returnCount /* count of bytes in delete buffer */
  1064. )
  1065. {
  1066. int copyCount;
  1067. TermLine line;
  1068. short localRow;
  1069. short localCol;
  1070. TermCharInfoRec charInfo;
  1071. if (!VALID_ROW(tb, *row) || !VALID_COL(tb, *col))
  1072. {
  1073. if (returnChars)
  1074. {
  1075. *returnChars = NULL;
  1076. *returnCount = 0;
  1077. }
  1078. return;
  1079. }
  1080. line = LINE_OF_TBUF(tb, *row);
  1081. #ifdef OLD_CODE
  1082. /* before we modify the buffer, disown the selection... */
  1083. (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
  1084. #endif /* OLD_CODE */
  1085. /* if this line is part of the selection, disown the selection... */
  1086. if (IS_IN_SELECTION(line, *col, MAX_SELECTION_COL)) {
  1087. (void) _DtTermPrimSelectDisown(WIDGET(tb));
  1088. }
  1089. if (BYTES_PER_CHAR(tb) > 1)
  1090. {
  1091. /*
  1092. ** we do not handle multibyte characters here...
  1093. */
  1094. _DtTermPrimBufferDeleteWc(tb, row, col, width, returnChars,
  1095. returnCount);
  1096. return;
  1097. }
  1098. localRow = *row;
  1099. localCol = *col;
  1100. *width = MAX(0, MIN(WIDTH(line) - localCol, *width));
  1101. /*
  1102. ** there are 4 cases of deleting a character from a line:
  1103. ** Case 1:
  1104. ** the cursor is past the end of the line (col >= WIDTH(line))
  1105. **
  1106. ** Case 2:
  1107. ** the cursor is in the middle of the line (copyCount > 0)
  1108. ** - move the remaining characters to the left
  1109. ** - deleteEnhancement
  1110. **
  1111. ** Case 3:
  1112. ** the cursor is at the end of the line (copyCount == 0 and
  1113. ** col == WIDTH(line) - 1)
  1114. ** - deleteEnhancement
  1115. ** - adjust WIDTH and LENGTH
  1116. */
  1117. if (localCol >= WIDTH(line) || *width == 0)
  1118. {
  1119. /*
  1120. ** Handle Case 1...
  1121. */
  1122. if (returnChars)
  1123. {
  1124. *returnChars = NULL;
  1125. *returnCount = 0;
  1126. }
  1127. return;
  1128. }
  1129. _DtTermPrimGetCharacterInfo(tb, localRow, localCol, &charInfo);
  1130. /*
  1131. ** Save the current characters before we overwrite them...
  1132. */
  1133. if (returnChars != NULL)
  1134. {
  1135. *returnCount = (*width * BYTES_PER_CHAR(tb));
  1136. *returnChars = (termChar *)XtMalloc(*returnCount);
  1137. memcpy(*returnChars, charInfo.u.pc, *returnCount);
  1138. }
  1139. /*
  1140. ** Cases 2 and 3 require that we delete the enhancement...
  1141. */
  1142. if (DELETE_ENH(tb))
  1143. {
  1144. (*DELETE_ENH(tb))(tb, localRow, localCol, *width);
  1145. }
  1146. copyCount = MAX(0, WIDTH(line) - *width - localCol);
  1147. if (copyCount > 0)
  1148. {
  1149. /*
  1150. ** handle case 2
  1151. */
  1152. memmove(charInfo.u.pc, charInfo.u.pc + *width,
  1153. copyCount * BYTES_PER_CHAR(tb));
  1154. }
  1155. /*
  1156. ** Case 2 and 3 require that we adjust the line width
  1157. */
  1158. WIDTH(line) -= *width;
  1159. LENGTH(line) -= *width;
  1160. }
  1161. /*
  1162. ** replace all characters between startCol, and stopCol with spaces,
  1163. ** if startCol > stopCol, then simply return
  1164. */
  1165. void
  1166. _DtTermPrimBufferErase
  1167. (
  1168. TermBuffer tb,
  1169. short row,
  1170. short startCol,
  1171. short stopCol
  1172. )
  1173. {
  1174. TermCharInfoRec charInfo;
  1175. char *pchar;
  1176. /*
  1177. ** Make sure we have a valid row, and if we have a valid
  1178. ** row, make sure that startCol is <= stopCol
  1179. */
  1180. if (!(VALID_ROW(tb, row)) || (startCol > stopCol))
  1181. {
  1182. return;
  1183. }
  1184. #ifdef OLD_CODE
  1185. /* before we modify the buffer, disown the selection... */
  1186. (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
  1187. #endif /* OLD_CODE */
  1188. /* if this line is part of the selection, disown the selection... */
  1189. if (IS_IN_SELECTION(LINE_OF_TBUF(tb, row), startCol, stopCol)) {
  1190. (void) _DtTermPrimSelectDisown(WIDGET(tb));
  1191. }
  1192. if (BYTES_PER_CHAR(tb) > 1)
  1193. {
  1194. _DtTermPrimBufferEraseWc(tb, row, startCol, stopCol);
  1195. }
  1196. else
  1197. {
  1198. _DtTermPrimGetCharacterInfo(tb, row, startCol, &charInfo);
  1199. pchar = charInfo.u.pc;
  1200. _DtTermPrimGetCharacterInfo(tb, row, stopCol, &charInfo);
  1201. /*
  1202. ** replace the characters with spaces...
  1203. */
  1204. while(pchar <= charInfo.u.pc)
  1205. {
  1206. *pchar = ' ';
  1207. pchar++;
  1208. }
  1209. }
  1210. }
  1211. /*
  1212. ** Adjust the line width, (the line can never be shortened)
  1213. */
  1214. Boolean
  1215. _DtTermPrimBufferSetLineWidth
  1216. (
  1217. const TermBuffer tb,
  1218. const short row,
  1219. short newWidth
  1220. )
  1221. {
  1222. TermLine line;
  1223. /*
  1224. ** Make sure we have a valid row.
  1225. */
  1226. if (!VALID_ROW(tb, row))
  1227. {
  1228. return(False);
  1229. }
  1230. line = LINE_OF_TBUF(tb, row);
  1231. #ifdef OLD_CODE
  1232. /* before we modify the buffer, disown the selection... */
  1233. (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
  1234. #endif /* OLD_CODE */
  1235. /* if this line is part of the selection, disown the selection... */
  1236. if (IS_IN_SELECTION(line, newWidth, MAX_SELECTION_COL)) {
  1237. (void) _DtTermPrimSelectDisown(WIDGET(tb));
  1238. }
  1239. /*
  1240. ** Clip the new width to the buffer width.
  1241. */
  1242. newWidth = MIN(newWidth, COLS(tb));
  1243. /*
  1244. ** Make sure we actually have something to do.
  1245. */
  1246. if (WIDTH(line) >= newWidth)
  1247. {
  1248. return(True);
  1249. }
  1250. WIDTH(line) = newWidth;
  1251. if (BYTES_PER_CHAR(tb) == 1)
  1252. {
  1253. /*
  1254. ** in single byte locales, we go ahead and set the line length too,
  1255. ** it is the responsibility of wide-character routines to set the
  1256. ** line length themselves...
  1257. */
  1258. LENGTH(line) = newWidth; /* works in single byte locales */
  1259. }
  1260. return(True);
  1261. }
  1262. /*
  1263. ** the line length is the lesser of the actual length, or the length
  1264. ** necessary to get to the buffer width
  1265. ** (in the case that the buffer shrank after the line was full)
  1266. */
  1267. short
  1268. _DtTermPrimBufferGetLineLength
  1269. (
  1270. const TermBuffer tb,
  1271. const short row
  1272. )
  1273. {
  1274. short retLen;
  1275. short width;
  1276. TermCharInfoRec charInfo;
  1277. if (VALID_ROW(tb, row))
  1278. {
  1279. width = MIN(WIDTH(LINE_OF_TBUF(tb, row)), COLS(tb));
  1280. if (width > 0)
  1281. {
  1282. (void)_DtTermPrimGetCharacterInfo(tb, row, width - 1, &charInfo);
  1283. /*
  1284. ** a line can not end on column 1 of 2. Note that we must
  1285. ** add 1 to the column index to make it the line length...
  1286. */
  1287. if ((charInfo.width == 2) && (charInfo.startCol != width - 2)) {
  1288. /* only half of charInfo.idx fits in the line, so drop
  1289. * it...
  1290. */
  1291. retLen = charInfo.idx;
  1292. } else {
  1293. /* single column character or double column character that
  1294. * fits on the line...
  1295. */
  1296. retLen = charInfo.idx + 1;
  1297. }
  1298. }
  1299. else
  1300. {
  1301. retLen = 0;
  1302. }
  1303. }
  1304. else
  1305. {
  1306. retLen = 0;
  1307. }
  1308. return(retLen);
  1309. }
  1310. /*
  1311. ** the line width is the lesser of the actual width, or the buffer width
  1312. ** (in the case that the buffer shrank after the line was full)
  1313. */
  1314. short
  1315. _DtTermPrimBufferGetLineWidth
  1316. (
  1317. const TermBuffer tb,
  1318. const short row
  1319. )
  1320. {
  1321. short width = 0;
  1322. TermCharInfoRec charInfo;
  1323. if (VALID_ROW(tb, row))
  1324. {
  1325. width = MIN(WIDTH(LINE_OF_TBUF(tb, row)), COLS(tb));
  1326. if (width > 0)
  1327. {
  1328. (void)_DtTermPrimGetCharacterInfo(tb, row, width - 1, &charInfo);
  1329. /*
  1330. ** a line can not end on column 1 of 2...
  1331. */
  1332. if ((charInfo.width == 2) && (charInfo.startCol != width - 2)) {
  1333. /* only half of charInfo.idx fits in the line, so drop
  1334. * it...
  1335. */
  1336. (void) width--;
  1337. } else {
  1338. /* single column character or double column character that
  1339. * fits on the line...
  1340. */
  1341. }
  1342. }
  1343. }
  1344. return(width);
  1345. }
  1346. /**************************************************************************
  1347. * Function:
  1348. * _DtTermPrimBufferMoveLockArea():
  1349. * move locked screen memory up or down in the screen buffer.
  1350. *
  1351. * Parameters:
  1352. * TermBuffer tb: term buffer to use
  1353. * short dest: point to move the locked region to
  1354. * short src: point to move the locked region from
  1355. * short length: size of the locked region
  1356. *
  1357. * Returns:
  1358. * <nothing>
  1359. *
  1360. * Notes:
  1361. */
  1362. void
  1363. _DtTermPrimBufferMoveLockArea
  1364. (
  1365. const TermBuffer tb,
  1366. const short dest,
  1367. const short src,
  1368. const short length
  1369. )
  1370. {
  1371. TermLine lineCache[10];
  1372. TermLine *holdLines = lineCache;
  1373. TermLine *destPtr;
  1374. TermLine *srcPtr;
  1375. short cacheSize;
  1376. short distance;
  1377. int i;
  1378. int refLineCount;
  1379. TermLine *refLines;
  1380. DebugF('B', 1, RememberTermBuffer(tb,&refLines,&refLineCount));
  1381. /* don't bother if there is we are being asked to do nothing...
  1382. */
  1383. if ((length <= 0) || (dest == src))
  1384. return;
  1385. #ifdef OLD_CODE
  1386. /* before we modify the buffer, disown the selection... */
  1387. (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
  1388. #endif /* OLD_CODE */
  1389. /* before we modify the buffer, check and see if the leading or
  1390. * trailing edge of the buffer crosses the selection and if the
  1391. * destination line crosses the selection. If it does, we need
  1392. * to disown it...
  1393. */
  1394. /* leading edge of src... */
  1395. if ((src > 0) &&
  1396. IS_IN_SELECTION(LINE_OF_TBUF(tb, src - 1), MIN_SELECTION_COL,
  1397. MAX_SELECTION_COL) &&
  1398. IS_IN_SELECTION(LINE_OF_TBUF(tb, src), MIN_SELECTION_COL,
  1399. MAX_SELECTION_COL)) {
  1400. (void) _DtTermPrimSelectDisown(WIDGET(tb));
  1401. }
  1402. /* trailing edge of src... */
  1403. if (((src + length) < ROWS(tb)) &&
  1404. IS_IN_SELECTION(LINE_OF_TBUF(tb, src + length - 1),
  1405. MIN_SELECTION_COL, MAX_SELECTION_COL) &&
  1406. IS_IN_SELECTION(LINE_OF_TBUF(tb, src + length), MIN_SELECTION_COL,
  1407. MAX_SELECTION_COL)) {
  1408. (void) _DtTermPrimSelectDisown(WIDGET(tb));
  1409. }
  1410. /* destination... */
  1411. if ((dest > 0) && IS_IN_SELECTION(LINE_OF_TBUF(tb, dest - 1),
  1412. MIN_SELECTION_COL, MAX_SELECTION_COL) &&
  1413. IS_IN_SELECTION(LINE_OF_TBUF(tb, dest),
  1414. MIN_SELECTION_COL, MAX_SELECTION_COL)) {
  1415. (void) _DtTermPrimSelectDisown(WIDGET(tb));
  1416. }
  1417. /* we need to save the line positions of the smaller of the length
  1418. * of the chunk to move, or the distance to move the chunk.
  1419. */
  1420. distance = (dest > src) ? (dest - src) : (src - dest);
  1421. cacheSize = MIN(length, distance);
  1422. /* if we are moving more lines than will fit in the lineCache, we need
  1423. * to malloc (and free) storage for the termLineRecs...
  1424. */
  1425. if (cacheSize > (sizeof(lineCache) / sizeof(lineCache[0]))) {
  1426. holdLines = (TermLine *) XtMalloc(cacheSize * sizeof(TermLine));
  1427. }
  1428. /*
  1429. ** clear the wrap flag for the line preceding the block to be
  1430. ** moved, and the last line of the block to be moved
  1431. */
  1432. _DtTermPrimBufferSetLineWrapFlag(tb, src - 1, FALSE);
  1433. _DtTermPrimBufferSetLineWrapFlag(tb, src + length, FALSE);
  1434. /* cache them away... */
  1435. if (distance > length) {
  1436. /* save away the locked area... */
  1437. destPtr = holdLines;
  1438. srcPtr = &(LINE_OF_TBUF(tb, src));
  1439. for (i = 0; i < length; i++) {
  1440. *destPtr++ = *srcPtr++;
  1441. }
  1442. /* move the area above/below the locked area... */
  1443. if (dest > src) {
  1444. /* we are moving the locked area down, so we must move
  1445. * the scroll area up...
  1446. */
  1447. destPtr = &(LINE_OF_TBUF(tb, src));
  1448. srcPtr = &(LINE_OF_TBUF(tb, src + length));
  1449. for (i = 0; i < distance; i++) {
  1450. *destPtr++ = *srcPtr++;
  1451. }
  1452. } else {
  1453. /* we are moving the locked area up, so we must move
  1454. * the scroll area down...
  1455. */
  1456. destPtr = &(LINE_OF_TBUF(tb, src + length - 1));
  1457. srcPtr = &(LINE_OF_TBUF(tb, src - 1));
  1458. for (i = 0; i < distance; i++) {
  1459. *destPtr-- = *srcPtr--;
  1460. }
  1461. }
  1462. /* restore the cached lock area... */
  1463. destPtr = &(LINE_OF_TBUF(tb, dest));
  1464. srcPtr = holdLines;
  1465. for (i = 0; i < length; i++) {
  1466. *destPtr++ = *srcPtr++;
  1467. }
  1468. } else {
  1469. /* save away the area we will move the lock area over...
  1470. */
  1471. if (dest > src) {
  1472. /* moving it down. Save the area under the lock area...
  1473. */
  1474. destPtr = holdLines;
  1475. srcPtr = &(LINE_OF_TBUF(tb, src + length));
  1476. for (i = 0; i < distance; i++) {
  1477. *destPtr++ = *srcPtr++;
  1478. }
  1479. /* move the lock area down... */
  1480. destPtr = &(LINE_OF_TBUF(tb, dest + length - 1));
  1481. srcPtr = &(LINE_OF_TBUF(tb, src + length - 1));
  1482. for (i = 0; i < length; i++) {
  1483. *destPtr-- = *srcPtr--;
  1484. }
  1485. /* restore the area under (that is now over) the lock area... */
  1486. destPtr = &(LINE_OF_TBUF(tb, src));
  1487. srcPtr = holdLines;
  1488. for (i = 0; i < distance; i++) {
  1489. *destPtr++ = *srcPtr++;
  1490. }
  1491. } else {
  1492. /* moving it up. Save the area over the lock area...
  1493. */
  1494. destPtr = holdLines;
  1495. srcPtr = &(LINE_OF_TBUF(tb, dest));
  1496. for (i = 0; i < distance; i++) {
  1497. *destPtr++ = *srcPtr++;
  1498. }
  1499. /* move the lock area up... */
  1500. destPtr = &(LINE_OF_TBUF(tb, dest));
  1501. srcPtr = &(LINE_OF_TBUF(tb, src));
  1502. for (i = 0; i < length; i++) {
  1503. *destPtr++ = *srcPtr++;
  1504. }
  1505. /* restore the area over (that is now under) the lock area... */
  1506. destPtr = &(LINE_OF_TBUF(tb, dest + length));
  1507. srcPtr = holdLines;
  1508. for (i = 0; i < distance; i++) {
  1509. *destPtr++ = *srcPtr++;
  1510. }
  1511. }
  1512. }
  1513. /* free up the holdLines (if we malloc'ed it)... */
  1514. if (holdLines != lineCache) {
  1515. (void) XtFree((char *) holdLines);
  1516. }
  1517. DebugF('B', 1, CheckTermBuffer(tb,refLines,refLineCount));
  1518. }
  1519. /**************************************************************************
  1520. * Function:
  1521. * _DtTermPrimBufferInsertLine(): insert one or more lines of text from
  1522. * the end of the buffer below the insertion point, or from
  1523. * the beginning of the buffer above the insertion point.
  1524. *
  1525. * Parameters:
  1526. * TermBuffer tb: term buffer to insert end/begining into
  1527. * short dest: point to insert below/above
  1528. * short length: number of lines to insert
  1529. * short src: source point of insertion
  1530. *
  1531. * Returns:
  1532. * <nothing>
  1533. *
  1534. * Notes:
  1535. */
  1536. void
  1537. _DtTermPrimBufferInsertLine
  1538. (
  1539. const TermBuffer tb,
  1540. const short dest,
  1541. const short length,
  1542. const short src
  1543. )
  1544. {
  1545. TermLine lineCache[10];
  1546. TermLine *holdLines = lineCache;
  1547. TermLine *destPtr;
  1548. TermLine *srcPtr;
  1549. short distance;
  1550. int i;
  1551. int refLineCount;
  1552. TermLine *refLines;
  1553. DebugF('B', 1, RememberTermBuffer(tb,&refLines,&refLineCount));
  1554. /* don't bother if there is we are being asked to do nothing...
  1555. */
  1556. if (length <= 0)
  1557. return;
  1558. #ifdef OLD_CODE
  1559. /* before we modify the buffer, disown the selection... */
  1560. (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
  1561. #endif /* OLD_CODE */
  1562. /* before we modify the buffer, check and see if the
  1563. * destination line crosses the selection. If it does, we need
  1564. * to disown it...
  1565. */
  1566. /* destination... */
  1567. if (dest > src) {
  1568. if (((dest + length) < ROWS(tb)) &&
  1569. IS_IN_SELECTION(LINE_OF_TBUF(tb, dest + length),
  1570. MIN_SELECTION_COL, MAX_SELECTION_COL) &&
  1571. IS_IN_SELECTION(LINE_OF_TBUF(tb, dest + length + 1),
  1572. MIN_SELECTION_COL, MAX_SELECTION_COL)) {
  1573. (void) _DtTermPrimSelectDisown(WIDGET(tb));
  1574. }
  1575. } else {
  1576. if (dest > 1) {
  1577. if (IS_IN_SELECTION(LINE_OF_TBUF(tb, dest),
  1578. MIN_SELECTION_COL, MAX_SELECTION_COL) &&
  1579. IS_IN_SELECTION(LINE_OF_TBUF(tb, dest - 1),
  1580. MIN_SELECTION_COL, MAX_SELECTION_COL)) {
  1581. (void) _DtTermPrimSelectDisown(WIDGET(tb));
  1582. }
  1583. }
  1584. }
  1585. /* if we are being asked to move all (or more) the lines in the
  1586. * buffer, then we can just clear them all out and return...
  1587. */
  1588. if (length >= ROWS(tb)) {
  1589. for (i = 0; i < ROWS(tb); i++) {
  1590. _DtTermPrimBufferClearLine(tb, i, 0);
  1591. }
  1592. return;
  1593. }
  1594. /* if dest and src match, we can just clear them out and return...
  1595. */
  1596. if (src == dest) {
  1597. for (i = 0; (i < length) && ((i + dest) < ROWS(tb)); i++) {
  1598. _DtTermPrimBufferClearLine(tb, src + i, 0);
  1599. }
  1600. return;
  1601. }
  1602. /* if we are moving more lines than will fit in the lineCache, we need
  1603. * to malloc (and free) storage for the termLineRecs...
  1604. */
  1605. if (length > (sizeof(lineCache) / sizeof(lineCache[0]))) {
  1606. holdLines = (TermLine *) XtMalloc(length * sizeof(TermLine));
  1607. }
  1608. if (dest > src) {
  1609. /* our src is above the destination. Copy the lines to insert,
  1610. * move the lines above the insertion pointer up, and insert
  1611. * the saved lines...
  1612. */
  1613. /* save away the top length lines... */
  1614. destPtr = holdLines;
  1615. srcPtr = &(LINE_OF_TBUF(tb, src));
  1616. for (i = 0; i < length; i++) {
  1617. /* these lines will be cleared, so we don't need to track
  1618. * movement of them...
  1619. */
  1620. *destPtr++ = *srcPtr++;
  1621. }
  1622. /* copy the lines above the insertion point up... */
  1623. destPtr = &(LINE_OF_TBUF(tb, src));
  1624. srcPtr = &(LINE_OF_TBUF(tb, src + length));
  1625. for (i = src; i < dest - length + 1; i++) {
  1626. *destPtr++ = *srcPtr++;
  1627. }
  1628. /* restore the saved lines above the insertion point... */
  1629. destPtr = &(LINE_OF_TBUF(tb, dest - length + 1));
  1630. srcPtr = holdLines;
  1631. for (i = 0; i < length; i++) {
  1632. *destPtr = *srcPtr;
  1633. /* clear the line... */
  1634. _DtTermPrimBufferClearLine(tb, dest - length + 1 + i, 0);
  1635. *destPtr++;
  1636. *srcPtr++;
  1637. }
  1638. #ifdef DONT_DO_THIS_ANY_MORE
  1639. /* Adjust or disown selection */
  1640. _DtTermPrimSelectDeleteLine(tb,length) ;
  1641. #endif /* DONT_DO_THIS_ANY_MORE */
  1642. } else {
  1643. /* our src is below the destination. Copy the lines to insert,
  1644. * move the lines below the insertion pointer down, and insert
  1645. * the saved lines...
  1646. */
  1647. /* save away the bottom length lines... */
  1648. destPtr = holdLines;
  1649. srcPtr = &(LINE_OF_TBUF(tb, src));
  1650. for (i = 0; i < length; i++) {
  1651. *destPtr++ = *srcPtr++;
  1652. }
  1653. /* copy the lines below the insertion point down... */
  1654. destPtr = &(LINE_OF_TBUF(tb, src + length - 1));
  1655. srcPtr = &(LINE_OF_TBUF(tb, src - 1));
  1656. for (i = 0; i < src - dest; i++) {
  1657. *destPtr-- = *srcPtr--;
  1658. }
  1659. /* restore the saved lines below the insertion point... */
  1660. destPtr = &(LINE_OF_TBUF(tb, dest));
  1661. srcPtr = holdLines;
  1662. for (i = 0; i < length; i++) {
  1663. *destPtr = *srcPtr;
  1664. /* clear the line... */
  1665. _DtTermPrimBufferClearLine(tb, dest + i, 0);
  1666. *destPtr++;
  1667. *srcPtr++;
  1668. }
  1669. }
  1670. /* free up the holdLines (if we malloc'ed it)... */
  1671. if (holdLines != lineCache) {
  1672. (void) XtFree((char *) holdLines);
  1673. }
  1674. DebugF('B', 1, CheckTermBuffer(tb,refLines,refLineCount));
  1675. }
  1676. /**************************************************************************
  1677. * Function:
  1678. * _DtTermPrimBufferInsertLineFromTB(): insert one or more lines
  1679. * of text from the end of the buffer below the insertion
  1680. * point, or from the beginning of the buffer above the
  1681. * insertion point.
  1682. *
  1683. * Parameters:
  1684. * TermBuffer tb: term buffer to insert end/begining into
  1685. * short dest: point to insert below/above
  1686. * short length: number of lines to insert
  1687. * InsertSource: source of insertion (end or beginning)
  1688. *
  1689. * Returns:
  1690. * <nothing>
  1691. *
  1692. * Notes:
  1693. */
  1694. void
  1695. _DtTermPrimBufferInsertLineFromTB
  1696. (
  1697. const TermBuffer tb,
  1698. const short dest,
  1699. const short length,
  1700. const InsertSource insertSource
  1701. )
  1702. {
  1703. if (insertSource == insertFromTop) {
  1704. (void) _DtTermPrimBufferInsertLine(tb, dest, length, 0);
  1705. } else {
  1706. (void) _DtTermPrimBufferInsertLine(tb, dest, length,
  1707. ROWS(tb) - length);
  1708. }
  1709. }
  1710. /**************************************************************************
  1711. * Function:
  1712. * _DtTermPrimBufferDeleteLine(): deletes one or more lines of text from
  1713. * the deletion poing and sticks them at the end of the
  1714. * line buffer. It does not clear the line. That is
  1715. * normally done when the line is inserted.
  1716. *
  1717. * Parameters:
  1718. * TermBuffer tb: term buffer to insert end/begining into
  1719. * short source: point to insert below/above
  1720. * short length: number of lines to insert
  1721. * short lastUsedLine: number of last line in the buffer we need
  1722. * to keep
  1723. *
  1724. * Returns:
  1725. * <nothing>
  1726. *
  1727. * Notes:
  1728. */
  1729. void
  1730. _DtTermPrimBufferDeleteLine
  1731. (
  1732. const TermBuffer tb,
  1733. const short source,
  1734. const short length,
  1735. const short lastUsedRow
  1736. )
  1737. {
  1738. TermLine lineCache[10];
  1739. TermLine *holdLines = lineCache;
  1740. TermLine *destPtr;
  1741. TermLine *srcPtr;
  1742. short copyLength;
  1743. int i;
  1744. int refLineCount;
  1745. TermLine *refLines;
  1746. DebugF('B', 1, RememberTermBuffer(tb,&refLines,&refLineCount));
  1747. /* don't bother if there is we are being asked to do nothing...
  1748. */
  1749. if (length <= 0)
  1750. return;
  1751. /* if we are being asked to move the last usedLines, we don't have
  1752. * to do anything either...
  1753. */
  1754. if (source + length >= lastUsedRow)
  1755. return;
  1756. #ifdef OLD_CODE
  1757. /* before we modify the buffer, disown the selection... */
  1758. (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
  1759. #endif /* OLD_CODE */
  1760. /* if we are moving more lines than will fit in the lineCache, we need
  1761. * to malloc (and free) storage for the termLineRecs...
  1762. */
  1763. if (length > (sizeof(lineCache) / sizeof(lineCache[0]))) {
  1764. holdLines = (TermLine *) XtMalloc(length * sizeof(TermLine));
  1765. }
  1766. /* clear the deleted lines... */
  1767. for (i = 0; i < length; i++) {
  1768. (void) _DtTermPrimBufferClearLine(tb, source + i, 0);
  1769. }
  1770. #ifdef USE_MEMCPY
  1771. (void) memcpy(holdLines, &(LINE_OF_TBUF(tb, source)), length *
  1772. sizeof(TermLine));
  1773. #else /* USE_MEMCPY */
  1774. destPtr = holdLines;
  1775. srcPtr = &(LINE_OF_TBUF(tb, source));
  1776. for (i = 0; i < length; i++) {
  1777. *destPtr++ = *srcPtr++;
  1778. }
  1779. #endif /* USE_MEMCPY */
  1780. /* ripple up the lines... */
  1781. copyLength = MAX(0, MIN(ROWS(tb), lastUsedRow) - source - length);
  1782. if (copyLength > 0) {
  1783. #ifdef USE_MEMCPY
  1784. (void) memmove(&(LINE_OF_TBUF(tb, source)),
  1785. &(LINE_OF_TBUF(tb, source + length)),
  1786. copyLength * sizeof(TermLine));
  1787. #else /* USE_MEMCPY */
  1788. destPtr = &(LINE_OF_TBUF(tb, source));
  1789. srcPtr = &(LINE_OF_TBUF(tb, source + length));
  1790. for (i = 0; i < copyLength; i++) {
  1791. *destPtr++ = *srcPtr++;
  1792. }
  1793. #endif /* USE_MEMCPY */
  1794. }
  1795. /* copy back the deleted (cached) lines... */
  1796. #ifdef USE_MEMCPY
  1797. (void) memcpy(&(LINE_OF_TBUF(tb, source + copyLength)), holdLines,
  1798. length * sizeof(TermLine));
  1799. #else /* USE_MEMCPY */
  1800. destPtr = &(LINE_OF_TBUF(tb, source + copyLength));
  1801. srcPtr = holdLines;
  1802. for (i = 0; i < length; i++) {
  1803. *destPtr++ = *srcPtr++;
  1804. }
  1805. #endif /* USE_MEMCPY */
  1806. /* free up the holdLines (if we malloc'ed it)... */
  1807. if (holdLines != lineCache) {
  1808. (void) XtFree((char *) holdLines);
  1809. }
  1810. DebugF('B', 1, CheckTermBuffer(tb,refLines,refLineCount));
  1811. }
  1812. /*
  1813. ** Pad the requested row from the current width to 'newWidth' with spaces...
  1814. */
  1815. void
  1816. _DtTermPrimBufferPadLine
  1817. (
  1818. const TermBuffer tb,
  1819. const short row,
  1820. const short newWidth
  1821. )
  1822. {
  1823. TermLine line;
  1824. #ifdef OLD_CODE
  1825. /* before we modify the buffer, disown the selection... */
  1826. (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
  1827. #endif /* OLD_CODE */
  1828. line = LINE_OF_TBUF(tb, row);
  1829. /* if this line is part of the selection, disown the selection... */
  1830. if (IS_IN_SELECTION(line, MIN(newWidth, WIDTH(line)),
  1831. MAX(newWidth, WIDTH(line)))) {
  1832. (void) _DtTermPrimSelectDisown(WIDGET(tb));
  1833. }
  1834. (void)memset(BUFFER(line) + WIDTH(line),
  1835. 0x20, (newWidth - WIDTH(line)) * BYTES_PER_CHAR(tb));
  1836. if (CLEAR_ENH(tb))
  1837. {
  1838. (*CLEAR_ENH(tb))(tb, row, WIDTH(line), newWidth - WIDTH(line));
  1839. }
  1840. _DtTermPrimBufferSetLineWidth(tb, row, newWidth);
  1841. }
  1842. /*
  1843. ** Clear the line to the new width (just reset the line width).
  1844. ** NOTES:
  1845. ** We also clear the wrapped flag as well.
  1846. */
  1847. Boolean
  1848. _DtTermPrimBufferClearLine
  1849. (
  1850. const TermBuffer tb,
  1851. const short row,
  1852. short newWidth
  1853. )
  1854. {
  1855. TermLine line;
  1856. #ifdef OLD_CODE
  1857. /* before we modify the buffer, disown the selection... */
  1858. (void) _DtTermPrimSelectDisownIfNecessary(WIDGET(tb));
  1859. #endif /* OLD_CODE */
  1860. /*
  1861. ** handle multi-byte locales...
  1862. */
  1863. if (BYTES_PER_CHAR(tb) > 1)
  1864. {
  1865. return(_DtTermPrimBufferClearLineWc(tb, row, newWidth));
  1866. }
  1867. /*
  1868. ** Some simple bounds checking.
  1869. */
  1870. if (!VALID_ROW(tb, row))
  1871. {
  1872. return(False);
  1873. }
  1874. line = LINE_OF_TBUF(tb, row);
  1875. /* if this line is part of the selection, disown the selection... */
  1876. if (IS_IN_SELECTION(line, MIN(newWidth, WIDTH(line)),
  1877. MAX(newWidth, WIDTH(line)))) {
  1878. (void) _DtTermPrimSelectDisown(WIDGET(tb));
  1879. }
  1880. /*
  1881. ** Clip the new width to the buffer width.
  1882. */
  1883. newWidth = MIN(newWidth, COLS(tb));
  1884. /*
  1885. ** force width to the desired value
  1886. **
  1887. ** (We take the direct approach because _DtTermPrimBufferSetLineWidth
  1888. ** doesn't allow the line width to decrease.)
  1889. */
  1890. if (newWidth < WIDTH(line))
  1891. {
  1892. /*
  1893. ** Call the helper function if it exists
  1894. */
  1895. if (CLEAR_LINE(tb))
  1896. {
  1897. (*CLEAR_LINE(tb))(tb, row, newWidth);
  1898. }
  1899. WRAPPED(line) = False;
  1900. WIDTH(line) = newWidth;
  1901. LENGTH(line) = newWidth; /* this works in single-byte locales */
  1902. }
  1903. return(True);
  1904. }
  1905. short
  1906. _DtTermPrimBufferGetNextTab
  1907. (
  1908. const TermBuffer tb,
  1909. short col
  1910. )
  1911. {
  1912. if (!VALID_COL(tb, col))
  1913. {
  1914. return(0);
  1915. }
  1916. /* find the next set tab stop... */
  1917. for (col++; (col < COLS(tb)) && (!TABS(tb)[col]); col++)
  1918. ;
  1919. /* did we go to the end of the line w/out hitting one?... */
  1920. if (col >= COLS(tb)) {
  1921. return(0);
  1922. } else {
  1923. return(col);
  1924. }
  1925. }
  1926. short
  1927. _DtTermPrimBufferGetPreviousTab
  1928. (
  1929. const TermBuffer tb,
  1930. short col
  1931. )
  1932. {
  1933. if (!VALID_COL(tb, col - 1))
  1934. {
  1935. return(0);
  1936. }
  1937. /* find the next set tab stop... */
  1938. for (col--; (col > 0) && (!TABS(tb)[col]); col--)
  1939. ;
  1940. /* we can just return col. If ther was not another tab stop, it will
  1941. * be -1...
  1942. */
  1943. return(col);
  1944. }
  1945. Boolean
  1946. _DtTermPrimBufferSetTab
  1947. (
  1948. const TermBuffer tb,
  1949. const short col
  1950. )
  1951. {
  1952. if (VALID_COL(tb, col))
  1953. {
  1954. TABS(tb)[col] = True;
  1955. return(True);
  1956. }
  1957. return(False);
  1958. }
  1959. Boolean
  1960. _DtTermPrimBufferClearTab
  1961. (
  1962. const TermBuffer tb,
  1963. const short col
  1964. )
  1965. {
  1966. if (VALID_COL(tb, col))
  1967. {
  1968. TABS(tb)[col] = False;
  1969. return(True);
  1970. }
  1971. return(False);
  1972. }
  1973. Boolean
  1974. _DtTermPrimBufferClearAllTabs
  1975. (
  1976. const TermBuffer tb
  1977. )
  1978. {
  1979. (void) memset(TABS(tb), '\0', COLS(tb) * sizeof(Boolean));
  1980. return(True);
  1981. }
  1982. /*
  1983. ** Set the line wrap flag to the desired state.
  1984. */
  1985. void
  1986. _DtTermPrimBufferSetLineWrapFlag
  1987. (
  1988. TermBuffer tb,
  1989. short row,
  1990. Boolean state
  1991. )
  1992. {
  1993. if (VALID_ROW(tb, row))
  1994. {
  1995. WRAPPED(LINE_OF_TBUF(tb, row)) = state;
  1996. }
  1997. return;
  1998. }
  1999. /*
  2000. ** Return the state of the line wrap flag.
  2001. */
  2002. Boolean
  2003. _DtTermPrimBufferTestLineWrapFlag
  2004. (
  2005. TermBuffer tb,
  2006. short row
  2007. )
  2008. {
  2009. if (VALID_ROW(tb, row))
  2010. {
  2011. return(WRAPPED(LINE_OF_TBUF(tb, row)));
  2012. }
  2013. else
  2014. {
  2015. return(FALSE);
  2016. }
  2017. }
  2018. /*
  2019. ** Set the in selection flag to the desired state.
  2020. */
  2021. void
  2022. _DtTermPrimBufferSetInSelectionFlag
  2023. (
  2024. TermBuffer tb,
  2025. short row,
  2026. TermLineSelection state
  2027. )
  2028. {
  2029. if (VALID_ROW(tb, row))
  2030. {
  2031. if (state) {
  2032. START_SELECTION(LINE_OF_TBUF(tb, row)) = state->selectionStart;
  2033. END_SELECTION(LINE_OF_TBUF(tb, row)) = state->selectionEnd;
  2034. } else {
  2035. START_SELECTION(LINE_OF_TBUF(tb, row)) = NON_SELECTION_COL;
  2036. END_SELECTION(LINE_OF_TBUF(tb, row)) = NON_SELECTION_COL;
  2037. }
  2038. }
  2039. return;
  2040. }
  2041. /*
  2042. ** Return the state of the in selection flag.
  2043. */
  2044. TermLineSelection
  2045. _DtTermPrimBufferGetInSelectionFlag
  2046. (
  2047. TermBuffer tb,
  2048. short row
  2049. )
  2050. {
  2051. if (VALID_ROW(tb, row))
  2052. {
  2053. if ((START_SELECTION(LINE_OF_TBUF(tb, row)) != NON_SELECTION_COL) &&
  2054. (END_SELECTION(LINE_OF_TBUF(tb, row)) != NON_SELECTION_COL)) {
  2055. return(&IN_SELECTION(LINE_OF_TBUF(tb, row)));
  2056. }
  2057. }
  2058. return((TermLineSelection) 0);
  2059. }
  2060. void
  2061. _DtTermPrimBufferSetSelectLines
  2062. (
  2063. TermBuffer tb,
  2064. short beginRow,
  2065. short beginCol,
  2066. short endRow,
  2067. short endCol
  2068. )
  2069. {
  2070. int i1;
  2071. for (i1 = 0; i1 < ROWS(tb); i1++) {
  2072. if ((i1 >= beginRow) && (i1 <= endRow)) {
  2073. if (i1 == beginRow) {
  2074. START_SELECTION(LINE_OF_TBUF(tb, i1)) = beginCol;
  2075. } else {
  2076. START_SELECTION(LINE_OF_TBUF(tb, i1)) = MIN_SELECTION_COL;
  2077. }
  2078. if (i1 == endRow) {
  2079. END_SELECTION(LINE_OF_TBUF(tb, i1)) = endCol;
  2080. } else {
  2081. END_SELECTION(LINE_OF_TBUF(tb, i1)) = MAX_SELECTION_COL;
  2082. }
  2083. } else {
  2084. START_SELECTION(LINE_OF_TBUF(tb, i1)) = NON_SELECTION_COL;
  2085. END_SELECTION(LINE_OF_TBUF(tb, i1)) = NON_SELECTION_COL;
  2086. }
  2087. }
  2088. }
  2089. #if (defined(TEST) || defined(__CODECENTER__) || defined(DEBUG))
  2090. static void
  2091. _termBufferPrintLine
  2092. (
  2093. const TermBuffer tb,
  2094. const short row
  2095. )
  2096. {
  2097. TermLine line;
  2098. termChar *pChar;
  2099. short j;
  2100. printf("Line: %d\n", row);
  2101. line = LINE_OF_TBUF(tb, row];
  2102. printf(" width: %3d\n", WIDTH(line));
  2103. printf(" length: %3d\n", LENGTH(line));
  2104. if (LENGTH(line) > 0)
  2105. {
  2106. printf(" buffer: <");
  2107. pChar = BUFFER(line);
  2108. for (j = 0; j < LENGTH(line); j++)
  2109. {
  2110. printf("%X", *pChar++);
  2111. }
  2112. printf(">\n");
  2113. }
  2114. }
  2115. /*
  2116. ** Print the contents of the TermBuffer.
  2117. */
  2118. static void
  2119. _termBufferPrintBuffer
  2120. (
  2121. const TermBuffer tb
  2122. )
  2123. {
  2124. short i;
  2125. short j;
  2126. short k;
  2127. if (tb == NULL) {
  2128. printf("TermBuffer has been freed.\n");
  2129. return;
  2130. }
  2131. printf("TermBuffer dimensions:\n");
  2132. printf(" rows: %d\n", ROWS(tb));
  2133. printf(" cols: %d\n", COLS(tb));
  2134. for (i = 0; i < ROWS(tb); i++)
  2135. {
  2136. _termBufferPrintLine(tb, i);
  2137. }
  2138. }
  2139. #endif /* (defined(TEST) || defined(__CODECENTER__)) */
  2140. #ifdef TEST
  2141. /*
  2142. ** Some simple tests of the termBuffer.
  2143. */
  2144. /* the following is to allow for a single main function in the code... */
  2145. #define termBufMain main
  2146. termBufMain()
  2147. {
  2148. const TermBuffer myTB;
  2149. printf("Sizeof termEnhRec : %d\n", sizeof(struct _termEnhRec));
  2150. printf("Sizeof termBufferRec : %d\n", sizeof(struct _TermBufferRec));
  2151. myTB = _DtTermPrimBufferCreateBuffer(12, 80);
  2152. _termBufferPrintBuffer(myTB);
  2153. printf("[0,0] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 0, enhVideo, BLINK));
  2154. _termBufferPrintEnhancement(myTB, 0, 0);
  2155. printf("[0,1] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 1, enhVideo, INVERSE));
  2156. _termBufferPrintEnhancement(myTB, 0, 0);
  2157. _termBufferPrintEnhancement(myTB, 0, 1);
  2158. printf("[0,9] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 9, enhVideo, UNDERLINE));
  2159. _termBufferPrintEnhancement(myTB, 0, 0);
  2160. _termBufferPrintEnhancement(myTB, 0, 1);
  2161. _termBufferPrintEnhancement(myTB, 0, 9);
  2162. printf("[0,6] %d\n", _DtTermPrimBufferSetEnhancement(myTB, 0, 6, enhVideo, HALF_BRIGHT));
  2163. _termBufferPrintEnhancement(myTB, 0, 0);
  2164. _termBufferPrintEnhancement(myTB, 0, 1);
  2165. _termBufferPrintEnhancement(myTB, 0, 6);
  2166. _termBufferPrintEnhancement(myTB, 0, 9);
  2167. _termBufferPrintBuffer(myTB);
  2168. _DtTermPrimBufferSetEnhancement(myTB, 10, 10, enhVideo, BLINK);
  2169. _DtTermPrimBufferSetEnhancement(myTB, 10, 20, enhColor, 3);
  2170. _termBufferPrintBuffer(myTB);
  2171. _DtTermPrimBufferResizeBuffer(&myTB, 6, 40);
  2172. _termBufferPrintBuffer(myTB);
  2173. _DtTermPrimBufferSetEnhancement(myTB, 10, 10, enhVideo, BLINK);
  2174. _DtTermPrimBufferResizeBuffer(&myTB, 12, 80);
  2175. _termBufferPrintBuffer(myTB);
  2176. _DtTermPrimBufferFreeBuffer(myTB);
  2177. }
  2178. #endif /* TEST */