#include "win32\win32guts.h" #ifndef _APRICOT_H_ #include "apricot.h" #endif #include "img_conv.h" #include "guts.h" #include "Window.h" #include "Printer.h" #include "DeviceBitmap.h" #ifdef __cplusplus extern "C" { #endif #define sys (( PDrawableData)(( PComponent) self)-> sysData)-> #define dsys( view) (( PDrawableData)(( PComponent) view)-> sysData)-> #define var (( PWidget) self)-> #define HANDLE sys handle #define DHANDLE(x) dsys(x) handle ApiHandle apc_prn_get_handle( Handle self) { objCheck 0; return ( ApiHandle) sys ps; } Bool apc_prn_create( Handle self) { objCheck false; apt_set(aptPrinter); return true; } static void ppi_create( LPPRINTER_INFO_2 dest, LPPRINTER_INFO_2 source) { #define SZCPY(field) dest-> field = duplicate_string( source-> field) memcpy( dest, source, sizeof( PRINTER_INFO_2)); SZCPY( pPrinterName); SZCPY( pServerName); SZCPY( pShareName); SZCPY( pPortName); SZCPY( pDriverName); SZCPY( pComment); SZCPY( pLocation); SZCPY( pSepFile); SZCPY( pPrintProcessor); SZCPY( pDatatype); SZCPY( pParameters); if ( source-> pDevMode) { int sz = source-> pDevMode-> dmSize + source-> pDevMode-> dmDriverExtra; dest-> pDevMode = ( LPDEVMODE) malloc( sz); if ( dest-> pDevMode) memcpy( dest-> pDevMode, source-> pDevMode, sz); } } static void ppi_destroy( LPPRINTER_INFO_2 ppi) { if ( !ppi) return; free( ppi-> pPrinterName); free( ppi-> pServerName); free( ppi-> pShareName); free( ppi-> pPortName); free( ppi-> pDriverName); free( ppi-> pComment); free( ppi-> pLocation); free( ppi-> pSepFile); free( ppi-> pPrintProcessor); free( ppi-> pDatatype); free( ppi-> pParameters); free( ppi-> pDevMode); memset( ppi, 0, sizeof( PRINTER_INFO_2)); } Bool apc_prn_destroy( Handle self) { ppi_destroy( &sys s. prn. ppi); return true; } static int prn_query( Handle self, const char * printer, LPPRINTER_INFO_2 info) { DWORD returned, needed; LPPRINTER_INFO_2 ppi, useThis = NULL; int i; Bool useDefault = ( printer == NULL || strlen( printer) == 0); char * device; EnumPrinters( PRINTER_ENUM_FAVORITE | PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &returned); ppi = ( LPPRINTER_INFO_2) malloc( needed + 4); if ( !ppi) return 0; if ( !EnumPrinters( PRINTER_ENUM_FAVORITE | PRINTER_ENUM_LOCAL, NULL, 2, ( LPBYTE) ppi, needed, &needed, &returned)) { apiErr; free( ppi); return 0; } if ( returned == 0) { apcErr( errNoPrinters); free( ppi); return 0; } device = apc_prn_get_default( self); for ( i = 0; i < returned; i++) { if ( useDefault && device && ( strcmp( device, ppi[ i]. pPrinterName) == 0)) { useThis = &ppi[ i]; break; } if ( !useDefault && ( strcmp( printer, ppi[ i]. pPrinterName) == 0)) { useThis = &ppi[ i]; break; } } if ( useDefault && useThis == NULL) useThis = ppi; if ( useThis) ppi_create( info, useThis); if ( !useThis) apcErr( errInvPrinter); free( ppi); return useThis ? 1 : -2; } PrinterInfo* apc_prn_enumerate( Handle self, int * count) { DWORD returned, needed; LPPRINTER_INFO_2 ppi; PPrinterInfo list; char *printer; int i; *count = 0; objCheck NULL; EnumPrinters( PRINTER_ENUM_FAVORITE | PRINTER_ENUM_LOCAL, NULL, 2, NULL, 0, &needed, &returned); ppi = ( LPPRINTER_INFO_2) malloc( needed + 4); if ( !ppi) return NULL; if ( !EnumPrinters( PRINTER_ENUM_FAVORITE | PRINTER_ENUM_LOCAL, NULL, 2, ( LPBYTE) ppi, needed, &needed, &returned)) { apiErr; free( ppi); return NULL; } if ( returned == 0) { apcErr( errNoPrinters); free( ppi); return NULL; } printer = apc_prn_get_default( self); list = ( PPrinterInfo) malloc( returned * sizeof( PrinterInfo)); if ( !list) { free( ppi); return NULL; } for ( i = 0; i < returned; i++) { strncpy( list[ i]. name, ppi[ i]. pPrinterName, 255); list[ i]. name[ 255] = 0; strncpy( list[ i]. device, ppi[ i]. pPortName, 255); list[ i]. device[ 255] = 0; list[ i]. defaultPrinter = (( printer != NULL) && ( strcmp( printer, list[ i]. name) == 0)); } *count = returned; free( ppi); return list; } static HDC prn_info_dc( Handle self) { LPPRINTER_INFO_2 ppi = &sys s. prn. ppi; HDC ret = CreateIC( ppi-> pDriverName, ppi-> pPrinterName, ppi-> pPortName, ppi-> pDevMode); if ( !ret) apiErr; return ret; } Bool apc_prn_select( Handle self, const char* printer) { int rc; PRINTER_INFO_2 ppi; HDC dc; objCheck false; rc = prn_query( self, printer, &ppi); if ( rc > 0) { ppi_destroy( &sys s. prn. ppi); memcpy( &sys s. prn. ppi, &ppi, sizeof( ppi)); } else return false; if ( !( dc = prn_info_dc( self))) return false; sys res. x = ( float) GetDeviceCaps( dc, LOGPIXELSX); sys res. y = ( float) GetDeviceCaps( dc, LOGPIXELSY); sys lastSize. x = GetDeviceCaps( dc, HORZRES); sys lastSize. y = GetDeviceCaps( dc, VERTRES); if ( !DeleteDC( dc)) apiErr; return true; } char * apc_prn_get_selected( Handle self) { objCheck ""; return sys s. prn. ppi. pPrinterName; } Point apc_prn_get_size( Handle self) { Point p = {0,0}; objCheck p; return sys lastSize; } Point apc_prn_get_resolution( Handle self) { Point p = {0,0}; objCheck p; return sys res; } char * apc_prn_get_default( Handle self) { objCheck ""; GetProfileString("windows", "device", ",,,", sys s. prn. defPrnBuf, 255); if (( sys s. prn. device = strtok( sys s. prn. defPrnBuf, (const char *) ",")) && ( sys s. prn. driver = strtok((char *) NULL, (const char *) ", ")) && ( sys s. prn. port = strtok ((char *) NULL, (const char *) ", "))) { } else sys s. prn. device = sys s. prn. driver = sys s. prn. port = NULL; return sys s. prn. device; } Bool apc_prn_setup( Handle self) { void * lph; LONG sz, ret; DEVMODE * dm; HWND who = GetActiveWindow(); HDC dc; objCheck false; if ( !OpenPrinter( sys s. prn. ppi. pPrinterName, &lph, NULL)) apiErrRet; sz = DocumentProperties( NULL, lph, sys s. prn. ppi. pPrinterName, NULL, NULL, 0); if ( sz <= 0) { apiErr; ClosePrinter( lph); return false; } dm = ( DEVMODE * ) malloc( sz); if ( !dm) { ClosePrinter( lph); return false; } sys s. prn. ppi. pDevMode-> dmFields = -1; ret = DocumentProperties( hwnd_to_view( who) ? who : NULL, lph, sys s. prn. ppi. pPrinterName, dm, sys s. prn. ppi. pDevMode, DM_IN_BUFFER|DM_IN_PROMPT|DM_OUT_BUFFER); ClosePrinter( lph); if ( ret != IDOK) { free( dm); return false; } free( sys s. prn. ppi. pDevMode); sys s. prn. ppi. pDevMode = dm; if ( !( dc = prn_info_dc( self))) return false; sys res. x = ( float) GetDeviceCaps( dc, LOGPIXELSX); sys res. y = ( float) GetDeviceCaps( dc, LOGPIXELSY); sys lastSize. x = GetDeviceCaps( dc, HORZRES); sys lastSize. y = GetDeviceCaps( dc, VERTRES); if ( !DeleteDC( dc)) apiErr; return true; } typedef struct _PrnKey { long value; char * name; } PrnKey; static PrnKey ctx_options[] = { { DM_ORIENTATION , "Orientation" }, { DM_PAPERSIZE , "PaperSize" }, { DM_PAPERLENGTH , "PaperLength" }, { DM_PAPERWIDTH , "PaperWidth" }, { DM_SCALE , "Scale" }, { DM_COPIES , "Copies" }, { DM_DEFAULTSOURCE , "DefaultSource" }, { DM_PRINTQUALITY , "PrintQuality" }, { DM_COLOR , "Color" }, { DM_DUPLEX , "Duplex" }, { DM_YRESOLUTION , "YResolution" }, { DM_TTOPTION , "TTOption" }, { DM_COLLATE , "Collate" }, { DM_FORMNAME , "FormName" } }; static PrnKey ctx_orientation[] = { { DMORIENT_PORTRAIT ,"Portrait" }, { DMORIENT_LANDSCAPE ,"Landscape" } }; static PrnKey ctx_papersize[] = { { DMPAPER_LETTER , "Letter" }, { DMPAPER_LETTERSMALL , "LetterSmall" }, { DMPAPER_TABLOID , "Tabloid" }, { DMPAPER_LEDGER , "Ledger" }, { DMPAPER_LEGAL , "Legal" }, { DMPAPER_STATEMENT , "Statement" }, { DMPAPER_EXECUTIVE , "Executive" }, { DMPAPER_A3 , "A3" }, { DMPAPER_A4 , "A4" }, { DMPAPER_A4SMALL , "A4Small" }, { DMPAPER_A5 , "A5" }, { DMPAPER_B4 , "B4" }, { DMPAPER_B5 , "B5" }, { DMPAPER_FOLIO , "Folio" }, { DMPAPER_QUARTO , "Quarto" }, { DMPAPER_10X14 , "10X14" }, { DMPAPER_11X17 , "11X17" }, { DMPAPER_NOTE , "Note" }, { DMPAPER_ENV_9 , "ENV_9" }, { DMPAPER_ENV_10 , "ENV_10" }, { DMPAPER_ENV_11 , "ENV_11" }, { DMPAPER_ENV_12 , "ENV_12" }, { DMPAPER_ENV_14 , "ENV_14" }, { DMPAPER_CSHEET , "CSheet" }, { DMPAPER_DSHEET , "DSheet" }, { DMPAPER_ESHEET , "ESheet" }, { DMPAPER_ENV_DL , "ENV_DL" }, { DMPAPER_ENV_C5 , "ENV_C5" }, { DMPAPER_ENV_C3 , "ENV_C3" }, { DMPAPER_ENV_C4 , "ENV_C4" }, { DMPAPER_ENV_C6 , "ENV_C6" }, { DMPAPER_ENV_C65 , "ENV_C65" }, { DMPAPER_ENV_B4 , "ENV_B4" }, { DMPAPER_ENV_B5 , "ENV_B5" }, { DMPAPER_ENV_B6 , "ENV_B6" }, { DMPAPER_ENV_ITALY , "ENV_Italy" }, { DMPAPER_ENV_MONARCH , "ENV_Monarch" }, { DMPAPER_ENV_PERSONAL , "ENV_Personal" }, { DMPAPER_FANFOLD_US , "Fanfold_US" }, { DMPAPER_FANFOLD_STD_GERMAN , "Fanfold_Std_German" }, { DMPAPER_FANFOLD_LGL_GERMAN , "Fanfold_Lgl_German" } #if(WINVER >= 0x0400) , { DMPAPER_ISO_B4 , "ISO_B4" }, { DMPAPER_JAPANESE_POSTCARD , "Japanese_Postcard" }, { DMPAPER_9X11 , "9X11" }, { DMPAPER_10X11 , "10X11" }, { DMPAPER_15X11 , "15X11" }, { DMPAPER_ENV_INVITE , "ENV_Invite" }, { DMPAPER_RESERVED_48 , "RESERVED_48" }, { DMPAPER_RESERVED_49 , "RESERVED_49" }, { DMPAPER_LETTER_EXTRA , "Letter_Extra" }, { DMPAPER_LEGAL_EXTRA , "Legal_Extra" }, { DMPAPER_TABLOID_EXTRA , "Tabloid_Extra" }, { DMPAPER_A4_EXTRA , "A4_Extra" }, { DMPAPER_LETTER_TRANSVERSE , "Letter_Transverse" }, { DMPAPER_A4_TRANSVERSE , "A4_Transverse" }, { DMPAPER_LETTER_EXTRA_TRANSVERSE, "Per_Letter_Extra_Transverse" }, { DMPAPER_A_PLUS , "A_Plus" }, { DMPAPER_B_PLUS , "B_Plus" }, { DMPAPER_LETTER_PLUS , "Letter_Plus" }, { DMPAPER_A4_PLUS , "A4_Plus" }, { DMPAPER_A5_TRANSVERSE , "A5_Transverse" }, { DMPAPER_B5_TRANSVERSE , "B5_Transverse" }, { DMPAPER_A3_EXTRA , "A3_Extra" }, { DMPAPER_A5_EXTRA , "A5_Extra" }, { DMPAPER_B5_EXTRA , "B5_Extra" }, { DMPAPER_A2 , "A2" }, { DMPAPER_A3_TRANSVERSE , "A3_Transverse" }, { DMPAPER_A3_EXTRA_TRANSVERSE, "A3_Extra_Transverse" } #endif }; static PrnKey ctx_defsource[] = { { DMBIN_AUTO , "Auto" }, { DMBIN_CASSETTE , "Cassette" }, { DMBIN_ENVELOPE , "Envelope" }, { DMBIN_ENVMANUAL , "EnvManual" }, { DMBIN_FORMSOURCE , "FormSource" }, { DMBIN_LARGECAPACITY , "LargeCapacity" }, { DMBIN_LARGEFMT , "LargeFmt" }, { DMBIN_LOWER , "Lower" }, { DMBIN_MANUAL , "Manual" }, { DMBIN_MIDDLE , "Middle" }, { DMBIN_ONLYONE , "OnlyOne" }, { DMBIN_TRACTOR , "Tractor" }, { DMBIN_SMALLFMT , "SmallFmt" }, { DMBIN_USER+0 , "User0" }, { DMBIN_USER+1 , "User1" }, { DMBIN_USER+2 , "User2" }, { DMBIN_USER+3 , "User3" }, { DMBIN_USER+4 , "User4" } }; static PrnKey ctx_quality[] = { { DMRES_HIGH , "High" }, { DMRES_MEDIUM , "Medium" }, { DMRES_LOW , "Low" }, { DMRES_DRAFT , "Draft" } }; static PrnKey ctx_color[] = { { DMCOLOR_COLOR , "Color" }, { DMCOLOR_MONOCHROME, "Monochrome" } }; static PrnKey ctx_duplex[] = { { DMDUP_SIMPLEX , "Simplex" }, { DMDUP_HORIZONTAL, "Horizontal" }, { DMDUP_VERTICAL, "Vertical" } }; static PrnKey ctx_ttoption[] = { { DMTT_BITMAP, "Bitmap" }, { DMTT_DOWNLOAD, "Download" }, #if(WINVER >= 0x0400) { DMTT_DOWNLOAD_OUTLINE, "Download_Outline" }, #endif { DMTT_SUBDEV, "SubDev" } }; static char * ctx_prn_find_string( PrnKey * table, int table_size, long value) { int i; for ( i = 0; i < table_size; i++, table++) { if ( table-> value == value) return table-> name; } return NULL; } #define BADVAL -16384 static long ctx_prn_find_value( PrnKey * table, int table_size, char * name) { int i; for ( i = 0; i < table_size; i++, table++) { if ( strcmp( table-> name, name) == 0) return table-> value; } return BADVAL; } Bool apc_prn_set_option( Handle self, char * option, char * value) { long v, num; char * e; LPDEVMODE dev = sys s. prn. ppi. pDevMode; objCheck false; if ( !dev) return false; v = ctx_prn_find_value( ctx_options, sizeof(ctx_options)/sizeof(PrnKey), option); if ( v == BADVAL) return false; /* DM_FORMNAME string is special because it's a literal string */ if ( v == DM_FORMNAME) { strncpy((char*) dev-> dmFormName, value, CCHFORMNAME); dev-> dmFormName[CCHFORMNAME-1] = 0; return true; } /* any other setting may be a number */ num = strtol( value, &e, 10); #define LOOKUP_INT(table) \ if ( *e) { \ /* not a numerical */ \ v = ctx_prn_find_value( table, sizeof(table)/sizeof(PrnKey), value); \ if ( v == BADVAL) return false; \ } else { \ v = num;\ } switch ( v) { case DM_ORIENTATION: LOOKUP_INT( ctx_orientation); dev-> dmOrientation = v; break; case DM_PAPERSIZE: LOOKUP_INT( ctx_papersize); dev-> dmPaperSize = v; break; case DM_PAPERLENGTH: if (*e) return false; dev-> dmPaperLength = v; break; case DM_PAPERWIDTH: if (*e) return false; dev-> dmPaperWidth = v; break; case DM_SCALE: if (*e) return false; dev-> dmScale = v; break; case DM_COPIES: if (*e) return false; dev-> dmCopies = v; break; case DM_DEFAULTSOURCE: LOOKUP_INT( ctx_defsource); dev-> dmDefaultSource = v; break; case DM_PRINTQUALITY: LOOKUP_INT( ctx_quality); dev-> dmPrintQuality = v; break; case DM_COLOR: LOOKUP_INT( ctx_color); dev-> dmColor = v; break; case DM_DUPLEX: LOOKUP_INT( ctx_duplex); dev-> dmDuplex = v; break; case DM_TTOPTION: LOOKUP_INT( ctx_ttoption); dev-> dmTTOption = v; break; case DM_YRESOLUTION: if (*e) return false; dev-> dmYResolution = v; break; case DM_COLLATE: if (*e) return false; dev-> dmCollate = v; break; default: return false; } return true; } Bool apc_prn_get_option( Handle self, char * option, char ** value) { long v; char * c = NULL, buf[256]; LPDEVMODE dev = sys s. prn. ppi. pDevMode; *value = NULL; objCheck false; if ( !dev) return false; v = ctx_prn_find_value( ctx_options, sizeof(ctx_options)/sizeof(PrnKey), option); if ( v == BADVAL) return false; #define LOOKUP_STR(table,value) \ /* is a defined string? */ \ if (( c = ctx_prn_find_string( \ table, sizeof(table)/sizeof(PrnKey), value) \ ) == NULL) { \ /* return just a number */ \ sprintf( c = buf, "%d", value); \ } switch ( v) { case DM_ORIENTATION: LOOKUP_STR( ctx_orientation, dev-> dmOrientation); break; case DM_PAPERSIZE: LOOKUP_STR( ctx_papersize, dev-> dmPaperSize); break; case DM_PAPERLENGTH: sprintf( c = buf, "%d", dev-> dmPaperLength); break; case DM_PAPERWIDTH: sprintf( c = buf, "%d", dev-> dmPaperWidth); break; case DM_SCALE: sprintf( c = buf, "%d", dev-> dmScale); break; case DM_COPIES: sprintf( c = buf, "%d", dev-> dmCopies); break; case DM_DEFAULTSOURCE: LOOKUP_STR( ctx_defsource, dev-> dmDefaultSource); break; case DM_PRINTQUALITY: LOOKUP_STR( ctx_quality, dev-> dmPrintQuality); break; case DM_COLOR: LOOKUP_STR( ctx_color, dev-> dmColor); break; case DM_DUPLEX: LOOKUP_STR( ctx_duplex, dev-> dmDuplex); break; case DM_TTOPTION: LOOKUP_STR( ctx_ttoption, dev-> dmTTOption); break; case DM_YRESOLUTION: sprintf( c = buf, "%d", dev-> dmYResolution); break; case DM_COLLATE: sprintf( c = buf, "%d", dev-> dmCollate); break; case DM_FORMNAME: strncpy( c = buf, (char*)dev-> dmFormName, CCHFORMNAME); break; default: return false; } if ( c) *value = duplicate_string( c); return true; } Bool apc_prn_enum_options( Handle self, int * count, char *** options) { LPDEVMODE dev = sys s. prn. ppi. pDevMode; int i, size; PrnKey * table; *count = 0; objCheck false; if ( !dev) return false; if ( !(*options = malloc( sizeof(char*) * 32))) return false; for ( i = 0, size = sizeof( ctx_options) / sizeof( PrnKey), table = ctx_options; i < size; i++, table++ ) { if ( dev-> dmFields & table-> value) (*options)[(*count)++] = table-> name; } return true; } #define apiPrnErr { \ rc = GetLastError(); \ if ( rc != 1223 /* ERROR_CANCELLED */) \ apiAltErr( rc) \ else \ apcErr( errUserCancelled); \ } Bool apc_prn_begin_doc( Handle self, const char* docName) { LPPRINTER_INFO_2 ppi = &sys s. prn. ppi; DOCINFO doc; doc. cbSize = sizeof( DOCINFO); doc. lpszDocName = docName; doc. lpszOutput = NULL; doc. lpszDatatype = NULL; doc. fwType = 0; objCheck false; if ( !( sys ps = CreateDC( ppi-> pDriverName, ppi-> pPrinterName, ppi-> pPortName, ppi-> pDevMode))) apiErrRet; if ( StartDoc( sys ps, &doc) <= 0) { apiPrnErr; DeleteDC( sys ps); sys ps = NULL; return false; } if ( StartPage( sys ps) <= 0) { apiPrnErr; DeleteDC( sys ps); sys ps = NULL; return false; } hwnd_enter_paint( self); if (( sys pal = palette_create( self))) { SelectPalette( sys ps, sys pal, 0); RealizePalette( sys ps); } return true; } Bool apc_prn_begin_paint_info( Handle self) { LPPRINTER_INFO_2 ppi = &sys s. prn. ppi; objCheck false; if ( !( sys ps = CreateDC( ppi-> pDriverName, ppi-> pPrinterName, ppi-> pPortName, ppi-> pDevMode))) apiErrRet; hwnd_enter_paint( self); sys pal = palette_create( self); return true; } Bool apc_prn_end_doc( Handle self) { apcErrClear; objCheck false; if ( EndPage( sys ps) < 0) apiPrnErr; if ( EndDoc ( sys ps) < 0) apiPrnErr; hwnd_leave_paint( self); if ( sys pal) DeleteObject( sys pal); DeleteDC( sys ps); sys pal = NULL; sys ps = NULL; return guts.apcError == errOk; } Bool apc_prn_end_paint_info( Handle self) { apcErrClear; objCheck false; hwnd_leave_paint( self); DeleteDC( sys ps); sys ps = NULL; return guts.apcError == errOk; } Bool apc_prn_new_page( Handle self) { apcErrClear; objCheck false; if ( EndPage( sys ps) < 0) apiPrnErr; if ( StartPage( sys ps) < 0) apiPrnErr; return guts.apcError == errOk; } Bool apc_prn_abort_doc( Handle self) { objCheck false; if ( AbortDoc( sys ps) < 0) apiPrnErr; hwnd_leave_paint( self); if ( sys pal) DeleteObject( sys pal); DeleteDC( sys ps); sys pal = NULL; sys ps = NULL; return guts.apcError == errOk; } #ifdef __cplusplus } #endif