home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / msdn_vcb / samples / vc98 / sdk / sdktools / imagedit / file.c < prev    next >
Text File  |  1996-06-12  |  24KB  |  834 lines

  1.     /****************************************************************************/
  2.     /*                                                                          */
  3.     /*                 Copyright (C) 1987-1996 Microsoft Corp.                */
  4.     /*                           All Rights Reserved                            */
  5.     /*                                                                          */
  6.     /****************************************************************************/
  7.     /****************************** Module Header *******************************
  8.     * Module Name: file.c
  9.     *
  10.     * Contains routines for handling files.
  11.     *
  12.     * History:
  13.     *
  14.     ****************************************************************************/
  15.     
  16.     #include "imagedit.h"
  17.     #include "dialogs.h"
  18.     
  19.     #include <string.h>
  20.  
  21.      #include <windowsx.h>
  22.     #include <commdlg.h>
  23.     
  24.     
  25.     #ifdef WIN16
  26.     typedef BOOL (APIENTRY *LPOFNHOOKPROC) (HWND, UINT, WPARAM, LONG);
  27.     #endif
  28.     
  29.     
  30.     STATICFN VOID NEAR AddFilterString(PSTR pszBuf, PSTR pszType, PSTR pszExt,
  31.         BOOL fFirst);
  32.     STATICFN PSTR NEAR DefExtFromFilter(INT index, PSTR pszFilter);
  33.     STATICFN BOOL NEAR LoadFile(PSTR pszFullFileName);
  34.     STATICFN INT NEAR GetTypeFromExt(PSTR pszFileName);
  35.     STATICFN VOID NEAR FileCat(PSTR pchName, PSTR pchCat);
  36.     
  37.     
  38.     static OPENFILENAME ofn;
  39.     
  40.     
  41.     
  42.     /************************************************************************
  43.     * SetFileName
  44.     *
  45.     * Updates the globals that contain the file name of the currently
  46.     * loaded file.  This routine will also cause the title bar to
  47.     * be udpated with the new name.
  48.     *
  49.     * Arguments:
  50.     *
  51.     * History:
  52.     *
  53.     ************************************************************************/
  54.     
  55.     VOID SetFileName(
  56.         PSTR pszFullFileName)
  57.     {
  58.         CHAR szTitle[CCHMAXPATH];
  59.         WIN32_FIND_DATA ffbuf;
  60.         CHAR *pch;
  61.     
  62.         if (pszFullFileName) {
  63.             HANDLE hfind;
  64.             strcpy(gszFullFileName, pszFullFileName);
  65.             gpszFileName = FileInPath(gszFullFileName);
  66.     
  67.             if((hfind = FindFirstFile( pszFullFileName, &ffbuf)) !=
  68.                     INVALID_HANDLE_VALUE) {
  69.     
  70.                 strcpy(gpszFileName, ffbuf.cFileName);
  71.                 FindClose(hfind);
  72.             }
  73.     
  74.         }
  75.         else {
  76.             *gszFullFileName = '\0';
  77.             gpszFileName = NULL;
  78.         }
  79.     
  80.         strcpy(szTitle, ids(IDS_PGMTITLE));
  81.         strcat(szTitle, " - ");
  82.         pch = gpszFileName ? gpszFileName : ids(IDS_UNTITLED);
  83.         strncat(szTitle, pch, sizeof(szTitle) - strlen(szTitle));
  84.         szTitle[CCHMAXPATH-1] = '\0';
  85.         SetWindowText(ghwndMain, szTitle);
  86.     }
  87.     
  88.     
  89.     
  90.     /************************************************************************
  91.     * FileInPath
  92.     *
  93.     * This function takes a path and returns a pointer to the file name
  94.     * portion of it.  For instance, it will return a pointer to
  95.     * "abc.res" if it is given the following path: "c:\windows\abc.res".
  96.     *
  97.     * Arguments:
  98.     *   PSTR pstrPath - Path to look through.
  99.     *
  100.     * History:
  101.     *
  102.     ************************************************************************/
  103.     
  104.     PSTR FileInPath(
  105.         PSTR pstrPath)
  106.     {
  107.         PSTR pstr;
  108.     
  109.         pstr = pstrPath + strlen(pstrPath);
  110.         while (pstr > pstrPath) {
  111.             pstr = FAR2NEAR(AnsiPrev(pstrPath, pstr));
  112.             if (*pstr == '\\' || *pstr == ':' || *pstr == '/') {
  113.                 pstr = FAR2NEAR(AnsiNext(pstr));
  114.                 break;
  115.             }
  116.         }
  117.     
  118.         return pstr;
  119.     }
  120.     
  121.     
  122.     
  123.     /************************************************************************
  124.     * ClearResource
  125.     *
  126.     * Resets the editor back to a neutral state before editing any image.
  127.     * This function can be called before starting to edit a new file
  128.     * (but not just a new image).  Files should be saved before calling
  129.     * this routine, because the entire image list is destroyed.
  130.     *
  131.     * History:
  132.     *
  133.     ************************************************************************/
  134.     
  135.     VOID ClearResource(VOID)
  136.     {
  137.         ImageLinkFreeList();
  138.     
  139.         SetFileName(NULL);
  140.     
  141.         gnImages = 0;
  142.         fImageDirty = FALSE;
  143.         fFileDirty = FALSE;
  144.         gpImageCur = NULL;
  145.     
  146.         /*
  147.          * Hide the workspace and view windows.
  148.          */
  149.         ShowWindow(ghwndWork, SW_HIDE);
  150.         ViewShow(FALSE);
  151.     
  152.         /*
  153.          * Destroy the image DC's.
  154.          */
  155.         ImageDCDelete();
  156.     
  157.         /*
  158.          * Update the properties bar.
  159.          */
  160.         PropBarClearPos();
  161.         PropBarClearSize();
  162.         PropBarUpdate();
  163.     }
  164.     
  165.     
  166.     
  167.     /************************************************************************
  168.     * OpenDlg
  169.     *
  170.     *
  171.     *
  172.     * Arguments:
  173.     *
  174.     * History:
  175.     *
  176.     ************************************************************************/
  177.     
  178.     BOOL OpenDlg(
  179.         PSTR pszFileName,
  180.         INT iType)
  181.     {
  182.         BOOL fGotName;
  183.         INT idDlg;
  184.         INT idPrevDlg;
  185.         CHAR szFilter[CCHTEXTMAX];
  186.     
  187.         pszFileName[0] = '\0';
  188.     
  189.         switch (iType) {
  190.             case FT_BITMAP:
  191.             case FT_ICON:
  192.             case FT_CURSOR:
  193.                 AddFilterString(szFilter, ids(IDS_BMPFILTER),
  194.                         ids(IDS_BMPFILTEREXT), TRUE);
  195.                 AddFilterString(szFilter, ids(IDS_ICOFILTER),
  196.                         ids(IDS_ICOFILTEREXT), FALSE);
  197.                 AddFilterString(szFilter, ids(IDS_CURFILTER),
  198.                         ids(IDS_CURFILTEREXT), FALSE);
  199.                 AddFilterString(szFilter, ids(IDS_ALLFILTER),
  200.                         ids(IDS_ALLFILTEREXT), FALSE);
  201.     
  202.                 ofn.nFilterIndex = iType + 1;
  203.                 idDlg = DID_COMMONFILEOPEN;
  204.     
  205.                 break;
  206.     
  207.             case FT_PALETTE:
  208.                 AddFilterString(szFilter, ids(IDS_PALFILTER),
  209.                         ids(IDS_PALFILTEREXT), TRUE);
  210.                 AddFilterString(szFilter, ids(IDS_ALLFILTER),
  211.                         ids(IDS_ALLFILTEREXT), FALSE);
  212.     
  213.                 ofn.nFilterIndex = 1;
  214.                 idDlg = DID_COMMONFILEOPENPAL;
  215.     
  216.                 break;
  217.         }
  218.     
  219.         ofn.lStructSize = sizeof(OPENFILENAME);
  220.         ofn.hwndOwner = ghwndMain;
  221.         ofn.hInstance = NULL;
  222.         ofn.lpstrFilter = szFilter;
  223.         ofn.lpstrCustomFilter = NULL;
  224.         ofn.nMaxCustFilter = 0;
  225.         ofn.lpstrFile = pszFileName;
  226.         ofn.nMaxFile = CCHMAXPATH;
  227.         ofn.lpstrFileTitle = NULL;
  228.         ofn.nMaxFileTitle = 0;
  229.         ofn.lpstrInitialDir = NULL;
  230.         ofn.lpstrTitle = NULL;
  231.         ofn.Flags = OFN_HIDEREADONLY | OFN_SHOWHELP | OFN_FILEMUSTEXIST |
  232.                 OFN_ENABLEHOOK;
  233.         ofn.nFileOffset = 0;
  234.         ofn.nFileExtension = 0;
  235.         ofn.lpstrDefExt = (LPCSTR)DefExtFromFilter((INT)ofn.nFilterIndex - 1,
  236.                 (PSTR)ofn.lpstrFilter);
  237.         ofn.lCustData = 0;
  238.         ofn.lpfnHook = (LPOFNHOOKPROC)MakeProcInstance(
  239.                 (FARPROC)GetOpenFileNameHook, ghInst);
  240.         ofn.lpTemplateName = NULL;
  241.     
  242.         EnteringDialog(idDlg, &idPrevDlg, TRUE);
  243.         fGotName = GetOpenFileName(&ofn);
  244.         EnteringDialog(idPrevDlg, NULL, FALSE);
  245.     
  246.         FreeProcInstance((FARPROC)ofn.lpfnHook);
  247.     
  248.         return fGotName;
  249.     }
  250.     
  251.     
  252.     
  253.     /************************************************************************
  254.     * SaveAsDlg
  255.     *
  256.     *
  257.     *
  258.     * Arguments:
  259.     *
  260.     * History:
  261.     *
  262.     ************************************************************************/
  263.     
  264.     BOOL SaveAsDlg(
  265.         PSTR pszFileName,
  266.         INT iType)
  267.     {
  268.         INT idDlg;
  269.         BOOL fGotName;
  270.         INT idPrevDlg;
  271.         CHAR szFilter[CCHTEXTMAX];
  272.     
  273.         switch (iType) {
  274.             case FT_BITMAP:
  275.                 AddFilterString(szFilter, ids(IDS_BMPFILTER),
  276.                         ids(IDS_BMPFILTEREXT), TRUE);
  277.     
  278.                 ofn.lpstrDefExt = ids(IDS_DEFEXTBMP);
  279.                 idDlg = DID_COMMONFILESAVE;
  280.     
  281.                 break;
  282.     
  283.             case FT_ICON:
  284.                 AddFilterString(szFilter, ids(IDS_ICOFILTER),
  285.                         ids(IDS_ICOFILTEREXT), TRUE);
  286.     
  287.                 ofn.lpstrDefExt = ids(IDS_DEFEXTICO);
  288.                 idDlg = DID_COMMONFILESAVE;
  289.     
  290.                 break;
  291.     
  292.             case FT_CURSOR:
  293.                 AddFilterString(szFilter, ids(IDS_CURFILTER),
  294.                         ids(IDS_CURFILTEREXT), TRUE);
  295.     
  296.                 ofn.lpstrDefExt = ids(IDS_DEFEXTCUR);
  297.                 idDlg = DID_COMMONFILESAVE;
  298.     
  299.                 break;
  300.     
  301.             case FT_PALETTE:
  302.                 AddFilterString(szFilter, ids(IDS_PALFILTER),
  303.                         ids(IDS_PALFILTEREXT), TRUE);
  304.     
  305.                 ofn.lpstrDefExt = ids(IDS_DEFEXTPAL);
  306.                 idDlg = DID_COMMONFILESAVEPAL;
  307.     
  308.                 break;
  309.         }
  310.     
  311.         ofn.lStructSize = sizeof(OPENFILENAME);
  312.         ofn.hwndOwner = ghwndMain;
  313.         ofn.hInstance = NULL;
  314.         ofn.lpstrFilter = szFilter;
  315.         ofn.lpstrCustomFilter = NULL;
  316.         ofn.nMaxCustFilter = 0;
  317.         ofn.nFilterIndex = 1;
  318.         ofn.lpstrFile = pszFileName;
  319.         ofn.nMaxFile = CCHMAXPATH;
  320.         ofn.lpstrFileTitle = NULL;
  321.         ofn.nMaxFileTitle = 0;
  322.         ofn.lpstrInitialDir = NULL;
  323.         ofn.lpstrTitle = NULL;
  324.         ofn.Flags = OFN_OVERWRITEPROMPT | OFN_HIDEREADONLY | OFN_SHOWHELP;
  325.         ofn.nFileOffset = 0;
  326.         ofn.nFileExtension = 0;
  327.         ofn.lCustData = 0;
  328.         ofn.lpfnHook = NULL;
  329.         ofn.lpTemplateName = NULL;
  330.     
  331.         EnteringDialog(idDlg, &idPrevDlg, TRUE);
  332.         fGotName = GetSaveFileName(&ofn);
  333.         EnteringDialog(idPrevDlg, NULL, FALSE);
  334.     
  335.         return fGotName;
  336.     }
  337.     
  338.     
  339.     
  340.     /************************************************************************
  341.     * GetOpenFileNameHook
  342.     *
  343.     * This function is the hook function for the Common Dialogs
  344.     * GetOpenFileName funtion.  It is used to be sure the default
  345.     * extension that is used when the function exits is the same
  346.     * as the image file type that the user specifies they want
  347.     * opened.
  348.     *
  349.     * Arguments:
  350.     *
  351.     * History:
  352.     *
  353.     ************************************************************************/
  354.     
  355.     DIALOGPROC GetOpenFileNameHook(
  356.         HWND hwnd,
  357.         UINT msg,
  358.         WPARAM wParam,
  359.         LPARAM lParam)
  360.     {
  361.         switch (msg) {
  362.             case WM_INITDIALOG:
  363.                 /*
  364.                  * Tell Windows to set the focus for me.
  365.                  */
  366.                 return TRUE;
  367.     
  368.             case WM_COMMAND:
  369.                 /*
  370.                  * Did they change the type of file from the File Type
  371.                  * combo box?
  372.                  */
  373.                 if (GET_WM_COMMAND_ID(wParam, lParam) == DID_COMMDLG_TYPECOMBO &&
  374.                         GET_WM_COMMAND_CMD(wParam, lParam) == CBN_SELCHANGE) {
  375.                     INT iSelect;
  376.     
  377.                     /*
  378.                      * Get the selected file type, then change the default
  379.                      * extension field of the ofn structure to match it.
  380.                      * This ensures that the proper default extension
  381.                      * gets added to the end of the file name if the user
  382.                      * does not specify an extension explicitly.
  383.                      */
  384.                     if ((iSelect = (INT)SendDlgItemMessage(hwnd,
  385.                             DID_COMMDLG_TYPECOMBO, CB_GETCURSEL, 0, 0L))
  386.                             != CB_ERR) {
  387.                         ofn.lpstrDefExt = (LPCSTR)DefExtFromFilter(
  388.                                 iSelect, (PSTR)ofn.lpstrFilter);
  389.                     }
  390.                 }
  391.     
  392.                 break;
  393.         }
  394.     
  395.         /*
  396.          * Process the message normally.
  397.          */
  398.         return FALSE;
  399.     }
  400.     
  401.     
  402.     
  403.     /************************************************************************
  404.     * AddFilterString
  405.     *
  406.     * This function adds a filter string pair to a filter string for
  407.     * use by the common dialog open/save file functions.  The string
  408.     * pair will be added to the end of the given filter string, unless
  409.     * fFirst is TRUE, in which case it will be written out to the
  410.     * start of the buffer.  A double null will always be written out
  411.     * at the end of the filter string.
  412.     *
  413.     * Arguments:
  414.     *   PSTR pszBuf  - Buffer to write to.
  415.     *   PSTR pszType - Type string.  Something like "Icon files (*.ico)".
  416.     *   PSTR pszExt  - Extension string.  Something like "*.ico".
  417.     *   BOOL fFirst  - TRUE if this is the first filter string in the
  418.     *                  buffer.  If FALSE, the new filter string pair will
  419.     *                  be added to the end of pszBuf.
  420.     *
  421.     * History:
  422.     *
  423.     ************************************************************************/
  424.     
  425.     STATICFN VOID NEAR AddFilterString(
  426.         PSTR pszBuf,
  427.         PSTR pszType,
  428.         PSTR pszExt,
  429.         BOOL fFirst)
  430.     {
  431.         PSTR psz;
  432.     
  433.         psz = pszBuf;
  434.     
  435.         /*
  436.          * If this is not the first filter string pair, skip to the
  437.          * terminating double null sequence.
  438.          */
  439.         if (!fFirst) {
  440.             while (*psz || *(psz + 1))
  441.                 psz++;
  442.     
  443.             psz++;
  444.         }
  445.     
  446.         strcpy(psz, pszType);
  447.         psz += strlen(pszType) + 1;
  448.         strcpy(psz, pszExt);
  449.         psz += strlen(pszExt) + 1;
  450.         *psz = '\0';
  451.     }
  452.     
  453.     
  454.     
  455.     /************************************************************************
  456.     * DefExtFromFilter
  457.     *
  458.     * This function returns the default extension for the given index
  459.     * from the specified filter string chain.  The filter string chain
  460.     * is in the format expected by the GetSaveFileName function.
  461.     *
  462.     * It will return NULL if the filter extension found is "*.*".
  463.     *
  464.     * Arguments:
  465.     *   INT index      - Zero based index to the filter string.
  466.     *   PSTR pszFilter - Pointer to the start of the filter chain.
  467.     *
  468.     * History:
  469.     *
  470.     ************************************************************************/
  471.     
  472.     STATICFN PSTR NEAR DefExtFromFilter(
  473.         INT index,
  474.         PSTR pszFilter)
  475.     {
  476.         if (!pszFilter)
  477.             return NULL;
  478.     
  479.         /*
  480.          * Skip to the specified filter string pair.
  481.          */
  482.         while (index--) {
  483.             pszFilter += strlen(pszFilter) + 1;
  484.             pszFilter += strlen(pszFilter) + 1;
  485.         }
  486.     
  487.         /*
  488.          * Skip the first string, then skip the '*' and the '.'.
  489.          */
  490.         pszFilter += strlen(pszFilter) + 1 + 1 + 1;
  491.     
  492.         /*
  493.          * If the string found was "*.*", return NULL for the default
  494.          * extension.
  495.          */
  496.         if (*pszFilter == '*')
  497.             return NULL;
  498.     
  499.         /*
  500.          * Return a pointer to the default extension.  This will be
  501.          * something like "bmp" or "ico".
  502.          */
  503.         return pszFilter;
  504.     }
  505.     
  506.     
  507.     
  508.     /************************************************************************
  509.     * VerifySaveFile
  510.     *
  511.     * Prompts the user if they want to save the current file to disk.
  512.     * If Yes, calls the appropriate save routine.
  513.     *
  514.     * Returns:
  515.     *   Returns TRUE if either the file was not dirty (no save was done)
  516.     *   or if it was and the user did not want to save it or the file
  517.     *   was dirty and the user wanted to save it and the save was
  518.     *   successful.
  519.     *
  520.     *   Returns FALSE if the user cancelled the operation, or an error
  521.     *   occured with the save.
  522.     *
  523.     * History:
  524.     *
  525.     ************************************************************************/
  526.     
  527.     BOOL VerifySaveFile(VOID)
  528.     {
  529.         if (fImageDirty || fFileDirty) {
  530.             switch (Message(MSG_SAVEFILE,
  531.                     gpszFileName ? gpszFileName : ids(IDS_UNTITLED))) {
  532.                 case IDYES:
  533.                     return SaveFile(FALSE);
  534.     
  535.                 case IDNO:
  536.                     fImageDirty = FALSE;
  537.                     break;
  538.     
  539.                 case IDCANCEL:
  540.                     return FALSE;
  541.             }
  542.         }
  543.     
  544.         return TRUE;
  545.     }
  546.     
  547.     
  548.     
  549.     /************************************************************************
  550.     * SaveFile
  551.     *
  552.     * Does a save of the current file.  If the file is untitled, it
  553.     * will ask the user for a file name.
  554.     *
  555.     * Arguments:
  556.     *   BOOL fSaveAs - TRUE to force a Save As operation (always prompts
  557.     *                  for the file name).
  558.     *
  559.     * Returns:
  560.     *   Returns TRUE if the save was successful.
  561.     *
  562.     *   Returns FALSE if the user cancelled the operation, or an error
  563.     *   occured with the save.
  564.     *
  565.     * History:
  566.     *
  567.     ************************************************************************/
  568.     
  569.     BOOL SaveFile(
  570.         BOOL fSaveAs)
  571.     {
  572.         CHAR szFileName[CCHMAXPATH];
  573.     
  574.         if (gnImages == 0) {
  575.             Message(MSG_NOIMAGES);
  576.             return FALSE;
  577.         }
  578.     
  579.         if (gpszFileName)
  580.             strcpy(szFileName, gszFullFileName);
  581.         else
  582.             *szFileName = '\0';
  583.     
  584.         if (fSaveAs || !gpszFileName) {
  585.             if (!SaveAsDlg(szFileName, giType))
  586.                 return FALSE;
  587.         }
  588.     
  589.         switch (giType) {
  590.             case FT_BITMAP:
  591.                 return SaveBitmapFile(szFileName);
  592.     
  593.             case FT_ICON:
  594.             case FT_CURSOR:
  595.                 return SaveIconCursorFile(szFileName, giType);
  596.         }
  597.     
  598.         return FALSE;
  599.     }
  600.     
  601.     
  602.     
  603.     /************************************************************************
  604.     * OpenAFile
  605.     *
  606.     * Prompts for a file name to open and then does the loading of it.
  607.     *
  608.     * History:
  609.     *
  610.     ************************************************************************/
  611.     
  612.     BOOL OpenAFile(VOID)
  613.     {
  614.         CHAR szFileName[CCHMAXPATH];
  615.     
  616.         if (OpenDlg(szFileName, giType)) {
  617.             /*
  618.              * Clear out the current resource.
  619.              */
  620.             ClearResource();
  621.     
  622.             LoadFile(szFileName);
  623.     
  624.             return TRUE;
  625.         }
  626.         else {
  627.             return FALSE;
  628.         }
  629.     }
  630.     
  631.     
  632.     
  633.     /************************************************************************
  634.     * LoadFile
  635.     *
  636.     * Loads the specified file for editing.
  637.     *
  638.     * Arguments:
  639.     *   PSTR pszFullFileName - Full path name to the file to load.
  640.     *
  641.     * History:
  642.     *
  643.     ************************************************************************/
  644.     
  645.     STATICFN BOOL NEAR LoadFile(
  646.         PSTR pszFullFileName)
  647.     {
  648.         switch (GetTypeFromExt(pszFullFileName)) {
  649.             case FT_BITMAP:
  650.                 return LoadBitmapFile(pszFullFileName);
  651.     
  652.             case FT_ICON:
  653.                 return LoadIconCursorFile(pszFullFileName, TRUE);
  654.     
  655.             case FT_CURSOR:
  656.                 return LoadIconCursorFile(pszFullFileName, FALSE);
  657.         }
  658.     
  659.         return FALSE;
  660.     }
  661.     
  662.     
  663.     
  664.     /************************************************************************
  665.     * GetTypeFromExt
  666.     *
  667.     * Returns the type of file based on it's file name extension.
  668.     *
  669.     * Arguments:
  670.     *   PSTR pszFileName - File name to check.
  671.     *
  672.     * History:
  673.     *
  674.     ************************************************************************/
  675.     
  676.     STATICFN INT NEAR GetTypeFromExt(
  677.         PSTR pszFileName)
  678.     {
  679.         PSTR pszExt;
  680.     
  681.         pszExt = pszFileName + strlen(pszFileName) - 3;
  682.     
  683.         if (strcmpi(pszExt, ids(IDS_DEFEXTICO)) == 0)
  684.             return FT_ICON;
  685.         else if (strcmpi(pszExt, ids(IDS_DEFEXTCUR)) == 0)
  686.             return FT_CURSOR;
  687.         else
  688.             return FT_BITMAP;
  689.     }
  690.     
  691.     
  692.     
  693.     /************************************************************************
  694.     * OpenCmdLineFile
  695.     *
  696.     * Handles opening of the file specified on the command line.
  697.     *
  698.     * History:
  699.     * Nov 7, 1989   Byron Dazey - Created
  700.     *
  701.     ************************************************************************/
  702.     
  703.     VOID OpenCmdLineFile(
  704.         PSTR pstrFileName)
  705.     {
  706.         CHAR szFullPath[CCHMAXPATH];
  707.         OFSTRUCT OfStruct;
  708.     
  709.         strcpy(szFullPath, pstrFileName);
  710.     
  711.         /*
  712.          * If the file name does not already have an extension,
  713.          * assume it is a bitmap file and add a .BMP extension
  714.          * to it.
  715.          */
  716.         FileCat(szFullPath, ids(IDS_DOTBMP));
  717.     
  718.         if ((HFILE)OpenFile(szFullPath, &OfStruct, OF_EXIST) == (HFILE)-1) {
  719.             Message(MSG_CANTOPEN, pstrFileName);
  720.         }
  721.         else {
  722.             LoadFile(OfStruct.szPathName);
  723.         }
  724.     }
  725.     
  726.     
  727.     
  728.     /************************************************************************
  729.     * FileCat
  730.     *
  731.     * This function checks for an extension on the give file name.
  732.     * If an extension is not found, the extension specified by
  733.     * pchCat is added to the file name.
  734.     *
  735.     * Arguments:
  736.     *     PSTR pch          = The file spec to "cat" the extension to.
  737.     *     PSTR pchCat       = The extension to "cat" on to pch,
  738.     *                         including the '.'
  739.     *
  740.     * History:
  741.     *
  742.     ************************************************************************/
  743.     
  744.     STATICFN VOID NEAR FileCat(
  745.         PSTR pchName,
  746.         PSTR pchCat)
  747.     {
  748.         PSTR pch;
  749.     
  750.         pch = pchName + strlen(pchName);
  751.         pch = FAR2NEAR(AnsiPrev(pchName, pch));
  752.     
  753.         /* back up to '.' or '\\' */
  754.         while (*pch != '.') {
  755.             if (*pch == '\\' || pch <= pchName) {
  756.                 /* no extension, add one */
  757.                 strcat(pchName, pchCat);
  758.                 return;
  759.             }
  760.     
  761.             pch = FAR2NEAR(AnsiPrev(pchName, pch));
  762.         }
  763.     }
  764.     
  765.     
  766.     
  767.     /************************************************************************
  768.     * MyFileRead
  769.     *
  770.     *
  771.     *
  772.     * Arguments:
  773.     *
  774.     * History:
  775.     *
  776.     ************************************************************************/
  777.     
  778.     BOOL MyFileRead(
  779.         HFILE hf,
  780.         LPSTR lpBuffer,
  781.         UINT nBytes,
  782.         PSTR pszFileName,
  783.         INT iType)
  784.     {
  785.         register UINT cb;
  786.     
  787.         cb = _lread((HFILE)hf, lpBuffer, nBytes);
  788.     
  789.         if (cb == -1) {
  790.             Message(MSG_READERROR, pszFileName);
  791.             return FALSE;
  792.         }
  793.         else if (cb != nBytes) {
  794.             Message((iType == FT_BITMAP) ? MSG_BADBMPFILE : MSG_BADICOCURFILE,
  795.                 pszFileName);
  796.             return FALSE;
  797.         }
  798.         else {
  799.             return TRUE;
  800.         }
  801.     }
  802.     
  803.     
  804.     
  805.     /************************************************************************
  806.     * MyFileWrite
  807.     *
  808.     *
  809.     *
  810.     * Arguments:
  811.     *
  812.     * History:
  813.     *
  814.     ************************************************************************/
  815.     
  816.     BOOL MyFileWrite(
  817.         HFILE hf,
  818.         LPSTR lpBuffer,
  819.         UINT nBytes,
  820.         PSTR pszFileName)
  821.     {
  822.         register UINT cb;
  823.     
  824.         cb = _lwrite((HFILE)hf, lpBuffer, nBytes);
  825.     
  826.         if (cb == -1 || cb != nBytes) {
  827.             Message(MSG_WRITEERROR, pszFileName);
  828.             return FALSE;
  829.         }
  830.         else {
  831.             return TRUE;
  832.         }
  833.     }
  834.