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.

679 lines
15 KiB

  1. /* File: D:\WACKER\tdll\backscrl.c (Created: 10-Dec-1993)
  2. *
  3. * Copyright 1994 by Hilgraeve Inc. -- Monroe, MI
  4. * All rights reserved
  5. *
  6. * $Revision: 9 $
  7. * $Date: 8/27/01 9:00a $
  8. */
  9. #include <windows.h>
  10. #pragma hdrstop
  11. #include <stdlib.h>
  12. #include <limits.h>
  13. #include "stdtyp.h"
  14. #include "tdll.h"
  15. #include "mc.h"
  16. #include "assert.h"
  17. #include "session.h"
  18. #include "session.hh"
  19. #include <emu\emu.h>
  20. #include <emu\emu.hh>
  21. #include "update.h"
  22. #include "backscrl.h"
  23. #include "backscrl.hh"
  24. #include "sess_ids.h"
  25. #include "htchar.h"
  26. #include "term.h"
  27. #include "sf.h"
  28. #include <term\res.h>
  29. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  30. * FUNCTION:
  31. * backscrlCreate
  32. *
  33. * DESCRIPTION:
  34. * Creates a server (now wudge) backsroll handle include the backscroll
  35. * region itself.
  36. *
  37. * ARGUMENTS:
  38. * Size of the backscoll region in bytes.
  39. *
  40. * RETURNS:
  41. * Handle to a backscroll structure on success, else (HBACKSCRL)0.
  42. *
  43. */
  44. HBACKSCRL backscrlCreate(const HSESSION hSession, const int iBytes)
  45. {
  46. int i;
  47. HHBACKSCRL hBk;
  48. assert(hSession);
  49. hBk = (HHBACKSCRL)malloc(sizeof(struct stBackscrl));
  50. if (hBk == 0)
  51. {
  52. assert(FALSE);
  53. return 0;
  54. }
  55. memset(hBk, 0, sizeof(struct stBackscrl));
  56. hBk->hSession = hSession;
  57. hBk->iPages = (iBytes / BACKSCRL_PAGESIZE) + 1;
  58. if (hBk->iPages > BACKSCRL_MAXPAGES)
  59. {
  60. assert(FALSE);
  61. free(hBk);
  62. hBk = NULL;
  63. return 0;
  64. }
  65. hBk->hBkPages = (HBKPAGE *)malloc((size_t)hBk->iPages * sizeof(HBKPAGE));
  66. if (hBk->hBkPages == 0)
  67. {
  68. assert(FALSE);
  69. free(hBk);
  70. hBk = NULL;
  71. return (HBACKSCRL)0;
  72. }
  73. for (i = 0 ; i < hBk->iPages ; ++i)
  74. {
  75. hBk->hBkPages[i] = (HBKPAGE)malloc(sizeof(struct stBackscrlPage));
  76. if (hBk->hBkPages[i] == (HBKPAGE)0)
  77. {
  78. assert(FALSE);
  79. goto ERROROUT;
  80. }
  81. hBk->hBkPages[i]->pachPage =
  82. (ECHAR *)malloc(BACKSCRL_PAGESIZE * sizeof(ECHAR));
  83. if (hBk->hBkPages[i]->pachPage == 0)
  84. {
  85. assert(FALSE);
  86. goto ERROROUT;
  87. }
  88. ECHAR_Fill(hBk->hBkPages[i]->pachPage, EMU_BLANK_CHAR, BACKSCRL_PAGESIZE);
  89. hBk->hBkPages[i]->iLines = 0;
  90. }
  91. hBk->iCurrPage = 0;
  92. hBk->iOffset = 0;
  93. hBk->iLines = 0;
  94. // Set this to some default...
  95. //
  96. hBk->iUserLines = hBk->iUserLinesSave = BKSCRL_USERLINES_DEFAULT_MAX;
  97. hBk->hBkPages[hBk->iCurrPage]->iLines = 0;
  98. return (HBACKSCRL)hBk;
  99. // Fanstastic error recovery.
  100. ERROROUT:
  101. while (--i > 0)
  102. {
  103. free(hBk->hBkPages[i]->pachPage);
  104. hBk->hBkPages[i]->pachPage = NULL;
  105. free(hBk->hBkPages[i]);
  106. hBk->hBkPages[i] = NULL;
  107. }
  108. free(hBk->hBkPages);
  109. hBk->hBkPages = NULL;
  110. free(hBk);
  111. hBk = NULL;
  112. return (HBACKSCRL)0; // caller does error message
  113. }
  114. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  115. * FUNCTION:
  116. * backscrlDestroy
  117. *
  118. * DESCRIPTION:
  119. * Routine to free memory associated with the given backscoll handle.
  120. *
  121. * ARGUMENTS:
  122. * HBACKSCRL hBackscrl - handle to free.
  123. *
  124. * RETURNS:
  125. * nothing.
  126. *
  127. */
  128. VOID backscrlDestroy(const HBACKSCRL hBackscrl)
  129. {
  130. int i;
  131. const HHBACKSCRL hBk = (HHBACKSCRL)hBackscrl;
  132. if (hBk == 0)
  133. {
  134. assert(0);
  135. return;
  136. }
  137. if (hBk->hBkPages)
  138. {
  139. for (i = 0 ; i < hBk->iPages ; ++i)
  140. {
  141. if (hBk->hBkPages[i]->pachPage)
  142. {
  143. free(hBk->hBkPages[i]->pachPage);
  144. hBk->hBkPages[i]->pachPage = NULL;
  145. }
  146. free(hBk->hBkPages[i]);
  147. hBk->hBkPages[i] = NULL;
  148. }
  149. free(hBk->hBkPages);
  150. hBk->hBkPages = NULL;
  151. }
  152. free(hBk);
  153. return;
  154. }
  155. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  156. * FUNCTION:
  157. * backscrlAdd
  158. *
  159. * DESCRIPTION:
  160. * Adds a new line to the backscoll handle. The affect is to scroll the
  161. * preceding lines up by one and to add the given string to the bottom
  162. * of the backscroll region.
  163. *
  164. * ARGUMENTS:
  165. * HBACKSCRL hBackscrl - as usual
  166. * LPTSTR pachBuf - string to add
  167. * int usLen - length of the string.
  168. *
  169. * RETURNS:
  170. * TRUE always.
  171. *
  172. */
  173. BOOL backscrlAdd(const HBACKSCRL hBackscrl,
  174. const ECHAR *pachBuf,
  175. const int iLen
  176. )
  177. {
  178. register int i;
  179. ECHAR *pachBackscrl;
  180. const HHBACKSCRL hBk = (HHBACKSCRL)hBackscrl;
  181. if (hBk == 0)
  182. {
  183. assert(0);
  184. return FALSE;
  185. }
  186. if (hBk->iUserLines == 0)
  187. return TRUE;
  188. // The following test has been removed because the emualtors no
  189. // longer use a '\0' to delimit the end of a line. 5/16/94 --jcm
  190. // Never let '\0's into the backscroll buffer! Avoid this like the
  191. // plague since they display as wierd characters depending on the
  192. // font selected on the CLIENT side. The wierd part is you can't
  193. // always depend on the emulators putting a '\0' in the the buffer
  194. // so we need to check for trailing space as well.
  195. for (i = 0 ; i < iLen ; ++i)
  196. {
  197. if (pachBuf[i] == (ECHAR)0)
  198. break;
  199. }
  200. // remove trailing whitespace.
  201. while (i)
  202. {
  203. if (pachBuf[i - 1] != ETEXT(' '))
  204. break;
  205. i -= 1;
  206. }
  207. DbgOutStr("%d-", i, 0, 0, 0, 0);
  208. // check to see if there is room on the current page.
  209. if (hBk->iOffset >= BACKSCRL_PAGESIZE ||
  210. ((int)BACKSCRL_PAGESIZE - hBk->iOffset) <= i)
  211. {
  212. // pad rest of page with blanks so we know that this part of
  213. // the buffer is empty.
  214. if ((pachBackscrl = hBk->hBkPages[hBk->iCurrPage]->pachPage) == 0)
  215. {
  216. assert(0);
  217. return FALSE;
  218. }
  219. ECHAR_Fill(pachBackscrl+hBk->iOffset, EMU_BLANK_CHAR,
  220. (size_t)(BACKSCRL_PAGESIZE - hBk->iOffset));
  221. hBk->iCurrPage += 1;
  222. if (hBk->iCurrPage >= hBk->iPages)
  223. hBk->iCurrPage = 0;
  224. hBk->iOffset = 0;
  225. // If we have wrapped, subtract the number of lines previously in
  226. // this page from the total line count. Since the line count is
  227. // intialized to 0 (see backscrlCreate()) I can always subract this
  228. // amount without checking for wrapping since it will only be
  229. // non-zero if we have wrapped.
  230. hBk->iLines -= hBk->hBkPages[hBk->iCurrPage]->iLines;
  231. hBk->hBkPages[hBk->iCurrPage]->iLines = 0;
  232. }
  233. // Assign a pointer for speed and clarity
  234. if ((pachBackscrl = hBk->hBkPages[hBk->iCurrPage]->pachPage) == 0)
  235. {
  236. assert(0);
  237. return FALSE;
  238. }
  239. // JYF 26-Mar-1999 limit the size so we don't overrun
  240. // the buffer.
  241. if (i)
  242. {
  243. MemCopy (pachBackscrl + hBk->iOffset,
  244. pachBuf,
  245. (size_t)min(BACKSCRL_PAGESIZE - hBk->iOffset, i) * sizeof(ECHAR));
  246. }
  247. hBk->iOffset += min(BACKSCRL_PAGESIZE - hBk->iOffset - 1, i);
  248. pachBackscrl[hBk->iOffset++] = ETEXT('\n');
  249. // Here's an interesting problem. We really can't reference more than
  250. // a signed-integer's worth of lines, but we may have megabytes of
  251. // backscroll memory. The answer is simple in this case. Never allow
  252. // the line count to exceed the signed int max. This has the affect
  253. // of spilling off the top lines in the buffer. - mrw
  254. hBk->iLines = min(hBk->iLines+1, INT_MAX);
  255. hBk->hBkPages[hBk->iCurrPage]->iLines += 1;
  256. hBk->iChanged = TRUE;
  257. updateBackscroll(sessQueryUpdateHdl(hBk->hSession), 1);
  258. return TRUE;
  259. }
  260. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  261. * FUNCTION:
  262. * backscrlGetBkLines
  263. *
  264. * DESCRIPTION:
  265. * Retrieves specifed lines from the backscoll. This function is
  266. * complicated by the fact the backscoll memory is paged. A request
  267. * might cross one or more page boundaries. Thus only a portion of
  268. * the request may be satisfied. The client knows this and makes new
  269. * requests based on what it got from the server.
  270. *
  271. * ARGUMENTS:
  272. * hBackscrl - the usual
  273. * yBeg - begining line in backscroll to get.
  274. * sWant - number of lines requested.
  275. * psGot - number of lines retrived.
  276. * lpststrTxt - handle to backscrl memory page retrived.
  277. * pwOffset - offset into retrieved page (in TCHAR units).
  278. *
  279. * RETURNS:
  280. * BOOL
  281. *
  282. */
  283. BOOL backscrlGetBkLines(const HBACKSCRL hBackscrl,
  284. const int yBeg,
  285. const int sWant,
  286. int *psGot,
  287. ECHAR **lptstrTxt,
  288. int *pwOffset
  289. )
  290. {
  291. register int i, j, k;
  292. ECHAR *pachText;
  293. const HHBACKSCRL hBk = (HHBACKSCRL)hBackscrl;
  294. assert(sWant > 0);
  295. // Check to see if we are requesting beyond the end of the
  296. // backscroll buffer.
  297. if (abs(yBeg) > hBk->iLines)
  298. return FALSE;
  299. k = hBk->iCurrPage;
  300. j = 0;
  301. i = 0;
  302. // Find the backscoll page that has the requested text
  303. //
  304. for (;;)
  305. {
  306. if ((j -= hBk->hBkPages[k]->iLines) <= yBeg)
  307. break;
  308. k = (hBk->iPages + k - 1) % hBk->iPages;
  309. if (++i >= hBk->iPages)
  310. return FALSE;
  311. }
  312. // Found the page.
  313. //
  314. *lptstrTxt = hBk->hBkPages[k]->pachPage;
  315. // Now find offset into page where first line of requested text begins
  316. //
  317. for (pachText = hBk->hBkPages[k]->pachPage ; j < yBeg ; ++j)
  318. {
  319. while (*pachText != ETEXT('\n'))
  320. {
  321. pachText += 1;
  322. }
  323. pachText += 1;
  324. }
  325. *pwOffset = (DWORD)(pachText - hBk->hBkPages[k]->pachPage);
  326. // Found offset. Now grab what we can and return it.
  327. //
  328. for (i = 1 ; i <= sWant ; ++i)
  329. {
  330. while ((pachText - hBk->hBkPages[k]->pachPage) < BACKSCRL_PAGESIZE
  331. && *pachText != ETEXT('\n'))
  332. {
  333. pachText += 1;
  334. }
  335. if ((pachText - hBk->hBkPages[k]->pachPage) >= BACKSCRL_PAGESIZE)
  336. break;
  337. *psGot = i;
  338. pachText += 1; // blow past newline
  339. }
  340. return TRUE;
  341. }
  342. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  343. * FUNCTION:
  344. * backscrlGetNumLines
  345. *
  346. * DESCRIPTION:
  347. * Returns the number of lines in the backscrl which is zero if the
  348. * backscroll is off, and the maximum is always the user set value.
  349. *
  350. * ARGUMENTS:
  351. * HBACKSCRL hBackscrl - external backscrl handle
  352. *
  353. * RETURNS:
  354. * Returns the uLines member.
  355. */
  356. int backscrlGetNumLines(const HBACKSCRL hBackscrl)
  357. {
  358. const HHBACKSCRL hBk = (HHBACKSCRL)hBackscrl;
  359. assert(hBk);
  360. return (hBk->fShowBackscrl) ? min(hBk->iUserLines, hBk->iLines) : 0;
  361. }
  362. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  363. * FUNCTION:
  364. * backscrlUSetNumLines
  365. *
  366. * DESCRIPTION:
  367. * Returns the iUserLines member.
  368. *
  369. * ARGUMENTS:
  370. * HBACKSCRL hBackscrl - external backscrl handle
  371. *
  372. * RETURNS:
  373. * void
  374. */
  375. int backscrlSetUNumLines(const HBACKSCRL hBackscrl, const int iUserLines)
  376. {
  377. const HHBACKSCRL hBk = (HHBACKSCRL)hBackscrl;
  378. if (hBk == 0)
  379. {
  380. assert(0);
  381. return -1;
  382. }
  383. if (iUserLines != hBk->iUserLines)
  384. {
  385. backscrlChanged(hBackscrl);
  386. hBk->iUserLines = iUserLines;
  387. // If we're setting the number of lines to zero, we're essentially
  388. // disabling the backscroll. Flushing clears the screen as well.
  389. //
  390. if (iUserLines == 0)
  391. {
  392. HHSESSION hhSession = (HHSESSION)hBk->hSession;
  393. // REV: 07/26/2001 posted message to clear the backscroll
  394. // otherwise a deadlock could occur as we may not be thread 0.
  395. // backscrlFlush(hBackscrl);
  396. PostMessage(hhSession->hwndSess, WM_COMMAND, IDM_CLEAR_BACKSCROLL, (LPARAM)0);
  397. }
  398. }
  399. return 0;
  400. }
  401. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  402. * FUNCTION:
  403. * backscrlGetUNumLines
  404. *
  405. * DESCRIPTION:
  406. * Returns the iUserLines member.
  407. *
  408. * ARGUMENTS:
  409. * HBACKSCRL hBackscrl - external backscrl handle
  410. *
  411. * RETURNS:
  412. * Returns the iUserLines member.
  413. */
  414. int backscrlGetUNumLines(const HBACKSCRL hBackscrl)
  415. {
  416. const HHBACKSCRL hBk = (HHBACKSCRL)hBackscrl;
  417. return hBk->iUserLines;
  418. }
  419. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  420. * FUNCTION:
  421. * backscrlRead
  422. *
  423. * DESCRIPTION:
  424. * Read the number of backscrol lines to keep as entered by the user.
  425. * NOTE: This should be put in the backscrlInitializeHdl() when this function
  426. * gets written.
  427. *
  428. * ARGUMENTS:
  429. * HBACKSCRL hBackscrl - external backscrl handle
  430. *
  431. * RETURNS:
  432. */
  433. void backscrlRead(const HBACKSCRL hBackscrl)
  434. {
  435. const HHBACKSCRL hBk = (HHBACKSCRL)hBackscrl;
  436. unsigned long ulSize;
  437. ulSize = sizeof(hBk->iUserLines);
  438. hBk->iUserLines = BKSCRL_USERLINES_DEFAULT_MAX;
  439. sfGetSessionItem(sessQuerySysFileHdl(hBk->hSession),
  440. SFID_BKSC_ULINES,
  441. &ulSize,
  442. &hBk->iUserLines);
  443. hBk->iUserLinesSave = hBk->iUserLines;
  444. }
  445. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  446. * FUNCTION:
  447. * backscrlSave
  448. *
  449. * DESCRIPTION:
  450. *
  451. * ARGUMENTS:
  452. * HBACKSCRL hBackscrl - external backscrl handle
  453. *
  454. * RETURNS:
  455. */
  456. void backscrlSave(const HBACKSCRL hBackscrl)
  457. {
  458. const HHBACKSCRL hBk = (HHBACKSCRL)hBackscrl;
  459. unsigned long ulSize;
  460. if (hBk->iUserLines != hBk->iUserLinesSave)
  461. {
  462. ulSize = sizeof(int);
  463. sfPutSessionItem(sessQuerySysFileHdl(hBk->hSession),
  464. SFID_BKSC_ULINES,
  465. ulSize,
  466. &(hBk->iUserLines));
  467. }
  468. }
  469. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  470. * FUNCTION:
  471. * backscrlFlush
  472. *
  473. * DESCRIPTION:
  474. * Empties the backscroll buffer and notifies the terminal so it can
  475. * update it's display.
  476. *
  477. * Note: Because this function calls RefreshTermWindow() it should only
  478. * be called from the main thread. - mrw
  479. *
  480. * ARGUMENTS:
  481. * hBackscrl - public backscroll handle
  482. *
  483. * RETURNS:
  484. * void
  485. *
  486. */
  487. void backscrlFlush(const HBACKSCRL hBackscrl)
  488. {
  489. int i;
  490. const HHBACKSCRL hBk = (HHBACKSCRL)hBackscrl;
  491. ECHAR aechBuf[10];
  492. assert(hBk);
  493. /* --- Shouldn't need this unless this is called while on line --- */
  494. emuLock(sessQueryEmuHdl(hBk->hSession));
  495. /* --- Force the update records to have something in them --- */
  496. CnvrtMBCStoECHAR(aechBuf, sizeof(aechBuf), TEXT(" "),
  497. StrCharGetByteCount(TEXT(" ")));
  498. backscrlAdd(hBackscrl, aechBuf, 1);
  499. /* --- Empty all pages --- */
  500. for (i = 0 ; i < hBk->iPages ; ++i)
  501. hBk->hBkPages[i]->iLines = 0;
  502. hBk->iLines = 0;
  503. hBk->iOffset = 0; //mrw:6/19/95
  504. emuUnlock(sessQueryEmuHdl(hBk->hSession));
  505. /* --- Let the terminal update now --- */
  506. NotifyClient(hBk->hSession, EVENT_TERM_UPDATE, 0);
  507. RefreshTermWindow(sessQueryHwndTerminal(hBk->hSession));
  508. return;
  509. }
  510. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  511. * FUNCTION:
  512. * backscrlChanged
  513. *
  514. * DESCRIPTION:
  515. * Returns iChanged member which is set whenever anything is added
  516. * to the backscroll buffer. It can be cleared by calling
  517. * backscrlResetChangedFlag().
  518. *
  519. * ARGUMENTS:
  520. * hBackscrl - public backscroll handle
  521. *
  522. * RETURNS:
  523. * BOOL
  524. *
  525. */
  526. BOOL backscrlChanged(const HBACKSCRL hBackscrl)
  527. {
  528. const HHBACKSCRL hBk = (HHBACKSCRL)hBackscrl;
  529. assert(hBk);
  530. return hBk->iChanged;
  531. }
  532. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  533. * FUNCTION:
  534. * backscrlResetChangedFlag
  535. *
  536. * DESCRIPTION:
  537. * Resets the iChanged member to 0. Subsequent calls to backscrlAdd()
  538. * will set the flag to 1.
  539. *
  540. * ARGUMENTS:
  541. * hBackscrl - public backscrl handle
  542. *
  543. * RETURNS:
  544. * void
  545. *
  546. */
  547. void backscrlResetChangedFlag(const HBACKSCRL hBackscrl)
  548. {
  549. const HHBACKSCRL hBk = (HHBACKSCRL)hBackscrl;
  550. assert(hBk);
  551. hBk->iChanged = 0;
  552. return;
  553. }
  554. /*=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
  555. * FUNCTION:
  556. * backscrlSetShowFlag
  557. *
  558. * DESCRIPTION:
  559. * The show flag controls whether or not the session will show/display
  560. * an antive backscrl.
  561. *
  562. * ARGUMENTS:
  563. * hBackscrl - public backscrl handle.
  564. * fFlag - TRUE=show, FALSE=hide
  565. *
  566. * RETURNS:
  567. * void
  568. *
  569. */
  570. void backscrlSetShowFlag(const HBACKSCRL hBackscrl, const int fFlag)
  571. {
  572. const HHBACKSCRL hBk = (HHBACKSCRL)hBackscrl;
  573. assert(hBk);
  574. hBk->fShowBackscrl = fFlag;
  575. return;
  576. }