home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Professional / OS2PRO194.ISO / os2 / sysutils / nead / neadfile.c < prev   
Encoding:
C/C++ Source or Header  |  1990-07-05  |  14.5 KB  |  460 lines

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