diff options
author | Kevin Walzer <kw@codebykevin.com> | 2021-05-08 13:22:37 (GMT) |
---|---|---|
committer | Kevin Walzer <kw@codebykevin.com> | 2021-05-08 13:22:37 (GMT) |
commit | 826c870297d0f8e9007aea7947f8fa4e49628f8e (patch) | |
tree | 7fb282df580adfb6cdc7d3be077dc21a84f7870e /win/tkWinGDI.c | |
parent | 4456905b5ffd46ca9759b0f883883f53a636d034 (diff) | |
parent | 7653fd57944db2a7fd92a7dc515faaf4d83026bc (diff) | |
download | tk-826c870297d0f8e9007aea7947f8fa4e49628f8e.zip tk-826c870297d0f8e9007aea7947f8fa4e49628f8e.tar.gz tk-826c870297d0f8e9007aea7947f8fa4e49628f8e.tar.bz2 |
Merge printing and GDI files into one for tighter coupling of print device context
Diffstat (limited to 'win/tkWinGDI.c')
-rw-r--r-- | win/tkWinGDI.c | 372 |
1 files changed, 341 insertions, 31 deletions
diff --git a/win/tkWinGDI.c b/win/tkWinGDI.c index 55a363d..5e8c57b 100644 --- a/win/tkWinGDI.c +++ b/win/tkWinGDI.c @@ -18,17 +18,25 @@ #include <windows.h> #include <stdlib.h> #include <math.h> -#include <wtypes.h> /* Ensure to include WINAPI definition. */ +#include <wtypes.h> +#include <winspool.h> +#include <commdlg.h> +#include <wingdi.h> #include <tcl.h> #include "tkWinInt.h" + /* Main dispatcher for commands. */ static int TkWinGDI (ClientData clientData, Tcl_Interp *interp, int argc, const char **argv); + /* Main dispatcher for subcommands. */ static int TkWinGDISubcmd (ClientData clientData, Tcl_Interp *interp, int argc, const char **argv); +/* Initialize all these API's. */ +int Winprint_Init(Tcl_Interp * interp); +int Gdi_Init(Tcl_Interp *interp); /* Real functions. */ @@ -81,12 +89,26 @@ static HPALETTE GetSystemPalette(void); static void GetDisplaySize (LONG *width, LONG *height); static int GdiWordToWeight(const char *str); static int GdiParseFontWords(Tcl_Interp *interp, LOGFONT *lf, const char *str[], int numargs); +static int PrintSelectPrinter(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[]); +int PrintOpenPrinter(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[]); +int PrintClosePrinter(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[]); +static int PrintOpenDoc(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[]); +static int PrintCloseDoc(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[]); +static int PrintOpenPage(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[]); +static int PrintClosePage(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[]); static const char gdi_usage_message[] = "::tk::print::_gdi [arc|characters|copybits|line|map|oval|" "photo|polygon|rectangle|text|version]\n" "\thdc parameters can be generated by the printer extension"; static char msgbuf[1024]; -static HDC get_dc(Tcl_Interp *interp, const char *name); +static HDC get_dc(Tcl_Interp *interp); +static PRINTDLG pd; +static DOCINFO di; +int copies, paper_width, paper_height, dpi_x, dpi_y; +char *localPrinterName; +PDEVMODE returnedDevmode; +PDEVMODE localDevmode; +static HDC printDC; @@ -221,7 +243,7 @@ static int GdiArc( /* Verrrrrry simple for now.... */ if (argc >= 5) { - hDC = get_dc(interp, argv[0]); + hDC = get_dc(interp); /* Check hDC. */ if (hDC == (HDC)0 ) { @@ -448,7 +470,7 @@ static int GdiPhoto( return TCL_ERROR; } - dst = get_dc(interp, argv[0]); + dst = get_dc(interp); /* Check hDC. */ if (dst == (HDC) 0) { @@ -719,7 +741,7 @@ static int GdiLine( /* Verrrrrry simple for now.... */ if (argc >= 5) { - hDC = get_dc(interp, argv[0]); + hDC = get_dc(interp); /* Check hDC. */ if (hDC == (HDC)0 ) { @@ -1041,7 +1063,7 @@ static int GdiOval( /* Verrrrrry simple for now.... */ if (argc >= 5) { - hDC = get_dc(interp, argv[0]); + hDC = get_dc(interp); /* Check hDC. */ if (hDC == (HDC)0 ) { @@ -1174,7 +1196,7 @@ static int GdiPolygon( /* Verrrrrry simple for now.... */ if (argc >= 5) { - hDC = get_dc(interp, argv[0]); + hDC = get_dc(interp); /* Check hDC. */ if (hDC == (HDC)0 ) { @@ -1356,7 +1378,7 @@ static int GdiRectangle( /* Verrrrrry simple for now.... */ if (argc >= 5) { - hDC = get_dc(interp, argv[0]); + hDC = get_dc(interp); /* Check hDC. */ if (hDC == (HDC)0 ) { @@ -1487,7 +1509,7 @@ static int GdiCharWidths( return TCL_ERROR; } - hDC = get_dc(interp, argv[0]); + hDC = get_dc(interp); /* Check hDC. */ if (hDC == (HDC)0 ) { @@ -1637,7 +1659,7 @@ int GdiText( if ( argc >= 4 ) { /* Parse the command. */ - hDC = get_dc(interp, argv[0]); + hDC = get_dc(interp); /* Check hDC. */ if (hDC == (HDC)0 ) { @@ -2066,7 +2088,7 @@ static int GdiMap( /* Required parameter: HDC for printer. */ if ( argc >= 1 ) { - hdc = get_dc(interp, argv[0]); + hdc = get_dc(interp); /* Check hDC. */ if (hdc == (HDC)0 ) { @@ -2312,7 +2334,7 @@ static int GdiCopyBits ( return TCL_ERROR; } - dst = get_dc(interp, argv[0]); + dst = get_dc(interp); /* Check hDC. */ if (dst == (HDC)0 ) @@ -4147,7 +4169,7 @@ static HANDLE CopyToDIB ( HWND hWnd, enum PrintType type ) * CopyScreenToBitmap and passing it the rectangle to grab. */ Rect.top = Rect.left = 0; - GetDisplaySize(&Rect.right, &Rect.bottom); + GetDisplaySize(&Rect.right, &Rect.bottom); hBitmap = CopyScreenToBitmap(&Rect); @@ -4612,18 +4634,12 @@ static int PalEntriesOnDevice(HDC hDC) *---------------------------------------------------------------------- */ -static HDC get_dc(Tcl_Interp *interp, const char *name) +static HDC get_dc(Tcl_Interp *interp) { /* ANY type of DC should be ok here. */ - char *strend; - unsigned long tmp; - - /* Perhaps it is a numeric DC. */ - tmp = strtoul(name, &strend, 0); - if ( strend != 0 && strend > name ) - { - DWORD objtype = GetObjectType((HGDIOBJ)tmp); + unsigned long tmp; + DWORD objtype = GetObjectType(printDC); switch (objtype) { /* Any of the DC types are OK. */ @@ -4633,18 +4649,12 @@ static HDC get_dc(Tcl_Interp *interp, const char *name) case 0: /* Function failed */ default: tmp = 0; - Tcl_AppendResult(interp, "Error: Wrong type of handle for this operation: ", - "need a drawing context, got non-context address: ", name, "\n", 0); + Tcl_AppendResult(interp, "Error: Wrong type of handle for this operation\n", 0); + return 0; break; } + return (HDC)tmp; - } - else - { - Tcl_AppendResult(interp, "Error: Wrong type of handle for this operation: ", - "need a drawing context, got: ", name, "\n", 0); - return 0; - } } /* @@ -4669,6 +4679,32 @@ int Gdi_Init(Tcl_Interp *interp) } /* + * -------------------------------------------------------------------------- + * + * Winprint_Init-- + * + * Initializes printing module on Windows. + * + * Results: + * Module initialized. + * + * ------------------------------------------------------------------------- + */ + +int Winprint_Init(Tcl_Interp * interp) +{ + Tcl_CreateObjCommand(interp, "::tk::print::_selectprinter", PrintSelectPrinter, NULL, NULL); + Tcl_CreateObjCommand(interp, "::tk::print::_openprinter", PrintOpenPrinter, NULL, NULL); + Tcl_CreateObjCommand(interp, "::tk::print::_closeprinter", PrintClosePrinter, NULL, NULL); + Tcl_CreateObjCommand(interp, "::tk::print::_opendoc", PrintOpenDoc, NULL, NULL); + Tcl_CreateObjCommand(interp, "::tk::print::_closedoc", PrintCloseDoc, NULL, NULL); + Tcl_CreateObjCommand(interp, "::tk::print::_openpage", PrintOpenPage, NULL, NULL); + Tcl_CreateObjCommand(interp, "::tk::print::_closepage", PrintClosePage, NULL, NULL); + return TCL_OK; +} + + +/* * The following functions are adapted from tkTrig.c. */ @@ -4944,6 +4980,280 @@ TkGdiMakeBezierCurve( return outputPoints; } +/* Print API functions. */ + +/*---------------------------------------------------------------------- + * + * PrintSelectPrinter-- + * + * Main dialog for selecting printer and initializing data for print job. + * + * Results: + * Printer selected. + * + *---------------------------------------------------------------------- + */ + +static int PrintSelectPrinter(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[]) +{ + + (void) clientData; + (void) argc; + (void) objv; + + returnedDevmode = NULL; + localDevmode = NULL; + localPrinterName = NULL; + copies = 0; + paper_width = 0; + paper_height = 0; + dpi_x = 0; + dpi_y = 0; + + /* Set up print dialog and initalize property structure. */ + + ZeroMemory( &pd, sizeof(pd)); + pd.lStructSize = sizeof(pd); + pd.hwndOwner = GetDesktopWindow(); + pd.Flags = PD_RETURNDC | PD_HIDEPRINTTOFILE | PD_DISABLEPRINTTOFILE | PD_NOSELECTION; + + if (PrintDlg(&pd) == TRUE) { + printDC = pd.hDC; + if (printDC = NULL) { + Tcl_AppendResult(interp, "can't allocate printer DC", NULL); + return TCL_ERROR; + } + + /*Get document info.*/ + ZeroMemory( &di, sizeof(di)); + di.cbSize = sizeof(di); + di.lpszDocName = "Tk Print Output"; + + + /* Copy print attributes to local structure. */ + returnedDevmode = (PDEVMODE)GlobalLock(pd.hDevMode); + localDevmode = (LPDEVMODE)HeapAlloc(GetProcessHeap(), + HEAP_ZERO_MEMORY | HEAP_GENERATE_EXCEPTIONS, + returnedDevmode->dmSize); + + if (localDevmode !=NULL) + { + memcpy((LPVOID)localDevmode, + (LPVOID)returnedDevmode, + returnedDevmode->dmSize); + + /* Get values from user-set and built-in properties. */ + localPrinterName = (char*) localDevmode->dmDeviceName; + dpi_y = localDevmode->dmYResolution; + dpi_x = localDevmode->dmPrintQuality; + paper_height = (int) localDevmode->dmPaperLength; + paper_width = (int) localDevmode->dmPaperWidth; + copies = pd.nCopies; + } + else + { + localDevmode = NULL; + } + if (pd.hDevMode !=NULL) + { + GlobalFree(pd.hDevMode); + } + } + + + /* + * Store print properties and link variables + * so they can be accessed from script level. + */ + + char *varlink1 = Tcl_Alloc(100 * sizeof(char)); + char **varlink2 = (char **)Tcl_Alloc(sizeof(char *)); + *varlink2 = varlink1; + strcpy (varlink1, localPrinterName); + + Tcl_LinkVar(interp, "::tk::print::printer_name", (char*)varlink2, TCL_LINK_STRING | TCL_LINK_READ_ONLY); + Tcl_LinkVar(interp, "::tk::print::copies", (char *)&copies, TCL_LINK_INT | TCL_LINK_READ_ONLY); + Tcl_LinkVar(interp, "::tk::print::dpi_x", (char *)&dpi_x, TCL_LINK_INT | TCL_LINK_READ_ONLY); + Tcl_LinkVar(interp, "::tk::print::dpi_y", (char *)&dpi_y, TCL_LINK_INT | TCL_LINK_READ_ONLY); + Tcl_LinkVar(interp, "::tk::print::paper_width", (char *)&paper_width, TCL_LINK_INT | TCL_LINK_READ_ONLY); + Tcl_LinkVar(interp, "::tk::print::paper_height", (char *)&paper_height, TCL_LINK_INT | TCL_LINK_READ_ONLY); + + return TCL_OK; +} + +/* + * -------------------------------------------------------------------------- + * + * PrintOpenPrinter-- + * + * Open the given printer. + * + * Results: + * Opens the selected printer. + * + * ------------------------------------------------------------------------- + */ + +int PrintOpenPrinter(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[]) +{ + (void) clientData; + + if (argc < 2) { + Tcl_WrongNumArgs(interp, 1, objv, "printer"); + return TCL_ERROR; + } + + char *printer = Tcl_GetString(objv[2]); + if (printDC== NULL) { + return TCL_ERROR; + } + OpenPrinter(printer, &printDC, NULL); + return TCL_OK; +} + +/* + * -------------------------------------------------------------------------- + * + * PrintClosePrinter-- + * + * Closes the given printer. + * + * Results: + * Printer closed. + * + * ------------------------------------------------------------------------- + */ + +int PrintClosePrinter(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[]) +{ + (void) clientData; + (void) argc; + (void) objv; + + ClosePrinter(printDC); + return TCL_OK; +} + +/* + * -------------------------------------------------------------------------- + * + * PrintOpenDoc-- + * + * Opens the document for printing. + * + * Results: + * Opens the print document. + * + * ------------------------------------------------------------------------- + */ + +int PrintOpenDoc(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[]) +{ + + (void) clientData; + (void) argc; + (void) objv; + + int output = 0; + + if (printDC == NULL) { + return TCL_ERROR; + } + + /* + * Start printing. + */ + output = StartDoc(printDC, &di); + if (output <= 0) { + Tcl_AppendResult(interp, "unable to start document", NULL); + return TCL_ERROR; + } + + return TCL_OK; +} + +/* + * -------------------------------------------------------------------------- + * + * PrintCloseDoc-- + * + * Closes the document for printing. + * + * Results: + * Closes the print document. + * + * ------------------------------------------------------------------------- + */ + + +int PrintCloseDoc(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[]) +{ + + (void) clientData; + (void) argc; + (void) objv; + + if ( EndDoc(printDC) <= 0) { + return TCL_ERROR; + } + return TCL_OK; +} + +/* + * -------------------------------------------------------------------------- + * + * PrintOpenPage-- + * + * Opens a page for printing. + * + * Results: + * Opens the print page. + * + * ------------------------------------------------------------------------- + */ + +int PrintOpenPage(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[]) +{ + + (void) clientData; + (void) argc; + (void) objv; + + /*Start an individual page.*/ + if ( StartPage(printDC) <= 0) { + Tcl_AppendResult(interp, "unable to start page", NULL); + return TCL_ERROR; + } + + return TCL_OK; +} + +/* + * -------------------------------------------------------------------------- + * + * PrintClosePage-- + * + * Closes the printed page. + * + * Results: + * Closes the page. + * + * ------------------------------------------------------------------------- + */ + +int PrintClosePage(ClientData clientData, Tcl_Interp *interp, int argc, Tcl_Obj *const objv[]) +{ + + (void) clientData; + (void) argc; + (void) objv; + + if ( EndPage(printDC) <= 0) { + return TCL_ERROR; + } + return TCL_OK; +} + /* * Local Variables: |