home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / Libraries / ABox 1.9.5 / CPlus Files / ABTopicList.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-10-26  |  11.9 KB  |  504 lines  |  [TEXT/MMCC]

  1. /*    
  2.     Copyright © 1991-1995 by TopSoft Inc.  All rights reserved.
  3.  
  4.     You may distribute this file under the terms of the TopSoft
  5.     Artistic License, accompanying this package.
  6.     
  7.     This file was developed by George (ty) Tempel in connection with TopSoft, Inc..
  8.     See the Modification History for more details.
  9.  
  10. Product
  11.     About Box
  12.  
  13. FILE
  14.     ABTopicList.c
  15.  
  16. NAME
  17.     ABTopicList.c, part of the ABox project source code,
  18.     responsible for handling the AboutBox Topic List class stuff.
  19.  
  20. DESCRIPTION
  21.     This file contains defines for the about box modules.
  22.     
  23. DEVELOPED BY
  24.     George (ty) Tempel                ttempel@monmouth.com
  25.     All code in this file, and its associated header file was
  26.     Created by George (ty) Tempel in connection with the TopSoft, Inc.
  27.     "FilterTop" application development, except where noted.
  28.  
  29. CARETAKER - George (ty) Tempel <ttempel@monmouth.com>
  30.      Please consult this person for any changes or suggestions to this file.
  31.  
  32. MODIFICATION HISTORY
  33.  
  34.     dd mmm yy    -    xxx    -    patchxx: description of patch
  35.     9 June 94    -    ty    -    Initial Version Created
  36.     15-july-94    -    ty    -    modifications to include ABUFSSpecs mix-in class
  37.     20-july-94    -    ty    -    initial version released
  38.     23-may-95    -    ty    -    changes for compatibility with the CodeWarrior CW6
  39.                             release and the associated Universal Headers from Apple:
  40.                             most methods that returned references now have "Ref" at
  41.                             the end of their methods names to prevent possible collisions
  42.                             with datatypes and classes of the same name (older versions
  43.                             of the compiler didn't have a problem with this).
  44.     25-oct-95    -    ty    -    changes for "const" usage under CW7; simplification of Boolean
  45.                             query methods
  46.  
  47. */
  48.  
  49. /*===========================================================================*/
  50.  
  51. /*======= Segmentation directives ========*/
  52.  
  53. #ifdef USE_MANUAL_SEGMENTATION
  54. #pragma segment ty
  55. #endif
  56.  
  57. /*============ Header files ==============*/
  58.     
  59. #include     "ABTopicList.h"
  60. #include    "ABoxDefs.h"
  61.  
  62.  
  63. /*=============== Globals ================*/
  64.  
  65. /*================ CODE ==================*/
  66.  
  67.  
  68.  
  69.  
  70.  
  71.  
  72. /*=============================== ABTopicList::ABTopicList ================================*/
  73. ABTopicList::ABTopicList(void)
  74. {
  75.     mDefaultResFileRefNum = 0;
  76. } // end ABTopicList
  77.  
  78.  
  79.  
  80. /*=============================== ABTopicList::~ABTopicList ================================*/
  81. ABTopicList::~ABTopicList(void)
  82. {
  83. }    // end ~ABTopicList
  84.  
  85.  
  86.  
  87.  
  88.  
  89.  
  90. /*=============================== ABTopicList::GotoLink ================================*/
  91. ABLink    *ABTopicList::GotoLink(ABIndex n)
  92. {
  93.     OSErr        error = noErr;
  94.     
  95.     //    begin here...
  96.     
  97.     if (this->HasCurrentLink())
  98.         error = ((ABTopic *) this->CurrentLink())->CloseTopic();
  99.     
  100. //    currentLink = NthLink(n);
  101.     
  102.     if (ABLinkedList::GotoLink(n))
  103.         error = ((ABTopic *) this->CurrentLink())->OpenTopic();
  104.  
  105.     return this->CurrentLink();
  106. } // end GotoLink
  107.  
  108.  
  109.  
  110.  
  111.  
  112. /*=============================== ABTopicList::PreviousLink ================================*/
  113. ABLink    *ABTopicList::PreviousLink(void)
  114. {
  115.     OSErr        error = noErr;
  116.     
  117.     //    begin here...
  118.  
  119.     if (this->HasCurrentLink())
  120.         error = ((ABTopic *) this->CurrentLink())->CloseTopic();
  121.         
  122.     ABLinkedList::PreviousLink();
  123.  
  124.     if (this->HasCurrentLink())
  125.         error = ((ABTopic *) this->CurrentLink())->OpenTopic();
  126.     
  127.     return this->CurrentLink();
  128. } // end PreviousLink
  129.  
  130.  
  131.  
  132. /*=============================== ABTopicList::NextLink ================================*/
  133. ABLink    *ABTopicList::NextLink(void)
  134. {
  135.     OSErr        error = noErr;
  136.     
  137.     //    begin here...
  138.  
  139.     if (this->HasCurrentLink())
  140.         error = ((ABTopic *) this->CurrentLink())->CloseTopic();
  141.         
  142.     ABLinkedList::NextLink();
  143.  
  144.     if (this->HasCurrentLink())
  145.         error = ((ABTopic *) this->CurrentLink())->OpenTopic();
  146.     
  147.     return this->CurrentLink();
  148. } // end NextLink
  149.  
  150.  
  151.  
  152. /*=============================== ABTopicList::FirstLink ================================*/
  153. ABLink    *ABTopicList::FirstLink(void)
  154. {
  155.  
  156.     if (this->IsntEmpty())
  157.         return this->GotoLink (1);
  158.     else
  159.         return NULL;
  160. } // end FirstLink
  161.  
  162.  
  163.  
  164. /*=============================== ABTopicList::LastLink ================================*/
  165. ABLink    *ABTopicList::LastLink(void)
  166. {
  167.     if (this->IsntEmpty())
  168.         return this->GotoLink (this->Count());
  169.     else
  170.         return NULL;
  171. } // end LastLink
  172.  
  173.  
  174.  
  175. /*=============================== ABTopicList::TryTopics ===============================*/
  176. //
  177. ABTopic* ABTopicList::TryTopics(FSSpec& inFileSpec)
  178. {
  179.     OSErr                error = noErr;
  180.     
  181.     ABTopic* theTopic = NULL;
  182.     
  183.     theTopic = this->TryTopic(inFileSpec, ETopicType_OtherTopic);
  184.     if (theTopic == NULL)
  185.         theTopic = this->TryTopic(inFileSpec, ETopicType_Topic);
  186.     if (theTopic == NULL)
  187.         theTopic = this->TryTopic(inFileSpec, ETopicType_MovieTopic);
  188.  
  189.     return theTopic;
  190. }
  191.  
  192.  
  193.  
  194. /*=============================== ABTopicList::TryTopic ===============================*/
  195. //
  196. ABTopic* ABTopicList::TryTopic(FSSpec& inFileSpec, ETopicType inTopicType)
  197. {
  198.     OSErr                error = noErr;
  199.     
  200.     ABTopic* theTopic = NULL;
  201.     
  202.     switch (inTopicType)
  203.     {
  204.         case    ETopicType_OtherTopic:
  205.                 theTopic = new ABOtherTopic(inFileSpec);
  206.                 break;
  207.                 
  208.         case    ETopicType_Topic:
  209.                 theTopic = new ABTopic(inFileSpec);
  210.                 break;
  211.                 
  212.         case    ETopicType_MovieTopic:
  213.                 theTopic = new ABMovieTopic(inFileSpec);
  214.                 break;
  215.         default:
  216.                 break;
  217.     }    
  218.  
  219.     if (theTopic)
  220.     {
  221.         error = theTopic->Load();
  222.         
  223.         if (error != noErr)
  224.         {
  225.             delete theTopic;
  226.             theTopic = NULL;
  227.         }
  228.     }
  229.     
  230.     return theTopic;
  231. }
  232.  
  233.  
  234.  
  235. /*=============================== ABTopicList::RecurseDownFolderTree ===============================*/
  236. //
  237. //    RecurseDownFolderTree will recursively descend a folder tree to accumulate a list
  238. //    of Topic files. When a valid file is encountered it is appended to the list/array
  239. //    of topics.
  240. //
  241. //    The function has no return value, but it will return the number of items
  242. //    processed in the caller-supplied *fileCount pointer (if the pointer is valid). 
  243. //
  244. //
  245. //    is called by:
  246. //        Load
  247. //        RecurseDownFolderTree
  248. //
  249. OSErr ABTopicList::RecurseDownFolderTree( FSSpecPtr top,
  250.                                             short int depth, 
  251.                                             ABTopic *parentFolder)
  252. {
  253.     OSErr                error = noErr;
  254.  
  255.     long                dirID;
  256.     short                vRefNum;
  257.     const StringPtr        nameStrForDir = NULL;
  258.     
  259.     Boolean                sameString = false;
  260.  
  261.     short                slideCount = 0;
  262.     short                currentResFile = CurResFile();
  263.     
  264.     ABTopic                *t = NULL;
  265.     ABTopic                *swappedTopic = NULL;
  266.     
  267.     const short            reqItemCount = 10;
  268.     FSSpec                topicFSSpecs[reqItemCount];
  269.     short                actItemCount;
  270.     short                itemIndex = 0;
  271.     short                index;
  272.     short                limit;
  273.     
  274.     const Boolean        getFiles = true;
  275.     const Boolean        getFolders = true;
  276.     Boolean                isFolder = false;
  277.     Boolean                resolvedAliasChains = true;
  278.     Boolean                wasAliased = false;
  279.     short                topicDepth = depth;
  280.     Boolean                done = false;
  281.     
  282.     //    begin here...
  283.     
  284.     if (!top)
  285.         return paramErr;
  286.         
  287.     //    first, resolve the "top" item
  288.     error = ::ResolveAliasFile (top, 
  289.                                 resolvedAliasChains, 
  290.                                 &isFolder, 
  291.                                 &wasAliased);
  292.     if (error)
  293.         return error;
  294.     
  295.     if (! isFolder)
  296.         return paramErr;
  297.         
  298.     //    as a preflight, get the dirID and the vRefNum from
  299.     //    the "top" item. Also, copy the name as well
  300.     vRefNum = top->vRefNum;
  301.     error = ABUFSSpecs::DirIDFromFSSpec (top,            //    const FSSpec *spec
  302.                                 &dirID,            //    long *dirID
  303.                                 &isFolder);        //    Boolean *isDirectory
  304.     if (error)
  305.         return error;
  306.     
  307.     if (! isFolder)
  308.         return paramErr;
  309.     
  310.     //    next, loop until we've gotten all of the items from the directory
  311.     itemIndex = 1;
  312.     //    starting with the first item, loop forever until we run out
  313.     //    of files, indicated by GetDirItems() returning fnfErr, which
  314.     //    we'll convert to a noErr and return
  315.     done = false;
  316.     while (!done) 
  317.     {
  318.         //    get a block of items from the directory
  319.         error = ABUFSSpecs::GetDirItems (vRefNum,        //    short vRefNum
  320.                                     dirID,            //    long dirID
  321.                                     nameStrForDir,    //    StringPtr name
  322.                                     getFiles,        //    Boolean getFiles
  323.                                     getFolders,        //    Boolean getDirectories
  324.                                     topicFSSpecs,    //    FSSpecPtr items
  325.                                     reqItemCount,    //    short reqItemCount
  326.                                     &actItemCount,    //    short *actItemCount (number returned)
  327.                                     &itemIndex);    //    short *itemIndex (1 = first item, then keep reusing)
  328.         if (error == fnfErr)
  329.         {
  330.             done = true;
  331.             error = noErr;
  332.         } // end if block
  333.             
  334.         if (error)
  335.             return error;
  336.         
  337.         //    now that we have a block of items from the directory,
  338.         //    try to process each of them in turn.
  339.         //
  340.         //    actItemCount items were returned, out of a possible reqItemCount
  341.         limit = (actItemCount < reqItemCount) ? actItemCount : reqItemCount;
  342.         for (index = 0; index < limit; ++index)
  343.         {
  344.             //    before we do _anything_, attempt to resolve any
  345.             //    aliases hanging around
  346.             error = ::ResolveAliasFile (&(topicFSSpecs[index]), 
  347.                                         resolvedAliasChains, 
  348.                                         &isFolder, 
  349.                                         &wasAliased);
  350.                                         
  351.             t = this->TryTopics(topicFSSpecs[index]);
  352.             
  353.             if (t == NULL)
  354.                 //    nothing could be made of the file, so skip it
  355.                 continue;
  356.  
  357.             //    well, the topic works! Save it
  358.              
  359.             //    NOTE: save the local stuff into the topic object
  360.             //
  361.             //    copy the filename into the topic name
  362.             ::BlockMove ((Ptr)(topicFSSpecs[index].name), 
  363.                         (Ptr)(t->NameRef()), 
  364.                         topicFSSpecs[index].name[0] + 1);
  365.             //    mark the depth at which this topic exists...
  366.             t->SetDepth(topicDepth);
  367.             
  368.             //    check to see if this file has the same name as
  369.             //    the enclosing folder.
  370.             //
  371.             sameString = false;
  372.             if (parentFolder)
  373.                 sameString = ::EqualString(t->NameRef(), 
  374.                                         parentFolder->GetName(), 
  375.                                         kABcaseSensitive,
  376.                                         kABdiacriticalSensitive);
  377.             
  378.             if (sameString && !isFolder) 
  379.             {
  380.                 //    the file has the same name as the enclosing folder
  381.                 //    so substitute this topic for the parent folder.
  382.                 
  383.                 swappedTopic = (ABTopic *)parentFolder->ExchangeWith(t);
  384.                 t->SetDepth(parentFolder->GetDepth());
  385.                 delete swappedTopic;
  386.                 swappedTopic = parentFolder = NULL;
  387.             } else {
  388.                 //    the file does _not_ have the same name as the enclosing
  389.                 //    folder, so save the information as a file.                
  390.                 this->Append(t);
  391.             
  392.             } // end if (sameString) else block
  393.  
  394.             if (isFolder)
  395.             {
  396.                 error = this->RecurseDownFolderTree( &(topicFSSpecs[index]), 
  397.                                                 depth + 1, 
  398.                                                 t);        // recursive call 
  399.                 if (error)
  400.                     return error;
  401.                     
  402.             } // end if (isFolder)
  403.                                         
  404.             //    now process the next item in the block
  405.         
  406.         } // end for (index) block...
  407.     } // end while (forever) loop
  408.     
  409.     return error;
  410.     
  411. }    //    end of function RecurseDownFolderTree()
  412.  
  413.  
  414.  
  415.  
  416.  
  417. /*=============================== ABTopicList::Load ===============================*/
  418. //
  419. //    CountAndLoadTopics will load an FSSpec for each of the topic
  420. //    files in the designated folder.
  421. //
  422. //    The caller can provide a pointer to a short integer value
  423. //    if it wishes to receive the number of items processed.
  424. //
  425. //    Any errors will be evident via the return value of the function.
  426. //
  427. //
  428. //    is called by:
  429. //        CreateAndFillTopicList
  430. //
  431. OSErr        ABTopicList::Load (FSSpecPtr top, short defaultRefNum)
  432. {
  433.     OSErr                error = noErr;
  434.     
  435.     Str255                tName;
  436.     const short int        depth = 0;
  437.     
  438.     ABTopic                *t = NULL;
  439.     short                currentResFile = ::CurResFile();
  440.     
  441.     //    begin here...
  442.  
  443.     ABUCursor::WatchCursor();
  444.     this->DefaultResFileRefNum() = defaultRefNum;
  445.     t = new ABTopic();
  446.     if (!t)
  447.     {
  448.         error = ::MemError();
  449.         ABUCursor::ArrowCursor();
  450.         return error;
  451.     } // end if block
  452.         
  453.     //    first grab a topic and slides from the application
  454.     //    if at all possible.
  455.     error = t->Load (this->DefaultResFileRefNum());
  456.     
  457.     if (!top || error) 
  458.     {
  459.         //    the fsspec was bad or missing, so we had to
  460.         //    deal with just the topic stored in the application.
  461.         //    We'll bail here.
  462.         //
  463.         ::UseResFile (currentResFile);
  464.         delete t;
  465.         if (!top)
  466.         {
  467.             ABUCursor::ArrowCursor();
  468.             return error;
  469.         } // end if block
  470.     } else if (!error) {
  471.         //    if there were topics (primary slides) stored inside the application
  472.         //    we'll pop those into the topics list first.
  473.         //
  474.         ::GetIndString (tName, kABStrings, kABdefaultTopicName);
  475.         ::BlockMove ((Ptr)tName, (Ptr)(t->NameRef()), *tName + 1);
  476.         t->SetDepth(0);
  477.         
  478.         this->Append(t);
  479.     }    //    end if block...
  480.         
  481.     ::UseResFile (currentResFile);
  482.     
  483.     
  484.     error = this->RecurseDownFolderTree(    top,        //    input FSSpecPtr
  485.                                     depth,         //    current depth marker
  486.                                     NULL);        //    parent topic
  487.     
  488.     if ((error == fnfErr) || (error == dirNFErr))
  489.         error = noErr;
  490.     
  491.     ABUCursor::ArrowCursor();    
  492.     return error;
  493.  
  494. }    //    end of function CountAndLoadTopics()
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.  
  503. //    end of file
  504.