|
|
1.1 root 1:
2: /******************************************************************************\
3: * This is a part of the Microsoft Source Code Samples.
4: * Copyright (C) 1993 Microsoft Corporation.
5: * All rights reserved.
6: * This source code is only intended as a supplement to
7: * Microsoft Development Tools and/or WinHelp documentation.
8: * See these sources for detailed information regarding the
9: * Microsoft samples programs.
10: \******************************************************************************/
11:
12: /****************************** Module Header *******************************
13: * Module Name: TPRINT.C
14: *
15: * Print functions.
16: *
17: * Functions:
18: *
19: * gtab_print()
20: * gtab_printsetup()
21: * gtab_prtwidths()
22: * gtab_printjob()
23: * AbortProc()
24: * AbortDlg()
25: * gtab_printpage()
26: * gtab_setrects()
27: * gtab_printhead()
28: *
29: * Comments:
30: *
31: * See table.h for interface description.
32: *
33: ****************************************************************************/
34:
35: #include <string.h>
36: #include <windows.h>
37: #include <commdlg.h>
38:
39: #include "gutils.h"
40: #include "gutilsrc.h"
41: #include "table.h"
42: #include "tpriv.h"
43:
44: /* in tpaint.c, calls GetTextExtentPoint */
45: extern int GetTextExtent(HDC, LPSTR, int);
46:
47: extern HANDLE hLibInst;
48:
49: /* function prototypes */
50: lpTable gtab_printsetup(HWND hwnd, lpTable ptab, HANDLE heap,
51: lpPrintContext pcontext);
52: BOOL gtab_prtwidths(HWND hwnd, lpTable ptab, HANDLE heap, lpPrintContext
53: pcontext);
54: void gtab_printjob(HWND hwnd, lpTable ptab, lpPrintContext pcontext);
55: int APIENTRY AbortProc(HDC hpr, int code);
56: int APIENTRY AbortDlg(HWND hdlg, UINT msg, UINT wParam, LONG lParam);
57: BOOL gtab_printpage(HWND hwnd, lpTable ptab, lpPrintContext pcontext, int page);
58: void gtab_setrects(lpPrintContext pcontext, LPRECT rcinner, LPRECT rcouter);
59: void gtab_printhead(HWND hwnd, HDC hdc, lpTable ptab, lpTitle head, int page);
60:
61:
62: /***************************************************************************
63: * Function: gtab_print
64: *
65: * Purpose:
66: *
67: * Prints a table.
68: */
69: void
70: gtab_print(HWND hwnd, lpTable ptab, HANDLE heap, lpPrintContext pcontext)
71: {
72: BOOL fNoContext, fNoMargin, fNoPD;
73: lpTable ptab_prt;
74:
75: fNoContext = FALSE;
76: fNoPD = FALSE;
77: fNoMargin = FALSE;
78:
79: if (pcontext == NULL) {
80: fNoContext = TRUE;
81: pcontext = (lpPrintContext) gmem_get(heap,
82: sizeof(PrintContext));
83: pcontext->head = pcontext->foot = NULL;
84: pcontext->margin = NULL;
85: pcontext->pd = NULL;
86: pcontext->id = 0;
87: }
88: if (pcontext->pd == NULL) {
89: fNoPD = TRUE;
90: }
91: if (pcontext->margin == NULL) {
92: fNoMargin = TRUE;
93: }
94: ptab_prt = gtab_printsetup(hwnd, ptab, heap, pcontext);
95:
96: if (ptab_prt != NULL) {
97: gtab_printjob(hwnd, ptab_prt, pcontext);
98:
99: gtab_deltable(hwnd, ptab_prt);
100: }
101: if (fNoMargin) {
102: gmem_free(heap, (LPSTR)pcontext->margin,
103: sizeof(Margin));
104: pcontext->margin = NULL;
105: }
106: if (fNoPD) {
107: if (pcontext->pd->hDevMode != NULL) {
108: GlobalFree(pcontext->pd->hDevMode);
109: }
110: if (pcontext->pd->hDevNames != NULL) {
111: GlobalFree(pcontext->pd->hDevNames);
112: }
113: gmem_free(heap, (LPSTR) pcontext->pd, sizeof(PRINTDLG));
114: pcontext->pd = NULL;
115: }
116: if (fNoContext) {
117: gmem_free(heap, (LPSTR) pcontext, sizeof(PrintContext));
118: }
119: }
120:
121:
122:
123: /***************************************************************************
124: * Function: gtab_printsetup
125: *
126: * Purpose:
127: *
128: * Sets up printercontext - builds lpTable for printer, incl. sizing
129: * and initialises pcontext fields that may be null.
130: */
131: lpTable
132: gtab_printsetup(HWND hwnd, lpTable ptab, HANDLE heap, lpPrintContext pcontext)
133: {
134: lpTable pprttab;
135: PRINTDLG FAR * pd;
136: int ncols, i;
137: ColPropsList cplist;
138:
139: /* set fields for context that user left null */
140: if (pcontext->margin == NULL) {
141: pcontext->margin = (lpMargin) gmem_get(heap, sizeof(Margin));
142: if (pcontext->margin == NULL) {
143: return(NULL);
144: }
145: pcontext->margin->left = 10;
146: pcontext->margin->right = 10;
147: pcontext->margin->top = 15;
148: pcontext->margin->bottom = 15;
149: pcontext->margin->topinner = 15;
150: pcontext->margin->bottominner = 15;
151: }
152:
153: if (pcontext->pd == NULL) {
154: pd = (PRINTDLG FAR *) gmem_get(heap, sizeof(PRINTDLG));
155: if (pd == NULL) {
156: return(NULL);
157: }
158: pcontext->pd = pd;
159:
160: pd->lStructSize = sizeof(PRINTDLG);
161: pd->hwndOwner = hwnd;
162: pd->hDevMode = (HANDLE) NULL;
163: pd->hDevNames = (HANDLE) NULL;
164: pd->Flags = PD_RETURNDC|PD_RETURNDEFAULT;
165:
166: if (PrintDlg(pd) == FALSE) {
167: return(NULL);
168: }
169: }
170:
171: /* now create a Table struct by querying the owner */
172: pprttab = (lpTable) gmem_get(heap, sizeof(Table));
173:
174: if (pprttab == NULL) {
175: return(NULL);
176: }
177: pprttab->hdr = ptab->hdr;
178:
179: /* get the row/column count from owner window */
180: if (pcontext->id == 0) {
181: pprttab->hdr.id = ptab->hdr.id;
182: } else {
183: pprttab->hdr.id = pcontext->id;
184: }
185: pprttab->hdr.props.valid = 0;
186: pprttab->hdr.sendscroll = FALSE;
187: if (gtab_sendtq(hwnd, TQ_GETSIZE, (long) (LPSTR)&pprttab->hdr) == FALSE) {
188: return(NULL);
189: }
190:
191: /* alloc and init the col data structs */
192: ncols = pprttab->hdr.ncols;
193: pprttab->pcolhdr = (lpColProps) gmem_get(heap, sizeof(ColProps) * ncols);
194: if (pprttab->pcolhdr == NULL) {
195: gmem_free(heap, (LPSTR)pprttab, sizeof(Table));
196: return(NULL);
197: }
198:
199: /* init col properties to default */
200: for (i=0; i < ncols; i++) {
201: pprttab->pcolhdr[i].props.valid = 0;
202: pprttab->pcolhdr[i].nchars = 0;
203: }
204: /* get the column props from owner */
205: cplist.plist = pprttab->pcolhdr;
206: cplist.id = pprttab->hdr.id;
207: cplist.startcol = 0;
208: cplist.ncols = ncols;
209: gtab_sendtq(hwnd, TQ_GETCOLPROPS, (long) (LPSTR)&cplist);
210:
211:
212: pprttab->scrollscale = 1;
213: pprttab->pcellpos = (lpCellPos) gmem_get(heap,
214: sizeof(CellPos) * ptab->hdr.ncols);
215: if (pprttab->pcellpos == NULL) {
216: gmem_free(heap, (LPSTR) pprttab->pcolhdr, sizeof(ColProps) * ncols);
217: gmem_free(heap, (LPSTR)pprttab, sizeof(Table));
218: return(NULL);
219: }
220:
221:
222: pprttab->pdata = NULL;
223: pprttab->nlines = 0;
224:
225: if (!gtab_prtwidths(hwnd, pprttab, heap, pcontext)) {
226: gmem_free(heap, (LPSTR)pprttab->pcellpos,
227: sizeof(CellPos) * ptab->hdr.ncols);
228: gmem_free(heap, (LPSTR)pprttab, sizeof(Table));
229: return(NULL);
230: }
231: return(pprttab);
232: }
233:
234:
235: /***************************************************************************
236: * Function: gtab_prtwidths
237: *
238: * Purpose:
239: *
240: * Calc the height/width settings and alloc line data
241: */
242: BOOL
243: gtab_prtwidths(HWND hwnd, lpTable ptab, HANDLE heap, lpPrintContext pcontext)
244: {
245: TEXTMETRIC tm;
246: int cx, cxtotal, i, curx, cury;
247: lpProps hdrprops, cellprops;
248: lpCellPos xpos, ypos;
249: RECT rcinner, rcouter;
250:
251: hdrprops = &ptab->hdr.props;
252: GetTextMetrics(pcontext->pd->hDC, &tm);
253: ptab->avewidth = tm.tmAveCharWidth;
254: ptab->rowheight = tm.tmHeight + tm.tmExternalLeading;
255: if (hdrprops->valid & P_HEIGHT) {
256: ptab->rowheight = hdrprops->height;
257: }
258:
259: /* set sizes for headers */
260: gtab_setrects(pcontext, &rcinner, &rcouter);
261:
262: /* set width/pos for each col. */
263: cxtotal = 0;
264: curx = rcinner.left;
265: for (i = 0; i < ptab->hdr.ncols; i++) {
266: cellprops = &ptab->pcolhdr[i].props;
267: xpos = &ptab->pcellpos[i];
268:
269: if (cellprops->valid & P_WIDTH) {
270: cx = cellprops->width;
271: } else if (hdrprops->valid & P_WIDTH) {
272: cx = hdrprops->width;
273: } else {
274: cx = ptab->pcolhdr[i].nchars + 1;
275: cx *= ptab->avewidth;
276: }
277: /* add 2 for intercol spacing */
278: cx += 2;
279:
280: xpos->size = cx;
281: xpos->start = curx + 1;
282: xpos->clipstart = xpos->start;
283: xpos->clipend = xpos->start + xpos->size - 2;
284: xpos->clipend = min(xpos->clipend, rcinner.right);
285:
286: cxtotal += xpos->size;
287: curx += xpos->size;
288: }
289: ptab->rowwidth = cxtotal;
290:
291: if(pcontext->head != NULL) {
292: xpos = &pcontext->head->xpos;
293: ypos = &pcontext->head->ypos;
294:
295: xpos->start = rcouter.left + 1;
296: xpos->clipstart = rcouter.left + 1;
297: xpos->clipend = rcouter.right - 1;
298: xpos->size = rcouter.right - rcouter.left;
299:
300: ypos->start = rcouter.top;
301: ypos->clipstart = rcouter.top;
302: ypos->clipend = rcinner.top;
303: ypos->size = ptab->rowheight;
304: }
305:
306: if (pcontext->foot != NULL) {
307: xpos = &pcontext->foot->xpos;
308: ypos = &pcontext->foot->ypos;
309:
310: xpos->start = rcouter.left + 1;
311: xpos->clipstart = rcouter.left + 1;
312: xpos->clipend = rcouter.right - 1;
313: xpos->size = rcouter.right - rcouter.left;
314:
315: ypos->start = rcouter.bottom - ptab->rowheight;
316: ypos->clipstart = rcinner.bottom;
317: ypos->clipend = rcouter.bottom;
318: ypos->size = ptab->rowheight;
319: }
320:
321: /* set nr of lines per page */
322: ptab->nlines = (rcinner.bottom - rcinner.top) / ptab->rowheight;
323: if (!gtab_alloclinedata(hwnd, heap, ptab)) {
324: return(FALSE);
325: }
326: /* set line positions */
327: cury = rcinner.top;
328: for (i = 0; i < ptab->nlines; i++) {
329: ypos = &ptab->pdata[i].linepos;
330: ypos->start = cury;
331: ypos->clipstart = ypos->start;
332: ypos->clipend = ypos->start + ypos->size;
333: ypos->clipend = min(ypos->clipend, rcinner.bottom);
334: cury += ypos->size;
335: }
336: return(TRUE);
337: }
338:
339:
340: /* static information for this module */
341: BOOL bAbort;
342: FARPROC lpAbortProc;
343: DLGPROC lpAbortDlg;
344: HWND hAbortWnd;
345: int npage;
346: int pages;
347:
348: /***************************************************************************
349: * Function: gtab_printjob
350: *
351: * Purpose:
352: *
353: * Sets up print job and dialogs
354: */
355: void
356: gtab_printjob(HWND hwnd, lpTable ptab, lpPrintContext pcontext)
357: {
358: int moveables;
359: int endpage;
360: int startpage = 1;
361: HDC hpr;
362: int status;
363: HANDLE hcurs;
364: static char str[256];
365: DOCINFO di;
366:
367: hcurs = SetCursor(LoadCursor(NULL, IDC_WAIT));
368:
369: moveables = ptab->nlines - ptab->hdr.fixedrows;
370: pages = (int) (ptab->hdr.nrows - ptab->hdr.fixedrows + moveables - 1)
371: / moveables;
372: endpage = pages;
373:
374: if (pcontext->pd->Flags & PD_PAGENUMS) {
375: startpage = pcontext->pd->nFromPage;
376: endpage = pcontext->pd->nToPage;
377: }
378: hpr = pcontext->pd->hDC;
379:
380: lpAbortDlg = (DLGPROC) MakeProcInstance((WNDPROC) AbortDlg, hLibInst);
381: lpAbortProc = (FARPROC) MakeProcInstance((WNDPROC)AbortProc, hLibInst);
382:
383: SetAbortProc(hpr, (ABORTPROC) lpAbortProc);
384:
385: di.lpszDocName = "Table";
386: di.cbSize = lstrlen(di.lpszDocName);
387: di.lpszOutput = NULL;
388:
389: StartDoc(hpr, &di);
390:
391: bAbort = FALSE;
392:
393: /* add abort modeless dialog later!! */
394: hAbortWnd = CreateDialog(hLibInst, "GABRTDLG", hwnd, lpAbortDlg);
395: if (hAbortWnd != NULL) {
396: ShowWindow(hAbortWnd, SW_NORMAL);
397: EnableWindow(hwnd, FALSE);
398: }
399: SetCursor(hcurs);
400:
401:
402: for (npage = startpage; npage<=endpage; npage++) {
403: wsprintf(str, "Page %d of %d pages", npage, pages);
404: SetDlgItemText(hAbortWnd, IDC_LPAGENR, str);
405: status = gtab_printpage(hwnd, ptab, pcontext, npage);
406: if (status < 0) {
407: AbortDoc(hpr);
408: break;
409: }
410: }
411: if (status >= 0) {
412: EndDoc(hpr);
413: }
414:
415: if (hAbortWnd != NULL) {
416: EnableWindow(hwnd, TRUE);
417: DestroyWindow(hAbortWnd);
418: }
419: FreeProcInstance((WNDPROC) lpAbortDlg);
420: FreeProcInstance(lpAbortProc);
421:
422: DeleteDC(hpr);
423: }
424:
425: /***************************************************************************
426: * Function: AbortProc
427: *
428: * Purpose:
429: *
430: * Abort procedure for print job
431: */
432: int APIENTRY
433: AbortProc(HDC hpr, int code)
434: {
435:
436: MSG msg;
437:
438: if (!hAbortWnd) {
439: return(TRUE);
440: }
441: while (!bAbort && PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) {
442: if (!IsDialogMessage(hAbortWnd, &msg)) {
443: TranslateMessage(&msg);
444: DispatchMessage(&msg);
445: }
446: }
447: return(!bAbort);
448: }
449:
450: /***************************************************************************
451: * Function: AbortDlg
452: *
453: * Purpose:
454: *
455: * Dialog for abort procedure
456: */
457: int APIENTRY
458: AbortDlg(HWND hdlg, UINT msg, UINT wParam, LONG lParam)
459: {
460: switch(msg) {
461:
462: case WM_COMMAND:
463: bAbort = TRUE;
464: EndDialog(hdlg, TRUE);
465: return TRUE;
466:
467: case WM_INITDIALOG:
468: return TRUE;
469: }
470: return(FALSE);
471: }
472:
473: /***************************************************************************
474: * Function: gtab_printpage
475: *
476: * Purpose:
477: *
478: * Print a single page. page number is 1-based
479: */
480: BOOL
481: gtab_printpage(HWND hwnd, lpTable ptab, lpPrintContext pcontext, int page)
482: {
483: HDC hpr;
484: int moveables, i;
485: int x1, y1, x2, y2;
486:
487: hpr = pcontext->pd->hDC;
488: StartPage(hpr);
489:
490: moveables = ptab->nlines - ptab->hdr.fixedrows;
491: ptab->toprow = moveables * (page-1);
492: gtab_invallines(hwnd, ptab, ptab->hdr.fixedrows, moveables);
493:
494: for (i =0; i < ptab->nlines; i++) {
495: gtab_paint(hwnd, hpr, ptab, i);
496: }
497: if ((ptab->hdr.vseparator) && (ptab->hdr.fixedcols > 0)) {
498: x1 = ptab->pcellpos[ptab->hdr.fixedcols -1].clipend+1;
499: y1 = ptab->pdata[0].linepos.clipstart;
500: y2 = ptab->pdata[ptab->nlines-1].linepos.clipend;
501: MoveToEx(hpr, x1, y1, NULL);
502: LineTo(hpr, x1, y2);
503: }
504: if ((ptab->hdr.hseparator) && (ptab->hdr.fixedrows > 0)) {
505: y1 = ptab->pdata[ptab->hdr.fixedrows-1].linepos.clipend;
506: x1 = ptab->pcellpos[0].clipstart;
507: x2 = ptab->pcellpos[ptab->hdr.ncols-1].clipend;
508: MoveToEx(hpr, x1, y1, NULL);
509: LineTo(hpr, x2, y1);
510: }
511:
512: if (pcontext->head != NULL) {
513: gtab_printhead(hwnd, hpr, ptab, pcontext->head, page);
514: }
515: if (pcontext->foot != NULL) {
516: gtab_printhead(hwnd, hpr, ptab, pcontext->foot, page);
517: }
518:
519: return(EndPage(hpr));
520: }
521:
522:
523: /***************************************************************************
524: * Function: gtab_setrects
525: *
526: * Purpose:
527: *
528: * Calculate the outline positions in pixels for the headers
529: * (outer rect) and for the page itself (inner rect). Based on
530: * page size and PrintContext margin info (which is in millimetres).
531: */
532: void
533: gtab_setrects(lpPrintContext pcontext, LPRECT rcinner, LPRECT rcouter)
534: {
535: HDC hpr;
536: int hpixels, hmms;
537: int vpixels, vmms;
538: int h_pixpermm, v_pixpermm;
539:
540: hpr = pcontext->pd->hDC;
541: hpixels = GetDeviceCaps(hpr, HORZRES);
542: vpixels = GetDeviceCaps(hpr, VERTRES);
543: vmms = GetDeviceCaps(hpr, VERTSIZE);
544: hmms = GetDeviceCaps(hpr, HORZSIZE);
545:
546: h_pixpermm = hpixels / hmms;
547: v_pixpermm = vpixels / vmms;
548:
549: rcouter->top = (pcontext->margin->top * v_pixpermm);
550: rcouter->bottom = vpixels - (pcontext->margin->bottom * v_pixpermm);
551: rcouter->left = (pcontext->margin->left * h_pixpermm);
552: rcouter->right = hpixels - (pcontext->margin->right * h_pixpermm);
553:
554: rcinner->left = rcouter->left;
555: rcinner->right = rcouter->right;
556: rcinner->top = rcouter->top +
557: (pcontext->margin->topinner * v_pixpermm);
558: rcinner->bottom = rcouter->bottom -
559: (pcontext->margin->bottominner * v_pixpermm);
560: }
561:
562:
563: /***************************************************************************
564: * Function: gtab_printhead
565: *
566: * Purpose:
567: *
568: * Print header information
569: */
570: void
571: gtab_printhead(HWND hwnd, HDC hdc, lpTable ptab, lpTitle head, int page)
572: {
573: RECT rc, rcbox;
574: int i, cx, x, y, tab;
575: UINT align;
576: LPSTR chp, tabp;
577: DWORD fcol, bkcol;
578: char str[256];
579:
580: rc.top = head->ypos.clipstart;
581: rc.bottom = head->ypos.clipend;
582: rc.left = head->xpos.clipstart;
583: rc.right = head->xpos.clipend;
584:
585: /* update page number */
586: chp = str;
587: for (i = 0; i < lstrlen(head->ptext); i++) {
588: switch(head->ptext[i]) {
589:
590: case '#':
591: chp += wsprintf(chp, "%d", page);
592: break;
593:
594: case '$':
595: chp += wsprintf(chp, "%d", pages);
596: break;
597:
598: default:
599: *chp++ = head->ptext[i];
600: break;
601: }
602: }
603: *chp = '\0';
604: chp = str;
605:
606: if (head->props.valid & P_ALIGN) {
607: align = head->props.alignment;
608: } else {
609: align = P_LEFT;
610: }
611:
612: /* set colours if not default */
613: if (head->props.valid & P_FCOLOUR) {
614: fcol = SetTextColor(hdc, head->props.forecolour);
615: }
616: if (head->props.valid & P_BCOLOUR) {
617: bkcol = SetBkColor(hdc, head->props.backcolour);
618: }
619:
620: /* calc offset of text within cell for right-align or centering */
621: if (align == P_LEFT) {
622: cx = ptab->avewidth/2;
623: } else {
624: cx = LOWORD(GetTextExtent(hdc, chp, lstrlen(chp)));
625: if (align == P_CENTRE) {
626: cx = (head->xpos.size - cx) / 2;
627: } else {
628: cx = head->xpos.size - cx - (ptab->avewidth/2);
629: }
630: }
631: cx += head->xpos.start;
632:
633: /* expand tabs on output */
634: tab = ptab->avewidth * 8;
635: x = 0;
636: y = head->ypos.start;
637:
638: for ( ; (tabp = strchr(chp, '\t')) != NULL; ) {
639: /* perform output upto tab char */
640: ExtTextOut(hdc, x+cx, y, ETO_CLIPPED, &rc, chp, tabp-chp, NULL);
641:
642: /* advance past the tab */
643: x += LOWORD(GetTextExtent(hdc, chp, tabp - chp));
644: x = ( (x + tab) / tab) * tab;
645: chp = ++tabp;
646: }
647:
648: /*no more tabs - output rest of string */
649: ExtTextOut(hdc, x+cx, y, ETO_CLIPPED, &rc, chp, lstrlen(chp), NULL);
650:
651: /* reset colours to original if not default */
652: if (head->props.valid & P_FCOLOUR) {
653: SetTextColor(hdc, fcol);
654: }
655: if (head->props.valid & P_BCOLOUR) {
656: SetBkColor(hdc, bkcol);
657: }
658:
659: /* now box cell if marked */
660: if (head->props.valid & P_BOX) {
661: if (head->props.box != 0) {
662: rcbox.top = head->ypos.start;
663: rcbox.bottom = rcbox.top + head->ypos.size;
664: rcbox.left = head->xpos.start;
665: rcbox.right = rcbox.left + head->xpos.size;
666: gtab_boxcell(hwnd, hdc, &rcbox, &rc, head->props.box);
667: }
668: }
669: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.