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.

646 lines
16 KiB

  1. //// TEXTWND.CPP
  2. //
  3. // Maintains the text display panel
  4. #include "precomp.hxx"
  5. #include "global.h"
  6. #include "winspool.h"
  7. #include <Tchar.h>
  8. //// InvalidateText - Force redisplay
  9. //
  10. //
  11. void InvalidateText() {
  12. RECT rc;
  13. rc.left = g_fPresentation ? 0 : g_iSettingsWidth;
  14. rc.top = 0;
  15. rc.right = 10000;
  16. rc.bottom = 10000;
  17. InvalidateRect(g_hTextWnd, &rc, TRUE);
  18. }
  19. //// Header - draw a simple header for each text section
  20. //
  21. // Used to distinguish logical, plaintext and formatted text sections of
  22. // text window.
  23. //
  24. // Advances SEPARATORHEIGHT drawing a horizontal line 2/5ths of the way
  25. // down, and displays a title below the line.
  26. //
  27. // At the top of the page displays only the title.
  28. void Header(HDC hdc, char* str, RECT *prc, int *piY) {
  29. HFONT hf;
  30. HFONT hfold;
  31. RECT rcClear;
  32. int iLinePos;
  33. int iTextPos;
  34. int iFontEmHeight;
  35. int iHeight;
  36. int separatorHeight = (prc->bottom - prc->top) / 20;
  37. iFontEmHeight = separatorHeight*40/100;
  38. if (*piY <= prc->top)
  39. {
  40. // Prepare settings for title only, at top of window
  41. iLinePos = -1;
  42. iTextPos = 0;
  43. iHeight = separatorHeight*60/100;
  44. }
  45. else
  46. {
  47. // Prepare settings for 40% white space, a line, 10% whitespace, text and 3% whitespace
  48. iLinePos = separatorHeight*30/100;
  49. iTextPos = separatorHeight*40/100;
  50. iHeight = separatorHeight;
  51. }
  52. rcClear = *prc;
  53. rcClear.top = *piY;
  54. rcClear.bottom = *piY + iHeight;
  55. FillRect(hdc, &rcClear, (HBRUSH) GetStockObject(WHITE_BRUSH));
  56. if (*piY > prc->top) {
  57. // Separate from previous output with double pixel line
  58. MoveToEx(hdc, prc->left, *piY+iLinePos, NULL);
  59. LineTo (hdc, prc->right, *piY+iLinePos);
  60. MoveToEx(hdc, prc->left, *piY+iLinePos+1, NULL);
  61. LineTo (hdc, prc->right, *piY+iLinePos+1);
  62. }
  63. hf = CreateFontA(-iFontEmHeight, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, "Tahoma");
  64. hfold = (HFONT) SelectObject(hdc, hf);
  65. ExtTextOutA(hdc, prc->left, *piY + iTextPos, 0, prc, str, strlen(str), NULL);
  66. *piY += iHeight;
  67. SelectObject(hdc, hfold);
  68. DeleteObject(hf);
  69. }
  70. //// ResetCaret - used during paint by each DSP*.CPP
  71. //
  72. //
  73. void ResetCaret(int iX, int iY, int iHeight) {
  74. g_iCaretX = iX;
  75. g_iCaretY = iY;
  76. if (g_iCaretHeight != iHeight) {
  77. g_iCaretHeight = iHeight;
  78. HideCaret(g_hTextWnd);
  79. DestroyCaret();
  80. CreateCaret(g_hTextWnd, NULL, 0, g_iCaretHeight);
  81. SetCaretPos(g_iCaretX, g_iCaretY);
  82. ShowCaret(g_hTextWnd);
  83. } else {
  84. SetCaretPos(g_iCaretX, g_iCaretY);
  85. }
  86. }
  87. ///// PaintDC - display all selected tests, either on screen
  88. // or on printer.
  89. void PaintDC(HDC hdc, BOOL presentation, RECT &rcText, INT &iY)
  90. {
  91. int iPos;
  92. int iLineHeight;
  93. iY = rcText.top;
  94. if (presentation) {
  95. iLineHeight = rcText.bottom*9/20;
  96. } else {
  97. iLineHeight = 40;
  98. }
  99. if (g_ShowGDI) {
  100. if (!presentation) {
  101. Header(hdc, "GDI", &rcText, &iY);
  102. }
  103. PaintGDI(hdc, &iY, &rcText, iLineHeight);
  104. }
  105. if (g_ShowFamilies) {
  106. if (!presentation) {
  107. Header(hdc, "Font families", &rcText, &iY);
  108. }
  109. PaintFamilies(hdc, &iY, &rcText, iLineHeight);
  110. }
  111. if (g_ShowLogical) {
  112. if (!presentation) {
  113. Header(hdc, "Logical characters (ScriptGetCmap, ExtTextOut(ETO_GLYPHINDEX))", &rcText, &iY);
  114. }
  115. PaintLogical(hdc, &iY, &rcText, iLineHeight);
  116. }
  117. if (g_ShowGlyphs) {
  118. if (!presentation) {
  119. Header(hdc, "DrawGlyphs", &rcText, &iY);
  120. }
  121. PaintGlyphs(hdc, &iY, &rcText, iLineHeight);
  122. }
  123. if (g_ShowDrawString) {
  124. if (!presentation) {
  125. Header(hdc, "DrawString", &rcText, &iY);
  126. }
  127. PaintDrawString(hdc, &iY, &rcText, iLineHeight);
  128. }
  129. if (g_ShowDriver) {
  130. if (!presentation) {
  131. Header(hdc, "DrawDriverString", &rcText, &iY);
  132. }
  133. PaintDrawDriverString(hdc, &iY, &rcText, iLineHeight);
  134. }
  135. if (g_ShowPath) {
  136. if (!presentation) {
  137. Header(hdc, "Path", &rcText, &iY);
  138. }
  139. PaintPath(hdc, &iY, &rcText, iLineHeight);
  140. }
  141. if (g_ShowMetric) {
  142. if (!presentation) {
  143. Header(hdc, "Metrics", &rcText, &iY);
  144. }
  145. PaintMetrics(hdc, &iY, &rcText, iLineHeight);
  146. }
  147. if (g_ShowPerformance) {
  148. if (!presentation) {
  149. Header(hdc, "Performance", &rcText, &iY);
  150. }
  151. PaintPerformance(hdc, &iY, &rcText, iLineHeight);
  152. }
  153. if (g_ShowScaling) {
  154. if (!presentation) {
  155. Header(hdc, "Scaling", &rcText, &iY);
  156. }
  157. PaintScaling(hdc, &iY, &rcText, iLineHeight);
  158. }
  159. /*
  160. if (g_fShowFancyText && !presentation) {
  161. Header(hdc, "Formatted text (ScriptItemize, ScriptLayout, ScriptShape, ScriptPlace, ScriptTextOut)", &rcText, &iY);
  162. PaintFormattedText(hdc, &iY, &rcText, iLineHeight);
  163. }
  164. */
  165. }
  166. //// Paint - redraw part or all of client area
  167. //
  168. //
  169. void PaintWindow(HWND hWnd) {
  170. PAINTSTRUCT ps;
  171. HDC hdc;
  172. RECT rcText;
  173. RECT rcClear;
  174. int iY;
  175. hdc = BeginPaint(hWnd, &ps);
  176. // Remove the settings dialog from the repaint rectangle
  177. if (ps.fErase) {
  178. // Clear below the settings dialog
  179. if (!g_fPresentation) {
  180. rcClear = ps.rcPaint;
  181. if (rcClear.right > g_iSettingsWidth) {
  182. rcClear.right = g_iSettingsWidth;
  183. }
  184. if (rcClear.top < g_iSettingsHeight) {
  185. rcClear.top = g_iSettingsHeight;
  186. }
  187. FillRect(ps.hdc, &rcClear, (HBRUSH) GetStockObject(WHITE_BRUSH));
  188. }
  189. }
  190. // Clear top and left margin
  191. GetClientRect(hWnd, &rcText);
  192. // Left margin
  193. rcClear = rcText;
  194. rcClear.left = g_fPresentation ? 0 : g_iSettingsWidth;
  195. rcClear.right = rcClear.left + 10;
  196. FillRect(ps.hdc, &rcClear, (HBRUSH) GetStockObject(WHITE_BRUSH));
  197. // Top margin
  198. rcClear = rcText;
  199. rcClear.left = g_fPresentation ? 0 : g_iSettingsWidth;
  200. rcClear.top = 0;
  201. rcClear.bottom = 8;
  202. FillRect(ps.hdc, &rcClear, (HBRUSH) GetStockObject(WHITE_BRUSH));
  203. rcText.left = g_fPresentation ? 10 : g_iSettingsWidth + 10;
  204. rcText.top = 8;
  205. if (!g_Offscreen)
  206. {
  207. PaintDC(hdc, g_fPresentation, rcText, iY);
  208. }
  209. else
  210. {
  211. // Render everything to an offscreen buffer instead of
  212. // directly to the display surface...
  213. HBITMAP hbmpOffscreen = NULL;
  214. HDC hdcOffscreen = NULL;
  215. RECT rectOffscreen;
  216. rectOffscreen.left = 0;
  217. rectOffscreen.top = 0;
  218. rectOffscreen.right = rcText.right - rcText.left;
  219. rectOffscreen.bottom = rcText.bottom - rcText.top;
  220. hbmpOffscreen = CreateCompatibleBitmap(hdc, rectOffscreen.right, rectOffscreen.bottom);
  221. if (hbmpOffscreen)
  222. {
  223. hdcOffscreen = CreateCompatibleDC(hdc);
  224. if (hdcOffscreen)
  225. {
  226. HBITMAP hbmpOld = (HBITMAP)SelectObject(hdcOffscreen, hbmpOffscreen);
  227. PaintDC(hdcOffscreen, g_fPresentation, rectOffscreen, iY);
  228. StretchBlt(
  229. hdc,
  230. rcText.left,
  231. rcText.top,
  232. rectOffscreen.right,
  233. rectOffscreen.bottom,
  234. hdcOffscreen,
  235. 0,
  236. 0,
  237. rectOffscreen.right,
  238. rectOffscreen.bottom,
  239. SRCCOPY);
  240. SelectObject(hdcOffscreen, (HGDIOBJ)hbmpOld);
  241. DeleteDC(hdcOffscreen);
  242. }
  243. DeleteObject(hbmpOffscreen);
  244. }
  245. }
  246. // Clear any remaining space below the text
  247. if ( ps.fErase
  248. && iY < rcText.bottom) {
  249. rcClear = rcText;
  250. rcClear.top = iY;
  251. FillRect(ps.hdc, &rcClear, (HBRUSH) GetStockObject(WHITE_BRUSH));
  252. }
  253. EndPaint(hWnd, &ps);
  254. }
  255. void PrintPage()
  256. {
  257. PRINTDLG printDialog;
  258. memset(&printDialog, 0, sizeof(printDialog));
  259. printDialog.lStructSize = sizeof(printDialog);
  260. printDialog.Flags = PD_RETURNDC | PD_NOPAGENUMS | PD_NOSELECTION ;
  261. if (PrintDlg(&printDialog))
  262. {
  263. HDC dc = printDialog.hDC;
  264. if (dc != NULL)
  265. {
  266. DOCINFO documentInfo;
  267. documentInfo.cbSize = sizeof(documentInfo);
  268. documentInfo.lpszDocName = _T("TextTest");
  269. documentInfo.lpszOutput = NULL;
  270. documentInfo.lpszDatatype = NULL;
  271. documentInfo.fwType = 0;
  272. if (StartDoc(dc, &documentInfo))
  273. {
  274. if (StartPage(dc) > 0)
  275. {
  276. RECT rcText;
  277. INT iY;
  278. rcText.left = 0;
  279. rcText.top = 0;
  280. rcText.right = GetDeviceCaps(dc, HORZRES);
  281. rcText.bottom = GetDeviceCaps(dc, VERTRES);
  282. PaintDC(dc, FALSE, rcText, iY);
  283. EndPage(dc);
  284. }
  285. EndDoc(dc);
  286. }
  287. DeleteDC(dc);
  288. }
  289. }
  290. }
  291. //// TextWndProc - Main window message handler and dispatcher
  292. //
  293. //
  294. LRESULT CALLBACK TextWndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) {
  295. HDC hdc;
  296. switch (message) {
  297. case WM_CREATE:
  298. hdc = GetDC(hWnd);
  299. g_iLogPixelsY = GetDeviceCaps(hdc, LOGPIXELSY);
  300. ReleaseDC(hWnd, hdc);
  301. break;
  302. case WM_ERASEBKGND:
  303. return 0; // Leave Paint to erase the background
  304. case WM_CHAR:
  305. if (!g_bUnicodeWnd) {
  306. // Convert ANSI keyboard data to Unicode
  307. int iCP;
  308. switch (PRIMARYLANGID(LOWORD(GetKeyboardLayout(NULL)))) {
  309. case LANG_ARABIC: iCP = 1256; break;
  310. case LANG_HEBREW: iCP = 1255; break;
  311. case LANG_THAI: iCP = 874; break;
  312. default: iCP = 1252; break;
  313. }
  314. MultiByteToWideChar(iCP, 0, (char*)&wParam, 1, (WCHAR*)&wParam, 1);
  315. }
  316. if (LOWORD(wParam) == 0x1B) {
  317. // Exit presentation mode
  318. g_fPresentation = FALSE;
  319. ShowWindow(g_hSettingsDlg, SW_SHOW);
  320. UpdateWindow(g_hSettingsDlg);
  321. InvalidateText();
  322. } else {
  323. EditChar(LOWORD(wParam));
  324. }
  325. break;
  326. case WM_KEYDOWN:
  327. EditKeyDown(LOWORD(wParam));
  328. break;
  329. case WM_KEYUP:
  330. if (wParam != VK_ESCAPE) {
  331. goto DefaultWindowProcedure;
  332. }
  333. // Eat all escape key processing
  334. break;
  335. case WM_LBUTTONDOWN:
  336. g_iMouseDownX = LOWORD(lParam); // horizontal position of cursor
  337. g_iMouseDownY = HIWORD(lParam); // vertical position of cursor
  338. g_fMouseDown = TRUE;
  339. SetFocus(hWnd);
  340. break;
  341. case WM_MOUSEMOVE:
  342. // Treat movement like lbuttonup while lbutton is down,
  343. // so the selection tracks the cursor movement.
  344. if (wParam & MK_LBUTTON) {
  345. g_iMouseUpX = LOWORD(lParam); // horizontal position of cursor
  346. g_iMouseUpY = HIWORD(lParam); // vertical position of cursor
  347. g_fMouseUp = TRUE;
  348. InvalidateText();
  349. SetActiveWindow(hWnd);
  350. }
  351. break;
  352. case WM_LBUTTONUP:
  353. g_iMouseUpX = LOWORD(lParam); // horizontal position of cursor
  354. g_iMouseUpY = HIWORD(lParam); // vertical position of cursor
  355. g_fMouseUp = TRUE;
  356. InvalidateText();
  357. SetActiveWindow(hWnd);
  358. break;
  359. case WM_SETFOCUS:
  360. CreateCaret(hWnd, NULL, 0, g_iCaretHeight);
  361. SetCaretPos(g_iCaretX, g_iCaretY);
  362. ShowCaret(hWnd);
  363. break;
  364. case WM_KILLFOCUS:
  365. DestroyCaret();
  366. break;
  367. case WM_GETMINMAXINFO:
  368. // Don't let text window size drop too low
  369. ((LPMINMAXINFO)lParam)->ptMinTrackSize.x = g_fPresentation ? 10 : g_iMinWidth;
  370. ((LPMINMAXINFO)lParam)->ptMinTrackSize.y = g_fPresentation ? 10 : g_iMinHeight;
  371. return 0;
  372. case WM_PAINT:
  373. PaintWindow(hWnd);
  374. break;
  375. case WM_DESTROY:
  376. if (g_textBrush)
  377. delete g_textBrush;
  378. if (g_textBackBrush)
  379. delete g_textBackBrush;
  380. DestroyWindow(g_hSettingsDlg);
  381. PostQuitMessage(0);
  382. return 0;
  383. default:
  384. DefaultWindowProcedure:
  385. if (g_bUnicodeWnd) {
  386. return DefWindowProcW(hWnd, message, wParam, lParam);
  387. } else {
  388. return DefWindowProcA(hWnd, message, wParam, lParam);
  389. }
  390. }
  391. return 0;
  392. }
  393. //// CreateTextWindow - create window class and window
  394. //
  395. // Attempts to use a Unicode window, if this fails uses an ANSI
  396. // window.
  397. //
  398. // For example the Unicode window will succeed on Windows NT and
  399. // Windows CE, but fail on Windows 9x.
  400. HWND CreateTextWindow() {
  401. WNDCLASSA wcA;
  402. WNDCLASSW wcW;
  403. HWND hWnd;
  404. // Try registering as a Unicode window
  405. wcW.style = CS_HREDRAW | CS_VREDRAW;
  406. wcW.lpfnWndProc = TextWndProc;
  407. wcW.cbClsExtra = 0;
  408. wcW.cbWndExtra = 0;
  409. wcW.hInstance = g_hInstance;
  410. wcW.hIcon = LoadIconW(g_hInstance, APPNAMEW);
  411. wcW.hCursor = LoadCursorW(NULL, (WCHAR*)IDC_ARROW);
  412. wcW.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  413. wcW.lpszMenuName = APPNAMEW;
  414. wcW.lpszClassName = APPNAMEW;
  415. if (RegisterClassW(&wcW)) {
  416. // Use a Unicode window
  417. g_bUnicodeWnd = TRUE;
  418. hWnd = CreateWindowW(
  419. APPNAMEW, APPTITLEW,
  420. WS_OVERLAPPEDWINDOW,
  421. CW_USEDEFAULT, 0,
  422. CW_USEDEFAULT, 0,
  423. NULL, NULL,
  424. g_hInstance,
  425. NULL);
  426. return hWnd;
  427. } else {
  428. // Must use an ANSI window.
  429. wcA.style = CS_HREDRAW | CS_VREDRAW;
  430. wcA.lpfnWndProc = TextWndProc;
  431. wcA.cbClsExtra = 0;
  432. wcA.cbWndExtra = 0;
  433. wcA.hInstance = g_hInstance;
  434. wcA.hIcon = LoadIconA(g_hInstance, APPNAMEA);
  435. wcA.hCursor = LoadCursor(NULL, IDC_ARROW);
  436. wcA.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  437. wcA.lpszMenuName = APPNAMEA;
  438. wcA.lpszClassName = APPNAMEA;
  439. if (!RegisterClassA(&wcA)) {
  440. return NULL;
  441. }
  442. g_bUnicodeWnd = FALSE;
  443. hWnd = CreateWindowA(
  444. APPNAMEA, APPTITLEA,
  445. WS_OVERLAPPEDWINDOW,
  446. CW_USEDEFAULT, 0,
  447. CW_USEDEFAULT, 0,
  448. NULL, NULL,
  449. g_hInstance,
  450. NULL);
  451. };
  452. return hWnd;
  453. }