Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

778 lines
20 KiB

  1. /* File: D:\WACKER\tdll\termupd.c (Created: 11-Dec-1993)
  2. *
  3. * Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
  4. * All rights reserved
  5. *
  6. * $Revision: 7 $
  7. * $Date: 3/27/02 1:35p $
  8. */
  9. #include <windows.h>
  10. #pragma hdrstop
  11. #include <stdlib.h>
  12. #include <limits.h>
  13. #include "stdtyp.h"
  14. #include "assert.h"
  15. #include "session.h"
  16. #include <emu\emu.h>
  17. #include <emu\emu.hh>
  18. #include "update.h"
  19. #include "update.hh"
  20. #include "backscrl.h"
  21. #include "timers.h"
  22. #include "tdll.h"
  23. #include "htchar.h"
  24. #include "term.h"
  25. #include "term.hh"
  26. #include "mc.h"
  27. static void termUpdate(const HHTERM hhTerm);
  28. static int termReallocBkBuf(const HHTERM hhTerm, const int iLines);
  29. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  30. * FUNCTION:
  31. * termGetUpdate
  32. *
  33. * DESCRIPTION:
  34. * Queries the update records and emulator to update the terminal image.
  35. *
  36. * ARGUMENTS:
  37. * hhTerm - internal terminal handle.
  38. *
  39. * RETURNS:
  40. * void
  41. *
  42. */
  43. void termGetUpdate(const HHTERM hhTerm, const int fRedraw)
  44. {
  45. ECHAR **pachTxt,
  46. *pachTermTxt,
  47. *pachEmuTxt;
  48. PSTATTR *pstAttr,
  49. pstTermAttr,
  50. pstEmuAttr;
  51. int i, j, k, m;
  52. BYTE *pabLines;
  53. // const iRows = hhTerm->iRows;
  54. // const iCols = hhTerm->iCols;
  55. const iRows = MAX_EMUROWS;
  56. const iCols = MAX_EMUCOLS;
  57. const HEMU hEmu = sessQueryEmuHdl(hhTerm->hSession);
  58. const HHUPDATE hUpd = (HHUPDATE)sessQueryUpdateHdl(hhTerm->hSession);
  59. /* --- Lock emulators so we have execlusive access --- */
  60. emuLock(hEmu);
  61. pachTxt = emuGetTxtBuf(hEmu);
  62. pstAttr = emuGetAttrBuf(hEmu);
  63. // Now check to see what needs updating...
  64. if (hUpd->bUpdateType == UPD_LINE)
  65. {
  66. struct stLineMode *pstLine = &hUpd->stLine;
  67. if (pstLine->iLine != -1)
  68. {
  69. // The emulators can place the cursor one past the number
  70. // of columns. Why, I don't know, so we check and adjust
  71. // so we don't overwrite our client arrays.
  72. pstLine->xEnd = min(pstLine->xEnd, iCols);
  73. assert(pstLine->xBeg <= pstLine->xEnd);
  74. k = (pstLine->iLine + hUpd->iTopline) % MAX_EMUROWS;
  75. pachEmuTxt = pachTxt[k] + pstLine->xBeg;
  76. pachTermTxt = hhTerm->fplpstrTxt[k] + pstLine->xBeg;
  77. pstEmuAttr = pstAttr[k] + pstLine->xBeg;
  78. pstTermAttr = hhTerm->fppstAttr[k] + pstLine->xBeg;
  79. for (k = pstLine->xEnd - pstLine->xBeg ; k >= 0 ; --k)
  80. {
  81. // Televideo uses \xFF as a NULL character.
  82. if (*pachEmuTxt == ETEXT('\0') || *pachEmuTxt == ETEXT('\xFF'))
  83. *pachTermTxt = ETEXT(' ');
  84. else
  85. *pachTermTxt = *pachEmuTxt;
  86. *pstTermAttr = *pstEmuAttr;
  87. pachTermTxt += 1;
  88. pachEmuTxt += 1;
  89. pstTermAttr += 1;
  90. pstEmuAttr += 1;
  91. }
  92. }
  93. }
  94. else if (hUpd->bUpdateType == UPD_SCROLL)
  95. {
  96. struct stScrlMode *pstScrl = &hUpd->stScrl;
  97. hUpd->iLines = hhTerm->iBkLines =
  98. backscrlGetNumLines(sessQueryBackscrlHdl(hhTerm->hSession));
  99. /* -------------- Backscroll portion ------------- */
  100. if ((i = min(hhTerm->iBkLines, pstScrl->iBksScrlInc)) > 0)
  101. termGetBkLines(hhTerm, i, -i, BKPOS_ABSOLUTE);
  102. /* -------------- Terminal portion ------------- */
  103. if (pstScrl->iScrlInc != 0)
  104. {
  105. if (pstScrl->iScrlInc > 0)
  106. {
  107. i = max(0, pstScrl->yEnd - pstScrl->iScrlInc + 1);
  108. m = pstScrl->yEnd;
  109. }
  110. else
  111. {
  112. i = pstScrl->yBeg;
  113. m = min(iRows, pstScrl->yBeg - pstScrl->iScrlInc - 1);
  114. }
  115. k = ((i + hUpd->iTopline) % MAX_EMUROWS);
  116. for (; i <= m ; ++i)
  117. {
  118. // Server and Client have different size emulator images
  119. // for historical reasons. Server side has 2 extra characters
  120. // per row.
  121. pachTermTxt = hhTerm->fplpstrTxt[k];
  122. pachEmuTxt = pachTxt[k];
  123. pstTermAttr = hhTerm->fppstAttr[k];
  124. pstEmuAttr = pstAttr[k];
  125. // Update the terminal buffer now.
  126. for (j = 0 ; j < iCols ; ++j, ++pachTermTxt, ++pachEmuTxt)
  127. {
  128. // Televideo uses \xFF as a NULL character.
  129. if (*pachEmuTxt == ETEXT('\0') ||
  130. *pachEmuTxt == ETEXT('\xFF'))
  131. {
  132. *pachTermTxt = ETEXT(' ');
  133. }
  134. else
  135. {
  136. *pachTermTxt = *pachEmuTxt;
  137. }
  138. }
  139. MemCopy(pstTermAttr, pstEmuAttr, iCols * sizeof(STATTR));
  140. if (++k >= MAX_EMUROWS)
  141. k = 0;
  142. }
  143. }
  144. // Check for lines now.
  145. k = hUpd->iTopline;
  146. pabLines = pstScrl->auchLines + pstScrl->iFirstLine;
  147. for (j = 0 ; j < iRows ; ++j, ++pabLines)
  148. {
  149. if (*pabLines != 0)
  150. {
  151. pachEmuTxt = pachTxt[k];
  152. pachTermTxt = hhTerm->fplpstrTxt[k];
  153. pstEmuAttr = pstAttr[k];
  154. pstTermAttr = hhTerm->fppstAttr[k];
  155. // Update the terminal buffer now.
  156. for (i = 0 ; i < iCols ; ++i, ++pachTermTxt, ++pachEmuTxt)
  157. {
  158. // Televideo uses \xFF as a NULL character.
  159. if (*pachEmuTxt == ETEXT('\0') ||
  160. *pachEmuTxt == ETEXT('\xFF'))
  161. {
  162. *pachTermTxt = ETEXT(' ');
  163. }
  164. else
  165. {
  166. *pachTermTxt = *pachEmuTxt;
  167. }
  168. }
  169. MemCopy(pstTermAttr, pstEmuAttr, iCols * sizeof(STATTR));
  170. }
  171. if (++k >= MAX_EMUROWS)
  172. k = 0;
  173. }
  174. // Another ugly situation. Because we can mark stuff in the
  175. // backscroll buffer and still have updates coming in, we have
  176. // to bump the marking region by the scrollinc to keep everything
  177. // synchronized. Note, we don't need to check for Marking locks
  178. // because we could not have been here had any been in place.
  179. if (hhTerm->ptBeg.y < 0 || hhTerm->ptEnd.y < 0)
  180. {
  181. hhTerm->ptBeg.y -= pstScrl->iScrlInc;
  182. hhTerm->ptEnd.y -= pstScrl->iScrlInc;
  183. }
  184. // Update emulator's topline field now.
  185. hhTerm->iTopline = hUpd->iTopline;
  186. }
  187. // Save a copy of the update handle in term. This way we can
  188. // release our lock and paint without blocking the emulator.
  189. *(HHUPDATE)hhTerm->hUpdate = *hUpd;
  190. updateReset(hUpd);
  191. /* --- Important to remember to unlock emulator --- */
  192. emuUnlock(hEmu);
  193. /* --- Now let the terminal figure out how to paint itself. --- */
  194. if (fRedraw)
  195. termUpdate(hhTerm);
  196. return;
  197. }
  198. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  199. * FUNCTION:
  200. * termUpdate
  201. *
  202. * DESCRIPTION:
  203. * Invalidates the proper portions of the terminal buffers, updates
  204. * scrollbars, and generally takes care of the busy work of keeping
  205. * the terminal screen up to date.
  206. *
  207. * ARGUMENTS:
  208. * hwnd - terminal window handle
  209. *
  210. * RETURNS:
  211. * void
  212. *
  213. */
  214. static void termUpdate(const HHTERM hhTerm)
  215. {
  216. RECT rc;
  217. int i, j, l;
  218. BYTE *pauchLines;
  219. SCROLLINFO scrinf;
  220. const HHUPDATE hUpd = (HHUPDATE)hhTerm->hUpdate;
  221. GetClientRect(hhTerm->hwnd, &rc);
  222. // Adjust rectangle not to include indent/outdent areas. This
  223. // will be ignored if we are scrolling the whole terminal.
  224. rc.left += hhTerm->xIndent + (hhTerm->iHScrlPos ? 0 : hhTerm->xBezel);
  225. rc.right = min(((hhTerm->iCols * hhTerm->xChar) + hhTerm->xIndent + hhTerm->xBezel),
  226. rc.right);
  227. if (hUpd->bUpdateType == UPD_LINE)
  228. {
  229. if (hUpd->stLine.iLine != -1)
  230. {
  231. rc.top = (hUpd->stLine.iLine -
  232. hhTerm->iVScrlPos + 1) * hhTerm->yChar;
  233. rc.bottom = rc.top + hhTerm->yChar;
  234. rc.left = ((hUpd->stLine.xBeg -
  235. hhTerm->iHScrlPos) * hhTerm->xChar)
  236. + hhTerm->xIndent + hhTerm->xBezel;
  237. rc.right = ((hUpd->stLine.xEnd -
  238. hhTerm->iHScrlPos + 1) * hhTerm->xChar)
  239. + hhTerm->xIndent + hhTerm->xBezel;
  240. // Invalidate entire line when doing italics
  241. //
  242. if (hhTerm->fItalic)
  243. {
  244. rc.left = 0;
  245. rc.right = hhTerm->cx;
  246. }
  247. InvalidateRect(hhTerm->hwnd, &rc, FALSE);
  248. }
  249. }
  250. else if (hUpd->bUpdateType == UPD_SCROLL)
  251. {
  252. // Scroll range will change because new text is
  253. // scrolling into the backscroll region.
  254. i = hhTerm->iVScrlMin;
  255. j = hhTerm->iVScrlMax;
  256. if (i == j)
  257. hhTerm->fBump = FALSE;
  258. l = 0;
  259. // If bezel is drawn, make sure we have room
  260. //
  261. if (hhTerm->xBezel)
  262. {
  263. if ((hhTerm->cy % hhTerm->yChar) < (hhTerm->xBezel + 1))
  264. l = 1;
  265. }
  266. hhTerm->iVScrlMin = min(-hUpd->iLines,
  267. hhTerm->iRows - hhTerm->iTermHite + 1 + l);
  268. // This forces the terminal paint correctly if the minimum
  269. // number of lines changes such that the current vertical
  270. // scrolling position is no longer valid. mrw:6/19/95
  271. //
  272. if (hhTerm->iVScrlPos < hhTerm->iVScrlMin)
  273. hhTerm->iVScrlPos = hhTerm->iVScrlMin;
  274. if (i != hhTerm->iVScrlMin)
  275. {
  276. scrinf.cbSize= sizeof(scrinf);
  277. scrinf.fMask = SIF_DISABLENOSCROLL | SIF_RANGE | SIF_PAGE;
  278. scrinf.nMin = hhTerm->iVScrlMin;
  279. scrinf.nMax = hhTerm->iVScrlMax + hhTerm->iTermHite - 1;
  280. scrinf.nPage = (unsigned int)hhTerm->iTermHite;
  281. SetScrollInfo(hhTerm->hwnd, SB_VERT, &scrinf, TRUE);
  282. }
  283. // This is subtle but necessary. When the window is
  284. // large enough to show full terminal and backscroll
  285. // and the backscroll is empty, iVScrlPos is 0. The
  286. // moment the backscroll buffer becomes larger than
  287. // the backscroll area displayed, the iVScrlPos becomes
  288. // iVScrlMax in the case where text is coming in at the
  289. // bottom of the terminal screen. We could update the
  290. // scrollbar on every pass, but this causes an annoying
  291. // flicker in the scrollbar. This next piece of code
  292. // catches the transition from backscroll smaller than
  293. // displayed area to backscroll greater than displayed
  294. // area and updates the scrollbar position.
  295. // DbgOutStr("bump=%d, Min=%d, Max=%d\r\n",
  296. // hhTerm->fBump, hhTerm->iVScrlMin, hhTerm->iVScrlMax, 0, 0);
  297. if (!hhTerm->fBump && hhTerm->iVScrlMin != hhTerm->iVScrlMax)
  298. {
  299. // DbgOutStr("Pos = %d\r\n", hhTerm->iVScrlPos, 0, 0, 0, 0);
  300. scrinf.cbSize= sizeof(scrinf);
  301. scrinf.fMask = SIF_DISABLENOSCROLL | SIF_POS;
  302. scrinf.nPos = hhTerm->iVScrlPos;
  303. SetScrollInfo(hhTerm->hwnd, SB_VERT, &scrinf, TRUE);
  304. hhTerm->fBump = TRUE;
  305. }
  306. // Scroll specified area.
  307. rc.top = max(0, hUpd->stScrl.yBeg -
  308. hhTerm->iVScrlPos + 1) * hhTerm->yChar;
  309. rc.bottom = min(hhTerm->iTermHite,
  310. (hUpd->stScrl.yEnd -
  311. hhTerm->iVScrlPos + 2)) * hhTerm->yChar;
  312. // use iOffset to check for cursor erase operation.
  313. if (!hhTerm->fBackscrlLock)
  314. {
  315. HideCursors(hhTerm);
  316. ScrollWindow(hhTerm->hwnd, 0, -hhTerm->yChar *
  317. hUpd->stScrl.iScrlInc, (LPRECT)0, &rc);
  318. DbgOutStr("scroll %d", -hhTerm->yChar * hUpd->stScrl.iScrlInc,
  319. 0, 0, 0, 0);
  320. }
  321. // Examine the lines portion of update record.
  322. // Note, this is a negative area rectangle (ie. top is larger
  323. // than bottom).
  324. //
  325. rc.top = INT_MAX;
  326. rc.bottom = 0;
  327. pauchLines = hUpd->stScrl.auchLines +
  328. hUpd->stScrl.iFirstLine;
  329. for (j = 0 ; j < hhTerm->iRows ; ++j, ++pauchLines)
  330. {
  331. if (*pauchLines != (UCHAR)0)
  332. {
  333. //iPaintEnd = max(iPaintEnd, j+1);
  334. DbgOutStr("pauchLines->%d\r\n", j, 0, 0, 0, 0);
  335. // Map invalid line to terminal.
  336. l = (j - hhTerm->iVScrlPos + 1) * hhTerm->yChar;
  337. if (l >= 0)
  338. {
  339. rc.top = min(rc.top, l);
  340. rc.bottom = max(rc.bottom, l + hhTerm->yChar);
  341. }
  342. InvalidateRect(hhTerm->hwnd, &rc, FALSE);
  343. }
  344. }
  345. } /* else */
  346. // Update the host cursor position according to the update record.
  347. // mrw:6/19/95 - comparison was backwards.
  348. //
  349. if (hhTerm->ptHstCur.y != hUpd->iRow || hhTerm->ptHstCur.x != hUpd->iCol)
  350. {
  351. HideCursors(hhTerm);
  352. hhTerm->ptHstCur.y = hUpd->iRow;
  353. hhTerm->ptHstCur.x = hUpd->iCol;
  354. }
  355. // Important to paint now. If we wait, and the
  356. // backscroll region is also invalid, Windows will take
  357. // the union of these two rectangles and paint a much
  358. // larger region of the screen than is needed or wanted.
  359. // Note: UpdateWindow does nothing if the update region
  360. // in empty.
  361. UpdateWindow(hhTerm->hwnd);
  362. // Now take care of the backscroll buffer.
  363. i = hUpd->stScrl.iBksScrlInc;
  364. if (i && hUpd->bUpdateType == UPD_SCROLL)
  365. {
  366. rc.top = 0;
  367. rc.bottom = min(hhTerm->iTermHite, -hhTerm->iVScrlPos) * hhTerm->yChar;
  368. if (rc.bottom > rc.top && !hhTerm->fBackscrlLock)
  369. {
  370. HideCursors(hhTerm);
  371. ScrollWindow(hhTerm->hwnd, 0, -hhTerm->yChar * i, (LPRECT)0, &rc);
  372. UpdateWindow(hhTerm->hwnd);
  373. }
  374. else if (hhTerm->fBackscrlLock)
  375. {
  376. hhTerm->iVScrlPos -= i;
  377. scrinf.cbSize= sizeof(scrinf);
  378. scrinf.fMask = SIF_DISABLENOSCROLL | SIF_POS;
  379. scrinf.nPos = hhTerm->iVScrlPos;
  380. SetScrollInfo(hhTerm->hwnd, SB_VERT, &scrinf, TRUE);
  381. }
  382. }
  383. // Important to do this again before we turn the host cursor
  384. // back on.
  385. // Note: UpdateWindow does nothing if the update region
  386. // is empty.
  387. UpdateWindow(hhTerm->hwnd);
  388. ShowCursors(hhTerm);
  389. return;
  390. }
  391. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  392. * FUNCTION:
  393. * termGetBkLines
  394. *
  395. * DESCRIPTION:
  396. * This function is uglier than ulgy. This function updates the local
  397. * backscroll buffer after it has been filled by backscrlCFillLocalBk().
  398. * This function only graps the actual number of lines it needs to update
  399. * the local backscroll page. The reason it is complex is because the
  400. * server also stores it's backscroll buffer in pages. If this routine
  401. * requires data from more than one page, it must repeatedly ask the
  402. * server until the request is satisfied. Some assumptions are made
  403. * here (and in backscrlCFillLocalBk()). First and foremost, requests
  404. * are never made beyond the backscroll region. The caller's of these
  405. * routines does this right now. Second, if x number of lines are asked
  406. * for, this routine will continue to try until it meets the request.
  407. * Again, the callers are smart enough not to exceed the backscroll ranges.
  408. *
  409. * ARGUMENTS:
  410. * HHTERM hhTerm -- internal terminal handle
  411. * int iScrlInc -- the # of lines and the direction scrolled
  412. * int yBeg -- depends on sType
  413. * int iType -- if BKPOS_THUMBPOS, yBeg is the thumb pos.
  414. * if BKPOS_ABSOLUTE, yBeg is absolute pos.
  415. *
  416. * RETURNS:
  417. * nothing
  418. *
  419. */
  420. void termGetBkLines(const HHTERM hhTerm, const int iScrlInc, int yBeg, int sType)
  421. {
  422. int i, j, k, l;
  423. int iWant, iGot;
  424. int iOffset;
  425. ECHAR *pachTxt, // terminal buffer
  426. *pachBkTxt; // engine buffer
  427. const HBACKSCRL hBackscrl = sessQueryBackscrlHdl(hhTerm->hSession);
  428. if (abs(iScrlInc) > hhTerm->iPhysicalBkRows)
  429. {
  430. termFillBk(hhTerm, yBeg);
  431. return;
  432. }
  433. // Get needed backscroll text from server
  434. if (iScrlInc < 0)
  435. {
  436. assert(sType != BKPOS_ABSOLUTE);
  437. i = iScrlInc;
  438. // l is a wrap counter and is calculated for speed.
  439. //
  440. l = hhTerm->iNextBkLn = (hhTerm->iNextBkLn +
  441. hhTerm->iPhysicalBkRows + iScrlInc) % hhTerm->iPhysicalBkRows;
  442. }
  443. else
  444. {
  445. if (sType == BKPOS_THUMBPOS)
  446. {
  447. yBeg += hhTerm->iTermHite - iScrlInc;
  448. assert(yBeg < 0);
  449. }
  450. i = 0;
  451. }
  452. // Since backscroll memory is pages we have to make multiple requests.
  453. //
  454. for (iWant=abs(iScrlInc), iGot=0 ; iWant > 0 ; iWant-=iGot, yBeg+=iGot)
  455. {
  456. if (backscrlGetBkLines(hBackscrl, yBeg, iWant, &iGot, &pachBkTxt,
  457. &iOffset) == FALSE)
  458. {
  459. return;
  460. }
  461. pachBkTxt += iOffset;
  462. // Apply text to backscroll buffer
  463. if (iScrlInc < 0)
  464. {
  465. for (k=0 ; (i < 0) && (k < iGot) ; ++i, ++k)
  466. {
  467. pachTxt = hhTerm->fplpstrBkTxt[l];
  468. for (j = 0 ; j < MAX_EMUCOLS && *pachBkTxt != ETEXT('\n') ; ++j)
  469. {
  470. assert(*pachBkTxt);
  471. *pachTxt++ = *pachBkTxt++;
  472. }
  473. for ( ; j < MAX_EMUCOLS ; ++j)
  474. *pachTxt++ = ' ';
  475. pachBkTxt += 1; // Blow past newline marker...
  476. if (++l >= hhTerm->iPhysicalBkRows)
  477. l = 0;
  478. }
  479. }
  480. else
  481. {
  482. for (k=0 ; (i < iScrlInc) && (k < iGot) ; ++i, ++k)
  483. {
  484. pachTxt = hhTerm->fplpstrBkTxt[hhTerm->iNextBkLn];
  485. for (j = 0 ; j < MAX_EMUCOLS && *pachBkTxt != ETEXT('\n') ; ++j)
  486. {
  487. assert(*pachBkTxt != ETEXT('\0'));
  488. *pachTxt++ = *pachBkTxt++;
  489. }
  490. for ( ; j < MAX_EMUCOLS ; ++j)
  491. *pachTxt++ = ETEXT(' ');
  492. if (++hhTerm->iNextBkLn >= hhTerm->iPhysicalBkRows)
  493. hhTerm->iNextBkLn = 0;
  494. pachBkTxt += 1; // Blow past newline marker...
  495. }
  496. }
  497. }
  498. return;
  499. }
  500. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  501. * FUNCTION:
  502. * termFillBk
  503. *
  504. * DESCRIPTION:
  505. * This routine fills an entire local (refering a view) backscroll buffer.
  506. * It is called only three times. Whenever the transistion is made from
  507. * active backscrolling to static backscrolling. When the Scroll
  508. * increment during a static backscroll operation is greater than the size
  509. * of the view (and therefore the number of lines in the backscroll buffer
  510. * as denoted by hhTerm->iPhysicalBkRows). And when the terminal window
  511. * is resized.
  512. *
  513. * ARGUMENTS:
  514. * HHTERM hhTerm -- internal terminal handle
  515. * int iTermHite -- # of rows that will fit on current terminal
  516. * int iBkPos -- where to start in backscroll
  517. *
  518. * RETURNS:
  519. * void
  520. *
  521. */
  522. void termFillBk(const HHTERM hhTerm, const int iBkPos)
  523. {
  524. int i, j;
  525. int iWant,
  526. iGot,
  527. yBeg;
  528. int iOffset;
  529. ECHAR **fplpstrBkTxt,
  530. *pachTxt, // terminal buffer
  531. *pachBkTxt; //
  532. const HBACKSCRL hBackscrl = sessQueryBackscrlHdl(hhTerm->hSession);
  533. if (hhTerm->iTermHite > hhTerm->iMaxPhysicalBkRows)
  534. {
  535. if (termReallocBkBuf(hhTerm, hhTerm->iTermHite) != 0)
  536. {
  537. assert(FALSE);
  538. return;
  539. }
  540. }
  541. /* --- Empty the rest of terminal's backscroll buffer --- */
  542. for (i = 0 ; i < hhTerm->iPhysicalBkRows ; ++i)
  543. ECHAR_Fill(hhTerm->fplpstrBkTxt[i], EMU_BLANK_CHAR, MAX_EMUCOLS);
  544. /* --- Grab whatever we can from the engine's backscroll buffer --- */
  545. hhTerm->iPhysicalBkRows = hhTerm->iTermHite;
  546. hhTerm->iNextBkLn = 0;
  547. // mrw: 2/29/96 - moved the check for an empty buffer to past where
  548. // the iPhyscialRows gets set.
  549. //
  550. if (hhTerm->iBkLines == 0)
  551. return;
  552. //*yBeg = iBkPos;
  553. yBeg = max(-hhTerm->iBkLines, iBkPos);
  554. iWant = min(hhTerm->iTermHite, abs(yBeg));
  555. fplpstrBkTxt = hhTerm->fplpstrBkTxt + (hhTerm->iTermHite - iWant);
  556. for (iGot=0 ; iWant > 0 ; iWant-=iGot, yBeg+=iGot)
  557. {
  558. if (backscrlGetBkLines(hBackscrl, yBeg, iWant, &iGot, &pachBkTxt,
  559. &iOffset) == FALSE)
  560. {
  561. return;
  562. }
  563. pachBkTxt += iOffset;
  564. for (i = 0 ; i < iGot ; ++i, ++fplpstrBkTxt)
  565. {
  566. pachTxt = *fplpstrBkTxt;
  567. for (j = 0 ; j < MAX_EMUCOLS && *pachBkTxt != ETEXT('\n') ; ++j)
  568. {
  569. assert(*pachBkTxt);
  570. *pachTxt++ = *pachBkTxt++;
  571. }
  572. for ( ; j < MAX_EMUCOLS ; ++j)
  573. *pachTxt++ = ETEXT(' ');
  574. pachBkTxt += 1;
  575. }
  576. }
  577. return;
  578. }
  579. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  580. * FUNCTION:
  581. * termReallocBkBuf
  582. *
  583. * DESCRIPTION:
  584. * This happens when the user changes to a smaller font which allows more
  585. * rows on the screen.
  586. *
  587. * ARGUMENTS:
  588. * hhTerm - private terminal handle
  589. * iLines - number of lines to realloc
  590. *
  591. * RETURNS:
  592. * 0=OK, 1=error
  593. *
  594. */
  595. static int termReallocBkBuf(const HHTERM hhTerm, const int iLines)
  596. {
  597. int i;
  598. ECHAR** pTempfplpstrBkTxt = NULL;
  599. if (iLines < hhTerm->iMaxPhysicalBkRows)
  600. {
  601. return 0;
  602. }
  603. pTempfplpstrBkTxt =
  604. (ECHAR**)realloc(hhTerm->fplpstrBkTxt,
  605. (unsigned int)iLines * sizeof(ECHAR *));
  606. if (pTempfplpstrBkTxt == NULL)
  607. {
  608. return 1;
  609. }
  610. else
  611. {
  612. hhTerm->fplpstrBkTxt = pTempfplpstrBkTxt;
  613. }
  614. for (i = hhTerm->iMaxPhysicalBkRows ; i < iLines ; ++i)
  615. {
  616. if ((hhTerm->fplpstrBkTxt[i] = malloc(MAX_EMUCOLS * sizeof(ECHAR)))
  617. == 0)
  618. {
  619. assert(FALSE);
  620. return 1;
  621. }
  622. ECHAR_Fill(hhTerm->fplpstrBkTxt[i], EMU_BLANK_CHAR, MAX_EMUCOLS);
  623. }
  624. hhTerm->iMaxPhysicalBkRows = iLines;
  625. return 0;
  626. }