home *** CD-ROM | disk | FTP | other *** search
/ Tools / WinSN5.0Ver.iso / NETSCAP.50 / WIN1998.ZIP / ns / lib / libmisc / hotlist.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-04-08  |  33.5 KB  |  1,456 lines

  1. /* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
  2.  *
  3.  * The contents of this file are subject to the Netscape Public License
  4.  * Version 1.0 (the "NPL"); you may not use this file except in
  5.  * compliance with the NPL.  You may obtain a copy of the NPL at
  6.  * http://www.mozilla.org/NPL/
  7.  *
  8.  * Software distributed under the NPL is distributed on an "AS IS" basis,
  9.  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
  10.  * for the specific language governing rights and limitations under the
  11.  * NPL.
  12.  *
  13.  * The Initial Developer of this code under the NPL is Netscape
  14.  * Communications Corporation.  Portions created by Netscape are
  15.  * Copyright (C) 1998 Netscape Communications Corporation.  All Rights
  16.  * Reserved.
  17.  */
  18.  
  19. #include "hotlist.h"
  20. #include "net.h"
  21. #include "xp_mcom.h"
  22. #include "client.h"
  23. #include "xpgetstr.h"
  24.  
  25. extern int XP_HOTLIST_DEF_NAME;
  26. extern int XP_HOTLIST_AUTOGENERATED_FILE;
  27.  
  28. #define DEF_NAME XP_GetString(XP_HOTLIST_DEF_NAME)
  29.  
  30. /*
  31.     Private Prototypes
  32. */
  33.  
  34. #ifdef NOPE
  35. PRIVATE HotlistStruct *
  36. hot_FindItemsParent(HotlistStruct * parent_node, HotlistStruct * item);
  37. #endif
  38.  
  39. HotlistStruct *
  40. hot_GetIndexOf(HotlistStruct *parent, int *index);
  41.  
  42. /* the main parent node
  43.  */
  44. PRIVATE HotlistStruct * hot_list=0;
  45. PRIVATE XP_Bool hot_list_modified=FALSE;
  46.  
  47. /* return a pointer to the main hotlist list
  48.  *
  49.  * returns NULL if nothing has ever been
  50.  * added to the hotlist
  51.  */
  52. PUBLIC XP_List *
  53. HOT_GetHotlistList(void)
  54. {
  55.   if (! hot_list) return 0;
  56.   return (hot_list->children);
  57. }
  58.  
  59. /* tell the hotlist code that the hotlist has been modified
  60.  * so that it gets saved the next time SaveHotlist is called
  61.  */
  62. PUBLIC void
  63. HOT_SetModified(void)
  64. {
  65.     hot_list_modified=TRUE;
  66. }
  67.  
  68. PRIVATE HotlistStruct *
  69. hot_FindItemStub(HotlistStruct *parent, char * url_address)
  70. {
  71.     XP_List * list_ptr;
  72.     HotlistStruct * object;
  73.  
  74.     if(parent == NULL) /* Eric made me do it */
  75.         return(0);
  76.  
  77.     list_ptr = parent->children;
  78.  
  79.     while((object = (HotlistStruct *)XP_ListNextObject(list_ptr))!=0)
  80.       {
  81.  
  82.         if(object->address && !XP_STRCMP(object->address, url_address))
  83.           {
  84.             return(object);
  85.           }
  86.  
  87.         if(object->type == HOT_HeaderType)
  88.           {
  89.             HotlistStruct * rv;
  90.             rv = hot_FindItemStub(object, url_address);
  91.  
  92.             if(rv)
  93.                 return(rv);
  94.           }
  95.       }
  96.  
  97.     return(0);
  98. }
  99.  
  100. /* checks the hotlist for a url and updates the last accessed
  101.  * time
  102.  */
  103. PUBLIC void
  104. HOT_UpdateHotlistTime(URL_Struct *URL_s, time_t cur_time)
  105. {
  106.     HotlistStruct * hs = hot_FindItemStub(hot_list, URL_s->address);
  107.  
  108.     if(hs)
  109.       {
  110.         TRACEMSG(("Updating hotlist item access time: %s", hs->address));
  111.         hs->last_visit = cur_time;
  112.         hot_list_modified = TRUE;
  113.       }
  114. }
  115.  
  116. /* create a hotlist entry struct and fill it in with
  117.  * the passed in data
  118.  *
  119.  * returns NULL on out of memory error.
  120.  */
  121. PUBLIC HotlistStruct *
  122. HOT_CreateEntry(HOT_Type type,
  123.                 const char *name, 
  124.                 const char *address,
  125.                 const char *content_type,
  126.                 time_t      last_visit)
  127. {
  128.     HotlistStruct * new_entry = XP_NEW(HotlistStruct);
  129.  
  130.     if(!new_entry)
  131.         return(NULL);
  132.  
  133.     memset(new_entry, 0, sizeof(HotlistStruct));
  134.  
  135.     new_entry->type = type;
  136.  
  137.     if(type == HOT_HeaderType)
  138.         new_entry->children = XP_ListNew();
  139.     else
  140.         StrAllocCopy(new_entry->address, address); /* headers can't have addresses */
  141.  
  142.     StrAllocCopy(new_entry->name, name);
  143.     StrAllocCopy(new_entry->content_type, content_type);
  144.     new_entry->last_visit = last_visit;
  145.     new_entry->addition_date = time(NULL);
  146.     new_entry->parent = NULL;
  147.     new_entry->lParent = NULL;
  148.  
  149.     return(new_entry);
  150. }
  151.  
  152. /* free's a hotlist entry
  153.  */
  154. PUBLIC void
  155. HOT_FreeEntry(HotlistStruct * entry)
  156. {
  157.     if(entry)
  158.       {
  159.         if(entry->type == HOT_HeaderType)
  160.           {
  161.             HotlistStruct * subItem;
  162.  
  163.             while((subItem = (HotlistStruct *) XP_ListRemoveTopObject(entry->children))!=0)
  164.               {
  165.                 HOT_FreeEntry(subItem);
  166.               }
  167.     
  168.             XP_ListDestroy(entry->children);
  169.           }
  170.  
  171.         if(entry->name)
  172.             XP_FREE(entry->name);
  173.         if(entry->address)
  174.             XP_FREE(entry->address);
  175.         if(entry->content_type)
  176.             XP_FREE(entry->content_type);
  177.         XP_FREE(entry);
  178.       }
  179. }
  180.  
  181. /* changes a entry to a header type from a non header type
  182.  * and vice versa.  If the object was a header and
  183.  * has children, the children will be blown away. (very bad)
  184.  */
  185. PUBLIC void
  186. HOT_ChangeEntryType(HotlistStruct * entry, HOT_Type type)
  187. {
  188.     if(entry->type == type)
  189.         return;
  190.  
  191.     entry->type = type;
  192.     if(entry->type == HOT_HeaderType)
  193.       {
  194.         entry->children = XP_ListNew();
  195.       }
  196.     else
  197.       {
  198.         XP_ListDestroy(entry->children);
  199.         entry->children = NULL;
  200.       }
  201.  
  202.     hot_list_modified = TRUE;
  203. }
  204.  
  205.  
  206. /* create a completely new copy of the entry passed in
  207.  */
  208. PUBLIC HotlistStruct *
  209. HOT_CopyEntry(HotlistStruct * entry)
  210. {
  211.     if(!entry)
  212.         return(NULL);
  213.  
  214.     return(HOT_CreateEntry(entry->type,
  215.                            entry->name,
  216.                            entry->address,
  217.                            entry->content_type,
  218.                            entry->last_visit));
  219. }
  220.  
  221. /* Fold or unfold a hotlist header
  222.  * 
  223.  * set the Boolean to True to fold the list and
  224.  * False to unfold
  225.  */
  226. PUBLIC void
  227. HOT_FoldHeader(HotlistStruct * item, Bool fold)
  228. {
  229.     hot_list_modified = TRUE;
  230.  
  231.     if(item)
  232.         item->is_folded = fold;
  233. }
  234.  
  235. #ifdef NOPE
  236. /* recursive routine to find a HotlistStruct parent structure containing 
  237.  * the list containing the specified hotlist item
  238.  */
  239. PRIVATE HotlistStruct *
  240. hot_FindItemsParent(HotlistStruct * parent_node, HotlistStruct * item)
  241. {
  242.     XP_List *cur_list = parent_node->children->next;
  243.  
  244.     if(!cur_list)
  245.         return(NULL);
  246.  
  247.     while(cur_list)
  248.       {
  249.         HotlistStruct *rv = NULL;
  250.         HotlistStruct *obj = (HotlistStruct *)cur_list->object;
  251.  
  252.         if(obj == item)
  253.           {
  254.             return(parent_node);
  255.           }
  256.         else if(obj->type == HOT_HeaderType)
  257.           {
  258.             rv = hot_FindItemsParent(obj, item);
  259.             if(rv)
  260.                 return(rv);
  261.           }
  262.         cur_list = cur_list->next;
  263.       }
  264.  
  265.     return(NULL);   /* not found */
  266. }
  267.  
  268.  
  269. #endif
  270.  
  271. /* insert an item before another item in the hotlist
  272.  *
  273.  * if the insert_before item is NULL or not found the item
  274.  * will be inserted at the begining of the list
  275.  */
  276. PUBLIC void
  277. HOT_InsertItemBefore(HotlistStruct * insert_before, HotlistStruct * insertee)
  278. {
  279.     HotlistStruct * hls=0;
  280.  
  281.     if(!insertee)
  282.         return;
  283.  
  284.     hot_list_modified = TRUE;
  285.  
  286.     if(!hot_list)
  287.       {
  288.         hot_list = HOT_CreateEntry (HOT_HeaderType, XP_GetString(XP_HOTLIST_DEF_NAME), NULL, NULL, 0);
  289.         if(!hot_list)
  290.             return;
  291.         hot_list->children = XP_ListNew();
  292.         if (!hot_list->children) 
  293.              {
  294.             HOT_FreeEntry(hot_list);
  295.             hot_list = NULL;
  296.             return;
  297.           }
  298.       }
  299.  
  300.     /* find the list that contains the insert_before object 
  301.      */
  302.     if(insert_before) {
  303.         if(insert_before->parent) {
  304.             hls = insert_before->parent;
  305.             XP_ListInsertObject(hls->children, insert_before, insertee);
  306.             insertee->parent = hls;
  307.             insertee->lParent = XP_ListFindObject(hls->children, insertee);
  308.         } else {
  309.             XP_ListInsertObject(hot_list->children, insert_before, insertee);
  310.             insertee->parent = NULL;
  311.             insertee->lParent = XP_ListFindObject(hot_list->children, insertee);
  312.         }
  313.     } else {
  314.         XP_ListAddObjectToEnd(hot_list->children, insertee);
  315.         insertee->parent = NULL;
  316.         insertee->lParent = XP_ListFindObject(hot_list->children, insertee);
  317.     }
  318.  
  319.     return;
  320. }
  321.  
  322. /* insert an item after another item in the hotlist
  323.  *
  324.  * if the insert_after item is NULL or not found the item
  325.  * will be inserted at the end of the list
  326.  */
  327. PUBLIC void
  328. HOT_InsertItemAfter(HotlistStruct * insert_after, HotlistStruct * insertee)
  329. {
  330.     HotlistStruct * hls=0;
  331.  
  332.     if(!insertee)
  333.         return;
  334.  
  335.     hot_list_modified = TRUE;
  336.  
  337.     if(!hot_list)
  338.       {
  339.         hot_list = HOT_CreateEntry(HOT_HeaderType, DEF_NAME, NULL, NULL, 0);
  340.         if(!hot_list)
  341.             return;
  342.         hot_list->children = XP_ListNew();
  343.       }
  344.  
  345.     /* find the list that contains the insert_after object
  346.      */
  347.     if(insert_after) {
  348.         if(insert_after->parent) {
  349.             hls = insert_after->parent;
  350.             XP_ListInsertObjectAfter(hls->children, insert_after, insertee);
  351.             insertee->parent = hls;
  352.             insertee->lParent = XP_ListFindObject(hls->children, insertee);
  353.         } else {
  354.             XP_ListInsertObjectAfter(hot_list->children, insert_after, insertee);
  355.             insertee->parent = NULL;
  356.             insertee->lParent = XP_ListFindObject(hot_list->children, insertee);
  357.         }
  358.     } else {
  359.         XP_ListAddObjectToEnd(hot_list->children, insertee);
  360.         insertee->parent = NULL;
  361.         insertee->lParent = XP_ListFindObject(hot_list->children, insertee);
  362.     }
  363.  
  364.     return;
  365. }
  366.  
  367. /* insert an item in a header if "insert_after" is a
  368.  * Header type, or after the item if "insert after" is
  369.  * not a header type.
  370.  *
  371.  * if the insert_after item is NULL or not found the item
  372.  * will be inserted at the end of the hotlist
  373.  */
  374. PUBLIC void
  375. HOT_InsertItemInHeaderOrAfterItem(HotlistStruct * insert_after, 
  376.                                   HotlistStruct * insertee)
  377. {
  378.     if(!insertee)
  379.         return;
  380.  
  381.     if(insert_after && insert_after->type == HOT_HeaderType)
  382.       {
  383.         XP_ListAddObject(insert_after->children, insertee);
  384.         if(insert_after != hot_list)
  385.             insertee->parent = insert_after;
  386.         else
  387.             insertee->parent = NULL;
  388.         insertee->lParent = XP_ListFindObject(insert_after->children, insertee);
  389.         return;
  390.       }
  391.  
  392.     /* else */
  393.     HOT_InsertItemAfter(insert_after, insertee);
  394. }
  395.  
  396.  
  397. /* remove an item from the hotlist and free's it
  398.  *
  399.  * returns TRUE on success, FALSE if not found
  400.  */
  401. PUBLIC Bool
  402. HOT_RemoveItem(HotlistStruct * old_item)
  403. {
  404.     HotlistStruct * hls = old_item->parent;
  405.     if(!hls)
  406.         hls = hot_list;
  407.  
  408.     hot_list_modified = TRUE;
  409.  
  410.     if(hls)
  411.       {
  412.         XP_ListRemoveObject(hls->children, old_item);
  413.         HOT_FreeEntry(old_item);
  414.         return(TRUE);
  415.       }
  416.  
  417.     /* else */
  418.     return(FALSE);
  419. }
  420.  
  421. /* remove an item from the hotlist and doesn't free it
  422.  *
  423.  * returns TRUE on success, FALSE if not found
  424.  */
  425. PUBLIC Bool
  426. HOT_RemoveItemFromList(HotlistStruct * old_item)
  427. {
  428.     HotlistStruct * hls = old_item->parent;
  429.     if(!hls)
  430.         hls = hot_list;
  431.  
  432.     hot_list_modified = TRUE;
  433.  
  434.     if(hls)
  435.       {
  436.         XP_ListRemoveObject(hls->children, old_item);
  437.         return(TRUE);
  438.       }
  439.  
  440.     /* else */
  441.     return(FALSE);
  442. }
  443.  
  444. PRIVATE int
  445. hot_GetIndexNum(HotlistStruct *parent, HotlistStruct * item, int *cur_count)
  446. {
  447.     XP_List * list_ptr = parent->children;
  448.     HotlistStruct * object;
  449.     int rv=0;
  450.  
  451.     while((object = (HotlistStruct *)XP_ListNextObject(list_ptr))!=0)
  452.       {
  453.  
  454.         if(object == item)
  455.             return(*cur_count);
  456.  
  457.         *(cur_count) += 1;
  458.  
  459.         if(object->type == HOT_HeaderType && !object->is_folded)
  460.           {
  461.              rv = hot_GetIndexNum(object, item, cur_count);
  462.  
  463.             if(rv)
  464.                 return(rv);
  465.           }
  466.       }
  467.  
  468.     return(0);
  469. }
  470.  
  471. /* returns an integer index of the item in the list
  472.  */
  473. PUBLIC int
  474. HOT_GetIndex(HotlistStruct * item)
  475. {
  476.     int count=1;
  477.  
  478.     if(hot_list)
  479.         return(hot_GetIndexNum(hot_list, item, &count));
  480.     else
  481.         return(0);
  482. }
  483.  
  484. PRIVATE int
  485. hot_GetUnfoldedIndexNum(HotlistStruct *parent, HotlistStruct * item, int *cur_count)
  486. {
  487.     XP_List * list_ptr = parent->children;
  488.     HotlistStruct * object;
  489.     int rv=0;
  490.  
  491.     while((object = (HotlistStruct *)XP_ListNextObject(list_ptr))!=0)
  492.       {
  493.  
  494.         if(object == item)
  495.             return(*cur_count);
  496.  
  497.         *(cur_count) += 1;
  498.  
  499.         if(object->type == HOT_HeaderType)
  500.           {
  501.              rv = hot_GetUnfoldedIndexNum(object, item, cur_count);
  502.  
  503.             if(rv)
  504.                 return(rv);
  505.           }
  506.       }
  507.  
  508.     return(0);
  509. }
  510.  
  511. /* returns an integer index of the item in the list
  512.  * and does not pay attention to the is_folded value
  513.  */
  514. PUBLIC int
  515. HOT_GetUnfoldedIndex(HotlistStruct * item)
  516. {
  517.     int count=1;
  518.  
  519.     if(hot_list)
  520.         return(hot_GetUnfoldedIndexNum(hot_list, item, &count));
  521.     else
  522.         return(0);
  523. }
  524.  
  525. /* returns TRUE if the second argument is a direct
  526.  * descendent of the first argument.
  527.  *
  528.  * returns FALSE otherwise
  529.  */
  530. PUBLIC Bool
  531. HOT_IsDescendent(HotlistStruct *parent, HotlistStruct *possible_child)
  532. {
  533.     int count = 1;
  534.  
  535.     if(parent
  536.         && parent->type == HOT_HeaderType
  537.           && hot_GetUnfoldedIndexNum(parent, possible_child, &count))
  538.         return(TRUE);
  539.  
  540.     return(FALSE);
  541. }
  542.  
  543. PRIVATE HotlistStruct *
  544. hot_SearchHotlistStub(HotlistStruct *parent, 
  545.                     char * search_string, 
  546.                     HotlistStruct ** start_obj, 
  547.                     int *cur_count,
  548.                     Bool *redisplay_all)
  549. {
  550.     XP_List * list_ptr = parent->children;
  551.     HotlistStruct * object;
  552.     HotlistStruct * rv;
  553.  
  554.     while((object = (HotlistStruct *)XP_ListNextObject(list_ptr))!=0)
  555.       {
  556.  
  557.         if(object == *start_obj)
  558.             *start_obj = NULL;
  559.         else if(!*start_obj &&
  560.               ((object->name && strcasestr(object->name, search_string)) ||
  561.                     (object->address && strcasestr(object->address, search_string))))
  562.             return(object);
  563.  
  564.         *(cur_count) += 1;
  565.  
  566.         if(object->type == HOT_HeaderType)
  567.           {
  568.              rv = hot_SearchHotlistStub(object, 
  569.                                         search_string, 
  570.                                         start_obj, 
  571.                                         cur_count,
  572.                                         redisplay_all);
  573.             if(rv)
  574.               {
  575.                if(object->is_folded)
  576.                  {
  577.                    *redisplay_all = TRUE;
  578.                    object->is_folded = FALSE;
  579.                  }
  580.  
  581.                 return(rv);
  582.               }
  583.           }
  584.       }
  585.  
  586.     return(NULL);
  587. }
  588.  
  589. /* Performs regular expression match on hotlist name and address
  590.  * fields.  Returns the found object, or NULL if not
  591.  * found.
  592.  *
  593.  * start_obj specifies the object to start searching
  594.  * on.  The start_num object WILL NOT be searched but all those
  595.  * after it will be.
  596.  * To search the whole list give NULL as start_obj.
  597.  *
  598.  * If headers became unfolded because of the search then redisplay_all
  599.  * will be set to TRUE
  600.  */
  601. PUBLIC HotlistStruct *
  602. HOT_SearchHotlist(char * search_string, HotlistStruct * start_obj, Bool * redisplay_all)
  603. {
  604.     int count=1;
  605.  
  606.     *redisplay_all = FALSE;
  607.  
  608.     if(hot_list)
  609.         return(hot_SearchHotlistStub(hot_list, 
  610.                                     search_string, 
  611.                                     &start_obj, 
  612.                                     &count,
  613.                                     redisplay_all));
  614.     else
  615.         return(NULL);
  616. }
  617.  
  618.  
  619. PRIVATE int
  620. hot_GetObjDepth(HotlistStruct *parent, HotlistStruct * item, int cur_depth)
  621. {
  622.     XP_List * list_ptr = parent->children;
  623.     HotlistStruct * object;
  624.     int rv=0;
  625.  
  626.     cur_depth++;
  627.  
  628.     while((object = (HotlistStruct *)XP_ListNextObject(list_ptr))!=0)
  629.       {
  630.  
  631.         if(object == item)
  632.             return(cur_depth);
  633.  
  634.         if(object->type == HOT_HeaderType)
  635.           {
  636.             rv = hot_GetObjDepth(object, item, cur_depth);
  637.  
  638.             if(rv)
  639.                 return(rv);
  640.           }
  641.       }
  642.  
  643.     return(0);
  644. }
  645.  
  646. /* returns an integer depth of the item in the list starting at zero
  647.  */
  648. PUBLIC int
  649. HOT_GetDepth(HotlistStruct * item)
  650. {
  651.  
  652.     if(hot_list)
  653.         return(hot_GetObjDepth(hot_list, item, -1));
  654.     else
  655.         return(0);
  656. }
  657.  
  658.  
  659. PUBLIC HotlistStruct *
  660. hot_GetIndexOf(HotlistStruct *parent, int *index)
  661. {
  662.     HotlistStruct * rv=0;
  663.     HotlistStruct * object;
  664.     XP_List * list_ptr = parent->children;
  665.  
  666.     while((object = (HotlistStruct *)XP_ListNextObject(list_ptr))!=0)
  667.       {
  668.         *(index) -= 1;
  669.  
  670.         if(*index <= 0)
  671.             return(object);
  672.  
  673.         if(object->type == HOT_HeaderType && !object->is_folded)
  674.           {
  675.              rv = hot_GetIndexOf(object, index);
  676.  
  677.             if(rv)
  678.                 return(rv);
  679.           }
  680.       }
  681.  
  682.     return(NULL);
  683. }
  684.  
  685. /* returns the object associated with the index returned by 
  686.  * HOT_GetIndex()
  687.  */
  688. PUBLIC HotlistStruct *
  689. HOT_IndexOf(int index)
  690. {
  691.     TRACEMSG(("HOT_IndexOf: Getting index: %d",index));
  692.  
  693.     if(hot_list && index > 0)
  694.         return(hot_GetIndexOf(hot_list, &index));
  695.     else
  696.         return(NULL);
  697. }
  698.  
  699. PUBLIC HotlistStruct *
  700. hot_GetUnfoldedIndexOf(HotlistStruct *parent, int *index)
  701. {
  702.     HotlistStruct * rv=0;
  703.     HotlistStruct * object;
  704.     XP_List * list_ptr = parent->children;
  705.  
  706.     while((object = (HotlistStruct *)XP_ListNextObject(list_ptr))!=0)
  707.       {
  708.         *(index) -= 1;
  709.  
  710.         if(*index <= 0)
  711.             return(object);
  712.  
  713.         if(object->type == HOT_HeaderType)
  714.           {
  715.              rv = hot_GetUnfoldedIndexOf(object, index);
  716.  
  717.             if(rv)
  718.                 return(rv);
  719.           }
  720.       }
  721.  
  722.     return(NULL);
  723. }
  724.  
  725. /* returns the object associated with the index returned by
  726.  * HOT_GetUnfoldedIndex()
  727.  */
  728. PUBLIC HotlistStruct *
  729. HOT_UnfoldedIndexOf(int index)
  730. {
  731.     TRACEMSG(("HOT_IndexOf: Getting index: %d",index));
  732.  
  733.     if(hot_list && index > 0)
  734.         return(hot_GetUnfoldedIndexOf(hot_list, &index));
  735.     else
  736.         return(NULL);
  737. }
  738.  
  739.  
  740. PRIVATE HotlistStruct *
  741. hot_FindLastItem(HotlistStruct * item)
  742. {
  743.     if(item->type == HOT_HeaderType)
  744.       {
  745.         HotlistStruct * rv = (HotlistStruct *)XP_ListGetEndObject(item->children);
  746.         if(rv)
  747.            return(hot_FindLastItem(rv));
  748.       }
  749.  
  750.     return(item);
  751. }
  752.  
  753. /* move an item up in the list
  754.  */
  755. PUBLIC void
  756. HOT_MoveObjectUp(HotlistStruct * item)   
  757. {
  758.     HotlistStruct * hls = item->parent;
  759.     if(!hls)
  760.         hls = hot_list;
  761.  
  762.     hot_list_modified = TRUE;
  763.  
  764.     if(hls)
  765.       {
  766.          /* find the previous object in the list
  767.           */
  768.           XP_List *prev=0;
  769.         XP_List *list_ptr = hls->children;
  770.         HotlistStruct * prev_item;
  771.  
  772.           while (list_ptr->next)
  773.           {
  774.             prev = list_ptr;
  775.             list_ptr = list_ptr->next;
  776.             if (item == (HotlistStruct *)list_ptr->object)
  777.               {
  778.                 prev_item = (HotlistStruct *)prev->object;
  779.  
  780.                 if(prev_item)
  781.                   {
  782.                     /* remove the item from the list
  783.                      */
  784.                     XP_ListRemoveObject(hls->children, item);
  785.  
  786.                     if(prev_item->type != HOT_HeaderType || prev_item->is_folded)
  787.                       {
  788.                         HOT_InsertItemBefore(prev_item, item);
  789.                         TRACEMSG(("Normal jump move"));
  790.                       }
  791.                     else
  792.                       {
  793.                         /* add to end of children list
  794.                          */
  795.                         XP_ListAddObjectToEnd(prev_item->children, item);
  796.                         item->lParent = XP_ListFindObject(prev_item->children, item);
  797.                         item->parent = prev_item;
  798.                         TRACEMSG(("Addition to list above"));
  799.                       }
  800.                     return;
  801.                   }
  802.                 else
  803.                   {
  804.                     /* oh nasty, now we have to move object to a higher list
  805.                      */
  806.                     if(hls == hot_list)
  807.                         return; /* cannot move it up, already at the top */
  808.  
  809.                     /* remove the item from the other list
  810.                      */
  811.                     XP_ListRemoveObject(hls->children, item);
  812.  
  813.                     HOT_InsertItemBefore(hls, item);
  814.  
  815.                     return;
  816.                   }
  817.               }
  818.           }
  819.       }
  820. }
  821.  
  822. /* returns True if the object can be moved Up
  823.  * False if the object cannot be moved Up or if
  824.  * it cannot be found in the list
  825.  */
  826. PUBLIC Bool
  827. HOT_ObjectCanGoUp(HotlistStruct * item)
  828. {
  829.     /* this is sortof a hack.
  830.      * find the index of item.
  831.      * if greater than one then it can go up
  832.      */
  833.     int item_count = HOT_GetIndex(item);
  834.  
  835.     if(item_count > 1)
  836.         return(TRUE);
  837.  
  838.     return(FALSE);
  839.  
  840. }
  841.  
  842.  
  843.  
  844.  
  845.  
  846. /* move an item down in the list
  847.  */
  848. PUBLIC void
  849. HOT_MoveObjectDown(HotlistStruct * item)
  850. {
  851.     HotlistStruct * hls = item->parent;
  852.     if(!hls)
  853.         hls = hot_list;
  854.  
  855.     hot_list_modified = TRUE;
  856.  
  857.     if(hls)
  858.       {
  859.          /* find the object in the list
  860.           */
  861.         XP_List *list_ptr = hls->children;
  862.         XP_List *prev;
  863.         XP_List *next_ptr;
  864.         HotlistStruct * next_item;
  865.  
  866.         while (list_ptr->next)
  867.           {
  868.             prev = list_ptr;
  869.             list_ptr = list_ptr->next;
  870.             if (item == (HotlistStruct *)list_ptr->object)
  871.               {
  872.                 next_ptr = list_ptr->next;
  873.  
  874.                 if(list_ptr->next)
  875.                   {
  876.                     next_item = (HotlistStruct *)next_ptr->object;
  877.  
  878.                     if(next_item->type == HOT_HeaderType)
  879.                       {
  880.                         /* remove the item from list
  881.                          */
  882.                         XP_ListRemoveObject(hls->children, item);
  883.  
  884.                         if(next_item->is_folded)
  885.                           {
  886.                             /* add right after folded lists
  887.                              */
  888.                             HOT_InsertItemAfter(next_item, item); 
  889. TRACEMSG(("Moving item after folded list"));
  890.                           }
  891.                         else
  892.                           {
  893.                             /* add to top of children list
  894.                              */
  895.                             XP_ListAddObject(next_item->children, item);
  896.                             item->lParent = XP_ListFindObject(next_item->children, item);
  897.                             item->parent = next_item;
  898. TRACEMSG(("Moving item into list"));
  899.                           }
  900.  
  901.                         return;
  902.                       }
  903.                     else
  904.                       {
  905.                         /* move it after the next one */
  906.                         /* remove the item from list
  907.                           */
  908.                         XP_ListRemoveObject(hls->children, item);
  909.  
  910.                         XP_ListInsertObjectAfter(hls->children, 
  911.                                                  next_ptr->object, 
  912.                                                  item);
  913.                         item->lParent = XP_ListFindObject(hls->children, item);
  914. TRACEMSG(("Moving item after normal item"));
  915.                         return;
  916.                       }
  917.                   }
  918.                 else
  919.                   {
  920.                     if(hls == hot_list)
  921.                         return; /* cannot move it down, already at the bottom */
  922.  
  923.                     /* remove the item from list
  924.                      */
  925.                     XP_ListRemoveObject(hls->children, item);
  926. TRACEMSG(("Moving item down a hicharchy"));
  927.  
  928.                     HOT_InsertItemAfter(hls, item); 
  929.                     return;
  930.                   }
  931.                 }
  932.           }
  933.       }
  934. }
  935.  
  936. /* returns True if the object can be moved down
  937.  * False if the object cannot be moved down or if
  938.  * it cannot be found in the list
  939.  */
  940. PUBLIC Bool
  941. HOT_ObjectCanGoDown(HotlistStruct * item)
  942. {
  943.     /* this is sortof a hack.
  944.      * find the index of item.
  945.      * if found then try and find
  946.      * an object with an index one higher
  947.      * than item.  If it exists then the
  948.      * object can move down :)
  949.      */
  950.     int item_count = HOT_GetIndex(item);
  951.  
  952.     if(item_count)
  953.       {
  954.         item_count++;
  955.  
  956.         /* if there are other object below it we can obviously
  957.          * move down
  958.          */
  959.         if(HOT_IndexOf(item_count))
  960.             return(TRUE);
  961.  
  962.         /* if the object is at a depth other than the first
  963.          * then we can move down as well
  964.          */
  965.         if(HOT_GetDepth(item) > 0)
  966.             return(TRUE);
  967.       }
  968.  
  969.     return(FALSE);
  970. }
  971.  
  972. #define HOTLIST_COOKIE "<!DOCTYPE NETSCAPE-Bookmark-file-1>"
  973.  
  974. #define READ_BUFFER_SIZE 2048
  975.  
  976. PRIVATE void
  977. hot_ReadSaveList(XP_File fp, HotlistStruct * item, char *buffer, char * relative_url)
  978. {
  979.     char *ptr, *end, *url;
  980.     HotlistStruct * new_item=0;
  981.     Bool item_saved=FALSE;
  982.     char *buffer_ptr;
  983.  
  984.     /* read loop
  985.      */
  986.     while(XP_FileReadLine(buffer, READ_BUFFER_SIZE, fp))
  987.       {
  988.         buffer_ptr = XP_StripLine(buffer);
  989.  
  990.         if((ptr = strcasestr(buffer_ptr, "HREF=\""))!=0)
  991.           {
  992.             char *quote, *gtr_than;
  993.             /* find next quote
  994.              */
  995.             quote = XP_STRCHR(ptr+6, '"');
  996.     
  997.             if(quote)
  998.               {
  999.                 *quote = '\0';
  1000.  
  1001.                 url = NET_MakeAbsoluteURL(relative_url, ptr+6);
  1002.  
  1003.                 new_item = HOT_CreateEntry(HOT_URLType, NULL, url, NULL, 0);
  1004.                 item_saved = FALSE;
  1005.  
  1006.                 XP_FREE(url);
  1007.                 if(!new_item)
  1008.                     return;
  1009.  
  1010.                 /* find '>' and the name will be right after it
  1011.                  */
  1012.                 gtr_than = XP_STRCHR(quote+1, '>');
  1013.  
  1014.                 if(gtr_than)
  1015.                   {
  1016.                     /* find the end of the name
  1017.                      */
  1018.                     end = strcasestr(gtr_than, "</A>");
  1019.  
  1020.                     if(end)
  1021.                       {
  1022.                         *end = '\0';
  1023.                         StrAllocCopy(new_item->name, XP_StripLine(gtr_than+1));
  1024.  
  1025.                         /* terminate at beginning of name since there
  1026.                           * is nothing interesting after that
  1027.                           */
  1028.                         *gtr_than = '\0';
  1029.                       }
  1030.                     else
  1031.                       {
  1032.                         StrAllocCopy(new_item->name, XP_StripLine(gtr_than+1));
  1033.  
  1034.                         XP_FileReadLine(buffer_ptr, READ_BUFFER_SIZE, fp);
  1035.  
  1036.                         end = strcasestr(buffer_ptr, "</A>");
  1037.                             
  1038.                         if(end)
  1039.                             *end = '\0';
  1040.  
  1041.                         StrAllocCat(new_item->name, XP_StripLine(buffer_ptr));
  1042.                       }
  1043.                   }
  1044.  
  1045.                 *quote = '"';
  1046.               }
  1047.           }
  1048.         else if(((ptr = strcasestr(buffer_ptr, "<H"))!=0) && isdigit(*(ptr+2)))
  1049.           {
  1050.             /* find the beginning of the name
  1051.              */    
  1052.             char * gtr_than = XP_STRCHR(ptr+3, '>');
  1053.  
  1054.             /* find the end of the name
  1055.              */
  1056.             if(gtr_than)
  1057.                 end = strcasestr(gtr_than, "</H");
  1058.         
  1059.             if(gtr_than && end)
  1060.               {
  1061.                 *end = '\0';
  1062.  
  1063.                 new_item = HOT_CreateEntry(HOT_HeaderType, gtr_than+1, NULL, NULL, 0);
  1064.                 item_saved = FALSE;
  1065.  
  1066.                 if(!new_item)
  1067.                     return;
  1068.  
  1069.                 if(strcasestr(buffer_ptr, "FOLDED"))
  1070.                     new_item->is_folded = TRUE;
  1071.                 else
  1072.                     new_item->is_folded = FALSE;
  1073.  
  1074.                 *end = '<';
  1075.               }
  1076.           }
  1077.         else if((ptr = strcasestr(buffer_ptr, "<HR>"))!=0)
  1078.           {
  1079.             new_item = HOT_CreateEntry(HOT_SeparatorType, NULL, NULL, NULL, 0);
  1080.             item_saved = FALSE;
  1081.           }
  1082.         else if(strcasestr(buffer_ptr, "</UL>") ||
  1083.                     strcasestr(buffer_ptr, "</MENU>") ||
  1084.                         strcasestr(buffer_ptr, "</DL>"))
  1085.           {
  1086.             /* end of a header */
  1087.             if(item != hot_list)
  1088.                 return;
  1089.           }
  1090.         else
  1091.           {
  1092.             /* assume the rest is descriptions
  1093.              * only add if new_item is a URL
  1094.              */
  1095.             if(new_item && new_item->type == HOT_URLType)
  1096.               {
  1097.                 /* skip <DL> if present */
  1098.                 if(*buffer_ptr == '<')
  1099.                     buffer_ptr += 4;
  1100.  
  1101.                 end = buffer_ptr+XP_STRLEN(buffer_ptr)-1;
  1102.  
  1103.                 /* check for <BR> on the end and remove it
  1104.                  *
  1105.                  * also add a return
  1106.                  */
  1107.                 if(*end == '>')
  1108.                   {
  1109.                     end -= 3;
  1110.                     XP_STRCPY(end, LINEBREAK);
  1111.                     end += XP_STRLEN(LINEBREAK);
  1112.                     *end = '\0';
  1113.                   }
  1114.                 else
  1115.                   {
  1116.                     end++;
  1117.                     XP_STRCPY(end, LINEBREAK);
  1118.                     end += XP_STRLEN(LINEBREAK);
  1119.                     *end = '\0';
  1120.                   }
  1121.  
  1122.                 /* go through and turn < into '<'
  1123.                  */
  1124.                 for(ptr=buffer_ptr, end=buffer_ptr; *end != '\0'; end++)
  1125.                   {
  1126.                     if(!strncasecomp(end, "<", 4))
  1127.                       {
  1128.                         end += 3;
  1129.                         *ptr++ = '<';
  1130.                       }
  1131.                     else
  1132.                         {
  1133.                         *ptr++ = *end;
  1134.                       }
  1135.                   }
  1136.                 *ptr = '\0'; /* terminate */
  1137.                     
  1138.                 StrAllocCat(new_item->description, buffer_ptr);
  1139.               }
  1140.           }
  1141.  
  1142.         if(new_item)
  1143.           {
  1144.             /* search for other general attributes
  1145.              */
  1146.             if((ptr = strcasestr(buffer_ptr, "ADD_DATE=\""))!=0)
  1147.               {
  1148.                 end = XP_STRCHR(ptr+10, '"');
  1149.  
  1150.                 if(end)
  1151.                   {
  1152.                     *end = '\0';
  1153.                     if(new_item)
  1154.                         new_item->addition_date = (time_t) atol(ptr+10);
  1155.                     *end = '"';
  1156.                   }
  1157.               }
  1158.  
  1159.             if((ptr = strcasestr(buffer_ptr, "LAST_VISIT=\""))!=0)
  1160.               {
  1161.                 end = XP_STRCHR(ptr+12, '"');
  1162.  
  1163.                 if(end)
  1164.                   {
  1165.                     *end = '\0';
  1166.                     if(new_item)
  1167.                         new_item->last_visit = (time_t) atol(ptr+12);
  1168.                     *end = '"';
  1169.                   }
  1170.               }
  1171.  
  1172.             if(!item_saved)
  1173.               {
  1174.                 if(!item)
  1175.                    {
  1176.                     if(!hot_list)
  1177.                       {
  1178.                         if(new_item->type == HOT_HeaderType)
  1179.                           {
  1180.                             hot_list = new_item;
  1181.                           }
  1182.                         else
  1183.                           {
  1184.                             hot_list = HOT_CreateEntry(HOT_HeaderType, 
  1185.                                                         DEF_NAME, NULL, NULL, 0);
  1186.                             if(!hot_list)
  1187.                                 return;
  1188.  
  1189.                             XP_ListAddObjectToEnd(hot_list->children, new_item);
  1190.                             new_item->parent = NULL;
  1191.                             new_item->lParent = XP_ListFindObject(hot_list->children, new_item);
  1192.                           }
  1193.                       }
  1194.     
  1195.                     item = hot_list;
  1196.                    }
  1197.                 else
  1198.                   {
  1199.                     XP_ListAddObjectToEnd(item->children, new_item);
  1200.                     if(item == hot_list)
  1201.                         new_item->parent = NULL;
  1202.                     else
  1203.                         new_item->parent = item;
  1204.                     new_item->lParent = XP_ListFindObject(item->children, new_item);
  1205.                     
  1206.                   }
  1207.  
  1208.                 item_saved = TRUE;
  1209.               }
  1210.  
  1211.             if(new_item->type == HOT_HeaderType)
  1212.                 hot_ReadSaveList(fp, new_item, buffer, relative_url);
  1213.           }
  1214.       }
  1215. }
  1216.  
  1217. /* read hotlist file from disk
  1218.  * 
  1219.  * pass in a file url
  1220.  */
  1221. PUBLIC void
  1222. HOT_ReadHotlistFromDisk(char * filename, char * relative_url)
  1223. {
  1224.     XP_File fp;
  1225.     char buffer[READ_BUFFER_SIZE];
  1226.     
  1227.     fp = XP_FileOpen(filename, xpHotlist, XP_FILE_READ);
  1228.  
  1229.     if(!fp)
  1230.       {
  1231.         TRACEMSG(("could not open hotlist file for reading"));
  1232.         return;
  1233.       }
  1234.  
  1235.     TRACEMSG(("Reading MCC hotlist file"));
  1236.  
  1237. /* DONT REQUIRE THE COOKIE FOR NOW
  1238.  *
  1239.  * if(XP_STRNCMP(buffer, HOTLIST_COOKIE, strlen(HOTLIST_COOKIE)))
  1240.  *   {
  1241.  *        TRACEMSG(("ERROR! - Hotlist cookie not found in hotlist file"));
  1242.  *       return;
  1243.  *   }
  1244.  */
  1245.     /* hot_list probably doesn't exist yet
  1246.      */
  1247.     hot_ReadSaveList(fp, hot_list, buffer, relative_url);
  1248.     XP_FileClose(fp);
  1249.     hot_list_modified = FALSE;
  1250.  
  1251. }
  1252.  
  1253.  
  1254. PRIVATE void
  1255. hot_PrintList(XP_File fp, HotlistStruct * item, int level)
  1256. {
  1257.     int i;
  1258.     char buffer[16];
  1259.  
  1260.     /* indent 
  1261.      */
  1262.     for(i=0; i<level; i++)
  1263.         XP_FileWrite("    ", -1, fp);
  1264.  
  1265.     if(item->type == HOT_HeaderType)
  1266.       {
  1267.         XP_List * list_ptr = item->children;
  1268.         HotlistStruct * obj_ptr;
  1269.  
  1270.         if(level != 0)
  1271.           {
  1272.             if(item->name)
  1273.               {
  1274.                 XP_FileWrite("<DT><H3 ", -1, fp);
  1275.                 if(item->is_folded)
  1276.                     XP_FileWrite("FOLDED ", -1, fp);
  1277.                 XP_FileWrite("ADD_DATE=\"", -1, fp);
  1278.                 XP_SPRINTF(buffer, "%ld\">", item->addition_date);
  1279.                 XP_FileWrite(buffer, XP_STRLEN(buffer), fp);
  1280.                 XP_FileWrite(item->name, XP_STRLEN(item->name), fp);
  1281.                 XP_FileWrite("</H3>", -1, fp);
  1282.                 XP_FileWrite(LINEBREAK, XP_STRLEN(LINEBREAK), fp);
  1283.               }
  1284.             for(i=0; i<level; i++)
  1285.                 XP_FileWrite("    ", -1, fp); /* indent */
  1286.           }
  1287.         XP_FileWrite("<DL><p>", -1, fp);
  1288.         XP_FileWrite(LINEBREAK, XP_STRLEN(LINEBREAK), fp);
  1289.  
  1290.         while((obj_ptr = (HotlistStruct *) XP_ListNextObject(list_ptr))!=0)
  1291.             hot_PrintList(fp, obj_ptr, level+1);
  1292.  
  1293.         for(i=0; i<level; i++)
  1294.             XP_FileWrite("    ", -1, fp); /* indent */
  1295.         XP_FileWrite("</DL><p>", -1, fp);
  1296.         XP_FileWrite(LINEBREAK, XP_STRLEN(LINEBREAK), fp);
  1297.       }
  1298.     else if(item->type == HOT_SeparatorType)
  1299.       {
  1300.         XP_FileWrite("<HR>", -1, fp);
  1301.         XP_FileWrite(LINEBREAK, XP_STRLEN(LINEBREAK), fp);
  1302.       }
  1303.     else if(item->address) /* item type */
  1304.       {
  1305.         XP_FileWrite("<DT>", -1, fp);
  1306.         XP_FileWrite("<A HREF=\"", -1, fp);
  1307.         XP_FileWrite(item->address, XP_STRLEN(item->address), fp);
  1308.         XP_FileWrite("\" ADD_DATE=\"", -1, fp);
  1309.  
  1310.         XP_SPRINTF(buffer, "%ld", item->addition_date);
  1311.         XP_FileWrite(buffer, XP_STRLEN(buffer), fp);
  1312.             
  1313.         XP_FileWrite("\" LAST_VISIT=\"", -1, fp);
  1314.  
  1315.         XP_SPRINTF(buffer, "%ld\">", item->last_visit);
  1316.         XP_FileWrite(buffer, XP_STRLEN(buffer), fp);
  1317.  
  1318.         if(item->name)
  1319.             XP_FileWrite(item->name, XP_STRLEN(item->name), fp);
  1320.         else 
  1321.             XP_FileWrite(item->address, XP_STRLEN(item->address), fp);
  1322.  
  1323.         XP_FileWrite("</A>", -1, fp);
  1324.         XP_FileWrite(LINEBREAK, XP_STRLEN(LINEBREAK), fp);
  1325.  
  1326.         /* write description if there is one
  1327.          */
  1328.         if(item->description)
  1329.           {
  1330.             char *ptr = XP_StripLine(item->description);
  1331.  
  1332.             XP_FileWrite("<DD>", -1, fp);
  1333.  
  1334.             for(; *ptr != '\0'; ptr++)
  1335.                 if(*ptr == '<')
  1336.                     {
  1337.                     XP_FileWrite("<", -1, fp);
  1338.                     }
  1339.                 else if(*ptr == '\n')
  1340.                     {
  1341.                     XP_FileWrite("<BR>", -1, fp);
  1342.                     XP_FileWrite(LINEBREAK, XP_STRLEN(LINEBREAK), fp);
  1343.                     }
  1344.                 else
  1345.                     {
  1346.                     XP_FileWrite(ptr, 1, fp);
  1347.                     }
  1348.  
  1349.             XP_FileWrite(LINEBREAK, XP_STRLEN(LINEBREAK), fp);
  1350.           }
  1351.       }
  1352. }
  1353.  
  1354. PUBLIC Bool
  1355. HOT_Modified (void)
  1356. {
  1357.   return (hot_list_modified);
  1358. }
  1359.  
  1360. /* save out the hotlist
  1361.  *
  1362.  * returns 1 on success and 0 on failure
  1363.  * NOTE: the hotlist may not be saved if nothing has
  1364.  * changed
  1365.  */
  1366. PUBLIC int
  1367. HOT_SaveHotlist(char * filename)
  1368. {
  1369.     XP_File fp;
  1370.     char buffer[128];
  1371.     const char * hot_list_name;
  1372.  
  1373.     if(!hot_list_modified)
  1374.         return(1);   /* don't rewrite */
  1375.  
  1376. #ifdef MOZ_MAIL_NEWS
  1377.      hot_list_name = FE_UsersFullName();
  1378.     if(!hot_list_name)
  1379.         hot_list_name = FE_UsersMailAddress();
  1380. #else
  1381.     hot_list_name = NULL;
  1382. #endif /* MOZ_MAIL_NEWS */
  1383.  
  1384. #if defined(DEBUG_BOOKMARKS) && defined(XP_UNIX)
  1385.     fprintf (stderr, "HOT_SaveHotlist: writing %s\n", filename);
  1386. #endif
  1387.  
  1388.     fp = XP_FileOpen(filename, xpHotlist, XP_FILE_WRITE);
  1389.  
  1390.     if(!fp)
  1391.       {
  1392.         TRACEMSG(("could not open hotlist file for writing"));
  1393.         return(0);
  1394.       }
  1395.     
  1396.      /* write cookie
  1397.       */
  1398.      XP_FileWrite(HOTLIST_COOKIE, strlen(HOTLIST_COOKIE), fp);
  1399.      XP_FileWrite(LINEBREAK, XP_STRLEN(LINEBREAK), fp);
  1400.  
  1401.      XP_FileWrite(XP_GetString(XP_HOTLIST_AUTOGENERATED_FILE), -1, fp); 
  1402.  
  1403. /* L10N? are we still using this code? */
  1404.      XP_SPRINTF(buffer, "\
  1405. <TITLE>%s%s Bookmarks</TITLE>\n\
  1406. <H1>%s%s Bookmarks</H1>\n", hot_list_name ? hot_list_name : "Personal",
  1407.                           hot_list_name ? "'s" : "",
  1408.                           hot_list_name ? hot_list_name : "Personal",
  1409.                           hot_list_name ? "'s" : "");
  1410.  
  1411.     XP_FileWrite(buffer, XP_STRLEN(buffer), fp);
  1412.     
  1413.     if(hot_list)
  1414.         hot_PrintList(fp, hot_list, 0);
  1415.     else
  1416.         TRACEMSG(("No hotlist to write!"));
  1417.  
  1418.     XP_FileClose(fp);
  1419.  
  1420.     hot_list_modified = FALSE;
  1421.  
  1422.     return(1);
  1423. }
  1424.  
  1425.  
  1426. /*
  1427.  *    Gets the top node of the hotlist
  1428. */
  1429. PUBLIC HotlistStruct*
  1430. HOT_GetHotlist (void)
  1431. {
  1432.     if (!hot_list) 
  1433.       {
  1434.         hot_list = HOT_CreateEntry (HOT_HeaderType, DEF_NAME, NULL, NULL, 0);
  1435.         if (!hot_list)
  1436.             return NULL;
  1437.         hot_list->children = XP_ListNew ();
  1438.         if (!hot_list->children) 
  1439.              {
  1440.             HOT_FreeEntry(hot_list);
  1441.             hot_list = NULL;
  1442.           }
  1443.       }
  1444.     return hot_list;
  1445. }
  1446.  
  1447. /* Free's the entire hotlist
  1448.  */
  1449. PUBLIC void
  1450. HOT_FreeHotlist (void)
  1451. {
  1452.   if (hot_list)
  1453.     HOT_FreeEntry (hot_list);
  1454.   hot_list = 0;
  1455. }
  1456.