2136 lines
62 KiB
C
2136 lines
62 KiB
C
/****************************************************************************
|
|
* NCSA Mosaic for the X Window System *
|
|
* Software Development Group *
|
|
* National Center for Supercomputing Applications *
|
|
* University of Illinois at Urbana-Champaign *
|
|
* 605 E. Springfield, Champaign IL 61820 *
|
|
* mosaic@ncsa.uiuc.edu *
|
|
* *
|
|
* Copyright (C) 1993, Board of Trustees of the University of Illinois *
|
|
* *
|
|
* NCSA Mosaic software, both binary and source (hereafter, Software) is *
|
|
* copyrighted by The Board of Trustees of the University of Illinois *
|
|
* (UI), and ownership remains with the UI. *
|
|
* *
|
|
* The UI grants you (hereafter, Licensee) a license to use the Software *
|
|
* for academic, research and internal business purposes only, without a *
|
|
* fee. Licensee may distribute the binary and source code (if released) *
|
|
* to third parties provided that the copyright notice and this statement *
|
|
* appears on all copies and that no charge is associated with such *
|
|
* copies. *
|
|
* *
|
|
* Licensee may make derivative works. However, if Licensee distributes *
|
|
* any derivative work based on or derived from the Software, then *
|
|
* Licensee will (1) notify NCSA regarding its distribution of the *
|
|
* derivative work, and (2) clearly notify users that such derivative *
|
|
* work is a modified version and not the original NCSA Mosaic *
|
|
* distributed by the UI. *
|
|
* *
|
|
* Any Licensee wishing to make commercial use of the Software should *
|
|
* contact the UI, c/o NCSA, to negotiate an appropriate license for such *
|
|
* commercial use. Commercial use includes (1) integration of all or *
|
|
* part of the source code into a product for sale or license by or on *
|
|
* behalf of Licensee to third parties, or (2) distribution of the binary *
|
|
* code or source code to third parties that need it to utilize a *
|
|
* commercial product sold or licensed by or on behalf of Licensee. *
|
|
* *
|
|
* UI MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR *
|
|
* ANY PURPOSE. IT IS PROVIDED "AS IS" WITHOUT EXPRESS OR IMPLIED *
|
|
* WARRANTY. THE UI SHALL NOT BE LIABLE FOR ANY DAMAGES SUFFERED BY THE *
|
|
* USERS OF THIS SOFTWARE. *
|
|
* *
|
|
* By using or copying this Software, Licensee agrees to abide by the *
|
|
* copyright law and all other applicable laws of the U.S. including, but *
|
|
* not limited to, export control laws, and the terms of this license. *
|
|
* UI shall have the right to terminate this license immediately by *
|
|
* written notice upon Licensee's breach of, or non-compliance with, any *
|
|
* of its terms. Licensee may be held legally responsible for any *
|
|
* copyright infringement that is caused or encouraged by Licensee's *
|
|
* failure to abide by the terms of this license. *
|
|
* *
|
|
* Comments and questions are welcome and can be sent to *
|
|
* mosaic-x@ncsa.uiuc.edu. *
|
|
****************************************************************************/
|
|
#include "../config.h"
|
|
#include "mosaic.h"
|
|
#include "hotlist.h"
|
|
#include "hotfile.h"
|
|
#include "gui.h"
|
|
#include "mo-www.h"
|
|
#include <time.h>
|
|
#include <Xm/List.h>
|
|
#include <Xm/TextF.h>
|
|
#include <Xm/ToggleBG.h>
|
|
#include <sys/types.h>
|
|
#include <libutils/flatpakCheck.h>
|
|
|
|
#include "bitmaps/hotlist.xbm"
|
|
#include "../libnut/system.h"
|
|
|
|
#ifndef DISABLE_TRACE
|
|
extern int srcTrace;
|
|
#endif
|
|
|
|
extern mo_window *current_win;
|
|
|
|
void mo_reinit_hotmenu();
|
|
|
|
|
|
/* This file provides support for hotlists of interesting
|
|
documents within the browser.
|
|
|
|
Initially there will be a single hotlist, 'Default'.
|
|
|
|
The old hotlist file format look like this:
|
|
|
|
ncsa-mosaic-hotlist-format-1 [identifying string]
|
|
Default [title]
|
|
url Fri Sep 13 00:00:00 1986 [first word is url;
|
|
subsequent words are
|
|
last-accessed date (GMT)]
|
|
document title cached here [cached title for above]
|
|
[2-line sequence for single document repeated as necessary]
|
|
...
|
|
|
|
Turns out this format is bad for two reasons:
|
|
(1) Document titles can have embedded carriage returns (usually
|
|
on purpose).
|
|
(2) URL's can have embedded carriage returns (usually on accident).
|
|
|
|
Also, we should just be using an HTML-derived format for hotlists.
|
|
*/
|
|
|
|
#define LISTINDIC "-> "
|
|
|
|
#define FindHotFromPos(hotnode, list, posi) \
|
|
do for (hotnode = list->nodelist; hotnode != NULL; \
|
|
hotnode = hotnode->any.next) \
|
|
{ \
|
|
if (hotnode->any.position == posi) \
|
|
break; \
|
|
} while(0)
|
|
|
|
typedef struct edit_or_insert_hot_info
|
|
{
|
|
Widget title_text;
|
|
int pos;
|
|
Widget url_lab;
|
|
Widget url_text;
|
|
Widget tog_url;
|
|
Widget tog_list;
|
|
Widget insert_tog;
|
|
} edit_or_insert_hot_info;
|
|
|
|
|
|
void URL_Include_Set(mo_window *win, int togval, int sensitive) {
|
|
|
|
if (!win) {
|
|
win=current_win;
|
|
if (!win) {
|
|
return;
|
|
}
|
|
}
|
|
|
|
XmxSetToggleButton(win->hotlist_rbm_toggle,
|
|
togval);
|
|
XtVaSetValues(win->hotlist_rbm_toggle,
|
|
XmNsensitive, sensitive,
|
|
NULL);
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
mo_root_hotlist *default_hotlist = NULL;
|
|
|
|
/*
|
|
* Given a hotlist and a hotnode, append the node
|
|
* to the hotlist.
|
|
* Change fields nodelist and nodelist_last in the hotlist,
|
|
* and fields next and previous in the hotnode.
|
|
* Also fill in field position in the hotnode.
|
|
* Return nothing.
|
|
*/
|
|
void mo_append_item_to_hotlist (mo_hotlist *list,
|
|
mo_hot_item *node)
|
|
{
|
|
if (node->type == mo_t_list)
|
|
node->list.parent = list;
|
|
if (list->nodelist == 0)
|
|
{
|
|
/* Nothing yet. */
|
|
list->nodelist = node;
|
|
list->nodelist_last = node;
|
|
node->any.next = 0;
|
|
node->any.previous = 0;
|
|
node->any.position = 1;
|
|
}
|
|
else
|
|
{
|
|
/* The new node becomes nodelist_last. */
|
|
/* But first, set up node. */
|
|
node->any.previous = list->nodelist_last;
|
|
node->any.next = 0;
|
|
node->any.position = node->any.previous->any.position + 1;
|
|
|
|
/* Now point forward from previous nodelist_last. */
|
|
list->nodelist_last->any.next = node;
|
|
|
|
/* Now set up new nodelist_last. */
|
|
list->nodelist_last = node;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/* Given a hotlist and a hotnode, rip the hotnode out of the hotlist.
|
|
No check is made as to whether the hotnode is actually in the hotlist;
|
|
it better be. */
|
|
static void mo_remove_hotnode_from_hotlist (mo_hotlist *list,
|
|
mo_hot_item *hotnode)
|
|
{
|
|
if (hotnode->any.previous == NULL)
|
|
{
|
|
/* Node was the first member of the list. */
|
|
if (hotnode->any.next != NULL)
|
|
{
|
|
/* Node was the first member of the list and had
|
|
a next node. */
|
|
/* The next node is now the first node in the list. */
|
|
hotnode->any.next->any.previous = NULL;
|
|
list->nodelist = hotnode->any.next;
|
|
}
|
|
else
|
|
{
|
|
/* Node was the first member of the list and
|
|
didn't have a next node. */
|
|
/* The list is now empty. */
|
|
list->nodelist = NULL;
|
|
list->nodelist_last = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
/* Node had a previous. */
|
|
if (hotnode->any.next != NULL)
|
|
{
|
|
/* Node had a previous and a next. */
|
|
hotnode->any.previous->any.next = hotnode->any.next;
|
|
hotnode->any.next->any.previous = hotnode->any.previous;
|
|
}
|
|
else
|
|
{
|
|
/* Node had a previous but no next. */
|
|
hotnode->any.previous->any.next = NULL;
|
|
list->nodelist_last = hotnode->any.previous;
|
|
}
|
|
}
|
|
|
|
if (hotnode->type == mo_t_list)
|
|
{
|
|
mo_hot_item *item, *prev;
|
|
for (item = hotnode->list.nodelist; item; free(prev))
|
|
{
|
|
mo_remove_hotnode_from_hotlist (&(hotnode->list), item);
|
|
prev = item; item = hotnode->list.nodelist;
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/* Go through a hotlist (sequence of hotnodes) and assign position
|
|
numbers for all of 'em. */
|
|
static void mo_recalculate_hotlist_positions (mo_hotlist *list)
|
|
{
|
|
mo_hot_item *hotnode;
|
|
int count = 1;
|
|
|
|
for (hotnode = list->nodelist; hotnode != NULL;
|
|
hotnode = hotnode->any.next)
|
|
hotnode->any.position = count++;
|
|
|
|
return;
|
|
}
|
|
|
|
/* Insert an item in a list at a given position.
|
|
if position is 0, then append it (at end of list). */
|
|
static void mo_insert_item_in_hotlist (mo_hotlist *list, mo_hot_item *node,
|
|
int position)
|
|
{
|
|
if (!position)
|
|
{
|
|
mo_append_item_to_hotlist (list, node);
|
|
}
|
|
else
|
|
{
|
|
if (node->type == mo_t_list)
|
|
node->list.parent = list;
|
|
if (list->nodelist == 0)
|
|
{
|
|
/* Nothing yet. */
|
|
list->nodelist = node;
|
|
list->nodelist_last = node;
|
|
node->any.next = 0;
|
|
node->any.previous = 0;
|
|
node->any.position = 1;
|
|
}
|
|
else
|
|
{
|
|
mo_hot_item *item, **prevNextPtr = &list->nodelist;
|
|
/* search the item at position 'position' */
|
|
for (item = list->nodelist; item != NULL;
|
|
item = item->any.next)
|
|
{
|
|
if (item->any.position == position)
|
|
break;
|
|
prevNextPtr = &item->any.next;
|
|
}
|
|
|
|
if (item == NULL) /* item not found */
|
|
mo_append_item_to_hotlist (list, node);
|
|
else
|
|
{
|
|
*prevNextPtr = node;
|
|
node->any.previous = item->any.previous;
|
|
node->any.next = item;
|
|
item->any.previous = node;
|
|
mo_recalculate_hotlist_positions (list);
|
|
}
|
|
}
|
|
}
|
|
mo_reinit_hotmenu();
|
|
}
|
|
|
|
/* Go Up The tree to check if a list is the ancestor of an item
|
|
*/
|
|
static int mo_is_ancestor (mo_hotlist *list, mo_hotlist *item)
|
|
{
|
|
while (item && item != list)
|
|
item = item->parent;
|
|
|
|
return item == list;
|
|
}
|
|
|
|
/* recursive function that copy a hierarchy of hotlist */
|
|
static mo_hotlist *mo_copy_hot_hier (mo_hotlist *list)
|
|
{
|
|
mo_hot_item *item;
|
|
mo_hotnode *hot;
|
|
mo_hotlist *hotlist = (mo_hotlist *)malloc(sizeof(mo_hotlist));
|
|
|
|
hotlist->name = strdup(list->name);
|
|
hotlist->type = mo_t_list;
|
|
hotlist->nodelist = hotlist->nodelist_last = 0;
|
|
for (item = list->nodelist; item; item = item->any.next)
|
|
if (item->type == mo_t_url)
|
|
{
|
|
hot = (mo_hotnode *)malloc(sizeof(mo_hotnode));
|
|
hot->type = mo_t_url;
|
|
hot->title = strdup(item->hot.title);
|
|
hot->url = strdup(item->hot.url);
|
|
/*hot->lastdate = strdup(item->hot.lastdate);*/
|
|
hot->lastdate = (char *) 0;
|
|
mo_append_item_to_hotlist(hotlist, (mo_hot_item *)hot);
|
|
}
|
|
else
|
|
{
|
|
mo_append_item_to_hotlist
|
|
(hotlist, (mo_hot_item *)mo_copy_hot_hier((mo_hotlist *)item));
|
|
}
|
|
return hotlist;
|
|
}
|
|
|
|
static char * mo_compute_hot_path (mo_hotlist *curr)
|
|
{
|
|
char *str;
|
|
char *prev = curr->parent ? strdup(curr->name) : strdup("/");
|
|
|
|
for (str = prev, curr = curr->parent; curr; curr = curr->parent)
|
|
{
|
|
if (curr->parent)
|
|
{
|
|
str = (char *)malloc(strlen(prev)+strlen(curr->name)+2);
|
|
strcat(strcat(strcpy(str, curr->name), "/"),prev);
|
|
}
|
|
else
|
|
{
|
|
str = (char *)malloc(strlen(prev)+2);
|
|
strcat(strcpy(str, "/"), prev);
|
|
}
|
|
free(prev);
|
|
prev = str;
|
|
}
|
|
return str;
|
|
}
|
|
|
|
static void mo_copy_hotlist_position (mo_window *win, int position)
|
|
{
|
|
mo_hot_item *item;
|
|
|
|
for (item = win->current_hotlist->nodelist;
|
|
item != NULL && item->any.position != position;
|
|
item = item->any.next) ;
|
|
|
|
if (item)
|
|
win->hot_cut_buffer = item;
|
|
}
|
|
|
|
static char * mo_highlight_hotlist (mo_hotlist *list)
|
|
{
|
|
char *str = (char *)malloc(strlen(list->name)+strlen(LISTINDIC)+1);
|
|
return
|
|
strcat(strcpy(str,LISTINDIC), list->name);
|
|
}
|
|
|
|
static void mo_gui_add_hot_item (mo_hotlist *list, mo_hot_item *item)
|
|
{
|
|
mo_window *win = NULL;
|
|
/* Now we've got to update all active hotlist_list's. */
|
|
while (win = mo_next_window (win))
|
|
if (win->hotlist_list && win->current_hotlist == list)
|
|
{
|
|
char *highlight = NULL;
|
|
XmString xmstr =
|
|
XmxMakeXmstrFromString
|
|
(item->type == mo_t_url ?
|
|
(get_pref_boolean(eDISPLAY_URLS_NOT_TITLES)?item->hot.url:item->hot.title) :
|
|
(highlight = mo_highlight_hotlist(&item->list)));
|
|
if (item->type == mo_t_list && highlight)
|
|
free(highlight);
|
|
XmListAddItemUnselected
|
|
(win->hotlist_list,
|
|
xmstr,
|
|
item->any.position);
|
|
XmStringFree (xmstr);
|
|
XmListSetBottomPos (win->hotlist_list, 0);
|
|
}
|
|
|
|
mo_reinit_hotmenu();
|
|
}
|
|
|
|
mo_status mo_add_item_to_hotlist (mo_hotlist *list, mo_item_type type,
|
|
char *title, char *url, int position,
|
|
int rbm)
|
|
{
|
|
mo_hot_item *item;
|
|
mo_window *win = NULL;
|
|
|
|
if ((title == NULL || title[0] == '\0') && (url == NULL || url[0] == '\0'))
|
|
return mo_fail;
|
|
|
|
if (type == mo_t_url)
|
|
{
|
|
mo_hotnode *hotnode = (mo_hotnode *)malloc (sizeof (mo_hotnode));
|
|
time_t foo = time (NULL);
|
|
char *ts = ctime (&foo);
|
|
|
|
item = (mo_hot_item *)hotnode;
|
|
ts[strlen(ts)-1] = '\0';
|
|
|
|
hotnode->type = mo_t_url;
|
|
if (title)
|
|
hotnode->title = strdup (title);
|
|
else
|
|
hotnode->title = strdup ("Unnamed");
|
|
mo_convert_newlines_to_spaces (hotnode->title);
|
|
|
|
hotnode->url = strdup (url);
|
|
mo_convert_newlines_to_spaces (hotnode->url);
|
|
|
|
hotnode->lastdate = strdup (ts);
|
|
|
|
hotnode->rbm=rbm;
|
|
}
|
|
else
|
|
{
|
|
mo_hotlist *hotlist = (mo_hotlist *)malloc(sizeof(mo_hotlist));
|
|
|
|
item = (mo_hot_item *)hotlist;
|
|
hotlist->type = mo_t_list;
|
|
if (title)
|
|
hotlist->name = strdup (title);
|
|
else
|
|
hotlist->name = strdup ("Unnamed");
|
|
mo_convert_newlines_to_spaces (hotlist->name);
|
|
hotlist->nodelist = hotlist->nodelist_last = 0;
|
|
hotlist->rbm=rbm;
|
|
}
|
|
|
|
if (position)
|
|
mo_insert_item_in_hotlist(list, item, position);
|
|
else
|
|
mo_append_item_to_hotlist (list, item);
|
|
|
|
mo_gui_add_hot_item (list, item);
|
|
|
|
return mo_succeed;
|
|
}
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/* ------------------------- gui support routines ------------------------- */
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
/* We've just init'd a new hotlist list widget; look at the default
|
|
hotlist and load 'er up. */
|
|
static void mo_load_hotlist_list (mo_window *win, Widget list)
|
|
{
|
|
mo_hot_item *node;
|
|
|
|
if (win->edithot_win && XtIsManaged(win->edithot_win))
|
|
XtUnmanageChild (win->edithot_win);
|
|
for (node = win->current_hotlist->nodelist; node != NULL;
|
|
node = node->any.next)
|
|
{
|
|
char *highlight = NULL;
|
|
XmString xmstr =
|
|
XmxMakeXmstrFromString
|
|
(node->type == mo_t_url ?
|
|
(get_pref_boolean(eDISPLAY_URLS_NOT_TITLES) ? node->hot.url : node->hot.title) :
|
|
(highlight = mo_highlight_hotlist(&node->list)));
|
|
if (node->type == mo_t_list && highlight)
|
|
free(highlight);
|
|
XmListAddItemUnselected
|
|
(list, xmstr, 0);
|
|
XmStringFree (xmstr);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static void mo_visit_hotlist_position (mo_window *win, int position)
|
|
{
|
|
mo_hot_item *hotnode;
|
|
|
|
for (hotnode = win->current_hotlist->nodelist; hotnode != NULL;
|
|
hotnode = hotnode->any.next)
|
|
{
|
|
if (hotnode->any.position == position)
|
|
if (hotnode->type == mo_t_url)
|
|
mo_access_document (win, hotnode->hot.url);
|
|
else
|
|
{
|
|
char *path = mo_compute_hot_path(&(hotnode->list));
|
|
|
|
win->current_hotlist = &(hotnode->list);
|
|
XmListDeleteAllItems(win->hotlist_list);
|
|
XmxTextSetString(win->hotlist_label, path);
|
|
free(path);
|
|
mo_load_hotlist_list(win, win->hotlist_list);
|
|
URL_Include_Set(win,0,0);
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
/* ------------------------------------------------------------------------ */
|
|
/* ----------- This part deals with the Edit and Insert features ---------- */
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
/* ----------------------- edit_or_insert_hot_cb -------------------------- */
|
|
|
|
static XmxCallback (edit_or_insert_hot_cb)
|
|
{
|
|
mo_window *win = mo_fetch_window_by_id
|
|
(XmxExtractUniqid ((int)client_data));
|
|
char *title;
|
|
edit_or_insert_hot_info *eht_info;
|
|
|
|
|
|
switch (XmxExtractToken ((int)client_data))
|
|
{
|
|
case 0: /* Commit Edit */
|
|
URL_Include_Set(win,0,0);
|
|
XmxSetArg (XmNuserData, (XtArgVal)&eht_info);
|
|
XtGetValues (win->edithot_win, Xmx_wargs, Xmx_n);
|
|
Xmx_n = 0;
|
|
XtUnmanageChild (win->edithot_win);
|
|
title = XmxTextGetString (eht_info->title_text);
|
|
|
|
{
|
|
/* OK, now position is still cached in win->edithot_pos. */
|
|
mo_hotlist *list = win->current_hotlist;
|
|
mo_hot_item *hotnode;
|
|
mo_window *w = NULL;
|
|
|
|
FindHotFromPos(hotnode, list, eht_info->pos);
|
|
|
|
if (hotnode == NULL)
|
|
goto punt;
|
|
|
|
/* OK, now we have the hotnode. */
|
|
|
|
if (hotnode->type == mo_t_url)
|
|
hotnode->hot.url = XmxTextGetString(eht_info->url_text);
|
|
else if (!strcmp(hotnode->any.name, title))
|
|
goto punt;
|
|
|
|
hotnode->any.name = title;
|
|
|
|
/* Save the hotlist before we screw something up. */
|
|
mo_write_default_hotlist ();
|
|
|
|
/* Change the extant hotlists. */
|
|
while (w = mo_next_window (w))
|
|
{
|
|
if (w->hotlist_list && w->current_hotlist == win->current_hotlist)
|
|
{
|
|
char *highlight = NULL;
|
|
XmString xmstr =
|
|
XmxMakeXmstrFromString
|
|
(hotnode->type == mo_t_url ?
|
|
(get_pref_boolean(eDISPLAY_URLS_NOT_TITLES)?hotnode->hot.url:title) :
|
|
(highlight = mo_highlight_hotlist(&hotnode->list)));
|
|
if (hotnode->type == mo_t_list && highlight)
|
|
free(highlight);
|
|
XmListDeletePos
|
|
(w->hotlist_list,
|
|
hotnode->any.position);
|
|
#ifndef DISABLE_TRACE
|
|
if (srcTrace) {
|
|
fprintf (stderr,
|
|
"w->hotlist_list 0x%08x, xmstr 0x%08x, hotnode->position %d\n",
|
|
w->hotlist_list,
|
|
xmstr,
|
|
hotnode->any.position);
|
|
}
|
|
#endif
|
|
/* There is what appears to be a Motif UMR here... */
|
|
XmListAddItemUnselected
|
|
(w->hotlist_list,
|
|
xmstr,
|
|
hotnode->any.position);
|
|
XmStringFree (xmstr);
|
|
}
|
|
if (w->hotlist_list && hotnode->type == mo_t_list &&
|
|
mo_is_ancestor((mo_hotlist *)hotnode, w->current_hotlist))
|
|
{
|
|
char *path = mo_compute_hot_path (w->current_hotlist);
|
|
XmxTextSetString(w->hotlist_label, path);
|
|
free(path);
|
|
}
|
|
}
|
|
|
|
/* That's it! */
|
|
}
|
|
punt:
|
|
break;
|
|
|
|
case 3: /* Commit Insert */
|
|
URL_Include_Set(win,0,0);
|
|
XmxSetArg (XmNuserData, (XtArgVal)&eht_info);
|
|
XtGetValues (win->inserthot_win, Xmx_wargs, Xmx_n);
|
|
Xmx_n = 0;
|
|
XtUnmanageChild (win->inserthot_win);
|
|
title = XmxTextGetString (eht_info->title_text);
|
|
{
|
|
Boolean isUrl = XmToggleButtonGadgetGetState(eht_info->tog_url);
|
|
Boolean useIns = XmToggleButtonGadgetGetState(eht_info->insert_tog);
|
|
int *pos_list;
|
|
int pos_cnt, posi = 0;
|
|
mo_status addOk = mo_succeed;
|
|
|
|
if (useIns)
|
|
if (XmListGetSelectedPos (win->hotlist_list, &pos_list, &pos_cnt) &&
|
|
pos_cnt)
|
|
{
|
|
posi = pos_list[0]; XtFree((char *)pos_list); /* DXP */
|
|
}
|
|
|
|
if (isUrl)
|
|
addOk = mo_add_item_to_hotlist
|
|
(win->current_hotlist, mo_t_url, title,
|
|
XmxTextGetString(eht_info->url_text), posi,
|
|
get_pref_boolean(eADD_HOTLIST_ADDS_RBM));
|
|
else
|
|
{
|
|
if (win->hot_cut_buffer &&
|
|
win->hot_cut_buffer->type == mo_t_list &&
|
|
(!strcmp(title, win->hot_cut_buffer->any.name)) &&
|
|
(!mo_is_ancestor((mo_hotlist *)win->hot_cut_buffer,
|
|
win->current_hotlist)))
|
|
{
|
|
mo_insert_item_in_hotlist
|
|
(win->current_hotlist,
|
|
(mo_hot_item *)mo_copy_hot_hier
|
|
((mo_hotlist *)win->hot_cut_buffer), posi);
|
|
/* Now we've got to update all active hotlist_list's. */
|
|
mo_gui_add_hot_item
|
|
(win->current_hotlist, win->current_hotlist->nodelist_last);
|
|
}
|
|
else
|
|
addOk = mo_add_item_to_hotlist(win->current_hotlist, mo_t_list,
|
|
title, NULL, posi,
|
|
get_pref_boolean(eADD_HOTLIST_ADDS_RBM));
|
|
}
|
|
if (addOk == mo_succeed)
|
|
mo_write_default_hotlist ();
|
|
}
|
|
win->hot_cut_buffer = NULL;
|
|
/* AMB do a redisplay here */
|
|
mo_compute_hot_path(win->current_hotlist);
|
|
XmListDeleteAllItems(win->hotlist_list);
|
|
mo_load_hotlist_list(win, win->hotlist_list);
|
|
/* /AMB */
|
|
|
|
break;
|
|
|
|
case 1: /* Dismiss Edit */
|
|
XtUnmanageChild (win->edithot_win);
|
|
/* Do nothing. */
|
|
break;
|
|
|
|
case 4: /* Dismiss Insert */
|
|
XtUnmanageChild (win->inserthot_win);
|
|
win->hot_cut_buffer = NULL;
|
|
/* Do nothing. */
|
|
break;
|
|
|
|
case 2: /* Help... (Edit) */
|
|
case 5: /* Help... (Insert) */
|
|
mo_open_another_window
|
|
(win,
|
|
mo_assemble_help_url ("help-on-hotlist-view.html"),
|
|
NULL, NULL);
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/* this is used to destroy the edit_or_insert_hot_info structure
|
|
called from the "destroyCallback" list. */
|
|
static XmxCallback (mo_destroy_hot)
|
|
{
|
|
free (client_data);
|
|
}
|
|
|
|
/* show or hide the url info with respect to the URL toggle */
|
|
static XmxCallback (url_or_list_cb)
|
|
{
|
|
edit_or_insert_hot_info *eht_info = (edit_or_insert_hot_info *)client_data;
|
|
if (((XmToggleButtonCallbackStruct *)call_data)->set)
|
|
{
|
|
XtManageChild(eht_info->url_lab);
|
|
XtManageChild(eht_info->url_text);
|
|
}
|
|
else
|
|
{
|
|
XtUnmanageChild(eht_info->url_lab);
|
|
XtUnmanageChild(eht_info->url_text);
|
|
}
|
|
}
|
|
|
|
|
|
/* If it don't exist, make it...
|
|
If isInsert is True, then we create an Insert Dialog window, otherwise
|
|
we create an Edit dialog window. */
|
|
static mo_status mo_create_ed_or_ins_hot_win (mo_window *win, int isInsert)
|
|
{
|
|
Widget ed_or_ins_w, dialog_frame;
|
|
Widget dialog_sep, buttons_form;
|
|
Widget eht_form, title_label, url_label, url_val, sep2;
|
|
edit_or_insert_hot_info *eht_info;
|
|
Widget togm, togm2, insert_tog, append_tog;
|
|
|
|
XmxSetUniqid (win->id);
|
|
eht_info = (edit_or_insert_hot_info *)
|
|
malloc(sizeof(edit_or_insert_hot_info));
|
|
XmxSetArg (XmNuserData, (XtArgVal)eht_info);
|
|
ed_or_ins_w = XmxMakeFormDialog
|
|
(win->hotlist_win, isInsert ? "NCSA Mosaic: Insert Hotlist Entry" :
|
|
"NCSA Mosaic: Edit Hotlist Entry" );
|
|
XtAddCallback(ed_or_ins_w, XmNdestroyCallback, mo_destroy_hot,
|
|
eht_info);
|
|
|
|
if (isInsert)
|
|
win->inserthot_win = ed_or_ins_w;
|
|
else
|
|
win->edithot_win = ed_or_ins_w;
|
|
|
|
dialog_frame = XmxMakeFrame (ed_or_ins_w, XmxShadowOut);
|
|
|
|
/* Constraints for ed_or_ins_w. */
|
|
XmxSetConstraints
|
|
(dialog_frame, XmATTACH_FORM, XmATTACH_FORM,
|
|
XmATTACH_FORM, XmATTACH_FORM, NULL, NULL, NULL, NULL);
|
|
|
|
/* Main form. */
|
|
eht_form = XmxMakeForm (dialog_frame);
|
|
|
|
title_label = XmxMakeLabel (eht_form, "Entry Title:" );
|
|
XmxSetArg (XmNwidth, 335);
|
|
eht_info->title_text = XmxMakeTextField (eht_form);
|
|
XmxAddCallbackToText (eht_info->title_text, edit_or_insert_hot_cb,
|
|
isInsert*3);
|
|
|
|
eht_info->url_lab =
|
|
url_label = XmxMakeLabel (eht_form, "URL:" );
|
|
|
|
XmxSetArg (XmNwidth, 335);
|
|
eht_info->url_text =
|
|
url_val = XmxMakeTextField(eht_form);
|
|
|
|
dialog_sep = XmxMakeHorizontalSeparator (eht_form);
|
|
|
|
if (isInsert)
|
|
{
|
|
togm = XmxMakeRadioBox(eht_form);
|
|
eht_info->tog_url =
|
|
XtVaCreateManagedWidget("toggle", xmToggleButtonGadgetClass, togm,
|
|
XtVaTypedArg, XmNlabelString,
|
|
XtRString, "URL" , strlen("URL" )+1,
|
|
XmNmarginHeight, 0,
|
|
XmNset, True, NULL);
|
|
XtAddCallback(eht_info->tog_url, XmNvalueChangedCallback, url_or_list_cb,
|
|
(XtPointer)eht_info);
|
|
eht_info->tog_list =
|
|
XtVaCreateManagedWidget("toggle", xmToggleButtonGadgetClass, togm,
|
|
XtVaTypedArg, XmNlabelString,
|
|
XtRString, "List" , strlen("List" )+1,
|
|
XmNmarginHeight, 0, NULL);
|
|
togm2 = XmxMakeRadioBox(eht_form);
|
|
eht_info->insert_tog = insert_tog =
|
|
XtVaCreateManagedWidget("toggle", xmToggleButtonGadgetClass, togm2,
|
|
XtVaTypedArg, XmNlabelString,
|
|
XtRString, "Insert" , strlen("Insert" )+1,
|
|
XmNmarginHeight, 0, NULL);
|
|
append_tog =
|
|
XtVaCreateManagedWidget("toggle", xmToggleButtonGadgetClass, togm2,
|
|
XtVaTypedArg, XmNlabelString,
|
|
XtRString, "Append" , strlen("Append" )+1,
|
|
XmNmarginHeight, 0,
|
|
XmNset, True, NULL);
|
|
sep2 = XmxMakeHorizontalSeparator (eht_form);
|
|
}
|
|
|
|
buttons_form = XmxMakeFormAndThreeButtons
|
|
(eht_form, edit_or_insert_hot_cb, "Save" ,
|
|
"Dismiss" , "Help..." ,
|
|
isInsert*3, isInsert*3+1, isInsert*3+2);
|
|
|
|
/* Constraints for eht_form. */
|
|
XmxSetOffsets (title_label, 14, 0, 10, 0);
|
|
XmxSetConstraints
|
|
(title_label, XmATTACH_FORM, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE,
|
|
NULL, NULL, NULL, NULL);
|
|
XmxSetOffsets (eht_info->title_text, 10, 0, 5, 10);
|
|
XmxSetConstraints
|
|
(eht_info->title_text, XmATTACH_FORM, XmATTACH_NONE, XmATTACH_WIDGET,
|
|
XmATTACH_FORM, NULL, NULL, title_label, NULL);
|
|
|
|
XmxSetOffsets (url_label, 12, 0, 10, 0);
|
|
XmxSetConstraints
|
|
(url_label, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE,
|
|
title_label, NULL, NULL, NULL);
|
|
XmxSetOffsets (url_val, 8, 10, 5, 10);
|
|
XmxSetConstraints
|
|
(url_val, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_WIDGET,
|
|
XmATTACH_FORM, title_label, NULL, url_label, NULL);
|
|
|
|
XmxSetArg (XmNtopOffset, 10);
|
|
XmxSetConstraints
|
|
(dialog_sep, XmATTACH_WIDGET, XmATTACH_WIDGET, XmATTACH_FORM,
|
|
XmATTACH_FORM,
|
|
url_val, isInsert ? togm : buttons_form, NULL, NULL);
|
|
if (isInsert)
|
|
{
|
|
XmxSetConstraints
|
|
(togm, XmATTACH_NONE, XmATTACH_WIDGET, XmATTACH_FORM,
|
|
XmATTACH_NONE,
|
|
NULL, sep2, NULL, NULL);
|
|
XmxSetPositions
|
|
(togm, XmxNoPosition, XmxNoPosition, XmxNoPosition, 50);
|
|
XmxSetConstraints
|
|
(togm2, XmATTACH_NONE, XmATTACH_WIDGET, XmATTACH_NONE,
|
|
XmATTACH_FORM,
|
|
NULL, sep2, NULL, NULL);
|
|
XmxSetPositions
|
|
(togm2, XmxNoPosition, XmxNoPosition, 50, XmxNoPosition);
|
|
XmxSetConstraints
|
|
(sep2, XmATTACH_NONE, XmATTACH_WIDGET, XmATTACH_FORM,
|
|
XmATTACH_FORM, NULL, buttons_form, NULL, NULL);
|
|
}
|
|
XmxSetConstraints
|
|
(buttons_form, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_FORM,
|
|
XmATTACH_FORM,
|
|
NULL, NULL, NULL, NULL);
|
|
|
|
return mo_succeed;
|
|
}
|
|
|
|
|
|
static mo_status mo_do_edit_hotnode_title_win (mo_window *win, mo_hot_item
|
|
*item, int position)
|
|
{
|
|
edit_or_insert_hot_info *eht_info;
|
|
|
|
/* This shouldn't happen. */
|
|
if (!win->hotlist_win)
|
|
return mo_fail;
|
|
|
|
if (!win->edithot_win)
|
|
mo_create_ed_or_ins_hot_win (win, 0);
|
|
|
|
XmxSetArg (XmNuserData, (XtArgVal)&eht_info);
|
|
XtGetValues (win->edithot_win, Xmx_wargs, Xmx_n);
|
|
Xmx_n = 0;
|
|
/* Cache the position. */
|
|
eht_info->pos = position;
|
|
|
|
/* Manage the little sucker. */
|
|
XmxManageRemanage (win->edithot_win);
|
|
|
|
/* Insert this title as a starting point. */
|
|
XmxTextSetString (eht_info->title_text, item->hot.title);
|
|
|
|
if (item->type == mo_t_url)
|
|
{
|
|
/* Insert URL */
|
|
XmxTextSetString (eht_info->url_text, item->hot.url);
|
|
XtManageChild(eht_info->url_lab);
|
|
XtManageChild(eht_info->url_text);
|
|
}
|
|
else
|
|
{
|
|
XtUnmanageChild(eht_info->url_lab);
|
|
XtUnmanageChild(eht_info->url_text);
|
|
}
|
|
|
|
return mo_succeed;
|
|
}
|
|
|
|
|
|
/*
|
|
* Edit the title of an element of the current hotlist.
|
|
* The element is referenced by its position.
|
|
* Algorithm for edit:
|
|
* Find hotnode with the position.
|
|
* Change the title.
|
|
* Cause redisplay.
|
|
* Return status.
|
|
*/
|
|
static mo_status mo_edit_title_in_current_hotlist (mo_window *win,
|
|
int position)
|
|
{
|
|
mo_hotlist *list = win->current_hotlist;
|
|
mo_hot_item *hotnode;
|
|
|
|
FindHotFromPos(hotnode, list, position);
|
|
|
|
/* OK, now we have hotnode loaded. */
|
|
/* hotnode->hot.title is the current title.
|
|
hotnode->hot.position is the current position. */
|
|
return
|
|
((hotnode != NULL) ?
|
|
mo_do_edit_hotnode_title_win (win, hotnode, position) :
|
|
mo_fail);
|
|
}
|
|
|
|
|
|
void RecursiveSetList(mo_window *win, mo_hotlist *list, int val, int force) {
|
|
|
|
static char *add="Do you wish to add all items in this list to the RBM?";
|
|
static char *remove="Do you wish to remove all items in this list from the RBM?";
|
|
mo_hot_item *item;
|
|
|
|
if (force || prompt_for_yes_or_no((val?add:remove))) {
|
|
for (item=list->nodelist; item; item=item->any.next) {
|
|
if (item->type==mo_t_url) {
|
|
item->hot.rbm=val;
|
|
}
|
|
else {
|
|
item->list.rbm=val;
|
|
RecursiveSetList(win,&(item->list),val,1);
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
|
|
/*
|
|
* Either add or remove this entry from the RBM.
|
|
* The element is referenced by its position.
|
|
* Algorithm:
|
|
* Find hotnode with the position.
|
|
* Change the RBM status.
|
|
* Cause rebuild of RBM.
|
|
* Return status.
|
|
*/
|
|
static mo_status mo_rbm_toggle_in_hotlist(mo_window *win,int position) {
|
|
|
|
mo_hotlist *list = win->current_hotlist;
|
|
mo_hot_item *hotnode;
|
|
|
|
FindHotFromPos(hotnode, list, position);
|
|
|
|
if (!hotnode) { /* How did this happen? */
|
|
return(mo_fail);
|
|
}
|
|
|
|
/*
|
|
* Set the new rbm value.
|
|
* Redisplay and rebuild the RBM.
|
|
*/
|
|
if (hotnode->type==mo_t_url) {
|
|
hotnode->hot.rbm=(!hotnode->hot.rbm);
|
|
}
|
|
else {
|
|
hotnode->list.rbm=(!hotnode->list.rbm);
|
|
RecursiveSetList(win,&hotnode->list,hotnode->list.rbm,0);
|
|
}
|
|
XmxSetToggleButton(win->hotlist_rbm_toggle,
|
|
(hotnode->type==mo_t_url?
|
|
hotnode->hot.rbm:
|
|
hotnode->list.rbm));
|
|
|
|
mo_reinit_hotmenu();
|
|
|
|
return(mo_succeed);
|
|
}
|
|
|
|
static void mo_insert_item_in_current_hotlist(mo_window *win)
|
|
{
|
|
if (win->hotlist_win)
|
|
{
|
|
edit_or_insert_hot_info *eht_info;
|
|
|
|
if (!win->inserthot_win)
|
|
mo_create_ed_or_ins_hot_win(win, 1);
|
|
|
|
XmxSetArg (XmNuserData, (XtArgVal)&eht_info);
|
|
XtGetValues (win->inserthot_win, Xmx_wargs, Xmx_n);
|
|
Xmx_n = 0;
|
|
/* Manage the little sucker. */
|
|
XmxManageRemanage (win->inserthot_win);
|
|
|
|
if (win->hot_cut_buffer)
|
|
{
|
|
/* Insert this title as a starting point. */
|
|
XmxTextSetString (eht_info->title_text,
|
|
win->hot_cut_buffer->any.name);
|
|
if (win->hot_cut_buffer->type == mo_t_url)
|
|
{
|
|
/* Insert URL */
|
|
XmxTextSetString (eht_info->url_text,
|
|
win->hot_cut_buffer->hot.url);
|
|
XtManageChild(eht_info->url_lab);
|
|
XtManageChild(eht_info->url_text);
|
|
XmToggleButtonGadgetSetState(eht_info->tog_list, False, False);
|
|
XmToggleButtonGadgetSetState(eht_info->tog_url, True, False);
|
|
}
|
|
else
|
|
{
|
|
/* Insert a List */
|
|
XtUnmanageChild(eht_info->url_lab);
|
|
XtUnmanageChild(eht_info->url_text);
|
|
XmToggleButtonGadgetSetState(eht_info->tog_list, True, False);
|
|
XmToggleButtonGadgetSetState(eht_info->tog_url, False, False);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
XmTextFieldSetString(eht_info->title_text, "");
|
|
XmTextFieldSetString(eht_info->url_text, "");
|
|
}
|
|
}
|
|
|
|
mo_reinit_hotmenu();
|
|
|
|
}
|
|
|
|
|
|
/*
|
|
* Create a new mo_root_hotlist.
|
|
* Pass in the new filename and the new title.
|
|
*/
|
|
static mo_root_hotlist *mo_new_root_hotlist (char *filename, char *title)
|
|
{
|
|
mo_root_hotlist *list;
|
|
|
|
list = (mo_root_hotlist *)malloc (sizeof (mo_root_hotlist));
|
|
list->type = mo_t_list;
|
|
list->nodelist = list->nodelist_last = 0;
|
|
list->filename = filename;
|
|
list->modified = 1;
|
|
list->next = list->previous = 0;
|
|
list->parent = 0;
|
|
list->name = title ? strdup (title) : title;
|
|
return list;
|
|
}
|
|
|
|
/* --------------------------- mo_read_hotlist ---------------------------- */
|
|
|
|
/*
|
|
* Read a hotlist from a file.
|
|
* Return pointer to a mo_hotlist structure, fully loaded
|
|
* and ready to go.
|
|
* Return NULL if file does not exist or is not readable.
|
|
*/
|
|
static mo_root_hotlist *mo_read_hotlist (char *filename, char *home)
|
|
{
|
|
mo_root_hotlist *list = NULL;
|
|
FILE *fp;
|
|
char line[MO_LINE_LENGTH];
|
|
char *status, *name;
|
|
int isnew;
|
|
char *oldfilename/*,*tmpfilename*/;
|
|
char *hotname;
|
|
char *tmp=get_pref_string(eDEFAULT_HOT_FILE);
|
|
|
|
hotname=(char *)calloc(strlen(home)+strlen(tmp)+5,sizeof(char));
|
|
sprintf(hotname,"%s/%s",home,tmp);
|
|
|
|
oldfilename = filename;
|
|
if (! (filename= malloc(strlen(filename) + 10)))
|
|
goto screwed_no_file;
|
|
sprintf(filename,"%s.html",oldfilename);
|
|
/* for backward compatibility */
|
|
|
|
/* oldfilename: cookie 1
|
|
filename: cookie 2
|
|
hotname: cookie 3 */
|
|
|
|
/* cookie 2 and cookie 3 are very similar, but format 2 browsers cannot
|
|
read format 3 without damaging them.
|
|
The cool thing is if we only have format 2, format 3 will automatically
|
|
be written out to the format 3 filename...so we don't have to worry
|
|
about converting anything. Groovy. --SWP */
|
|
|
|
if (!(fp=fopen(hotname,"r"))) {
|
|
fp = fopen (filename, "r");
|
|
if (!fp) {
|
|
fp = fopen (oldfilename, "r");
|
|
if (!fp) {
|
|
goto screwed_no_file;
|
|
}
|
|
else if (get_pref_boolean(eBACKUP_FILES)) {
|
|
char *tf=NULL,retBuf[BUFSIZ];
|
|
|
|
tf=(char *)calloc(strlen(oldfilename)+strlen(".backup")+5,sizeof(char));
|
|
sprintf(tf,"%s.backup",oldfilename);
|
|
if (my_copy(oldfilename,tf,retBuf,BUFSIZ-1,1)!=SYS_SUCCESS) {
|
|
fprintf(stderr,"%s\n",retBuf);
|
|
}
|
|
free(tf);
|
|
}
|
|
}
|
|
else if (get_pref_boolean(eBACKUP_FILES)) {
|
|
char *tf=NULL,retBuf[BUFSIZ];
|
|
|
|
tf=(char *)calloc(strlen(filename)+strlen(".backup")+5,sizeof(char));
|
|
sprintf(tf,"%s.backup",filename);
|
|
if (my_copy(filename,tf,retBuf,BUFSIZ-1,1)!=SYS_SUCCESS) {
|
|
fprintf(stderr,"%s\n",retBuf);
|
|
}
|
|
free(tf);
|
|
}
|
|
}
|
|
else if (get_pref_boolean(eBACKUP_FILES)) {
|
|
char *tf=NULL,retBuf[BUFSIZ];
|
|
|
|
tf=(char *)calloc(strlen(hotname)+strlen(".backup")+5,sizeof(char));
|
|
sprintf(tf,"%s.backup",hotname);
|
|
if (my_copy(hotname,tf,retBuf,BUFSIZ-1,1)!=SYS_SUCCESS) {
|
|
fprintf(stderr,"%s\n",retBuf);
|
|
}
|
|
free(tf);
|
|
}
|
|
|
|
status = fgets (line, MO_LINE_LENGTH, fp);
|
|
if (!status || !(*line)) {
|
|
goto screwed_open_file;
|
|
}
|
|
|
|
/* See if it's our format. */
|
|
if (!strncmp (line, NCSA_HOTLIST_FORMAT_COOKIE_ONE,
|
|
strlen (NCSA_HOTLIST_FORMAT_COOKIE_ONE))) {
|
|
isnew = 0;
|
|
}
|
|
else {
|
|
status = fgets (line, MO_LINE_LENGTH, fp);
|
|
if (!status || !(*line)) {
|
|
goto screwed_open_file;
|
|
}
|
|
|
|
if (!strncmp(line, NCSA_HOTLIST_FORMAT_COOKIE_TWO,
|
|
strlen (NCSA_HOTLIST_FORMAT_COOKIE_TWO))) {
|
|
isnew = 1;
|
|
}
|
|
else if (!strncmp(line, NCSA_HOTLIST_FORMAT_COOKIE_THREE,
|
|
strlen (NCSA_HOTLIST_FORMAT_COOKIE_THREE))) {
|
|
isnew = 2;
|
|
}
|
|
else {
|
|
fprintf(stderr,"Unknown hotlist format. Attempting to parse. This\n could result in damage to this file.\n");
|
|
isnew = 2;
|
|
}
|
|
|
|
rewind(fp);
|
|
status = fgets (line, MO_LINE_LENGTH, fp);
|
|
if (!status || !(*line)) {
|
|
goto screwed_open_file;
|
|
}
|
|
}
|
|
|
|
if (isnew)
|
|
{
|
|
list = mo_new_root_hotlist(hotname, NULL);
|
|
list->name = mo_read_new_hotlist((mo_hotlist *)list, fp);
|
|
if (isnew==1) {
|
|
fprintf(stderr,"Your hotlist has been updated to a new format!\n It is now called 'hot.html'.\n");
|
|
}
|
|
goto done;
|
|
}
|
|
/* Go fetch the name on the next line. */
|
|
status = fgets (line, MO_LINE_LENGTH, fp);
|
|
if (!status || (!*line))
|
|
goto screwed_open_file;
|
|
name = strtok (line, "\n");
|
|
if (!name)
|
|
goto screwed_open_file;
|
|
|
|
/* amb - display update message for 2.4 users */
|
|
{
|
|
fputs("Your hotlist file has been updated and is now saved as:\n",
|
|
stderr);
|
|
fputs(filename, stderr);
|
|
putc('\n', stderr);
|
|
}
|
|
/* Hey, whaddaya know, it is. */
|
|
list = mo_new_root_hotlist (filename, name);
|
|
|
|
/* Start grabbing documents. */
|
|
while (1)
|
|
{
|
|
mo_hotnode *node;
|
|
|
|
status = fgets (line, MO_LINE_LENGTH, fp);
|
|
if (!status || !(*line))
|
|
goto done;
|
|
|
|
/* We've got a new node. */
|
|
node = (mo_hotnode *)malloc (sizeof (mo_hotnode));
|
|
node->type = mo_t_url;
|
|
node->url = strtok (line, " ");
|
|
if (!node->url)
|
|
goto screwed_open_file;
|
|
node->url = strdup (node->url);
|
|
mo_convert_newlines_to_spaces (node->url);
|
|
|
|
node->lastdate = strtok (NULL, "\n");
|
|
if (!node->lastdate) {
|
|
goto screwed_open_file;
|
|
}
|
|
node->lastdate = strdup (node->lastdate);
|
|
|
|
status = fgets (line, MO_LINE_LENGTH, fp);
|
|
if (!status || !(*line))
|
|
{
|
|
/* Oops, something went wrong. */
|
|
free (node->url);
|
|
if (node->lastdate) {
|
|
free (node->lastdate);
|
|
}
|
|
free (node);
|
|
goto done;
|
|
}
|
|
|
|
node->title = strtok (line, "\n");
|
|
if (!node->title)
|
|
goto screwed_open_file;
|
|
node->title = strdup (node->title);
|
|
mo_convert_newlines_to_spaces (node->title);
|
|
|
|
mo_append_item_to_hotlist ((mo_hotlist *)list, (mo_hot_item *)node);
|
|
}
|
|
|
|
done:
|
|
fclose (fp);
|
|
return list;
|
|
|
|
screwed_open_file:
|
|
fclose (fp);
|
|
|
|
screwed_no_file:
|
|
return list;
|
|
}
|
|
|
|
|
|
#if 0
|
|
/*
|
|
* Write a hotlist out to stdout.
|
|
* Return mo_succeed if everything goes OK;
|
|
* mo_fail else.
|
|
*/
|
|
mo_status mo_dump_hotlist (mo_hotlist *list)
|
|
{
|
|
mo_write_hotlist (list, stdout);
|
|
|
|
return mo_succeed;
|
|
}
|
|
#endif
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
/* ----------------------------- HOTLIST GUI ------------------------------ */
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
/* Initial GUI support for hotlist will work like this:
|
|
|
|
There will be a single hotlist, called 'Default'.
|
|
It will be persistent across all windows.
|
|
|
|
Upon program startup an attempt will be made to load it out
|
|
of its file; if this attempt isn't successful, it just plain
|
|
doesn't exist yet. Bummer.
|
|
|
|
Upon program exit it will be stored to its file.
|
|
*/
|
|
|
|
/*
|
|
* Called on initialization.
|
|
* Tries to load the default hotlist.
|
|
*/
|
|
mo_status mo_setup_default_hotlist (void)
|
|
{
|
|
char *home = flatpakCheck();
|
|
char *default_filename = get_pref_string(eDEFAULT_HOTLIST_FILE);
|
|
char *hot_filename = get_pref_string(eDEFAULT_HOT_FILE);
|
|
char *filename;
|
|
|
|
/* This shouldn't happen. */
|
|
if (!home)
|
|
home = "/tmp";
|
|
|
|
filename = (char *)malloc
|
|
((strlen (home) + strlen (default_filename) + 8) * sizeof (char));
|
|
sprintf (filename, "%s/%s", home, default_filename);
|
|
|
|
/* Try to load the default hotlist. */
|
|
default_hotlist = mo_read_hotlist (filename, home);
|
|
/* Doesn't exist? Bummer. Make a new one. */
|
|
if (!default_hotlist)
|
|
{
|
|
fprintf(stderr,"Could not find a hotlit. Creating a new one.\n");
|
|
/* amb - doesn't have any hotlist, add the .html extension (ugh) */
|
|
/* sprintf(filename, "%s/%s.html", home, default_filename); */
|
|
/* New hotlist format... SWP */
|
|
free(filename);
|
|
filename = (char *)malloc
|
|
((strlen (home) + strlen (hot_filename) + 8) * sizeof (char));
|
|
sprintf (filename, "%s/%s", home, hot_filename);
|
|
fprintf(stderr, "%s\n", filename);
|
|
default_hotlist = mo_new_root_hotlist (filename, "Default");
|
|
}
|
|
|
|
return mo_succeed;
|
|
}
|
|
|
|
/*
|
|
* Called on program exit.
|
|
* Tries to write the default hotlist.
|
|
*/
|
|
mo_status mo_write_default_hotlist (void)
|
|
{
|
|
FILE *fp = fopen (default_hotlist->filename, "w");
|
|
|
|
if (!fp)
|
|
return mo_fail;
|
|
|
|
mo_write_hotlist ((mo_hotlist *)default_hotlist, fp);
|
|
if (fclose (fp))
|
|
return mo_fail;
|
|
|
|
default_hotlist->modified = 0;
|
|
return mo_succeed;
|
|
}
|
|
|
|
static XmxCallback (save_hot_cb)
|
|
{
|
|
char *fname = NULL, efname[MO_LINE_LENGTH];
|
|
FILE *fp;
|
|
mo_window *win = mo_fetch_window_by_id (XmxExtractUniqid ((int)client_data));
|
|
|
|
XtUnmanageChild (win->save_hotlist_win);
|
|
mo_busy ();
|
|
XmStringGetLtoR (((XmFileSelectionBoxCallbackStruct *)call_data)->value,
|
|
XmSTRING_DEFAULT_CHARSET, &fname);
|
|
pathEval (efname, fname);
|
|
fp = fopen (efname, "w");
|
|
if (!fp)
|
|
{
|
|
char *buf, *final, tmpbuf[80];
|
|
int final_len;
|
|
|
|
buf=my_strerror(errno);
|
|
if (!buf || !*buf || !strcmp(buf,"Error 0")) {
|
|
sprintf(tmpbuf,"Unknown Error");
|
|
buf=tmpbuf;
|
|
}
|
|
|
|
final_len=30+((!efname || !*efname?3:strlen(efname))+13)+15+(strlen(buf)+13);
|
|
final=(char *)calloc(final_len,sizeof(char));
|
|
|
|
sprintf(final,"\nUnable to save hotlist:\n %s\n\nSave Error:\n %s\n" ,(!efname||!*efname?" ":efname),buf);
|
|
|
|
XmxMakeErrorDialog (win->save_hotlist_win,
|
|
final, "Save Error" );
|
|
XtManageChild (Xmx_w);
|
|
|
|
if (final) {
|
|
free(final);
|
|
final=NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
mo_write_hotlist (win->current_hotlist, fp);
|
|
fclose(fp);
|
|
}
|
|
mo_not_busy ();
|
|
free (fname);
|
|
}
|
|
|
|
static XmxCallback (load_hot_cb)
|
|
{
|
|
char *fname = NULL, efname[MO_LINE_LENGTH];
|
|
FILE *fp;
|
|
mo_window *win = mo_fetch_window_by_id (XmxExtractUniqid ((int)client_data));
|
|
|
|
XtUnmanageChild (win->load_hotlist_win);
|
|
mo_busy ();
|
|
XmStringGetLtoR (((XmFileSelectionBoxCallbackStruct *)call_data)->value,
|
|
XmSTRING_DEFAULT_CHARSET, &fname);
|
|
pathEval (efname, fname);
|
|
fp = fopen (efname, "r");
|
|
if (!fp)
|
|
{
|
|
char *buf, *final, tmpbuf[80];
|
|
int final_len;
|
|
|
|
buf=my_strerror(errno);
|
|
if (!buf || !*buf || !strcmp(buf,"Error 0")) {
|
|
sprintf(tmpbuf,"Unknown Error");
|
|
buf=tmpbuf;
|
|
}
|
|
|
|
final_len=30+((!efname || !*efname?3:strlen(efname))+13)+15+(strlen(buf)+13);
|
|
final=(char *)calloc(final_len,sizeof(char));
|
|
|
|
sprintf(final,"\nUnable to open hotlist:\n %s\n\nOpen Error:\n %s\n" ,(!efname||!*efname?" ":efname),buf);
|
|
|
|
XmxMakeErrorDialog (win->load_hotlist_win,
|
|
final, "Open Error" );
|
|
XtManageChild (Xmx_w);
|
|
|
|
if (final) {
|
|
free(final);
|
|
final=NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
Widget tb;
|
|
|
|
XmxSetArg (XmNuserData, (XtArgVal)&tb);
|
|
XtGetValues (win->load_hotlist_win, Xmx_wargs, Xmx_n);
|
|
Xmx_n = 0;
|
|
if (XmToggleButtonGadgetGetState (tb))
|
|
{
|
|
mo_hotlist *list = (mo_hotlist *)malloc (sizeof(mo_hotlist));
|
|
|
|
list->type = mo_t_list;
|
|
list->nodelist = list->nodelist_last = 0;
|
|
list->name = mo_read_new_hotlist (list, fp);
|
|
if (list->name == NULL)
|
|
list->name = strdup("Unnamed" );
|
|
mo_append_item_to_hotlist(win->current_hotlist, (mo_hot_item *)list);
|
|
mo_gui_add_hot_item (win->current_hotlist, (mo_hot_item *)list);
|
|
}
|
|
else
|
|
{
|
|
mo_hot_item *item = win->current_hotlist->nodelist_last;
|
|
|
|
mo_read_new_hotlist (win->current_hotlist, fp);
|
|
if (item == NULL)
|
|
item = win->current_hotlist->nodelist;
|
|
else
|
|
item = item->any.next;
|
|
for (;item; item = item->any.next)
|
|
mo_gui_add_hot_item (win->current_hotlist, item);
|
|
}
|
|
fclose (fp);
|
|
default_hotlist->modified = 1;
|
|
mo_write_default_hotlist ();
|
|
URL_Include_Set(win,0,0);
|
|
}
|
|
mo_not_busy ();
|
|
free (fname);
|
|
}
|
|
|
|
/* --------------- mo_delete_position_from_current_hotlist ---------------- */
|
|
/*
|
|
* Delete an element of the default hotlist.
|
|
* The element is referenced by its position.
|
|
* Algorithm for removal:
|
|
* Find hotnode with the position.
|
|
* If it is a list, change the current list of the windows that has hotnode
|
|
* as an ancestor.
|
|
* Remove the hotnode from the hotlist data structure.
|
|
* Recalculate positions of the hotlist.
|
|
* Remove the element in the position in the list widgets.
|
|
* Return status.
|
|
*/
|
|
static void delete_hot_from_list (mo_hotlist *list, mo_hot_item *hotnode,
|
|
int position)
|
|
{
|
|
mo_window *win = NULL;
|
|
|
|
if (hotnode == NULL)
|
|
return;
|
|
if (hotnode->type == mo_t_list)
|
|
while (win = mo_next_window (win))
|
|
{
|
|
if (win->hotlist_list &&
|
|
mo_is_ancestor (&(hotnode->list), win->current_hotlist))
|
|
{
|
|
char *path = mo_compute_hot_path(list);
|
|
|
|
XmListDeleteAllItems(win->hotlist_list);
|
|
win->current_hotlist = list;
|
|
XmxTextSetString(win->hotlist_label, path);
|
|
free(path);
|
|
mo_load_hotlist_list(win, win->hotlist_list);
|
|
}
|
|
}
|
|
/* Pull the hotnode out of the hotlist. */
|
|
mo_remove_hotnode_from_hotlist (list, hotnode);
|
|
free (hotnode);
|
|
/* Recalculate positions in this hotlist. */
|
|
mo_recalculate_hotlist_positions (list);
|
|
|
|
/* Do the GUI stuff. */
|
|
while (win = mo_next_window (win))
|
|
{
|
|
if (win->hotlist_list && win->current_hotlist == list)
|
|
XmListDeletePos (win->hotlist_list, position);
|
|
if (win->hot_cut_buffer == hotnode)
|
|
win->hot_cut_buffer = NULL;
|
|
}
|
|
mo_reinit_hotmenu();
|
|
|
|
}
|
|
|
|
static XmxCallback (remove_confirm_cb)
|
|
{
|
|
mo_window *win = mo_fetch_window_by_id
|
|
(XmxExtractUniqid ((int)client_data));
|
|
int position = XmxExtractToken ((int)client_data);
|
|
|
|
if (position)
|
|
{
|
|
mo_hot_item *hotnode;
|
|
FindHotFromPos(hotnode, win->current_hotlist, position);
|
|
delete_hot_from_list(win->current_hotlist, hotnode, position);
|
|
URL_Include_Set(win,0,0);
|
|
}
|
|
XtDestroyWidget(w);
|
|
}
|
|
|
|
static mo_status mo_delete_position_from_current_hotlist (mo_window *win,
|
|
int position)
|
|
{
|
|
mo_hotlist *list = win->current_hotlist;
|
|
mo_hot_item *hotnode;
|
|
|
|
FindHotFromPos(hotnode, list, position);
|
|
|
|
if (hotnode == NULL)
|
|
return mo_fail;
|
|
|
|
/* OK, now we have hotnode loaded. */
|
|
|
|
if (hotnode->type == mo_t_list)
|
|
{
|
|
char *question;
|
|
char *endquestion;
|
|
char *buff;
|
|
|
|
question=strdup("Are you sure you want to remove the \"" );
|
|
endquestion=strdup("\" list?" );
|
|
buff = (char *)malloc
|
|
(strlen(question)+strlen(hotnode->list.name)+strlen(endquestion)+1);
|
|
|
|
strcat(strcat(strcpy(buff, question), hotnode->list.name), endquestion);
|
|
XmxSetUniqid (win->id);
|
|
XmxMakeQuestionDialog
|
|
(win->hotlist_win, buff, "NCSA Mosaic: Remove list" ,
|
|
remove_confirm_cb, position, 0);
|
|
free(buff);
|
|
free(question);
|
|
free(endquestion);
|
|
XtManageChild (Xmx_w);
|
|
}
|
|
else {
|
|
delete_hot_from_list(list, hotnode, position);
|
|
URL_Include_Set(win,0,0);
|
|
}
|
|
|
|
mo_reinit_hotmenu();
|
|
return mo_succeed;
|
|
}
|
|
|
|
|
|
/* ----------------------------- mail hotlist ----------------------------- */
|
|
|
|
static XmxCallback (mailhot_win_cb)
|
|
{
|
|
mo_window *win = mo_fetch_window_by_id
|
|
(XmxExtractUniqid ((int)client_data));
|
|
char *to, *subj;
|
|
FILE *fp;
|
|
|
|
switch (XmxExtractToken ((int)client_data))
|
|
{
|
|
case 0:
|
|
XtUnmanageChild (win->mailhot_win);
|
|
|
|
mo_busy ();
|
|
|
|
to = XmxTextGetString (win->mailhot_to_text);
|
|
if (!to)
|
|
return;
|
|
if (to[0] == '\0')
|
|
return;
|
|
|
|
subj = XmxTextGetString (win->mailhot_subj_text);
|
|
|
|
/* Open a file descriptor to sendmail. */
|
|
fp = mo_start_sending_mail_message (to, subj, "text/x-html", NULL);
|
|
if (!fp)
|
|
goto oops;
|
|
|
|
{
|
|
mo_write_hotlist(win->current_hotlist, fp);
|
|
}
|
|
|
|
mo_finish_sending_mail_message ();
|
|
|
|
oops:
|
|
free (to);
|
|
free (subj);
|
|
|
|
mo_not_busy ();
|
|
|
|
break;
|
|
case 1:
|
|
XtUnmanageChild (win->mailhot_win);
|
|
/* Do nothing. */
|
|
break;
|
|
case 2:
|
|
mo_open_another_window
|
|
(win,
|
|
mo_assemble_help_url ("help-on-hotlist-view.html"),
|
|
NULL, NULL);
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static mo_status mo_post_mailhot_win (mo_window *win)
|
|
{
|
|
/* This shouldn't happen. */
|
|
if (!win->hotlist_win)
|
|
return mo_fail;
|
|
|
|
if (!win->mailhot_win)
|
|
{
|
|
Widget dialog_frame;
|
|
Widget dialog_sep, buttons_form;
|
|
Widget mailhot_form, to_label, subj_label;
|
|
|
|
/* Create it for the first time. */
|
|
XmxSetUniqid (win->id);
|
|
win->mailhot_win = XmxMakeFormDialog
|
|
(win->hotlist_win, "NCSA Mosaic: Mail Hotlist" );
|
|
dialog_frame = XmxMakeFrame (win->mailhot_win, XmxShadowOut);
|
|
|
|
/* Constraints for base. */
|
|
XmxSetConstraints
|
|
(dialog_frame, XmATTACH_FORM, XmATTACH_FORM,
|
|
XmATTACH_FORM, XmATTACH_FORM, NULL, NULL, NULL, NULL);
|
|
|
|
/* Main form. */
|
|
mailhot_form = XmxMakeForm (dialog_frame);
|
|
|
|
to_label = XmxMakeLabel (mailhot_form, "Mail To:" );
|
|
XmxSetArg (XmNwidth, 335);
|
|
win->mailhot_to_text = XmxMakeTextField (mailhot_form);
|
|
|
|
subj_label = XmxMakeLabel (mailhot_form, "Subject:" );
|
|
win->mailhot_subj_text = XmxMakeTextField (mailhot_form);
|
|
|
|
dialog_sep = XmxMakeHorizontalSeparator (mailhot_form);
|
|
|
|
buttons_form = XmxMakeFormAndThreeButtons
|
|
(mailhot_form, mailhot_win_cb, "Mail" ,
|
|
"Dismiss" , "Help..." , 0, 1, 2);
|
|
|
|
/* Constraints for mailhot_form. */
|
|
XmxSetOffsets (to_label, 14, 0, 10, 0);
|
|
XmxSetConstraints
|
|
(to_label, XmATTACH_FORM, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_NONE,
|
|
NULL, NULL, NULL, NULL);
|
|
XmxSetOffsets (win->mailhot_to_text, 10, 0, 5, 10);
|
|
XmxSetConstraints
|
|
(win->mailhot_to_text, XmATTACH_FORM, XmATTACH_NONE, XmATTACH_WIDGET,
|
|
XmATTACH_FORM, NULL, NULL, to_label, NULL);
|
|
|
|
XmxSetOffsets (subj_label, 14, 0, 10, 0);
|
|
XmxSetConstraints
|
|
(subj_label, XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM,
|
|
XmATTACH_NONE,
|
|
win->mailhot_to_text, NULL, NULL, NULL);
|
|
XmxSetOffsets (win->mailhot_subj_text, 10, 0, 5, 10);
|
|
XmxSetConstraints
|
|
(win->mailhot_subj_text, XmATTACH_WIDGET,
|
|
XmATTACH_NONE, XmATTACH_WIDGET,
|
|
XmATTACH_FORM, win->mailhot_to_text, NULL, subj_label, NULL);
|
|
|
|
XmxSetArg (XmNtopOffset, 10);
|
|
XmxSetConstraints
|
|
(dialog_sep, XmATTACH_WIDGET, XmATTACH_WIDGET, XmATTACH_FORM,
|
|
XmATTACH_FORM,
|
|
win->mailhot_subj_text, buttons_form, NULL, NULL);
|
|
XmxSetConstraints
|
|
(buttons_form, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_FORM,
|
|
XmATTACH_FORM,
|
|
NULL, NULL, NULL, NULL);
|
|
}
|
|
|
|
XtManageChild (win->mailhot_win);
|
|
|
|
return mo_succeed;
|
|
}
|
|
|
|
|
|
static XmxCallback(hotlist_rbm_toggle_cb) {
|
|
|
|
mo_window *win;
|
|
Boolean rv;
|
|
int *pos_list;
|
|
int pos_cnt;
|
|
mo_hotlist *list;
|
|
mo_hot_item *hotnode;
|
|
|
|
win=current_win;
|
|
if (!win) {
|
|
return;
|
|
}
|
|
|
|
list=win->current_hotlist;
|
|
rv = XmListGetSelectedPos (win->hotlist_list, &pos_list, &pos_cnt);
|
|
if (rv && pos_cnt) {
|
|
FindHotFromPos(hotnode, list, pos_list[0]);
|
|
if (!hotnode) {
|
|
return;
|
|
}
|
|
URL_Include_Set(win,
|
|
(hotnode->type==mo_t_url?
|
|
hotnode->hot.rbm:
|
|
hotnode->list.rbm),
|
|
1);
|
|
}
|
|
else {
|
|
XmxMakeErrorDialog
|
|
(win->hotlist_win, "No entry in the hotlist is currently selected.\n\nTo go to an entry in the hotlist,\nselect it with a single mouse click\nand press the Go To button again." , "Error: Nothing Selected" );
|
|
XtManageChild (Xmx_w);
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
/* ---------------------------- hotlist_win_cb ---------------------------- */
|
|
|
|
static XmxCallback (hotlist_win_cb)
|
|
{
|
|
mo_window *win = mo_fetch_window_by_id (XmxExtractUniqid ((int)client_data));
|
|
|
|
switch (XmxExtractToken ((int)client_data))
|
|
{
|
|
case 0:
|
|
XtUnmanageChild (win->hotlist_win);
|
|
/* Dismissed -- do nothing. */
|
|
break;
|
|
case 1:
|
|
mo_post_mailhot_win (win);
|
|
break;
|
|
case 2:
|
|
mo_open_another_window
|
|
(win,
|
|
mo_assemble_help_url ("help-on-hotlist-view.html"),
|
|
NULL, NULL);
|
|
break;
|
|
case 3:
|
|
/* Add current. */
|
|
if (win->current_node)
|
|
{
|
|
mo_add_node_to_current_hotlist (win);
|
|
mo_write_default_hotlist ();
|
|
URL_Include_Set(win,0,0);
|
|
}
|
|
break;
|
|
case 4:
|
|
/* Goto selected. */
|
|
{
|
|
Boolean rv;
|
|
int *pos_list;
|
|
int pos_cnt;
|
|
rv = XmListGetSelectedPos (win->hotlist_list, &pos_list, &pos_cnt);
|
|
if (rv && pos_cnt)
|
|
{
|
|
mo_visit_hotlist_position (win, pos_list[0]);
|
|
}
|
|
else
|
|
{
|
|
XmxMakeErrorDialog
|
|
(win->hotlist_win, "No entry in the hotlist is currently selected.\n\nTo go to an entry in the hotlist,\nselect it with a single mouse click\nand press the Go To button again." , "Error: Nothing Selected" );
|
|
XtManageChild (Xmx_w);
|
|
}
|
|
}
|
|
break;
|
|
case 5:
|
|
/* Remove selected. */
|
|
{
|
|
Boolean rv;
|
|
int *pos_list;
|
|
int pos_cnt;
|
|
rv = XmListGetSelectedPos (win->hotlist_list, &pos_list, &pos_cnt);
|
|
if (rv && pos_cnt)
|
|
{
|
|
mo_delete_position_from_current_hotlist (win,
|
|
pos_list[0]);
|
|
mo_write_default_hotlist ();
|
|
}
|
|
else
|
|
{
|
|
XmxMakeErrorDialog
|
|
(win->hotlist_win, "No entry in the hotlist is currently selected.\n\nTo remove an entry in the hotlist,\nselect it with a single mouse click\nand press the Remove button again." , "Error: Nothing Selected" );
|
|
XtManageChild (Xmx_w);
|
|
}
|
|
}
|
|
break;
|
|
case 6:
|
|
/* Edit title of selected. */
|
|
{
|
|
Boolean rv;
|
|
int *pos_list;
|
|
int pos_cnt;
|
|
rv = XmListGetSelectedPos (win->hotlist_list, &pos_list, &pos_cnt);
|
|
if (rv && pos_cnt)
|
|
{
|
|
mo_edit_title_in_current_hotlist (win, pos_list[0]);
|
|
XtFree((char *)pos_list); /* DXP */
|
|
/* Writing the default hotlist should take place in the callback. */
|
|
/* mo_write_default_hotlist (); */
|
|
}
|
|
else
|
|
{
|
|
XmxMakeErrorDialog
|
|
(win->hotlist_win, "No entry in the hotlist is currently selected.\n\nTo edit an entry in the hotlist,\nselect it with a single mouse click\nand press the Edit button again." , "Error: Nothing Selected" );
|
|
XtManageChild (Xmx_w);
|
|
}
|
|
}
|
|
break;
|
|
case 7:
|
|
/* Copy item to cut buffer */
|
|
{
|
|
int *pos_list;
|
|
int pos_cnt;
|
|
|
|
if (XmListGetSelectedPos (win->hotlist_list, &pos_list, &pos_cnt) &&
|
|
pos_cnt)
|
|
{
|
|
mo_copy_hotlist_position(win, pos_list[0]);
|
|
XtFree((char *)pos_list); /* DXP */
|
|
}
|
|
else
|
|
{
|
|
XmxMakeErrorDialog
|
|
(win->hotlist_win, "No entry in the hotlist is currently selected.\n\nTo copy an entry in the hotlist,\nselect it with a single mouse click\nand press the Copy button again." , "Error: Nothing Selected" );
|
|
XtManageChild (Xmx_w);
|
|
}
|
|
}
|
|
break;
|
|
case 8:
|
|
/* Insert an Item in the current hotlist */
|
|
mo_insert_item_in_current_hotlist(win);
|
|
break;
|
|
case 9:
|
|
/* Go Up one level */
|
|
if (win->current_hotlist->parent != 0) {
|
|
char *path = mo_compute_hot_path(win->current_hotlist->parent);
|
|
|
|
XmListDeleteAllItems(win->hotlist_list);
|
|
win->current_hotlist = win->current_hotlist->parent;
|
|
XmxTextSetString(win->hotlist_label, path);
|
|
free(path);
|
|
mo_load_hotlist_list(win, win->hotlist_list);
|
|
URL_Include_Set(win,0,0);
|
|
}
|
|
break;
|
|
case 10:
|
|
/* Save in a file */
|
|
XmxSetUniqid (win->id);
|
|
if (!win->save_hotlist_win)
|
|
win->save_hotlist_win = XmxMakeFileSBDialog
|
|
(win->hotlist_win, "NCSA Mosaic: Save Current hotlist" ,
|
|
"Name for saved hotlist" , save_hot_cb, 0);
|
|
else
|
|
XmFileSelectionDoSearch (win->save_hotlist_win, NULL);
|
|
|
|
XmxManageRemanage (win->save_hotlist_win);
|
|
break;
|
|
case 11:
|
|
/* Load a hotlist file */
|
|
if (!win->load_hotlist_win)
|
|
{
|
|
Widget frame, workarea, tb;
|
|
|
|
XmxSetUniqid (win->id);
|
|
win->load_hotlist_win = XmxMakeFileSBDialog
|
|
(win->hotlist_win, "NCSA Mosaic: Load in Current hotlist" ,
|
|
"Name of file to open" , load_hot_cb, 0);
|
|
/* This makes a frame as a work area for the dialog box. */
|
|
XmxSetArg (XmNmarginWidth, 5);
|
|
XmxSetArg (XmNmarginHeight, 5);
|
|
frame = XmxMakeFrame (win->load_hotlist_win, XmxShadowEtchedIn);
|
|
XmxSetArg (XmNorientation, XmHORIZONTAL);
|
|
workarea = XmxMakeRadioBox (frame);
|
|
tb = XtVaCreateManagedWidget("toggle", xmToggleButtonGadgetClass,
|
|
workarea,
|
|
XtVaTypedArg, XmNlabelString,
|
|
XtRString, "Create new hotlist" , strlen("Create new hotlist" )+1,
|
|
XmNmarginHeight, 0,
|
|
XmNset, True, NULL);
|
|
XmxSetArg (XmNuserData, (XtArgVal)tb);
|
|
XmxSetValues (win->load_hotlist_win);
|
|
XtVaCreateManagedWidget("toggle", xmToggleButtonGadgetClass,
|
|
workarea,
|
|
XtVaTypedArg, XmNlabelString,
|
|
XtRString, "Load in current hotlist" , strlen("Load in current hotlist" )+1,
|
|
XmNmarginHeight, 0,
|
|
NULL);
|
|
}
|
|
else
|
|
XmFileSelectionDoSearch (win->load_hotlist_win, NULL);
|
|
|
|
XmxManageRemanage (win->load_hotlist_win);
|
|
break;
|
|
case 12:
|
|
/* Add selected to the RBM or take it away... */
|
|
{
|
|
Boolean rv;
|
|
int *pos_list;
|
|
int pos_cnt;
|
|
rv = XmListGetSelectedPos (win->hotlist_list, &pos_list, &pos_cnt);
|
|
if (rv && pos_cnt)
|
|
{
|
|
mo_rbm_toggle_in_hotlist(win,pos_list[0]);
|
|
XtFree((char *)pos_list); /* DXP */
|
|
mo_write_default_hotlist();
|
|
}
|
|
else
|
|
{
|
|
XmxMakeErrorDialog
|
|
(win->hotlist_win, "No entry in the hotlist is currently selected.\n\nTo edit an entry in the hotlist,\nselect it with a single mouse click\nand press the Edit button again." , "Error: Nothing Selected" );
|
|
XtManageChild (Xmx_w);
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
return;
|
|
}
|
|
|
|
static XmxCallback (hotlist_list_cb)
|
|
{
|
|
mo_window *win = mo_fetch_window_by_id (XmxExtractUniqid ((int)client_data));
|
|
XmListCallbackStruct *cs = (XmListCallbackStruct *)call_data;
|
|
|
|
URL_Include_Set(win,0,0);
|
|
|
|
mo_visit_hotlist_position (win, cs->item_position);
|
|
|
|
/* Don't unmanage the list. */
|
|
|
|
return;
|
|
}
|
|
|
|
/* ------------------------- mo_post_hotlist_win -------------------------- */
|
|
|
|
/*
|
|
* Pop up a hotlist window for an mo_window.
|
|
*/
|
|
mo_status mo_post_hotlist_win (mo_window *win)
|
|
{
|
|
if (!win->hotlist_win)
|
|
{
|
|
Widget dialog_frame/*, toto*/;
|
|
Widget dialog_sep, buttons_form, buttons1_form, buttons2_form;
|
|
Widget hotlist_form/*, buttons1_frame*/;
|
|
XtTranslations listTable;
|
|
static char listTranslations[] =
|
|
"~Shift ~Ctrl ~Meta ~Alt <Btn2Down>: ListBeginSelect() \n\
|
|
Button2<Motion>: ListButtonMotion()\n\
|
|
~Shift ~Ctrl ~Meta ~Alt <Btn2Up>: ListBeginSelect() ListEndSelect()";
|
|
|
|
listTable = XtParseTranslationTable(listTranslations);
|
|
|
|
/* Create it for the first time. */
|
|
XmxSetUniqid (win->id);
|
|
XmxSetArg (XmNwidth, 475);
|
|
XmxSetArg (XmNheight, 342);
|
|
win->hotlist_win = XmxMakeFormDialog
|
|
(win->base, "NCSA Mosaic: Hotlist View" );
|
|
dialog_frame = XmxMakeFrame (win->hotlist_win, XmxShadowOut);
|
|
|
|
/* Constraints for base. */
|
|
XmxSetConstraints
|
|
(dialog_frame, XmATTACH_FORM, XmATTACH_FORM,
|
|
XmATTACH_FORM, XmATTACH_FORM, NULL, NULL, NULL, NULL);
|
|
|
|
/* Main form. */
|
|
hotlist_form = XmxMakeForm (dialog_frame);
|
|
|
|
win->current_hotlist = (mo_hotlist *)default_hotlist;
|
|
XmxSetArg (XmNcursorPositionVisible, False);
|
|
XmxSetArg (XmNeditable, False);
|
|
XmxSetArg (XmNvalue, (XtArgVal)"/");
|
|
win->hotlist_label = XmxMakeTextField(hotlist_form);
|
|
|
|
buttons1_form = XmxMakeFormAndFourButtons
|
|
(hotlist_form, hotlist_win_cb, "Add Current" ,
|
|
"Goto URL" , "Remove" ,
|
|
"Edit" , 3, 4, 5, 6);
|
|
buttons2_form = XmxMakeFormAndThreeButtons
|
|
(hotlist_form, hotlist_win_cb, "Copy" ,
|
|
"Insert" , "Up" ,
|
|
7, 8, 9);
|
|
XmxSetArg (XmNfractionBase, (XtArgVal)4);
|
|
XmxSetArg (XmNverticalSpacing, (XtArgVal)0);
|
|
XmxSetValues(buttons2_form);
|
|
|
|
/* Hotlist list itself. */
|
|
XmxSetArg (XmNresizable, False);
|
|
XmxSetArg (XmNscrollBarDisplayPolicy, XmSTATIC);
|
|
XmxSetArg (XmNlistSizePolicy, XmCONSTANT);
|
|
win->hotlist_list =
|
|
XmxMakeScrolledList (hotlist_form, hotlist_list_cb, 0);
|
|
XtAugmentTranslations (win->hotlist_list, listTable);
|
|
XtAddCallback(win->hotlist_list,
|
|
XmNbrowseSelectionCallback, hotlist_rbm_toggle_cb,
|
|
0);
|
|
|
|
win->hotlist_rbm_toggle=XmxMakeToggleButton(hotlist_form,
|
|
"Include On Right Button Menu",
|
|
hotlist_win_cb,
|
|
12);
|
|
URL_Include_Set(win,0,0);
|
|
|
|
dialog_sep = XmxMakeHorizontalSeparator (hotlist_form);
|
|
|
|
buttons_form = XmxMakeFormAndFiveButtons(hotlist_form,
|
|
hotlist_win_cb,
|
|
"Mail To...",
|
|
"Save",
|
|
"Load",
|
|
"Dismiss",
|
|
"Help...",
|
|
1,
|
|
10,
|
|
11,
|
|
0,
|
|
2);
|
|
|
|
/* Constraints for hotlist_form. */
|
|
/* buttons1_form: top to nothing, bottom to hotlist_list,
|
|
left to form, right to form. */
|
|
XmxSetOffsets (win->hotlist_label, 4, 0, 2, 2);
|
|
XmxSetConstraints
|
|
(win->hotlist_label, XmATTACH_FORM, XmATTACH_NONE, XmATTACH_FORM,
|
|
XmATTACH_FORM, NULL, NULL, NULL, NULL);
|
|
XmxSetOffsets (buttons1_form, 0, 0, 0, 0);
|
|
XmxSetConstraints
|
|
(buttons1_form,
|
|
XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_FORM,
|
|
win->hotlist_label, NULL, NULL, NULL);
|
|
XmxSetOffsets (buttons2_form, 0, 2, 0, 0);
|
|
XmxSetConstraints
|
|
(buttons2_form,
|
|
XmATTACH_WIDGET, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_FORM,
|
|
buttons1_form, NULL, NULL, NULL);
|
|
/* list: top to form, bottom to rbm_toggle,
|
|
etc... */
|
|
XmxSetOffsets (XtParent (win->hotlist_list), 10, 10, 8, 8);
|
|
XmxSetConstraints
|
|
(XtParent (win->hotlist_list),
|
|
XmATTACH_WIDGET, XmATTACH_WIDGET, XmATTACH_FORM, XmATTACH_FORM,
|
|
buttons2_form, win->hotlist_rbm_toggle, NULL, NULL);
|
|
XmxSetOffsets (win->hotlist_rbm_toggle, 0, 10, 6, 6);
|
|
XmxSetConstraints
|
|
(win->hotlist_rbm_toggle,
|
|
XmATTACH_NONE, XmATTACH_WIDGET, XmATTACH_FORM, XmATTACH_NONE,
|
|
NULL, dialog_sep, NULL, NULL);
|
|
XmxSetConstraints
|
|
(dialog_sep,
|
|
XmATTACH_NONE, XmATTACH_WIDGET, XmATTACH_FORM, XmATTACH_FORM,
|
|
NULL, buttons_form, NULL, NULL);
|
|
XmxSetConstraints
|
|
(buttons_form, XmATTACH_NONE, XmATTACH_FORM, XmATTACH_FORM,
|
|
XmATTACH_FORM,
|
|
NULL, NULL, NULL, NULL);
|
|
win->save_hotlist_win = win->load_hotlist_win = NULL;
|
|
win->hot_cut_buffer = NULL;
|
|
/* Go get the hotlist up to this point set up... */
|
|
mo_load_hotlist_list (win, win->hotlist_list);
|
|
}
|
|
|
|
XmxManageRemanage (win->hotlist_win);
|
|
|
|
return mo_succeed;
|
|
}
|
|
|
|
/* -------------------- mo_add_node_to_current_hotlist -------------------- */
|
|
|
|
mo_status mo_add_node_to_current_hotlist (mo_window *win)
|
|
{
|
|
if (!win->hotlist_win)
|
|
win->current_hotlist = (mo_hotlist *)default_hotlist;
|
|
return mo_add_item_to_hotlist (win->current_hotlist, mo_t_url,
|
|
win->current_node->title,
|
|
win->current_node->url, 0,
|
|
get_pref_boolean(eADD_HOTLIST_ADDS_RBM));
|
|
}
|
|
|
|
|
|
void mo_init_hotmenu()
|
|
{
|
|
mo_init_hotlist_menu((mo_hotlist *) default_hotlist);
|
|
}
|
|
|
|
void mo_reinit_hotmenu()
|
|
{
|
|
mo_reinit_hotlist_menu((mo_hotlist *) default_hotlist);
|
|
}
|
|
|
|
void mo_rbm_myself_to_death(mo_window *win, int val) {
|
|
|
|
RecursiveSetList(win,(mo_hotlist *)default_hotlist,val,1);
|
|
mo_reinit_hotmenu();
|
|
}
|