////////////////////////////////////////////////////////// // Name: ListFunctions.cpp // // // // Description: Contains functions for managing // // information inside double-linked lists of type // // BookmarkDataStruct and FolderDataStruct. // // Double-linked lists are not encapsulated, but // // these functions automate list operations. // // // // AUTHOR(1.0): Lucas Scharf, Feb 17, 1998 // // // // REVISIONS: // // 1.10: 4/6/1998: Added Searching Functions: // // FindFolderWithNameString // // FindBookmarkWithNameString // // // // VERSION: 1.10 // ////////////////////////////////////////////////////////// //////////////////////////////////////////////////////// // Compiler Directives // //////////////////////////////////////////////////////// #include //Used in FindFolderWithName and FindBookmarkWithName //for compares, etc. #include "Constants.h" //Global Constants #include "BookmarkFileStructs.h" //Bookmark and folder data types #include "ListFunctions.h" //List Functions #include "PointerStack.h" //Stack ADT ////////////////////////////////////////////////////////// // Local Function Headers // ////////////////////////////////////////////////////////// void RemoveOneFolder(FolderDataPtr &ListHeadPtr, FolderDataPtr &FolderToDeletePtr); ////////////////////////////////////////////////////////// // Name: CreateBookmarkList // // // // Description: Initializes bookmark list head pointer. // // // // Algorithm: Assignment statement. // // // // Called By: WebAddressLister // // // // Calls: None // // // // Parameters: ListHeadPtr: Data in & out - Pointer to // // the head of the list. // // // // VERSION: 1.00 // ////////////////////////////////////////////////////////// void CreateBookmarkList(BookmarkDataPtr &ListHeadPtr){ ListHeadPtr = null; //Initialize pointer }//End Create ////////////////////////////////////////////////////////// // Name: CreateFolderList // // // // Description: Initializes folder list head pointer. // // // // Algorithm: Assignment statement. // // // // Called By: WebAddressLister // // // // Calls: None // // // // Parameters: ListHeadPtr: Data in & out - Pointer to // // the head of the list. // // // // VERSION: 1.00 // ////////////////////////////////////////////////////////// void CreateFolderList(FolderDataPtr &ListHeadPtr){ ListHeadPtr = null; //Initialize pointer }//End Create; ////////////////////////////////////////////////////////// // Name: AddBookmark // // // // Description: Adds a bookmark into the double-linked // // list beginning at ListHead. // // // // Algorithm: Simple ordered double-linked list add. // // New items are added in order of ParentEntryIndex. // // // // Called By: LoadBookmarks // // PromptAddBookmark // // PromptModifyBookmark // // Calls: None // // // // Parameters: NewBookmark: Data in - Bookmark data to // // be added to the structure. // // ListHeadPtr: Data in & out - a pointer // // to the first item in the list. // // // // VERSION: 1.00 // ////////////////////////////////////////////////////////// void AddBookmark(BookmarkDataStruct NewBookmark, BookmarkDataPtr &ListHeadPtr){ //-- Variable Declarations -- BookmarkDataPtr CurrentPosition,//Pointer used to step through list LastPosition, //Trailing pointer for stepping through the list NewItemPtr; //Temporary pointer to the new item in the list //-- Assign link information -- NewBookmark.LinkNext = null; NewBookmark.LinkPrevious = null; //-- Create new node -- NewItemPtr = new BookmarkDataStruct; //-- Insert item into empty list -- if (!ListHeadPtr){ //-- Set new head -- ListHeadPtr = NewItemPtr; } //end if-empty list //----- Insert item into a non-emptry list ----- else { //-- Find position for new item in list -- LastPosition = null; CurrentPosition = ListHeadPtr; while (CurrentPosition && CurrentPosition->ParentEntryIndex <= NewBookmark.ParentEntryIndex){ LastPosition = CurrentPosition; CurrentPosition = CurrentPosition->LinkNext; }//end while //-- if at beginning of list -- if (CurrentPosition == ListHeadPtr){ NewBookmark.LinkNext = ListHeadPtr; ListHeadPtr->LinkPrevious = NewItemPtr; ListHeadPtr = NewItemPtr; }//end if-beginning of list //-- if middle of the list -- else if (CurrentPosition && LastPosition){ NewBookmark.LinkPrevious = LastPosition; NewBookmark.LinkNext = CurrentPosition; LastPosition->LinkNext = NewItemPtr; CurrentPosition->LinkPrevious = NewItemPtr; }//end if-end of list //-- End of list -- else { NewBookmark.LinkPrevious = LastPosition; LastPosition->LinkNext = NewItemPtr; }//end if-end of list }//end if-empty list //-- Assign info to node -- *NewItemPtr = NewBookmark; }//end AddBookmark ////////////////////////////////////////////////////////// // Name: AddFolder // // // // Description: Adds a Folder into the double-linked // // list beginning at ListHead. // // // // Algorithm: Simple unordered double-linked list add. // // New items are added to the beginning of the list // // for simplicity and speed. // // Will order by Eindex if I have time. :) // // // // Called By: LoadBookmarks // // PromptAddFolder // // PromptModifyFolder // // Calls: None // // // // Parameters: NewFolder: Data in & out - Bookmark // // data to be added to the structure. // // Pointers to adjancent list nodes // // returned // // ListHead: Data in & out - a pointer to // // the first item in the list. // // // // VERSION: 1.00 // ////////////////////////////////////////////////////////// void AddFolder(FolderDataStruct NewFolder, FolderDataPtr& ListHeadPtr){ //-- Variable Declarations -- FolderDataPtr CurrentPosition,//Pointer used to step through list LastPosition, //Trailing pointer for stepping through the list NewItemPtr; //Temporary pointer to the new item in the list //-- Assign link information -- NewFolder.LinkNext = null; NewFolder.LinkPrevious = null; //-- Create new node -- NewItemPtr = new FolderDataStruct; //-- Insert item into empty list -- if (!ListHeadPtr){ //-- Set new head -- ListHeadPtr = NewItemPtr; } //end if-empty list //----- Insert item into a non-emptry list ----- else { //-- Find position for new item in list -- LastPosition = null; CurrentPosition = ListHeadPtr; while (CurrentPosition && CurrentPosition->EntryIndex <= NewFolder.EntryIndex){ LastPosition = CurrentPosition; CurrentPosition = CurrentPosition->LinkNext; }//end while //-- if at beginning of list -- if (CurrentPosition == ListHeadPtr){ NewFolder.LinkNext = ListHeadPtr; ListHeadPtr->LinkPrevious = NewItemPtr; ListHeadPtr = NewItemPtr; }//end if-beginning of list //-- if middle of the list -- else if (CurrentPosition && LastPosition){ NewFolder.LinkPrevious = LastPosition; NewFolder.LinkNext = CurrentPosition; LastPosition->LinkNext = NewItemPtr; CurrentPosition->LinkPrevious = NewItemPtr; }//end if-end of list //-- End of list -- else { NewFolder.LinkPrevious = LastPosition; LastPosition->LinkNext = NewItemPtr; }//end if-end of list }//end if-empty list //-- Assign info to node -- *NewItemPtr = NewFolder; }//end AddFolder ////////////////////////////////////////////////////////// // Name: RemoveBookmark // // // // Description: Removes the bookmark located at // // BookmakDataPtr from the double-linked list // // // // Algorithm: Simple double-linked list delete; // // re-arrange pointers. // // // // Called By: WebAddressListManager // // Calls: None // // // // Parameters: ListHeadPtr: Data in & out - a pointer // // to the first item in the list. // // ThisPtr: Data in & out - Pointer to the // // bookmark to be deleted. // // // // VERSION: 1.00 // ////////////////////////////////////////////////////////// void RemoveBookmark(BookmarkDataPtr& ListHeadPtr, BookmarkDataPtr& ThisPtr){ //-- Emptry List Check -- if (!ThisPtr){ return; } //-- Remove Bookmark from beginning of list -- if (ThisPtr == ListHeadPtr){ ListHeadPtr = ListHeadPtr->LinkNext; ThisPtr->LinkPrevious = null; delete ThisPtr; }//end if-beginning //-- Remove Bookmark from end of list -- else if (!ThisPtr->LinkNext){ ThisPtr->LinkPrevious->LinkNext = null; delete ThisPtr; }//end if-end //-- Remove Bookmark from middle of list -- else { ThisPtr->LinkPrevious->LinkNext = ThisPtr->LinkNext; ThisPtr->LinkNext->LinkPrevious = ThisPtr->LinkPrevious; delete ThisPtr; }//end if-Middle }//End RemoveBookmark ////////////////////////////////////////////////////////// // Name: RemoveFolder // // // // Description: Removes the folder located at // // BookmakDataPtr from the double-linked list // // // // Algorithm: Simple double-linked list delete; // // re-arrange pointers. // // // // Called By: WebAddressListManager // // Calls: None // // // // Parameters: ListHeadPtr: Data in & out - a pointer // // to the first item in the list. // // ThisPtr: Data in & out - Pointer to the // // folder to be deleted. // // DeleteType: Data in - The type of // // delete to be performed. // // Returns: // // The contents of the the folder removed from the // // list. // // // // VERSION: 1.00 // ////////////////////////////////////////////////////////// void RemoveFolder(FolderDataPtr &FolderListHeadPtr, BookmarkDataPtr BookmarkListHeadPtr, FolderDataPtr &FolderToDeletePtr, FolderDeleteEnumType DeleteType){ //-- Variable Declarations -- FolderDataPtr FolderBeingExamined; //The folder being examined; used for stepping through Folder list FolderDataPtr TempFolderPtr; //A temporary pointer - makes improves generic-pointer readability BookmarkDataPtr BookmarkBeingExamined; //The bookmark being examined; used from stepping through Bookmark list BookmarkDataPtr BookmarkToDelete; //Trailing Pointer //-- If Empty List -- if (!FolderToDeletePtr){ return; }//end if - Empty_List //-- Delete Folder -- switch (DeleteType){ case EDeleteSloppy: //-- Delete folder with no cleanup -- RemoveOneFolder(FolderListHeadPtr, FolderToDeletePtr); break; case EDeleteShift: //-- Delete & shift -- //Delete and shift all subfoldsers to the current folder //-- Shift Folders -- FolderBeingExamined = FolderListHeadPtr; //Move to first folder while (FolderBeingExamined){ //-- If folder being examined is child to the folder being deleted -- if (FolderBeingExamined->ParentEntryIndex == FolderToDeletePtr->EntryIndex){ //-- Promote folder -- FolderBeingExamined->ParentEntryIndex = FolderToDeletePtr->ParentEntryIndex; }//end if //-- Move to next folder -- FolderBeingExamined = FolderBeingExamined->LinkNext; }//end while //-- Delete Child Bookmarks -- BookmarkBeingExamined = BookmarkListHeadPtr->LinkNext; //Move to first Bookmark //-- Check all bookmarks for childness to FolderToDelete -- BookmarkBeingExamined = BookmarkListHeadPtr; while (BookmarkBeingExamined){ //-- If bookmark is child to the folder being deleted -- if (BookmarkBeingExamined->ParentEntryIndex == FolderToDeletePtr->EntryIndex){ //-- Move to next bookmark, save current position -- BookmarkToDelete = BookmarkBeingExamined; BookmarkBeingExamined = BookmarkBeingExamined->LinkNext; //-- Remove Bookmark -- RemoveBookmark(BookmarkListHeadPtr, BookmarkToDelete); } else { //-- Move to next bookmark -- BookmarkBeingExamined = BookmarkBeingExamined->LinkNext; }//end if }//End Bookmark-while //-- Delete Folder -- RemoveOneFolder(FolderListHeadPtr, FolderToDeletePtr); break; case EDeleteAll: //-- Delete folder and all subfolders -- //Delete all folders, subfolders, and bookmarks //-- Initialize Stack -- StackInit(); //-- Push Current Folder onto Stack -- if (!StackFull()) StackPush((void*)FolderToDeletePtr); while (!StackEmpty() && !StackFull()){ //-- Travel to farthest folder -- TempFolderPtr = (FolderDataPtr)StackTop(); FolderBeingExamined = FindFolderWithParentEntryIndex(FolderListHeadPtr, TempFolderPtr->EntryIndex); while (FolderBeingExamined){ //-- Change to the farther folder StackPush((void*)FolderBeingExamined); TempFolderPtr = (FolderDataPtr)StackTop(); FolderBeingExamined = FindFolderWithParentEntryIndex(FolderListHeadPtr, TempFolderPtr->EntryIndex); }//end //-- Check all bookmarks for childness to Folder Currently on top of stack -- BookmarkBeingExamined = BookmarkListHeadPtr; //-- Delete Bookmarks in farthest folder -- while (BookmarkBeingExamined){ //-- If bookmark is child to the folder being deleted -- if (BookmarkBeingExamined->ParentEntryIndex == ((FolderDataPtr)StackTop())->EntryIndex){ //-- Move to next bookmark, save current position -- BookmarkToDelete = BookmarkBeingExamined; BookmarkBeingExamined = BookmarkBeingExamined->LinkNext; //-- Remove Bookmark -- RemoveBookmark(BookmarkListHeadPtr, BookmarkToDelete); } else { //-- Move to next bookmark -- BookmarkBeingExamined = BookmarkBeingExamined->LinkNext; }//end if }//End Bookmark-while //-- Pop from stack & Remove farthest folder -- TempFolderPtr = (FolderDataPtr)StackPop(); RemoveOneFolder(FolderListHeadPtr, TempFolderPtr); }//end while stack not empty //-- Destroy Stack -- StackDestroy(); break; }//end switch }//end RemoveFolder ////////////////////////////////////////////////////////// // Name: RemoveOneFolder // // // // Description: Removes the specified folder with no // // regard for the folder heirarchy from the folderlist // // // // Algorithm: Simple double-linked list delete. // // // // Called By: RemoveFolder // // Calls: None // // // // Parameters: // // FolderaDataPtr ListHeadPtr: Data in & out - pointer // // to the first item in the list. // // FolderDataPtr FolderToDelete: Data in & out - // // pointer to the item being delete // // // // VERSION: 1.00 // ////////////////////////////////////////////////////////// void RemoveOneFolder(FolderDataPtr &FolderListHeadPtr, FolderDataPtr &FolderToDeletePtr){ //-- Remove Folder from beginning of list -- if (!(FolderToDeletePtr->LinkPrevious) && (FolderToDeletePtr->LinkNext)){ FolderListHeadPtr = FolderToDeletePtr->LinkNext; FolderToDeletePtr->LinkNext->LinkPrevious = FolderToDeletePtr->LinkPrevious; delete FolderToDeletePtr; }//end if-beginning //-- Remove Folder from middle of list -- if ((FolderToDeletePtr->LinkPrevious) && (FolderToDeletePtr->LinkNext)){ FolderToDeletePtr->LinkPrevious->LinkNext = FolderToDeletePtr->LinkNext; FolderToDeletePtr->LinkNext->LinkPrevious = FolderToDeletePtr->LinkPrevious; delete FolderToDeletePtr; }//end if-Middle //-- Remove Folder from end of list -- if ((FolderToDeletePtr->LinkPrevious) && !(FolderToDeletePtr->LinkNext)){ FolderToDeletePtr->LinkPrevious->LinkNext = FolderToDeletePtr->LinkNext; delete FolderToDeletePtr; }//end if-end }//end RemoveOneFolder ////////////////////////////////////////////////////////// // Name: DestroyBookmarkList // // // // Description: Emptys list located at ListHead. // // // // Algorithm: Multiple calls to simple double-linked // // list delete; re-arrange pointers. // // // // Called By: WebAddressListManager // // Calls: None // // // // Parameters: ListHeadPtr: Data in & out - a pointer // // to the first item in the list. // // // // VERSION: 1.00 // ////////////////////////////////////////////////////////// void DestroyBookmarkList(BookmarkDataPtr &ListHeadPtr){ //-- Empty list check -- if (!ListHeadPtr) return; //-- Nuke List -- while (ListHeadPtr->LinkNext){ ListHeadPtr=ListHeadPtr->LinkNext; delete ListHeadPtr->LinkPrevious; }//end while delete ListHeadPtr; ListHeadPtr=null; }//end DestroyBookmarkList ////////////////////////////////////////////////////////// // Name: DestroyFolderList // // // // Description: Emptys list located at ListHeadPtr. // // // // Algorithm: Multiple calls to simple double-linked // // list delete; re-arrange pointers. // // // // Called By: WebAddressListManager // // Calls: None // // // // Parameters: ListHeadPtr: Data in & out - a pointer // // to the first item in the list. // // // // VERSION: 1.00 // ////////////////////////////////////////////////////////// void DestroyFolderList(FolderDataPtr &ListHeadPtr){ //-- Empty List Check -- if (!ListHeadPtr) return; //-- Nuke List -- while (ListHeadPtr->LinkNext){ ListHeadPtr=ListHeadPtr->LinkNext; delete ListHeadPtr->LinkPrevious; }//end while delete ListHeadPtr; ListHeadPtr=null; }//end DestroyFolderList ////////////////////////////////////////////////////////// // Name: FindFolderWithEntryIndex // // // // Description: Finds a folder with a specific // // entryindex in the folder list // // // // Algorithm: Linear Search // // // // Called By: // // NavigateFolders // // NoFileMenu // // Calls: None // // // // Parameters: Position: Data in - Starting point for // // search // // EntryIndex: Data in - The entry index // // to search for. // // Returns: A pointer to the folder with position // // EntryIndex. Returns null if not // // found. // // // // VERSION: 1.00 // ////////////////////////////////////////////////////////// FolderDataPtr FindFolderWithEntryIndex(FolderDataPtr Position, int EntryIndex){ while (Position!=null && Position->EntryIndex!=EntryIndex){ Position = Position->LinkNext; }//End while return Position; }//End FildFolderWithEntryIndex ////////////////////////////////////////////////////////// // Name: FindFolderWithParentEntryIndex // // // // Description: Finds a folder with a specific // // parent entry index in the folder list // // // // Algorithm: Linear Search // // // // Called By: // // RemoveFolder // // Calls: None // // // // Parameters: Position: Data in - Starting point for // // search // // ParentEntryIndex: Data in - The parent // // entry index to search for. // // Returns: A pointer to the folder with position // // EntryIndex. Returns null if not // // found. // // // // VERSION: 1.00 // ////////////////////////////////////////////////////////// FolderDataPtr FindFolderWithParentEntryIndex(FolderDataPtr Position, int ParentEntryIndex){ while (Position && Position->ParentEntryIndex != ParentEntryIndex){ Position = Position->LinkNext; }//End while return Position; }//End FildFolderWithParentEntryIndex ////////////////////////////////////////////////////////// // Name: FindFolderWithName // // // // Description: Returns a pointer to the first folder // // found that has the name specified by NameToFind. // // Only matches to the end of NameToFind. If the // // user specifies to find folder "AFold", // // FindFolderWithName will return a pointer to a // // folder titled "AFold", or "AFolder", or "AFolder // // that has a really long name". // // // // Algorithm: Linear Search // // // // Called By: // // SearchFolders // // // // Calls: None // // // // Parameters: StartingPosition: Data in - Starting // // point for search // // NameToFind: Data in - The string to // // search for in the name field of the // // FolderDataStruct list. // // Returns: A pointer to the folder with the name // // matching NameToFind. // // // // VERSION: 1.00 // ////////////////////////////////////////////////////////// FolderDataPtr FindFolderWithName(FolderDataPtr StartingPosition, const char NameToFind[]){ //-- Variable Declarations -- int NumCharsToCompare = strlen(NameToFind); //The number of charictars to compare FolderDataPtr CurrentPosition = StartingPosition; //The current position in the list //-- Find folder -- //Advance while Position is not equal to null, and while strncmp has //not found a match. while (CurrentPosition && strncmp(CurrentPosition->Name, NameToFind, NumCharsToCompare)){ CurrentPosition = CurrentPosition->LinkNext; //Advance to next folder }//End while return CurrentPosition; }//End FildFolderWithName ////////////////////////////////////////////////////////// // Name: FindBookmarkWithParentEntryIndex // // // // Description: Returns a pointer to the first Bookmark // // found that has the name specified by // // ParentEntryIndex. // // // // Algorithm: Linear Search // // // // Called By: // // // // Calls: None // // // // Parameters: StartingPosition: Data in - Starting // // point for search // // ParentEntryIndexToFind: Data in - the // // parent entry index to find in the // // bookmark list. // // Returns: A pointer to the Bookmark with the // // ParentEntryIndex mathinging // // matching ParentEntryIndexToFind // // // // VERSION: 1.00 // ////////////////////////////////////////////////////////// BookmarkDataPtr FindBookmarkWithParentEntryIndex(BookmarkDataPtr StartingPosition, int ParentEntryIndexToFind){ //-- Variable Declarations -- BookmarkDataPtr CurrentPosition = StartingPosition; //The current position in the list //-- Find Bookmark -- //Advance while Position is not equal to null, and while strncmp has //not found a match. while (CurrentPosition && CurrentPosition->ParentEntryIndex != ParentEntryIndexToFind){ CurrentPosition = CurrentPosition->LinkNext; //Advance to next Bookmark }//End while return CurrentPosition; }//End FildBookmarkWithParentEntryIndex ////////////////////////////////////////////////////////// // Name: FindBookmarkNumberInFolder // // // // Description: Finds the the BookmarkNumber-ith // // bookmark with the ParentEntryIndex specified by // // ParentEntryIndex. // // // // Algorithm: Linear Search // // // // Called By: BookmarkMenu // // Calls: None // // // // Parameters: // // ListHead - Data in: Pointer to the first item in // // the bookmark list. // // ParentEntryIndex - Data in: The entry index of the // // folder we're examining. // // BookmarkNumber - Data in: The 1-based index of the // // bookmark we're looking for // // // // Returns: // // A pointer to the bookmark with position EntryIndex. // // Returns null if not found. // // // // Notes: // // Loosly based on list functions in CS2574 course // // notes. // // // // VERSION: 1.00 // ////////////////////////////////////////////////////////// BookmarkDataPtr FindBookmarkNumberInFolder(BookmarkDataPtr ListHead, int ParentEntryIndex, int BookmarkNumber){ //-- Variable Declaration -- int CountIndex = 1; //Keeps track of the number of bookmarks in the folder that have been //encoutnered so far bool StopFlag = false; //Used to stop the while loop BookmarkDataPtr CurrentPosition = ListHead; //Pointer to the location in the double-linked //list currently being examined //-- Check for totally invalid input -- if (BookmarkNumber < 1){ CurrentPosition = null; return CurrentPosition; }//end if //-- Step through list -- if (BookmarkNumber == 1){ //-- Find first -- while ((CurrentPosition) && (CurrentPosition->ParentEntryIndex != ParentEntryIndex)){ CurrentPosition = CurrentPosition->LinkNext; }//end while } else { //-- Find 2nd on out -- while ((CurrentPosition) && !(StopFlag)){ //-- Check to see if this bookmark is in the folder if (CurrentPosition->ParentEntryIndex == ParentEntryIndex){ CountIndex++; if (CountIndex >= BookmarkNumber) StopFlag = true; }//end if //-- Move to next node in list -- CurrentPosition = CurrentPosition->LinkNext; }//end while }//end if //-- Return value -- return CurrentPosition; }//End FindBookmarkNumberInFolder ////////////////////////////////////////////////////////// // Name: FindBookmarkWithName // // // // Description: Returns a pointer to the first Bookmark // // found that has the name specified by NameToFind. // // Only matches to the end of NameToFind. If the // // user specifies to find Bookmark "AFold", // // FindBookmarkWithName will return a pointer to a // // Bookmark titled "AFold", or "ABookmark", or // // "ABookmark that has a really long name". // // // // Algorithm: Linear Search // // // // Called By: // // SearchBookmarks // // // // Calls: None // // // // Parameters: Position: Data in - Starting point for // // search // // NameToFind: Data in - The string to // // search for in the name field of the // // BookmarkDataStruct list. // // Returns: A pointer to the Bookmark with the name // // matching NameToFind. // // // // VERSION: 1.00 // ////////////////////////////////////////////////////////// BookmarkDataPtr FindBookmarkWithName(BookmarkDataPtr StartingPosition, const char NameToFind[]){ //-- Variable Declarations -- int NumCharsToCompare = strlen(NameToFind); //The number of charictars to compare BookmarkDataPtr CurrentPosition = StartingPosition; //The current position in the list //-- Find Bookmark -- //Advance while Position is not equal to null, and while strncmp has //not found a match. while (CurrentPosition && strncmp(CurrentPosition->Name, NameToFind, NumCharsToCompare)){ CurrentPosition = CurrentPosition->LinkNext; //Advance to next Bookmark }//End while return CurrentPosition; }//End FildBookmarkWithEntryIndex