Source code of Windows XP (NT5)
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.

344 lines
8.6 KiB

  1. /*
  2. * TESTSUBS.C
  3. *
  4. * String formatting class, window procedure and helper functions
  5. */
  6. #define UNICODE
  7. #include <windows.h>
  8. #include <windowsx.h>
  9. #include <stdio.h>
  10. #include <string.h>
  11. #include "ddespy.h"
  12. #include "globals.h"
  13. #define OFF2P(psw, off) ((TCHAR *)psw + off)
  14. #define BOUND(n, min, max) ((n) < (min) ? (min) : ((n) > (max) ? (max) : n))
  15. INT cyChar; /* Height of a line */
  16. INT cxChar;
  17. INT cyDescent;
  18. /***************************** Public Function ****************************\
  19. * BOOL InitTestSubs( )
  20. *
  21. * This routine MUST be called before using anything in this file. Registers
  22. * window classes, loads brushes, etc. Returns TRUE if successful, FALSE
  23. * otherwise.
  24. *
  25. \***************************************************************************/
  26. BOOL InitTestSubs()
  27. {
  28. WNDCLASS cls;
  29. cls.style = 0;
  30. cls.lpfnWndProc = (WNDPROC)StrWndProc;
  31. cls.cbClsExtra = 0;
  32. cls.cbWndExtra = sizeof(HANDLE);
  33. cls.hInstance = hInst;
  34. cls.hIcon = NULL;
  35. cls.hCursor = LoadCursor(NULL, IDC_ARROW);
  36. cls.hbrBackground = (HBRUSH)COLOR_WINDOW;
  37. cls.lpszMenuName = NULL;
  38. cls.lpszClassName = (LPCTSTR) RefString(IDS_STRINGCLASS);
  39. if (!RegisterClass((WNDCLASS FAR * ) & cls))
  40. return(FALSE);
  41. return(TRUE);
  42. }
  43. VOID CloseTestSubs(
  44. HANDLE hInst)
  45. {
  46. UnregisterClass((LPCTSTR) RefString(IDS_STRINGCLASS), hInst);
  47. }
  48. VOID NextLine( STRWND *psw)
  49. {
  50. psw->offBottomLine += psw->cchLine;
  51. if (psw->offBottomLine == psw->offBufferMax)
  52. psw->offBottomLine = psw->offBuffer;
  53. psw->offOutput = psw->offBottomLine;
  54. *OFF2P(psw, psw->offOutput) = TEXT('\0');
  55. }
  56. /***************************** Public Function ****************************\
  57. * VOID DrawString(hwnd, sz)
  58. *
  59. * This routine prints a string in the specified StringWindow class window.
  60. * sz is a NEAR pointer to a zero-terminated string, which can be produced
  61. * with wsprintf().
  62. \***************************************************************************/
  63. VOID DrawString( HWND hwnd, TCHAR *sz)
  64. {
  65. register STRWND *psw;
  66. INT cLines = 1;
  67. HANDLE hpsw;
  68. hpsw = (HANDLE)GetWindowLongPtr(hwnd, 0);
  69. psw = (STRWND *)LocalLock(hpsw);
  70. NextLine(psw);
  71. while (*sz) {
  72. switch (*sz) {
  73. case TEXT('\r'):
  74. break;
  75. case TEXT('\n'):
  76. *OFF2P(psw, psw->offOutput++) = TEXT('\0');
  77. NextLine(psw);
  78. cLines++;
  79. break;
  80. default:
  81. *OFF2P(psw, psw->offOutput++) = *sz;
  82. }
  83. sz++;
  84. }
  85. *OFF2P(psw, psw->offOutput++) = TEXT('\0');
  86. LocalUnlock(hpsw);
  87. ScrollWindow(hwnd, 0, -((cyChar + cyDescent) * cLines), (LPRECT)NULL,
  88. (LPRECT)NULL);
  89. UpdateWindow(hwnd);
  90. }
  91. /***************************** Public Function ****************************\
  92. * "StringWindow" window class
  93. *
  94. * Windows of the "StringWindow" window class are simple scrolling text output
  95. * windows that are refreshed properly as windows are rearranged. A text buffer
  96. * is maintained to store the characters as they are drawn.
  97. *
  98. * When creating a StringWindow window, lpCreateParams is actually a UINT
  99. * containing the dimensions of the text buffer to be created, if 0L, then
  100. * a 80 by 25 buffer is created.
  101. *
  102. \***************************************************************************/
  103. LRESULT CALLBACK StrWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  104. {
  105. HANDLE hpsw;
  106. PAINTSTRUCT ps;
  107. RECT rc;
  108. switch (msg) {
  109. case WM_CREATE:
  110. cyChar = 14;
  111. cxChar = 8;
  112. cyDescent = 2;
  113. if (*(PUINT)lParam == 0L) {
  114. *(PUINT)lParam = MAKELONG(80, 50);
  115. }
  116. if (!StrWndCreate(hwnd, LOWORD(*(PUINT)lParam), HIWORD(*(PUINT)lParam)))
  117. return(TRUE);
  118. break;
  119. case WM_SIZE:
  120. InvalidateRect(hwnd, NULL, TRUE);
  121. break;
  122. case WM_DESTROY:
  123. if ((hpsw = (HANDLE)GetWindowLongPtr(hwnd, 0)) != NULL)
  124. LocalFree(hpsw);
  125. break;
  126. case WM_ERASEBKGND:
  127. GetClientRect(hwnd, (LPRECT) &rc);
  128. FillRect((HDC) wParam, (LPRECT) &rc, GetStockObject(WHITE_BRUSH));
  129. break;
  130. case WM_VSCROLL:
  131. scroll(hwnd, GET_WM_VSCROLL_CODE(wParam, lParam),
  132. GET_WM_VSCROLL_POS(wParam, lParam), SB_VERT);
  133. break;
  134. case WM_HSCROLL:
  135. scroll(hwnd, GET_WM_HSCROLL_CODE(wParam, lParam),
  136. GET_WM_HSCROLL_POS(wParam, lParam), SB_HORZ);
  137. break;
  138. case WM_PAINT:
  139. BeginPaint(hwnd, &ps);
  140. PaintStrWnd(hwnd, &ps);
  141. EndPaint(hwnd, &ps);
  142. break;
  143. default:
  144. return(DefWindowProc(hwnd, msg, wParam, lParam));
  145. break;
  146. }
  147. return(0L);
  148. }
  149. VOID scroll(HWND hwnd, UINT msg, UINT sliderpos, UINT style)
  150. {
  151. RECT rc;
  152. INT iPos;
  153. INT dn;
  154. HANDLE hpsw;
  155. register STRWND *psw;
  156. GetClientRect(hwnd, (LPRECT) &rc);
  157. iPos = GetScrollPos(hwnd, style);
  158. hpsw = (HANDLE)GetWindowLongPtr(hwnd, 0);
  159. psw = (STRWND *)LocalLock(hpsw);
  160. switch (msg) {
  161. case SB_LINEDOWN:
  162. dn = 1;
  163. break;
  164. case SB_LINEUP:
  165. dn = -1;
  166. break;
  167. case SB_PAGEDOWN:
  168. if (style == SB_VERT) {
  169. dn = rc.bottom / (cyChar + cyDescent);
  170. } else {
  171. dn = rc.right / cxChar;
  172. }
  173. break;
  174. case SB_PAGEUP:
  175. if (style == SB_VERT) {
  176. dn = -rc.bottom / (cyChar + cyDescent);
  177. } else {
  178. dn = -rc.right / cxChar;
  179. }
  180. break;
  181. case SB_THUMBTRACK:
  182. case SB_THUMBPOSITION:
  183. dn = sliderpos-iPos;
  184. break;
  185. default:
  186. dn = 0;
  187. }
  188. if (style == SB_VERT) {
  189. if (dn = BOUND (iPos + dn, 0, psw->cLine) - iPos) {
  190. psw->cBottomLine -= dn;
  191. ScrollWindow (hwnd, 0, -dn * (cyChar + cyDescent), NULL, NULL);
  192. SetScrollPos (hwnd, SB_VERT, iPos + dn, TRUE);
  193. }
  194. } else /* style == SB_HORZ */ {
  195. if (dn = BOUND (iPos + dn, 0, psw->cchLine) - iPos) {
  196. psw->cLeftChar += dn;
  197. ScrollWindow (hwnd, -dn * cxChar, 0, NULL, NULL);
  198. SetScrollPos (hwnd, SB_HORZ, iPos + dn, TRUE);
  199. }
  200. }
  201. LocalUnlock(hpsw);
  202. }
  203. BOOL StrWndCreate(HWND hwnd, INT cchLine, INT cLine)
  204. {
  205. register INT off;
  206. STRWND *psw;
  207. HANDLE hpsw;
  208. if ((hpsw = LocalAlloc(LMEM_MOVEABLE, sizeof(STRWND)
  209. + (sizeof (TCHAR) * cchLine * cLine))) == NULL)
  210. return(FALSE);
  211. SetWindowLongPtr(hwnd, 0, (UINT_PTR)hpsw);
  212. psw = (STRWND *)LocalLock(hpsw);
  213. psw->cchLine = cchLine;
  214. psw->cLine = cLine;
  215. off = sizeof(STRWND);
  216. psw->offBuffer = off;
  217. psw->offBufferMax = off + cchLine * cLine;
  218. psw->offBottomLine = off;
  219. psw->offOutput = off;
  220. psw->cBottomLine = 0;
  221. psw->cLeftChar = 0;
  222. ClearScreen(psw);
  223. SetScrollRange(hwnd, SB_VERT, 0, cLine, FALSE);
  224. SetScrollPos(hwnd, SB_VERT, cLine, TRUE);
  225. SetScrollRange(hwnd, SB_HORZ, 0, cchLine, TRUE);
  226. LocalUnlock(hpsw);
  227. return(TRUE);
  228. }
  229. VOID ClearScreen(register STRWND *psw)
  230. {
  231. register INT off;
  232. /*
  233. * Make all the lines empty
  234. */
  235. off = psw->offBuffer;
  236. while (off < psw->offBufferMax) {
  237. *OFF2P(psw, off) = TEXT('\0');
  238. off += psw->cchLine;
  239. }
  240. }
  241. VOID PaintStrWnd( HWND hwnd, LPPAINTSTRUCT pps)
  242. {
  243. register STRWND *psw;
  244. register INT off;
  245. INT x;
  246. INT y;
  247. RECT rc, rcOut;
  248. HANDLE hpsw;
  249. SelectObject(pps->hdc, GetStockObject(SYSTEM_FIXED_FONT));
  250. hpsw = (HANDLE)GetWindowLongPtr(hwnd, 0);
  251. psw = (STRWND *)LocalLock(hpsw);
  252. GetClientRect(hwnd, (LPRECT)&rc);
  253. if (!pps->fErase)
  254. FillRect(pps->hdc, (LPRECT)&rc, GetStockObject(WHITE_BRUSH));
  255. x = rc.left - cxChar * psw->cLeftChar;
  256. y = rc.bottom - cyDescent + (cyChar + cyDescent) * psw->cBottomLine;
  257. off = psw->offBottomLine;
  258. if (&pps->rcPaint != NULL)
  259. IntersectRect((LPRECT)&rc, (LPRECT)&rc, &pps->rcPaint);
  260. do {
  261. if (y <= rc.top - cyDescent)
  262. break;
  263. if (y - cyChar <= rc.bottom) {
  264. rcOut.left = x;
  265. rcOut.bottom = y + cyDescent;
  266. rcOut.right = 1000;
  267. rcOut.top = y - cyChar;
  268. DrawText(pps->hdc, (LPTSTR)OFF2P(psw, off), -1, (LPRECT)&rcOut,
  269. DT_LEFT | DT_VCENTER | DT_NOCLIP | DT_EXPANDTABS |
  270. DT_EXTERNALLEADING | DT_NOPREFIX | DT_TABSTOP | 0x0400);
  271. }
  272. y -= cyChar + cyDescent;
  273. /*
  274. * Back up to previous line
  275. */
  276. if (off == psw->offBuffer)
  277. off = psw->offBufferMax;
  278. off -= psw->cchLine;
  279. } while (off != psw->offBottomLine);
  280. LocalUnlock(hpsw);
  281. }