home *** CD-ROM | disk | FTP | other *** search
- /************ FILE C Sample Program Source Code File (.C) *******************
- *
- * PROGRAM NAME: GRAPHIC
- * -------------
- * Presentation Manager Non-Retained Graphics C Sample Program
- *
- * WHAT THIS PROGRAM DEMONSTRATES:
- * -------------------------------
- * Following are all the functions needed to print "GPI", "METAFILE"
- * in a separate thread.
- *
- * Copyright (C) 1991, 1993 IBM Corporation
- *
- * DISCLAIMER OF WARRANTIES. The following [enclosed] code is
- * sample code created by IBM Corporation. This sample code is not
- * part of any standard or IBM product and is provided to you solely
- * for the purpose of assisting you in the development of your
- * applications. The code is provided "AS IS", without
- * warranty of any kind. IBM shall not be liable for any damages
- * arising out of your use of the sample code, even if they have been
- * advised of the possibility of such damages. *
- ******************************************************************************/
-
- /* Include the required sections of the PM header file */
-
- #include <stdlib.h>
- #include <string.h>
-
- #define INCL_DOSPROCESS
- #define INCL_DOSSEMAPHORES
- #define INCL_WINWINDOWMGR
- #define INCL_GPICONTROL
- #define INCL_WINPOINTERS
- #define INCL_GPIMETAFILES
- #define INCL_GPICORRELATION
- #define INCL_WINMESSAGEMGR
- #define INCL_GPIREGIONS
- #define INCL_WINRECTANGLES
- #define INCL_GPITRANSFORMS
- #define INCL_GPIPRIMITIVES
- #define INCL_WINERRORS
- #define INCL_GPILCIDS
- #define INCL_WINDIALOGS
- #define INCL_DEV
- #define INCL_WINSTDDLGS
- #define INCL_DOSERRORS
- #define INCL_GPIERRORS
-
- #include <os2.h>
- #include <malloc.h>
- #include <memory.h>
- #include <sys\types.h>
- #include <sys\stat.h>
- #include "graphic.h"
-
- #define EXPORT_BUFFER_SIZE 1000
-
- /* static function definitions */
- static VOID PreparePrinting(PHPS hpsPrint,
- PHDC hdcPrinter,
- HAB habPrint,
- PSIZEL sizlPS,
- PRESOLUTION Resolution,
- PPRTTXT_DATA PrintData,
- PSIZEL DevCaps);
- static VOID MetaOutput(PDRAW_PARM PrtParm,
- PPRTTXT_DATA PrintData,
- HAB habPrint);
- static int _Optlink SortQueues(const void *Queue1, const void *Queue2);
- static PSZ GetQueueNamesString(PULONG);
- static CHAR pm_spooler_queue_dd[] = "PM_SPOOLER_QUEUE_DD";
- static CHAR Drive[]={0,0,0};
-
- /*********************************************************************
- *
- * Name: OpenFileDialog
- *
- * Purpose: open the standard file open dialog as file extention
- * and return the filename
- *
- * Usage: called when the user needs to supply a name for
- * the file to be opened
- *
- * Method: calls the standard file open dialog to get the
- * file name.
- *
- * Parameters: HWD hwnd Handle of the owner window.
- * PSZ szTitle Title of open dialog.
- * PSZ pszFileExt File extention. (for example : *.txt)
- * PSZ pszFullPath PSZ for returning the file name.
- *
- * Returns: TRUE if successful in getting a file name, FALSE
- * if not in pushing CANCEL
- * PSZ pszFullPath pointer to filename (full path)
- *
- **********************************************************************/
- BOOL OpenFileDialog(HWND hwndOwner,
- PSZ szTitle,
- PSZ szFileExt,
- PSZ szFullPath)
- {
- static PSZ ppszdefaultdrivelist[] = {NULL};
-
- FILEDLG fdg; /* file dialog structure */
-
- fdg.cbSize = sizeof(FILEDLG); /* Size of FILEDLG. */
- fdg.pszTitle = szTitle; /* String to display in title bar. */
- fdg.pszOKButton = (PSZ)"Open"; /* String to display in OK button. */
- fdg.ulUser = 0L; /* User defined field. */
- fdg.fl = FDS_HELPBUTTON | /* FDS flags. */
- FDS_CENTER |
- FDS_OPEN_DIALOG;
- fdg.pfnDlgProc = (PFNWP)TemplateOpenFilterProc;/* Entry point to custom*/
- /* dialog proc. */
- fdg.lReturn = 0L; /* Result code from dialog dismissal. */
- fdg.lSRC = 0L; /* System return code. */
- fdg.hMod = 0; /* Custom file dialog template. */
- fdg.usDlgId = 0; /* Custom file dialog ID. */
- fdg.x = 0; /* X coordinate of the dialog. */
- fdg.y = 0; /* Y coordinate of the dialog. */
-
- /* set selected fully qualified path */
- strcpy( fdg.szFullFile, szFileExt);
-
- fdg.pszIType = NULL; /* Pointer to string containing */
- /* Initial EA type filter. */
- fdg.papszITypeList = NULL; /* Pointer to table of pointers */
- /* that point to null terminated */
- if (!Drive[0]) /* Type strings. */
- fdg.pszIDrive = NULL; /* Pointer to string containing */
- else /* initial drive. */
- fdg.pszIDrive = Drive;
-
- fdg.papszIDriveList = (PAPSZ)ppszdefaultdrivelist;
- /* Pointer to table of pointers */
- /* that point to null terminated */
- /* Drive strings. */
- fdg.sEAType = 0; /* Selected file's EA Type. */
- fdg.papszFQFilename = NULL; /* Pointer to table of pointers */
- /* point to null terminated */
- /* FQFname strings. */
- fdg.ulFQFCount = 0L; /* Numbers of file selected. */
-
- /* get the file */
-
- if (!WinFileDlg(HWND_DESKTOP, hwndOwner, (PFILEDLG)&fdg))
- return FALSE;
-
- if (fdg.lReturn == DID_CANCEL)
- return FALSE;
-
- /* copy file name into file name buffer */
-
- strcpy(szFullPath, fdg.szFullFile);
- strcpy(szFileExt, fdg.szFullFile);
- strncpy(Drive,fdg.szFullFile,2); /* Always Contains Drive letter */
-
- return TRUE;
- } /* End of OpenFileDialog */
-
- /**************************************************************************
- * Function: DrawThread
- *
- * DrawThread is the asynchronous drawing thread. It performs all
- * drawing, whether to the screen or to the printer.
- * It obtains an anchor block handle and creates a message queue.
- * It then posts a private message to the main thread's client area
- * if successful. NewThread monitors its own message queue, and
- * processes the commands it receives.
- *
- * Parameters: PMAIN_PARM main parameter structure
- *
- * Result: none
- *
- ***************************************************************************/
- VOID DrawThread(PMAIN_PARM Parm)
- {
- static CHAR DrawThreadErrorTitle[] = "Draw Thread Error:";
- static CHAR DrawThreadError1[] = "WinInitialize failed!";
- static CHAR DrawThreadError2[] = "Cannot Create Message Queue.";
- QMSG qmsgAsync; /* Message structure for WinGetMsg */
- QMSG qmsgPeek; /* Message structure for WinPeekMsg */
- BOOL fFlushQueue; /* Flush-queue indicator */
- BOOL fQueueFlush;
- RECTL rclClient; /* Bounding rect for picture xform */
- BOOL Loop = TRUE;
- static PSZ dcdatablk[9] = {0,
- "MEMORY", /* display driver */
- 0, 0, 0, 0, 0, 0, 0 };
-
- /*
- * Obtain an anchor block handle. If this fails, the thread and
- * the application are terminated.
- */
-
- if ((Parm->DrawParm.hABDraw = WinInitialize((USHORT)0)) == (HAB)NULLHANDLE)
- {
- WinPostMsg(Parm->hWndFrame,
- WM_USER_END_ON_ERROR,
- MPFROMP(DrawThreadErrorTitle),
- MPFROMP(DrawThreadError1));
- DosExit(EXIT_THREAD, 0);
- }
-
- /*
- * Create a message queue. If this fails, the thread and the
- * application are terminated.
- */
-
- if ((Parm->hMQDraw = WinCreateMsgQueue(Parm->DrawParm.hABDraw, 0)) ==
- (HMQ)NULLHANDLE)
- {
- WinTerminate(Parm->DrawParm.hABDraw);
- WinPostMsg(Parm->hWndFrame,
- WM_USER_END_ON_ERROR,
- MPFROMP(DrawThreadErrorTitle),
- MPFROMP(DrawThreadError2));
- DosExit(EXIT_THREAD, 0);
- }
-
- /*
- * The SetTransform function is invoked to set up the transformation
- * for the default picture. The main thread's priority is adjusted
- * to be higher than that of the asynchronous thread. (GPI CIRCLES)
- */
-
- WinPostMsg(Parm->hWndFrame,
- WM_COMMAND,
- MPFROMP(IDM_F_GPI),
- MPFROMP(NULL));
- DosSetPriority(PRTYS_THREAD, PRTYC_NOCHANGE, 1L, 0L);
- while (Loop)
- {
-
- /*
- * The semaphore hsemStoppable is obtained so that the flag
- * fWaiting can be set to TRUE. This indicates that the thread is
- * waiting for a message, and prevents the main thread from
- * issuing GpiSetStopDraw.
- * To be sure that it will not be suspended, the asynchronous
- * thread sets the stop-draw condition off. It then reads its
- * message queue.
- */
-
- WinRequestMutexSem(Parm->hmtxsemStoppable, (ULONG)-1);
- Parm->fWaiting = TRUE;
- DosReleaseMutexSem(Parm->hmtxsemStoppable);
-
- if (Parm->hpsClient != (HPS)NULLHANDLE)
- GpiSetStopDraw(Parm->hpsClient, (LONG)FALSE);
-
- WinGetMsg(Parm->DrawParm.hABDraw, &qmsgAsync, (HWND)NULLHANDLE, 0L, 0L);
-
- /*
- * When a message has been read from the queue, the flag fWaiting
- * is set the FALSE. This allows the main thread to issue the
- * GpiSetStopDraw call if necessary.
- */
-
- WinRequestMutexSem(Parm->hmtxsemStoppable, (ULONG)-1);
- Parm->fWaiting = FALSE;
- DosReleaseMutexSem(Parm->hmtxsemStoppable);
-
- /*
- * Before doing any drawing, the thread examines its message queue
- * to see if it contains any other commands that would force
- * redrawing. If there is a flush command in the queue, all
- * commands, up to and including the flush command, are read from
- * the queue. A SET_TRANSFORM message is treated like a flush
- * command, because it also means that a new picture is required.
- */
-
- fFlushQueue = WinPeekMsg(Parm->DrawParm.hABDraw,
- &qmsgPeek,
- 0L,
- FLUSH_COMMAND,
- FLUSH_COMMAND,
- PM_NOREMOVE);
-
- fQueueFlush = WinPeekMsg(Parm->DrawParm.hABDraw,
- &qmsgPeek,
- 0L,
- SET_TRANSFORM,
- SET_TRANSFORM,
- PM_NOREMOVE);
-
- if (fFlushQueue|| fQueueFlush)
- do
- {
- WinGetMsg(Parm->DrawParm.hABDraw, &qmsgAsync, NULLHANDLE, 0L, 0L);
- } while (qmsgAsync.msg != FLUSH_COMMAND &&
- qmsgAsync.msg != SET_TRANSFORM &&
- qmsgAsync.msg != STOP_DRAWING
- ); /* enddo */
-
- if (WinPeekMsg(Parm->DrawParm.hABDraw,
- &qmsgPeek,
- NULLHANDLE,
- STOP_THREAD,
- DUMMY_COMMAND,
- PM_NOREMOVE))
- Parm->DrawParm.fDrawing = FALSE;
- else
- Parm->DrawParm.fDrawing = TRUE;
-
- /* Process the commands. */
-
- switch (qmsgAsync.msg)
- {
- case SET_TRANSFORM:
- /*
- * Invoke the SetTransform function to define a default viewing
- * transformation for the picture.
- */
- if (*Parm->Message != '\0')
- break;
- SetTransform(Parm, qmsgAsync.mp1);
- break;
-
- case DRAW_ORDERS:
- /*
- * Invoke the DoDraw function. DoDraw uses the region definition
- * passed to it to repaint the invalidated area of the screen.
- * The region definition is then destroyed.
- */
- if (Parm->CheckedItem == 3)
- {
- break;
- }
- else
- {
- if (*Parm->Message != '\0')
- break;
- DoDraw(Parm->hpsClient, &Parm->DrawParm, (HRGN)qmsgAsync.mp1,
- Parm->InfoWnd.hWnd);
- if (qmsgAsync.mp1 != MPVOID)
- GpiDestroyRegion(Parm->hpsClient, (HRGN)qmsgAsync.mp1);
-
- break;
- }
- case DISPLAY_MESSAGE:
- DisplayMessage(Parm->hWndClient,
- Parm->Message);
- break;
-
- case SIZING:
- /* Recalculate the picture transformation. */
-
- if (*Parm->Message != '\0')
- break;
- WinQueryWindowRect(Parm->hWndClient, &rclClient);
- Transform(&Parm->DrawParm, Parm->hpsClient, &rclClient);
- break;
-
- case ACTIVATE_DRAW_THREAD:
- WinPostMsg(Parm->hWndFrame, ACTIVATE_DRAW_THREAD, MPVOID, MPVOID);
- break;
-
- case STOP_DRAWING:
- Parm->DrawThreadActivated = FALSE;
- DosPostEventSem(Parm->hevsemStop);
- break;
-
- case STOP_THREAD:
- /* StopThread is invoked to terminate the thread. */
- Loop = FALSE;
- break;
-
- case FLUSH_COMMAND:
- /*
- * Other commands have already been discarded. Set the fAllValid
- * flag to TRUE.
- */
- Parm->DrawParm.fAllValid = TRUE;
- break;
- }
- }
-
- DosSetPriority(PRTYS_THREAD, PRTYC_IDLETIME, 0L, 0L);
-
- WinDestroyMsgQueue(Parm->hMQDraw); /* Destroy this thread's message queue */
-
- WinTerminate(Parm->DrawParm.hABDraw);
-
- DosPostEventSem(Parm->hevsemTerminate);
-
- DosExit(EXIT_THREAD, 0);
- } /* End of DrawThread */
-
- /**************************************************************************
- * Function: SendCommand
- *
- * The SendCommand function posts the required command and its
- * parameters to the asynchronous drawing thread's message queue.
- *
- * Parameters: PMAIN_PARM main parameter structure
- * usCommand command to send
- * ULONG long value passed to draw thread as parameter1
- *
- * Result: BOOL TRUE is ok
- *
- ***************************************************************************/
- BOOL SendCommand(PMAIN_PARM Parm, ULONG ulCommand, ULONG ulInfo)
- {
- APIRET Ret;
-
- if (Parm->hMQDraw == (HMQ)NULLHANDLE)
- return FALSE;
- /*
- * Communication between the main thread and the asynchronous thread
- * is controlled by the two flags fWaiting and fStoppable. Access to
- * the two flags is regulated by the semaphore hsemStoppable.
- * The main thread requests access to the semaphore, and waits until
- * it is available. If this command is one that causes drawing, the
- * main thread checks whether the asynchronous thread is waiting for
- * a message. If it is not waiting, the main thread issues
- * GpiSetStopDraw to suspend drawing. It then frees the semaphore,
- * and posts the message to the asynchronous thread's message queue.
- */
- do
- {
- Ret = WinRequestMutexSem(Parm->hmtxsemStoppable, (ULONG)-1);
- } while (Ret == (APIRET)ERROR_INTERRUPT);
-
- if (ulCommand <= DUMMY_COMMAND)
- if (!Parm->fWaiting)
- GpiSetStopDraw(Parm->hpsClient, (ULONG)Parm->fStoppable);
-
- DosReleaseMutexSem(Parm->hmtxsemStoppable);
-
- return WinPostQueueMsg(Parm->hMQDraw,
- ulCommand,
- MPFROMLONG(ulInfo),
- MPVOID);
- } /* End of SendCommand */
-
- /**************************************************************************
- * Function: SetTransform
- *
- * The SetTransform function calculates the original default viewing
- * transformation for the picture. This function can be interrupted
- * only by another request to set the default viewing transformation,
- * or by a request to terminate the thread. SetTransform invokes the
- * DoDraw function to draw the picture, and then calculates the
- * bounding rectangle of the picture.
- * It then invokes the Transform function to set the appropriate
- * transformation.
- *
- * Parameters: PMAIN_PARM main parameter structure
- * MPARAM message parameter passed from SendCommand
- *
- * Result: none
- *
- ***************************************************************************/
- VOID SetTransform(PMAIN_PARM Parm, MPARAM mp1)
- {
- LONG lRc;
- RECTL rclDest;
- RECTL rclClient;
- POINTL ptlWork;
- RECTL rclWork;
-
- GpiErase(Parm->hpsClient);
- WinInvalidateRect(Parm->InfoWnd.hWnd, (PRECTL)NULL, TRUE);
-
- DisplayMessage(Parm->hWndClient,
- GetString(Parm->DrawParm.hABDraw,
- ((HMF)mp1 == (HMF)NULLHANDLE) ?
- TEXT_DRAWTHR_SIZEGPI : TEXT_DRAWTHR_SIZEMETA,
- STATIC_STRING));
-
- Parm->fBusy = TRUE;
- if (WinQueryPointerPos(HWND_DESKTOP, &ptlWork))
- if (WinMapWindowPoints(HWND_DESKTOP, Parm->hWndClient, &ptlWork, 1))
- if (WinQueryWindowRect(Parm->hWndClient, &rclWork))
- if (WinPtInRect(Parm->DrawParm.hABDraw, &rclWork, &ptlWork))
- WinSetPointer(HWND_DESKTOP, Parm->hptrGlass);
-
- if (Parm->DrawParm.hmfPicture != (HMF)NULLHANDLE)
- GpiDeleteMetaFile(Parm->DrawParm.hmfPicture);
-
- /* The current metafile is deleted before the next one is drawn. */
- Parm->DrawParm.hmfPicture = (HMF)mp1;
-
- WinRequestMutexSem(Parm->hmtxsemStoppable, (ULONG)-1);
- Parm->fStoppable = FALSE;
- DosReleaseMutexSem(Parm->hmtxsemStoppable);
-
- /*
- * The boundary data is cleared so that the transformation and the
- * presentation space are not reset after the GpiPlayMetaFile call.
- */
- Parm->DrawParm.rclBounds.xRight = 0xFFFF;
- Parm->DrawParm.rclBounds.xLeft = 0xFFFF;
- Parm->DrawParm.rclBounds.yTop = 0xFFFF;
- Parm->DrawParm.rclBounds.yBottom = 0xFFFF;
- GpiResetBoundaryData(Parm->hpsClient);
- /*
- * The presentation space is disassociated from the device context.
- * Boundary-data accumulation is switched on, and the DoDraw
- * function is invoked to draw the picture into the disassociated
- * device context. The picture is drawn, but not displayed. The
- * boundary data is retrieved, and the presentation space is
- * reassociated with the device context. Boundary-data accumulation
- * is switched off.
- */
- GpiAssociate(Parm->hpsClient, (HDC)NULLHANDLE);
- GpiSetDrawControl(Parm->hpsClient, DCTL_BOUNDARY, DCTL_ON);
-
- GpiSetStopDraw(Parm->hpsClient, (ULONG)Parm->fStoppable);
- Parm->DrawParm.fDrawing = TRUE;
- lRc = DoDraw(Parm->hpsClient, &Parm->DrawParm, (HRGN)NULLHANDLE,
- Parm->InfoWnd.hWnd);
-
- GpiQueryBoundaryData(Parm->hpsClient, &Parm->DrawParm.rclBounds);
- GpiAssociate(Parm->hpsClient, Parm->hdcClient);
- GpiSetDrawControl(Parm->hpsClient, DCTL_BOUNDARY, DCTL_OFF);
- /*
- * The presentation space is reset so that subsequent
- * GpiPlayMetaFile calls will succeed.
- */
- GpiResetPS(Parm->hpsClient, GRES_ALL);
- /*
- * If the DoDraw function was successful, the Transform function is
- * invoked to set the transformation. WinInvalidateRect invalidates
- * the client area and causes a WM_PAINT message to be issued.
- * The title bar is also updated.
- */
- if (lRc == DRAW_OK)
- {
- WinQueryWindowRect(Parm->hWndClient, &rclClient);
- Transform(&Parm->DrawParm, Parm->hpsClient, &rclClient);
- WinRequestMutexSem(Parm->hmtxsemStoppable, (ULONG)-1);
- Parm->fNotReady = FALSE;
- /*
- * The application can now process paint and erase-background
- * requests.
- */
- DosReleaseMutexSem(Parm->hmtxsemStoppable);
- WinQueryWindowRect(Parm->hWndClient, &rclDest);
- WinInvalidateRect(Parm->hWndClient, &rclDest, FALSE);
- }
- else
- {
- strcpy(Parm->Message,
- GetString(Parm->DrawParm.hABDraw,
- ERRMSG_DRAWTHR_MSG2,
- STATIC_STRING));
- strcat(Parm->Message, Parm->MetafilePath);
- DisplayMessage(Parm->hWndClient, Parm->Message);
- Parm->fNotReady = FALSE;
- }
- /*
- * If the DoDraw function failed, the main thread is prompted to
- * display a warning message and issue another SET_TRANSFORM
- * message for the default picture.
- */
- Parm->fBusy = FALSE;
- if (WinQueryPointerPos(HWND_DESKTOP, &ptlWork))
- if (WinMapWindowPoints(HWND_DESKTOP, Parm->hWndClient, &ptlWork, 1))
- if (WinQueryWindowRect(Parm->hWndClient, &rclWork))
- if (WinPtInRect(Parm->DrawParm.hABDraw, &rclWork, &ptlWork))
- WinSetPointer(HWND_DESKTOP, Parm->hptrArrow);
-
- /* Allow GpiSetStopDraw to interrupt subsequent drawing. */
- WinRequestMutexSem(Parm->hmtxsemStoppable, (ULONG)-1);
- Parm->fStoppable = TRUE;
- DosReleaseMutexSem(Parm->hmtxsemStoppable);
- return;
- } /* End of SetTransform */
-
- /**************************************************************************
- * Function: WndProcPaint
- *
- * The WndProcPaint function is invoked from the window procedure
- * ClientWndProc to process the WM_PAINT message. WndProcPaint
- * in turn invokes the asynchronous thread to perform the window
- * painting. If the asynchronous thread has both a drawing and a
- * transformation to process, a region is created that is equal to the
- * update region. This is passed to the asynchronous thread and the
- * region is validated. Otherwise, no painting occurs.
- * If the asynchronous thread does not have time to paint the updated
- * regions, it accumulates them.
- *
- * Parameters: PMAIN_PARM main parameter structure
- *
- * Result: MRESULT message result
- *
- ***************************************************************************/
- MRESULT WndProcPaint(PMAIN_PARM Parm)
- {
- HRGN hrgnUpdt;
- LONG sRgnType;
- APIRET Ret;
- ULONG MsgTyp;
-
- do
- {
- Ret = WinRequestMutexSem(Parm->hmtxsemStoppable, (ULONG)-1);
- } while (Ret == (APIRET)ERROR_INTERRUPT);
-
- hrgnUpdt = GpiCreateRegion(Parm->hpsPaint, 0L, (PRECTL)NULL);
- sRgnType = WinQueryUpdateRegion(Parm->hWndClient, hrgnUpdt);
- if (!Parm->fNotReady)
- {
- if (*Parm->Message != '\0')
- MsgTyp = DISPLAY_MESSAGE;
- else
- MsgTyp = DRAW_ORDERS;
-
- DosReleaseMutexSem(Parm->hmtxsemStoppable);
- if ((sRgnType == RGN_RECT) ||
- (sRgnType == RGN_COMPLEX))
- {
- if (!SendCommand(Parm, MsgTyp, 0L))
- GpiDestroyRegion(Parm->hpsPaint, hrgnUpdt);
- WinValidateRegion(Parm->hWndClient, hrgnUpdt, FALSE);
- }
- else
- {
- SendCommand(Parm, MsgTyp, 0L);
- WinValidateRegion(Parm->hWndClient, hrgnUpdt, FALSE);
- GpiDestroyRegion(Parm->hpsPaint, hrgnUpdt);
- } /* endif */
- }
- else
- {
- DosReleaseMutexSem(Parm->hmtxsemStoppable);
- WinValidateRegion(Parm->hWndClient, hrgnUpdt, FALSE);
- GpiDestroyRegion(Parm->hpsPaint, hrgnUpdt);
- } /* endif */
- return(FALSE);
- } /* End of WndProcPaint */
-
- /**************************************************************************
- * Function: Transform
- *
- * The Transform function recalculates the default viewing
- * transformation when the picture is scrolled or sized, and when the
- * 'Best Fit' option is changed.
- * If the window handle is NULLHANDLE, the default viewing transformation
- * is applied to ensure that the picture is contained within the page
- * and that no graphics clipping occurs for printing.
- *
- * Parameters: PDRAW_PARM draw parameter structure
- * HPS presentation space handle for drawing
- * PRECTL rectangle
- *
- * Result: none
- *
- ***************************************************************************/
- VOID Transform(PDRAW_PARM Parm, HPS hpsXForm, PRECTL prclXform)
- {
- LONG lxPictRight, lxPictLeft;
- LONG lyPictTop, lyPictBottom; /* picture boundary information */
- LONG clxPict, clyPict; /* picture extents */
- POINTL ptlPictCenter; /* center of picture */
- LONG clxBounds, clyBounds; /* bounds area extent */
- LONG alScale[2]; /* scaling factors */
- LONG sxWork, syWork; /* work areas */
- LONG lxWork, lyWork; /* work areas */
- static MATRIXLF matlfViewTransform = {65536,0,0,0,65536,0,0,0,1};
-
- /* Calculate the center of the bounding rectangle of the picture. */
- lxPictRight = Parm->rclBounds.xRight + 5;
- lxPictLeft = Parm->rclBounds.xLeft - 5;
- lyPictTop = Parm->rclBounds.yTop + 5;
- lyPictBottom = Parm->rclBounds.yBottom - 5;
-
- ptlPictCenter.x = (lxPictRight - lxPictLeft)/2 + lxPictLeft;
- ptlPictCenter.y = (lyPictTop - lyPictBottom)/2 + lyPictBottom;
-
-
- /* Get the picture extents. */
- clxPict = lxPictRight - lxPictLeft;
- clyPict = lyPictTop - lyPictBottom;
-
- /* Get the current bounding rectangle extent. */
- clxBounds = prclXform->xRight - prclXform->xLeft;
- clyBounds = prclXform->yTop - prclXform->yBottom;
-
- /* Calculate the x/y ratio of the current bounding area. */
- sxWork = (LONG)(clyBounds/clxBounds);
- lxWork = clyBounds%clxBounds;
- alScale[0] = MAKEULONG((USHORT)((lxWork * 0x10000)/clxBounds), sxWork);
-
- /* Calculate the x/y ratio of the picture. */
- syWork = clyPict/clxPict;
- lyWork = clyPict%clxPict;
- alScale[1] = MAKEULONG((USHORT)((lyWork * 0x10000)/clxPict), syWork);
- /*
- * Compare the two ratios to determine the dimension along which
- * scaling is to be provided, so that the picture fits into the
- * area and its aspect ratio is preserved. The same scaling is
- * then applied along both the x and y axes.
- */
- if (alScale[0] > alScale[1])
- {
- sxWork = clxBounds/clxPict;
- lxWork = clxBounds%clxPict;
- alScale[0] = MAKEULONG((USHORT)((lxWork * 0x10000)/clxPict), sxWork);
- alScale[1] = alScale[0];
- }
- else
- {
- syWork = clyBounds/clyPict;
- lyWork = clyBounds%clyPict;
- alScale[1] = MAKEULONG((USHORT)((lyWork * 0x10000)/clyPict), syWork);
- alScale[0] = alScale[1];
- }
-
- GpiScale(hpsXForm,
- &matlfViewTransform,
- TRANSFORM_REPLACE,
- (PFIXED)alScale,
- &ptlPictCenter);
- /*
- * Translate the center of the picture to the center of the
- * bounding area, based on the page origin.
- */
- ptlPictCenter.x = (prclXform->xRight - prclXform->xLeft)/2 - ptlPictCenter.x;
- ptlPictCenter.y = (prclXform->yTop - prclXform->yBottom)/2 - ptlPictCenter.y;
-
- GpiTranslate(hpsXForm,
- &matlfViewTransform,
- TRANSFORM_ADD,
- &ptlPictCenter);
-
- /* Now set the default viewing transform. */
- GpiSetDefaultViewMatrix(hpsXForm,
- 9L,
- &matlfViewTransform,
- TRANSFORM_REPLACE);
- /*
- * If the picture has been transformed for the screen, we need to
- * reset the scroll bar thumb size, so convert the picture height
- * from world to page coordinates and together with the rect area
- * height send the visible/total sizes to the scroll bar.
- */
- } /* End of Transform */
-
- /*************************************************************************
- * Function: DoDraw
- *
- * The DoDraw function draws the metafile contents. The supplied
- * update rectangle is used to define a clipping region, so that the
- * amount of drawing required is restricted.
- *
- * Parameters: HPS presentation space handle for drawing
- * PDRAW_PARM draw parameter structure
- * HRGN region for drawing
- * HWND window handle of information window
- *
- * Result: LONG return code
- *
- ***************************************************************************/
- LONG DoDraw(HPS hpsDraw, PDRAW_PARM Parm, HRGN rgn, HWND InfoWnd)
- {
- LONG lRc;
- LONG lOptionCount;
- LONG alOptionArray[8];
- LONG lSegCount;
- LONG lDescLen;
- CHAR achDescBuff[251];
- LONG lSaveMode;
- HRGN hrgnOld;
- MATRIXLF matlfSaveTransform;
- FIXED fxSize;
- static AREABUNDLE PatternAttr =
- {CLR_BACKGROUND, 0L, 0, 0, 0, 0, 0L};
- static POINTL ptlCurr = {0, 0};
-
- if (rgn != (HRGN)NULLHANDLE)
- {
- /*
- * A valid region has been passed to DoDraw. Depending on the
- * setting of the flag fAllValid, the region is either copied or
- * is combined with the current region using a logical OR
- * operation.
- */
- if (Parm->fAllValid)
- {
- GpiCombineRegion(hpsDraw,
- Parm->hrgnInvalid,
- rgn,
- Parm->hrgnInvalid,
- CRGN_COPY);
- Parm->fAllValid = FALSE;
- }
- else
- {
- GpiCombineRegion(hpsDraw,
- Parm->hrgnInvalid,
- Parm->hrgnInvalid,
- rgn,
- CRGN_OR);
- } /* endif */
- } /* endif */
-
- /* Stop here if the flag fDrawing is set to FALSE. */
- if (!Parm->fDrawing)
- return(FALSE);
- /*
- * If an invalid region exists, define a clipping region and clear
- * the area within the region. If there is no invalid region, the
- * whole client area is cleared.
- */
- if (rgn != (HRGN)NULLHANDLE)
- {
- lSaveMode = GpiQueryAttrMode(hpsDraw);
- GpiSetAttrMode(hpsDraw, AM_PRESERVE);
- GpiSetAttrs(hpsDraw,
- PRIM_AREA,
- ABB_COLOR,
- 0L,
- (PBUNDLE)&PatternAttr);
- GpiPaintRegion(hpsDraw, Parm->hrgnInvalid);
- GpiSetAttrMode(hpsDraw, lSaveMode);
- GpiPop(hpsDraw, 1L);
- GpiSetClipRegion(hpsDraw, Parm->hrgnInvalid, &hrgnOld);
- }
- else
- {
- GpiErase(hpsDraw);
- if (InfoWnd != (HWND)NULLHANDLE)
- WinInvalidateRect(InfoWnd, (PRECTL)NULL, TRUE);
- } /* endif */
- /*
- * If a metafile has been loaded, it is played into the presentation
- * space. If GpiPlayMetaFile is successful, the setting of the
- * stop-draw flag is checked. If the flag is set, it is assumed that
- * GpiPlayMetaFile did not complete successfully.
- * If no metafile has been loaded, a simple default picture is drawn.
- */
- if (Parm->hmfPicture != (HMF)NULLHANDLE)
- {
- lDescLen = 250;
- lOptionCount = 8L;
- alOptionArray[PMF_SEGBASE] = 0L;
- alOptionArray[PMF_LOADTYPE] = LT_DEFAULT;
- alOptionArray[PMF_RESOLVE] = RS_DEFAULT;
- alOptionArray[PMF_LCIDS] = LC_LOADDISC;
- alOptionArray[PMF_RESET] = RES_DEFAULT;
- alOptionArray[PMF_SUPPRESS] = SUP_DEFAULT;
- alOptionArray[PMF_COLORTABLES] = CTAB_REPLACE;
- alOptionArray[PMF_COLORREALIZABLE] = CREA_DEFAULT;
- lRc = GpiPlayMetaFile(hpsDraw,
- Parm->hmfPicture,
- lOptionCount,
- (PLONG)alOptionArray,
- &lSegCount,
- lDescLen,
- (PSZ)&achDescBuff[0]
- );
- if (lRc == GPI_OK)
- if (LOUSHORT(WinGetLastError(Parm->hABDraw)) ==
- PMERR_STOP_DRAW_OCCURRED)
- lRc = DRAW_STOPPED;
- /*
- * Reset the presentation space, including the default viewing
- * transformation, and then reapply the required transformation.
- * This is to ensure that the metafile can be replayed without
- * causing errors due to stored segments or new character sets,
- * for example. The presentation space is not reset if called
- * from the SetTransform function, as that function needs the
- * accumulated boundary information.
- */
- if (Parm->rclBounds.xRight != 0xFFFF)
- {
- GpiQueryDefaultViewMatrix(hpsDraw,
- 9L,
- &matlfSaveTransform);
- GpiResetPS(hpsDraw, GRES_ALL);
- GpiSetDefaultViewMatrix(hpsDraw,
- 9L,
- &matlfSaveTransform,
- TRANSFORM_REPLACE);
- }
- }
- else
- {
- GpiSetColor(hpsDraw, CLR_BLACK);
- fxSize = 0x100000;
- if (Circles(hpsDraw, &ptlCurr, fxSize))
- {
- lRc = DRAW_OK;
- }
- else
- {
- lRc = DRAW_STOPPED;
- }
- } /* endif */
-
- /* Clear any clipping region defined earlier. */
- if (rgn != (HRGN)NULLHANDLE)
- GpiSetClipRegion(hpsDraw, (HRGN)NULLHANDLE, &hrgnOld);
- /*
- * If the drawing failed, the flag fAllValid is not set. This
- * ensures that, the next time through, the region will be combined
- * with the new invalid region.
- */
- if (lRc == DRAW_OK)
- if (rgn != (HRGN)NULLHANDLE)
- Parm->fAllValid = TRUE;
- return(lRc);
- } /* End of DoDraw */
-
- /*************************************************************************
- * Function: Circles
- *
- * The Circles function draws a circle and then calls itself to
- * draw four further circles within the first one. It will
- * repeat this until the circles reach a certain size or if StopDraw
- * has been set for the presentation space.
- *
- * Parameters: HPS presentation space handle for drawing
- * PPOINTL point structure
- * FIXED size
- *
- * Result: BOOL return code, TRUE if ok
- *
- ***************************************************************************/
- BOOL Circles(HPS hpsDraw, PPOINTL pptlCur, FIXED fxSize)
- {
- LONG i;
- POINTL ptlWork;
- FIXED fxWork;
- static LONG xOff[4] = {0, 1, 0, -1};
- static LONG yOff[4] = {1, 0, -1, 0};
- static LONG ColorTab[] =
- {
- CLR_BLACK,
- CLR_RED,
- CLR_GREEN,
- CLR_BLUE
- };
-
- /* Don't continue if StopDraw is set */
- if (GpiQueryStopDraw(hpsDraw) == SDW_ON)
- return(FALSE);
- /* Don't continue if the circles are getting too small */
- if (fxSize < 0x10000)
- return(TRUE);
- /* Draw a circle of the required size at the required position. */
- GpiSetCurrentPosition(hpsDraw, pptlCur);
- GpiFullArc(hpsDraw, DRO_OUTLINE, fxSize);
- /*
- * Now draw a further 4 circles, half the current size, within the
- * one just drawn.
- */
- fxWork = fxSize >> 1;
- for (i = 0; i < 4; i++)
- {
- ptlWork.x = pptlCur->x + xOff[i]*(FIXEDINT(fxSize)>>1);
- ptlWork.y = pptlCur->y + yOff[i]*(FIXEDINT(fxSize)>>1);
- GpiSetColor(hpsDraw, ColorTab[i]);
- if (!Circles(hpsDraw, &ptlWork, fxWork))
- return(FALSE);
- }
- return(TRUE);
- } /* End of Circles */
-
- /*************************************************************************
- * Function: DisplayMessage
- *
- * Display a message in the client area.
- *
- * Parameters: HWND window handle
- * PSZ message to display
- *
- * Result: none
- *
- ***************************************************************************/
- VOID DisplayMessage(HWND hwndDraw, PSZ Message)
- {
- RECTL rDraw;
- PFONTMETRICS FontMetrics;
- POINTL MessagePos;
- HPS hpsDraw;
-
- WinQueryWindowRect(hwndDraw, &rDraw); /* query window size */
-
- hpsDraw = WinGetPS(hwndDraw);
-
- WinFillRect(hpsDraw, &rDraw, CLR_BACKGROUND); /* clear window */
-
- FontMetrics = (PFONTMETRICS)malloc(sizeof(FONTMETRICS)); /* query fontsize */
-
- GpiQueryFontMetrics(hpsDraw, (LONG)sizeof(FONTMETRICS), FontMetrics);
-
- MessagePos.x = 4L; /* set message position*/
- MessagePos.y = rDraw.yTop - FontMetrics->lMaxAscender;
-
- GpiCharStringAt(hpsDraw, &MessagePos, /* display message*/
- (LONG)strlen(Message), Message);
-
- WinReleasePS(hpsDraw);
-
- free((PVOID)FontMetrics);
- } /* End of DisplayMessage */
-
- /**************************************************************************
- * Function: PrintGpiMeta
- *
- * Create a structure with the printer specific data and send a message to
- * the print thread to print GPI or METAFILE.
- *
- * Parameters: PMAIN_PARM main parameter structure
- * ULONG identifier if GPI or METAFILE
- *
- * Result: none
- *
- ***************************************************************************/
- VOID PrintGpiMeta(PMAIN_PARM Parm, ULONG Message)
- {
- PPRTTXT_DATA PrintData;
- PDRAW_PARM PrtParm;
- /* definitions for print */
-
- /* Allocate Space for PrintData */
- PrintData = malloc(sizeof(PRTTXT_DATA));
-
- /* Allocate Space for PrtParm which is used in Draw-Functions */
- PrtParm = (PDRAW_PARM)malloc(sizeof(DRAW_PARM));
-
- /* now copy all additional information to the print structure */
- strcpy(PrintData->QueueName, Parm->QueueName);
- strcpy(PrintData->DriverName, Parm->DriverName);
-
- /* Allocate space for DriverData */
- PrintData->DriverData = malloc(Parm->DriverDataLength);
-
- memcpy(PrintData->DriverData, Parm->DriverData, Parm->DriverDataLength);
- memcpy((PSZ)PrtParm, (PSZ)&Parm->DrawParm, sizeof(DRAW_PARM));
- PrtParm->fDrawing = TRUE;
- PrintData->hWndFrame = Parm->hWndFrame;
-
- strcpy(PrintData->Jobname, ((Message == DRAW_GPI) ? "GPI" : "METAFILE"));
-
- /* now send the print thread a message to print GPI or METAFILE */
- WinPostQueueMsg(Parm->hMQPrint, Message,
- MPFROMP(PrintData), MPFROMP(PrtParm));
- } /* End of PrintGpiMeta */
-
- /*************************************************************************
- * Function: PrintThread
- *
- * PrintThread is the asynchronous printing thread. It performs all
- * printing, text and graphic.
- * It obtains an anchor block handle and creates a message queue.
- *
- * Parameters: PMAIN_PARM main parameter structure
- *
- * Result: none
- *
- ***************************************************************************/
- VOID PrintThread(PMAIN_PARM Parm)
- {
- HAB habPrint;
- static CHAR PrintThreadErrorTitle[] = "Print Thread Error:";
- static CHAR PrintThreadError1[] = "WinInitialize failed!";
- static CHAR PrintThreadError2[] = "Cannot Create Message Queue.";
- BOOL Loop = TRUE;
- QMSG qmsgAsync; /* Message structure for WinGetMsg */
- /*
- * Obtain an anchor block handle. If this fails, the thread and
- * the application are terminated.
- */
- if ((habPrint = WinInitialize(0L)) == (HAB)NULLHANDLE)
- {
- WinPostMsg(Parm->hWndFrame,
- WM_USER_END_ON_ERROR,
- MPFROMP(PrintThreadErrorTitle),
- MPFROMP(PrintThreadError1));
- DosExit(EXIT_THREAD, 0);
- }
- /*
- *Create a message queue. If this fails, the thread and the
- * application are terminated.
- */
- if ((Parm->hMQPrint = WinCreateMsgQueue(habPrint, 0L)) == (HMQ)NULLHANDLE)
- {
- WinTerminate(habPrint);
- WinPostMsg(Parm->hWndFrame,
- WM_USER_END_ON_ERROR,
- MPFROMP(PrintThreadErrorTitle),
- MPFROMP(PrintThreadError2));
- DosExit(EXIT_THREAD, 0);
- }
-
- DosSetPriority(PRTYS_THREAD, PRTYC_NOCHANGE, 1L, 0L);
-
- while (Loop)
- {
- WinGetMsg(habPrint, &qmsgAsync, (HWND)NULLHANDLE, 0L, 0L);
- switch (qmsgAsync.msg)
- {
- case STOP_THREAD: /* end thread */
- Loop = FALSE;
- break;
- case DRAW_GPI: /* print GPI/METAFILE */
- case DRAW_META:
- MetaOutput((PDRAW_PARM)PVOIDFROMMP(qmsgAsync.mp2),
- (PPRTTXT_DATA)PVOIDFROMMP(qmsgAsync.mp1),
- habPrint);
- break;
- }
- }
-
- DosSetPriority(PRTYS_THREAD, PRTYC_IDLETIME, 0L, 0L);
-
- WinDestroyMsgQueue(Parm->hMQPrint); /* Destroy this thread's message queue */
-
- WinTerminate(habPrint);
-
- DosPostEventSem(Parm->hevsemPrintEnds);
-
- DosExit(EXIT_THREAD, 0);
- } /* End of PrintThread */
-
- /**************************************************************************
- * Function: PreparePrinting
- *
- * Create device context and presentation space for printing
- *
- * Parameters: PHPS presentations space handle for printing(return)
- * PHDC device context handle for printing (return)
- * HAB anchor block handle of the print process
- * PSIZEL size of the presentation space (return)
- * PRESOLUTION resolution of the device (return)
- * PPRTTXT_DATA print data structure
- * PSIZEL device capabilities
- *
- * Result: none
- *
- ***************************************************************************/
- static VOID PreparePrinting(PHPS hpsPrint,
- PHDC hdcPrinter,
- HAB habPrint,
- PSIZEL sizlPS,
- PRESOLUTION Resolution,
- PPRTTXT_DATA PrintData,
- PSIZEL DevCaps)
- {
- DEVOPENSTRUC dopPrinter;
- ULONG i1;
- static CHAR Comment[] = "Graphic";
- LONG alDevInfo[DEVINFOSIZE];
-
- /* initialize DEVOPENSTRUC */
- memset((PVOID)&dopPrinter, '\0', sizeof(DEVOPENSTRUC));
- dopPrinter.pszLogAddress = PrintData->QueueName;
- i1 = strcspn(PrintData->DriverName, ".");
- PrintData->DriverName[i1] = '\0';
- dopPrinter.pszDriverName = PrintData->DriverName;
- dopPrinter.pdriv = (PDRIVDATA)PrintData->DriverData;
- dopPrinter.pszDataType = NULL;
-
- dopPrinter.pszComment = Comment;
- /* Open device context for printer */
- *hdcPrinter = DevOpenDC(habPrint,
- OD_QUEUED,
- (PSZ)"*",
- 5L,
- (PDEVOPENDATA)&dopPrinter,
- (HDC)NULLHANDLE);
- /* Query Height and Width of the printer */
-
- DevQueryCaps(*hdcPrinter,
- 0L,
- (LONG)DEVINFOSIZE,
- alDevInfo);
-
- sizlPS->cx = (alDevInfo[CAPS_WIDTH] * 10000) /
- alDevInfo[CAPS_HORIZONTAL_RESOLUTION];
-
- sizlPS->cy = (alDevInfo[CAPS_HEIGHT] * 10000) /
- alDevInfo[CAPS_VERTICAL_RESOLUTION];
-
- /* return device capabilities if pointer not NULL */
- if (DevCaps != (PSIZEL)NULL)
- {
- DevCaps->cx = alDevInfo[CAPS_WIDTH];
- DevCaps->cy = alDevInfo[CAPS_HEIGHT];
- }
-
- Resolution->x = (alDevInfo[CAPS_HORIZONTAL_FONT_RES] * 10000) /
- alDevInfo[CAPS_HORIZONTAL_RESOLUTION];
- Resolution->y = (alDevInfo[CAPS_VERTICAL_FONT_RES] * 10000) /
- alDevInfo[CAPS_VERTICAL_RESOLUTION];
-
- /* create presentation space */
- *hpsPrint = GpiCreatePS(habPrint,
- *hdcPrinter,
- sizlPS,
- PU_LOMETRIC | GPIA_ASSOC | GPIT_NORMAL);
- } /* End of PreparePrinting */
-
- /**************************************************************************
- * Function: MetaOutput
- *
- * Create spoolfile for GPI or METAFILE.
- *
- * Parameters: PDRAW_PARM draw parameter structure
- * PPRTTXT_DATA print parameter structure
- * HAB anchor block handle of the print process
- *
- * Result: none
- *
- ***************************************************************************/
- static VOID MetaOutput(PDRAW_PARM PrtParm,
- PPRTTXT_DATA PrintData,
- HAB habPrint)
- {
- HDC hdcPrinter;
- RESOLUTION Resolution;
- SIZEL sizlPS;
- HPS hpsPrint;
- ULONG JobNr;
- ULONG Dummy;
- RECTL rclPrinter;
-
- PrtParm->hABDraw = habPrint;
-
- /* create device context and presentations space for printing */
- PreparePrinting(&hpsPrint, &hdcPrinter, habPrint,
- &sizlPS, &Resolution, PrintData, (PSIZEL)NULL);
-
- /* disable menuitem "Print" */
- WinPostMsg(PrintData->hWndFrame, SET_PRINT_STATUS, MPFROMSHORT(1),
- MPFROMLONG(hpsPrint));
-
- /* Start Document */
- DevEscape(hdcPrinter,
- DEVESC_STARTDOC,
- (LONG)strlen(PrintData->Jobname),
- (PSZ)PrintData->Jobname,
- 0L,
- (PSZ)NULL);
-
- rclPrinter.xLeft = rclPrinter.yBottom = 0;
- rclPrinter.xRight = sizlPS.cx;
- rclPrinter.yTop = sizlPS.cy;
-
- /* draw GPI/METAFILE to the print presentation space */
- Transform(PrtParm, hpsPrint, &rclPrinter);
-
- if (DoDraw(hpsPrint, PrtParm, (HRGN)NULLHANDLE, (HWND)NULLHANDLE) != DRAW_OK)
- DevEscape(hdcPrinter,
- DEVESC_ABORTDOC,
- 0L,
- (PSZ)NULL,
- (PLONG)NULL,
- (PSZ)NULL);
- else
- {
- DevEscape(hdcPrinter, DEVESC_NEWFRAME,
- 0L, (PSZ)NULL, (PLONG)NULL, (PSZ)NULL);
- DevEscape(hdcPrinter,
- DEVESC_ENDDOC,
- 0L,
- (PSZ)NULL,
- (PLONG)&Dummy,
- (PSZ)&JobNr);
- }
-
- GpiAssociate(hpsPrint, (HDC)NULLHANDLE);
- GpiDestroyPS(hpsPrint);
- DevCloseDC(hdcPrinter);
-
- /* Release Data fields */
- free((PVOID)PrintData->DriverData);
-
- WinPostMsg(PrintData->hWndFrame, SET_PRINT_STATUS, MPVOID, MPVOID);
-
- free((PVOID)PrintData);
- } /* End of MetaOutput */
-
- /*************************************************************************
- * Function: QueryPrinterQueue
- *
- * query all printer queues, display them in a listbox an do a selection.
- *
- * Parameters: HAB anchor block handle of main process
- * HWND window handle of frame window
- * PVOID pointer to driver data structure
- * PULONG length of driver data
- * PSZ (pre)selected queue name
- * PSZ (pre)selected printer driver name
- *
- * Result: BOOL TRUE if printer changed, otherwise FALSE
- *
- ***************************************************************************/
- BOOL QueryPrinterQueue(HAB hAB,
- HWND hWnd,
- PVOID *DriverData,
- PULONG DriverDataLength,
- PSZ QueueName,
- PSZ DriverName)
- {
- PSZ pszQueueNames;
- PSZ pszQueueName;
- CHAR DefaultQueue[10];
- static CHAR pm_spooler_queue_descr[] = "PM_SPOOLER_QUEUE_DESCR";
- PRINTER_SEL_PARM PrtSelParm;
- ULONG i1;
- BOOL rc;
- LONG SelectedItem;
-
- /* initialize printer selection structure */
- PrtSelParm.ulLen = sizeof(PRINTER_SEL_PARM);
- PrtSelParm.ulType = 0L; /* reserved, must be zero */
- /*
- * First query all printer queues with a default driver name defined on it
- * If it fails, bring up a Message Box
- */
- if ((pszQueueNames = GetQueueNamesString(&PrtSelParm.QueuesCount)) == NULL)
- {
- WinMessageBox(HWND_DESKTOP,
- hWnd,
- (PSZ)"There are no Printer Queues defined, use PrintManager to define at least one Queue and Printer.",
- (PSZ)NULL,
- 0L,
- MB_OK | MB_MOVEABLE | MB_CUAWARNING | MB_APPLMODAL);
- return(FALSE);
- }
-
- /* if no Queue is connected to a Printer Driver, bring up a message */
- if (PrtSelParm.QueuesCount == 0)
- {
- WinMessageBox(HWND_DESKTOP,
- hWnd,
- (PSZ)"There are no Printer Queues connected to a Printer Driver, use PrintManager to connect a Printer to the Queue.",
- (PSZ)NULL,
- 0L,
- MB_OK | MB_MOVEABLE | MB_CUAWARNING | MB_APPLMODAL);
- free(pszQueueNames);
- return(FALSE);
- }
-
- /* Allocate Printer Selection Table */
- PrtSelParm.QueueSelTable = malloc(PrtSelParm.QueuesCount * sizeof(QUEUE_SEL));
- /*
- * Fill Printer Selection Table with Queue-Names and connected Printer
- * Driver Names
- */
- for (pszQueueName = pszQueueNames, i1 = 0;
- *pszQueueName;
- pszQueueName = &pszQueueName[strlen(pszQueueName) + 1], i1++)
- {
- PrfQueryProfileString(HINI_PROFILE,
- (PSZ)pm_spooler_queue_dd,
- (PSZ)pszQueueName,
- (PSZ)NULL,
- (PVOID)PrtSelParm.QueueSelTable[i1].DriverName,
- (ULONG)DRIVERNAME_LENGTH);
-
- strcpy(PrtSelParm.QueueSelTable[i1].QueueName, pszQueueName);
- /* eliminate ; */
- PrtSelParm.QueueSelTable[i1].DriverName[strlen(
- PrtSelParm.QueueSelTable[i1].DriverName) - 1] = '\0';
-
- /* Query Queue-Description */
- PrfQueryProfileString(HINI_PROFILE,
- (PSZ)pm_spooler_queue_descr,
- (PSZ)pszQueueName,
- (PSZ)NULL,
- (PVOID)PrtSelParm.QueueSelTable[i1].QueueDescription,
- (ULONG)DESCRIPTION_LENGTH);
- /* eliminate ; */
- PrtSelParm.QueueSelTable[i1].QueueDescription[strlen(
- PrtSelParm.QueueSelTable[i1].QueueDescription) - 1] = '\0';
- PrtSelParm.QueueSelTable[i1].DriverData = NULL;
- PrtSelParm.QueueSelTable[i1].DriverDataLength = 0;
- }
-
- free(pszQueueNames); /* free queue names */
-
- /* Sort Queue-Descriptions */
- qsort((void *)PrtSelParm.QueueSelTable,
- (size_t)PrtSelParm.QueuesCount,
- (size_t)sizeof(QUEUE_SEL),
- SortQueues);
-
- /* Define preselected queue */
- PrtSelParm.SelectedItem = -1;
-
- strcpy(DefaultQueue, QueueName);
- /*
- * if Queue Name not given or not found in table, query Default Queue
- * if queue name defined, test if the queue is valid
- */
- if (QueryDefaultQueue(DefaultQueue, (PSZ)NULL))
- {
- /* If default Queue defined and connected to Driver, search table */
- for (i1 = 0; i1 < PrtSelParm.QueuesCount; i1++)
- {
- /* if found in table, set Selected Item to entry */
- if (!strcmp(DefaultQueue, PrtSelParm.QueueSelTable[i1].QueueName))
- {
- PrtSelParm.SelectedItem = SelectedItem = i1;
- PrtSelParm.QueueSelTable[i1].DriverData = *DriverData;
- PrtSelParm.QueueSelTable[i1].DriverDataLength = *DriverDataLength;
- break;
- }
- }
- }
-
- /* if no queue defined or queue not valid, free driver data if allocated */
- if ((SelectedItem = PrtSelParm.SelectedItem) == -1)
- if (*DriverData != NULL)
- {
- free(*DriverData);
- *DriverDataLength = 0;
- *DriverData = NULL;
- }
-
- PrtSelParm.hAB = hAB;
-
- /* if an other printer is selected, copy the data to the function parameters */
- if (PrtSelParm.SelectedItem != SelectedItem)
- {
- rc = TRUE;
- strcpy(QueueName,
- PrtSelParm.QueueSelTable[PrtSelParm.SelectedItem].QueueName);
- strcpy(DriverName,
- PrtSelParm.QueueSelTable[PrtSelParm.SelectedItem].DriverName);
- *DriverData = PrtSelParm.QueueSelTable[PrtSelParm.SelectedItem].DriverData;
- *DriverDataLength = PrtSelParm.QueueSelTable[PrtSelParm.SelectedItem].DriverDataLength;
- }
- else
- rc = FALSE;
-
- /* free fields in queue selection table */
- for (i1 = 0; i1 < PrtSelParm.QueuesCount; i1++)
- if ((i1 != (ULONG)PrtSelParm.SelectedItem) &&
- (PrtSelParm.QueueSelTable[i1].DriverData != NULL))
- {
- free(PrtSelParm.QueueSelTable[i1].DriverData);
- }
-
- free(PrtSelParm.QueueSelTable);
-
- return(rc);
- } /* End of QueryPrinterQueue */
-
- /**************************************************************************
- * Function: SortQueues
- *
- * Compare routine for sorting the queue names table.
- *
- * Parameters: PQUEUE_SEL pointer to queue selection structure 1
- * PQUEUE_SEL pointer to queue selection structure 2
- *
- * Result: int result of comparison
- *
- ***************************************************************************/
- static int _Optlink SortQueues(const void *Queue1, const void *Queue2)
- {
- return(strcmp(((PQUEUE_SEL)Queue1)->QueueDescription,
- ((PQUEUE_SEL)Queue2)->QueueDescription));
- } /* End of SortQueues */
-
- /**************************************************************************
- * Function: QueryDefaultQueue
- *
- * if queue name passed, test if queue is valid, otherwise query default
- * printer queue.
- *
- * Parameters: PSZ queue name or nullstring
- * PSZ queue driver name or nullstring
- *
- * Result: BOOL TRUE if driver is connected to queue
- *
- ***************************************************************************/
- BOOL QueryDefaultQueue(PSZ QueueName, PSZ QueueDriver)
- {
- PSZ pszQueueNames;
- PSZ pszQueueName;
- CHAR QueueNameTemp[DRIVERNAME_LENGTH];
- BOOL rc = FALSE;
- static CHAR pm_spooler[] = "PM_SPOOLER";
-
- /* if no queue name passed, query default printer queue */
- if (!*QueueName)
- {
- if (!PrfQueryProfileString(HINI_PROFILE,
- (PSZ)pm_spooler,
- (PSZ)"QUEUE",
- NULL,
- (PSZ)QueueNameTemp,
- (LONG)sizeof(QueueNameTemp)))
- {
- *QueueName = '\0'; /* if no default printer queue found, */
- return(FALSE); /* return FALSE */
- }
-
- /* cut ; */
- QueueNameTemp[strlen(QueueNameTemp) - 1] = '\0';
-
- /* return Queue Name */
- strcpy(QueueName, QueueNameTemp);
- }
-
- /* Get String with all Queue Names to which a driver is connected */
- if ((pszQueueNames = GetQueueNamesString((PULONG)NULL)) != NULL)
- {
- /* Compare all Queue Names with default Queue Name */
- for (pszQueueName = pszQueueNames;
- *pszQueueName;
- pszQueueName = &pszQueueName[strlen(pszQueueName) + 1])
- {
- if (!strcmp(pszQueueName, QueueName))
- {
- /* if Queue found in string, set rc = TRUE */
- rc = TRUE;
- break;
- }
- }
- /* Free Queue Names string */
- free(pszQueueNames);
- }
-
- /* if queue driver defined and Queue found, query queue driver name */
- if ((QueueDriver != (PSZ)NULL) && rc)
- {
- PrfQueryProfileString(HINI_PROFILE,
- (PSZ)pm_spooler_queue_dd,
- (PSZ)QueueName,
- NULL,
- (PSZ)QueueNameTemp,
- DRIVERNAME_LENGTH);
- QueueNameTemp[strlen(QueueNameTemp) - 1] = '\0';
- strcpy(QueueDriver, QueueNameTemp);
- }
-
- return(rc);
- } /* End of QueryDefaultQueue */
-
- /**************************************************************************
- * Function: GetQueueNamesString
- *
- * Get a string with all Queue Names with a connected Driver Name.
- *
- * Parameters: PULONG pointer to ULONG for returning the queue count
- *
- * Result: PSZ string with all queuenames
- *
- ***************************************************************************/
- static PSZ GetQueueNamesString(PULONG QCount)
- {
- ULONG QueueNamesLength;
- PSZ pszQueueNames;
- PSZ pszQueueNamesWithDriver;
- PSZ pszQueueName;
- PSZ pszQueueStringPtr;
- PSZ pszQueueDriver;
- ULONG QueuesCt;
-
- /* Query size of Queues-String, if not defined return NULL */
- if (!PrfQueryProfileSize(HINI_PROFILE,
- (PSZ)pm_spooler_queue_dd,
- (PSZ)NULL,
- (PULONG)&QueueNamesLength))
- return((PSZ)NULL);
-
- /* Allocate Space for Queue Names, if it fails return NULL */
- if ((pszQueueNames = malloc(QueueNamesLength)) == NULL)
- return((PSZ)NULL);
-
- /* Allocate Space for Queue Names with driver, if it fails return NULL */
- if ((pszQueueNamesWithDriver = malloc(QueueNamesLength)) == NULL)
- {
- free(pszQueueNames);
- return((PSZ)NULL);
- }
-
- /* Get Queue Names */
- PrfQueryProfileString(HINI_PROFILE,
- (PSZ)pm_spooler_queue_dd,
- (PSZ)NULL,
- (PSZ)NULL,
- (PVOID)pszQueueNames,
- QueueNamesLength);
- /*
- * Query Count of Queues to which a Printer Driver is connected and
- * copy all Queue Names to pszQueueNamesWithDriver
- * Allocate space for Queue Driver Name, if it fails return NULL
- */
- if ((pszQueueDriver = malloc(DRIVERNAME_LENGTH)) == NULL)
- {
- free(pszQueueNames);
- free(pszQueueNamesWithDriver);
- return((PSZ)NULL);
- }
-
- pszQueueStringPtr = pszQueueNamesWithDriver;
-
- for (pszQueueName = pszQueueNames, QueuesCt = 0;
- *pszQueueName;
- pszQueueName = &pszQueueName[strlen(pszQueueName) + 1])
- {
- /* Query Queue Driver */
- PrfQueryProfileString(HINI_PROFILE,
- (PSZ)pm_spooler_queue_dd,
- (PSZ)pszQueueName,
- (PSZ)NULL,
- (PVOID)pszQueueDriver,
- DRIVERNAME_LENGTH);
- /*
- * if Queue Driver isn't a null-string, increment Queues Count
- * and copy queue name to string
- */
- if ((*pszQueueDriver != ';') && (*pszQueueDriver != '\0'))
- {
- strcpy(pszQueueStringPtr, pszQueueName);
- pszQueueStringPtr = &pszQueueStringPtr[strlen(pszQueueStringPtr) + 1];
- QueuesCt++;
- }
- }
-
- /* add a x'00' to the end of the string */
- *pszQueueStringPtr = '\0';
-
- /* free temporary fields */
- free(pszQueueDriver);
- free(pszQueueNames);
-
- /* Return Queues Count, if Pointer != NULL */
- if (QCount != (PULONG)NULL)
- *QCount = QueuesCt;
-
- /* return string with Queue Names */
- return(pszQueueNamesWithDriver);
- } /* End of GetQueueNamesString */
-
- /*************************************************************************
- * Function: QueryJobProperties
- *
- * Query job properties (print properties) of the printer driver.
- *
- * Parameters: HAB anchor block handle of the process
- * PVOID pointer to driver data
- * PULONG driver data length
- * PSZ queue driver name
- * PSZ printer queue name
- * PSZ printer driver name
- * BOOL flag, if FALSE don't display the dialog
- *
- * Result: BOOL TRUE if ok
- *
- ***************************************************************************/
- BOOL QueryJobProperties(HAB hAB,
- PVOID *DriverData,
- PULONG DriverDataLength,
- PSZ QueueDriverName,
- PSZ QueueName,
- PSZ PrtName,
- BOOL Flag)
- {
- CHAR DriverName[10];
- CHAR DeviceName[64];
- LONG rc;
- LONG i1;
- ULONG Length;
- PSZ PrinterNames = NULL;
- PSZ PrinterName;
- PSZ PrinterInfo;
- PSZ QueueInfo;
- PSZ DriverInfo;
- PSZ Queue;
- PSZ Driver;
- BOOL found;
- ULONG flOptions;
- static CHAR pm_spooler_printer[] = "PM_SPOOLER_PRINTER";
- static CHAR separator1[] = ";";
- static CHAR separator2[] = ",";
-
- /* if flag=TRUE display the dialog, otherwise only query default properties */
- if (Flag)
- flOptions = DPDM_POSTJOBPROP;
- else
- flOptions = DPDM_QUERYJOBPROP;
-
- /* separate driver name at the dot (e.g PLOTTERS.IBM6180) */
- if ((i1 = (LONG)strcspn(QueueDriverName, ".")) != 0L)
- {
- strncpy(DriverName, QueueDriverName, i1);
- DriverName[i1] = '\0';
- strcpy(DeviceName, &QueueDriverName[i1 + 1]);
- }
- else
- {
- strcpy(DriverName, QueueDriverName);
- *DeviceName = '\0';
- }
- /*
- * Query device name because some printer drivers need this information
- * in the DevPostDeviceModes call
- */
-
- /* Query the size needed to get the printer names */
- PrfQueryProfileSize(HINI_PROFILE,
- (PSZ)pm_spooler_printer,
- (PSZ)NULL,
- (PULONG)&Length);
-
- /* Allocate space for printer names */
- PrinterNames = malloc((LONG)Length);
-
- /* Get the printer names */
- PrfQueryProfileString(HINI_PROFILE,
- (PSZ)pm_spooler_printer,
- (PSZ)NULL,
- (PSZ)NULL,
- (PVOID)PrinterNames,
- Length);
-
- /* get Printer information and search for the specific queue */
- for (PrinterName = PrinterNames, found = FALSE;
- *PrinterName;
- PrinterName = &PrinterName[strlen(PrinterName) + 1])
- {
- /* Query the size needed to get the printer information */
- PrfQueryProfileSize(HINI_PROFILE,
- (PSZ)pm_spooler_printer,
- (PSZ)PrinterName,
- (PULONG)&Length);
-
- PrinterInfo = malloc((ULONG)Length);
-
- PrfQueryProfileString(HINI_PROFILE,
- (PSZ)pm_spooler_printer,
- (PSZ)PrinterName,
- (PSZ)NULL,
- (PVOID)PrinterInfo,
- Length);
-
- /* Get Driver Info and Queue Info of the string */
- DriverInfo = &PrinterInfo[strcspn(PrinterInfo, separator1) + 1];
- QueueInfo = &DriverInfo[strcspn(DriverInfo, separator1) + 1];
- QueueInfo[strcspn(QueueInfo, separator1)] = '\0';
- QueueInfo[-1] = '\0';
-
- /* Verify Queues with specific Queue Name */
- Queue = strchr(QueueInfo, separator2[0]);
-
- while (Queue)
- {
- /* if Queue found, compare Driver Names */
- if (!strcmp(Queue, QueueName))
- {
- Driver = strchr(DriverInfo, separator2[0]);
- while (Driver)
- {
- /* if Driver found, stop loop */
- if (!strcmp(Driver, QueueDriverName))
- {
- found = TRUE;
- break;
- }
- Driver = strchr(NULL, separator2[0]);
- }
- break;
- }
- Queue = strchr(NULL,separator2[0]);
- }
-
- free(PrinterInfo);
-
- if (found)
- break;
- }
-
- if (*DriverData == NULL)
- {
- /* Query length for Job-Properties */
- rc = DevPostDeviceModes(hAB,
- NULL,
- DriverName,
- DeviceName,
- PrinterName,
- flOptions);
-
- if (rc <= 0L)
- {
- free(PrinterNames);
- return(FALSE);
- }
-
- *DriverData = malloc((LONG)rc);
-
- *DriverDataLength = (LONG)rc;
- }
-
- /* call DevPostDeviceModes */
- rc = DevPostDeviceModes(hAB,
- *DriverData,
- DriverName,
- DeviceName,
- PrinterName,
- flOptions);
-
- if ((PrtName != (PSZ)NULL) && (PrinterName != NULL))
- strcpy(PrtName, PrinterName);
-
- if (PrinterNames != NULL)
- free(PrinterNames);
-
- return TRUE;
- } /* End of QueryJobProperties */
- /************************** End of FILE.C *********************************/
-