/* * bookmark.c * * Copyright (c) 1996-1997, John Kilburg * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "port_before.h" #include #ifdef HAVE_STRING_H #include #endif #include #include #include #include #include #include #include #include #include #include #include "port_after.h" #include "ChimeraP.h" #include "ml.h" #include "MyDialog.h" typedef struct { char *title; char *url; } BMark; typedef struct { char *name; GList mlist; } BGroup; struct BookmarkContextP { MemPool mp; GList glist; GList nel; /* name element list

or */ bool is_group_element; bool is_mark_element; MLState ml; char *filename; /* bookmark filename */ Widget bw; /* bookmark shell widget */ Widget glw; Widget mlw; Widget ampop; bool ampopped; Widget agpop; bool agpopped; char **gnames; /* group name array for list widget */ int glen; char **mnames; /* bookmark array for list widget */ int mlen; char *header; char *footer; ChimeraResources cres; }; static BGroup *GroupCreate _ArgProto((BookmarkContext, char *, bool)); static void BMChangeGroupList _ArgProto((BookmarkContext)); static void BMChangeMarkList _ArgProto((BookmarkContext)); static BGroup *BMFindGroup _ArgProto((BookmarkContext)); static BMark *BMFindMark _ArgProto((BookmarkContext)); static void BMWrite _ArgProto((BookmarkContext)); static void BMCreate _ArgProto((BookmarkContext, BGroup *, char *, char *)); static void BMElementHandler _ArgProto((void *, MLElement)); static char *BMGetText _ArgProto((MemPool, GList)); static void BMDAddGroup _ArgProto((Widget, XtPointer, XtPointer)); static void BMDAddMark _ArgProto((Widget, XtPointer, XtPointer)); /* * BMChangeGroupList */ static void BMChangeGroupList(bc) BookmarkContext bc; { int cnt; BGroup *g; for (cnt = 0, g = (BGroup *)GListGetHead(bc->glist); g != NULL; cnt++, g = (BGroup *)GListGetNext(bc->glist)) { ; } if (bc->gnames == NULL) { bc->gnames = (char **)alloc_mem(sizeof(char *) * (cnt + 1)); bc->glen = cnt; } else if (bc->glen < cnt) { bc->gnames = (char **)realloc_mem(bc->gnames, sizeof(char *) * (cnt + 1)); bc->glen = cnt; } for (g = (BGroup *)GListGetHead(bc->glist), cnt = 0; g != NULL; g = (BGroup *)GListGetNext(bc->glist)) { bc->gnames[cnt++] = g->name; } bc->gnames[cnt] = NULL; XawListChange(bc->glw, bc->gnames, 0, 0, True); if (cnt > 0) XawListHighlight(bc->glw, 0); BMChangeMarkList(bc); return; } /* * BMChangeMarkList */ static void BMChangeMarkList(bc) BookmarkContext bc; { int cnt; BMark *m; BGroup *g; if ((g = BMFindGroup(bc)) == NULL) return; for (cnt = 0, m = (BMark *)GListGetHead(g->mlist); m != NULL; cnt++, m = (BMark *)GListGetNext(g->mlist)) { ; } if (bc->mnames == NULL) { bc->mnames = (char **)alloc_mem(sizeof(char *) * (cnt + 2)); bc->mlen = cnt; } else if (bc->mlen < cnt) { bc->mnames = (char **)realloc_mem(bc->mnames, sizeof(char *) * (cnt + 2)); bc->mlen = cnt; } for (m = (BMark *)GListGetHead(g->mlist), cnt = 0; m != NULL; m = (BMark *)GListGetNext(g->mlist)) { bc->mnames[cnt++] = m->title; } if (cnt > 0) { bc->mnames[cnt] = NULL; XawListChange(bc->mlw, bc->mnames, 0, 0, True); XawListHighlight(bc->mlw, 0); } else { bc->mnames[cnt] = ""; bc->mnames[cnt + 1] = NULL; XawListChange(bc->mlw, bc->mnames, 0, 0, True); } return; } /* * BMWrite */ static void BMWrite(bc) BookmarkContext bc; { FILE *fp; const char *brec = "
  • %s\n"; BMark *c; BGroup *g; if ((fp = fopen(bc->filename, "w")) != NULL) { fprintf (fp, bc->header); fprintf (fp, "\n"); for (g = (BGroup *)GListGetHead(bc->glist); g != NULL; g = (BGroup *)GListGetNext(bc->glist)) { fprintf (fp, "

    %s

    \n
      \n", g->name); for (c = (BMark *)GListGetHead(g->mlist); c != NULL; c = (BMark *)GListGetNext(g->mlist)) { fprintf (fp, brec, c->url, c->title); } fprintf (fp, "
    \n"); } fprintf (fp, bc->footer); fprintf (fp, "\n"); fclose(fp); } return; } /* * GroupCreate */ static BGroup * GroupCreate(bc, group, top) BookmarkContext bc; char *group; bool top; { BGroup *g; g = (BGroup *)MPCGet(bc->mp, sizeof(BGroup)); g->name = MPStrDup(bc->mp, group); g->mlist = GListCreateX(bc->mp); if (top) GListAddHead(bc->glist, g); else GListAddTail(bc->glist, g); BMChangeGroupList(bc); return(g); } /* * BMCreate */ static void BMCreate(bc, g, title, url) BookmarkContext bc; BGroup *g; char *title; char *url; { BMark *n; n = (BMark *)MPCGet(bc->mp, sizeof(BMark)); n->url = MPStrDup(bc->mp, url); if (title == NULL) n->title = MPStrDup(bc->mp, url); else n->title = MPStrDup(bc->mp, title); GListAddTail(g->mlist, n); BMChangeMarkList(bc); return; } /* * BMGetText */ static char * BMGetText(mp, list) MemPool mp; GList list; { MLElement c; char *text, *str; size_t tlen = 0; size_t len; if (GListEmpty(list)) return(NULL); /* Skip first element...it is the opening tag */ GListGetHead(list); for (c = (MLElement)GListGetNext(list); c != NULL; c = (MLElement)GListGetNext(list)) { MLGetText(c, &str, &len); tlen += len; } text = MPGet(mp, tlen + 1); tlen = 0; GListGetHead(list); for (c = (MLElement)GListGetNext(list); c != NULL; c = (MLElement)GListGetNext(list)) { MLGetText(c, &str, &len); strncpy(text + tlen, str, len); tlen += len; } text[tlen] = '\0'; return(text); } /* * BMElementHandler */ static void BMElementHandler(closure, p) void *closure; MLElement p; { BookmarkContext bc = (BookmarkContext)closure; char *value; char *title; char *name; MLElementType mt; MLElement h; mt = MLGetType(p); if (mt == ML_EOF) return; if ((name = MLTagName(p)) == NULL) { if (bc->is_group_element || bc->is_mark_element) GListAddTail(bc->nel, p); return; } if (strlen(name) == 2 && strcasecmp("h3", name) == 0) { if (MLGetType(p) == ML_ENDTAG) { if (bc->is_group_element) { GroupCreate(bc, BMGetText(bc->mp, bc->nel), false); bc->is_group_element = false; } } else { bc->is_group_element = true; GListClear(bc->nel); GListAddHead(bc->nel, p); } } else if (strlen(name) == 1 && strcasecmp("a", name) == 0) { if (MLGetType(p) == ML_ENDTAG) { if (bc->is_mark_element) { bc->is_mark_element = false; h = (MLElement)GListGetHead(bc->nel); if (h == NULL) return; if ((value = MLFindAttribute(h, "href")) != NULL) { title = BMGetText(bc->mp, bc->nel); if (title == NULL || title[0] == '\0') { title = MPStrDup(bc->mp, value); } if (GListEmpty(bc->glist)) GroupCreate(bc, "default", true); BMCreate(bc, (BGroup *)GListGetTail(bc->glist), title, MPStrDup(bc->mp, value)); } } } else { bc->is_mark_element = true; GListClear(bc->nel); GListAddHead(bc->nel, p); } } return; } /* * BookmarkAdd */ void BookmarkAdd(bc, title, url) BookmarkContext bc; char *title; char *url; { BGroup *g; if ((g = BMFindGroup(bc)) == NULL) return; BMCreate(bc, g, title, url); return; } /* * BookmarkDestroyContext */ void BookmarkDestroyContext(bc) BookmarkContext bc; { XtDestroyWidget(bc->bw); if (bc->mnames != NULL) free_mem(bc->mnames); if (bc->gnames != NULL) free_mem(bc->gnames); MPDestroy(bc->mp); return; } /* * BookmarkShow */ void BookmarkShow(bc) BookmarkContext bc; { XtMapWidget(bc->bw); return; } /* * BMFindGroup */ static BGroup * BMFindGroup(bc) BookmarkContext bc; { int i; BGroup *g; XawListReturnStruct *lrs; if ((lrs = XawListShowCurrent(bc->glw)) == NULL) return(NULL); if (lrs->list_index < 0) return(NULL); for (i = 0, g = (BGroup *)GListGetHead(bc->glist); i < lrs->list_index && g != NULL; i++, g = (BGroup *)GListGetNext(bc->glist)) { ; } return(g); } /* * BMFindMark */ static BMark * BMFindMark(bc) BookmarkContext bc; { int i; BMark *m; BGroup *g; XawListReturnStruct *lrs; if ((g = BMFindGroup(bc)) == NULL) return(NULL); if ((lrs = XawListShowCurrent(bc->mlw)) == NULL) return(NULL); if (lrs->list_index < 0) return(NULL); for (i = 0, m = (BMark *)GListGetHead(g->mlist); i < lrs->list_index && m != NULL; i++, m = (BMark *)GListGetNext(g->mlist)) { ; } return(m); } /* * BMDAddGroup */ static void BMDAddGroup(w, cldata, cbdata) Widget w; XtPointer cldata, cbdata; { BookmarkContext bc = (BookmarkContext)cldata; XtPopdown(bc->agpop); bc->agpopped = false; return; } /* * BMOAddGroup */ static void BMOAddGroup(w, cldata, cbdata) Widget w; XtPointer cldata, cbdata; { BookmarkContext bc = (BookmarkContext)cldata; char *name; if ((name = MyDialogGetValue(GetDialogWidget(bc->agpop))) == NULL || name[0] == '\0') { return; } GroupCreate(bc, name, true); BMDAddGroup(w, cldata, cbdata); BMWrite(bc); return; } /* * BMAddGroup */ static void BMAddGroup(w, cldata, cbdata) Widget w; XtPointer cldata, cbdata; { BookmarkContext bc = (BookmarkContext)cldata; if (bc->agpopped) return; if (bc->agpop == NULL) { bc->agpop = CreateDialog(bc->bw, "agpop", BMOAddGroup, BMDAddGroup, BMOAddGroup, bc); } MyDialogSetValue(GetDialogWidget(bc->agpop), ""); XtPopup(bc->agpop, XtGrabNone); bc->agpopped = true; return; } /* * BMRMGroup */ static void BMRMGroup(w, cldata, cbdata) Widget w; XtPointer cldata, cbdata; { BookmarkContext bc = (BookmarkContext)cldata; BGroup *g; if ((g = BMFindGroup(bc)) != NULL) { GListRemoveItem(bc->glist, g); if (GListEmpty(bc->glist)) GroupCreate(bc, "default", true); BMChangeGroupList(bc); BMChangeMarkList(bc); BMWrite(bc); } return; } /* * BMDAddMark */ static void BMDAddMark(w, cldata, cbdata) Widget w; XtPointer cldata, cbdata; { BookmarkContext bc = (BookmarkContext)cldata; XtPopdown(bc->ampop); bc->ampopped = false; return; } /* * BMOAddMark */ static void BMOAddMark(w, cldata, cbdata) Widget w; XtPointer cldata, cbdata; { BookmarkContext bc = (BookmarkContext)cldata; char *name; char *url; if ((name = MyDialogGetValue(GetDialogWidget(bc->ampop))) == NULL || name[0] == '\0') { return; } if ((url = StackGetCurrentURL(bc->cres->bmcontext->tstack)) != NULL) { BookmarkAdd(bc, name, url); } BMDAddMark(w, cldata, cbdata); BMWrite(bc); return; } /* * BMAddMark */ static void BMAddMark(w, cldata, cbdata) Widget w; XtPointer cldata, cbdata; { BookmarkContext bc = (BookmarkContext)cldata; char *title; ChimeraRender wn; if (bc->ampopped) return; if (bc->cres->bmcontext == NULL) return; wn = StackToRender(bc->cres->bmcontext->tstack); if ((title = RenderQuery(wn, "title")) == NULL) { if ((title = StackGetCurrentURL(bc->cres->bmcontext->tstack)) == NULL) { title = "unknown"; } } if (bc->ampop == NULL) { bc->ampop = CreateDialog(bc->bw, "ampop", BMOAddMark, BMDAddMark, BMOAddMark, bc); } MyDialogSetValue(GetDialogWidget(bc->ampop), title); XtPopup(bc->ampop, XtGrabNone); bc->ampopped = true; return; } /* * BMRMMark */ static void BMRMMark(w, cldata, cbdata) Widget w; XtPointer cldata, cbdata; { BookmarkContext bc = (BookmarkContext)cldata; BMark *m; BGroup *g; if ((g = BMFindGroup(bc)) == NULL) return; if ((m = BMFindMark(bc)) != NULL) { GListRemoveItem(g->mlist, m); BMChangeMarkList(bc); BMWrite(bc); } return; } /* * BMDismiss */ static void BMDismiss(w, cldata, cbdata) Widget w; XtPointer cldata, cbdata; { BookmarkContext bc = (BookmarkContext)cldata; if (bc->ampop != NULL) XtPopdown(bc->ampop); if (bc->agpop != NULL) XtPopdown(bc->agpop); XtUnmapWidget(bc->bw); return; } /* * BMGroupList */ static void BMGroupList(w, cldata, cbdata) Widget w; XtPointer cldata, cbdata; { BookmarkContext bc = (BookmarkContext)cldata; BMChangeMarkList(bc); return; } /* * BMMarkList */ static void BMMarkList(w, cldata, cbdata) Widget w; XtPointer cldata, cbdata; { BookmarkContext bc = (BookmarkContext)cldata; BMark *m; if ((m = BMFindMark(bc)) == NULL) return; StackOpen(bc->cres->bmcontext->tstack, RequestCreate(bc->cres, m->url, NULL)); return; } /* * BookmarkCreateContext */ BookmarkContext BookmarkCreateContext(cres) ChimeraResources cres; { Widget fw, w, gvw, mvw; BookmarkContext bc; struct stat s; FILE *fp; char *bdata; char *filename; MemPool mp; Window rw, cw; int rx, ry, wx, wy; unsigned int mask; if ((filename = ResourceGetString(cres, "bookmark.filename")) == NULL) { return(NULL); } mp = MPCreate(); bc = (BookmarkContext)MPCGet(mp, sizeof(struct BookmarkContextP)); bc->mp = mp; bc->cres = cres; XQueryPointer(cres->dpy, DefaultRootWindow(cres->dpy), &rw, &cw, &rx, &ry, &wx, &wy, &mask); bc->bw = XtVaAppCreateShell("bookmark", "Bookmark", transientShellWidgetClass, cres->dpy, XtNx, rx, XtNy, ry, NULL); /* group widgets */ fw = XtVaCreateManagedWidget("form", formWidgetClass, bc->bw, NULL); gvw = XtVaCreateManagedWidget("groupview", viewportWidgetClass, fw, NULL); bc->glw = XtVaCreateManagedWidget("grouplist", listWidgetClass, gvw, NULL); XtAddCallback(bc->glw, XtNcallback, BMGroupList, (XtPointer)bc); w = XtVaCreateManagedWidget("addgroup", commandWidgetClass, fw, XtNfromVert, gvw, NULL); XtAddCallback(w, XtNcallback, BMAddGroup, (XtPointer)bc); w = XtVaCreateManagedWidget("rmgroup", commandWidgetClass, fw, XtNfromVert, gvw, XtNfromHoriz, w, NULL); XtAddCallback(w, XtNcallback, BMRMGroup, (XtPointer)bc); /* Mark widgets */ mvw = XtVaCreateManagedWidget("markview", viewportWidgetClass, fw, XtNfromVert, w, NULL); bc->mlw = XtVaCreateManagedWidget("marklist", listWidgetClass, mvw, NULL); XtAddCallback(bc->mlw, XtNcallback, BMMarkList, (XtPointer)bc); w = XtVaCreateManagedWidget("addmark", commandWidgetClass, fw, XtNfromVert, mvw, NULL); XtAddCallback(w, XtNcallback, BMAddMark, (XtPointer)bc); w = XtVaCreateManagedWidget("rmmark", commandWidgetClass, fw, XtNfromVert, mvw, XtNfromHoriz, w, NULL); XtAddCallback(w, XtNcallback, BMRMMark, (XtPointer)bc); w = XtVaCreateManagedWidget("dismiss", commandWidgetClass, fw, XtNfromVert, mvw, XtNfromHoriz, w, NULL); XtAddCallback(w, XtNcallback, BMDismiss, (XtPointer)bc); if ((bc->header = ResourceGetString(cres, "bookmark.header")) == NULL) { bc->header = ""; } if ((bc->footer = ResourceGetString(cres, "bookmark.footer")) == NULL) { bc->footer = ""; } bc->glist = GListCreateX(bc->mp); bc->nel = GListCreateX(bc->mp); bc->filename = FixPath(bc->mp, filename); if (stat(bc->filename, &s) == 0) { if ((fp = fopen(bc->filename, "r")) != NULL) { bdata = (char *)alloc_mem(s.st_size); if (fread(bdata, 1, s.st_size, fp) == s.st_size) { bc->ml = MLInit(BMElementHandler, bc); MLEndData(bc->ml, bdata, s.st_size); MLDestroy(bc->ml); } free_mem(bdata); fclose(fp); } } if (GListEmpty(bc->glist)) GroupCreate(bc, "default", true); XtSetMappedWhenManaged(bc->bw, False); XtRealizeWidget(bc->bw); return(bc); }