saving URL's

David C. Martin (dcmartin@library.ucsf.edu)
Thu, 15 Jul 1993 16:44:36 PDT


I have wanted to be able to save URL's for some time and have now hacked
Xmosaic to support this feature. This feature allows you to find a
document via navigation and then save the URL for that document in the
UNIX filesystem as a symbolic link (and, of course, open the local file
and have it interpreted as a URL).

Comments, bug fixes, etc... appreciated.

dcm

BTW: You need to -DCKM and add search.[co] to the Makefile.
--------
#!/bin/sh
# This is a shell archive (produced by shar 3.50)
# To extract the files from this archive, save it to a file, remove
# everything above the "!/bin/sh" line above, and type "sh file_name".
#
# made 07/15/1993 23:42 UTC by dcmartin@brasil
# Source directory /local/dcmartin/work/xmosaic-1.2/src
#
# existing files will NOT be overwritten unless -c is specified
#
# This shar contains:
# length mode name
# ------ ---------- ------------------------------------------
# 2909 -r--r--r-- search.c
# 9163 -rw-r--r-- gui2.c-dif
#
# ============= search.c ==============
if test -f 'search.c' -a X"$1" != X"-c"; then
echo 'x - skipping search.c (File already exists)'
else
echo 'x - extracting search.c (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'search.c' &&
/*
X * search.c -- alternate file search procedure
X *
X * Replaces the default file search procedure of a FileSelectionBoxWidget.
X * The default procedure skips over any matching symbolic links which
X * cannot be resolved (don't seem to point anywhere).
X *
X * This search procedure checks symbolic links (which match the given filter)
X * to see if they might encode a URL (Universal Resource Locator). Such links
X * are included in the resulting file list along with any other matching files.
X *
X *
X */
X
#include <stdio.h>
#include <Xm/Xm.h>
#include <Xm/FileSB.h>
#include <Xm/DialogS.h>
#include <Xm/PushBG.h>
#include <Xm/PushB.h>
#include <sys/stat.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/param.h>
X
extern char *re_comp();
extern int re_exec();
X
void alt_file_search_proc(fs, cbs)
Widget fs;
XXmFileSelectionBoxCallbackStruct* cbs;
{
X DIR* dir;
X char* dirbuf;
X char* patbuf;
X char* expbuf = alloca(BUFSIZ);
X int i = 0;
X
X /* convert to strings */
X if (XmStringGetLtoR(cbs->dir, XmSTRING_DEFAULT_CHARSET, &dirbuf)) {
X if (XmStringGetLtoR(cbs->pattern, XmSTRING_DEFAULT_CHARSET, &patbuf)) {
X /* fix up the regular expression */
X expbuf[i++] = '^';
X while (*patbuf) {
X switch(*patbuf) {
X case '*':
X expbuf[i++] = '.';
X expbuf[i++] = '*';
X break;
X case '.':
X expbuf[i++] = '\\';
X expbuf[i++] = '.';
X break;
X default:
X expbuf[i++] = *patbuf;
X break;
X }
X ++patbuf;
X }
X expbuf[i++] = '$';
X expbuf[i] = '\0';
X
X /* compile the reg exp */
X if (re_comp(expbuf) == NULL) {
X /* open the dirbuf */
X if ((dir = opendir(dirbuf)) != NULL) {
X struct dirent* ent;
X static int count = 0;
X static XmString names[256];
X
X while (count > 0) XmStringFree(names[count--]);
X while ((ent = readdir(dir)) != (struct dirent*) NULL) {
X if (re_exec(ent->d_name) == 1) {
X char path[MAXPATHLEN];
X struct stat stat_buf;
X
X (void) strcpy(path, dirbuf);
X (void) strcat(path, ent->d_name);
X if (lstat(path, &stat_buf) == 0) {
X if (S_ISREG(stat_buf.st_mode) ||
X S_ISLNK(stat_buf.st_mode)) {
X /* remember matching entries */
X names[count] = XmStringCreateSimple(path);
X /* only take the first 256 */
X if (++count == 256) break;
X }
X } else {
X perror("lstat");
X }
X }
X }
X /* update the file list */
X if (count > 0) {
X XtVaSetValues(fs,
X XmNfileListItems, names,
X XmNfileListItemCount, count,
X XmNdirSpec, names[0],
X XmNdirectoryValid, True,
X XmNlistUpdated, True,
X NULL);
X return;
X }
X }
X }
X }
X }
X XtVaSetValues(fs,
X XmNfileListItems, NULL,
X XmNfileListItemCount, 0,
X XmNdirectoryValid, False,
X XmNlistUpdated, False,
X NULL);
}
SHAR_EOF
chmod 0444 search.c ||
echo 'restore of search.c failed'
Wc_c="`wc -c < 'search.c'`"
test 2909 -eq "$Wc_c" ||
echo 'search.c: original size 2909, current size' "$Wc_c"
fi
# ============= gui2.c-dif ==============
if test -f 'gui2.c-dif' -a X"$1" != X"-c"; then
echo 'x - skipping gui2.c-dif (File already exists)'
else
echo 'x - extracting gui2.c-dif (Text)'
sed 's/^X//' << 'SHAR_EOF' > 'gui2.c-dif' &&
*** 1.1 1993/06/30 19:33:21
--- gui2.c 1993/07/15 00:35:44
***************
*** 54,59 ****
--- 54,76 ----
X
X #include "mosaic.h"
X
+ /*
+ * Include these for symbolic link encoded URL's
+ */
+ #ifdef CKM
+ #include <sys/stat.h>
+ #include <sys/param.h>
+ #endif
+
+ #ifdef CKM
+
+ /*
+ * Alternate file searching procedure
+ */
+ extern void alt_file_search_proc();
+
+ #endif
+
X #include <Xm/LabelG.h>
X #include <Xm/PushB.h>
X #include <Xm/ScrolledW.h>
***************
*** 74,80 ****
X
X typedef enum
X {
! mo_plaintext = 0, mo_formatted_text, mo_html, mo_latex, mo_postscript,
X mo_mif
X } mo_format_token;
X
--- 91,102 ----
X
X typedef enum
X {
! mo_plaintext = 0,
! mo_url,
! mo_formatted_text,
! mo_html,
! mo_latex,
! mo_postscript,
X mo_mif
X } mo_format_token;
X
***************
*** 83,88 ****
--- 105,111 ----
X { "Plain Text", mo_plaintext, XmxSet },
X { "Formatted Text", mo_formatted_text, XmxNotSet },
X { "PostScript", mo_postscript, XmxNotSet },
+ { "URL", mo_url, XmxNotSet },
X { "HTML", mo_html, XmxNotSet },
X { "LaTeX Source", mo_latex, XmxNotSet },
X { "Frame MIF", mo_mif, XmxNotSet },
***************
*** 102,172 ****
X
X static XmxCallback (save_win_cb)
X {
! char *fname = (char *)malloc (sizeof (char) * 128);
! FILE *fp;
! mo_window *win = mo_fetch_window_by_id
! (XmxExtractUniqid ((int)client_data));
!
! mo_busy ();
!
! XtUnmanageChild (win->save_win);
!
! XmStringGetLtoR (((XmFileSelectionBoxCallbackStruct *)call_data)->value,
! XmSTRING_DEFAULT_CHARSET,
! &fname);
!
! if (can_instrument && win->instrument_usage)
! mo_inst_register_action (mo_inst_save, win->current_node->url);
X
! fp = fopen (fname, "w");
! if (!fp)
! {
! XmxMakeErrorDialog (win->save_win,
! "Unable to save document.", "Save Error");
! XtManageChild (Xmx_w);
! }
! else
! {
! if (win->save_format == mo_plaintext)
! {
! char *text = HTMLGetText (win->view, 0);
! if (text)
! {
! fputs (text, fp);
! free (text);
! }
! }
! else if (win->save_format == mo_formatted_text)
! {
! char *text = HTMLGetText (win->view, 1);
! if (text)
! {
! fputs (text, fp);
! free (text);
! }
! }
! else if (win->save_format == mo_postscript)
! {
! char *text = HTMLGetText (win->view, 2);
! if (text)
! {
! fputs (text, fp);
! free (text);
! }
! }
! else if (win->current_node->text)
! {
! /* HTML source */
! fputs (win->current_node->text, fp);
! }
! fclose (fp);
! }
X
! mo_not_busy ();
X
! free (fname);
X
! return;
X }
X
X static XmxCallback (format_optmenu_cb)
--- 125,191 ----
X
X static XmxCallback (save_win_cb)
X {
! char* fname = (char*) calloc(128, sizeof (char));
! FILE* fp;
! mo_window* win;
X
! win = mo_fetch_window_by_id(XmxExtractUniqid((int)client_data));
X
! mo_busy ();
X
! XtUnmanageChild (win->save_win);
X
! XmStringGetLtoR (((XmFileSelectionBoxCallbackStruct *)call_data)->value,
! XmSTRING_DEFAULT_CHARSET,
! &fname);
!
! if (can_instrument && win->instrument_usage)
! mo_inst_register_action (mo_inst_save, win->current_node->url);
!
! if (win->save_format == mo_url) {
! /*
! * Save symbolic link encoded URL for document
! */
! if (symlink(win->current_node->url, fname) != 0) {
! XmxMakeErrorDialog (win->save_win,
! "Unable to save document.", "Save Error");
! XtManageChild (Xmx_w);
! }
! } else {
!
! if ((fp = fopen (fname, "w")) == NULL) {
! XmxMakeErrorDialog (win->save_win,
! "Unable to save document.", "Save Error");
! XtManageChild (Xmx_w);
! } else {
! if (win->save_format == mo_plaintext) {
! char *text = HTMLGetText (win->view, 0);
! if (text) {
! fputs (text, fp);
! free (text);
! }
! } else if (win->save_format == mo_formatted_text) {
! char *text = HTMLGetText (win->view, 1);
! if (text) {
! fputs (text, fp);
! free (text);
! }
! } else if (win->save_format == mo_postscript) {
! char *text = HTMLGetText (win->view, 2);
! if (text) {
! fputs (text, fp);
! free (text);
! }
! } else if (win->current_node->text) {
! /* HTML source */
! fputs (win->current_node->text, fp);
! }
! fclose (fp);
! }
! }
! mo_not_busy ();
! free (fname);
! return;
X }
X
X static XmxCallback (format_optmenu_cb)
***************
*** 189,194 ****
--- 208,223 ----
X (win->base, "NCSA Mosaic: Save Document", "Name for saved document:",
X save_win_cb, 0);
X
+ #ifdef CKM
+ /*
+ * Replace the current file-search procedure with one which
+ * knows about symbolic-link-encoded-URL's
+ */
+ XtVaSetValues (win->save_win,
+ XmNfileSearchProc, (XtArgVal) &alt_file_search_proc,
+ NULL);
+ #endif
+
X /* This makes a frame as a work area for the dialog box. */
X XmxSetArg (XmNmarginWidth, 5);
X XmxSetArg (XmNmarginHeight, 5);
***************
*** 298,344 ****
X
X static XmxCallback (open_local_win_cb)
X {
! char *fname = (char *)malloc (sizeof (char) * 128);
! char *url;
! mo_window *win = mo_fetch_window_by_id (XmxExtractUniqid ((int)client_data));
!
! XtUnmanageChild (win->open_local_win);
!
! XmStringGetLtoR (((XmFileSelectionBoxCallbackStruct *)call_data)->value,
! XmSTRING_DEFAULT_CHARSET,
! &fname);
X
! url = (char *)malloc
! ((strlen (fname) + strlen (shortmachine) + 16) * sizeof (char));
! sprintf (url, "file://%s%s\0", shortmachine, fname);
! if (url[strlen(url)-1] == '/')
! url[strlen(url)-1] = '\0';
! mo_load_window_text (win, url, NULL);
X
! free (fname);
!
! return;
X }
X
X mo_status mo_post_open_local_window (mo_window *win)
X {
! XmxSetUniqid (win->id);
! if (!win->open_local_win)
! {
! Widget frame, workarea, format_label;
!
! win->open_local_win = XmxMakeFileSBDialog
! (win->base, "NCSA Mosaic: Open Local Document",
! "Name of local document to open:",
! open_local_win_cb, 0);
X }
! else
! {
! XmFileSelectionDoSearch (win->open_local_win, NULL);
! }
!
! XmxManageRemanage (win->open_local_win);
! return mo_succeed;
X }
X
X /* ----------------------- mo_post_open_window ------------------------ */
--- 327,410 ----
X
X static XmxCallback (open_local_win_cb)
X {
! char* fname = calloc(128, sizeof(char));
! char* url;
! mo_window* win;
! #ifdef CKM
! struct stat stat_buf;
! int lnksiz = 0, bufsiz = MAXPATHLEN;
! #endif
X
! win = mo_fetch_window_by_id(XmxExtractUniqid ((int)client_data));
X
! XtUnmanageChild (win->open_local_win);
!
! XmStringGetLtoR (((XmFileSelectionBoxCallbackStruct *)call_data)->value,
! XmSTRING_DEFAULT_CHARSET,
! &fname);
!
! #ifdef CKM
! /*
! * If the file is a symbolic link that doesn't seem to point
! * anywhere, then assume it is a symbolic link encoded URL
! */
! if (lstat(fname, &stat_buf) == 0 &&
! S_ISLNK(stat_buf.st_mode) &&
! #ifndef AIX
! ((bufsiz = stat_buf.st_size) > 0) &&
! #endif
! stat(fname, &stat_buf) == -1) {
! char* buf = calloc(bufsiz, sizeof(char));
!
! if ((lnksiz = readlink(fname, buf, bufsiz)) < 0) {
! perror("readlink");
! (void) free(buf);
! return;
! } else {
! url = (char*) calloc(lnksiz + 1, sizeof(char));
! buf[lnksiz] = (char) NULL;
! (void) strcpy(url, buf);
! }
! (void) free(buf);
! } else {
! #endif
! url = (char*) malloc((strlen(fname) +
! strlen(shortmachine) + 16) * sizeof(char));
! sprintf (url, "file://%s%s\0", shortmachine, fname);
! if (url[strlen(url)-1] == '/') url[strlen(url)-1] = '\0';
! #ifdef CKM
! }
! #endif
! (void) free(fname);
! mo_load_window_text (win, url, NULL);
! return;
X }
X
X mo_status mo_post_open_local_window (mo_window *win)
X {
! XmxSetUniqid (win->id);
! if (!win->open_local_win) {
! Widget frame, workarea, format_label;
!
! win->open_local_win =
! XmxMakeFileSBDialog(win->base,
! "NCSA Mosaic: Open Local Document",
! "Name of local document to open:",
! open_local_win_cb, 0);
! #ifdef CKM
! /*
! * Replace the current file-search procedure with one which
! * knows about symbolic-link-encoded-URL's
! */
! XtVaSetValues (win->open_local_win,
! XmNfileSearchProc, (XtArgVal) &alt_file_search_proc,
! NULL);
! #endif
! } else {
! XmFileSelectionDoSearch (win->open_local_win, NULL);
X }
! XmxManageRemanage (win->open_local_win);
! return mo_succeed;
X }
X
X /* ----------------------- mo_post_open_window ------------------------ */
SHAR_EOF
chmod 0644 gui2.c-dif ||
echo 'restore of gui2.c-dif failed'
Wc_c="`wc -c < 'gui2.c-dif'`"
test 9163 -eq "$Wc_c" ||
echo 'gui2.c-dif: original size 9163, current size' "$Wc_c"
fi
exit 0