[w3m-dev 04241] selection menu of external viewer, download, or ...

[email protected] (Hironori SAKAMOTO) Sat, 19 May 2007 03:04:34 +0900
Newsgroups gmane.comp.web.w3m.devel
Message-ID <[email protected]>
$B:dK\$G$9!#(B

$B%j%s%/$r30It%3%^%s%I$G<B9T$7$?$j%@%&%s%m!<%I$9$k;~$KA*Br(B/$B3NG'(B
$B$9$k$?$a$N%a%K%e!<$,I=<($5$l$k$h$&$K$7$F$_$^$7$?!#(B($B$*;n$7HG(B)
$B$I$s$J$b$s$G$7$g!#(B
-----------------------------------
$B:dK\(B $B9@B'(B <[email protected]>

diff -ru ../test/file.c ./file.c
--- ../test/file.c	Thu Apr 19 21:00:37 2007
+++ ./file.c	Sat May 19 02:22:59 2007
@@ -2169,9 +2169,20 @@
 #endif
     else if (w3m_backend) ;
     else if (!(w3m_dump & ~DUMP_FRAME) || is_dump_text_type(t)) {
-	if (!do_download && doExternal(f,
-				       pu.real_file ? pu.real_file : pu.file,
-				       t, &b, t_buf)) {
+	int act = do_download ? ACT_DOWNLOAD : ACT_EXT_VIEWER;
+
+	if (act == ACT_EXT_VIEWER) {
+	    act = doExternal(f, &pu, t, &b, t_buf);
+	    if (act == ACT_NOTHING) {
+		TRAP_OFF;
+		return NO_BUFFER;
+	    }
+	}
+	if (act == ACT_AS_HTML)
+	    proc = loadHTMLBuffer;
+	else if (act == ACT_AS_PLAIN)
+	    proc = loadBuffer;
+	else if (act == ACT_EXT_VIEWER) {
 	    if (b && b != NO_BUFFER) {
 		b->real_scheme = f.scheme;
 		b->real_type = real_type;
@@ -7399,7 +7410,7 @@
     }
 #endif
     else {
-	if (doExternal(uf, "-", t, &buf, t_buf)) {
+	if (doExternal(uf, NULL, t, &buf, t_buf) != ACT_DOWNLOAD) {
 	    UFclose(&uf);
 	    if (buf == NULL || buf == NO_BUFFER)
 		return buf;
@@ -7601,7 +7612,7 @@
 }
 
 int
-doExternal(URLFile uf, char *path, char *type, Buffer **bufp,
+doExternal(URLFile uf, ParsedURL *pu, char *type, Buffer **bufp,
 	   Buffer *defaultbuf)
 {
     Str tmpf, command;
@@ -7609,9 +7620,37 @@
     int mc_stat;
     Buffer *buf = NULL;
     char *header, *src = NULL, *ext = uf.ext;
+#ifdef USE_MENU
+    int act;
+    char *ans;
+    struct mailcap act_mcap;
+    MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL;
+#endif
 
-    if (!(mcap = searchExtViewer(type)))
-	return 0;
+    mcap = searchExtViewer(type);
+#ifdef USE_MENU
+    if (fmInitialized && CurrentTab && Currentbuf && pu) {
+	TRAP_OFF;
+	act = external_menu(parsedURL2Str(pu)->ptr, type,
+		reconstructMailcapEntry(mcap));
+	if (act == ACT_OTHER_VIEWER || (act == ACT_EXT_VIEWER && !mcap)) {
+	    ans = inputLineHist("External viewer: ", NULL, IN_COMMAND,
+		ShellHist);
+	    if (!(ans && extractMailcapEntry(Sprintf("%s;%s", type, ans)->ptr,
+		&act_mcap))) {
+		TRAP_ON;
+		return ACT_NOTHING;
+	    }
+	    act = ACT_EXT_VIEWER;
+	    mcap = &act_mcap;
+	}
+	TRAP_ON;
+	if (act != ACT_EXT_VIEWER)
+	    return act;
+    }
+#endif
+    if (!mcap)
+	return ACT_DOWNLOAD;
 
     if (mcap->nametemplate) {
 	tmpf = unquote_mailcap(mcap->nametemplate, NULL, "", NULL, NULL);
@@ -7645,14 +7684,14 @@
 	    myExec(command->ptr);
 	}
 	*bufp = NO_BUFFER;
-	return 1;
+	return ACT_EXT_VIEWER;
     }
     else
 #endif
     {
 	if (save2tmp(uf, tmpf->ptr) < 0) {
 	    *bufp = NULL;
-	    return 1;
+	    return ACT_EXT_VIEWER;
 	}
     }
     if (mcap->flags & (MAILCAP_HTMLOUTPUT | MAILCAP_COPIOUSOUTPUT)) {
@@ -7695,14 +7734,14 @@
 	buf = NO_BUFFER;
     }
     if (buf && buf != NO_BUFFER) {
-	buf->filename = path;
+	buf->filename = pu ? (pu->real_file ? pu->real_file : pu->file) : "-";
 	if (buf->buffername == NULL || buf->buffername[0] == '\0')
-	    buf->buffername = conv_from_system(lastFileName(path));
+	    buf->buffername = conv_from_system(lastFileName(buf->filename));
 	buf->edit = mcap->edit;
 	buf->mailcap = mcap;
     }
     *bufp = buf;
-    return 1;
+    return ACT_EXT_VIEWER;
 }
 
 static int
diff -ru ../test/fm.h ./fm.h
--- ../test/fm.h	Fri May 18 23:09:17 2007
+++ ./fm.h	Sat May 19 00:16:12 2007
@@ -255,6 +255,13 @@
 #define IMG_FLAG_ERROR		2
 #define IMG_FLAG_DONT_REMOVE	4
 
+#define ACT_NOTHING	-1
+#define ACT_DOWNLOAD	0
+#define ACT_EXT_VIEWER	1
+#define ACT_AS_PLAIN	2
+#define ACT_AS_HTML	3
+#define ACT_OTHER_VIEWER	4
+
 /* 
  * Macros.
  */
diff -ru ../test/mailcap.c ./mailcap.c
--- ../test/mailcap.c	Mon Aug  7 12:10:26 2006
+++ ./mailcap.c	Sat May 19 02:24:54 2007
@@ -110,7 +110,7 @@
     return 0;
 }
 
-static int
+int
 extractMailcapEntry(char *mcap_entry, struct mailcap *mcap)
 {
     int j, k;
@@ -177,6 +177,29 @@
 	}
     }
     return 1;
+}
+
+char *
+reconstructMailcapEntry(struct mailcap *mcap)
+{
+    Str tmp;
+
+    if (!(mcap && mcap->viewer))
+	return NULL;
+    tmp = Strnew_charp(mcap->viewer);
+    if (mcap->flags & MAILCAP_NEEDSTERMINAL)
+	Strcat_charp(tmp, "; needsterminal");
+    if (mcap->flags & MAILCAP_COPIOUSOUTPUT)
+	Strcat_charp(tmp, "; copiousoutput");
+    if (mcap->flags & MAILCAP_HTMLOUTPUT)
+	Strcat_charp(tmp, "; x-htmloutput");
+    if (mcap->test)
+	Strcat_m_charp(tmp, "; test=", mcap->test, NULL);
+    if (mcap->nametemplate)
+	Strcat_m_charp(tmp, "; nametemplate=", mcap->nametemplate, NULL);
+    if (mcap->edit)
+	Strcat_m_charp(tmp, "; edit=", mcap->edit, NULL);
+    return tmp->ptr;
 }
 
 static struct mailcap *
diff -ru ../test/menu.c ./menu.c
--- ../test/menu.c	Fri May 18 22:50:31 2007
+++ ./menu.c	Sat May 19 02:23:54 2007
@@ -2070,4 +2070,77 @@
     return (key >= 0) ? ap[key] : NULL;
 }
 
+int
+external_menu(char *url, char *type, char *viewer)
+{
+    Menu menu;
+    int i, n, limit, init, val = 0, act[10];
+    char **label;
+    Str tmp = Strnew_charp(url);
+
+    limit = COLS - 9;
+    if (limit < 15)
+	limit = 15;
+    n = (tmp->length - 1) / limit + 1;
+    if (n > 5)
+	n = 5;
+    label = New_N(char *, 8 + n);
+    i = 0;
+    label[i] = Sprintf("URL: %s", Strsubstr(tmp, 0, limit)->ptr)->ptr;
+    act[i++] = ACT_NOTHING;
+    while (i < n) {
+        label[i] = Sprintf("     %s", Strsubstr(tmp, i * limit,
+		limit)->ptr)->ptr;
+        act[i++] = ACT_NOTHING;
+    }
+    label[i] = Sprintf("Type: %s", type ? type : "unknown")->ptr;
+    act[i++] = ACT_NOTHING;
+    if (viewer) {
+	label[i] = Sprintf("Viewer: %s", viewer)->ptr;
+	act[i++] = ACT_NOTHING;
+    }
+    label[i] = "d) Download";
+    act[i++] = ACT_DOWNLOAD;
+    if (viewer) {
+	init = i;
+	label[i] = "e) Execute external viewer";
+	act[i++] = ACT_EXT_VIEWER;
+	label[i] = "o) Execute other viewer";
+	act[i++] = ACT_OTHER_VIEWER;
+    }
+    else {
+	init = i - 1;
+	label[i] = "e) Execute external viewer";
+	act[i++] = ACT_OTHER_VIEWER;
+    }
+    label[i] = "p) Open as plain text";
+    act[i++] = ACT_AS_PLAIN;
+    label[i] = "h) Open as HTML";
+    act[i++] = ACT_AS_HTML;
+    label[i] = NULL;
+
+    set_menu_frame();
+    new_option_menu(&menu, label, &val, NULL);
+
+    menu.initial = init;
+    menu.cursorX = Currentbuf->cursorX + Currentbuf->rootX;
+    menu.cursorY = Currentbuf->cursorY + Currentbuf->rootY;
+    menu.x = menu.cursorX + FRAME_WIDTH - 1;
+    menu.y = menu.cursorY + init + 2;
+
+    for (i = 0; label[i] != NULL; i++) {
+	if (act[i] != ACT_NOTHING) {
+	    n = (int)label[i][0];
+	    menu.keymap[n] = mSelect;
+	    menu.keyselect[n] = i;
+	}
+	else
+	    menu.item[i].type = MENU_NOP;
+    }
+
+    popup_menu(NULL, &menu);
+
+    return act[val];
+}
+
 #endif				/* USE_MENU */
diff -ru ../test/proto.h ./proto.h
--- ../test/proto.h	Fri Apr  7 22:21:12 2006
+++ ./proto.h	Sat May 19 02:21:52 2007
@@ -245,7 +245,7 @@
 extern Buffer *openGeneralPagerBuffer(InputStream stream);
 extern Line *getNextPage(Buffer *buf, int plen);
 extern int save2tmp(URLFile uf, char *tmpf);
-extern int doExternal(URLFile uf, char *path, char *type, Buffer **bufp,
+extern int doExternal(URLFile uf, ParsedURL *pu, char *type, Buffer **bufp,
 		      Buffer *defaultbuf);
 extern int _doFileCopy(char *tmpf, char *defstr, int download);
 #define doFileCopy(tmpf, defstr) _doFileCopy(tmpf, defstr, FALSE);
@@ -516,6 +516,8 @@
 		       HRequest *hr, unsigned char *status);
 extern int mailcapMatch(struct mailcap *mcap, char *type);
 extern struct mailcap *searchMailcap(struct mailcap *table, char *type);
+extern int extractMailcapEntry(char *mcap_entry, struct mailcap *mcap);
+extern char *reconstructMailcapEntry(struct mailcap *mcap);
 extern void initMailcap();
 extern char *acceptableMimeTypes();
 extern struct mailcap *searchExtViewer(char *type);
@@ -751,6 +753,7 @@
 extern void optionMenu(int x, int y, char **label, int *variable, int initial,
 		       void (*func) ());
 extern void initMenu(void);
+extern external_menu(char *url, char *type, char *viewer);
 #else				/* not USE_MENU */
 #define mainMn nulcmd
 #define selMn selBuf