summaryrefslogtreecommitdiffstats
path: root/win/tkWinGDI.c
diff options
context:
space:
mode:
authorKevin Walzer <kw@codebykevin.com>2021-05-08 13:22:37 (GMT)
committerKevin Walzer <kw@codebykevin.com>2021-05-08 13:22:37 (GMT)
commit826c870297d0f8e9007aea7947f8fa4e49628f8e (patch)
tree7fb282df580adfb6cdc7d3be077dc21a84f7870e /win/tkWinGDI.c
parent4456905b5ffd46ca9759b0f883883f53a636d034 (diff)
parent7653fd57944db2a7fd92a7dc515faaf4d83026bc (diff)
downloadtk-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.c372
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: