Logo Search packages:      
Sourcecode: wine-unstable version File versions  Download package

cmdlgtst.c

/*
 * Copyright (c) 1999-2000 Eric Williams.
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 */

/*
 * One might call this a Commdlg test jig.  Its sole function in life
 * is to call the Commdlg Common Dialogs.  The results of a call to
 * File Open or File Save are printed in the upper left corner;
 * Font adjusts the font of the printout, and Color adjusts the color
 * of the background.
 */

/*
 * Ideally it would also do event logging and be a bit less stupid
 * about displaying the results of the various requesters.  But hey,
 * it's only a first step. :-)
 */

#define NONAMELESSUNION
#define NONAMELESSSTRUCT

#include <windows.h>
#include <commdlg.h>
#include <stdio.h>
#include <string.h>
#include "cmdlgtst.h"

#include <wine/debug.h>

WINE_DEFAULT_DEBUG_CHANNEL(cmdlgtst);

/*
 * This structure is to set up flag / control associations for the custom
 * requesters.  The ft_id is the id for the control (usually generated
 * by the system) and the ft_bit is the flag bit which goes into the
 * settings longword for the various Commdlg structures.  It is assumed
 * that all flags fit in an unsigned long and that all bits are in fact
 * one bit.
 */

/*
 * The array of entries is terminated by {IDOK, 0}; the assumption is that
 * IDOK would never be associated with a dialogbox control (since it's
 * usually the ID of the OK button}.
 */

struct FlagTableEntry {
      int ft_id;
      unsigned long ft_bit;
};

#define EXPORT

static const char menuName[]   = "CmdlgtstMenu";
static const char className[]  = "CmdlgtstClass";
static const char windowName[] = "Cmdlgtst Window";

/*
 * global hInstance variable.  This makes the code non-threadable,
 * but wotthehell; this is Win32 anyway!  (Though it does work
 * under Win16, if one doesn't run more than one copy at a time.)
 */

static HINSTANCE g_hInstance;

/*
 * global CommDlg data structures for modals.  These are placed here
 * so that the custom dialog boxes can get at them.
 */

static PAGESETUPDLG psd;
static PRINTDLG pd;
static COLORREF cc_cr[16];
static CHOOSECOLOR cc;
static LOGFONT cf_lf;
static CHOOSEFONT cf;
static const char ofn_filepat[] = "All Files (*.*)\0*.*\0Only Text Files (*.txt)\0*.txt\0";
static char ofn_result[1024];
static char ofn_titleresult[128];
static OPENFILENAME ofn;

/* Stuff for find and replace.  These are modeless, so I have to put them here. */

static HWND findDialogBox = 0;
static UINT findMessageId = 0;

static FINDREPLACE frS;
static char fromstring[1024], tostring[1024];

/* Stuff for the drawing of the window(s).  I put them here for convenience. */

static COLORREF fgColor = RGB(0, 0, 0); /* not settable */
static COLORREF bgColor = RGB(255, 255, 255); /* COLOR dialog */
static COLORREF txtColor = RGB(0, 0, 0); /* settable if one enables CF_EFFECTS */

/* Utility routines. */

static void nyi(HWND hWnd)
{
      /* "Hi there!  I'm not yet implemented!" */
      MessageBox(hWnd, "Not yet implemented!", "NYI", MB_ICONEXCLAMATION | MB_OK);
}

#if 0
static UINT CALLBACK dummyfnHook(HWND hWnd, UINT msg, UINT wParam, UINT lParam)
{
      /*
       * If the user specifies something that needs an awfully stupid hook function,
       * this is the one to use.  It's a no-op, and says "I didn't do anything."
       */

      (void) hWnd;
      (void) msg;
      (void) wParam;
      (void) lParam;

      WINE_TRACE("dummyfnhook\n"); /* visible under Wine, but Windows probably won't see it! */

      return 0;
}
#endif

/*
 * Initialization code.  This code simply shoves in predefined
 * data into the COMMDLG data structures; in the future, I might use
 * a series of loadable resources, or static initializers; of course,
 * if Microsoft decides to change the field ordering, I'd be screwed.
 */

static void mwi_Print(HWND hWnd)
{
      pd.lStructSize = sizeof(PRINTDLG);
      pd.hwndOwner = hWnd;
      pd.hDevMode = 0;
      pd.hDevNames = 0;
      pd.hDC = 0;
      pd.Flags = 0;
      pd.nMinPage = 1;
      pd.nMaxPage = 100;
      pd.hInstance = g_hInstance;
      pd.lCustData = 0;
      pd.lpfnPrintHook = 0;
      pd.lpfnSetupHook = 0;
      pd.lpPrintTemplateName = 0;
      pd.lpSetupTemplateName = 0;
      pd.hPrintTemplate = 0;
      pd.hSetupTemplate = 0;
}

static void mwi_PageSetup(HWND hWnd)
{
      ZeroMemory(&psd, sizeof(PAGESETUPDLG));
      psd.lStructSize = sizeof(PAGESETUPDLG);
      psd.hwndOwner = hWnd;
      
}

static void mwi_Color(HWND hWnd)
{
      int i;

      /* there's probably an init call for this, somewhere. */

      for(i=0;i<16;i++)
            cc_cr[i] = RGB(0,0,0);

      cc.lStructSize = sizeof(CHOOSECOLOR);
      cc.hwndOwner = hWnd;
      cc.hInstance = (HWND)g_hInstance; /* Should be an HINSTANCE but MS made a typo */
      cc.rgbResult = RGB(0,0,0);
      cc.lpCustColors = cc_cr;
      cc.Flags = 0;
      cc.lCustData = 0;
      cc.lpfnHook = 0;
      cc.lpTemplateName = 0;
}

static void mwi_Font(HWND hWnd)
{
      cf.lStructSize = sizeof(CHOOSEFONT);
      cf.hwndOwner = hWnd;
      cf.hDC = 0;
      cf.lpLogFont = &cf_lf;
      cf.Flags = CF_SCREENFONTS; /* something's needed for display; otherwise it craps out with an error */
      cf.rgbColors = RGB(0,0,0);  /* what is *this* doing here?? */
      cf.lCustData = 0;
      cf.lpfnHook = 0;
      cf.lpTemplateName = 0;
      cf.hInstance = g_hInstance;
      cf.lpszStyle = 0;
      cf.nFontType = 0;
      cf.nSizeMin = 8;
      cf.nSizeMax = 72;

      cf_lf.lfHeight = -18; /* this can be positive or negative, but negative is usually used. */
}

static void mwi_File(HWND hWnd)
{
      ofn.lStructSize = sizeof(OPENFILENAME);
      ofn.hwndOwner = hWnd;
      ofn.hInstance = g_hInstance;
      ofn.lpstrFilter = ofn_filepat;
      ofn.lpstrCustomFilter = 0;
      ofn.nMaxCustFilter = 0;
      ofn.nFilterIndex = 0;
      ofn.lpstrFile = ofn_result;
      ofn.nMaxFile = sizeof(ofn_result);
      ofn.lpstrFileTitle = ofn_titleresult;
      ofn.nMaxFileTitle = sizeof(ofn_titleresult);
      ofn.lpstrInitialDir = 0;
      ofn.lpstrTitle = "Open File";
      ofn.Flags = 0;
      ofn.nFileOffset = 0;
      ofn.nFileExtension = 0;
      ofn.lpstrDefExt = "*";
      ofn.lCustData = 0;
      ofn.lpfnHook = 0;
      ofn.lpTemplateName = 0;

      ofn_result[0] = '\0';
}

static void mwi_FindReplace(HWND hWnd)
{
      frS.lStructSize = sizeof(FINDREPLACE);
      frS.hwndOwner = hWnd;
      frS.hInstance = g_hInstance;
      frS.Flags = FR_DOWN;
      frS.lpstrFindWhat = fromstring;
      frS.lpstrReplaceWith = tostring;
      frS.wFindWhatLen = sizeof(fromstring);
      frS.wReplaceWithLen = sizeof(tostring);
      frS.lCustData = 0;
      frS.lpfnHook = 0;
      frS.lpTemplateName = 0;

      fromstring[0] = '\0';
      tostring[0] = '\0';
      findMessageId = RegisterWindowMessage(FINDMSGSTRING);
}

static void mwi_InitAll(HWND hWnd)
{
      mwi_Print(hWnd);
      mwi_Font(hWnd);
      mwi_Color(hWnd);
      mwi_File(hWnd);
      mwi_FindReplace(hWnd);
      mwi_PageSetup(hWnd);
}

/*
 * Various configurations for the window.  Ideally, this
 * would be stored with the window itself, but then, this
 * isn't the brightest of apps.  Wouldn't be hard to set up,
 * though -- one of the neater functions of Windows, but if
 * someone decides to load the windows themselves from resources,
 * there might be a problem.
 */

static void paintMainWindow(HWND hWnd, UINT iMessage, WPARAM wParam, LPARAM lParam)
{
      PAINTSTRUCT ps;
      RECT rect;
      HPEN pen;
      HFONT font;
      HBRUSH brush;

      (void) iMessage;
      (void) wParam;
      (void) lParam;

      /* Commence painting! */

      BeginPaint(hWnd, &ps);
      GetClientRect(hWnd, &rect);

      pen = SelectObject(ps.hdc, CreatePen(0, 0, fgColor));
      brush = SelectObject(ps.hdc, CreateSolidBrush(bgColor));
      font = SelectObject(ps.hdc, CreateFontIndirect(&cf_lf));

      /*
       * Ideally, we'd only need to draw the exposed bit.
       * But something in BeginPaint is screwing up the rectangle.
       * Either that, or Windows is drawing it wrong.  AARGH!
       * Rectangle(ps.hdc, ps.rcPaint.left, ps.rcPaint.top, ps.rcPaint.right, ps.rcPaint.bottom);
         */
      Rectangle(ps.hdc, rect.left, rect.top, rect.right, rect.bottom);

      /* now draw a couple of lines, just for giggles. */

      MoveToEx(ps.hdc, rect.left, rect.top, NULL);
      LineTo(ps.hdc, rect.right, rect.bottom);
      MoveToEx(ps.hdc, rect.left, rect.bottom, NULL);
      LineTo(ps.hdc, rect.right, rect.top);

      /* draw some text */

      SetTextAlign(ps.hdc, TA_CENTER|TA_BASELINE);
      SetTextColor(ps.hdc, txtColor);
      TextOut(ps.hdc, (rect.left+rect.right)/2, (rect.top+rect.bottom)/2, "Common Dialog Test Page", 23);

      SetTextAlign(ps.hdc, TA_LEFT|TA_TOP);
      TextOut(ps.hdc, rect.left+10, rect.top+10, ofn_result, strlen(ofn_result));
      TextOut(ps.hdc, rect.left+10, rect.top-cf_lf.lfHeight+10, ofn_titleresult, strlen(ofn_titleresult));

      /*
       * set the HDC back to the old pen and brush,
       * and delete the newly created objects.
       */

      pen = SelectObject(ps.hdc, pen);
      DeleteObject(pen);
      brush = SelectObject(ps.hdc, brush);
      DeleteObject(brush);
      font = SelectObject(ps.hdc, font);
      DeleteObject(font);

      EndPaint(hWnd, &ps);
}

/*
 * This function simply returns an error indication.  Naturally,
 * I do not (yet) see an elegant method by which one can convert
 * the CDERR_xxx return values into something resembling usable text;
 * consult cderr.h to see what was returned.
 */

static void mw_checkError(HWND hWnd, BOOL explicitcancel)
{
      DWORD errval = CommDlgExtendedError();
      if(errval) {
            char errbuf[80];

            sprintf(errbuf, "CommDlgExtendedError(): error code %d (0x%x)", errval, errval);
            MessageBox(hWnd, errbuf, "Error", MB_ICONEXCLAMATION | MB_OK);
      }
      else {
            if(explicitcancel) MessageBox(hWnd, "Nope, user canceled it.", "No", MB_OK);
      }
}

/*
 * The actual dialog function calls.  These merely wrap the Commdlg
 * calls, and do something (not so) intelligent with the result.
 * Ideally, the main window would refresh and take into account the
 * various values specified in the dialog.
 */

static void mw_ColorSetup(HWND hWnd)
{
      if(ChooseColor(&cc)) {
            RECT rect;

            GetClientRect(hWnd, &rect);
            InvalidateRect(hWnd, &rect, FALSE);
            bgColor = cc.rgbResult;
      }
      else mw_checkError(hWnd, FALSE);
}

static void mw_FontSetup(HWND hWnd)
{
      if(ChooseFont(&cf)) {
            RECT rect;
            GetClientRect(hWnd, &rect);
            InvalidateRect(hWnd, &rect, FALSE);
            txtColor = cf.rgbColors;
      }
      else mw_checkError(hWnd, FALSE);
}

static void mw_FindSetup(HWND hWnd)
{
      if(findDialogBox == 0) {
            findDialogBox = FindText(&frS);
            if(findDialogBox==0) mw_checkError(hWnd,TRUE);
      }
}

static void mw_ReplaceSetup(HWND hWnd)
{
      if(findDialogBox == 0) {
            findDialogBox = ReplaceText(&frS);
            if(findDialogBox==0) mw_checkError(hWnd,TRUE);
      }
}

static void mw_OpenSetup(HWND hWnd)
{
      if(GetOpenFileName(&ofn)) {
            RECT rect;
            GetClientRect(hWnd, &rect);
            InvalidateRect(hWnd, &rect, FALSE);
      }
      else mw_checkError(hWnd,FALSE);
}

static void mw_SaveSetup(HWND hWnd)
{
      if(GetSaveFileName(&ofn)) {
            RECT rect;
            GetClientRect(hWnd, &rect);
            InvalidateRect(hWnd, &rect, FALSE);
      }
      else mw_checkError(hWnd,FALSE);
}

/*
 * Can't find documentation in Borland for this one.  Does it
 * exist at all, or is it merely a subdialog of Print?
 */

static void mw_PSetupSetup(HWND hWnd)
{
      nyi(hWnd);
}

static void mw_PrintSetup(HWND hWnd)
{
      if(PrintDlg(&pd)) {
            /*
             * the following are suggested in the Borland documentation,
             * but aren't that useful until WinE starts to actually
             * function with respect to printing.
             */

#if 0
            Escape(tmp.hDC, STARTDOC, 8, "Test-Doc", NULL);
#endif

       /* Print text and rectangle */

#if 0
            TextOut(tmp.hDC, 50, 50, "Common Dialog Test Page", 23);

            Rectangle(tmp.hDC, 50, 90, 625, 105);
            Escape(tmp.hDC, NEWFRAME, 0, NULL, NULL);
            Escape(tmp.hDC, ENDDOC, 0, NULL, NULL);
            DeleteDC(tmp.hDC);
#endif
             if (pd.hDevMode != 0)
                   GlobalFree(pd.hDevMode);
             if (pd.hDevNames != 0)
                   GlobalFree(pd.hDevNames);

             pd.hDevMode = 0;
             pd.hDevNames = 0;

             MessageBox(hWnd, "Success.", "Yes", MB_OK);
      }
      else mw_checkError(hWnd,TRUE);
}

#define OF(fn, fi, fl)  \
            if(dm->dmFields & fl){ \
                  WINE_TRACE("        %s  =%hd\n", (fn), dm->fi); \
            } else \
                  WINE_TRACE("        %s NOT SET!\n", fn);


static void mw_PageSetup(HWND hWnd)
{
      DEVMODEA *dm;
      DEVNAMES *dn;
      CHAR      tmplnm[30] = "PAGESETUPDLGORD_CSTM";
      
      if(psd.Flags & PSD_ENABLEPAGESETUPTEMPLATE)
            psd.lpPageSetupTemplateName = tmplnm;
      psd.hInstance = g_hInstance;
      
      if(PageSetupDlg(&psd)){
            dm = GlobalLock(psd.hDevMode);
            if(dm) {
                  WINE_TRACE("dm != NULL\nDEVMODEA struct:\n");
                  WINE_TRACE("    dmDeviceName    ='%s'\n",       dm->dmDeviceName);
                  WINE_TRACE("    dmSpecVersion   =%#x\n",  dm->dmSpecVersion);
                  WINE_TRACE("    dmDriverVersion =%#x\n",  dm->dmDriverVersion);
                  WINE_TRACE("    dmSize          =%#x\n",  dm->dmSize);      
                  WINE_TRACE("    dmDriverExtra   =%#x\n",  dm->dmDriverExtra);
                  WINE_TRACE("    dmFields        =%#x\n",  dm->dmFields);
                  OF("dmOrientation",     u1.s1.dmOrientation,    DM_ORIENTATION)
                  OF("dmPaperSize", u1.s1.dmPaperSize,      DM_PAPERSIZE);
                  OF("dmPaperLength",     u1.s1.dmPaperLength,    DM_PAPERLENGTH);
                  OF("dmPaperWidth",      u1.s1.dmPaperWidth,     DM_PAPERWIDTH);
                  OF("dmScale",           u1.s1.dmScale,    DM_SCALE);
                  OF("dmCopies",          u1.s1.dmCopies,   DM_COPIES);
                  OF("dmDefaultSource",   u1.s1.dmDefaultSource,DM_DEFAULTSOURCE);
                  OF("dmPrintQuality",    u1.s1.dmPrintQuality,   DM_PRINTQUALITY);
                  if(dm->dmFields & DM_POSITION)
                        WINE_TRACE("        dmPosition(%d, %d)\n", dm->u1.s2.dmPosition.x, dm->u1.s2.dmPosition.y);
                  else
                        WINE_TRACE("        dmPosition NOT SET!\n");
                  OF("dmColor",           dmColor,    DM_COLOR);
                  OF("dmDuplex",          dmDuplex,   DM_DUPLEX);
                  OF("dmYResolution",     dmYResolution,    DM_YRESOLUTION);
                  OF("dmTTOption",  dmTTOption, DM_TTOPTION);
                  OF("dmCollate",         dmCollate,  DM_COLLATE);
                  if(dm->dmFields & DM_FORMNAME)
                        WINE_TRACE("        dmFormName = '%s'\n", dm->dmFormName);
                  else 
                        WINE_TRACE("        dmFormName NOT SET!\n");
                  if(dm->dmFields & DM_ICMMETHOD)
                        WINE_TRACE("        dmICMMethod = %#x\n", dm->dmICMMethod);
                  else
                        WINE_TRACE("        dmICMMethod NOT SET!\n");
                  
                  GlobalUnlock(psd.hDevMode);
            }
            else
                  WINE_TRACE("dm == NULL\n");
      
            WINE_TRACE("\nPAGESETUPDLG struct\n");
            WINE_TRACE("    ptPaperSize(%d, %d)\n", psd.ptPaperSize.x, psd.ptPaperSize.y);
            WINE_TRACE("    rtMargin(%d, %d, %d, %d)\n",
                  psd.rtMargin.left, psd.rtMargin.top, psd.rtMargin.right, psd.rtMargin.bottom);
      
            WINE_TRACE("\nDEVNAMES struct\n");
            dn = GlobalLock(psd.hDevNames);
            if(dn){
                  WINE_TRACE("    wDriverOffset='%s'\n", ((char*)dn+dn->wDriverOffset));
                  WINE_TRACE("    wDeviceOffset='%s'\n", ((char*)dn+dn->wDeviceOffset));
                  WINE_TRACE("    wOutputOffset='%s'\n", ((char*)dn+dn->wOutputOffset));
                  WINE_TRACE("    wDefault     ='%s'\n", ((char*)dn+dn->wDefault));
                  GlobalUnlock(psd.hDevNames);
            }else
                  WINE_TRACE(" dn == NULL!\n");       
            WINE_TRACE("End.\n");

            if (psd.hDevMode != NULL)
                  GlobalFree(psd.hDevMode);
            if (psd.hDevNames != NULL)
                  GlobalFree(psd.hDevNames);
            if (psd.hPageSetupTemplate != NULL)
                  GlobalFree(psd.hPageSetupTemplate);

            psd.hDevMode  = NULL;
            psd.hDevNames = NULL;
            psd.hPageSetupTemplate = NULL;

            MessageBox(hWnd, "Success.", "Yes", MB_OK);
      } mw_checkError(hWnd, FALSE);
}

/********************************************************************************************************/
/*
 * Some support functions for the custom dialog box handlers.
 * In particular, we have to set things properly, and get the flags back.
 */

static void mwcd_SetFlags(HWND hWnd, struct FlagTableEntry *table, DWORD flags)
{
      int i;

      for(i=0; table[i].ft_id != IDOK; i++)
      {
            CheckDlgButton(hWnd, table[i].ft_id,(table[i].ft_bit & flags) ? 1 : 0);
      }
}

static DWORD mwcd_GetFlags(HWND hWnd, struct FlagTableEntry * table)
{
      int i;
      unsigned long l = 0;

      for(i=0; table[i].ft_id != IDOK; i++)
      {
            if(IsDlgButtonChecked(hWnd, table[i].ft_id) == 1)
                  l |= table[i].ft_bit;
      }

      return l;
}

/*
 * These functions are the custom dialog box handlers.
 * The division of labor may be a tad peculiar; in particular,
 * the flag tables should probably be in the main functions,
 * not the handlers.  I'll fix that later; this works as of right now.
 */

static INT_PTR mwcd_Setup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
                               struct FlagTableEntry * table, DWORD* flags)
{
      (void) lParam;

      switch(uMsg)
      {
            case WM_INITDIALOG:
                  /* Set the controls properly. */

                  mwcd_SetFlags(hWnd, table, *flags);

                  return TRUE; /* I would return FALSE if I explicitly called SetFocus(). */
                             /* As usual, Windows is weird. */

            case WM_COMMAND:
                  switch(wParam) {
                        case IDOK:
                              *flags = mwcd_GetFlags(hWnd, table);
                              EndDialog(hWnd,1);
                              break;

                        case IDCANCEL:
                              EndDialog(hWnd,0);
                              break;

                        case CM_R_HELP:
                              break; /* help?  We don't need no steenkin help! */

                        default:
                              break; /* eat the message */
                  }
                  return TRUE;

            default:
                  return FALSE; /* since I don't process this particular message */
      }
}

static INT_PTR CALLBACK mwcd_ColorSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
      static struct FlagTableEntry flagTable[] = {
            {I_CC_RGBINIT, CC_RGBINIT},
            {I_CC_SHOWHELP, CC_SHOWHELP},
            {I_CC_PREVENTFULLOPEN, CC_PREVENTFULLOPEN},
            {I_CC_FULLOPEN, CC_FULLOPEN},
            {I_CC_ENABLETEMPLATEHANDLE, CC_ENABLETEMPLATEHANDLE},
            {I_CC_ENABLETEMPLATE, CC_ENABLETEMPLATE},
            {I_CC_ENABLEHOOK, CC_ENABLEHOOK},
            {IDOK, 0},
      };

      return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &cc.Flags);
}

static INT_PTR CALLBACK mwcd_FontSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
      static struct FlagTableEntry flagTable[] = {
            {I_CF_APPLY, CF_APPLY},
            {I_CF_ANSIONLY, CF_ANSIONLY},
            {I_CF_BOTH, CF_BOTH},
            {I_CF_TTONLY, CF_TTONLY},
            {I_CF_EFFECTS, CF_EFFECTS},
            {I_CF_ENABLEHOOK, CF_ENABLEHOOK},
            {I_CF_ENABLETEMPLATE, CF_ENABLETEMPLATE},
            {I_CF_ENABLETEMPLATEHANDLE, CF_ENABLETEMPLATEHANDLE},
            {I_CF_FIXEDPITCHONLY, CF_FIXEDPITCHONLY},
            {I_CF_INITTOLOGFONTSTRUCT, CF_INITTOLOGFONTSTRUCT},
            {I_CF_LIMITSIZE, CF_LIMITSIZE},
            {I_CF_NOFACESEL, CF_NOFACESEL},
            {I_CF_USESTYLE, CF_USESTYLE},
            {I_CF_WYSIWYG, CF_WYSIWYG},
            {I_CF_SHOWHELP, CF_SHOWHELP},
            {I_CF_SCREENFONTS, CF_SCREENFONTS},
            {I_CF_SCALABLEONLY, CF_SCALABLEONLY},
            {I_CF_PRINTERFONTS, CF_PRINTERFONTS},
            {I_CF_NOVECTORFONTS, CF_NOVECTORFONTS},
            {I_CF_NOSTYLESEL, CF_NOSTYLESEL},
            {I_CF_NOSIZESEL, CF_NOSIZESEL},
            {I_CF_NOOEMFONTS, CF_NOOEMFONTS},
            {IDOK, 0},
      };

      return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &cf.Flags);
}

static INT_PTR CALLBACK mwcd_FindSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{

      static struct FlagTableEntry flagTable[] = {
            {I_FR_DIALOGTERM, FR_DIALOGTERM},
            {I_FR_DOWN, FR_DOWN},
            {I_FR_ENABLEHOOK, FR_ENABLEHOOK},
            {I_FR_ENABLETEMPLATE, FR_ENABLETEMPLATE},
            {I_FR_ENABLETEMPLATEHANDLE, FR_ENABLETEMPLATEHANDLE},
            {I_FR_FINDNEXT, FR_FINDNEXT},
            {I_FR_HIDEMATCHCASE, FR_HIDEMATCHCASE},
            {I_FR_HIDEWHOLEWORD, FR_HIDEWHOLEWORD},
            {I_FR_HIDEUPDOWN, FR_HIDEUPDOWN},
            {I_FR_MATCHCASE, FR_MATCHCASE},
            {I_FR_NOMATCHCASE, FR_NOMATCHCASE},
            {I_FR_NOUPDOWN, FR_NOUPDOWN},
            {I_FR_NOWHOLEWORD, FR_NOWHOLEWORD},
            {I_FR_REPLACE, FR_REPLACE},
            {I_FR_REPLACEALL, FR_REPLACEALL},
            {I_FR_SHOWHELP, FR_SHOWHELP},
            {I_FR_WHOLEWORD, FR_WHOLEWORD},
            {IDOK, 0},
      };

      return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &frS.Flags);
}

static INT_PTR CALLBACK mwcd_PrintSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
      static struct FlagTableEntry flagTable[] = {
            {I_PD_ALLPAGES, PD_ALLPAGES},
            {I_PD_COLLATE, PD_COLLATE},
            {I_PD_DISABLEPRINTTOFILE, PD_DISABLEPRINTTOFILE},
            {I_PD_ENABLEPRINTHOOK, PD_ENABLEPRINTHOOK},
            {I_PD_ENABLEPRINTTEMPLATE, PD_ENABLEPRINTTEMPLATE},
            {I_PD_ENABLEPRINTTEMPLATEHANDLE, PD_ENABLEPRINTTEMPLATEHANDLE},
            {I_PD_ENABLESETUPHOOK, PD_ENABLESETUPHOOK},
            {I_PD_ENABLESETUPTEMPLATE, PD_ENABLESETUPTEMPLATE},
            {I_PD_ENABLESETUPTEMPLATEHANDLE, PD_ENABLESETUPTEMPLATEHANDLE},
            {I_PD_HIDEPRINTTOFILE, PD_HIDEPRINTTOFILE},
            {I_PD_NOPAGENUMS, PD_NOPAGENUMS},
            {I_PD_NOSELECTION, PD_NOSELECTION},
            {I_PD_NOWARNING, PD_NOWARNING},
            {I_PD_PAGENUMS, PD_PAGENUMS},
            {I_PD_PRINTSETUP, PD_PRINTSETUP},
            {I_PD_PRINTTOFILE, PD_PRINTTOFILE},
            {I_PD_RETURNDC, PD_RETURNDC},
            {I_PD_RETURNDEFAULT, PD_RETURNDEFAULT},
            {I_PD_RETURNIC, PD_RETURNIC},
            {I_PD_SELECTION, PD_SELECTION},
            {I_PD_SHOWHELP, PD_SHOWHELP},
            {I_PD_USEDEVMODECOPIES, PD_USEDEVMODECOPIES},
            {IDOK, 0},
      };

      return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &pd.Flags);
}

static INT_PTR CALLBACK mwcd_PageSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
      static struct FlagTableEntry flagTable[] = {
            {I_PSD_DEFAULTMINMARGINS,     PSD_DEFAULTMINMARGINS},
            {I_PSD_DISABLEMARGINS,        PSD_DISABLEMARGINS},
            {I_PSD_DISABLEORIENTATION,    PSD_DISABLEORIENTATION},
            {I_PSD_DISABLEPAGEPAINTING,   PSD_DISABLEPAGEPAINTING},
            {I_PSD_DISABLEPAPER,          PSD_DISABLEPAPER},
            {I_PSD_DISABLEPRINTER,        PSD_DISABLEPRINTER},
            {I_PSD_ENABLEPAGEPAINTHOOK,   PSD_ENABLEPAGEPAINTHOOK},
            {I_PSD_ENABLEPAGESETUPHOOK,   PSD_ENABLEPAGESETUPHOOK},
            {I_PSD_ENABLEPAGESETUPTEMPLATE, PSD_ENABLEPAGESETUPTEMPLATE},
            {I_PSD_ENABLEPAGESETUPTEMPLATEHANDLE, PSD_ENABLEPAGESETUPTEMPLATEHANDLE},
            {I_PSD_INHUNDREDTHSOFMILLIMETERS, PSD_INHUNDREDTHSOFMILLIMETERS},
            {I_PSD_INTHOUSANDTHSOFINCHES,       PSD_INTHOUSANDTHSOFINCHES},
            {I_PSD_INWININIINTLMEASURE,   PSD_INWININIINTLMEASURE},
            {I_PSD_MARGINS,         PSD_MARGINS},
            {I_PSD_MINMARGINS,            PSD_MINMARGINS},
            {I_PSD_NONETWORKBUTTON,       PSD_NONETWORKBUTTON},
            {I_PSD_NOWARNING,             PSD_NOWARNING},
            {I_PSD_RETURNDEFAULT,         PSD_RETURNDEFAULT},
            {I_PSD_SHOWHELP,        PSD_SHOWHELP},
            {IDOK, 0}
      };

      return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &psd.Flags);
}

static INT_PTR CALLBACK mwcd_FileSetup(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
      static struct FlagTableEntry flagTable[] = {
            {I_OFN_ALLOWMULTISELECT, OFN_ALLOWMULTISELECT},
            {I_OFN_CREATEPROMPT, OFN_CREATEPROMPT},
            {I_OFN_ENABLEHOOK, OFN_ENABLEHOOK},
            {I_OFN_ENABLETEMPLATE, OFN_ENABLETEMPLATE},
            {I_OFN_ENABLETEMPLATEHANDLE, OFN_ENABLETEMPLATEHANDLE},
            {I_OFN_EXTENSIONDIFFERENT, OFN_EXTENSIONDIFFERENT},
            {I_OFN_FILEMUSTEXIST, OFN_FILEMUSTEXIST},
            {I_OFN_HIDEREADONLY, OFN_HIDEREADONLY},
            {I_OFN_NOCHANGEDIR, OFN_NOCHANGEDIR},
            {I_OFN_NOREADONLYRETURN, OFN_NOREADONLYRETURN},
            {I_OFN_NOTESTFILECREATE, OFN_NOTESTFILECREATE},
            {I_OFN_NOVALIDATE, OFN_NOVALIDATE},
            {I_OFN_OVERWRITEPROMPT, OFN_OVERWRITEPROMPT},
            {I_OFN_PATHMUSTEXIST, OFN_PATHMUSTEXIST},
            {I_OFN_READONLY, OFN_READONLY},
            {I_OFN_SHAREAWARE, OFN_SHAREAWARE},
            {I_OFN_SHOWHELP, OFN_SHOWHELP},
            {IDOK, 0},
      };

      return mwcd_Setup(hWnd, uMsg, wParam, lParam, flagTable, &ofn.Flags);
}

static INT_PTR CALLBACK mwcd_About(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
      (void) wParam;
      (void) lParam;

      switch(uMsg) {
            case WM_INITDIALOG: return TRUE; /* let WINDOWS set the focus. */
            case WM_COMMAND: EndDialog(hWnd, 0); return TRUE; /* it's our OK button. */
            default: return FALSE; /* it's something else, let Windows worry about it */
      }
}

/*
 * These functions call custom dialog boxes (resource-loaded, if I do this right).
 * Right now they don't do a heck of a lot, but at some future time
 * they will muck about with the flags (and be loaded from the flags) of
 * the CommDlg structures initialized by the mwi_xxx() routines.
 */

static void mwc_ColorSetup(HWND hWnd)
{
      int r = DialogBox(g_hInstance, "Color_Flags_Dialog", hWnd, mwcd_ColorSetup);
      if(r < 0) { MessageBox(hWnd, "Failure opening Color_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
}

static void mwc_FontSetup(HWND hWnd)
{
      int r = DialogBox(g_hInstance, "Font_Flags_Dialog", hWnd, mwcd_FontSetup);
      if(r < 0) { MessageBox(hWnd, "Failure opening Font_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
}

static void mwc_FindReplaceSetup(HWND hWnd)
{
      int r = DialogBox(g_hInstance, "Find_Flags_Dialog", hWnd, mwcd_FindSetup);
      if(r < 0) { MessageBox(hWnd, "Failure opening Find_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
}

static void mwc_PrintSetup(HWND hWnd)
{
      int r = DialogBox(g_hInstance, "Print_Flags_Dialog", hWnd, mwcd_PrintSetup);
      if(r < 0) { MessageBox(hWnd, "Failure opening Print_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
}

static void mwc_PageSetup(HWND hWnd)
{
      int r = DialogBox(g_hInstance, "PageSetup_Flags_Dialog", hWnd, mwcd_PageSetup);
      if(r < 0) { MessageBox(hWnd, "Failure opening PageSetup_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
}

static void mwc_FileSetup(HWND hWnd)
{
      int r = DialogBox(g_hInstance, "File_Flags_Dialog", hWnd, mwcd_FileSetup);
      if(r < 0) { MessageBox(hWnd, "Failure opening File_Flags_Dialog box", "Error", MB_ICONASTERISK|MB_OK); }
}

/*
 * Main window message dispatcher.  Here the messages get chewed up
 * and spit out.  Note the ugly hack for the modeless Find/Replace box;
 * this looks like it was bolted on with hexhead screws and is now
 * dangling from Windows like a loose muffler.  Sigh.
 */

static LRESULT CALLBACK EXPORT mainWindowDispatcher(
      HWND hWnd,
      UINT uMsg,
      WPARAM wParam,
      LPARAM lParam
)
{

      if(uMsg == findMessageId) {
            FINDREPLACE * lpfr = (FINDREPLACE *) lParam;
            if(lpfr->Flags & FR_DIALOGTERM) {
                  MessageBox(hWnd, "User closing us down.", "Down", MB_OK);
                  findDialogBox = 0;
            }
            else if (lpfr->Flags & FR_FINDNEXT) {
                  MessageBox(hWnd, "Finding next occurrence.", "Findnext", MB_OK);
            }
            else if (lpfr->Flags & FR_REPLACE) {
                  MessageBox(hWnd, "Replacing next occurrence.", "Replace", MB_OK);
            }
            else if (lpfr->Flags & FR_REPLACEALL) {
                  MessageBox(hWnd, "Replacing all occurrences.", "Replace All", MB_OK);
            }
            else {
                  MessageBox(hWnd, "Eh?", "Eh?", MB_OK);
            }
            return 1;
      }
      else switch(uMsg) {
      case WM_CREATE:
                  /*
                   * this is always the first message... at least as far
                   * as we are concerned.
                   */
            mwi_InitAll(hWnd);
            break;

      case WM_PAINT:
                  /* Well, draw something! */
            paintMainWindow(hWnd, uMsg, wParam, lParam);
            break;

      case WM_DESTROY:
                  /* Uh oh.  Eject!  Eject!  Eject! */
            PostQuitMessage(0);
            break;

      case WM_COMMAND:
                  /* menu or accelerator pressed; do something. */

            switch(wParam) {
            case CM_U_EXIT:
                        /* Uh oh.  Eject!  Eject!  Eject! */
                  PostQuitMessage(0);
                  break;

            /* these actually call the Common Dialogs. */

            case CM_U_COLOR:
                  mw_ColorSetup(hWnd); return 1;

            case CM_U_FONT:
                  mw_FontSetup(hWnd); return 1;

            case CM_U_FIND:
                  mw_FindSetup(hWnd); return 1;

            case CM_U_REPLACE:
                  mw_ReplaceSetup(hWnd); return 1;

            case CM_U_OPEN:
                  mw_OpenSetup(hWnd); return 1;

            case CM_U_SAVE:
                  mw_SaveSetup(hWnd); return 1;

            case CM_U_PSETUP:
                  mw_PSetupSetup(hWnd); return 1;

            case CM_U_PRINT:
                  mw_PrintSetup(hWnd); return 1;
                  
            case CM_U_PAGESETUP:
                  mw_PageSetup(hWnd); return 1;
                  
            /*
             * these set up various flags and values in the Common Dialog
             * data structures, which are currently stored in static memory.
             * The control dialogs themselves are resources as well.
             */

            case CM_F_FILE:
                  mwc_FileSetup(hWnd); return 1;

            case CM_F_COLOR:
                  mwc_ColorSetup(hWnd); return 1;

            case CM_F_FONT:
                  mwc_FontSetup(hWnd); return 1;

            case CM_F_FINDREPLACE:
                  mwc_FindReplaceSetup(hWnd); return 1;

            case CM_F_PRINT:
                  mwc_PrintSetup(hWnd); return 1;

            case CM_F_PAGESETUP: 
                  mwc_PageSetup(hWnd); return 1;

            case CM_H_ABOUT:
                  DialogBox(g_hInstance, "AboutDialog", hWnd, mwcd_About);
                  return 1;
            case CM_H_USAGE:
                  DialogBox(g_hInstance, "UsageDialog", hWnd, mwcd_About);
            /* return value?  *What* return value? */
                  return 1;

            default:
                  nyi(hWnd); return 1;
            }
            break;

      default:
            return DefWindowProc(hWnd, uMsg, wParam, lParam);
      }
      return 0;
}

/* Class registration.  One might call this a Windowsism. */

static int registerMainWindowClass(HINSTANCE hInstance)
{
      WNDCLASS wndClass;

      wndClass.style         = CS_HREDRAW|CS_VREDRAW;
      wndClass.lpfnWndProc   = mainWindowDispatcher;
      wndClass.cbClsExtra    = 0;
      wndClass.cbWndExtra    = 0;
      wndClass.hInstance     = hInstance;
#if 0
      wndClass.hIcon         = LoadIcon(hInstance, "whello");
      wndClass.hCursor       = LoadCursor(hInstance, IDC_ARROW);
#endif
      wndClass.hIcon         = 0;
      wndClass.hCursor       = 0;
      wndClass.hbrBackground = GetStockObject(WHITE_BRUSH);
      wndClass.lpszMenuName  = menuName;
      wndClass.lpszClassName = className;

      return RegisterClass(&wndClass);
}

/*
 * Another Windowsism; this one's not too bad, as it compares
 * favorably with CreateWindow() in X (mucking about with X Visuals
 * can get messy; at least here we don't have to worry about that).
 */

static HWND createMainWindow(HINSTANCE hInstance, int show)
{
      HWND hWnd;

      hWnd = CreateWindow(
            className,  /* classname */
            windowName,  /* windowname/title */
            WS_OVERLAPPEDWINDOW, /* dwStyle */
            0, /* x */
            0, /* y */
            CW_USEDEFAULT, /* width */
            CW_USEDEFAULT, /* height */
            0, /* parent window */
            0, /* menu */
            hInstance, /* instance */
            0          /* passthrough for MDI */
      );

      if(hWnd==0) return 0;

      ShowWindow(hWnd, show);
      UpdateWindow(hWnd);

      return hWnd;
}

static int messageLoop(HINSTANCE hInstance, HWND hWnd)
{
      MSG msg;

      (void) hInstance;
      (void) hWnd;

      while(GetMessage(&msg, 0, 0, 0)) {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
      }

      return msg.wParam;
}

/*
 * Oh, did we tell you that main() isn't the name of the
 * thing called in a Win16/Win32 app?  And then there are
 * the lack of argument lists, the necessity (at least in Win16)
 * of having to deal with class registration exactly once (as the
 * app may be run again), and some other bizarre holdovers from
 * Windows 3.x days.  But hey, Solitaire still works.
 */

int PASCAL WinMain(
      HINSTANCE hInstance, HINSTANCE hPrevInstance,
      LPSTR lpszCmdLine, int nCmdShow
)
{
      HWND hWnd;

      (void) lpszCmdLine;

      strcpy(ofn_result, "--- not yet set ---");

      if(hPrevInstance==0) {
            if(!registerMainWindowClass(hInstance))
                  return -1;
      }

      g_hInstance = hInstance;

      hWnd = createMainWindow(hInstance,nCmdShow);
      if(hWnd == 0)
            return -1;

      return messageLoop(hInstance, hWnd);
}

/* And now the end of the program.  Enjoy. */

/*
 * (c) 1999-2000 Eric Williams.  Rights as specified under the WINE
 * License.  Don't hoard code; share it!
 */

Generated by  Doxygen 1.6.0   Back to index