home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d5xx / d502 / cells.lha / CELLS / CELLSSource.lzh / cLSList.c < prev    next >
C/C++ Source or Header  |  1991-04-20  |  16KB  |  639 lines

  1. /*
  2.  *  CELLS       An Implementation of the WireWorld cellular automata
  3.  *              as described in Scientific American, Jan 1990.
  4.  *
  5.  *              Copyright 1990 by Davide P. Cervone.
  6.  *  You may use this code, provided this copyright notice is kept intact.
  7.  *  See the CELLS.HELP file for complete information on distribution conditions.
  8.  */
  9.  
  10. /*
  11.  *  File:  cLSList.c            Handles maintenance of File Requester lists
  12.  *                              and miscellaneous gadgets.
  13.  */
  14.  
  15.  
  16. #include "Cells.h"
  17. #include "cRequest.h"
  18. #include "cReqLS.h"
  19. #include "cBoxes.h"
  20. #include "cMemory.h"
  21. #include "cDos.h"
  22.  
  23. extern char LSDirName[];
  24. extern char LSNameBuf[];
  25. extern char DirName[];
  26.  
  27. static char Message[MAXBUFFER];     /* message box buffer */
  28. static FILEINFO FirstFile;          /* list of files for display */
  29. int RequestID;                      /* type or file requester (save,load) */
  30.  
  31. extern FILEINFO mSort();
  32.  
  33.  
  34. #define LSGADGET    LSRequest.er_Request.ReqGadget
  35.  
  36.  
  37. /*
  38.  *  LSMessage()
  39.  *
  40.  *  If a messageis to be displayed
  41.  *    copy the message into the buffer area and get its length
  42.  *    set up the gadget to use the new message text
  43.  *    split the message into two lines if necessary
  44.  *    center the messages within the message box
  45.  *  otherwise (no message)
  46.  *    clear the message area
  47.  *  Refresh the gadget if the requester is already active
  48.  */
  49.  
  50. void LSMessage(s,x1,x2,x3,x4,x5,x6)
  51. char *s,*x1,*x2,*x3,*x4,*x5,*x6;
  52. {
  53.    struct Gadget *theGadget = &LSGADGET[LS_MESSAGE];
  54.    struct IntuiText *theText = (struct IntuiText *)theGadget->UserData;
  55.    short Len,i;
  56.  
  57.    Forbid();
  58.    if (s)
  59.    {
  60.       sprintf(Message,s,x1,x2,x3,x4,x5,x6);
  61.       Len = strlen(Message);
  62.       theGadget->GadgetText = theText;
  63.       theGadget->GadgetText->IText = Message;
  64.       if (Len > 33)
  65.       {
  66.          theText[0].NextText = &theText[1];
  67.          theText[0].TopEdge  = 2;
  68.          theText[1].TopEdge  = 11;
  69.          for (i=33; i>0 && Message[i] != ' '; i--);
  70.          if (i == 0) i = 33;
  71.          Message[i] = 0;
  72.          theText[0].LeftEdge = (LS_MESSAGEW - CHAR_WIDTH*i++) / 2;
  73.          theText[1].LeftEdge = (LS_MESSAGEW - CHAR_WIDTH*(Len-i)) / 2;
  74.          theText[1].IText = &Message[i];
  75.       } else {
  76.          theText[0].LeftEdge = (LS_MESSAGEW - CHAR_WIDTH*Len) / 2;
  77.          theText[0].TopEdge  = 1 + LNAMEH/2;
  78.          theText[0].NextText = NULL;
  79.       }
  80.    } else {
  81.       theGadget->GadgetText = NULL;
  82.    }
  83.    Permit();
  84.    if (ActiveRequest == &LSRequest)
  85.       RefreshGList(theGadget,myWindow,ActiveRequest,1);
  86. }
  87.  
  88.  
  89. /*
  90.  *  RecallLSMessage()
  91.  *
  92.  *  If the message box has no message being displayed,
  93.  *    put the gadget text pointer back to the last message shown
  94.  *    and refresh the gadget
  95.  */
  96.  
  97. void RecallLSMessage(theGadget)
  98. struct Gadget *theGadget;
  99. {
  100.    if (theGadget->GadgetText == NULL)
  101.    {
  102.       Forbid();
  103.       theGadget->GadgetText = (struct IntuiText *)theGadget->UserData;
  104.       RefreshGList(theGadget,myWindow,&LSRequest,1);
  105.       Permit();
  106.    }
  107. }
  108.  
  109.  
  110. /*
  111.  *  SetLSDirName()
  112.  *
  113.  *  If the directory name is too long, copy only the last part, otherwise
  114.  *    copy the entire name into the directory name gadget and center it
  115.  *  If the requester is active
  116.  *    refresh the directory name (twice if it is currently selected, since
  117.  *    it is a GADGHCOMP gadget)
  118.  */
  119.  
  120. static void SetLSDirName(Name)
  121. char *Name;
  122. {
  123.    struct IntuiText *theText = LSGADGET[LS_DIR].GadgetText;
  124.    short Len = strlen(Name);
  125.  
  126.    if (Len > 20) strcpy(LSDirName,&Name[Len-20]); else strcpy(LSDirName,Name);
  127.    theText->LeftEdge = (LS_DIRW - CHAR_WIDTH * strlen(Name) - SLIDEWH) / 2;
  128.    if (theText->LeftEdge < 3) theText->LeftEdge = 3;
  129.    if (ActiveRequest == &LSRequest)
  130.    {
  131.       if (LSGADGET[LS_DIR].Flags & SELECTED)
  132.          RefreshRequest(&LSRequest,LS_DIR,NULL);
  133.       RefreshRequest(&LSRequest,LS_DIR,NULL);
  134.    }
  135. }
  136.  
  137.  
  138. /*
  139.  *  SetLSTexts()
  140.  *
  141.  *  Get the directory name and set the directory gadget to it
  142.  *  Set the requester title to the give title and center it
  143.  *  Set the name and ID of the LOAD/SAVE button
  144.  *  Set the title of the check gadget and make sure it is not checked
  145.  *  Set the initial message, if any
  146.  *  Save the type of requester (SAVE or LOAD) for future reference
  147.  */
  148.  
  149. void SetLSTexts(Title,Button,Check,ID)
  150. char *Title,*Button,*Check;
  151. int ID;
  152. {
  153.    GetProcessDir(DirName);
  154.    SetLSDirName(DirName);
  155.    LSRequest.er_Request.ReqText->IText = Title;
  156.    LSRequest.er_Request.ReqText->LeftEdge =
  157.       (LS_PANELW - CHAR_WIDTH * strlen(Title)) / 2;
  158.    LSGADGET[LS_LOAD].GadgetText->IText = Button;
  159.    LSGADGET[LS_LOAD].GadgetText->LeftEdge = 15;
  160.    LSGADGET[LS_LOAD].GadgetID = ID;
  161.    LSGADGET[LS_CHECK].GadgetText->IText = Check;
  162.    LSGADGET[LS_CHECK].Flags &= ~SELECTED;
  163.    if (LSGADGET[LS_NLIST].Flags & GADGDISABLED)
  164.    {
  165.       LSMessage("Click on Directory Name for a List of Files");
  166.    } else {
  167.       LSMessage(NULL);
  168.       LSGADGET[LS_NLIST].GadgetText = LSListInfo.IText;
  169.       UnsetListSelect(&LSListInfo,FALSE);
  170.    }
  171.    RequestID = ID;
  172. }
  173.  
  174.  
  175. /*
  176.  *  DisableLSList()
  177.  *
  178.  *  If the list is not already disabled
  179.  *    clear any selection and set the list to a NULL list
  180.  *    remove the IntuiTexts from the gadget
  181.  *    make the background gadget full sized
  182.  *    disable the gadget and its slider and arrows
  183.  *    refresh the disabled gadgets
  184.  */
  185.  
  186. void DisableLSList(theGadget)
  187. struct Gadget *theGadget;
  188. {
  189.    short i;
  190.  
  191.    if ((theGadget->Flags & GADGDISABLED) == 0)
  192.    {
  193.       UnsetListSelect(theGadget->UserData,TRUE);
  194.       SetList(theGadget,NULL,NULL);
  195.       Forbid();
  196.       theGadget->GadgetText = NULL;
  197.       LSListInfo.Image->PlaneOnOff = BACKGROUND;
  198.       LSListInfo.Image->Height = LS_NLISTH-2;
  199.       LSListInfo.Image->TopEdge = 1;
  200.       for (i=0; i<4; theGadget[i++].Flags |= GADGDISABLED);
  201.       RefreshGList(theGadget,myWindow,&LSRequest,4);
  202.       Permit();
  203.    }
  204. }
  205.  
  206.  
  207. /*
  208.  *  EnableLSList()
  209.  *
  210.  *  If the list is disabled
  211.  *    Set the list gadget's text to the list's text array
  212.  *    Reset the gadget's background color (the image is still full size)
  213.  *    enable the list, its slider and its arrows
  214.  *    refresh the list and its sliders
  215.  *    refresh the list border (kludge: the list gadget really should be smaller)
  216.  *    Now reset the gadget image to its normal height
  217.  */
  218.  
  219. void EnableLSList(theGadget)
  220. struct Gadget *theGadget;
  221. {
  222.    short i;
  223.  
  224.    if (theGadget->Flags & GADGDISABLED);
  225.    {
  226.       Forbid();
  227.       theGadget->GadgetText = LSListInfo.IText;
  228.       LSListInfo.Image->PlaneOnOff = FOREGROUND;
  229.       for (i=0; i<4; theGadget[i++].Flags &= ~GADGDISABLED);
  230.       RefreshGList(theGadget,myWindow,&LSRequest,4);
  231.       RefreshRequest(&LSRequest,LS_BRDRGADG,NULL);
  232.       LSListInfo.Image->Height = LNAMEH;
  233.       Permit();
  234.    }
  235. }
  236.  
  237.  
  238. /*
  239.  *  CompareFiles()
  240.  *
  241.  *  Compare two file names to see if they are equal, or which one is
  242.  *  first alphabetically (NOFIRST is a kludge to ignore the leading '/' in 
  243.  *  directory names).  The list is to be sorted in reverse order, so the
  244.  *  file names are reversed inthe stricmp() call
  245.  */
  246.  
  247. static CompareFiles(File1,File2)
  248. FILEINFO File1,File2;
  249. {
  250.    char *s1 = File1->Name;
  251.    char *s2 = File2->Name;
  252.    
  253.    if (File1->Flags & LI_NOFIRST) s1++;
  254.    if (File2->Flags & LI_NOFIRST) s2++;
  255.    return(stricmp(s2,s1));
  256. }
  257.  
  258.  
  259. /*
  260.  *  FreeFile()
  261.  *
  262.  *  Frees the memory associated with a file name in the directory list
  263.  */
  264.  
  265. static void FreeFile(theFile)
  266. FILEINFO theFile;
  267. {
  268.    if (theFile->Name) FREECHAR(theFile->Name,theFile->NameLen);
  269.    FREESTRUCT(FileInfo,theFile);
  270. }
  271.  
  272.  
  273. /*
  274.  *  ClearDirectoryList()
  275.  *
  276.  *  For each file in the list, clear the memory for the file
  277.  */
  278.  
  279. void ClearDirectoryList()
  280. {
  281.    FILEINFO theFile;
  282.  
  283.    while (FirstFile)
  284.    {
  285.       theFile = FirstFile;
  286.       FirstFile = FirstFile->Next;
  287.       FreeFile(theFile);
  288.    }
  289. }
  290.  
  291.  
  292. /*
  293.  *  FindFile()
  294.  *
  295.  *  Look through the directory list for the given file name (put it into
  296.  *  a fake file item so that CompareFiles can be used).  Returns NULL if
  297.  *  the file is not in the list.
  298.  */
  299.  
  300. FILEINFO FindFile(Name)
  301. char *Name;
  302. {
  303.    FILEINFO theFile = FirstFile;
  304.    int NotFound = TRUE;
  305.    struct FileInfo CmpFile;
  306.    
  307.    CmpFile.Name = Name;
  308.    while (theFile && NotFound)
  309.    {
  310.       if (CompareFiles(theFile,&CmpFile) == 0) NotFound = FALSE;
  311.       else theFile = theFile->Next;
  312.    }
  313.    return(theFile);
  314. }
  315.  
  316.  
  317. /*
  318.  *  RemoveFile()
  319.  *
  320.  *  Unlink the file from the directory list, remove the item from the
  321.  *  list gadget, and free the file's memory
  322.  */
  323.  
  324. void RemoveFile(theFile)
  325. FILEINFO theFile;
  326. {
  327.    if (theFile->Next) theFile->Next->Prev = theFile->Prev;
  328.    if (theFile->Prev) theFile->Prev->Next = theFile->Next;
  329.    if (theFile == FirstFile) FirstFile = theFile->Next;
  330.    RemoveListItem(&LSListInfo,theFile);
  331.    FreeFile(theFile);
  332. }
  333.  
  334.  
  335. /*
  336.  *  MakeFile()
  337.  *
  338.  *  If a new FileInfo structure can be allocated
  339.  *    get the length of the file name
  340.  *    if the file is a directory, increase the length (for the '/')
  341.  *    if we can allocate a character string of the given size
  342.  *      if the file is a directory
  343.  *        set the file's flags and copy the name preceeeded by a '/'
  344.  *      otherwise
  345.  *        just copy the name
  346.  *    otherwise
  347.  *      free the structure and return NULL
  348.  */
  349.  
  350. static FILEINFO MakeFile(Fib)
  351. FIB Fib;
  352. {
  353.    FILEINFO theFile = NULL;
  354.    
  355.    if (NEWSTRUCT(FileInfo,theFile))
  356.    {
  357.       theFile->NameLen = strlen(Fib->fib_FileName);
  358.       if (Fib->fib_DirEntryType > 0) theFile->NameLen++;
  359.       if (NEWCHAR(theFile->Name,theFile->NameLen))
  360.       {
  361.          if (Fib->fib_DirEntryType > 0)
  362.          {
  363.             theFile->Flags = FI_DIRECTORY | LI_NOFIRST;
  364.             theFile->Name[0] = '/';
  365.             strcpy(&theFile->Name[1],Fib->fib_FileName);
  366.          } else {
  367.             strcpy(theFile->Name,Fib->fib_FileName);
  368.          }
  369.       } else {
  370.          FREESTRUCT(FileInfo,theFile);
  371.          theFile = NULL;
  372.       }
  373.    }
  374.    return(theFile);
  375. }
  376.  
  377.  
  378. /*
  379.  *  MakeDevice()
  380.  *
  381.  *  If a new FileInfo structure can be allocated
  382.  *    get the device name length plus one (for ':')
  383.  *    if we can get a characgter string that long
  384.  *      get the device's name string
  385.  *      mark the device as a directory (for purposes or openning)
  386.  *    otherwise
  387.  *      free the structure and return NULL
  388.  */
  389.  
  390. static FILEINFO MakeDevice(theDevice)
  391. struct DeviceList *theDevice;
  392. {
  393.    FILEINFO theFile = NULL;
  394.    
  395.    if (NEWSTRUCT(FileInfo,theFile))
  396.    {
  397.       theFile->NameLen = BCPL_TO_SIZE(theDevice->dl_Name)+1;
  398.       if (NEWCHAR(theFile->Name,theFile->NameLen))
  399.       {
  400.          GetDevName(theFile->Name,theDevice);
  401.          theFile->Flags = FI_DIRECTORY;
  402.       } else {
  403.          FREESTRUCT(FileInfo,theFile);
  404.          theFile = NULL;
  405.       }
  406.    }
  407.    return(theFile);
  408. }
  409.  
  410.  
  411. /*
  412.  *  AddFile()
  413.  *
  414.  *  If a file was given
  415.  *    link it into the directory list and increment the length of the list
  416.  *  otherwise
  417.  *    give an error message
  418.  */
  419.  
  420. static int AddFile(theFile,Count)
  421. FILEINFO theFile;
  422. int Count;
  423. {
  424.    if (theFile)
  425.    {
  426.       theFile->Prev = NULL;
  427.       theFile->Next = FirstFile;
  428.       if (FirstFile) FirstFile->Prev = theFile;
  429.       FirstFile = theFile;
  430.       Count++;
  431.    } else {
  432.       LSMessage("Can't Get Memory for File Info");
  433.    }
  434.    return(Count);
  435. }
  436.  
  437.  
  438. /*
  439.  *  GetDirectoryList()
  440.  *
  441.  *  If the directory can be locked,
  442.  *    and it can be examined
  443.  *      Clear the list gadget's contents
  444.  *      put up a message about reading the directory
  445.  *      clear the old list
  446.  *      while there are more files in the directory, add them to the list
  447.  *      if there was some error while reading the directory
  448.  *        give the message, otherwise tell how many were read
  449.  *      sort the list alphabetically
  450.  *    Unlock the directory
  451.  */
  452.  
  453. static void GetDirectoryList()
  454. {
  455.    short Count = 0;
  456.    LOCK lock;
  457.    FIB Fib;
  458.  
  459.    if (DosLock(&lock,DirName,TYPE_DIR))
  460.    {
  461.       if (DosExamine(lock,&Fib,TYPE_DIR))
  462.       {
  463.          SetList(&LSGADGET[LS_NLIST],NULL,NULL);
  464.          LSMessage("Reading Directory...");
  465.          ClearDirectoryList();
  466.          while (ExNext(lock,Fib))
  467.             Count = AddFile(MakeFile(Fib),Count);
  468.          if (IoErr() != ERROR_NO_MORE_ENTRIES)
  469.             DosError("Read","Directory");
  470.            else
  471.             LSMessage("%d File%s",Count,(Count == 1)? "": "s");
  472.          FirstFile = mSort(FirstFile,&CompareFiles,NULL);
  473.       }
  474.       UnLock(lock);
  475.    }
  476. }
  477.  
  478.  
  479. /*
  480.  *  GetDeviceList()
  481.  *
  482.  *  Put up the message about the device list
  483.  *  Clear the old list
  484.  *  Starting at the first device, while ther are more devices in the list
  485.  *    add the device to the list, and go on to the next item
  486.  *    (only the MOUNTED devices are listed; i.e., only ones with active tasks)
  487.  *  Sort the list, and tell how many devices were listed
  488.  */
  489.  
  490. static void GetDeviceList()
  491. {
  492.    short Count = 0; 
  493.    struct DeviceList *theDevice;
  494.  
  495.    LSMessage("Reading Device List...");
  496.    ClearDirectoryList();
  497.    Forbid();
  498.    theDevice = FIRSTDEV;
  499.    while (theDevice)
  500.    {
  501.       if (theDevice->dl_Task) Count = AddFile(MakeDevice(theDevice),Count);
  502.       theDevice = DEVLIST(theDevice->dl_Next);
  503.    }
  504.    Permit();
  505.    FirstFile = mSort(FirstFile,&CompareFiles,NULL);
  506.    LSMessage("%d Device%s",Count,(Count == 1)? "": "s");
  507. }
  508.  
  509.  
  510. /*
  511.  *  SetLSDirectory()
  512.  *
  513.  *  Set the directory gadget to the given name
  514.  *  Clear the file name gadget and refresh it
  515.  *  If the directory list is active
  516.  *    get the list of files in the current directory
  517.  *    remove any selected item, and show the new list
  518.  */
  519.  
  520. void SetLSDirectory(Name)
  521. char *Name;
  522. {
  523.    Forbid();
  524.    SetLSDirName(Name);
  525.    SetStringInfo(&LSGADGET[LS_NAME],"");
  526.    RefreshRequest(&LSRequest,LS_NAME,NULL);
  527.    Permit();
  528.  
  529.    if ((LSGADGET[LS_NLIST].Flags & GADGDISABLED) == 0)
  530.    {
  531.       UnsetListSelect(&LSListInfo,TRUE);
  532.       GetDirectoryList();
  533.       SetList(&LSGADGET[LS_NLIST],FirstFile,NULL);
  534.    }
  535. }
  536.  
  537.  
  538. /*
  539.  *  SetLSDevices()
  540.  *
  541.  *  Set the directory name to blank
  542.  *  Clear the file name gadget
  543.  *  If the directory list is active
  544.  *    get the list of devices
  545.  *    clear any old selection and show the new list
  546.  */
  547.  
  548. void SetLSDevices()
  549. {
  550.    Forbid();
  551.    SetLSDirName("");
  552.    SetStringInfo(&LSGADGET[LS_NAME],"");
  553.    RefreshRequest(&LSRequest,LS_NAME,NULL);
  554.    Permit();
  555.  
  556.    if ((LSGADGET[LS_NLIST].Flags & GADGDISABLED) == 0)
  557.    {
  558.       GetDeviceList();
  559.       UnsetListSelect(&LSListInfo,TRUE);
  560.       SetList(&LSGADGET[LS_NLIST],FirstFile,NULL);
  561.    }
  562. }
  563.  
  564. static char *OldButton;         /* button name before it became "REWRITE" */
  565.  
  566.  
  567. /*
  568.  *  SetReWrite()
  569.  *
  570.  *  Display the warning message
  571.  *  Save the old button name (LOAD or SAVE)
  572.  *  Set the button name and ID to REWRITE and refresh the button
  573.  */
  574.  
  575. void SetReWrite()
  576. {
  577.    struct Gadget *theGadget = &LSGADGET[LS_LOAD];
  578.  
  579.    LSMessage("File Exists: Press REWRITE to Over-Write it");
  580.    Forbid();
  581.    OldButton = theGadget->GadgetText->IText;
  582.    theGadget->GadgetText->IText = "ReWrite";
  583.    theGadget->GadgetText->LeftEdge = 7;
  584.    theGadget->GadgetID = LS_REWRITE;
  585.    RefreshGList(theGadget,myWindow,&LSRequest,1);
  586.    Permit();
  587. }
  588.  
  589.  
  590. /*
  591.  *  UnsetReWrite()
  592.  *
  593.  *  If there is a button name being saved
  594.  *    Clear the REWRITE name
  595.  *    Set the name and ID back to what it was, and refresh the button
  596.  *    Clear the old button name and the message box
  597.  */
  598.  
  599. void UnsetReWrite()
  600. {
  601.    struct Gadget *theGadget = &LSGADGET[LS_LOAD];
  602.  
  603.    if (OldButton)
  604.    {
  605.       Forbid();
  606.       theGadget->GadgetText->IText = "       ";
  607.       RefreshGList(theGadget,myWindow,&LSRequest,1);
  608.       theGadget->GadgetText->IText = OldButton;
  609.       theGadget->GadgetText->LeftEdge = 15;
  610.       theGadget->GadgetID = RequestID;
  611.       RefreshGList(theGadget,myWindow,&LSRequest,1);
  612.       Permit();
  613.       OldButton = NULL;
  614.       LSMessage(NULL);
  615.    }
  616. }
  617.  
  618.  
  619. /*
  620.  *  ActivateLSName()
  621.  *
  622.  *  If the list is disabled,
  623.  *    activate the name gadget
  624.  *  otherwise
  625.  *    ask the list manager to activate the name (and deselect any 
  626.  *    selected items, etc)
  627.  *  [there is a bug in Intuition that causes this to fail if the string gadget
  628.  *  was the previously active gadget; i.e., when you press RETURN in the file
  629.  *  name gadget]
  630.  */
  631.  
  632. void ActivateLSName()
  633. {
  634.    if (LSGADGET[LS_NLIST].Flags & GADGDISABLED)
  635.       ActivateGadget(&LSGADGET[LS_NAME],myWindow,&LSRequest);
  636.      else
  637.       ActivateName(&LSListInfo);
  638. }
  639.