Back to index

lightning-sunbird  0.9+nobinonly
nsDeviceContextOS2.cpp
Go to the documentation of this file.
00001 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-
00002  *
00003  * ***** BEGIN LICENSE BLOCK *****
00004  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00005  *
00006  * The contents of this file are subject to the Mozilla Public License Version
00007  * 1.1 (the "License"); you may not use this file except in compliance with
00008  * the License. You may obtain a copy of the License at
00009  * http://www.mozilla.org/MPL/
00010  *
00011  * Software distributed under the License is distributed on an "AS IS" basis,
00012  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00013  * for the specific language governing rights and limitations under the
00014  * License.
00015  *
00016  * The Original Code is the Mozilla OS/2 libraries.
00017  *
00018  * The Initial Developer of the Original Code is
00019  * John Fairhurst, <john_fairhurst@iname.com>.
00020  * Portions created by the Initial Developer are Copyright (C) 1999
00021  * the Initial Developer. All Rights Reserved.
00022  *
00023  * Contributor(s):
00024  *   Henry Sobotka <sobotka@axess.com> 2OOO/O2 update
00025  *   IBM Corp.
00026  *
00027  * Alternatively, the contents of this file may be used under the terms of
00028  * either of the GNU General Public License Version 2 or later (the "GPL"),
00029  * or the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00030  * in which case the provisions of the GPL or the LGPL are applicable instead
00031  * of those above. If you wish to allow use of your version of this file only
00032  * under the terms of either the GPL or the LGPL, and not to allow others to
00033  * use your version of this file under the terms of the MPL, indicate your
00034  * decision by deleting the provisions above and replace them with the notice
00035  * and other provisions required by the GPL or the LGPL. If you do not delete
00036  * the provisions above, a recipient may use your version of this file under
00037  * the terms of any one of the MPL, the GPL or the LGPL.
00038  *
00039  * ***** END LICENSE BLOCK ***** */
00040 
00041 #include "nsDeviceContextOS2.h"
00042 #include "nsRenderingContextOS2.h"
00043 #include "nsDeviceContextSpecOS2.h"
00044 #include "nsIServiceManager.h"
00045 #include "nsCOMPtr.h"
00046 #include "nsIScreenManager.h"
00047 #include "nsIScreen.h"
00048 
00049 #include "nsHashTable.h" // For CreateFontAliasTable()
00050 
00051 #include "nsGfxDefs.h"
00052 #include "nsIPref.h"
00053 
00054 #include "nsOS2Uni.h"
00055 #include "nsPaletteOS2.h"
00056 
00057 #define NOT_SETUP 0x33
00058 static PRBool gIsWarp4 = NOT_SETUP;
00059 
00060 PRUint32 nsDeviceContextOS2::sNumberOfScreens = 0;
00061 nscoord nsDeviceContextOS2::mDpi = 120;
00062 
00063 nsDeviceContextOS2 :: nsDeviceContextOS2()
00064   : DeviceContextImpl()
00065 {
00066   mSurface = NULL;
00067   mIsPaletteDevice = PR_FALSE;
00068   mPrintDC = NULL;
00069   mWidth = -1;
00070   mHeight = -1;
00071   mSpec = nsnull;
00072   mCachedClientRect = PR_FALSE;
00073   mCachedFullRect = PR_FALSE;
00074   mSupportsRasterFonts = PR_FALSE;
00075   mPrintingStarted = PR_FALSE;
00076 #ifdef XP_OS2
00077   mPrintState = nsPrintState_ePreBeginDoc;
00078 #endif
00079 
00080   // The first time in we initialize gIsWarp4 flag
00081   if (NOT_SETUP == gIsWarp4) {
00082     unsigned long ulValues[2];
00083     DosQuerySysInfo( QSV_VERSION_MAJOR, QSV_VERSION_MINOR,
00084                      ulValues, sizeof(ulValues));
00085     gIsWarp4 = (ulValues[0] >= 20) && (ulValues[1] >= 40);
00086   }
00087 }
00088 
00089 nsDeviceContextOS2::~nsDeviceContextOS2()
00090 {
00091   if(mPrintDC)
00092   {
00093     GFX (::GpiDestroyPS (mPrintPS), FALSE);
00094     ::DevCloseDC(mPrintDC);
00095   } else {
00096     nsresult rv;
00097     nsCOMPtr<nsIPref> prefs = do_GetService(NS_PREF_CONTRACTID, &rv);
00098     if (NS_SUCCEEDED(rv)) {
00099       prefs->UnregisterCallback("layout.css.dpi",
00100                                 prefChanged, (void *)this);
00101     }
00102   }
00103   NS_IF_RELEASE(mSpec);
00104 }
00105 
00106 nsresult nsDeviceContextOS2::Init( nsNativeWidget aWidget)
00107 {
00108   mWidget = aWidget;
00109 
00110   CommonInit(::WinOpenWindowDC((HWND)aWidget));
00111 
00112   static int initialized = 0;
00113   PRInt32 prefVal = -1;
00114   if (!initialized) {
00115     initialized = 1;
00116 
00117     // Set prefVal the value of the preference
00118     // "layout.css.dpi"
00119     // or -1 if we can't get it.
00120     // If it's negative, we pretend it's not set.
00121     // If it's 0, it means force use of the operating system's logical
00122     // resolution.
00123     // If it's positive, we use it as the logical resolution
00124     nsresult res;
00125 
00126     nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID, &res));
00127     if (NS_SUCCEEDED(res) && prefs) {
00128       res = prefs->GetIntPref("layout.css.dpi", &prefVal);
00129       if (NS_FAILED(res)) {
00130         prefVal = -1;
00131       }
00132       prefs->RegisterCallback("layout.css.dpi", prefChanged,
00133                               (void *)this);
00134     }
00135 
00136     SetDPI(prefVal);
00137   } else {
00138     SetDPI(mDpi); // to setup p2t and t2p
00139   }
00140 
00141   return NS_OK;
00142 }
00143 
00144 // This version of Init() is called when creating a print DC
00145 nsresult nsDeviceContextOS2::Init( nsNativeDeviceContext aContext,
00146                                    nsIDeviceContext *aOrigContext)
00147 {
00148   float origscale, newscale;
00149   float t2d, a2d;
00150 
00151   mPrintDC = (HDC)aContext;
00152 
00153   NS_ASSERTION( mPrintDC, "!ERROR! - Received empty DC for printer");
00154 
00155 #ifdef XP_OS2
00156   // Create a print PS now.  This is necessary 'cos we need it from
00157   // odd places to do font-y things, where the only common reference
00158   // point is this DC.  We can't just create a new PS because only one
00159   // PS can be associated with a given DC, and we can't get that PS from
00160   // the DC (really?).  And it would be slow :-)
00161   SIZEL sizel = { 0 , 0 };
00162   mPrintPS = GFX (::GpiCreatePS ( 0/*hab*/, mPrintDC, &sizel, 
00163                   PU_PELS | GPIT_MICRO | GPIA_ASSOC), GPI_ERROR);
00164 #endif
00165 
00166   CommonInit( mPrintDC);
00167 
00168   long dpi;
00169   GFX (::DevQueryCaps(mPrintDC, CAPS_VERTICAL_FONT_RES, 1, &dpi), FALSE);
00170 
00171   mPixelsToTwips = ((float)NSIntPointsToTwips(72)) / ((float)dpi);
00172   mTwipsToPixels = 1.0 / mPixelsToTwips;
00173 
00174   newscale = TwipsToDevUnits();
00175 // On OS/2, origscale can be different based on the video resolution.
00176 // On 640x480, it's 1/15, on everything else it is 1/12.
00177 // For consistent printing, 1/15 is the correct value to use.
00178 // It is the closest to 4.x and to Windows.
00179 //  origscale = aOrigContext->TwipsToDevUnits();
00180   origscale = 1.0/15.0;
00181 
00182   mCPixelScale = newscale / origscale;
00183 
00184   t2d = aOrigContext->TwipsToDevUnits();
00185   a2d = aOrigContext->AppUnitsToDevUnits();
00186 
00187   mAppUnitsToDevUnits = (a2d / t2d) * mTwipsToPixels;
00188   mDevUnitsToAppUnits = 1.0f / mAppUnitsToDevUnits;
00189 
00190 #ifdef XP_OS2
00191   HCINFO hcinfo;
00192   PrnQueryHardcopyCaps( mPrintDC, &hcinfo);
00193   mWidth = hcinfo.xPels;
00194   mHeight = hcinfo.yPels;
00195   // XXX hsb says there are margin problems, must be from here...
00196 #ifdef DEBUG
00197   printf( "Got surface of size %d x %d pixels (%d Kb)\n", mWidth, mHeight, mWidth * mHeight * mDepth / 8 / 1024);
00198   printf( "mCPixelScale = %f\n", mCPixelScale);
00199 #endif
00200 
00201 #endif
00202 
00203   return NS_OK;
00204 }
00205 
00206 void nsDeviceContextOS2 :: CommonInit(HDC aDC)
00207 {
00208   LONG alArray[CAPS_DEVICE_POLYSET_POINTS];
00209 
00210   GFX (::DevQueryCaps(aDC, CAPS_FAMILY, CAPS_DEVICE_POLYSET_POINTS, alArray), FALSE);
00211 
00212   mDepth = alArray[CAPS_COLOR_BITCOUNT];
00213   mIsPaletteDevice = ((alArray[CAPS_ADDITIONAL_GRAPHICS] & CAPS_PALETTE_MANAGER) == CAPS_PALETTE_MANAGER);
00214 
00215   mWidth = alArray[CAPS_WIDTH];
00216   mHeight = alArray[CAPS_HEIGHT];
00217 
00218   if (alArray[CAPS_TECHNOLOGY] == CAPS_TECH_RASTER_DISPLAY)
00219   {
00220     // init the screen manager and compute our client rect based on the
00221     // screen objects. We'll save the result 
00222     nsresult ignore;
00223     mScreenManager = do_GetService("@mozilla.org/gfx/screenmanager;1", &ignore);   
00224     if ( !sNumberOfScreens )
00225       mScreenManager->GetNumberOfScreens(&sNumberOfScreens);
00226     mSupportsRasterFonts = !!(alArray[CAPS_RASTER_CAPS] & CAPS_RASTER_FONTS);
00227   } // if this dc is not a print device
00228 
00229   DeviceContextImpl::CommonInit();
00230 }
00231 
00232 void
00233 nsDeviceContextOS2 :: ComputeClientRectUsingScreen ( nsRect* outRect )
00234 {
00235   if ( !mCachedClientRect ) {
00236     nsCOMPtr<nsIScreen> screen;
00237     FindScreen ( getter_AddRefs(screen) );
00238     if ( screen ) {
00239       PRInt32 x, y, width, height;
00240       screen->GetAvailRect ( &x, &y, &width, &height );
00241     
00242       // convert to device units
00243       outRect->y = NSToIntRound(y * mDevUnitsToAppUnits);
00244       outRect->x = NSToIntRound(x * mDevUnitsToAppUnits);
00245       outRect->width = NSToIntRound(width * mDevUnitsToAppUnits);
00246       outRect->height = NSToIntRound(height * mDevUnitsToAppUnits);
00247 
00248       mCachedClientRect = PR_TRUE;
00249       mClientRect = *outRect;
00250     }
00251   }
00252   else
00253     *outRect = mClientRect;
00254 
00255 } // ComputeClientRectUsingScreen
00256 
00257 
00258 void
00259 nsDeviceContextOS2 :: ComputeFullAreaUsingScreen ( nsRect* outRect )
00260 {
00261   if ( !mCachedFullRect ) {
00262     nsCOMPtr<nsIScreen> screen;
00263     FindScreen ( getter_AddRefs(screen) );
00264     if ( screen ) {
00265       PRInt32 x, y, width, height;
00266       screen->GetRect ( &x, &y, &width, &height );
00267     
00268       // convert to device units
00269       outRect->y = NSToIntRound(y * mDevUnitsToAppUnits);
00270       outRect->x = NSToIntRound(x * mDevUnitsToAppUnits);
00271       outRect->width = NSToIntRound(width * mDevUnitsToAppUnits);
00272       outRect->height = NSToIntRound(height * mDevUnitsToAppUnits);
00273 
00274       mWidth = width;
00275       mHeight = height;
00276       mCachedFullRect = PR_TRUE;
00277     }
00278   }
00279   else {
00280       outRect->y = 0;
00281       outRect->x = 0;
00282       outRect->width = NSToIntRound(mWidth * mDevUnitsToAppUnits);
00283       outRect->height = NSToIntRound(mHeight * mDevUnitsToAppUnits);
00284   }
00285  
00286 } // ComputeFullRectUsingScreen
00287 
00288 
00289 //
00290 // FindScreen
00291 //
00292 // Determines which screen intersects the largest area of the given surface.
00293 //
00294 void
00295 nsDeviceContextOS2 :: FindScreen ( nsIScreen** outScreen )
00296 {
00297   // optimize for the case where we only have one monitor.
00298   static nsCOMPtr<nsIScreen> sPrimaryScreen;
00299   if ( !sPrimaryScreen && mScreenManager )
00300     mScreenManager->GetPrimaryScreen ( getter_AddRefs(sPrimaryScreen) );  
00301   NS_IF_ADDREF(*outScreen = sPrimaryScreen.get());
00302   return;
00303 } // FindScreen
00304 
00305 /* OS2TODO - NOT PORTED */
00306 // Create a rendering context against our hdc for a printer
00307 nsresult nsDeviceContextOS2::CreateRenderingContext( nsIRenderingContext *&aContext)
00308 {
00309 #ifdef NS_PRINT_PREVIEW
00310    // Defer to Alt when there is one
00311   if (mAltDC && ((mUseAltDC & kUseAltDCFor_CREATERC_PAINT) || (mUseAltDC & kUseAltDCFor_CREATERC_REFLOW))) {
00312       return mAltDC->CreateRenderingContext(aContext);  
00313   }
00314 #endif
00315 
00316    NS_ASSERTION( mPrintDC, "CreateRenderingContext for non-print DC");
00317 
00318    nsIRenderingContext *pContext = new nsRenderingContextOS2;
00319    if (!pContext)
00320      return NS_ERROR_OUT_OF_MEMORY;
00321    NS_ADDREF(pContext);
00322 
00323    nsPrintSurface *surf = new nsPrintSurface;
00324    if (!surf)
00325      return NS_ERROR_OUT_OF_MEMORY;
00326 
00327    surf->Init( mPrintPS, mWidth, mHeight, 0);
00328 
00329    nsresult rc = pContext->Init(this, surf);
00330 
00331    if( NS_OK != rc)
00332    {
00333       delete surf;
00334       NS_IF_RELEASE(pContext);
00335    }
00336 
00337    aContext = pContext;
00338 
00339    return rc;
00340 }
00341 
00342 NS_IMETHODIMP nsDeviceContextOS2 :: SupportsNativeWidgets(PRBool &aSupportsWidgets)
00343 {
00344   if (nsnull == mPrintDC)
00345     aSupportsWidgets = PR_TRUE;
00346   else
00347     aSupportsWidgets = PR_FALSE;
00348 
00349   return NS_OK;
00350 }
00351 
00352 NS_IMETHODIMP nsDeviceContextOS2 :: GetScrollBarDimensions(float &aWidth, float &aHeight) const
00353 {
00354   float scale = mCPixelScale;
00355   aWidth = ::WinQuerySysValue( HWND_DESKTOP, SV_CXVSCROLL) * mDevUnitsToAppUnits * scale;
00356   aHeight = ::WinQuerySysValue( HWND_DESKTOP, SV_CYHSCROLL) * mDevUnitsToAppUnits * scale;
00357   return NS_OK;
00358 }
00359 
00360 nscolor GetSysColorInfo(int iSysColor) 
00361 {
00362   long lColor = ::WinQuerySysColor( HWND_DESKTOP, iSysColor, 0);
00363   RGB2 *pRGB2 = (RGB2*) &lColor;
00364   return NS_RGB( pRGB2->bRed, pRGB2->bGreen, pRGB2->bBlue);
00365 }
00366 
00367 /* Helper function to query font from INI file */
00368 
00369 void QueryFontFromINI(char* fontType, char* fontName, ULONG ulLength)
00370 {
00371   ULONG ulMaxNameL = ulLength;
00372 
00373   /* We had to switch to using PrfQueryProfileData because */
00374   /* some users have binary font data in their INI files */
00375   BOOL rc = PrfQueryProfileData(HINI_USER, "PM_SystemFonts", fontType,
00376                                 fontName, &ulMaxNameL);
00377   /* If there was no entry in the INI, default to something */
00378   if (rc == FALSE) {
00379     /* Different values for DBCS vs. SBCS */
00380     if (!IsDBCS()) {
00381       /* WarpSans is only available on Warp 4 and above */
00382       if (gIsWarp4)
00383         strcpy(fontName, "9.WarpSans");
00384       else
00385         strcpy(fontName, "8.Helv");
00386     } else {
00387       /* WarpSans is only available on Warp 4 and above */
00388       if (gIsWarp4)
00389         strcpy(fontName, "9.WarpSans Combined");
00390       else
00391         strcpy(fontName, "10.Helv Combined");
00392     }
00393   } else {
00394     /* null terminate fontname */
00395     fontName[ulMaxNameL] = '\0';
00396   }
00397 }
00398 
00399 
00400 nsresult GetSysFontInfo(nsSystemFontID aID, nsFont* aFont) 
00401 {
00402   char szFontNameSize[MAXNAMEL];
00403 
00404   switch (aID)
00405   {
00406     case eSystemFont_Icon: 
00407       QueryFontFromINI("IconText", szFontNameSize, MAXNAMEL);
00408       break;
00409 
00410     case eSystemFont_Menu: 
00411       QueryFontFromINI("Menus", szFontNameSize, MAXNAMEL);
00412       break;
00413 
00414     case eSystemFont_Caption: 
00415 
00416     case eSystemFont_MessageBox: 
00417 
00418     case eSystemFont_SmallCaption: 
00419 
00420     case eSystemFont_StatusBar: 
00421     case eSystemFont_Tooltips: 
00422 
00423     case eSystemFont_Widget:
00424 
00425     case eSystemFont_Window:      // css3
00426     case eSystemFont_Document:
00427     case eSystemFont_Workspace:
00428     case eSystemFont_Desktop:
00429     case eSystemFont_Info:
00430     case eSystemFont_Dialog:
00431     case eSystemFont_Button:
00432     case eSystemFont_PullDownMenu:
00433     case eSystemFont_List:
00434     case eSystemFont_Field:
00435       QueryFontFromINI("WindowText", szFontNameSize, MAXNAMEL);
00436       break;
00437   } // switch 
00438 
00439   int pointSize;
00440   char *szFacename;
00441 
00442   pointSize = atoi(szFontNameSize);
00443   szFacename = strchr(szFontNameSize, '.');
00444 
00445   if ((pointSize == 0) || (!szFacename) || (*(szFacename++) == '\0')) {
00446      return NS_ERROR_FAILURE;
00447   }
00448 
00449 #ifdef OLDCODE
00450   PRUnichar name[FACESIZE];
00451   name[0] = 0;
00452   MultiByteToWideChar(0, szFacename,
00453                       strlen(szFacename) + 1, name, sizeof(name)/sizeof(name[0]));
00454 #endif
00455   aFont->name.AssignWithConversion(szFacename);
00456 
00457   // Do Style
00458   aFont->style = NS_FONT_STYLE_NORMAL;
00459 #if 0
00460   if (ptrLogFont->lfItalic)
00461   {
00462     aFont->style = NS_FONT_STYLE_ITALIC;
00463   }
00464 #endif
00465   // XXX What about oblique?
00466 
00467   aFont->variant = NS_FONT_VARIANT_NORMAL;
00468 
00469   // Do Weight
00470 #if 0
00471   aFont->weight = (ptrLogFont->lfWeight == FW_BOLD ? 
00472             NS_FONT_WEIGHT_BOLD : NS_FONT_WEIGHT_NORMAL);
00473 #else
00474   aFont->weight = NS_FONT_WEIGHT_NORMAL;
00475 #endif
00476 
00477   // Do decorations
00478   aFont->decorations = NS_FONT_DECORATION_NONE;
00479 #if 0
00480   if (ptrLogFont->lfUnderline)
00481   {
00482     aFont->decorations |= NS_FONT_DECORATION_UNDERLINE;
00483   }
00484   if (ptrLogFont->lfStrikeOut)
00485   {
00486     aFont->decorations |= NS_FONT_DECORATION_LINE_THROUGH;
00487   }
00488 #endif
00489 
00490   // Do Size
00491   aFont->size = NSIntPointsToTwips(pointSize);
00492 
00493   aFont->systemFont = PR_TRUE;
00494 
00495   return NS_OK;
00496 }
00497 
00498 NS_IMETHODIMP nsDeviceContextOS2 :: GetSystemFont(nsSystemFontID aID, nsFont *aFont) const
00499 {
00500   nsresult status = NS_OK;
00501 
00502   switch (aID) {
00503     case eSystemFont_Caption: 
00504     case eSystemFont_Icon: 
00505     case eSystemFont_Menu: 
00506     case eSystemFont_MessageBox: 
00507     case eSystemFont_SmallCaption: 
00508     case eSystemFont_StatusBar: 
00509     case eSystemFont_Tooltips: 
00510     case eSystemFont_Widget:
00511 
00512     case eSystemFont_Window:      // css3
00513     case eSystemFont_Document:
00514     case eSystemFont_Workspace:
00515     case eSystemFont_Desktop:
00516     case eSystemFont_Info:
00517     case eSystemFont_Dialog:
00518     case eSystemFont_Button:
00519     case eSystemFont_PullDownMenu:
00520     case eSystemFont_List:
00521     case eSystemFont_Field:
00522     {
00523       status = GetSysFontInfo(aID, aFont);
00524       break;
00525     }
00526   }
00527 
00528   return status;
00529 }
00530 
00531 NS_IMETHODIMP nsDeviceContextOS2 :: CheckFontExistence(const nsString& aFontName)
00532 {
00533   HPS     hps = NULL;
00534 
00535   if (NULL != mPrintDC){
00536     hps = mPrintPS;
00537   } else {
00538     hps = ::WinGetPS((HWND)mWidget);
00539   }
00540 
00541   nsAutoCharBuffer fontName;
00542   PRInt32 fontNameLength;
00543   WideCharToMultiByte(0, aFontName.get(), aFontName.Length(),
00544                       fontName, fontNameLength);
00545 
00546   long lWant = 0;
00547   long lFonts = GFX (::GpiQueryFonts(hps, QF_PUBLIC | QF_PRIVATE,
00548                                      fontName.get(), &lWant, 0, 0),
00549                      GPI_ALTERROR);
00550 
00551   if (NULL == mPrintDC)
00552     ::WinReleasePS(hps);
00553 
00554   if (lFonts > 0)
00555     return NS_OK;
00556   else
00557     return NS_ERROR_FAILURE;
00558 }
00559 
00560 NS_IMETHODIMP nsDeviceContextOS2::GetDepth(PRUint32& aDepth)
00561 {
00562   aDepth = mDepth;
00563   return NS_OK;
00564 }
00565 
00566 nsresult
00567 nsDeviceContextOS2::SetDPI(PRInt32 aPrefDPI)
00568 {
00569   // Set OSVal to what the operating system thinks the logical resolution is.
00570   long OSVal;
00571   HPS ps = ::WinGetScreenPS(HWND_DESKTOP);
00572   HDC hdc = GFX (::GpiQueryDevice (ps), HDC_ERROR);
00573   GFX (::DevQueryCaps(hdc, CAPS_HORIZONTAL_FONT_RES, 1, &OSVal), FALSE);
00574   ::WinReleasePS(ps);
00575 
00576   if (aPrefDPI > 0) {
00577     // If there's a valid pref value for the logical resolution,
00578     // use it.
00579     mDpi = aPrefDPI;
00580   } else if ((aPrefDPI == 0) || (OSVal > 96)) {
00581     // Either if the pref is 0 (force use of OS value) or the OS
00582     // value is bigger than 96, use the OS value.
00583     mDpi = OSVal;
00584   } else {
00585     // if we couldn't get the pref or it's negative, and the OS
00586     // value is under 96ppi, then use 96.
00587     mDpi = 96;
00588   }
00589 
00590   int pt2t = 72;
00591 
00592   // make p2t a nice round number - this prevents rounding problems
00593   mPixelsToTwips = float(NSToIntRound(float(NSIntPointsToTwips(pt2t)) / float(mDpi)));
00594   mTwipsToPixels = 1.0f / mPixelsToTwips;
00595 
00596   // XXX need to reflow all documents
00597   return NS_OK;
00598 }
00599 
00600 int prefChanged(const char *aPref, void *aClosure)
00601 {
00602   nsDeviceContextOS2 *context = (nsDeviceContextOS2*)aClosure;
00603   nsresult rv;
00604   
00605   if (nsCRT::strcmp(aPref, "layout.css.dpi")==0) {
00606     PRInt32 dpi;
00607     nsCOMPtr<nsIPref> prefs(do_GetService(NS_PREF_CONTRACTID, &rv));
00608     rv = prefs->GetIntPref(aPref, &dpi);
00609     if (NS_SUCCEEDED(rv))
00610       context->SetDPI(dpi);
00611 
00612   }
00613   
00614   return 0;
00615 }
00616 
00617 NS_IMETHODIMP nsDeviceContextOS2 :: GetDeviceSurfaceDimensions(PRInt32 &aWidth, PRInt32 &aHeight)
00618 {
00619 #ifdef NS_PRINT_PREVIEW
00620   // Defer to Alt when there is one
00621   if (mAltDC && (mUseAltDC & kUseAltDCFor_SURFACE_DIM))
00622     return mAltDC->GetDeviceSurfaceDimensions(aWidth, aHeight);
00623 #endif
00624 
00625   if ( mSpec )
00626   {
00627     // we have a printer device
00628     aWidth = NSToIntRound(mWidth * mDevUnitsToAppUnits);
00629     aHeight = NSToIntRound(mHeight * mDevUnitsToAppUnits);
00630   }
00631   else {
00632     nsRect area;
00633     ComputeFullAreaUsingScreen ( &area );
00634     aWidth = area.width;
00635     aHeight = area.height;
00636   }
00637 
00638   return NS_OK;
00639 }
00640 
00641 NS_IMETHODIMP nsDeviceContextOS2 :: GetRect(nsRect &aRect)
00642 {
00643   if ( mSpec )
00644   {
00645     // we have a printer device
00646     aRect.x = 0;
00647     aRect.y = 0;
00648     aRect.width = NSToIntRound(mWidth * mDevUnitsToAppUnits);
00649     aRect.height = NSToIntRound(mHeight * mDevUnitsToAppUnits);
00650   }
00651   else
00652     ComputeFullAreaUsingScreen ( &aRect );
00653 
00654   return NS_OK;
00655 }
00656 
00657 
00658 NS_IMETHODIMP nsDeviceContextOS2 :: GetClientRect(nsRect &aRect)
00659 {
00660   if ( mSpec )
00661   {
00662     // we have a printer device
00663     aRect.x = 0;
00664     aRect.y = 0;
00665     aRect.width = NSToIntRound(mWidth * mDevUnitsToAppUnits);
00666     aRect.height = NSToIntRound(mHeight * mDevUnitsToAppUnits);
00667   }
00668   else
00669     ComputeClientRectUsingScreen ( &aRect );
00670 
00671   return NS_OK;
00672 }
00673 
00674 NS_IMETHODIMP nsDeviceContextOS2 :: GetDeviceContextFor(nsIDeviceContextSpec *aDevice,
00675                                                         nsIDeviceContext *&aContext)
00676 {
00677   PRTQUEUE *pq;
00678 
00679   aContext = new nsDeviceContextOS2();
00680   if(nsnull != aContext){
00681     NS_ADDREF(aContext);
00682   } else {
00683     return NS_ERROR_OUT_OF_MEMORY;
00684   }
00685  
00686   ((nsDeviceContextOS2 *)aContext)->mSpec = aDevice;
00687   NS_ADDREF(aDevice);
00688   
00689   int numCopies = 0;
00690   int printerDest = 0;
00691   char *file = nsnull;
00692 
00693   ((nsDeviceContextSpecOS2 *)aDevice)->GetPRTQUEUE(pq);
00694   ((nsDeviceContextSpecOS2 *)aDevice)->GetCopies(numCopies);
00695   ((nsDeviceContextSpecOS2 *)aDevice)->GetDestination(printerDest);
00696   if (!printerDest) 
00697      ((nsDeviceContextSpecOS2 *)aDevice)->GetPath(&file);
00698 
00699   HDC dc = PrnOpenDC(pq, "Mozilla", numCopies, printerDest, file);
00700 
00701   if (!dc) {
00702      return NS_ERROR_FAILURE; //PMERROR("DevOpenDC");
00703   } /* endif */
00704 
00705   return ((nsDeviceContextOS2 *)aContext)->Init((nsNativeDeviceContext)dc, this);
00706 }
00707 
00708 nsresult nsDeviceContextOS2::CreateFontAliasTable()
00709 {
00710    nsresult result = NS_OK;
00711 
00712    if( !mFontAliasTable)
00713    {
00714       mFontAliasTable = new nsHashtable;
00715 
00716       nsAutoString  times;              times.AssignLiteral("Times");
00717       nsAutoString  timesNewRoman;      timesNewRoman.AssignLiteral("Times New Roman");
00718       nsAutoString  timesRoman;         timesRoman.AssignLiteral("Tms Rmn");
00719       nsAutoString  arial;              arial.AssignLiteral("Arial");
00720       nsAutoString  helv;               helv.AssignLiteral("Helv");
00721       nsAutoString  helvetica;          helvetica.AssignLiteral("Helvetica");
00722       nsAutoString  courier;            courier.AssignLiteral("Courier");
00723       nsAutoString  courierNew;         courierNew.AssignLiteral("Courier New");
00724       nsAutoString  sans;               sans.AssignLiteral("Sans");
00725       nsAutoString  unicode;            unicode.AssignLiteral("Unicode");
00726       nsAutoString  timesNewRomanMT30;  timesNewRomanMT30.AssignLiteral("Times New Roman MT 30");
00727       nsAutoString  nullStr;
00728 
00729       AliasFont(times, timesNewRoman, timesRoman, PR_FALSE);
00730       AliasFont(timesRoman, timesNewRoman, times, PR_FALSE);
00731       AliasFont(timesNewRoman, timesRoman, times, PR_FALSE);
00732       AliasFont(arial, helv, helvetica, PR_FALSE);
00733       AliasFont(helvetica, helv, arial, PR_FALSE);
00734       AliasFont(courier, courierNew, nullStr, PR_TRUE);
00735       AliasFont(courierNew, courier, nullStr, PR_FALSE);
00736       AliasFont(sans, helv, arial, PR_FALSE);
00737 
00738       // Is this right?
00739       AliasFont(unicode, timesNewRomanMT30, nullStr, PR_FALSE);
00740    }
00741    return result;
00742 }
00743 
00744 // Printing ------------------------------------------------------------------
00745 nsresult nsDeviceContextOS2::PrepareDocument(PRUnichar * aTitle, PRUnichar* aPrintToFileName)
00746 {
00747   nsresult rv = NS_OK;
00748 
00749   if (NULL != mPrintDC){
00750     nsString titleStr;
00751     titleStr = aTitle;
00752     char *title = GetACPString(titleStr);
00753 
00754     PSZ pszDocName;
00755     const PSZ pszGenericDocName = "MozillaDocument";
00756 
00757     if (title) {
00758       pszDocName = title;
00759     } else {
00760       pszDocName = pszGenericDocName;
00761     } 
00762 
00763     long lDummy = 0;
00764     long lResult = ::DevEscape(mPrintDC, DEVESC_STARTDOC,
00765                                strlen(pszDocName) + 1, pszDocName,
00766                                &lDummy, NULL);
00767 
00768     mPrintingStarted = PR_TRUE;
00769 
00770     if (lResult == DEV_OK)
00771       rv = NS_OK;
00772     else
00773       rv = NS_ERROR_GFX_PRINTER_STARTDOC;
00774 
00775     if (title != nsnull) {
00776       nsMemory::Free(title);
00777     }
00778   }
00779 
00780   return rv;
00781 }
00782 
00783 nsresult nsDeviceContextOS2::BeginDocument(PRUnichar * aTitle, PRUnichar* aPrintToFileName, PRInt32 aStartPage, PRInt32 aEndPage)
00784 {
00785   // Everything is done in PrepareDocument
00786   return NS_OK;
00787 }
00788 
00789 nsresult nsDeviceContextOS2::EndDocument()
00790 {
00791   if (NULL != mPrintDC)
00792   {
00793     long   lOutCount = 2;
00794     USHORT usJobID = 0;
00795     long   lResult = ::DevEscape(mPrintDC, DEVESC_ENDDOC,
00796                                  0, NULL,
00797                                  &lOutCount, (PBYTE)&usJobID);
00798     if (lResult == DEV_OK)
00799       return NS_OK;
00800     else
00801       return NS_ERROR_GFX_PRINTER_ENDDOC;
00802   }
00803 
00804   return NS_OK;
00805 }
00806 
00807 nsresult nsDeviceContextOS2::AbortDocument()
00808 {
00809   if (NULL != mPrintDC)
00810   {
00811     long ldummy = 0;
00812     long lResult = ::DevEscape(mPrintDC, DEVESC_ABORTDOC, 0, NULL,
00813                                &ldummy, NULL);
00814     if (lResult == DEV_OK)
00815       return NS_OK;
00816     else
00817       return NS_ERROR_ABORT;
00818   }
00819 
00820   return NS_OK;
00821 }
00822 
00823 
00824 nsresult nsDeviceContextOS2::BeginPage()
00825 {
00826   if (mPrintingStarted) {
00827     mPrintingStarted = PR_FALSE;
00828     return NS_OK;
00829   }
00830 
00831   if (NULL != mPrintDC)
00832   {
00833     long lDummy = 0;
00834     long lResult = ::DevEscape(mPrintDC, DEVESC_NEWFRAME, 0, NULL,
00835                                &lDummy, NULL);
00836 
00837     if (lResult == DEV_OK)
00838       return NS_OK;
00839     else
00840       return NS_ERROR_GFX_PRINTER_STARTPAGE;
00841   }
00842 
00843   return NS_OK;
00844 
00845 }
00846 
00847 nsresult nsDeviceContextOS2::EndPage()
00848 {
00849    return NS_OK;
00850 }
00851 
00852 char* 
00853 nsDeviceContextOS2::GetACPString(const nsString& aStr)
00854 {
00855    if (aStr.Length() == 0) {
00856       return nsnull;
00857    }
00858 
00859    nsAutoCharBuffer acp;
00860    PRInt32 acpLength;
00861    WideCharToMultiByte(0, aStr.get(), aStr.Length(), acp, acpLength);
00862    return ToNewCString(nsDependentCString(acp.get()));
00863 }
00864 
00865 BOOL nsDeviceContextOS2::isPrintDC()
00866 {
00867    if ( mPrintDC == nsnull )
00868       return 0;
00869 
00870    else
00871       return 1;
00872 }
00873 PRBool nsDeviceContextOS2::SupportsRasterFonts()
00874 {
00875    return mSupportsRasterFonts;
00876 }