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.

620 lines
18 KiB

  1. /*
  2. * standard table class.
  3. *
  4. * print functions.
  5. *
  6. * see table.h for interface description
  7. */
  8. #include <string.h>
  9. #include "windows.h"
  10. #include "commdlg.h"
  11. #include "gutils.h"
  12. #include "gutilsrc.h"
  13. #include "table.h"
  14. #include "tpriv.h"
  15. /* in tpaint.c, calls GetTextExtentPoint */
  16. extern int GetTextExtent(HDC, LPSTR, int);
  17. extern HANDLE hLibInst;
  18. /* function prototypes */
  19. lpTable gtab_printsetup(HWND hwnd, lpTable ptab, HANDLE heap,
  20. lpPrintContext pcontext);
  21. BOOL gtab_prtwidths(HWND hwnd, lpTable ptab, HANDLE heap, lpPrintContext
  22. pcontext);
  23. void gtab_printjob(HWND hwnd, lpTable ptab, lpPrintContext pcontext);
  24. int APIENTRY AbortProc(HDC hpr, int code);
  25. INT_PTR CALLBACK AbortDlg(HWND, UINT, WPARAM, LPARAM);
  26. BOOL gtab_printpage(HWND hwnd, lpTable ptab, lpPrintContext pcontext, int page);
  27. void gtab_setrects(lpPrintContext pcontext, LPRECT rcinner, LPRECT rcouter);
  28. void gtab_printhead(HWND hwnd, HDC hdc, lpTable ptab, lpTitle head, int page, BOOL fExpandChars);
  29. /*
  30. * gtab_print
  31. */
  32. BOOL
  33. gtab_print(HWND hwnd, lpTable ptab, HANDLE heap, lpPrintContext pcontext)
  34. {
  35. BOOL fNoContext, fNoMargin, fNoPD;
  36. BOOL fSuccess = TRUE;
  37. lpTable ptab_prt;
  38. fNoContext = FALSE;
  39. fNoPD = FALSE;
  40. fNoMargin = FALSE;
  41. if (pcontext == NULL) {
  42. fNoContext = TRUE;
  43. pcontext = (lpPrintContext) gmem_get(heap,
  44. sizeof(PrintContext));
  45. pcontext->head = pcontext->foot = NULL;
  46. pcontext->margin = NULL;
  47. pcontext->pd = NULL;
  48. pcontext->id = 0;
  49. }
  50. if (pcontext->pd == NULL) {
  51. fNoPD = TRUE;
  52. }
  53. if (pcontext->margin == NULL) {
  54. fNoMargin = TRUE;
  55. }
  56. ptab_prt = gtab_printsetup(hwnd, ptab, heap, pcontext);
  57. if (ptab_prt != NULL) {
  58. gtab_printjob(hwnd, ptab_prt, pcontext);
  59. gtab_deltable(hwnd, ptab_prt);
  60. } else fSuccess = FALSE;
  61. if (fNoMargin) {
  62. gmem_free(heap, (LPSTR)pcontext->margin,
  63. sizeof(Margin));
  64. pcontext->margin = NULL;
  65. }
  66. if (fNoPD) {
  67. if (pcontext->pd->hDevMode != NULL) {
  68. GlobalFree(pcontext->pd->hDevMode);
  69. }
  70. if (pcontext->pd->hDevNames != NULL) {
  71. GlobalFree(pcontext->pd->hDevNames);
  72. }
  73. gmem_free(heap, (LPSTR) pcontext->pd, sizeof(PRINTDLG));
  74. pcontext->pd = NULL;
  75. }
  76. if (fNoContext) {
  77. gmem_free(heap, (LPSTR) pcontext, sizeof(PrintContext));
  78. }
  79. return fSuccess;
  80. }
  81. /*
  82. * gtab_printsetup()
  83. *
  84. * sets up printercontext - builds lpTable for printer, incl. sizing
  85. * and initialises pcontext fields that may be null.
  86. */
  87. lpTable
  88. gtab_printsetup(HWND hwnd, lpTable ptab, HANDLE heap, lpPrintContext pcontext)
  89. {
  90. lpTable pprttab;
  91. PRINTDLG FAR * pd;
  92. int ncols, i;
  93. ColPropsList cplist;
  94. /* set fields for context that user left null */
  95. if (pcontext->margin == NULL) {
  96. pcontext->margin = (lpMargin) gmem_get(heap, sizeof(Margin));
  97. if (pcontext->margin == NULL) {
  98. return(NULL);
  99. }
  100. pcontext->margin->left = 10;
  101. pcontext->margin->right = 10;
  102. pcontext->margin->top = 15;
  103. pcontext->margin->bottom = 15;
  104. pcontext->margin->topinner = 15;
  105. pcontext->margin->bottominner = 15;
  106. }
  107. if (pcontext->pd == NULL) {
  108. pd = (PRINTDLG FAR *) gmem_get(heap, sizeof(PRINTDLG));
  109. if (pd == NULL) {
  110. return(NULL);
  111. }
  112. pcontext->pd = pd;
  113. pd->lStructSize = sizeof(PRINTDLG);
  114. pd->hwndOwner = hwnd;
  115. pd->hDevMode = (HANDLE) NULL;
  116. pd->hDevNames = (HANDLE) NULL;
  117. pd->Flags = PD_RETURNDC|PD_RETURNDEFAULT;
  118. if (PrintDlg(pd) == FALSE) {
  119. return(NULL);
  120. }
  121. }
  122. /* now create a Table struct by querying the owner */
  123. pprttab = (lpTable) gmem_get(heap, sizeof(Table));
  124. if (pprttab == NULL) {
  125. return(NULL);
  126. }
  127. pprttab->hdr = ptab->hdr;
  128. pprttab->tabchars = ptab->tabchars;
  129. pprttab->show_whitespace = ptab->show_whitespace;
  130. /* get the row/column count from owner window */
  131. if (pcontext->id == 0) {
  132. pprttab->hdr.id = ptab->hdr.id;
  133. } else {
  134. pprttab->hdr.id = pcontext->id;
  135. }
  136. pprttab->hdr.props.valid = 0;
  137. pprttab->hdr.sendscroll = FALSE;
  138. if (gtab_sendtq(hwnd, TQ_GETSIZE, (LPARAM)&pprttab->hdr) == FALSE) {
  139. return(NULL);
  140. }
  141. /* alloc and init the col data structs */
  142. ncols = pprttab->hdr.ncols;
  143. pprttab->pcolhdr = (lpColProps) gmem_get(heap, sizeof(ColProps) * ncols);
  144. if (pprttab->pcolhdr == NULL) {
  145. gmem_free(heap, (LPSTR)pprttab, sizeof(Table));
  146. return(NULL);
  147. }
  148. /* init col properties to default */
  149. for (i=0; i < ncols; i++) {
  150. pprttab->pcolhdr[i].props.valid = 0;
  151. pprttab->pcolhdr[i].nchars = 0;
  152. }
  153. /* get the column props from owner */
  154. cplist.plist = pprttab->pcolhdr;
  155. cplist.id = pprttab->hdr.id;
  156. cplist.startcol = 0;
  157. cplist.ncols = ncols;
  158. gtab_sendtq(hwnd, TQ_GETCOLPROPS, (LPARAM)&cplist);
  159. pprttab->scrollscale = 1;
  160. pprttab->pcellpos = (lpCellPos) gmem_get(heap,
  161. sizeof(CellPos) * ptab->hdr.ncols);
  162. if (pprttab->pcellpos == NULL) {
  163. gmem_free(heap, (LPSTR) pprttab->pcolhdr, sizeof(ColProps) * ncols);
  164. gmem_free(heap, (LPSTR)pprttab, sizeof(Table));
  165. return(NULL);
  166. }
  167. pprttab->pdata = NULL;
  168. pprttab->nlines = 0;
  169. if (!gtab_prtwidths(hwnd, pprttab, heap, pcontext)) {
  170. gmem_free(heap, (LPSTR)pprttab->pcellpos,
  171. sizeof(CellPos) * ptab->hdr.ncols);
  172. gmem_free(heap, (LPSTR)pprttab, sizeof(Table));
  173. return(NULL);
  174. }
  175. return(pprttab);
  176. }
  177. /* calc the height/width settings and alloc line data */
  178. BOOL
  179. gtab_prtwidths(HWND hwnd, lpTable ptab, HANDLE heap, lpPrintContext pcontext)
  180. {
  181. TEXTMETRIC tm;
  182. int cx, cxtotal, i, curx, cury;
  183. lpProps hdrprops, cellprops;
  184. lpCellPos xpos, ypos;
  185. RECT rcinner, rcouter;
  186. hdrprops = &ptab->hdr.props;
  187. GetTextMetrics(pcontext->pd->hDC, &tm);
  188. ptab->avewidth = tm.tmAveCharWidth;
  189. ptab->rowheight = tm.tmHeight + tm.tmExternalLeading;
  190. if (hdrprops->valid & P_HEIGHT) {
  191. ptab->rowheight = hdrprops->height;
  192. }
  193. /* set sizes for headers */
  194. gtab_setrects(pcontext, &rcinner, &rcouter);
  195. /* set width/pos for each col. */
  196. cxtotal = 0;
  197. curx = rcinner.left;
  198. for (i = 0; i < ptab->hdr.ncols; i++) {
  199. cellprops = &ptab->pcolhdr[i].props;
  200. xpos = &ptab->pcellpos[i];
  201. if (cellprops->valid & P_WIDTH) {
  202. cx = cellprops->width;
  203. } else if (hdrprops->valid & P_WIDTH) {
  204. cx = hdrprops->width;
  205. } else {
  206. cx = ptab->pcolhdr[i].nchars + 1;
  207. cx *= ptab->avewidth;
  208. }
  209. /* add 2 for intercol spacing */
  210. cx += 2;
  211. xpos->size = cx;
  212. xpos->start = curx + 1;
  213. xpos->clipstart = xpos->start;
  214. xpos->clipend = xpos->start + xpos->size - 2;
  215. xpos->clipend = min(xpos->clipend, rcinner.right);
  216. cxtotal += xpos->size;
  217. curx += xpos->size;
  218. }
  219. ptab->rowwidth = cxtotal;
  220. if (pcontext->head != NULL) {
  221. xpos = &pcontext->head->xpos;
  222. ypos = &pcontext->head->ypos;
  223. xpos->start = rcouter.left + 1;
  224. xpos->clipstart = rcouter.left + 1;
  225. xpos->clipend = rcouter.right - 1;
  226. xpos->size = rcouter.right - rcouter.left;
  227. ypos->start = rcouter.top;
  228. ypos->clipstart = rcouter.top;
  229. ypos->clipend = rcinner.top;
  230. ypos->size = ptab->rowheight;
  231. }
  232. if (pcontext->foot != NULL) {
  233. xpos = &pcontext->foot->xpos;
  234. ypos = &pcontext->foot->ypos;
  235. xpos->start = rcouter.left + 1;
  236. xpos->clipstart = rcouter.left + 1;
  237. xpos->clipend = rcouter.right - 1;
  238. xpos->size = rcouter.right - rcouter.left;
  239. ypos->start = rcouter.bottom - ptab->rowheight;
  240. ypos->clipstart = rcinner.bottom;
  241. ypos->clipend = rcouter.bottom;
  242. ypos->size = ptab->rowheight;
  243. }
  244. /* set nr of lines per page */
  245. ptab->nlines = (rcinner.bottom - rcinner.top) / ptab->rowheight;
  246. if (!gtab_alloclinedata(hwnd, heap, ptab)) {
  247. return(FALSE);
  248. }
  249. /* set line positions */
  250. cury = rcinner.top;
  251. for (i = 0; i < ptab->nlines; i++) {
  252. ypos = &ptab->pdata[i].linepos;
  253. ypos->start = cury;
  254. ypos->clipstart = ypos->start;
  255. ypos->clipend = ypos->start + ypos->size;
  256. ypos->clipend = min(ypos->clipend, rcinner.bottom);
  257. cury += ypos->size;
  258. }
  259. return(TRUE);
  260. }
  261. /* static information for this module */
  262. BOOL bAbort;
  263. FARPROC lpAbortProc;
  264. //DLGPROC lpAbortDlg;
  265. HWND hAbortWnd;
  266. int npage;
  267. int pages;
  268. void
  269. gtab_printjob(HWND hwnd, lpTable ptab, lpPrintContext pcontext)
  270. {
  271. int moveables;
  272. int endpage;
  273. int startpage = 1;
  274. HDC hpr;
  275. int status;
  276. HANDLE hcurs;
  277. static char str[256];
  278. DOCINFO di;
  279. TCHAR szPage[60]; /* for LoadString */
  280. hcurs = SetCursor(LoadCursor(NULL, IDC_WAIT));
  281. moveables = ptab->nlines - ptab->hdr.fixedrows;
  282. pages = (int) (ptab->hdr.nrows - ptab->hdr.fixedrows + moveables - 1)
  283. / moveables;
  284. endpage = pages;
  285. if (pcontext->pd->Flags & PD_PAGENUMS) {
  286. startpage = pcontext->pd->nFromPage;
  287. endpage = pcontext->pd->nToPage;
  288. }
  289. hpr = pcontext->pd->hDC;
  290. //lpAbortDlg = (DLGPROC) MakeProcInstance((WINPROCTYPE) AbortDlg, hLibInst);
  291. lpAbortProc = (FARPROC) MakeProcInstance((WINPROCTYPE)AbortProc, hLibInst);
  292. SetAbortProc(hpr, (ABORTPROC) lpAbortProc);
  293. di.lpszDocName = "Table";
  294. di.cbSize = lstrlen(di.lpszDocName);
  295. di.lpszOutput = NULL;
  296. di.lpszDatatype = NULL;
  297. di.fwType = 0;
  298. StartDoc(hpr, &di);
  299. bAbort = FALSE;
  300. /* add abort modeless dialog later!! */
  301. //hAbortWnd = CreateDialog(hLibInst, "GABRTDLG", hwnd, lpAbortDlg);
  302. hAbortWnd = CreateDialog(hLibInst, "GABRTDLG", hwnd, AbortDlg);
  303. if (hAbortWnd != NULL) {
  304. ShowWindow(hAbortWnd, SW_NORMAL);
  305. EnableWindow(hwnd, FALSE);
  306. }
  307. SetCursor(hcurs);
  308. status = 0; /* kills a "used without init" diagnostic */
  309. for (npage = startpage; npage<=endpage; npage++) {
  310. LoadString(hLibInst,IDS_PAGE_STR,szPage,sizeof(szPage));
  311. wsprintf(str, szPage, npage, pages);
  312. if (hAbortWnd != NULL)
  313. SetDlgItemText(hAbortWnd, IDC_LPAGENR, str);
  314. status = gtab_printpage(hwnd, ptab, pcontext, npage);
  315. if (status < 0) {
  316. AbortDoc(hpr);
  317. break;
  318. }
  319. }
  320. if (status >= 0) {
  321. EndDoc(hpr);
  322. }
  323. if (hAbortWnd != NULL) {
  324. EnableWindow(hwnd, TRUE);
  325. DestroyWindow(hAbortWnd);
  326. }
  327. //FreeProcInstance((WINPROCTYPE) lpAbortDlg);
  328. FreeProcInstance(lpAbortProc);
  329. DeleteDC(hpr);
  330. }
  331. int APIENTRY
  332. AbortProc(HDC hpr, int code)
  333. {
  334. MSG msg;
  335. if (!hAbortWnd) {
  336. return(TRUE);
  337. }
  338. while (!bAbort && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
  339. if (!IsDialogMessage(hAbortWnd, &msg)) {
  340. TranslateMessage(&msg);
  341. DispatchMessage(&msg);
  342. }
  343. }
  344. return(!bAbort);
  345. }
  346. INT_PTR CALLBACK
  347. AbortDlg(HWND hdlg, UINT msg, WPARAM wParam, LPARAM lParam)
  348. {
  349. switch (msg) {
  350. case WM_COMMAND:
  351. bAbort = TRUE;
  352. EndDialog(hdlg, TRUE);
  353. return TRUE;
  354. case WM_INITDIALOG:
  355. return TRUE;
  356. }
  357. return(FALSE);
  358. }
  359. /*
  360. * print a single page. page number is 1-based
  361. */
  362. BOOL
  363. gtab_printpage(HWND hwnd, lpTable ptab, lpPrintContext pcontext, int page)
  364. {
  365. HDC hpr;
  366. int moveables, i;
  367. int x1, y1, x2, y2;
  368. hpr = pcontext->pd->hDC;
  369. StartPage(hpr);
  370. moveables = ptab->nlines - ptab->hdr.fixedrows;
  371. ptab->toprow = moveables * (page-1);
  372. gtab_invallines(hwnd, ptab, ptab->hdr.fixedrows, moveables);
  373. for (i =0; i < ptab->nlines; i++) {
  374. gtab_paintline(hwnd, hpr, ptab, i, ptab->show_whitespace, TRUE);
  375. }
  376. if ((ptab->hdr.vseparator) && (ptab->hdr.fixedcols > 0)) {
  377. x1 = ptab->pcellpos[ptab->hdr.fixedcols -1].clipend+1;
  378. y1 = ptab->pdata[0].linepos.clipstart;
  379. y2 = ptab->pdata[ptab->nlines-1].linepos.clipend;
  380. MoveToEx(hpr, x1, y1, NULL);
  381. LineTo(hpr, x1, y2);
  382. }
  383. if ((ptab->hdr.hseparator) && (ptab->hdr.fixedrows > 0)) {
  384. y1 = ptab->pdata[ptab->hdr.fixedrows-1].linepos.clipend;
  385. x1 = ptab->pcellpos[0].clipstart;
  386. x2 = ptab->pcellpos[ptab->hdr.ncols-1].clipend;
  387. MoveToEx(hpr, x1, y1, NULL);
  388. LineTo(hpr, x2, y1);
  389. }
  390. if (pcontext->head != NULL) {
  391. gtab_printhead(hwnd, hpr, ptab, pcontext->head, page, FALSE);
  392. }
  393. if (pcontext->foot != NULL) {
  394. gtab_printhead(hwnd, hpr, ptab, pcontext->foot, page, TRUE);
  395. }
  396. return(EndPage(hpr));
  397. }
  398. /*
  399. * calculate the outline positions in pixels for the headers
  400. * (outer rect) and for the page itself (inner rect). Based on
  401. * page size and PrintContext margin info (which is in millimetres).
  402. */
  403. void
  404. gtab_setrects(lpPrintContext pcontext, LPRECT rcinner, LPRECT rcouter)
  405. {
  406. HDC hpr;
  407. int hpixels, hmms;
  408. int vpixels, vmms;
  409. int h_pixpermm, v_pixpermm;
  410. hpr = pcontext->pd->hDC;
  411. hpixels = GetDeviceCaps(hpr, HORZRES);
  412. vpixels = GetDeviceCaps(hpr, VERTRES);
  413. vmms = GetDeviceCaps(hpr, VERTSIZE);
  414. hmms = GetDeviceCaps(hpr, HORZSIZE);
  415. h_pixpermm = hpixels / hmms;
  416. v_pixpermm = vpixels / vmms;
  417. rcouter->top = (pcontext->margin->top * v_pixpermm);
  418. rcouter->bottom = vpixels - (pcontext->margin->bottom * v_pixpermm);
  419. rcouter->left = (pcontext->margin->left * h_pixpermm);
  420. rcouter->right = hpixels - (pcontext->margin->right * h_pixpermm);
  421. rcinner->left = rcouter->left;
  422. rcinner->right = rcouter->right;
  423. rcinner->top = rcouter->top +
  424. (pcontext->margin->topinner * v_pixpermm);
  425. rcinner->bottom = rcouter->bottom -
  426. (pcontext->margin->bottominner * v_pixpermm);
  427. }
  428. void
  429. gtab_printhead(HWND hwnd, HDC hdc, lpTable ptab, lpTitle head, int page, BOOL fExpandChars)
  430. {
  431. RECT rc, rcbox;
  432. int i, cx, x, y, tab;
  433. UINT align;
  434. LPSTR chp, tabp;
  435. DWORD fcol, bkcol;
  436. char str[MAX_PATH * 2];
  437. fcol = 0; bkcol = 0; /* eliminate spurious diagnostic - generate worse code */
  438. rc.top = head->ypos.clipstart;
  439. rc.bottom = head->ypos.clipend;
  440. rc.left = head->xpos.clipstart;
  441. rc.right = head->xpos.clipend;
  442. /* update page number */
  443. if (fExpandChars) {
  444. chp = str;
  445. for (i = 0; i < lstrlen(head->ptext); i++) {
  446. switch (head->ptext[i]) {
  447. case '#':
  448. chp += wsprintf(chp, "%d", page);
  449. break;
  450. case '$':
  451. chp += wsprintf(chp, "%d", pages);
  452. break;
  453. default:
  454. if (IsDBCSLeadByte(head->ptext[i]) &&
  455. head->ptext[i+1])
  456. {
  457. *chp = head->ptext[i];
  458. chp++;
  459. i++;
  460. }
  461. *chp++ = head->ptext[i];
  462. break;
  463. }
  464. }
  465. *chp = '\0';
  466. } else {
  467. lstrcpy(str, head->ptext);
  468. }
  469. chp = str;
  470. if (head->props.valid & P_ALIGN) {
  471. align = head->props.alignment;
  472. } else {
  473. align = P_LEFT;
  474. }
  475. /* set colours if not default */
  476. if (head->props.valid & P_FCOLOUR) {
  477. fcol = SetTextColor(hdc, head->props.forecolour);
  478. }
  479. if (head->props.valid & P_BCOLOUR) {
  480. bkcol = SetBkColor(hdc, head->props.backcolour);
  481. }
  482. /* calc offset of text within cell for right-align or centering */
  483. if (align == P_LEFT) {
  484. cx = ptab->avewidth/2;
  485. } else {
  486. cx = LOWORD(GetTextExtent(hdc, chp, lstrlen(chp)));
  487. if (align == P_CENTRE) {
  488. cx = (head->xpos.size - cx) / 2;
  489. } else {
  490. cx = head->xpos.size - cx - (ptab->avewidth/2);
  491. }
  492. }
  493. cx += head->xpos.start;
  494. /* expand tabs on output */
  495. tab = ptab->avewidth * ptab->tabchars;
  496. x = 0;
  497. y = head->ypos.start;
  498. for ( ; (tabp = My_mbschr(chp, '\t')) != NULL; ) {
  499. /* perform output upto tab char */
  500. ExtTextOut(hdc, x+cx, y, ETO_CLIPPED, &rc, chp, (UINT)(tabp-chp), NULL);
  501. /* advance past the tab */
  502. x += LOWORD(GetTextExtent(hdc, chp, (INT)(tabp - chp)));
  503. x = ( (x + tab) / tab) * tab;
  504. chp = ++tabp;
  505. }
  506. /*no more tabs - output rest of string */
  507. ExtTextOut(hdc, x+cx, y, ETO_CLIPPED, &rc, chp, lstrlen(chp), NULL);
  508. /* reset colours to original if not default */
  509. if (head->props.valid & P_FCOLOUR) {
  510. SetTextColor(hdc, fcol);
  511. }
  512. if (head->props.valid & P_BCOLOUR) {
  513. SetBkColor(hdc, bkcol);
  514. }
  515. /* now box cell if marked */
  516. if (head->props.valid & P_BOX) {
  517. if (head->props.box != 0) {
  518. rcbox.top = head->ypos.start;
  519. rcbox.bottom = rcbox.top + head->ypos.size;
  520. rcbox.left = head->xpos.start;
  521. rcbox.right = rcbox.left + head->xpos.size;
  522. gtab_boxcell(hwnd, hdc, &rcbox, &rc, head->props.box);
  523. }
  524. }
  525. }