#line 41 "hotlist.c-nw" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "add.xpm" #include "add1.xpm" #include "open.xpm" #include "open1.xpm" #include "delete.xpm" #include "delete1.xpm" #include "hotlist.xpm" #define ADD_CURRENT 1 /* Codes for doHotlist() */ #define OPEN_DIALOG 2 #define HOTLIST_NAME ".argo_hotlist" #define MAGIC "ncsa-xmosaic-hotlist-format-1\nDefault\n" #ifndef PATH_MAX #define PATH_MAX 1024 #endif #define INCR 256 #define max(a, b) ((a) > (b) ? (a) : (b)) typedef struct {char *title, *url, *time;} *ListType; static W3ADocumentInfo *curdoc = NULL; static Widget dialog = NULL, listw = NULL; static ListType list = NULL; static int nritems = 0; static Bool file_has_been_read = FALSE; static char *filename = HOTLIST_NAME; /* hotlistname -- return absolute pathname of hotlist file */ static char *hotlistname(void) { static char s[PATH_MAX]; struct passwd *pw; if (filename[0] == '/') strcpy(s, filename); else if ((pw = getpwnam(getlogin())) || (pw = getpwuid(getuid()))) sprintf(s, "%s/%s", pw->pw_dir, filename); else strcpy(s, filename); return s; } #line 111 "hotlist.c-nw" /* add_current -- append URL of current document to the hotlist file */ static Bool add_current(void) { struct stat statbuf; char s[PATH_MAX + 50]; XmString ms; time_t tm; FILE *f; if (curdoc == NULL) return FALSE; tm = time(NULL); /* Add it to the in-memory list if that list exists */ if (file_has_been_read) { renewarray(list, nritems + 1); list[nritems].title = newstring(curdoc->title ? curdoc->title : curdoc->url); list[nritems].url = newstring(curdoc->url); list[nritems].time = newstring(ctime(&tm)); nritems++; } /* Add it to the list widget in the dialog, if it exists */ if (listw) { ms = XmStringCreateLocalized (curdoc->title ? curdoc->title : curdoc->url); XmListAddItem(listw, ms, 0); XmStringFree(ms); } /* Append it to the hotlist file */ if (stat(hotlistname(), &statbuf) != 0) { /* File exists? */ if (! (f = fopen(hotlistname(), "w"))) { /* Create it */ sprintf(s, "Couldn't create %s", hotlistname()); XtAppWarning(XtWidgetToApplicationContext(W3Atoplevel()), s); return FALSE; } fputs(MAGIC, f); } else if (! (f = fopen(hotlistname(), "a"))) { sprintf(s, "Couldn't write %s", hotlistname()); XtAppWarning(XtWidgetToApplicationContext(W3Atoplevel()), s); return FALSE; } fprintf(f, "%s %s%s%s\n", curdoc->url, ctime(&tm), curdoc->title ? "" : "Untitled: ", curdoc->title ? curdoc->title : curdoc->url); fclose(f); return TRUE; } /* read_hotlist -- read the hotlist file into list */ static Bool read_hotlist(void) { char s[PATH_MAX + 50], line[BUFSIZ], url[BUFSIZ], title[BUFSIZ]; char time[BUFSIZ]; FILE *f; int listlen = 0; if (! (f = fopen(hotlistname(), "r")) || ! fgets(line, sizeof(line), f)) { /* File doesn't exist, or empty file (probably...) */ fclose(f); file_has_been_read = TRUE; return TRUE; } if (! eq(line, "ncsa-xmosaic-hotlist-format-1\n") || ! fgets(line, sizeof(line), f) || ! eq(line, "Default\n")) { fclose(f); sprintf(s, "File is not a hotlist: %s", hotlistname()); XtAppWarning(XtWidgetToApplicationContext(W3Atoplevel()), s); return FALSE; } while (fscanf(f, " %s %[^\n] %[^\n]", url, time, title) == 3) { if (listlen != ((nritems + INCR)/INCR) * INCR) { listlen = ((nritems + INCR)/INCR) * INCR; renewarray(list, listlen); } list[nritems].url = newstring(url); list[nritems].title = newstring(title); list[nritems].time = newstring(time); nritems++; } fclose(f); file_has_been_read = TRUE; return TRUE; } /* rewrite_hotlist_file -- write the whole hotlist file anew */ static void rewrite_hotlist_file(void) { char s[PATH_MAX + 50]; FILE *f; int i; if (! (f = fopen(hotlistname(), "w"))) { sprintf(s, "Couldn't write %s", hotlistname()); XtAppWarning(XtWidgetToApplicationContext(W3Atoplevel()), s); return; } fputs(MAGIC, f); for (i = 0; i < nritems; i++) fprintf(f, "%s %s\n%s\n", list[i].url, list[i].time, list[i].title); fclose(f); } /* open_document_cb -- handle a double click on a list item */ static void open_document_cb(Widget w, XtPointer client_data, XtPointer call_data) { W3ADocumentInfo *doc; int *selected, nrselected, item; #if 1 XtPopdown(dialog); #endif if (XmListGetSelectedPos(listw, &selected, &nrselected)) { item = selected[0] - 1; XtFree((char *) selected); doc = new_doc(); doc->url = newstring(list[item].url); doc->title = newstring(list[item].title); (void) W3Aprocess(doc, GET_METHOD, NULL, 0); dispose_doc(doc); } } /* add_cb -- handle a click on the `add current' button */ static void add_cb(Widget w, XtPointer client_data, XtPointer call_data) { (void) add_current(); } /* cancel_cb -- handle a click on the `cancel' button */ static void cancel_cb(Widget w, XtPointer client_data, XtPointer call_data) { #if 1 XtPopdown(dialog); #endif } /* delete_cb -- handle a click on the `delete' button */ static void delete_cb(Widget w, XtPointer client_data, XtPointer call_data) { int *selected, nrselected, i; assert(listw != NULL); if (XmListGetSelectedPos(listw, &selected, &nrselected)) { assert(list != NULL); XmListDeletePos(listw, selected[0]); assert(selected[0] <= nritems); for (i = selected[0]; i < nritems; i++) list[i-1] = list[i]; nritems--; rewrite_hotlist_file(); XtFree((char *) selected); } } /* create_dialog -- create the dialog box, install callbacks */ static Bool create_dialog(void) { Widget formw, addw, gotow, cancelw, deletew; Atom WM_Delete_Window; XmString ms; int i; #if 0 dialog = XtVaCreatePopupShell("hotlist", xmDialogShellWidgetClass, W3Atoplevel(), XtNtitle, "Hotlist", NULL); #else dialog = XtVaCreatePopupShell("hotlist", transientShellWidgetClass, W3Atoplevel(), XtNtitle, "Hotlist", NULL); #endif formw = XtVaCreateManagedWidget ("form", xmFormWidgetClass, dialog, XmNmarginHeight, 10, XmNmarginWidth, 10, XmNhorizontalSpacing, 10, XmNverticalSpacing, 10, NULL); addw = XmCreatePixmapPushButtonGadget (formw, "add current", add, add1, NULL, NULL, 0); XtManageChild(addw); gotow = XmCreatePixmapPushButtonGadget (formw, "open", open, open1, NULL, NULL, 0); XtManageChild(gotow); deletew = XmCreatePixmapPushButtonGadget (formw, "delete", delete, delete1, NULL, NULL, 0); XtManageChild(deletew); #if 0 cancelw = XtVaCreateManagedWidget ("cancel", xmPushButtonGadgetClass, formw, NULL); #else cancelw = XmCreateStandardPushButtonGadget (formw, "cancel", XmPUSHBUTTON_CANCEL, NULL, 0); XtManageChild(cancelw); #endif listw = XmCreateScrolledList(formw, "list", NULL, 0); XtManageChild(listw); XtAddCallback(addw, XmNactivateCallback, add_cb, NULL); XtAddCallback(gotow, XmNactivateCallback, open_document_cb, NULL); XtAddCallback(deletew, XmNactivateCallback, delete_cb, NULL); XtAddCallback(cancelw, XmNactivateCallback, cancel_cb, NULL); XtAddCallback(listw, XmNdefaultActionCallback, open_document_cb, NULL); XtVaSetValues (XtParent(listw), XmNleftAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_WIDGET, XmNrightWidget, addw, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, NULL); XtVaSetValues (addw, XmNtopAttachment, XmATTACH_FORM, XmNrightAttachment, XmATTACH_FORM, NULL); XtVaSetValues (gotow, XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET, XmNleftWidget, addw, XmNleftOffset, 0, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, addw, XmNrightAttachment, XmATTACH_FORM, NULL); XtVaSetValues (deletew, XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET, XmNleftWidget, gotow, XmNleftOffset, 0, XmNtopAttachment, XmATTACH_WIDGET, XmNtopWidget, gotow, XmNrightAttachment, XmATTACH_FORM, NULL); XtVaSetValues (cancelw, XmNleftAttachment, XmATTACH_OPPOSITE_WIDGET, XmNleftWidget, deletew, XmNleftOffset, 0, XmNrightAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_FORM, NULL); /* Intercept the WM_DELETE_WINDOW protocol */ XtVaSetValues(dialog, XmNdeleteResponse, XmUNMAP, NULL); XtVaSetValues(formw, XmNcancelButton, cancelw, NULL); for (i = 0; i < nritems; i++) { ms = XmStringCreateLocalized(list[i].title); XmListAddItem(listw, ms, 0); XmStringFree(ms); } return TRUE; } /* open_dialog -- open a dialog and let users select a hotlist entry */ static Bool open_dialog(int mid_x, int mid_y) { int width, height; if (! file_has_been_read && ! read_hotlist()) return FALSE; if (! dialog && ! create_dialog()) return FALSE; XtVaGetValues(dialog, XmNwidth, &width, XmNheight, &height, NULL); XtVaSetValues(dialog, XmNx, max(0, mid_x - width/2), XmNy, max(0, mid_y - height/2), NULL); #if 1 XtPopup(dialog, XtGrabNonexclusive); #else XtManageChild(dialog); #endif return TRUE; } EXPORT Bool initHotlist(long id, char ***labels, ThreeIcons *icons_data[], int *nrlabels) { static char *labs[] = { "Add current to hotlist", "Hotlist"}; #if 0 static char **data[][3] = { /* 3 icons per label */ {add, add1, NULL}, {hotlist, NULL, NULL}}; #else static ThreeIcons data[] = { /* 3 icons per label */ {add, add1, NULL}, {hotlist, NULL, NULL}}; #endif *labels = labs; *icons_data = data; *nrlabels = XtNumber(labs); return True; } EXPORT Bool doHotlist(int code, int mid_x, int mid_y) { switch (code) { case ADD_CURRENT: return add_current(); case OPEN_DIALOG: return open_dialog(mid_x, mid_y); default: assert(! "Cannot happen"); } } EXPORT void eventHotlist(long sourceid, long eventtype, void *params) { if (eventtype == NEW_DOCUMENT) { if (curdoc) dispose_doc(curdoc); curdoc = new_doc(); copy_doc(curdoc, *((W3ADocumentInfo *) params)); } }