gecko-dev/lib/libmisc/hotlist.c
1998-03-28 02:44:41 +00:00

1456 lines
32 KiB
C

/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*-
*
* The contents of this file are subject to the Netscape Public License
* Version 1.0 (the "NPL"); you may not use this file except in
* compliance with the NPL. You may obtain a copy of the NPL at
* http://www.mozilla.org/NPL/
*
* Software distributed under the NPL is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the NPL
* for the specific language governing rights and limitations under the
* NPL.
*
* The Initial Developer of this code under the NPL is Netscape
* Communications Corporation. Portions created by Netscape are
* Copyright (C) 1998 Netscape Communications Corporation. All Rights
* Reserved.
*/
#include "hotlist.h"
#include "net.h"
#include "xp_mcom.h"
#include "client.h"
#include "xpgetstr.h"
extern int XP_HOTLIST_DEF_NAME;
extern int XP_HOTLIST_AUTOGENERATED_FILE;
#define DEF_NAME XP_GetString(XP_HOTLIST_DEF_NAME)
/*
Private Prototypes
*/
#ifdef NOPE
PRIVATE HotlistStruct *
hot_FindItemsParent(HotlistStruct * parent_node, HotlistStruct * item);
#endif
HotlistStruct *
hot_GetIndexOf(HotlistStruct *parent, int *index);
/* the main parent node
*/
PRIVATE HotlistStruct * hot_list=0;
PRIVATE XP_Bool hot_list_modified=FALSE;
/* return a pointer to the main hotlist list
*
* returns NULL if nothing has ever been
* added to the hotlist
*/
PUBLIC XP_List *
HOT_GetHotlistList(void)
{
if (! hot_list) return 0;
return (hot_list->children);
}
/* tell the hotlist code that the hotlist has been modified
* so that it gets saved the next time SaveHotlist is called
*/
PUBLIC void
HOT_SetModified(void)
{
hot_list_modified=TRUE;
}
PRIVATE HotlistStruct *
hot_FindItemStub(HotlistStruct *parent, char * url_address)
{
XP_List * list_ptr;
HotlistStruct * object;
if(parent == NULL) /* Eric made me do it */
return(0);
list_ptr = parent->children;
while((object = (HotlistStruct *)XP_ListNextObject(list_ptr))!=0)
{
if(object->address && !XP_STRCMP(object->address, url_address))
{
return(object);
}
if(object->type == HOT_HeaderType)
{
HotlistStruct * rv;
rv = hot_FindItemStub(object, url_address);
if(rv)
return(rv);
}
}
return(0);
}
/* checks the hotlist for a url and updates the last accessed
* time
*/
PUBLIC void
HOT_UpdateHotlistTime(URL_Struct *URL_s, time_t cur_time)
{
HotlistStruct * hs = hot_FindItemStub(hot_list, URL_s->address);
if(hs)
{
TRACEMSG(("Updating hotlist item access time: %s", hs->address));
hs->last_visit = cur_time;
hot_list_modified = TRUE;
}
}
/* create a hotlist entry struct and fill it in with
* the passed in data
*
* returns NULL on out of memory error.
*/
PUBLIC HotlistStruct *
HOT_CreateEntry(HOT_Type type,
const char *name,
const char *address,
const char *content_type,
time_t last_visit)
{
HotlistStruct * new_entry = XP_NEW(HotlistStruct);
if(!new_entry)
return(NULL);
memset(new_entry, 0, sizeof(HotlistStruct));
new_entry->type = type;
if(type == HOT_HeaderType)
new_entry->children = XP_ListNew();
else
StrAllocCopy(new_entry->address, address); /* headers can't have addresses */
StrAllocCopy(new_entry->name, name);
StrAllocCopy(new_entry->content_type, content_type);
new_entry->last_visit = last_visit;
new_entry->addition_date = time(NULL);
new_entry->parent = NULL;
new_entry->lParent = NULL;
return(new_entry);
}
/* free's a hotlist entry
*/
PUBLIC void
HOT_FreeEntry(HotlistStruct * entry)
{
if(entry)
{
if(entry->type == HOT_HeaderType)
{
HotlistStruct * subItem;
while((subItem = (HotlistStruct *) XP_ListRemoveTopObject(entry->children))!=0)
{
HOT_FreeEntry(subItem);
}
XP_ListDestroy(entry->children);
}
if(entry->name)
XP_FREE(entry->name);
if(entry->address)
XP_FREE(entry->address);
if(entry->content_type)
XP_FREE(entry->content_type);
XP_FREE(entry);
}
}
/* changes a entry to a header type from a non header type
* and vice versa. If the object was a header and
* has children, the children will be blown away. (very bad)
*/
PUBLIC void
HOT_ChangeEntryType(HotlistStruct * entry, HOT_Type type)
{
if(entry->type == type)
return;
entry->type = type;
if(entry->type == HOT_HeaderType)
{
entry->children = XP_ListNew();
}
else
{
XP_ListDestroy(entry->children);
entry->children = NULL;
}
hot_list_modified = TRUE;
}
/* create a completely new copy of the entry passed in
*/
PUBLIC HotlistStruct *
HOT_CopyEntry(HotlistStruct * entry)
{
if(!entry)
return(NULL);
return(HOT_CreateEntry(entry->type,
entry->name,
entry->address,
entry->content_type,
entry->last_visit));
}
/* Fold or unfold a hotlist header
*
* set the Boolean to True to fold the list and
* False to unfold
*/
PUBLIC void
HOT_FoldHeader(HotlistStruct * item, Bool fold)
{
hot_list_modified = TRUE;
if(item)
item->is_folded = fold;
}
#ifdef NOPE
/* recursive routine to find a HotlistStruct parent structure containing
* the list containing the specified hotlist item
*/
PRIVATE HotlistStruct *
hot_FindItemsParent(HotlistStruct * parent_node, HotlistStruct * item)
{
XP_List *cur_list = parent_node->children->next;
if(!cur_list)
return(NULL);
while(cur_list)
{
HotlistStruct *rv = NULL;
HotlistStruct *obj = (HotlistStruct *)cur_list->object;
if(obj == item)
{
return(parent_node);
}
else if(obj->type == HOT_HeaderType)
{
rv = hot_FindItemsParent(obj, item);
if(rv)
return(rv);
}
cur_list = cur_list->next;
}
return(NULL); /* not found */
}
#endif
/* insert an item before another item in the hotlist
*
* if the insert_before item is NULL or not found the item
* will be inserted at the begining of the list
*/
PUBLIC void
HOT_InsertItemBefore(HotlistStruct * insert_before, HotlistStruct * insertee)
{
HotlistStruct * hls=0;
if(!insertee)
return;
hot_list_modified = TRUE;
if(!hot_list)
{
hot_list = HOT_CreateEntry (HOT_HeaderType, XP_GetString(XP_HOTLIST_DEF_NAME), NULL, NULL, 0);
if(!hot_list)
return;
hot_list->children = XP_ListNew();
if (!hot_list->children)
{
HOT_FreeEntry(hot_list);
hot_list = NULL;
return;
}
}
/* find the list that contains the insert_before object
*/
if(insert_before) {
if(insert_before->parent) {
hls = insert_before->parent;
XP_ListInsertObject(hls->children, insert_before, insertee);
insertee->parent = hls;
insertee->lParent = XP_ListFindObject(hls->children, insertee);
} else {
XP_ListInsertObject(hot_list->children, insert_before, insertee);
insertee->parent = NULL;
insertee->lParent = XP_ListFindObject(hot_list->children, insertee);
}
} else {
XP_ListAddObjectToEnd(hot_list->children, insertee);
insertee->parent = NULL;
insertee->lParent = XP_ListFindObject(hot_list->children, insertee);
}
return;
}
/* insert an item after another item in the hotlist
*
* if the insert_after item is NULL or not found the item
* will be inserted at the end of the list
*/
PUBLIC void
HOT_InsertItemAfter(HotlistStruct * insert_after, HotlistStruct * insertee)
{
HotlistStruct * hls=0;
if(!insertee)
return;
hot_list_modified = TRUE;
if(!hot_list)
{
hot_list = HOT_CreateEntry(HOT_HeaderType, DEF_NAME, NULL, NULL, 0);
if(!hot_list)
return;
hot_list->children = XP_ListNew();
}
/* find the list that contains the insert_after object
*/
if(insert_after) {
if(insert_after->parent) {
hls = insert_after->parent;
XP_ListInsertObjectAfter(hls->children, insert_after, insertee);
insertee->parent = hls;
insertee->lParent = XP_ListFindObject(hls->children, insertee);
} else {
XP_ListInsertObjectAfter(hot_list->children, insert_after, insertee);
insertee->parent = NULL;
insertee->lParent = XP_ListFindObject(hot_list->children, insertee);
}
} else {
XP_ListAddObjectToEnd(hot_list->children, insertee);
insertee->parent = NULL;
insertee->lParent = XP_ListFindObject(hot_list->children, insertee);
}
return;
}
/* insert an item in a header if "insert_after" is a
* Header type, or after the item if "insert after" is
* not a header type.
*
* if the insert_after item is NULL or not found the item
* will be inserted at the end of the hotlist
*/
PUBLIC void
HOT_InsertItemInHeaderOrAfterItem(HotlistStruct * insert_after,
HotlistStruct * insertee)
{
if(!insertee)
return;
if(insert_after && insert_after->type == HOT_HeaderType)
{
XP_ListAddObject(insert_after->children, insertee);
if(insert_after != hot_list)
insertee->parent = insert_after;
else
insertee->parent = NULL;
insertee->lParent = XP_ListFindObject(insert_after->children, insertee);
return;
}
/* else */
HOT_InsertItemAfter(insert_after, insertee);
}
/* remove an item from the hotlist and free's it
*
* returns TRUE on success, FALSE if not found
*/
PUBLIC Bool
HOT_RemoveItem(HotlistStruct * old_item)
{
HotlistStruct * hls = old_item->parent;
if(!hls)
hls = hot_list;
hot_list_modified = TRUE;
if(hls)
{
XP_ListRemoveObject(hls->children, old_item);
HOT_FreeEntry(old_item);
return(TRUE);
}
/* else */
return(FALSE);
}
/* remove an item from the hotlist and doesn't free it
*
* returns TRUE on success, FALSE if not found
*/
PUBLIC Bool
HOT_RemoveItemFromList(HotlistStruct * old_item)
{
HotlistStruct * hls = old_item->parent;
if(!hls)
hls = hot_list;
hot_list_modified = TRUE;
if(hls)
{
XP_ListRemoveObject(hls->children, old_item);
return(TRUE);
}
/* else */
return(FALSE);
}
PRIVATE int
hot_GetIndexNum(HotlistStruct *parent, HotlistStruct * item, int *cur_count)
{
XP_List * list_ptr = parent->children;
HotlistStruct * object;
int rv=0;
while((object = (HotlistStruct *)XP_ListNextObject(list_ptr))!=0)
{
if(object == item)
return(*cur_count);
*(cur_count) += 1;
if(object->type == HOT_HeaderType && !object->is_folded)
{
rv = hot_GetIndexNum(object, item, cur_count);
if(rv)
return(rv);
}
}
return(0);
}
/* returns an integer index of the item in the list
*/
PUBLIC int
HOT_GetIndex(HotlistStruct * item)
{
int count=1;
if(hot_list)
return(hot_GetIndexNum(hot_list, item, &count));
else
return(0);
}
PRIVATE int
hot_GetUnfoldedIndexNum(HotlistStruct *parent, HotlistStruct * item, int *cur_count)
{
XP_List * list_ptr = parent->children;
HotlistStruct * object;
int rv=0;
while((object = (HotlistStruct *)XP_ListNextObject(list_ptr))!=0)
{
if(object == item)
return(*cur_count);
*(cur_count) += 1;
if(object->type == HOT_HeaderType)
{
rv = hot_GetUnfoldedIndexNum(object, item, cur_count);
if(rv)
return(rv);
}
}
return(0);
}
/* returns an integer index of the item in the list
* and does not pay attention to the is_folded value
*/
PUBLIC int
HOT_GetUnfoldedIndex(HotlistStruct * item)
{
int count=1;
if(hot_list)
return(hot_GetUnfoldedIndexNum(hot_list, item, &count));
else
return(0);
}
/* returns TRUE if the second argument is a direct
* descendent of the first argument.
*
* returns FALSE otherwise
*/
PUBLIC Bool
HOT_IsDescendent(HotlistStruct *parent, HotlistStruct *possible_child)
{
int count = 1;
if(parent
&& parent->type == HOT_HeaderType
&& hot_GetUnfoldedIndexNum(parent, possible_child, &count))
return(TRUE);
return(FALSE);
}
PRIVATE HotlistStruct *
hot_SearchHotlistStub(HotlistStruct *parent,
char * search_string,
HotlistStruct ** start_obj,
int *cur_count,
Bool *redisplay_all)
{
XP_List * list_ptr = parent->children;
HotlistStruct * object;
HotlistStruct * rv;
while((object = (HotlistStruct *)XP_ListNextObject(list_ptr))!=0)
{
if(object == *start_obj)
*start_obj = NULL;
else if(!*start_obj &&
((object->name && strcasestr(object->name, search_string)) ||
(object->address && strcasestr(object->address, search_string))))
return(object);
*(cur_count) += 1;
if(object->type == HOT_HeaderType)
{
rv = hot_SearchHotlistStub(object,
search_string,
start_obj,
cur_count,
redisplay_all);
if(rv)
{
if(object->is_folded)
{
*redisplay_all = TRUE;
object->is_folded = FALSE;
}
return(rv);
}
}
}
return(NULL);
}
/* Performs regular expression match on hotlist name and address
* fields. Returns the found object, or NULL if not
* found.
*
* start_obj specifies the object to start searching
* on. The start_num object WILL NOT be searched but all those
* after it will be.
* To search the whole list give NULL as start_obj.
*
* If headers became unfolded because of the search then redisplay_all
* will be set to TRUE
*/
PUBLIC HotlistStruct *
HOT_SearchHotlist(char * search_string, HotlistStruct * start_obj, Bool * redisplay_all)
{
int count=1;
*redisplay_all = FALSE;
if(hot_list)
return(hot_SearchHotlistStub(hot_list,
search_string,
&start_obj,
&count,
redisplay_all));
else
return(NULL);
}
PRIVATE int
hot_GetObjDepth(HotlistStruct *parent, HotlistStruct * item, int cur_depth)
{
XP_List * list_ptr = parent->children;
HotlistStruct * object;
int rv=0;
cur_depth++;
while((object = (HotlistStruct *)XP_ListNextObject(list_ptr))!=0)
{
if(object == item)
return(cur_depth);
if(object->type == HOT_HeaderType)
{
rv = hot_GetObjDepth(object, item, cur_depth);
if(rv)
return(rv);
}
}
return(0);
}
/* returns an integer depth of the item in the list starting at zero
*/
PUBLIC int
HOT_GetDepth(HotlistStruct * item)
{
if(hot_list)
return(hot_GetObjDepth(hot_list, item, -1));
else
return(0);
}
PUBLIC HotlistStruct *
hot_GetIndexOf(HotlistStruct *parent, int *index)
{
HotlistStruct * rv=0;
HotlistStruct * object;
XP_List * list_ptr = parent->children;
while((object = (HotlistStruct *)XP_ListNextObject(list_ptr))!=0)
{
*(index) -= 1;
if(*index <= 0)
return(object);
if(object->type == HOT_HeaderType && !object->is_folded)
{
rv = hot_GetIndexOf(object, index);
if(rv)
return(rv);
}
}
return(NULL);
}
/* returns the object associated with the index returned by
* HOT_GetIndex()
*/
PUBLIC HotlistStruct *
HOT_IndexOf(int index)
{
TRACEMSG(("HOT_IndexOf: Getting index: %d",index));
if(hot_list && index > 0)
return(hot_GetIndexOf(hot_list, &index));
else
return(NULL);
}
PUBLIC HotlistStruct *
hot_GetUnfoldedIndexOf(HotlistStruct *parent, int *index)
{
HotlistStruct * rv=0;
HotlistStruct * object;
XP_List * list_ptr = parent->children;
while((object = (HotlistStruct *)XP_ListNextObject(list_ptr))!=0)
{
*(index) -= 1;
if(*index <= 0)
return(object);
if(object->type == HOT_HeaderType)
{
rv = hot_GetUnfoldedIndexOf(object, index);
if(rv)
return(rv);
}
}
return(NULL);
}
/* returns the object associated with the index returned by
* HOT_GetUnfoldedIndex()
*/
PUBLIC HotlistStruct *
HOT_UnfoldedIndexOf(int index)
{
TRACEMSG(("HOT_IndexOf: Getting index: %d",index));
if(hot_list && index > 0)
return(hot_GetUnfoldedIndexOf(hot_list, &index));
else
return(NULL);
}
PRIVATE HotlistStruct *
hot_FindLastItem(HotlistStruct * item)
{
if(item->type == HOT_HeaderType)
{
HotlistStruct * rv = (HotlistStruct *)XP_ListGetEndObject(item->children);
if(rv)
return(hot_FindLastItem(rv));
}
return(item);
}
/* move an item up in the list
*/
PUBLIC void
HOT_MoveObjectUp(HotlistStruct * item)
{
HotlistStruct * hls = item->parent;
if(!hls)
hls = hot_list;
hot_list_modified = TRUE;
if(hls)
{
/* find the previous object in the list
*/
XP_List *prev=0;
XP_List *list_ptr = hls->children;
HotlistStruct * prev_item;
while (list_ptr->next)
{
prev = list_ptr;
list_ptr = list_ptr->next;
if (item == (HotlistStruct *)list_ptr->object)
{
prev_item = (HotlistStruct *)prev->object;
if(prev_item)
{
/* remove the item from the list
*/
XP_ListRemoveObject(hls->children, item);
if(prev_item->type != HOT_HeaderType || prev_item->is_folded)
{
HOT_InsertItemBefore(prev_item, item);
TRACEMSG(("Normal jump move"));
}
else
{
/* add to end of children list
*/
XP_ListAddObjectToEnd(prev_item->children, item);
item->lParent = XP_ListFindObject(prev_item->children, item);
item->parent = prev_item;
TRACEMSG(("Addition to list above"));
}
return;
}
else
{
/* oh nasty, now we have to move object to a higher list
*/
if(hls == hot_list)
return; /* cannot move it up, already at the top */
/* remove the item from the other list
*/
XP_ListRemoveObject(hls->children, item);
HOT_InsertItemBefore(hls, item);
return;
}
}
}
}
}
/* returns True if the object can be moved Up
* False if the object cannot be moved Up or if
* it cannot be found in the list
*/
PUBLIC Bool
HOT_ObjectCanGoUp(HotlistStruct * item)
{
/* this is sortof a hack.
* find the index of item.
* if greater than one then it can go up
*/
int item_count = HOT_GetIndex(item);
if(item_count > 1)
return(TRUE);
return(FALSE);
}
/* move an item down in the list
*/
PUBLIC void
HOT_MoveObjectDown(HotlistStruct * item)
{
HotlistStruct * hls = item->parent;
if(!hls)
hls = hot_list;
hot_list_modified = TRUE;
if(hls)
{
/* find the object in the list
*/
XP_List *list_ptr = hls->children;
XP_List *prev;
XP_List *next_ptr;
HotlistStruct * next_item;
while (list_ptr->next)
{
prev = list_ptr;
list_ptr = list_ptr->next;
if (item == (HotlistStruct *)list_ptr->object)
{
next_ptr = list_ptr->next;
if(list_ptr->next)
{
next_item = (HotlistStruct *)next_ptr->object;
if(next_item->type == HOT_HeaderType)
{
/* remove the item from list
*/
XP_ListRemoveObject(hls->children, item);
if(next_item->is_folded)
{
/* add right after folded lists
*/
HOT_InsertItemAfter(next_item, item);
TRACEMSG(("Moving item after folded list"));
}
else
{
/* add to top of children list
*/
XP_ListAddObject(next_item->children, item);
item->lParent = XP_ListFindObject(next_item->children, item);
item->parent = next_item;
TRACEMSG(("Moving item into list"));
}
return;
}
else
{
/* move it after the next one */
/* remove the item from list
*/
XP_ListRemoveObject(hls->children, item);
XP_ListInsertObjectAfter(hls->children,
next_ptr->object,
item);
item->lParent = XP_ListFindObject(hls->children, item);
TRACEMSG(("Moving item after normal item"));
return;
}
}
else
{
if(hls == hot_list)
return; /* cannot move it down, already at the bottom */
/* remove the item from list
*/
XP_ListRemoveObject(hls->children, item);
TRACEMSG(("Moving item down a hicharchy"));
HOT_InsertItemAfter(hls, item);
return;
}
}
}
}
}
/* returns True if the object can be moved down
* False if the object cannot be moved down or if
* it cannot be found in the list
*/
PUBLIC Bool
HOT_ObjectCanGoDown(HotlistStruct * item)
{
/* this is sortof a hack.
* find the index of item.
* if found then try and find
* an object with an index one higher
* than item. If it exists then the
* object can move down :)
*/
int item_count = HOT_GetIndex(item);
if(item_count)
{
item_count++;
/* if there are other object below it we can obviously
* move down
*/
if(HOT_IndexOf(item_count))
return(TRUE);
/* if the object is at a depth other than the first
* then we can move down as well
*/
if(HOT_GetDepth(item) > 0)
return(TRUE);
}
return(FALSE);
}
#define HOTLIST_COOKIE "<!DOCTYPE NETSCAPE-Bookmark-file-1>"
#define READ_BUFFER_SIZE 2048
PRIVATE void
hot_ReadSaveList(XP_File fp, HotlistStruct * item, char *buffer, char * relative_url)
{
char *ptr, *end, *url;
HotlistStruct * new_item=0;
Bool item_saved=FALSE;
char *buffer_ptr;
/* read loop
*/
while(XP_FileReadLine(buffer, READ_BUFFER_SIZE, fp))
{
buffer_ptr = XP_StripLine(buffer);
if((ptr = strcasestr(buffer_ptr, "HREF=\""))!=0)
{
char *quote, *gtr_than;
/* find next quote
*/
quote = XP_STRCHR(ptr+6, '"');
if(quote)
{
*quote = '\0';
url = NET_MakeAbsoluteURL(relative_url, ptr+6);
new_item = HOT_CreateEntry(HOT_URLType, NULL, url, NULL, 0);
item_saved = FALSE;
XP_FREE(url);
if(!new_item)
return;
/* find '>' and the name will be right after it
*/
gtr_than = XP_STRCHR(quote+1, '>');
if(gtr_than)
{
/* find the end of the name
*/
end = strcasestr(gtr_than, "</A>");
if(end)
{
*end = '\0';
StrAllocCopy(new_item->name, XP_StripLine(gtr_than+1));
/* terminate at beginning of name since there
* is nothing interesting after that
*/
*gtr_than = '\0';
}
else
{
StrAllocCopy(new_item->name, XP_StripLine(gtr_than+1));
XP_FileReadLine(buffer_ptr, READ_BUFFER_SIZE, fp);
end = strcasestr(buffer_ptr, "</A>");
if(end)
*end = '\0';
StrAllocCat(new_item->name, XP_StripLine(buffer_ptr));
}
}
*quote = '"';
}
}
else if(((ptr = strcasestr(buffer_ptr, "<H"))!=0) && isdigit(*(ptr+2)))
{
/* find the beginning of the name
*/
char * gtr_than = XP_STRCHR(ptr+3, '>');
/* find the end of the name
*/
if(gtr_than)
end = strcasestr(gtr_than, "</H");
if(gtr_than && end)
{
*end = '\0';
new_item = HOT_CreateEntry(HOT_HeaderType, gtr_than+1, NULL, NULL, 0);
item_saved = FALSE;
if(!new_item)
return;
if(strcasestr(buffer_ptr, "FOLDED"))
new_item->is_folded = TRUE;
else
new_item->is_folded = FALSE;
*end = '<';
}
}
else if((ptr = strcasestr(buffer_ptr, "<HR>"))!=0)
{
new_item = HOT_CreateEntry(HOT_SeparatorType, NULL, NULL, NULL, 0);
item_saved = FALSE;
}
else if(strcasestr(buffer_ptr, "</UL>") ||
strcasestr(buffer_ptr, "</MENU>") ||
strcasestr(buffer_ptr, "</DL>"))
{
/* end of a header */
if(item != hot_list)
return;
}
else
{
/* assume the rest is descriptions
* only add if new_item is a URL
*/
if(new_item && new_item->type == HOT_URLType)
{
/* skip <DL> if present */
if(*buffer_ptr == '<')
buffer_ptr += 4;
end = buffer_ptr+XP_STRLEN(buffer_ptr)-1;
/* check for <BR> on the end and remove it
*
* also add a return
*/
if(*end == '>')
{
end -= 3;
XP_STRCPY(end, LINEBREAK);
end += XP_STRLEN(LINEBREAK);
*end = '\0';
}
else
{
end++;
XP_STRCPY(end, LINEBREAK);
end += XP_STRLEN(LINEBREAK);
*end = '\0';
}
/* go through and turn &lt; into '<'
*/
for(ptr=buffer_ptr, end=buffer_ptr; *end != '\0'; end++)
{
if(!strncasecomp(end, "&lt;", 4))
{
end += 3;
*ptr++ = '<';
}
else
{
*ptr++ = *end;
}
}
*ptr = '\0'; /* terminate */
StrAllocCat(new_item->description, buffer_ptr);
}
}
if(new_item)
{
/* search for other general attributes
*/
if((ptr = strcasestr(buffer_ptr, "ADD_DATE=\""))!=0)
{
end = XP_STRCHR(ptr+10, '"');
if(end)
{
*end = '\0';
if(new_item)
new_item->addition_date = (time_t) atol(ptr+10);
*end = '"';
}
}
if((ptr = strcasestr(buffer_ptr, "LAST_VISIT=\""))!=0)
{
end = XP_STRCHR(ptr+12, '"');
if(end)
{
*end = '\0';
if(new_item)
new_item->last_visit = (time_t) atol(ptr+12);
*end = '"';
}
}
if(!item_saved)
{
if(!item)
{
if(!hot_list)
{
if(new_item->type == HOT_HeaderType)
{
hot_list = new_item;
}
else
{
hot_list = HOT_CreateEntry(HOT_HeaderType,
DEF_NAME, NULL, NULL, 0);
if(!hot_list)
return;
XP_ListAddObjectToEnd(hot_list->children, new_item);
new_item->parent = NULL;
new_item->lParent = XP_ListFindObject(hot_list->children, new_item);
}
}
item = hot_list;
}
else
{
XP_ListAddObjectToEnd(item->children, new_item);
if(item == hot_list)
new_item->parent = NULL;
else
new_item->parent = item;
new_item->lParent = XP_ListFindObject(item->children, new_item);
}
item_saved = TRUE;
}
if(new_item->type == HOT_HeaderType)
hot_ReadSaveList(fp, new_item, buffer, relative_url);
}
}
}
/* read hotlist file from disk
*
* pass in a file url
*/
PUBLIC void
HOT_ReadHotlistFromDisk(char * filename, char * relative_url)
{
XP_File fp;
char buffer[READ_BUFFER_SIZE];
fp = XP_FileOpen(filename, xpHotlist, XP_FILE_READ);
if(!fp)
{
TRACEMSG(("could not open hotlist file for reading"));
return;
}
TRACEMSG(("Reading MCC hotlist file"));
/* DONT REQUIRE THE COOKIE FOR NOW
*
* if(XP_STRNCMP(buffer, HOTLIST_COOKIE, strlen(HOTLIST_COOKIE)))
* {
* TRACEMSG(("ERROR! - Hotlist cookie not found in hotlist file"));
* return;
* }
*/
/* hot_list probably doesn't exist yet
*/
hot_ReadSaveList(fp, hot_list, buffer, relative_url);
XP_FileClose(fp);
hot_list_modified = FALSE;
}
PRIVATE void
hot_PrintList(XP_File fp, HotlistStruct * item, int level)
{
int i;
char buffer[16];
/* indent
*/
for(i=0; i<level; i++)
XP_FileWrite(" ", -1, fp);
if(item->type == HOT_HeaderType)
{
XP_List * list_ptr = item->children;
HotlistStruct * obj_ptr;
if(level != 0)
{
if(item->name)
{
XP_FileWrite("<DT><H3 ", -1, fp);
if(item->is_folded)
XP_FileWrite("FOLDED ", -1, fp);
XP_FileWrite("ADD_DATE=\"", -1, fp);
XP_SPRINTF(buffer, "%ld\">", item->addition_date);
XP_FileWrite(buffer, XP_STRLEN(buffer), fp);
XP_FileWrite(item->name, XP_STRLEN(item->name), fp);
XP_FileWrite("</H3>", -1, fp);
XP_FileWrite(LINEBREAK, XP_STRLEN(LINEBREAK), fp);
}
for(i=0; i<level; i++)
XP_FileWrite(" ", -1, fp); /* indent */
}
XP_FileWrite("<DL><p>", -1, fp);
XP_FileWrite(LINEBREAK, XP_STRLEN(LINEBREAK), fp);
while((obj_ptr = (HotlistStruct *) XP_ListNextObject(list_ptr))!=0)
hot_PrintList(fp, obj_ptr, level+1);
for(i=0; i<level; i++)
XP_FileWrite(" ", -1, fp); /* indent */
XP_FileWrite("</DL><p>", -1, fp);
XP_FileWrite(LINEBREAK, XP_STRLEN(LINEBREAK), fp);
}
else if(item->type == HOT_SeparatorType)
{
XP_FileWrite("<HR>", -1, fp);
XP_FileWrite(LINEBREAK, XP_STRLEN(LINEBREAK), fp);
}
else if(item->address) /* item type */
{
XP_FileWrite("<DT>", -1, fp);
XP_FileWrite("<A HREF=\"", -1, fp);
XP_FileWrite(item->address, XP_STRLEN(item->address), fp);
XP_FileWrite("\" ADD_DATE=\"", -1, fp);
XP_SPRINTF(buffer, "%ld", item->addition_date);
XP_FileWrite(buffer, XP_STRLEN(buffer), fp);
XP_FileWrite("\" LAST_VISIT=\"", -1, fp);
XP_SPRINTF(buffer, "%ld\">", item->last_visit);
XP_FileWrite(buffer, XP_STRLEN(buffer), fp);
if(item->name)
XP_FileWrite(item->name, XP_STRLEN(item->name), fp);
else
XP_FileWrite(item->address, XP_STRLEN(item->address), fp);
XP_FileWrite("</A>", -1, fp);
XP_FileWrite(LINEBREAK, XP_STRLEN(LINEBREAK), fp);
/* write description if there is one
*/
if(item->description)
{
char *ptr = XP_StripLine(item->description);
XP_FileWrite("<DD>", -1, fp);
for(; *ptr != '\0'; ptr++)
if(*ptr == '<')
{
XP_FileWrite("&lt;", -1, fp);
}
else if(*ptr == '\n')
{
XP_FileWrite("<BR>", -1, fp);
XP_FileWrite(LINEBREAK, XP_STRLEN(LINEBREAK), fp);
}
else
{
XP_FileWrite(ptr, 1, fp);
}
XP_FileWrite(LINEBREAK, XP_STRLEN(LINEBREAK), fp);
}
}
}
PUBLIC Bool
HOT_Modified (void)
{
return (hot_list_modified);
}
/* save out the hotlist
*
* returns 1 on success and 0 on failure
* NOTE: the hotlist may not be saved if nothing has
* changed
*/
PUBLIC int
HOT_SaveHotlist(char * filename)
{
XP_File fp;
char buffer[128];
const char * hot_list_name;
if(!hot_list_modified)
return(1); /* don't rewrite */
#ifdef MOZ_MAIL_NEWS
hot_list_name = FE_UsersFullName();
if(!hot_list_name)
hot_list_name = FE_UsersMailAddress();
#else
hot_list_name = NULL;
#endif /* MOZ_MAIL_NEWS */
#if defined(DEBUG_BOOKMARKS) && defined(XP_UNIX)
fprintf (stderr, "HOT_SaveHotlist: writing %s\n", filename);
#endif
fp = XP_FileOpen(filename, xpHotlist, XP_FILE_WRITE);
if(!fp)
{
TRACEMSG(("could not open hotlist file for writing"));
return(0);
}
/* write cookie
*/
XP_FileWrite(HOTLIST_COOKIE, strlen(HOTLIST_COOKIE), fp);
XP_FileWrite(LINEBREAK, XP_STRLEN(LINEBREAK), fp);
XP_FileWrite(XP_GetString(XP_HOTLIST_AUTOGENERATED_FILE), -1, fp);
/* L10N? are we still using this code? */
XP_SPRINTF(buffer, "\
<TITLE>%s%s Bookmarks</TITLE>\n\
<H1>%s%s Bookmarks</H1>\n", hot_list_name ? hot_list_name : "Personal",
hot_list_name ? "'s" : "",
hot_list_name ? hot_list_name : "Personal",
hot_list_name ? "'s" : "");
XP_FileWrite(buffer, XP_STRLEN(buffer), fp);
if(hot_list)
hot_PrintList(fp, hot_list, 0);
else
TRACEMSG(("No hotlist to write!"));
XP_FileClose(fp);
hot_list_modified = FALSE;
return(1);
}
/*
* Gets the top node of the hotlist
*/
PUBLIC HotlistStruct*
HOT_GetHotlist (void)
{
if (!hot_list)
{
hot_list = HOT_CreateEntry (HOT_HeaderType, DEF_NAME, NULL, NULL, 0);
if (!hot_list)
return NULL;
hot_list->children = XP_ListNew ();
if (!hot_list->children)
{
HOT_FreeEntry(hot_list);
hot_list = NULL;
}
}
return hot_list;
}
/* Free's the entire hotlist
*/
PUBLIC void
HOT_FreeHotlist (void)
{
if (hot_list)
HOT_FreeEntry (hot_list);
hot_list = 0;
}