home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / tolkit45.zip / os2tk45 / samples / os2 / eaedit / easfile.c < prev    next >
C/C++ Source or Header  |  1999-05-11  |  19KB  |  458 lines

  1. /*static char *SCCSID = "@(#)easfile.c    6.13 92/03/18";*/
  2. /*==============================================================*\
  3.  *                                                              *
  4.  * EASFILE.C                                                    *
  5.  *    (C) Copyright IBM Corporation 1992.                       *
  6.  *--------------------------------------------------------------*
  7.  *  This module contains subroutines for eas.c that specifically*
  8.  *  deal with the Open file interface. Most of the routines were*
  9.  *  taken from Charles Petzold's book "Programming the OS/2     *
  10.  *  Presentation Manager" and were slightly modified.           *
  11.  *                                                              *
  12.  *--------------------------------------------------------------*
  13.  *  Procedures in this file:                                    *
  14.  *   OpenFile()        Asks user for new file name and opens it *
  15.  *   OpenFileProc()    Dialog proc that prompts user file name  *
  16.  *   FillDirListBox()  Fills the directory list box             *
  17.  *   FillFileListBox() Fills the file list box                  *
  18.  *                                                              *
  19. \*==============================================================*/
  20. /*--------------------------------------------------------------*\
  21.  *  Include files, macros, defined constants, and externs       *
  22. \*--------------------------------------------------------------*/
  23. #include "eas.h"
  24.  
  25. extern EADATA ConvTable[EATABLESIZE];
  26.  
  27. /****************************************************************\
  28.  *                                                              *
  29.  *  Name:    OpenFile(hwnd, usMode)                             *
  30.  *                                                              *
  31.  *  Purpose: This routine handles opening a new file.  It will  *
  32.  *           also query the user for the disposition of the     *
  33.  *           current file if it has been modified before loading*
  34.  *           the new file.                                      *
  35.  *                                                              *
  36.  *  Usage  : This routine is called by MainDlgProc to deal with *
  37.  *           the Open file interface.                           *
  38.  *                                                              *
  39.  *  Method : Routine should be bullet proof as it does its own  *
  40.  *           error checking.  It assumes that hwnd points to the*
  41.  *           correct window with the name listbox in it.        *
  42.  *                                                              *
  43.  *  Returns: TRUE if a file is open upon exit.                  *
  44.  *                                                              *
  45. \****************************************************************/
  46. BOOL OpenFile(HWND hwnd, ULONG usMode)
  47. {
  48.    CHAR szOldFile[CCHMAXPATH];
  49.    HFILE  FileHandle=0;
  50.    ULONG  ulAct=0L;
  51.  
  52.    strcpy(szOldFile,szFileName);  /* Save name of the currently open file */
  53.  
  54.    if(usMode != ARGFILE)                /* It isn't the command line file */
  55.    {
  56.       if(!WinDlgBox(HWND_DESKTOP,      /* Get the file name from the user */
  57.                     hwnd,
  58.                     OpenFileProc,
  59.                     '\0',
  60.                     IDD_OPENBOX,
  61.                     NULL))
  62.       {
  63.          strcpy(szFileName,szOldFile); /* They canceled, restore old file */
  64.          return(FILE_ISOPEN);
  65.       }
  66.    }
  67.                              /* Check filename availble or not */
  68.    if( DosOpen(szFileName, &FileHandle, &ulAct, 0L, FILE_NORMAL,
  69.                         FILE_OPEN, OPEN_SHARE_DENYWRITE, NULL) )
  70.    {
  71.       MessageBox(hwnd, IDMSG_ERRORFILEOPEN, "Error !",
  72.                        MB_OK | MB_ERROR, TRUE);
  73.       return(FILE_ISOPEN);
  74.    }
  75.    else                 /* File is existed and availble to use */
  76.       DosClose(FileHandle);
  77.  
  78.    if(FILE_ISOPEN) /* Free up everything associated with the current file */
  79.    {
  80.       Free_FEAList(pHoldFEA,pDelList);
  81.       FILE_ISOPEN = FALSE;
  82.    }
  83.  
  84.    if(QueryEAs(szFileName))                         /* We were successful */
  85.    {
  86.       HOLDFEA *pFEA=pHoldFEA;
  87.  
  88.       FILE_ISOPEN = TRUE;
  89.       FILE_CHANGED = FALSE;
  90.  
  91.       WinSendDlgItemMsg(hwnd, IDD_WINLBOX, LM_DELETEALL,0L,0L); /* Fill L-box */
  92.  
  93.       while(pFEA)
  94.       {
  95.          WinSendDlgItemMsg(hwnd, IDD_WINLBOX, LM_INSERTITEM,
  96.                            MPFROM2SHORT(LIT_END,0),
  97.                            MPFROMP(pFEA->szName));
  98.          pFEA = pFEA->next;
  99.       }
  100.    }
  101.    else                                      /* We couldn't query the EAs */
  102.    {
  103.       *szFileName = '\000';
  104.       memset(szEAType, 0, sizeof(szEAType) );
  105.       WinInvalidateRect(hwndMain, NULL, FALSE);
  106.       FILE_ISOPEN = FALSE;
  107.       return (FILE_ISOPEN);
  108.    }
  109.    memset(szEAType, 0, sizeof(szEAType) );
  110.    WinInvalidateRect(hwndMain, NULL, FALSE);
  111.    pDelList = NULL;
  112.    return(TRUE);
  113. }
  114.  
  115. /****************************************************************\
  116.  *                                                              *
  117.  *  Name:    OpenFileProc(hwnd, msg, mp1, mp2)                  *
  118.  *                                                              *
  119.  *  Purpose: This proc handles the user interface to select a   *
  120.  *           file name. Some elementary checks are done to make *
  121.  *           sure the filename is valid.                        *
  122.  *                                                              *
  123.  *  Usage  : This routine is called by OpenFile to open the file*
  124.  *                                                              *
  125.  *  Method : The interface is NOT foolproof as it is possible to*
  126.  *           continue with a non-existant file name.  Also,     *
  127.  *           users are not currently allowed to view/edit the   *
  128.  *           EAs attached to a directory.                       *
  129.  *                                                              *
  130.  *  Returns: TRUE if selects OK, FALSE if Cancel is selected.   *
  131.  *                                                              *
  132. \****************************************************************/
  133. MRESULT EXPENTRY OpenFileProc(HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
  134. {
  135.    static CHAR szCurrentPath[CCHMAXPATH]={'.', '\\', '*', '\000'},
  136.                 szBuffer[CCHMAXPATH];
  137.    CHAR        szParsedPath[CCHMAXPATH];
  138.    SHORT       sSelect;
  139.    MRESULT sRC;
  140.  
  141.    switch(msg)
  142.    {
  143.       case WM_INITDLG:
  144.          FixSysMenu(hwnd);
  145.          FillDirListBox(hwnd,szCurrentPath);
  146.          FillFileListBox(hwnd);
  147.          WinSendDlgItemMsg(hwnd, IDD_FILEEDIT,EM_SETTEXTLIMIT,
  148.                                  MPFROM2SHORT(CCHMAXPATH,0),NULL);
  149.          return (MRESULT)0L;
  150.  
  151.       case WM_CONTROL:                      /* An lbox item is selected */
  152.          if(SHORT1FROMMP(mp1) == IDD_DIRLIST ||
  153.             SHORT1FROMMP(mp1) == IDD_FILELIST)
  154.          {                                        /* Get item->szBuffer */
  155.             sSelect = (USHORT) WinSendDlgItemMsg(hwnd,
  156.                                SHORT1FROMMP(mp1),
  157.                                LM_QUERYSELECTION, 0L, 0L);
  158.  
  159.             WinSendDlgItemMsg(hwnd, SHORT1FROMMP(mp1),
  160.                               LM_QUERYITEMTEXT,
  161.                               MPFROM2SHORT(sSelect, sizeof(szBuffer)),
  162.                               MPFROMP(szBuffer));
  163.          }
  164.  
  165.          switch(SHORT1FROMMP(mp1))
  166.          {
  167.             case IDD_DIRLIST:          /* Item was in the directory lbox */
  168.                switch(SHORT2FROMMP(mp1))
  169.                {
  170.                   case LN_ENTER:           /* Go to the select drive/dir */
  171.                      if(*szBuffer == ' ')
  172.                         DosSelectDisk(*(szBuffer+1) - '@');
  173.                      else
  174.                         DosSetCurrentDir(szBuffer);
  175.  
  176.                      FillDirListBox(hwnd, szCurrentPath);
  177.                      FillFileListBox(hwnd);
  178.  
  179.                      WinSetDlgItemText(hwnd, IDD_FILEEDIT, "");
  180.                      return (MRESULT)0L;
  181.                }
  182.                break;
  183.  
  184.             case IDD_FILELIST:             /* Item was in the file lbox */
  185.                switch(SHORT2FROMMP(mp1))
  186.                {
  187.                   case LN_SELECT:          /* Copy name to entry field  */
  188.                      WinSetDlgItemText(hwnd, IDD_FILEEDIT, szBuffer);
  189.                      return (MRESULT)0L;
  190.  
  191.                   case LN_ENTER:              /* Try to query the file */
  192.                      if(ParseFileName(szFileName, szBuffer) != FILE_VALID)
  193.                         return 0;          /* Some error, don't finish */
  194.                      WinDismissDlg(hwnd, TRUE);
  195.                      return (MRESULT)0L;
  196.                }
  197.                break;
  198.          }
  199.          break;
  200.  
  201.       case WM_COMMAND:
  202.          switch(LOUSHORT(mp1))
  203.          {
  204.             case DID_OK:       /* Try to query file in the entry field */
  205.                memset(szBuffer, 0, sizeof(szBuffer) );
  206.                WinQueryDlgItemText(hwnd, IDD_FILEEDIT,
  207.                                    sizeof(szBuffer), szBuffer);
  208.                                          /* Check filename availble or not */
  209.                if(*szBuffer == '\000')
  210.                {
  211.                   MessageBox(hwnd, IDMSG_NOFILEOPEN, "Error !",
  212.                                    MB_OK | MB_ERROR, TRUE);
  213.                   return FALSE;
  214.                }
  215.                switch(ParseFileName(szParsedPath, szBuffer))
  216.                {
  217.                   case FILE_INVALID:            /* Can't open the file */
  218.                      WinAlarm(HWND_DESKTOP, WA_ERROR);
  219.                      FillDirListBox(hwnd, szCurrentPath);
  220.                      FillFileListBox(hwnd);
  221.                      return (MRESULT)0L;
  222.  
  223.                   case FILE_PATH:    /* It was an incomplete path name */
  224.                      strcpy(szCurrentPath,szBuffer);
  225.                      FillDirListBox(hwnd, szCurrentPath);
  226.                      FillFileListBox(hwnd);
  227.                      WinSetDlgItemText(hwnd, IDD_FILEEDIT, "");
  228.                      return (MRESULT)0L;
  229.  
  230.                   case FILE_VALID:                     /* It was valid */
  231.                      strcpy(szFileName, szParsedPath);
  232.                      WinDismissDlg(hwnd, TRUE);
  233.                      return (MRESULT)0L;
  234.                }
  235.                break;
  236.  
  237.             case DID_CANCEL:
  238.                WinDismissDlg(hwnd, FALSE);
  239.                return (MRESULT)0L;
  240.          }
  241.          break;
  242.  
  243.       case WM_CLOSE:
  244.          WinDismissDlg(hwnd, FALSE);
  245.          return (MRESULT)0L;
  246.  
  247.    }
  248.    sRC = WinDefDlgProc(hwnd, msg, mp1, mp2);
  249.    return sRC;
  250. }
  251.  
  252. /****************************************************************\
  253.  *                                                              *
  254.  *  Name:    FillDirListBox(hwnd, pcCurrentPath)                *
  255.  *                                                              *
  256.  *  Purpose: This routine is called by OpenFileProc to fill in  *
  257.  *           the directory list box                             *
  258.  *                                                              *
  259.  *  Usage  : This routine is called by OpenFileProc to fill the *
  260.  *           file list box.                                     *
  261.  *                                                              *
  262.  *  Method : Adequete error checking is NOT done on the return  *
  263.  *           values of the system calls.  Also, it is remotely  *
  264.  *           possible that the calls to add to the list box     *
  265.  *           could fail.                                        *
  266.  *                                                              *
  267.  *  Returns: VOID                                               *
  268.  *                                                              *
  269. \* **************************************************************/
  270. VOID FillDirListBox(HWND hwnd, CHAR *pcCurrentPath)
  271. {
  272.    static CHAR szDrive [] = "  :";
  273.    FILEFINDBUF3 findbuf;
  274.    HDIR        hDir = HDIR_CREATE;
  275.    SHORT       sDrive;
  276.    ULONG       ulCurPathLen, ulDriveMap=0L, ulSearchCount = 1, ulDriveNum=0L;
  277.  
  278.    memset(&findbuf,0,sizeof(FILEFINDBUF) );
  279.  
  280.    DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);
  281.    *pcCurrentPath     = (CHAR) (ulDriveNum + '@');
  282.    *(pcCurrentPath+1) = ':';
  283.    *(pcCurrentPath+2) = '\\';
  284.    ulCurPathLen = CCHMAXPATH;
  285.    DosQueryCurrentDir(0L, pcCurrentPath + 3, &ulCurPathLen);
  286.  
  287.    WinSetDlgItemText(hwnd, IDD_PATH, pcCurrentPath);
  288.    WinSendDlgItemMsg(hwnd, IDD_DIRLIST, LM_DELETEALL, NULL, NULL);
  289.  
  290.    for(sDrive = ('A'-'A'); sDrive <= ('Z'-'A'); sDrive++)
  291.    {
  292.       if(ulDriveMap & (1L << sDrive))
  293.       {
  294.          *(szDrive+1) = (CHAR) (sDrive + 'A');
  295.  
  296.          WinSendDlgItemMsg(hwnd, IDD_DIRLIST, LM_INSERTITEM,
  297.                            MPFROM2SHORT(LIT_END, 0),
  298.                            MPFROMP(szDrive));
  299.       }
  300.    }
  301.    if (DosFindFirst("*", &hDir, FILE_DIRECTORY, &findbuf,
  302.                 sizeof(findbuf), &ulSearchCount, FIL_STANDARD))
  303.    {
  304.       DosBeep(500,110);
  305.       return;
  306.    }
  307.    while(ulSearchCount)
  308.    {
  309.       if(findbuf.attrFile & 0x0010 &&
  310.          (findbuf.achName[0] != '.' || findbuf.achName[1]))
  311.  
  312.          WinSendDlgItemMsg(hwnd, IDD_DIRLIST, LM_INSERTITEM,
  313.                            MPFROM2SHORT(LIT_SORTASCENDING, 0),
  314.                            MPFROMP(findbuf.achName));
  315.  
  316.       if(DosFindNext(hDir, &findbuf, sizeof(findbuf), &ulSearchCount))
  317.          break;
  318.    }
  319.    return;
  320. }
  321.  
  322. /****************************************************************\
  323.  *                                                              *
  324.  *  Name:    FillFileListBox(hwnd)                              *
  325.  *                                                              *
  326.  *  Purpose: This routine is called by OpenFileProc to fill in  *
  327.  *           the file list box with files in the current        *
  328.  *           directory.                                         *
  329.  *                                                              *
  330.  *  Usage  : This routine is called by OpenFileProc to fill the *
  331.  *           file list box.                                     *
  332.  *                                                              *
  333.  *  Method : Adequete error checking is NOT done on the return  *
  334.  *           values of the system calls.  Also, it is remotely  *
  335.  *           possible that the calls to add to the list box     *
  336.  *           could fail.                                        *
  337.  *                                                              *
  338.  *  Returns: VOID                                               *
  339.  *                                                              *
  340. \****************************************************************/
  341. VOID FillFileListBox(HWND hwnd)
  342. {
  343.    FILEFINDBUF3 findbuf;
  344.    HDIR        hDir = HDIR_CREATE;
  345.    ULONG       ulSearchCount = 1; /* Read 1 entry at a time */
  346.  
  347.    memset(&findbuf,0,sizeof(FILEFINDBUF) );
  348.    WinSendDlgItemMsg(hwnd, IDD_FILELIST, LM_DELETEALL, NULL, NULL);
  349.  
  350.    if (DosFindFirst("*", &hDir, FILE_NORMAL, &findbuf, sizeof(findbuf),
  351.                        &ulSearchCount,FIL_STANDARD))
  352.    {
  353.       DosBeep(700,110);
  354.       return;
  355.    }
  356.    while(ulSearchCount)
  357.    {
  358.       WinSendDlgItemMsg(hwnd, IDD_FILELIST, LM_INSERTITEM,
  359.                         MPFROM2SHORT(LIT_SORTASCENDING, 0),
  360.                         MPFROMP(findbuf.achName));
  361.  
  362.       if(DosFindNext(hDir, &findbuf, sizeof(findbuf), &ulSearchCount))
  363.          break;
  364.    }
  365.    return;
  366. }
  367.  
  368. /****************************************************************\
  369.  *                                                              *
  370.  *  Name:    ParseFileName(pcOut, pcIn)                         *
  371.  *                                                              *
  372.  *  Purpose: This routine changes drive and directory as per    *
  373.  *           pcIn string.                                       *
  374.  *                                                              *
  375.  *  Usage:   Note that pcOut is only valid if FILE_VALID is     *
  376.  *           returned. In place of strupr(), a codepage should  *
  377.  *           be fetched and DosCaseMap() should be used to allow*
  378.  *           for extended chars. This routine could use some    *
  379.  *           cleanup work.                                      *
  380.  *                                                              *
  381.  *  Returns: FILE_INVALID if pcIn had invalid drive or no       *
  382.  *                           directory                          *
  383.  *           FILE_PATH    if pcIn was empty or had just a path/ *
  384.  *                           no file name.                      *
  385.  *           FILE_VALID   if pcIn point to good file.           *
  386.  *                                                              *
  387. \****************************************************************/
  388. LONG ParseFileName(CHAR *pcOut, CHAR *pcIn)
  389. {
  390.    CHAR   *pcLastSlash, *pcFileOnly ;
  391.    ULONG  ulDriveMap, ulDirLen = CCHMAXPATH, ulDriveNum=0L;
  392.  
  393.    strupr(pcIn);   /* Does NOT handle extended chars, should use DosCaseMap */
  394.  
  395.    if(*pcIn == '\000')              /* If string is empty, return FILE_PATH */
  396.  
  397.       return FILE_PATH;
  398.  
  399.                         /* Get drive from input string or use current drive */
  400.    if(*(pcIn+1) == ':')                      /* Yup, they specified a drive */
  401.    {
  402.       if(DosSelectDisk(*pcIn - '@'))            /* Change to selected drive */
  403.          return FILE_INVALID;
  404.       pcIn += 2;
  405.    }
  406.    DosQueryCurrentDisk(&ulDriveNum, &ulDriveMap);      /* Get current drive */
  407.    *pcOut++ = (CHAR) (ulDriveNum + '@');              /* Build drive letter */
  408.    *pcOut++ = ':';
  409.    *pcOut++ = '\\';
  410.  
  411.    if(*pcIn == '\000')  /* If rest of the string is empty, return FILE_PATH */
  412.       return FILE_PATH;
  413.  
  414.        /* Search for the last backslash.  If none, it could be a directory. */
  415.    if(!(pcLastSlash = strrchr(pcIn, '\\')))                  /* No slashes? */
  416.    {
  417.       if(!DosSetCurrentDir(pcIn))
  418.          return FILE_PATH;                            /* It was a directory */
  419.                                        /* Get current dir & attach input fn */
  420.       DosQueryCurrentDir(0L, pcOut, &ulDirLen);
  421.  
  422.       if(*(pcOut+strlen(pcOut)-1) != '\\')
  423.          strcat(pcOut++, "\\");
  424.  
  425.       strcat(pcOut, pcIn);
  426.       return FILE_VALID;
  427.    }
  428.                /* If the only backslash is at the beginning, change to root */
  429.    if(pcIn == pcLastSlash)
  430.    {
  431.       DosSetCurrentDir("\\");
  432.  
  433.       if(*(pcIn+1) == '\000')
  434.          return FILE_PATH;
  435.  
  436.       strcpy(pcOut, pcIn+1);
  437.       return FILE_VALID;
  438.    }
  439.                    /* Attempt to change directory -- Get current dir if OK */
  440.   *pcLastSlash = '\0';
  441.  
  442.    if(DosSetCurrentDir(pcIn))
  443.       return FILE_INVALID;
  444.  
  445.    DosQueryCurrentDir(0L, pcOut, &ulDirLen);
  446.                                             /* Append input filename if any */
  447.    pcFileOnly = pcLastSlash+1;
  448.  
  449.    if(*pcFileOnly == '\000')
  450.       return FILE_PATH;
  451.  
  452.    if(*(pcOut+strlen(pcOut)-1) != '\\')
  453.       strcat(pcOut++, "\\");
  454.  
  455.    strcat(pcOut, pcFileOnly);
  456.    return FILE_VALID;
  457. }
  458.