From 83d6e26b31e85b91ffae9e6e1748d20076119e4f Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Wed, 5 Nov 2003 00:37:47 +0000 Subject: [PATCH] Support for duplex printing. --- dlls/wineps/driver.c | 51 +++++++++++++++++++++++++--------------- dlls/wineps/init.c | 18 +++++++++++++-- dlls/wineps/ppd.c | 54 ++++++++++++++++++++++++++++++++++++++++++- dlls/wineps/ps.c | 14 +++++++++++ dlls/wineps/psdlg.h | 3 ++- dlls/wineps/psdrv.h | 10 ++++++++ dlls/wineps/wps_De.rc | 3 +++ dlls/wineps/wps_En.rc | 3 +++ dlls/wineps/wps_Fr.rc | 3 +++ dlls/wineps/wps_Ko.rc | 3 +++ dlls/wineps/wps_Pt.rc | 3 +++ dlls/wineps/wps_Ru.rc | 9 +++++--- dlls/wineps/wps_Si.rc | 3 +++ dlls/wineps/wps_Sk.rc | 3 +++ 14 files changed, 155 insertions(+), 25 deletions(-) diff --git a/dlls/wineps/driver.c b/dlls/wineps/driver.c index e15431a4de3..56106e2f48b 100644 --- a/dlls/wineps/driver.c +++ b/dlls/wineps/driver.c @@ -136,7 +136,7 @@ void PSDRV_MergeDevmodes(PSDRV_DEVMODEA *dm1, PSDRV_DEVMODEA *dm2, dm1->dmPublic.dmPrintQuality = dm2->dmPublic.dmPrintQuality; if (dm2->dmPublic.dmFields & DM_COLOR ) dm1->dmPublic.dmColor = dm2->dmPublic.dmColor; - if (dm2->dmPublic.dmFields & DM_DUPLEX ) + if (dm2->dmPublic.dmFields & DM_DUPLEX && pi->ppd->DefaultDuplex && pi->ppd->DefaultDuplex->WinDuplex != 0) dm1->dmPublic.dmDuplex = dm2->dmPublic.dmDuplex; if (dm2->dmPublic.dmFields & DM_YRESOLUTION ) dm1->dmPublic.dmYResolution = dm2->dmPublic.dmYResolution; @@ -201,7 +201,7 @@ INT_PTR CALLBACK PSDRV_PaperDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM PSDRV_DLGINFO *di; int i, Cursel = 0; PAGESIZE *ps; - + DUPLEX *duplex; switch(msg) { case WM_INITDIALOG: @@ -215,11 +215,25 @@ INT_PTR CALLBACK PSDRV_PaperDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM Cursel = i; } SendDlgItemMessageA(hwnd, IDD_PAPERS, LB_SETCURSEL, Cursel, 0); - + CheckRadioButton(hwnd, IDD_ORIENT_PORTRAIT, IDD_ORIENT_LANDSCAPE, di->pi->Devmode->dmPublic.u1.s1.dmOrientation == DMORIENT_PORTRAIT ? IDD_ORIENT_PORTRAIT : IDD_ORIENT_LANDSCAPE); + + if(!di->pi->ppd->Duplexes) { + ShowWindow(GetDlgItem(hwnd, IDD_DUPLEX), SW_HIDE); + ShowWindow(GetDlgItem(hwnd, IDD_DUPLEX_NAME), SW_HIDE); + } else { + Cursel = 0; + for(duplex = di->pi->ppd->Duplexes, i = 0; duplex; duplex = duplex->next, i++) { + SendDlgItemMessageA(hwnd, IDD_DUPLEX, CB_INSERTSTRING, i, + (LPARAM)(duplex->FullName ? duplex->FullName : duplex->Name)); + if(di->pi->Devmode->dmPublic.dmDuplex == duplex->WinDuplex) + Cursel = i; + } + SendDlgItemMessageA(hwnd, IDD_DUPLEX, CB_SETCURSEL, Cursel, 0); + } break; case WM_COMMAND: @@ -242,6 +256,16 @@ INT_PTR CALLBACK PSDRV_PaperDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM di->dlgdm->dmPublic.u1.s1.dmOrientation = wParam == IDD_ORIENT_PORTRAIT ? DMORIENT_PORTRAIT : DMORIENT_LANDSCAPE; break; + case IDD_DUPLEX: + if(HIWORD(wParam) == CBN_SELCHANGE) { + Cursel = SendDlgItemMessageA(hwnd, LOWORD(wParam), CB_GETCURSEL, 0, 0); + for(i = 0, duplex = di->pi->ppd->Duplexes; i < Cursel; i++, duplex = duplex->next) + ; + TRACE("Setting duplex to item %d Winduplex = %d\n", Cursel, + duplex->WinDuplex); + di->dlgdm->dmPublic.dmDuplex = duplex->WinDuplex; + } + break; } break; @@ -417,6 +441,7 @@ DWORD PSDRV_DeviceCapabilities(LPSTR lpszDriver, LPCSTR lpszDevice, LPCSTR lpszP { PRINTERINFO *pi; DEVMODEA *lpdm; + DWORD ret; pi = PSDRV_FindPrinterInfo(lpszDevice); TRACE("Cap=%d. Got PrinterInfo = %p\n", fwCapability, pi); @@ -482,12 +507,6 @@ DWORD PSDRV_DeviceCapabilities(LPSTR lpszDriver, LPCSTR lpszDevice, LPCSTR lpszP WORD *wp = (WORD *)lpszOutput; int i = 0; - /* We explicitly list DMBIN_AUTO first; actually while win9x does this - win2000 lists DMBIN_FORMSOURCE instead. */ - i++; - if(lpszOutput != NULL) - *wp++ = DMBIN_AUTO; - for(slot = pi->ppd->InputSlots; slot; slot = slot->next, i++) if(lpszOutput != NULL) *wp++ = slot->WinBin; @@ -500,13 +519,6 @@ DWORD PSDRV_DeviceCapabilities(LPSTR lpszDriver, LPCSTR lpszDevice, LPCSTR lpszP char *cp = lpszOutput; int i = 0; - /* Add an entry corresponding to DMBIN_AUTO, see DC_BINS */ - i++; - if(lpszOutput != NULL) { - strcpy(cp, "Automatically Select"); - cp += 24; - } - for(slot = pi->ppd->InputSlots; slot; slot = slot->next, i++) if(lpszOutput != NULL) { lstrcpynA(cp, slot->FullName, 24); @@ -542,8 +554,11 @@ DWORD PSDRV_DeviceCapabilities(LPSTR lpszDriver, LPCSTR lpszDevice, LPCSTR lpszP return -1; /* simulate that the driver supports 'RAW' */ case DC_DUPLEX: - FIXME("DC_DUPLEX: returning %d. Is this correct?\n", lpdm->dmDuplex); - return lpdm->dmDuplex; + ret = 0; + if(pi->ppd->DefaultDuplex && pi->ppd->DefaultDuplex->WinDuplex != 0) + ret = 1; + TRACE("DC_DUPLEX: returning %ld\n", ret); + return ret; case DC_EMF_COMPLIANT: FIXME("DC_EMF_COMPLIANT: stub.\n"); diff --git a/dlls/wineps/init.c b/dlls/wineps/init.c index 1ed5fcb130d..bb7d8180ccd 100644 --- a/dlls/wineps/init.c +++ b/dlls/wineps/init.c @@ -59,7 +59,7 @@ static PSDRV_DEVMODEA DefaultDevmode = /* dmDriverExtra */ sizeof(PSDRV_DEVMODEA)-sizeof(DEVMODEA), /* dmFields */ DM_ORIENTATION | DM_PAPERSIZE | DM_SCALE | DM_COPIES | DM_DEFAULTSOURCE | DM_COLOR | - DM_DUPLEX | DM_YRESOLUTION | DM_TTOPTION, + DM_YRESOLUTION | DM_TTOPTION, { /* u1 */ { /* s1 */ /* dmOrientation */ DMORIENT_PORTRAIT, @@ -73,7 +73,7 @@ static PSDRV_DEVMODEA DefaultDevmode = /* dmDefaultSource */ DMBIN_AUTO, /* dmPrintQuality */ 0, /* dmColor */ DMCOLOR_COLOR, -/* dmDuplex */ 0, +/* dmDuplex */ DMDUP_SIMPLEX, /* dmYResolution */ 0, /* dmTTOption */ DMTT_SUBDEV, /* dmCollate */ 0, @@ -682,6 +682,20 @@ PRINTERINFO *PSDRV_FindPrinterInfo(LPCSTR name) goto closeprinter; } + /* Duplex is indicated by the setting of the DM_DUPLEX bit in dmFields. + WinDuplex == 0 is a special case which means that the ppd has a + *DefaultDuplex: NotCapable entry. In this case we'll try not to confuse + apps and set dmDuplex to DMDUP_SIMPLEX but leave the DM_DUPLEX clear. + PSDRV_WriteHeader understands this and copes. */ + pi->Devmode->dmPublic.dmFields &= ~DM_DUPLEX; + if(pi->ppd->DefaultDuplex) { + pi->Devmode->dmPublic.dmDuplex = pi->ppd->DefaultDuplex->WinDuplex; + if(pi->Devmode->dmPublic.dmDuplex != 0) + pi->Devmode->dmPublic.dmFields |= DM_DUPLEX; + else + pi->Devmode->dmPublic.dmDuplex = DMDUP_SIMPLEX; + } + res = EnumPrinterDataExA (hPrinter, "PrinterDriverData\\FontSubTable", NULL, 0, &needed, &pi->FontSubTableSize); if (res == ERROR_SUCCESS || res == ERROR_FILE_NOT_FOUND) { diff --git a/dlls/wineps/ppd.c b/dlls/wineps/ppd.c index 445ba54a9c4..293349ed1ca 100644 --- a/dlls/wineps/ppd.c +++ b/dlls/wineps/ppd.c @@ -556,7 +556,7 @@ PPD *PSDRV_ParsePPD(char *fname) FILE *fp; PPD *ppd; PPDTuple tuple; - char *default_pagesize = NULL; + char *default_pagesize = NULL, *default_duplex = NULL; TRACE("file '%s'\n", fname); @@ -814,6 +814,40 @@ PPD *PSDRV_ParsePPD(char *fname) TRACE("*TTRasterizer = %d\n", ppd->TTRasterizer); } + else if(!strcmp("*Duplex", tuple.key)) { + DUPLEX **duplex; + for(duplex = &ppd->Duplexes; *duplex; duplex = &(*duplex)->next) + ; + *duplex = HeapAlloc(GetProcessHeap(), 0, sizeof(**duplex)); + (*duplex)->Name = tuple.option; + (*duplex)->FullName = tuple.opttrans; + (*duplex)->InvocationString = tuple.value; + (*duplex)->next = NULL; + if(!strcasecmp("None", tuple.option) || !strcasecmp("False", tuple.option) + || !strcasecmp("Simplex", tuple.option)) + (*duplex)->WinDuplex = DMDUP_SIMPLEX; + else if(!strcasecmp("DuplexNoTumble", tuple.option)) + (*duplex)->WinDuplex = DMDUP_VERTICAL; + else if(!strcasecmp("DuplexTumble", tuple.option)) + (*duplex)->WinDuplex = DMDUP_HORIZONTAL; + else if(!strcasecmp("Notcapable", tuple.option)) + (*duplex)->WinDuplex = 0; + else { + FIXME("Unknown option %s for *Duplex defaulting to simplex\n", tuple.option); + (*duplex)->WinDuplex = DMDUP_SIMPLEX; + } + tuple.option = tuple.opttrans = tuple.value = NULL; + } + + else if(!strcmp("*DefaultDuplex", tuple.key)) { + if(default_duplex) { + WARN("Already set default duplex\n"); + } else { + default_duplex = tuple.value; + tuple.value = NULL; + } + } + if(tuple.key) HeapFree(PSDRV_Heap, 0, tuple.key); if(tuple.option) HeapFree(PSDRV_Heap, 0, tuple.option); if(tuple.value) HeapFree(PSDRV_Heap, 0, tuple.value); @@ -840,6 +874,24 @@ PPD *PSDRV_ParsePPD(char *fname) TRACE("Setting DefaultPageSize to first in list\n"); } + ppd->DefaultDuplex = NULL; + if(default_duplex) { + DUPLEX *duplex; + for(duplex = ppd->Duplexes; duplex; duplex = duplex->next) { + if(!strcmp(duplex->Name, default_duplex)) { + ppd->DefaultDuplex = duplex; + TRACE("DefaultDuplex: %s\n", duplex->Name); + break; + } + } + HeapFree(PSDRV_Heap, 0, default_duplex); + } + if(!ppd->DefaultDuplex) { + ppd->DefaultDuplex = ppd->Duplexes; + TRACE("Setting DefaultDuplex to first in list\n"); + } + + { FONTNAME *fn; PAGESIZE *page; diff --git a/dlls/wineps/ps.c b/dlls/wineps/ps.c index e0c3e8d142c..b1c24c45a81 100644 --- a/dlls/wineps/ps.c +++ b/dlls/wineps/ps.c @@ -234,6 +234,8 @@ INT PSDRV_WriteHeader( PSDRV_PDEVICE *physDev, LPCSTR title ) char *buf; INPUTSLOT *slot; PAGESIZE *page; + DUPLEX *duplex; + int win_duplex; int llx, lly, urx, ury; TRACE("'%s'\n", debugstr_a(title)); @@ -289,6 +291,18 @@ INT PSDRV_WriteHeader( PSDRV_PDEVICE *physDev, LPCSTR title ) } } + win_duplex = physDev->Devmode->dmPublic.dmFields & DM_DUPLEX ? + physDev->Devmode->dmPublic.dmDuplex : 0; + for(duplex = physDev->pi->ppd->Duplexes; duplex; duplex = duplex->next) { + if(duplex->WinDuplex == win_duplex) { + if(duplex->InvocationString) { + PSDRV_WriteFeature(physDev->job.hJob, "*Duplex", duplex->Name, + duplex->InvocationString); + break; + } + } + } + WriteSpool16( physDev->job.hJob, psendsetup, strlen(psendsetup) ); diff --git a/dlls/wineps/psdlg.h b/dlls/wineps/psdlg.h index 6e58563a1b7..3a1e87d794d 100644 --- a/dlls/wineps/psdlg.h +++ b/dlls/wineps/psdlg.h @@ -24,5 +24,6 @@ #define IDD_PAPERS 100 #define IDD_ORIENT_PORTRAIT 101 #define IDD_ORIENT_LANDSCAPE 102 - +#define IDD_DUPLEX 110 +#define IDD_DUPLEX_NAME 111 #endif /* __WINE_PSDLG_H */ diff --git a/dlls/wineps/psdrv.h b/dlls/wineps/psdrv.h index b6909b3bba3..12cfd2037b0 100644 --- a/dlls/wineps/psdrv.h +++ b/dlls/wineps/psdrv.h @@ -175,6 +175,14 @@ typedef struct _tagINPUTSLOT { typedef enum _RASTERIZEROPTION {RO_None, RO_Accept68K, RO_Type42, RO_TrueImage} RASTERIZEROPTION; +typedef struct _tagDUPLEX { + char *Name; + char *FullName; + char *InvocationString; + WORD WinDuplex; /* eg DMDUP_SIMPLEX */ + struct _tagDUPLEX *next; +} DUPLEX; + typedef struct { char *NickName; int LanguageLevel; @@ -192,6 +200,8 @@ typedef struct { CONSTRAINT *Constraints; INPUTSLOT *InputSlots; RASTERIZEROPTION TTRasterizer; + DUPLEX *Duplexes; + DUPLEX *DefaultDuplex; } PPD; typedef struct { diff --git a/dlls/wineps/wps_De.rc b/dlls/wineps/wps_De.rc index bcc68a62b30..a8ce71274d9 100644 --- a/dlls/wineps/wps_De.rc +++ b/dlls/wineps/wps_De.rc @@ -31,4 +31,7 @@ FONT 8, "Helv" WS_TABSTOP, 20, 90, 60, 10 CONTROL "&Querformat", IDD_ORIENT_LANDSCAPE, "Button", BS_AUTORADIOBUTTON, 20, 110, 60, 10 + LTEXT "Duplex:", IDD_DUPLEX_NAME, 10, 140, 100, 8 + COMBOBOX IDD_DUPLEX, 10, 151, 200, 20, CBS_DROPDOWNLIST | CBS_HASSTRINGS | + WS_TABSTOP } diff --git a/dlls/wineps/wps_En.rc b/dlls/wineps/wps_En.rc index ca0d0d999f5..45ea136a09c 100644 --- a/dlls/wineps/wps_En.rc +++ b/dlls/wineps/wps_En.rc @@ -31,4 +31,7 @@ FONT 8, "Helv" WS_TABSTOP, 20, 90, 60, 10 CONTROL "&Landscape", IDD_ORIENT_LANDSCAPE, "Button", BS_AUTORADIOBUTTON, 20, 110, 60, 10 + LTEXT "Duplex:", IDD_DUPLEX_NAME, 10, 140, 100, 8 + COMBOBOX IDD_DUPLEX, 10, 151, 200, 20, CBS_DROPDOWNLIST | CBS_HASSTRINGS | + WS_TABSTOP } diff --git a/dlls/wineps/wps_Fr.rc b/dlls/wineps/wps_Fr.rc index 82bff864a38..2366df5562c 100644 --- a/dlls/wineps/wps_Fr.rc +++ b/dlls/wineps/wps_Fr.rc @@ -34,4 +34,7 @@ FONT 8, "Helv" WS_TABSTOP, 20, 90, 60, 10 CONTROL "P&aysage", IDD_ORIENT_LANDSCAPE, "Button", BS_AUTORADIOBUTTON, 20, 110, 60, 10 + LTEXT "Recto-verso:", IDD_DUPLEX_NAME, 10, 140, 100, 8 + COMBOBOX IDD_DUPLEX, 10, 151, 200, 20, CBS_DROPDOWNLIST | CBS_HASSTRINGS | + WS_TABSTOP } diff --git a/dlls/wineps/wps_Ko.rc b/dlls/wineps/wps_Ko.rc index a8c0a1d9609..4e8702aea06 100644 --- a/dlls/wineps/wps_Ko.rc +++ b/dlls/wineps/wps_Ko.rc @@ -31,4 +31,7 @@ FONT 9, "Helv" WS_TABSTOP, 20, 90, 60, 10 CONTROL "&Landscape", IDD_ORIENT_LANDSCAPE, "Button", BS_AUTORADIOBUTTON, 20, 110, 60, 10 + LTEXT "Duplex:", IDD_DUPLEX_NAME, 10, 140, 100, 8 + COMBOBOX IDD_DUPLEX, 10, 151, 200, 20, CBS_DROPDOWNLIST | CBS_HASSTRINGS | + WS_TABSTOP } diff --git a/dlls/wineps/wps_Pt.rc b/dlls/wineps/wps_Pt.rc index cd5bc0c4a83..6f85948fae4 100644 --- a/dlls/wineps/wps_Pt.rc +++ b/dlls/wineps/wps_Pt.rc @@ -31,4 +31,7 @@ FONT 8, "Helv" WS_TABSTOP, 20, 90, 60, 10 CONTROL "&Paisagem", IDD_ORIENT_LANDSCAPE, "Button", BS_AUTORADIOBUTTON, 20, 110, 60, 10 + LTEXT "Duplex:", IDD_DUPLEX_NAME, 10, 140, 100, 8 + COMBOBOX IDD_DUPLEX, 10, 151, 200, 20, CBS_DROPDOWNLIST | CBS_HASSTRINGS | + WS_TABSTOP } diff --git a/dlls/wineps/wps_Ru.rc b/dlls/wineps/wps_Ru.rc index 85aa699ffb7..b6297e0f8d5 100644 --- a/dlls/wineps/wps_Ru.rc +++ b/dlls/wineps/wps_Ru.rc @@ -25,12 +25,15 @@ STYLE WS_POPUP | WS_CAPTION | WS_CLIPSIBLINGS | WS_VISIBLE CAPTION "Бумага" FONT 8, "Helv" { - LTEXT "&Размер бумаги:", -1, 10, 6, 100, 8 + LTEXT "&Размер бумаги:", -1, 10, 6, 200, 8 LISTBOX IDD_PAPERS, 10, 15, 200, 45, LBS_STANDARD | LBS_HASSTRINGS | WS_TABSTOP GROUPBOX "Ориентация", -1, 10, 80, 200, 50 CONTROL "&Книжная", IDD_ORIENT_PORTRAIT, "Button", BS_AUTORADIOBUTTON | - WS_TABSTOP, 20, 90, 60, 10 + WS_TABSTOP, 20, 90, 180, 10 CONTROL "&Альбомная", IDD_ORIENT_LANDSCAPE, "Button", BS_AUTORADIOBUTTON, - 20, 110, 60, 10 + 20, 110, 180, 10 + LTEXT "2-х сторонняя печать:", IDD_DUPLEX_NAME, 10, 140, 200, 8 + COMBOBOX IDD_DUPLEX, 10, 151, 200, 20, CBS_DROPDOWNLIST | CBS_HASSTRINGS | + WS_TABSTOP } diff --git a/dlls/wineps/wps_Si.rc b/dlls/wineps/wps_Si.rc index 8d18d88efb5..640d3bb7921 100644 --- a/dlls/wineps/wps_Si.rc +++ b/dlls/wineps/wps_Si.rc @@ -31,4 +31,7 @@ FONT 8, "MS Sans Serif" WS_TABSTOP, 20, 90, 60, 10 CONTROL "L&eћeиa", IDD_ORIENT_LANDSCAPE, "Button", BS_AUTORADIOBUTTON, 20, 110, 60, 10 + LTEXT "Duplex:", IDD_DUPLEX_NAME, 10, 140, 100, 8 + COMBOBOX IDD_DUPLEX, 10, 151, 200, 20, CBS_DROPDOWNLIST | CBS_HASSTRINGS | + WS_TABSTOP } diff --git a/dlls/wineps/wps_Sk.rc b/dlls/wineps/wps_Sk.rc index 6571cd6d54e..c3e0dd7914f 100644 --- a/dlls/wineps/wps_Sk.rc +++ b/dlls/wineps/wps_Sk.rc @@ -31,4 +31,7 @@ FONT 8, "Helv" WS_TABSTOP, 20, 90, 60, 10 CONTROL "&Na љнrku", IDD_ORIENT_LANDSCAPE, "Button", BS_AUTORADIOBUTTON, 20, 110, 60, 10 + LTEXT "Duplex:", IDD_DUPLEX_NAME, 10, 140, 100, 8 + COMBOBOX IDD_DUPLEX, 10, 151, 200, 20, CBS_DROPDOWNLIST | CBS_HASSTRINGS | + WS_TABSTOP }