home *** CD-ROM | disk | FTP | other *** search
/ Club Amiga de Montreal - CAM / CAM_CD_1.iso / files / 073.lha / FileIO / filename.c < prev    next >
Encoding:
C/C++ Source or Header  |  1987-06-02  |  10.2 KB  |  376 lines

  1.  
  2. /* *** filename.c ***********************************************************
  3.  *
  4.  * File IO Suite  --  File Name Construction Routines
  5.  *     from Book 1 of the Amiga Programmers' Suite by RJ Mical
  6.  *
  7.  * Copyright (C) 1986, 1987, Robert J. Mical
  8.  * All Rights Reserved.
  9.  *
  10.  * Created for Amiga developers.
  11.  * Any or all of this code can be used in any program as long as this
  12.  * entire copyright notice is retained, ok?  Thanks.
  13.  *
  14.  * HISTORY      NAME            DESCRIPTION
  15.  * -----------  --------------  --------------------------------------------
  16.  * 4 Feb 87     RJ              Real release
  17.  * 12 Aug 86    RJ >:-{)*       Prepare (clean house) for release
  18.  * 3 May 86     =RJ Mical=      Fix prop gadget for both 1.1 and 1.2
  19.  * 1 Feb 86     =RJ Mical=      Created this file.
  20.  *
  21.  * *********************************************************************** */
  22.  
  23.  
  24. #define FILEIO_SOURCEFILE
  25. #include "fileio.h"
  26. #include <libraries\dosextens.h>
  27.  
  28.  
  29. #define FRIENDLY_NOT    0
  30. #define FRIENDLY_DRAWER    1
  31. #define FRIENDLY_OTHER     2
  32.  
  33.  
  34.  
  35. VOID BuildNameTable(fileio)
  36. struct FileIOSupport *fileio;
  37. /* This routine searches through the fileio lock for all file entries,
  38.  * and builds a list of the names found.
  39.  * If the user wants Workbench-style pattern matching, filenames are
  40.  * passed through a filter before being added to the list.
  41.  * All directory entries are added to the list.
  42.  */
  43. {
  44.    struct FileInfoBlock *fileinfo;
  45.    UBYTE *ptr;
  46.    UBYTE workname[MAX_NAME_LENGTH + 5]; /* the extra 5 are for the ".info" */
  47.    struct Remember **key;
  48.    ULONG lock;
  49.    SHORT i, flags, type;
  50.    SHORT pick;
  51.  
  52.    fileio->NameCount = 0;
  53.    lock = fileio->DOSLock;
  54.    key = &fileio->NameKey;
  55.    FreeRemember(key, TRUE);
  56.    ClearFlag(fileio->Flags, GOOD_FILENAMES);
  57.  
  58.    if ((fileinfo = (struct FileInfoBlock *)AllocMem(
  59.          sizeof(struct FileInfoBlock), MEMF_CLEAR)) == NULL)
  60.       goto BUILD_EXIT;
  61.  
  62.    SetWaitPointer(OpenReqWindow);
  63.  
  64.    /* Now, first, before we might be interrupted by MessageInterrupt(),
  65.     * check whether or not we're looking in a drawer and, if so, add the
  66.     * entry that allows the user to ascend one drawer.
  67.     */
  68.    if (StringLength(&OpenReqFileIO->DrawerName[0]))
  69.       {
  70.       MakeEntry("\253\253 PRIOR DRAWER", &fileio->NameKey, NAMED_PREVIOUS);
  71.       /* bump the master count */
  72.       fileio->NameCount++;
  73.       }
  74.  
  75.    /* starting from Examine() until ExNext() is NULL */
  76.    if (Examine(lock, fileinfo))
  77.       while (ExNext(lock, fileinfo))
  78.          {
  79.          /* Default:  this entry is a normal file */
  80.          flags = NULL;
  81.          CopyString(&workname[0], fileinfo->fib_FileName);
  82.  
  83. #ifdef WBENCH_CODE
  84.          /* Now, does the caller want Workbench-style pattern matching? */
  85.          if (FlagIsSet(fileio->Flags, WBENCH_MATCH))
  86.             {
  87.             /* start from location 1 to avoid matching the ".info" file */
  88.             if (ptr = FindSuffix(&workname[1], ".info")) 
  89.                {
  90.                *ptr = '\0';   /* strip the suffix off that baby */
  91.  
  92.                /* Get the friendliness quotient of this .info file */
  93.                type = FriendlyInfoType(&workname[0], fileio);
  94.  
  95.                /* If just not friendly, forget about it */
  96.                if (type == FRIENDLY_NOT) goto NEXT_LOCK;
  97.  
  98.                /* If this was a drawer, set the fileinfo as a directory */
  99.                if (type == FRIENDLY_DRAWER)
  100.                   fileinfo->fib_DirEntryType = 1;
  101.                }
  102.             else goto NEXT_LOCK;
  103.             }
  104. #endif /* ... of WBENCH_CODE conditional */
  105.  
  106.          if (fileinfo->fib_DirEntryType >= 0)
  107.             {
  108.             /* This entry is a directory */
  109.             flags = NAMED_DIRECTORY;
  110.  
  111.             /* If you change the following text, change DIR_TEXT_SIZE too */
  112.             for (i = StringLength(&workname[0]); i >= 0; i--)
  113.                workname[i + DIR_TEXT_SIZE] = workname[i];
  114.             workname[0] = '\273';
  115.             workname[1] = '\273';
  116.             workname[2] = ' ';
  117.             }
  118.  
  119.          pick = MakeEntry(&workname[0], &fileio->NameKey, flags);
  120.          /* bump the master count */
  121.          fileio->NameCount++;
  122.  
  123.          if (pick <= fileio->CurrentPick)
  124.             fileio->CurrentPick++;
  125.  
  126.          InitOpenProp(FALSE);
  127.          StuffSelectNames(2);
  128.  
  129. NEXT_LOCK:
  130.          /* If there's a message pending, split with what we've got */
  131.          if (MessageInterrupt()) goto EXAMINE_DONE;
  132.          }
  133.  
  134.    SetFlag(fileio->Flags, GOOD_FILENAMES);
  135.  
  136.  
  137. EXAMINE_DONE:
  138.  
  139.    if (OpenReqWindow) ClearPointer(OpenReqWindow);
  140.    FreeMem(fileinfo, sizeof(struct FileInfoBlock));
  141.  
  142.  
  143. BUILD_EXIT: ;
  144. }
  145.  
  146.  
  147.  
  148. VOID PropInterrupt()
  149. /* This routine is called by MessageInterrupt() if the prop gadget 
  150.  * is played with while the file name table is being built.  
  151.  * As long as the user is using the proportional gadget, hang around here. 
  152.  */
  153. {
  154.    struct IntuiMessage *message;
  155.    struct Gadget *gadget;
  156.    BOOL mousemove;
  157.  
  158.    FOREVER
  159.       {
  160.       WaitPort(OpenReqWindow->UserPort);
  161.       mousemove = FALSE;
  162.  
  163.       while (message = GetMsg(OpenReqWindow->UserPort))
  164.          {
  165.          switch (message->Class)
  166.             {
  167.             case GADGETUP:
  168.                gadget = (struct Gadget *)message->IAddress;
  169.                switch (gadget->GadgetID)
  170.                   {
  171.                   case OPENGADGET_PROPGADGET:
  172.                      ReplyMsg(message);
  173.                      HandleGadget(gadget, 0, 0, 0, 0);
  174.                      return;
  175.  
  176.                   default:
  177.                      goto MESSAGE_RETURN;
  178.                   }
  179.                break;
  180.  
  181.             case MOUSEMOVE:
  182.                ReplyMsg(message);
  183.                mousemove = TRUE;
  184.                break;
  185.  
  186.             default:
  187.                goto MESSAGE_RETURN;
  188.  
  189.             }
  190.          }
  191.  
  192.       if (mousemove) PropMouseMoves();
  193.       }
  194.  
  195. MESSAGE_RETURN:
  196.    /* Pretend we didn't see this message */
  197.    AddHead(&OpenReqWindow->UserPort->mp_MsgList, message);
  198. }
  199.  
  200.  
  201.  
  202. BOOL MessageInterruptGrunt(message)
  203. struct IntuiMessage *message;
  204. /* Test if there's a gadget type of message at the window port, 
  205.  * react to it if there is one, and return TRUE if the message is 
  206.  * one that should interrupt the building of the file name list.
  207.  */
  208. {
  209.    ULONG class;
  210.    SHORT x, y;
  211.    struct Gadget *gadget;
  212.    LONG seconds, micros;
  213.  
  214.    class = message->Class;
  215.    if ((class == GADGETDOWN) || (class == GADGETUP))
  216.       {
  217.       gadget = (struct Gadget *)message->IAddress;
  218.       x = message->MouseX;
  219.       y = message->MouseY;
  220.       seconds = message->Seconds;
  221.       micros = message->Micros;
  222.       OpenReqSupport.SelectedGadgetID = gadget->GadgetID;
  223.  
  224.       switch (gadget->GadgetID)
  225.          {
  226.          case OPENGADGET_SELECTNAME:
  227.             y = HandleSelect(y, seconds, micros);
  228.             if ((y == -1) || (y == 1))
  229.                {
  230.                /* Pretend we didn't see this message */
  231.                AddHead(&OpenReqWindow->UserPort->mp_MsgList, message);
  232.                return(TRUE);
  233.                }
  234.  
  235.             StuffFileName();
  236.             StuffSelectNames(5);
  237.             goto REPLY_AND_RETURN_FALSE;
  238.  
  239.          case OPENGADGET_UPGADGET:
  240.          case OPENGADGET_DOWNGADGET:
  241.             goto REPLY_AND_RETURN_FALSE;
  242.  
  243.          case OPENGADGET_PROPGADGET:
  244.             HandleGadget(gadget, x, y, seconds, micros);
  245.             if (class == GADGETDOWN) PropInterrupt();
  246.             goto REPLY_AND_RETURN_FALSE;
  247.  
  248.          default:
  249.             /* Do nothing, fall into the message's AddHead() below.
  250.              * This includes the gadgets OK, CANCEL, NEXTDISK, 
  251.              * DISKNAME, DRAWERNAME, FILENAME, and BACKDROP.
  252.              */
  253.             break;
  254.          }
  255.       }
  256.  
  257.    /* Pretend we didn't see this message */
  258.    AddHead(&OpenReqWindow->UserPort->mp_MsgList, message);
  259.    return(TRUE);
  260.  
  261. REPLY_AND_RETURN_FALSE:
  262.    ReplyMsg(message);
  263.    return(FALSE);
  264. }
  265.  
  266.  
  267.  
  268. BOOL MessageInterrupt()
  269. /* Call MessageInterruptGrunt() with each message.
  270.  * Return TRUE if the message is one that should interrupt the building 
  271.  * of the file name list, else return FALSE.
  272.  */
  273. {
  274.    struct IntuiMessage *message;
  275.  
  276.    while (message = GetMsg(OpenReqWindow->UserPort))
  277.       {
  278.       if (MessageInterruptGrunt(message))
  279.          return(TRUE);
  280.       }
  281.    return(FALSE);
  282. }
  283.  
  284.  
  285.  
  286. SHORT MakeEntry(name, startkey, flags)
  287. UBYTE *name;
  288. struct Remember **startkey;
  289. UBYTE flags;
  290. {
  291.    SHORT length, pos;
  292.    struct Remember *localkey, *nextkey, *oldkey;
  293.    UBYTE *ptr;
  294.  
  295.    /* length equals the length of the text plus one for the 
  296.     * terminating NULL
  297.     */
  298.    length = StringLength(name) + 1;
  299.    localkey = NULL;
  300.    /* Alloc one larger than length to make room for the flag byte */
  301.    ptr = AllocRemember(&localkey, length + 1, NULL);
  302.    if (ptr == NULL) return;
  303.    CopyString(ptr, name);
  304.    *(ptr + length) = flags;
  305.    nextkey = *startkey;
  306.    pos = 0;
  307.    oldkey = NULL;
  308.    while (nextkey)
  309.       {
  310.       if (CompareUpperStrings(nextkey->Memory, name) >= 0)
  311.          goto DONE;
  312.  
  313.       oldkey = nextkey;
  314.       nextkey = nextkey->NextRemember;
  315.       pos++;
  316.       }
  317.  
  318. DONE:
  319.    if (oldkey) oldkey->NextRemember = localkey;
  320.    else *startkey = localkey;
  321.    localkey->NextRemember = nextkey;
  322.    return(pos);
  323. }
  324.  
  325.  
  326.  
  327.  
  328. #ifdef WBENCH_CODE
  329.  
  330. SHORT FriendlyInfoType(infoname, fileio)
  331. UBYTE *infoname;
  332. struct FileIOSupport *fileio;
  333. /* This routine looks at the .info file that's named infoname and
  334.  * tests to see if its object type and tool type match the specifications
  335.  * in the fileio structure.  Returns TRUE if everything matches.
  336.  * If the .info file couldn't be opened or if the requirements don't
  337.  * match, FALSE is returned.
  338.  */
  339. {
  340.    struct DiskObject *object;
  341.    SHORT result;
  342.  
  343.    result = FRIENDLY_NOT;
  344.    if (object = GetDiskObject(infoname)) 
  345.       {
  346.       if ((object->do_Type == WBDRAWER) || (object->do_Type == WBGARBAGE))
  347.          result = FRIENDLY_DRAWER;
  348.       else if (object->do_Type == WBDISK) 
  349.          result = FRIENDLY_NOT;
  350.       else
  351.          {
  352.          if (FlagIsSet(fileio->Flags, MATCH_OBJECTTYPE))
  353.             if (object->do_Type != fileio->DiskObjectType) goto FRIEND_DONE;
  354.  
  355.          result = FRIENDLY_OTHER;
  356.  
  357.          if (FlagIsSet(fileio->Flags, MATCH_TOOLTYPE))
  358.             {
  359.             if (NOT MatchToolValue(
  360.                   FindToolType(object->do_ToolTypes, "FILETYPE"), 
  361.                   &fileio->ToolType[0]))
  362.                result = FRIENDLY_NOT;
  363.             }
  364.          }
  365.       }
  366.  
  367. FRIEND_DONE:
  368.    if (object) FreeDiskObject(object);
  369.    return(result);
  370. }
  371.  
  372. #endif /* ... of WBENCH_CODE conditional */
  373.  
  374.  
  375.  
  376.