mirror of https://github.com/lianthony/NT4.0
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1039 lines
30 KiB
1039 lines
30 KiB
/*
|
|
** File: hthotlst.c
|
|
**
|
|
** Description: Parser for hierarchical hotlist (HTML) file.
|
|
** All source code modifications to support hierarchical
|
|
** hotlists are enclosed with "#ifdef FEATURE_KAZAN_HOTLIST".
|
|
**
|
|
** Author(s): Scott Piette [email protected]
|
|
** Bradford L. Terrell [email protected]
|
|
**
|
|
** Copyright: (c) 1994, 1995 by Spyglass, Inc.
|
|
** All Rights Reserved
|
|
**
|
|
** History: (Most recent first)
|
|
**
|
|
** 11/01/95 blt Modified DlgHotTree_AddTreeItem() to conditionally
|
|
** make items visible based on a new "FOLDER_STATE"
|
|
** keyword.
|
|
** 09/15/95 blt Modified DumpTreeItem() and WriteItem() to
|
|
** handle empty folders in the TreeView.
|
|
** 09/15/95 blt Modified DlgHotTree_AddTreeItem() and added
|
|
** AddRootToTreeView() to fix bug in hotlist
|
|
** parsing. This fix inserts top-level items
|
|
** into the tree as children of the root node
|
|
** rather than siblings.
|
|
** 09/05/95 blt Modified DlgHotTree_AddTreeItem() to use
|
|
** I_IMAGECALLBACK for folders in Image List.
|
|
** Modified to add a root node to Tree View.
|
|
** 08/25/95 blt Modified to use Windows TreeView control for
|
|
** hierarchical hotlists.
|
|
*/
|
|
|
|
#include "all.h"
|
|
|
|
#ifdef FEATURE_KAZAN_HOTLIST
|
|
static HTREEITEM parentTreeItem[MAX_HOTLIST_NESTING + 1];
|
|
static int parentItemIndex = 0;
|
|
#endif
|
|
|
|
|
|
#ifdef MAC
|
|
extern void DlgHOT_RefreshHotlist (void);
|
|
#endif
|
|
|
|
extern void HotList_updatedisplay(int flag);
|
|
|
|
static BOOL bHotListLoading;
|
|
|
|
typedef struct _hotlist_stack_table
|
|
{
|
|
|
|
struct hash_table *hotlist_stack[MAX_HOTLIST_NESTING + 1];
|
|
int hotlist_stack_index;
|
|
int hotlist_menu_index;
|
|
|
|
} hotlist_stack_table;
|
|
|
|
struct _hotlist_stack_table gHotListTable;
|
|
|
|
far struct hash_table gHotList;
|
|
|
|
/* HTML Object
|
|
** -----------
|
|
*/
|
|
|
|
#define TITLE_LEN 512
|
|
|
|
struct _HTStructured
|
|
{
|
|
CONST HTStructuredClass *isa;
|
|
CONST SGML_dtd *dtd;
|
|
|
|
BOOL bInAnchor;
|
|
BOOL bHaveAnchor;
|
|
BOOL bInHeader;
|
|
BOOL bHaveHeader;
|
|
#ifdef FEATURE_KAZAN_HOTLIST
|
|
BOOL bVisible;
|
|
#endif
|
|
char href[MAX_URL_STRING + 1];
|
|
char title[TITLE_LEN + 1]; /* TODO check this for overflow */
|
|
int lenTitle;
|
|
char base_url[MAX_URL_STRING + 1];
|
|
struct hash_table *hash_stack[MAX_HOTLIST_NESTING + 1];
|
|
int hash_table_index;
|
|
};
|
|
|
|
/* Flush Buffer
|
|
** ------------
|
|
*/
|
|
PRIVATE void HTHotList_flush(HTStructured * me)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
/* Character handling
|
|
** ------------------
|
|
**
|
|
*/
|
|
PRIVATE void HTHotList_put_character(HTStructured * me, char c)
|
|
{
|
|
switch (c)
|
|
{
|
|
case '\n':
|
|
case '\t':
|
|
case '\r':
|
|
c = ' ';
|
|
break;
|
|
default:
|
|
break;
|
|
}
|
|
|
|
if (me->bInAnchor || me->bInHeader)
|
|
{
|
|
if (!(c == ' ' && me->lenTitle == 0))
|
|
{
|
|
me->title[me->lenTitle++] = c;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* String handling
|
|
** ---------------
|
|
*/
|
|
PRIVATE void HTHotList_put_string(HTStructured * me, CONST char *s)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
PRIVATE void HTHotList_write(HTStructured * me, CONST char *s, int l)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
/* Start Element
|
|
** -------------
|
|
**
|
|
*/
|
|
PRIVATE void HTHotList_start_element(HTStructured * me, int element_number, CONST BOOL * present, CONST char **value)
|
|
{
|
|
switch (element_number)
|
|
{
|
|
case HTML_DL:
|
|
{
|
|
#ifndef FEATURE_KAZAN_HOTLIST
|
|
struct hash_table *new_hash;
|
|
#endif
|
|
|
|
if (me->bHaveHeader)
|
|
{
|
|
if (me->title[0])
|
|
{
|
|
if (me->hash_table_index < MAX_HOTLIST_NESTING)
|
|
{
|
|
#ifdef FEATURE_KAZAN_HOTLIST
|
|
if (parentItemIndex == 0)
|
|
{
|
|
HWND hWndTreeView = DlgHotTree_GetHotlistTreeViewWindow();
|
|
parentTreeItem[parentItemIndex] = DlgHotTree_AddTreeItem(TreeView_GetRoot(hWndTreeView), me->title, NULL,
|
|
(HTREEITEM) TVI_LAST, I_IMAGECALLBACK, hWndTreeView, me->bVisible);
|
|
}
|
|
else
|
|
parentTreeItem[parentItemIndex] = DlgHotTree_AddTreeItem(parentTreeItem[parentItemIndex - 1], me->title, NULL,
|
|
(HTREEITEM) TVI_LAST, I_IMAGECALLBACK, DlgHotTree_GetHotlistTreeViewWindow(), me->bVisible);
|
|
parentItemIndex++;
|
|
#else
|
|
new_hash = Hash_Create();
|
|
Hash_Add(me->hash_stack[me->hash_table_index++],
|
|
me->title, NULL, new_hash);
|
|
me->hash_stack[me->hash_table_index] = new_hash;
|
|
/* Now add the back link to the hash */
|
|
Hash_Add(me->hash_stack[me->hash_table_index],
|
|
HOTLIST_SUBMENU_LINK_TEXT, NULL,
|
|
me->hash_stack[me->hash_table_index-1]);
|
|
#endif
|
|
}
|
|
}
|
|
me->bHaveHeader = FALSE;
|
|
}
|
|
else if (me->bHaveAnchor)
|
|
{
|
|
if (me->title[0])
|
|
{
|
|
#ifdef FEATURE_KAZAN_HOTLIST
|
|
if (parentItemIndex == 0)
|
|
DlgHotTree_AddTreeItem(NULL, me->title, me->href,
|
|
(HTREEITEM) TVI_LAST, DlgHotTree_GetWebPageBitmapIndex(),
|
|
DlgHotTree_GetHotlistTreeViewWindow(), me->bVisible);
|
|
else
|
|
DlgHotTree_AddTreeItem(parentTreeItem[parentItemIndex - 1], me->title, me->href,
|
|
(HTREEITEM) TVI_LAST, DlgHotTree_GetWebPageBitmapIndex(),
|
|
DlgHotTree_GetHotlistTreeViewWindow(), me->bVisible);
|
|
#else
|
|
Hash_Add(me->hash_stack[me->hash_table_index],
|
|
me->href, me->title, NULL);
|
|
#endif
|
|
}
|
|
me->bHaveAnchor = FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case HTML_DT:
|
|
{
|
|
if (me->bHaveAnchor)
|
|
{
|
|
if (me->title[0])
|
|
{
|
|
#ifdef FEATURE_KAZAN_HOTLIST
|
|
if (parentItemIndex == 0)
|
|
DlgHotTree_AddTreeItem(NULL, me->title, me->href,
|
|
(HTREEITEM) TVI_LAST, DlgHotTree_GetWebPageBitmapIndex(),
|
|
DlgHotTree_GetHotlistTreeViewWindow(), me->bVisible);
|
|
else
|
|
DlgHotTree_AddTreeItem(parentTreeItem[parentItemIndex - 1], me->title, me->href,
|
|
(HTREEITEM) TVI_LAST, DlgHotTree_GetWebPageBitmapIndex(),
|
|
DlgHotTree_GetHotlistTreeViewWindow(), me->bVisible);
|
|
#else
|
|
Hash_Add(me->hash_stack[me->hash_table_index],
|
|
me->href, me->title, NULL);
|
|
#endif
|
|
}
|
|
me->bHaveAnchor = FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case HTML_H3:
|
|
{
|
|
if (me->bHaveAnchor)
|
|
{
|
|
if (me->title[0])
|
|
{
|
|
#ifdef FEATURE_KAZAN_HOTLIST
|
|
if (parentItemIndex == 0)
|
|
DlgHotTree_AddTreeItem(NULL, me->title, me->href,
|
|
(HTREEITEM) TVI_LAST, DlgHotTree_GetWebPageBitmapIndex(),
|
|
DlgHotTree_GetHotlistTreeViewWindow(), me->bVisible);
|
|
else
|
|
DlgHotTree_AddTreeItem(parentTreeItem[parentItemIndex - 1], me->title, me->href,
|
|
(HTREEITEM) TVI_LAST, DlgHotTree_GetWebPageBitmapIndex(),
|
|
DlgHotTree_GetHotlistTreeViewWindow(), me->bVisible);
|
|
#else
|
|
Hash_Add(me->hash_stack[me->hash_table_index],
|
|
me->href, me->title, NULL);
|
|
|
|
#endif
|
|
}
|
|
me->bHaveAnchor = FALSE;
|
|
}
|
|
me->bHaveHeader = FALSE;
|
|
memset(me->title, 0, TITLE_LEN + 1);
|
|
me->lenTitle = 0;
|
|
me->bInHeader = TRUE;
|
|
#ifdef FEATURE_KAZAN_HOTLIST
|
|
if (present[HTML_HEADER_VISIBLE] && (strcmp(value[HTML_HEADER_VISIBLE], "1") == 0))
|
|
{
|
|
me->bVisible = TRUE;
|
|
}
|
|
else
|
|
{
|
|
me->bVisible = FALSE;
|
|
}
|
|
#endif
|
|
break;
|
|
}
|
|
|
|
case HTML_A:
|
|
{
|
|
if (me->bHaveAnchor)
|
|
{
|
|
if (me->title[0])
|
|
{
|
|
#ifdef FEATURE_KAZAN_HOTLIST
|
|
if (parentItemIndex == 0)
|
|
DlgHotTree_AddTreeItem(NULL, me->title, me->href,
|
|
(HTREEITEM) TVI_LAST, DlgHotTree_GetWebPageBitmapIndex(),
|
|
DlgHotTree_GetHotlistTreeViewWindow(), me->bVisible);
|
|
else
|
|
DlgHotTree_AddTreeItem(parentTreeItem[parentItemIndex - 1], me->title, me->href,
|
|
(HTREEITEM) TVI_LAST, DlgHotTree_GetWebPageBitmapIndex(),
|
|
DlgHotTree_GetHotlistTreeViewWindow(), me->bVisible);
|
|
#else
|
|
Hash_Add(me->hash_stack[me->hash_table_index],
|
|
me->href, me->title, NULL);
|
|
#endif
|
|
}
|
|
me->bHaveAnchor = FALSE;
|
|
}
|
|
if (present[HTML_A_HREF])
|
|
{
|
|
GTR_strncpy(me->href, value[HTML_A_HREF], MAX_URL_STRING);
|
|
HTSimplify(me->href);
|
|
}
|
|
|
|
memset(me->title, 0, TITLE_LEN + 1);
|
|
me->lenTitle = 0;
|
|
me->bInAnchor = TRUE;
|
|
me->bHaveAnchor = FALSE;
|
|
#ifdef FEATURE_KAZAN_HOTLIST
|
|
if (present[HTML_A_VISIBLE] && (strcmp(value[HTML_A_VISIBLE], "1") == 0))
|
|
{
|
|
me->bVisible = TRUE;
|
|
}
|
|
else
|
|
{
|
|
me->bVisible = FALSE;
|
|
}
|
|
#endif
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* End Element
|
|
** -----------
|
|
**
|
|
*/
|
|
PRIVATE void HTHotList_end_element(HTStructured * me, int element_number)
|
|
{
|
|
char *full_address;
|
|
char mycopy[MAX_URL_STRING + 1];
|
|
char *stripped;
|
|
|
|
switch (element_number)
|
|
{
|
|
case HTML_DL:
|
|
{
|
|
if (me->bHaveAnchor)
|
|
{
|
|
if (me->title[0])
|
|
{
|
|
#ifdef FEATURE_KAZAN_HOTLIST
|
|
if (parentItemIndex == 0)
|
|
DlgHotTree_AddTreeItem(NULL, me->title, me->href,
|
|
(HTREEITEM) TVI_LAST, DlgHotTree_GetWebPageBitmapIndex(),
|
|
DlgHotTree_GetHotlistTreeViewWindow(), me->bVisible);
|
|
else
|
|
DlgHotTree_AddTreeItem(parentTreeItem[parentItemIndex - 1], me->title, me->href,
|
|
(HTREEITEM) TVI_LAST, DlgHotTree_GetWebPageBitmapIndex(),
|
|
DlgHotTree_GetHotlistTreeViewWindow(), me->bVisible);
|
|
#else
|
|
Hash_Add(me->hash_stack[me->hash_table_index],
|
|
me->href, me->title, NULL);
|
|
#endif
|
|
}
|
|
me->bHaveAnchor = FALSE;
|
|
}
|
|
#ifdef FEATURE_KAZAN_HOTLIST
|
|
if (parentItemIndex > 0)
|
|
{
|
|
parentItemIndex--;
|
|
}
|
|
#endif
|
|
if (me->hash_table_index > 0)
|
|
{
|
|
me->hash_table_index--;
|
|
}
|
|
}
|
|
break;
|
|
case HTML_H3:
|
|
{
|
|
if (me->title[0])
|
|
me->bHaveHeader = TRUE;
|
|
me->bInHeader = FALSE;
|
|
}
|
|
break;
|
|
case HTML_A:
|
|
/*
|
|
First get the full URL
|
|
*/
|
|
if (me->href)
|
|
{
|
|
GTR_strncpy(mycopy, me->href, MAX_URL_STRING);
|
|
|
|
stripped = HTStrip(mycopy);
|
|
if (stripped)
|
|
{
|
|
full_address = HTParse(stripped, me->base_url,
|
|
PARSE_ACCESS | PARSE_HOST | PARSE_PATH | PARSE_PUNCTUATION | PARSE_ANCHOR);
|
|
if (full_address)
|
|
{
|
|
GTR_strncpy(me->href, full_address, MAX_URL_STRING);
|
|
GTR_FREE(full_address);
|
|
me->bHaveAnchor = TRUE;
|
|
}
|
|
}
|
|
}
|
|
me->bInAnchor = FALSE;
|
|
break;
|
|
}
|
|
}
|
|
|
|
|
|
/* Expanding entities
|
|
** ------------------
|
|
**
|
|
*/
|
|
PRIVATE void HTHotList_put_entity(HTStructured * me, int entity_number)
|
|
{
|
|
|
|
}
|
|
|
|
|
|
/* Free an HTML object
|
|
** -------------------
|
|
**
|
|
*/
|
|
PRIVATE void HTHotList_free(HTStructured * me)
|
|
{
|
|
if (me->bHaveAnchor)
|
|
{
|
|
if (me->title[0])
|
|
{
|
|
#ifdef FEATURE_KAZAN_HOTLIST
|
|
if (parentItemIndex == 0)
|
|
DlgHotTree_AddTreeItem(NULL, me->title, me->href,
|
|
(HTREEITEM) TVI_LAST, DlgHotTree_GetWebPageBitmapIndex(),
|
|
DlgHotTree_GetHotlistTreeViewWindow(), me->bVisible);
|
|
else
|
|
DlgHotTree_AddTreeItem(parentTreeItem[parentItemIndex - 1], me->title, me->href,
|
|
(HTREEITEM) TVI_LAST, DlgHotTree_GetWebPageBitmapIndex(),
|
|
DlgHotTree_GetHotlistTreeViewWindow(), me->bVisible);
|
|
#else
|
|
Hash_Add(me->hash_stack[me->hash_table_index],
|
|
me->href, me->title, NULL);
|
|
#endif
|
|
}
|
|
me->bHaveAnchor = FALSE;
|
|
}
|
|
|
|
GTR_FREE(me);
|
|
}
|
|
|
|
|
|
PRIVATE void HTHotList_abort(HTStructured * me, HTError e)
|
|
{
|
|
HTHotList_free(me);
|
|
}
|
|
|
|
|
|
/* Structured Object Class
|
|
** -----------------------
|
|
*/
|
|
PRIVATE CONST HTStructuredClass HTHotList = /* As opposed to print etc */
|
|
{
|
|
"HTMLToHotList",
|
|
HTHotList_free,
|
|
HTHotList_abort,
|
|
HTHotList_put_character, HTHotList_put_string, HTHotList_write,
|
|
HTHotList_start_element, HTHotList_end_element,
|
|
HTHotList_put_entity, NULL, NULL
|
|
};
|
|
|
|
|
|
/* HTConverter from HTML to TeX Stream
|
|
** ------------------------------------------
|
|
**
|
|
*/
|
|
PUBLIC HTStream *HTMLToHotList(struct Mwin *tw, HTRequest * request, void *param, HTFormat input_format, HTFormat output_format, HTStream * output_stream)
|
|
{
|
|
HTStructured *me = (HTStructured *) GTR_CALLOC(1, sizeof(*me));
|
|
if (me)
|
|
{
|
|
GTR_strncpy(me->base_url, request->destination->szActualURL, MAX_URL_STRING);
|
|
me->bInAnchor = FALSE;
|
|
me->bHaveAnchor = FALSE;
|
|
me->bInHeader = FALSE;
|
|
me->bHaveHeader = FALSE;
|
|
#ifdef FEATURE_KAZAN_HOTLIST
|
|
me->bVisible = FALSE;
|
|
#endif
|
|
me->hash_table_index = 0;
|
|
me->hash_stack[0] = &gHotList;
|
|
me->isa = (HTStructuredClass *) & HTHotList;
|
|
me->dtd = &HTMLP_dtd;
|
|
return SGML_new(tw, &HTMLP_dtd, me, request);
|
|
}
|
|
else
|
|
{
|
|
return NULL;
|
|
}
|
|
}
|
|
|
|
struct Params_HotList_Load {
|
|
HTRequest *request;
|
|
|
|
/* Used internally */
|
|
int status;
|
|
};
|
|
|
|
static int HotList_Load_Async(struct Mwin *tw, int nState, void **ppInfo)
|
|
{
|
|
struct Params_HotList_Load *pParams;
|
|
struct Params_LoadAsync *p2;
|
|
|
|
pParams = *ppInfo;
|
|
|
|
switch (nState)
|
|
{
|
|
case STATE_INIT:
|
|
p2 = GTR_MALLOC(sizeof(*p2));
|
|
p2->request = pParams->request;
|
|
p2->pStatus = &pParams->status;
|
|
bHotListLoading = TRUE;
|
|
Async_DoCall(HTLoadDocument_Async, p2);
|
|
return STATE_OTHER;
|
|
case STATE_OTHER:
|
|
case STATE_ABORT:
|
|
bHotListLoading = FALSE;
|
|
Dest_DestroyDest(pParams->request->destination);
|
|
HTRequest_delete(pParams->request);
|
|
return STATE_DONE;
|
|
}
|
|
XX_Assert((0), ("Function called with illegal state: %d", nState));
|
|
return STATE_DONE;
|
|
}
|
|
|
|
#ifdef FEATURE_KAZAN_HOTLIST
|
|
/****************************************************************************
|
|
*
|
|
* FUNCTION: HotList_IsLoading()
|
|
*
|
|
* PURPOSE: Returns the state of the asynchronous hotlist loading
|
|
* procedure. This is used to disable the hotlist menu
|
|
* item while the hotlist file is being read. The hotlist
|
|
* is written to the filesystem synchronously.
|
|
*
|
|
****************************************************************************/
|
|
BOOL HotList_IsLoading(void)
|
|
{
|
|
return bHotListLoading;
|
|
}
|
|
#endif /* FEATURE_KAZAN_HOTLIST */
|
|
|
|
void HotList_Init(void)
|
|
{
|
|
HTRequest *request;
|
|
char url[MAX_URL_STRING + 1];
|
|
struct Params_HotList_Load *phll;
|
|
struct DestInfo *pDest;
|
|
#ifdef FEATURE_KAZAN_HOTLIST
|
|
int idx;
|
|
#endif
|
|
|
|
#ifdef WIN32
|
|
char path[_MAX_PATH];
|
|
|
|
PREF_GetPathToHotlistFile(path);
|
|
FixPathName(path);
|
|
|
|
strcpy(url, "file:///");
|
|
strcat(url, path);
|
|
#endif
|
|
|
|
#ifdef FEATURE_KAZAN_HOTLIST
|
|
/* Initialize the array of level pointers. */
|
|
parentItemIndex = 0;
|
|
for (idx = 0; idx < MAX_HOTLIST_NESTING + 1; idx++)
|
|
{
|
|
parentTreeItem[idx] = NULL;
|
|
}
|
|
#endif
|
|
|
|
#ifdef MAC
|
|
#include "resequ.h"
|
|
Str255 filename;
|
|
|
|
strcpy(url, "file:///");
|
|
strcat(url, vv_Application);
|
|
GetIndString(filename, OEM_FILES_STR_LIST, OEM_HLISTNAME_STR);
|
|
p2cstr(filename);
|
|
strcat(url, " ");
|
|
strcat(url, filename);
|
|
|
|
PathNameFromDirID (MacGlobals.prefFldrDirID, MacGlobals.prefFldrVRefNum, url + 8);
|
|
FixPathName(url + 8);
|
|
#endif
|
|
|
|
#ifdef UNIX
|
|
char path[_MAX_PATH];
|
|
|
|
strcpy(url, "file://");
|
|
strcat(url, gPrefs.szHotListFile);
|
|
#endif
|
|
|
|
memset(&gHotListTable, 0, sizeof(hotlist_stack_table));
|
|
#ifndef FEATURE_KAZAN_HOTLIST
|
|
Hash_Init(&gHotList);
|
|
|
|
gHotListTable.hotlist_stack_index = 0;
|
|
gHotListTable.hotlist_stack[gHotListTable.hotlist_stack_index] = &gHotList;
|
|
gHotListTable.hotlist_menu_index = 0;
|
|
#endif
|
|
|
|
pDest = Dest_CreateDest(url);
|
|
if (pDest)
|
|
{
|
|
request = HTRequest_new();
|
|
HTFormatInit(request->conversions);
|
|
request->output_format = HTAtom_for("www/hotlist");
|
|
request->destination = pDest;
|
|
|
|
phll = GTR_MALLOC(sizeof(*phll));
|
|
phll->request = request;
|
|
Async_StartThread(HotList_Load_Async, phll, NULL);
|
|
}
|
|
}
|
|
|
|
#ifdef FEATURE_KAZAN_HOTLIST
|
|
static void WriteEnterSubMenu(FILE *fp, int level)
|
|
{
|
|
int j;
|
|
|
|
for (j = 0; j < level; j++) fprintf(fp, " ");
|
|
fprintf(fp, "<dl><br>\n");
|
|
}
|
|
|
|
static void WriteLeaveSubMenu(FILE *fp, int level)
|
|
{
|
|
int j;
|
|
|
|
for (j = 0; j < level; j++) fprintf(fp, " ");
|
|
fprintf(fp,"</dl><br>\n");
|
|
}
|
|
|
|
static void WriteItem(FILE *fp, char *title, char *url, int level, BOOL isFolder, BOOL emptyFolder, BOOL isVisible)
|
|
{
|
|
int j;
|
|
|
|
for (j = 0; j < level; j++) fprintf(fp, " ");
|
|
if (level > 0) fprintf(fp,"<dt>");
|
|
if (isFolder)
|
|
{
|
|
// If the child of the folder item is visible, then the folder
|
|
// state must be visible.
|
|
if (isVisible)
|
|
fprintf(fp, "<h3 VISIBLE=\"1\">%s</h3>\n", title);
|
|
else
|
|
fprintf(fp, "<h3>%s</h3>\n", title);
|
|
if (emptyFolder)
|
|
{
|
|
WriteEnterSubMenu(fp, level);
|
|
WriteLeaveSubMenu(fp, level);
|
|
}
|
|
}
|
|
else if (url != NULL)
|
|
{
|
|
if (isVisible)
|
|
fprintf(fp,"<a VISIBLE=\"1\" href=\"%s\">%s</a><br>\n", url, title);
|
|
else
|
|
fprintf(fp,"<a href=\"%s\">%s</a><br>\n", url, title);
|
|
}
|
|
else
|
|
{
|
|
if (isVisible)
|
|
fprintf(fp,"<a VISIBLE=\"1\" href=\"\">%s</a><br>\n", title);
|
|
else
|
|
fprintf(fp,"<a href=\"\">%s</a><br>\n", title);
|
|
}
|
|
}
|
|
|
|
static void DumpTreeItem(FILE *fp, HWND hWnd, HTREEITEM hItem, int level)
|
|
{
|
|
TV_ITEM tvi;
|
|
BOOL isFolder, emptyFolder;
|
|
char szBuffer[256];
|
|
|
|
memset(szBuffer, '\0', sizeof(szBuffer));
|
|
|
|
/*
|
|
** The "lParam" field contains a pointer to the memory allocated for the
|
|
** URL string. The memory pointed to by the "lParam" field does not get
|
|
** copied or modified.
|
|
*/
|
|
tvi.mask = TVIF_TEXT | TVIF_IMAGE | TVIF_SELECTEDIMAGE | TVIF_PARAM;
|
|
tvi.hItem = hItem;
|
|
tvi.pszText = szBuffer;
|
|
tvi.cchTextMax = sizeof(szBuffer);
|
|
TreeView_GetItem(hWnd, &tvi);
|
|
|
|
isFolder = (tvi.iImage != DlgHotTree_GetWebPageBitmapIndex());
|
|
emptyFolder = (TreeView_GetChild(hWnd, hItem) == NULL);
|
|
WriteItem(fp, tvi.pszText, (char *) tvi.lParam, level, isFolder, emptyFolder, DlgHotTree_IsItemVisible(hWnd, hItem));
|
|
}
|
|
|
|
static void HotList_DumpTreeContents(FILE *fp, HWND hWnd, HTREEITEM hRoot)
|
|
{
|
|
HTREEITEM hItem;
|
|
static int level = 0;
|
|
|
|
if (hRoot != NULL)
|
|
{
|
|
DumpTreeItem(fp, hWnd, hRoot, level);
|
|
hItem = TreeView_GetChild(hWnd, hRoot);
|
|
if (hItem != NULL)
|
|
{
|
|
WriteEnterSubMenu(fp, level);
|
|
level++;
|
|
HotList_DumpTreeContents(fp, hWnd, hItem);
|
|
level--;
|
|
WriteLeaveSubMenu(fp, level);
|
|
}
|
|
hItem = TreeView_GetNextSibling(hWnd, hRoot);
|
|
if (hItem != NULL)
|
|
{
|
|
HotList_DumpTreeContents(fp, hWnd, hItem);
|
|
}
|
|
}
|
|
}
|
|
#endif /* FEATURE_KAZAN_HOTLIST */
|
|
|
|
int HotList_Export(char *file)
|
|
{
|
|
#ifdef FEATURE_KAZAN_HOTLIST
|
|
HWND hWnd;
|
|
FILE *fp;
|
|
|
|
fp = fopen(file, "w");
|
|
if (!fp)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
fprintf(fp, GTR_GetString(SID_INF_HOTLIST));
|
|
fprintf(fp, GTR_GetString(SID_INF_HOTLIST_PAGE));
|
|
|
|
hWnd = DlgHotTree_GetHotlistTreeViewWindow();
|
|
/* Do not write out the root of the tree, start at the root's child. */
|
|
if (hWnd) HotList_DumpTreeContents(fp, hWnd, TreeView_GetChild(hWnd, TreeView_GetRoot(hWnd)));
|
|
|
|
fclose(fp);
|
|
return 0;
|
|
#else
|
|
int count;
|
|
char *s1;
|
|
char *s2;
|
|
FILE *fp;
|
|
int i;
|
|
int hash_last[MAX_HOTLIST_NESTING + 1];
|
|
int j, hash_index, last;
|
|
struct hash_table *hash_stack[MAX_HOTLIST_NESTING + 1];
|
|
struct hash_table *new_hash;
|
|
BOOL bNested;
|
|
|
|
fp = fopen(file, "w");
|
|
if (!fp)
|
|
{
|
|
return -1;
|
|
}
|
|
|
|
fprintf(fp, GTR_GetString(SID_INF_HOTLIST));
|
|
fprintf(fp, GTR_GetString(SID_INF_HOTLIST_PAGE));
|
|
|
|
hash_stack[0] = &gHotList;
|
|
hash_last[0] = 0;
|
|
hash_index = 1;
|
|
|
|
while (hash_index > 0)
|
|
{
|
|
count = Hash_Count(hash_stack[hash_index-1]);
|
|
last = hash_last[hash_index-1];
|
|
bNested = FALSE;
|
|
for (i = last; i < count && !bNested; i++)
|
|
{
|
|
new_hash = 0;
|
|
Hash_GetIndexedEntry(hash_stack[hash_index-1], i,
|
|
&s1, &s2, (void **) &new_hash);
|
|
if (!new_hash)
|
|
{
|
|
for (j = 1; j < hash_index; j++) fprintf(fp, " ");
|
|
if (hash_index > 1)
|
|
fprintf(fp,"<dt>");
|
|
fprintf(fp,"<a href=\"%s\">%s</a><br>\n", s1, s2);
|
|
}
|
|
else
|
|
{
|
|
/* Check for a back link */
|
|
if (strcmp(HOTLIST_SUBMENU_LINK_TEXT,s1) != 0)
|
|
{
|
|
for (j = 1; j < hash_index; j++) fprintf(fp, " ");
|
|
if (hash_index > 1)
|
|
fprintf(fp, "<dt>");
|
|
fprintf(fp, "<h3>%s</h3>\n", s1);
|
|
for (j = 1; j < hash_index; j++) fprintf(fp, " ");
|
|
fprintf(fp, "<dl><br>\n");
|
|
hash_last[hash_index-1] = ++i;
|
|
hash_stack[hash_index] = new_hash;
|
|
hash_last[hash_index] = 0;
|
|
hash_index++;
|
|
bNested = TRUE;
|
|
}
|
|
}
|
|
}
|
|
if (!bNested)
|
|
{
|
|
--hash_index;
|
|
if (hash_index > 0)
|
|
{
|
|
for (j = 1; j < hash_index; j++) fprintf(fp, " ");
|
|
fprintf(fp,"</dl><br>\n");
|
|
}
|
|
}
|
|
}
|
|
|
|
fclose(fp);
|
|
return 0;
|
|
#endif
|
|
}
|
|
|
|
int HotList_SaveToDisk(void)
|
|
{
|
|
char path[_MAX_PATH];
|
|
int status;
|
|
#ifdef MAC
|
|
strcpy (path, vv_Application);
|
|
strcat (path, " Hotlist.html");
|
|
PathNameFromDirID (MacGlobals.prefFldrDirID, MacGlobals.prefFldrVRefNum, path);
|
|
#endif
|
|
#ifdef WIN32
|
|
PREF_GetPathToHotlistFile(path);
|
|
#endif
|
|
#ifdef UNIX
|
|
strcpy(path, gPrefs.szHotListFile);
|
|
#endif
|
|
|
|
/** Do not save if we have not finished loading the file from disk **/
|
|
if (bHotListLoading)
|
|
return(0);
|
|
|
|
status = HotList_Export(path);
|
|
#ifdef MAC
|
|
if (!status)
|
|
{
|
|
short tempWD;
|
|
|
|
(void) makevwd (MacGlobals.prefFldrVRefNum, MacGlobals.prefFldrDirID, &tempWD); /* make a WD for it */
|
|
MakeGuitarFile (tempWD, path);
|
|
}
|
|
#endif
|
|
return status;
|
|
}
|
|
|
|
/** Pass a null to destroy the global hotlist from the top **/
|
|
/** Otherwise pass the hash_table *, and the hash_table will **/
|
|
/** be free'd along with any children tables . **/
|
|
void HotList_Destroy(struct hash_table *top)
|
|
{
|
|
#ifdef FEATURE_KAZAN_HOTLIST
|
|
/*
|
|
** The Tree View and associated memory are destroyed when
|
|
** the hotlist dialog is destroyed. This happens when the
|
|
** program terminates.
|
|
*/
|
|
#else
|
|
int hash_last[MAX_HOTLIST_NESTING + 1];
|
|
int i, count, hash_index, last;
|
|
char *s1;
|
|
char *s2;
|
|
struct hash_table *hash_stack[MAX_HOTLIST_NESTING + 1];
|
|
struct hash_table *new_hash;
|
|
BOOL bNested;
|
|
|
|
hash_stack[0] = top;
|
|
if (!hash_stack[0])
|
|
hash_stack[0] = &gHotList;
|
|
hash_last[0] = 0;
|
|
hash_index = 1;
|
|
|
|
while (hash_index > 0)
|
|
{
|
|
count = Hash_Count(hash_stack[hash_index-1]);
|
|
last = hash_last[hash_index-1];
|
|
bNested = FALSE;
|
|
for (i = last; i < count && !bNested; i++)
|
|
{
|
|
new_hash = 0;
|
|
Hash_GetIndexedEntry(hash_stack[hash_index-1], i,
|
|
&s1, &s2, (void **) &new_hash);
|
|
if (new_hash)
|
|
{
|
|
/* Check for a back link */
|
|
if (strcmp(HOTLIST_SUBMENU_LINK_TEXT,s1) != 0)
|
|
{
|
|
hash_last[hash_index-1] = ++i;
|
|
hash_stack[hash_index] = new_hash;
|
|
hash_last[hash_index] = 0;
|
|
hash_index++;
|
|
bNested = TRUE;
|
|
}
|
|
}
|
|
}
|
|
if (!bNested)
|
|
{
|
|
Hash_FreeContents(hash_stack[--hash_index]);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void HotList_DeleteIndexedItem(int ndx)
|
|
{
|
|
#ifdef FEATURE_KAZAN_HOTLIST
|
|
/*
|
|
** This is called when deleting items from the listbox
|
|
** when not using hierarchical hotlists. This will
|
|
** never be called when using hierarchical hotlists.
|
|
*/
|
|
#else
|
|
struct hash_table *new_cache;
|
|
char *s1;
|
|
|
|
/** Now delete the item that is in the current hash level **/
|
|
/** First check to see if it is a menu link **/
|
|
if (Hash_GetIndexedEntry(HotList_getcache(), ndx, &s1, NULL,
|
|
(void **)&new_cache) >= 0)
|
|
{
|
|
if (new_cache && strcmp(HOTLIST_SUBMENU_LINK_TEXT, s1) != 0)
|
|
{
|
|
HotList_Destroy(new_cache);
|
|
}
|
|
Hash_DeleteIndexedEntry(HotList_getcache(), ndx);
|
|
}
|
|
HotList_SaveToDisk();
|
|
#endif
|
|
}
|
|
|
|
BOOL HotList_Add(char *title, char *url)
|
|
{
|
|
char *pTitle, bPrintable;
|
|
int i = 1;
|
|
|
|
if ( title && *title )
|
|
{
|
|
/* Insure there are printable characters in the <TITLE> field */
|
|
/* If none, put URL into hotlist instead of <TITLE> */
|
|
bPrintable = FALSE;
|
|
while ( title[i] && !bPrintable )
|
|
{
|
|
bPrintable = ((title[0] != ' ') &&
|
|
(title[0] != '\n') &&
|
|
(title[0] != '\t') &&
|
|
(title[0] != '\r'));
|
|
i++;
|
|
}
|
|
if (bPrintable)
|
|
{
|
|
pTitle = title;
|
|
}
|
|
else
|
|
{
|
|
pTitle = url;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
pTitle = url;
|
|
}
|
|
#ifdef FEATURE_KAZAN_HOTLIST
|
|
{
|
|
/* Insert the new item at the root level. */
|
|
HWND hWndTreeView = DlgHotTree_GetHotlistTreeViewWindow();
|
|
DlgHotTree_AddTreeItem(TreeView_GetRoot(hWndTreeView), pTitle, url,
|
|
(HTREEITEM) TVI_LAST, DlgHotTree_GetWebPageBitmapIndex(),
|
|
hWndTreeView, TRUE);
|
|
return TRUE;
|
|
}
|
|
#else
|
|
/** Now add the item in the current hash level **/
|
|
if (Hash_Add(HotList_getcache(), url, pTitle, NULL) != -1)
|
|
{
|
|
HotList_SaveToDisk();
|
|
|
|
#if defined(WIN32) || defined(MAC)
|
|
HotList_updatedisplay(HOTLIST_ADD_ITEM_TO_LIST);
|
|
#endif
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
#endif /* FEATURE_KAZAN_HOTLIST */
|
|
}
|
|
|
|
#ifndef FEATURE_KAZAN_HOTLIST
|
|
struct hash_table *
|
|
HotList_getcache(void)
|
|
{
|
|
return(gHotListTable.hotlist_stack[gHotListTable.hotlist_stack_index]);
|
|
}
|
|
|
|
void
|
|
HotList_pushcache(struct hash_table *new_cache)
|
|
{
|
|
if (gHotListTable.hotlist_stack_index < MAX_HOTLIST_NESTING)
|
|
{
|
|
gHotListTable.hotlist_stack[++gHotListTable.hotlist_stack_index] = new_cache;
|
|
}
|
|
}
|
|
|
|
void
|
|
HotList_popcache(void)
|
|
{
|
|
if (gHotListTable.hotlist_stack_index > 0)
|
|
{
|
|
gHotListTable.hotlist_stack_index--;
|
|
}
|
|
}
|
|
#endif
|
|
/*
|
|
* Flag should be one of the defines in history.h
|
|
* HOTLIST_INITIALIZE_LIST
|
|
* HOTLIST_ADD_ITEM_TO_LIST
|
|
* HOTLIST_DELETE_ITEM_FROM_LIST
|
|
*/
|
|
void
|
|
HotList_updatedisplay(int flag)
|
|
{
|
|
#ifdef WIN32
|
|
#ifndef FEATURE_KAZAN_HOTLIST
|
|
if (DlgHOT_IsHotlistRunning())
|
|
DlgHOT_RefreshHotlist();
|
|
#endif
|
|
#endif
|
|
|
|
#ifdef MAC
|
|
DlgHOT_RefreshHotlist ();
|
|
#endif
|
|
|
|
#ifdef UNIX
|
|
init_hotlist(-1, flag);
|
|
#endif
|
|
}
|
|
|