Implement ResetDC and PHYSICALOFFSET[X|Y] devcaps.
Fixes to MergeDevmodes.

diff --git a/dlls/wineps/driver.c b/dlls/wineps/driver.c
index 66fbfc3..9738e06 100644
--- a/dlls/wineps/driver.c
+++ b/dlls/wineps/driver.c
@@ -45,11 +45,17 @@
 {
     /* some sanity checks here on dm2 */
 
-    if(dm2->dmPublic.dmFields & DM_ORIENTATION)
+    if(dm2->dmPublic.dmFields & DM_ORIENTATION) {
         dm1->dmPublic.u1.s1.dmOrientation = dm2->dmPublic.u1.s1.dmOrientation;
+	TRACE("Changing orientation to %d (%s)\n",
+	      dm1->dmPublic.u1.s1.dmOrientation,
+	      dm1->dmPublic.u1.s1.dmOrientation == DMORIENT_PORTRAIT ?
+	      "Portrait" :
+	      (dm1->dmPublic.u1.s1.dmOrientation == DMORIENT_LANDSCAPE ?
+	       "Landscape" : "unknown"));
+    }
 
     /* NB PaperWidth is always < PaperLength */
-
     if(dm2->dmPublic.dmFields & DM_PAPERSIZE) {
         PAGESIZE *page;
 
@@ -63,6 +69,8 @@
 								254.0 / 72.0;
 	    dm1->dmPublic.u1.s1.dmPaperLength = page->PaperDimension->y *
 								254.0 / 72.0;
+	    dm1->dmPublic.dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH);
+	    dm1->dmPublic.dmFields |= DM_PAPERSIZE;
 	    TRACE("Changing page to %s %d x %d\n", page->FullName,
 		  dm1->dmPublic.u1.s1.dmPaperWidth,
 		  dm1->dmPublic.u1.s1.dmPaperLength );
@@ -70,20 +78,22 @@
 	    TRACE("Trying to change to unsupported pagesize %d\n",
 		      dm2->dmPublic.u1.s1.dmPaperSize);
 	}
-    }
-
-    if(dm2->dmPublic.dmFields & DM_PAPERLENGTH) {
+    } else if((dm2->dmPublic.dmFields & DM_PAPERLENGTH) &&
+       (dm2->dmPublic.dmFields & DM_PAPERWIDTH)) {
         dm1->dmPublic.u1.s1.dmPaperLength = dm2->dmPublic.u1.s1.dmPaperLength; 
-	TRACE("Changing PaperLength to %d\n",
-	      dm2->dmPublic.u1.s1.dmPaperLength);
-	FIXME("Changing PaperLength.  Do we adjust PaperSize?\n");
-    }
-
-    if(dm2->dmPublic.dmFields & DM_PAPERWIDTH) {
         dm1->dmPublic.u1.s1.dmPaperWidth = dm2->dmPublic.u1.s1.dmPaperWidth; 
-	TRACE("Changing PaperWidth to %d\n",
+	TRACE("Changing PaperLength|Width to %dx%d\n",
+	      dm2->dmPublic.u1.s1.dmPaperLength,
 	      dm2->dmPublic.u1.s1.dmPaperWidth);
-	FIXME("Changing PaperWidth.  Do we adjust PaperSize?\n");
+	dm1->dmPublic.dmFields &= ~DM_PAPERSIZE;
+	dm1->dmPublic.dmFields |= (DM_PAPERLENGTH | DM_PAPERWIDTH);
+    } else if(dm2->dmPublic.dmFields & (DM_PAPERLENGTH | DM_PAPERWIDTH)) {
+      /* You might think that this would be allowed if dm1 is in custom size
+	 mode, but apparently Windows reverts to standard paper mode even in
+	 this case */
+        FIXME("Trying to change only paperlength or paperwidth\n");
+	dm1->dmPublic.dmFields &= ~(DM_PAPERLENGTH | DM_PAPERWIDTH);
+	dm1->dmPublic.dmFields |= DM_PAPERSIZE;
     }
 
     if(dm2->dmPublic.dmFields & DM_SCALE) {
diff --git a/dlls/wineps/init.c b/dlls/wineps/init.c
index 9e3192c..7aaa66f 100644
--- a/dlls/wineps/init.c
+++ b/dlls/wineps/init.c
@@ -138,6 +138,94 @@
 }
 
 
+static void PSDRV_UpdateDevCaps( PSDRV_PDEVICE *physDev )
+{
+    PAGESIZE *page;
+    INT width = 0, height = 0;
+    
+    if(physDev->Devmode->dmPublic.dmFields & DM_PAPERSIZE) {
+        for(page = physDev->pi->ppd->PageSizes; page; page = page->next) {
+	    if(page->WinPage == physDev->Devmode->dmPublic.u1.s1.dmPaperSize)
+	        break;
+	}
+
+	if(!page) {
+	    FIXME("Can't find page\n");
+	    physDev->ImageableArea.left = 0;
+	    physDev->ImageableArea.right = 0;
+	    physDev->ImageableArea.bottom = 0;
+	    physDev->ImageableArea.top = 0;
+	    physDev->PageSize.cx = 0;
+	    physDev->PageSize.cy = 0;
+	} else if(page->ImageableArea) {
+	  /* physDev sizes in device units; ppd sizes in 1/72" */
+	    physDev->ImageableArea.left = page->ImageableArea->llx *
+	      physDev->logPixelsX / 72;
+	    physDev->ImageableArea.right = page->ImageableArea->urx *
+	      physDev->logPixelsX / 72;
+	    physDev->ImageableArea.bottom = page->ImageableArea->lly *
+	      physDev->logPixelsY / 72;
+	    physDev->ImageableArea.top = page->ImageableArea->ury *
+	      physDev->logPixelsY / 72;
+	    physDev->PageSize.cx = page->PaperDimension->x *
+	      physDev->logPixelsX / 72;
+	    physDev->PageSize.cy = page->PaperDimension->y *
+	      physDev->logPixelsY / 72;
+	} else {
+	    physDev->ImageableArea.left = physDev->ImageableArea.bottom = 0;
+	    physDev->ImageableArea.right = physDev->PageSize.cx =
+	      page->PaperDimension->x * physDev->logPixelsX / 72;
+	    physDev->ImageableArea.top = physDev->PageSize.cy =
+	      page->PaperDimension->y * physDev->logPixelsY / 72;
+	}
+    } else if((physDev->Devmode->dmPublic.dmFields & DM_PAPERLENGTH) &&
+	      (physDev->Devmode->dmPublic.dmFields & DM_PAPERWIDTH)) {
+      /* physDev sizes in device units; Devmode sizes in 1/10 mm */
+        physDev->ImageableArea.left = physDev->ImageableArea.bottom = 0;
+	physDev->ImageableArea.right = physDev->PageSize.cx =
+	  physDev->Devmode->dmPublic.u1.s1.dmPaperWidth *
+	  physDev->logPixelsX / 254;
+	physDev->ImageableArea.top = physDev->PageSize.cy =
+	  physDev->Devmode->dmPublic.u1.s1.dmPaperLength *
+	  physDev->logPixelsY / 254;
+    } else {
+        FIXME("Odd dmFields %lx\n", physDev->Devmode->dmPublic.dmFields);
+	physDev->ImageableArea.left = 0;
+	physDev->ImageableArea.right = 0;
+	physDev->ImageableArea.bottom = 0;
+	physDev->ImageableArea.top = 0;
+	physDev->PageSize.cx = 0;
+	physDev->PageSize.cy = 0;
+    }
+
+    TRACE("ImageableArea = %d,%d - %d,%d: PageSize = %ldx%ld\n",
+	  physDev->ImageableArea.left, physDev->ImageableArea.bottom,
+	  physDev->ImageableArea.right, physDev->ImageableArea.top,
+	  physDev->PageSize.cx, physDev->PageSize.cy);
+
+    /* these are in device units */
+    width = physDev->ImageableArea.right - physDev->ImageableArea.left;
+    height = physDev->ImageableArea.top - physDev->ImageableArea.bottom;
+
+    if(physDev->Devmode->dmPublic.u1.s1.dmOrientation == DMORIENT_PORTRAIT) {
+        physDev->horzRes = width;
+        physDev->vertRes = height;
+    } else {
+        physDev->horzRes = height;
+        physDev->vertRes = width;
+    }
+
+    /* these are in mm */
+    physDev->horzSize = (physDev->horzRes * 25.4) / physDev->logPixelsX;
+    physDev->vertSize = (physDev->vertRes * 25.4) / physDev->logPixelsY;
+
+    TRACE("devcaps: horzSize = %dmm, vertSize = %dmm, "
+	  "horzRes = %d, vertRes = %d\n",
+	  physDev->horzSize, physDev->vertSize,
+	  physDev->horzRes, physDev->vertRes);
+}
+
+
 /**********************************************************************
  *	     PSDRV_CreateDC
  */
@@ -146,8 +234,6 @@
 {
     PSDRV_PDEVICE *physDev;
     PRINTERINFO *pi;
-    PAGESIZE *page;
-    INT width = 0, height = 0;
 
     /* If no device name was specified, retrieve the device name
      * from the DEVMODE structure from the DC's physDev.
@@ -186,70 +272,26 @@
     
     memcpy( physDev->Devmode, pi->Devmode, sizeof(PSDRV_DEVMODEA) );
 
-    if(initData) {
-        PSDRV_MergeDevmodes(physDev->Devmode, (PSDRV_DEVMODEA *)initData, pi);
-    }
-
     physDev->logPixelsX = physDev->pi->ppd->DefaultResolution;
     physDev->logPixelsY = physDev->pi->ppd->DefaultResolution;
 
-    for(page = pi->ppd->PageSizes; page; page = page->next) {
-        if(page->WinPage == physDev->Devmode->dmPublic.u1.s1.dmPaperSize)
-	    break;
-    }
-
-    if(!page) {
-        FIXME("Can't find page\n");
-	physDev->PageSize.left = 0;
-	physDev->PageSize.right = 0;
-	physDev->PageSize.bottom = 0;
-        physDev->PageSize.top = 0;
-    } else if(page->ImageableArea) {  /* PageSize is in device units */
-        physDev->PageSize.left = page->ImageableArea->llx * physDev->logPixelsX / 72;
-        physDev->PageSize.right = page->ImageableArea->urx * physDev->logPixelsX / 72;
-        physDev->PageSize.bottom = page->ImageableArea->lly * physDev->logPixelsY / 72;
-        physDev->PageSize.top = page->ImageableArea->ury * physDev->logPixelsY / 72;
-    } else {
-        physDev->PageSize.left = physDev->PageSize.bottom = 0;
-        physDev->PageSize.right = page->PaperDimension->x * physDev->logPixelsX / 72;
-        physDev->PageSize.top = page->PaperDimension->y * physDev->logPixelsY / 72;
-    }
-    TRACE("PageSize = (%d,%d - %d,%d)\n",physDev->PageSize.left, physDev->PageSize.bottom, physDev->PageSize.right, physDev->PageSize.top);
-
-    /* these are in device units */
-    width = physDev->PageSize.right - physDev->PageSize.left;
-    height = physDev->PageSize.top - physDev->PageSize.bottom;
-
-    if(physDev->Devmode->dmPublic.u1.s1.dmOrientation == DMORIENT_PORTRAIT) {
-        physDev->horzRes = width;
-        physDev->vertRes = height;
-    } else {
-        physDev->horzRes = height;
-        physDev->vertRes = width;
-    }
-
-    /* these are in mm */
-    physDev->horzSize = (physDev->horzRes * 25.4) / physDev->logPixelsX;
-    physDev->vertSize = (physDev->vertRes * 25.4) / physDev->logPixelsY;
-
-    TRACE("devcaps: horzSize = %dmm, vertSize = %dmm, "
-	  "horzRes = %d, vertRes = %d\n",
-	  physDev->horzSize, physDev->vertSize,
-	  physDev->horzRes, physDev->vertRes);
-
-    /* etc */
-
-    dc->hVisRgn = CreateRectRgn(0, 0, physDev->horzRes, physDev->vertRes);
-    dc->hFont = PSDRV_DefaultFont;
-
     if (!output) output = "LPT1:";  /* HACK */
     physDev->job.output = HeapAlloc( PSDRV_Heap, 0, strlen(output)+1 );
     strcpy( physDev->job.output, output );
     physDev->job.hJob = 0;
+
+    if(initData) {
+        PSDRV_MergeDevmodes(physDev->Devmode, (PSDRV_DEVMODEA *)initData, pi);
+    }
+
+    PSDRV_UpdateDevCaps(physDev);
+    dc->hVisRgn = CreateRectRgn(0, 0, physDev->horzRes, physDev->vertRes);
+    dc->hFont = PSDRV_DefaultFont;
     return TRUE;
 }
 
 
+
 /**********************************************************************
  *	     PSDRV_DeleteDC
  */
@@ -266,76 +308,16 @@
 }
 
 
-/***********************************************************************
- *           get_phys_page_size
- *
- * Helper function to compute PHYSICALWIDTH and PHYSICALHEIGHT dev caps.
+/**********************************************************************
+ *	     ResetDC   (WINEPS.@)
  */
-static void get_phys_page_size( const PSDRV_PDEVICE *pdev, POINT *p )
+HDC PSDRV_ResetDC( PSDRV_PDEVICE *physDev, const DEVMODEA *lpInitData )
 {
-    p->x = p->y = 0;
-
-    if ((pdev->Devmode->dmPublic.dmFields & DM_PAPERSIZE) != 0 &&
-        pdev->Devmode->dmPublic.u1.s1.dmPaperSize != 0)
-    {
-        PAGESIZE *page = pdev->pi->ppd->PageSizes;
-
-        while (page != NULL)
-        {
-            if (page->WinPage == pdev->Devmode->dmPublic.u1.s1.dmPaperSize)
-                break;
-            page = page->next;
-        }
-
-        if (page == NULL)
-        {
-            ERR("No entry for papersize %u in PPD file for '%s'\n",
-                pdev->Devmode->dmPublic.u1.s1.dmPaperSize,
-                pdev->pi->FriendlyName);
-            return;
-        }
-
-        TRACE("Found '%s' for paper size %u\n", page->FullName,
-              pdev->Devmode->dmPublic.u1.s1.dmPaperSize);
-
-        p->x = page->PaperDimension->x * pdev->logPixelsX / 72;
-        p->y = page->PaperDimension->y * pdev->logPixelsY / 72;
-
-        TRACE("%fx%f PostScript points = %lix%li device units\n",
-              page->PaperDimension->x, page->PaperDimension->y,
-              p->x, p->y);
+    if(lpInitData) {
+        PSDRV_MergeDevmodes(physDev->Devmode, (PSDRV_DEVMODEA *)lpInitData, physDev->pi);
+        PSDRV_UpdateDevCaps(physDev);
     }
-
-    /* These are in tenths of a millimeter */
-    if ((pdev->Devmode->dmPublic.dmFields & DM_PAPERWIDTH) != 0 &&
-        pdev->Devmode->dmPublic.u1.s1.dmPaperWidth != 0)
-    {
-        p->x = (pdev->Devmode->dmPublic.u1.s1.dmPaperWidth *
-                pdev->logPixelsX) / 254;
-        TRACE("dmPaperWidth = %li device units\n", p->x);
-    }
-
-    if ((pdev->Devmode->dmPublic.dmFields & DM_PAPERLENGTH) != 0 &&
-        pdev->Devmode->dmPublic.u1.s1.dmPaperLength != 0)
-    {
-        p->y = (pdev->Devmode->dmPublic.u1.s1.dmPaperLength *
-                pdev->logPixelsY) / 254;
-        TRACE("dmPaperLength = %li device units\n", p->y);
-    }
-
-    if (p->x == 0 || p->y == 0)
-    {
-        ERR("Paper size not properly set for '%s'\n", pdev->pi->FriendlyName);
-        return;
-    }
-
-    if ((pdev->Devmode->dmPublic.dmFields & DM_ORIENTATION) != 0 &&
-        pdev->Devmode->dmPublic.u1.s1.dmOrientation == DMORIENT_LANDSCAPE)
-    {
-        INT temp = p->y;
-        p->y = p->x;
-        p->x = temp;
-    }
+    return physDev->hdc;
 }
 
 
@@ -344,8 +326,6 @@
  */
 INT PSDRV_GetDeviceCaps( PSDRV_PDEVICE *physDev, INT cap )
 {
-    POINT pt;
-
     switch(cap)
     {
     case DRIVERVERSION:
@@ -386,7 +366,7 @@
         return (PC_POLYGON | PC_RECTANGLE | PC_WINDPOLYGON | PC_SCANLINE |
                 PC_WIDE | PC_STYLED | PC_WIDESTYLED | PC_INTERIORS);
     case TEXTCAPS:
-        return TC_CR_ANY; /* psdrv 0x59f7 */
+        return TC_CR_ANY | TC_VA_ABLE; /* psdrv 0x59f7 */
     case CLIPCAPS:
         return CP_RECTANGLE;
     case RASTERCAPS:
@@ -411,13 +391,29 @@
     case COLORRES:
         return 0;
     case PHYSICALWIDTH:
-        get_phys_page_size( physDev, &pt );
-        return pt.x;
+        return (physDev->Devmode->dmPublic.u1.s1.dmOrientation == DMORIENT_LANDSCAPE) ?
+	  physDev->PageSize.cy : physDev->PageSize.cx;
     case PHYSICALHEIGHT:
-        get_phys_page_size( physDev, &pt );
-        return pt.y;
+        return (physDev->Devmode->dmPublic.u1.s1.dmOrientation == DMORIENT_LANDSCAPE) ?
+	  physDev->PageSize.cx : physDev->PageSize.cy;
     case PHYSICALOFFSETX:
+      if(physDev->Devmode->dmPublic.u1.s1.dmOrientation == DMORIENT_LANDSCAPE) {
+          if(physDev->pi->ppd->LandscapeOrientation == -90)
+	      return physDev->PageSize.cy - physDev->ImageableArea.top;
+	  else
+	      return physDev->ImageableArea.bottom;
+      }
+      return physDev->ImageableArea.left;
+
     case PHYSICALOFFSETY:
+      if(physDev->Devmode->dmPublic.u1.s1.dmOrientation == DMORIENT_LANDSCAPE) {
+          if(physDev->pi->ppd->LandscapeOrientation == -90)
+	      return physDev->PageSize.cx - physDev->ImageableArea.right;
+	  else
+	      return physDev->ImageableArea.left;
+      }
+      return physDev->PageSize.cy - physDev->ImageableArea.top;
+
     case SCALINGFACTORX:
     case SCALINGFACTORY:
     case VREFRESH:
diff --git a/dlls/wineps/ps.c b/dlls/wineps/ps.c
index d0c30e6..d82faf5 100644
--- a/dlls/wineps/ps.c
+++ b/dlls/wineps/ps.c
@@ -237,10 +237,10 @@
     
     /* BBox co-ords are in default user co-ord system so urx < ury even in
        landscape mode */
-    llx = physDev->PageSize.left * 72.0 / physDev->logPixelsX;
-    lly = physDev->PageSize.bottom * 72.0 / physDev->logPixelsY;
-    urx = physDev->PageSize.right * 72.0 / physDev->logPixelsX;
-    ury = physDev->PageSize.top * 72.0 / physDev->logPixelsY;
+    llx = physDev->ImageableArea.left * 72.0 / physDev->logPixelsX;
+    lly = physDev->ImageableArea.bottom * 72.0 / physDev->logPixelsY;
+    urx = physDev->ImageableArea.right * 72.0 / physDev->logPixelsX;
+    ury = physDev->ImageableArea.top * 72.0 / physDev->logPixelsY;
 
     if(physDev->Devmode->dmPublic.u1.s1.dmOrientation == DMORIENT_LANDSCAPE) {
 	orient = "Landscape";
@@ -346,17 +346,17 @@
 
     if(physDev->Devmode->dmPublic.u1.s1.dmOrientation == DMORIENT_LANDSCAPE) {
         if(physDev->pi->ppd->LandscapeOrientation == -90) {
-	    xtrans = physDev->PageSize.right;
-	    ytrans = physDev->PageSize.top;
+	    xtrans = physDev->ImageableArea.right;
+	    ytrans = physDev->ImageableArea.top;
 	    rotation = 90;
 	} else {
-	    xtrans = physDev->PageSize.left;
-	    ytrans = physDev->PageSize.bottom;
+	    xtrans = physDev->ImageableArea.left;
+	    ytrans = physDev->ImageableArea.bottom;
 	    rotation = -90;
 	}
     } else {
-        xtrans = physDev->PageSize.left;
-	ytrans = physDev->PageSize.top;
+        xtrans = physDev->ImageableArea.left;
+	ytrans = physDev->ImageableArea.top;
 	rotation = 0;
     }
 
diff --git a/dlls/wineps/psdrv.h b/dlls/wineps/psdrv.h
index 675fd58..3a6ff72 100644
--- a/dlls/wineps/psdrv.h
+++ b/dlls/wineps/psdrv.h
@@ -277,7 +277,12 @@
     JOB			job;
     PSDRV_DEVMODEA	*Devmode;
     PRINTERINFO		*pi;
-    RECT                PageSize;      /* Imageable area in device co-ords */
+    SIZE                PageSize;      /* Physical page size in device units */
+    RECT                ImageableArea; /* Imageable area in device units */
+                                       /* NB both PageSize and ImageableArea
+					  are not rotated in landscape mode,
+					  so PageSize.cx is generally
+					  < PageSize.cy */
     int                 horzRes;       /* device caps */
     int                 vertRes;
     int                 horzSize;
diff --git a/dlls/wineps/wineps.spec b/dlls/wineps/wineps.spec
index a8df866..be7bbb8 100644
--- a/dlls/wineps/wineps.spec
+++ b/dlls/wineps/wineps.spec
@@ -38,6 +38,7 @@
 @ cdecl Polygon(ptr ptr long) PSDRV_Polygon
 @ cdecl Polyline(ptr ptr long) PSDRV_Polyline
 @ cdecl Rectangle(ptr long long long long) PSDRV_Rectangle
+@ cdecl ResetDC(ptr ptr) PSDRV_ResetDC
 @ cdecl RoundRect(ptr long long long long long long) PSDRV_RoundRect
 @ cdecl SelectBitmap(ptr long) PSDRV_SelectBitmap
 @ cdecl SelectBrush(ptr long) PSDRV_SelectBrush