w3m

Unnamed repository; edit this file to name it for gitweb.
git clone https://logand.com/git/w3m.git/
Log | Files | Refs | README

commit dc6d25d95630138b6d045240702116ba45760fc8
parent 447a95119c2d8f0f638e5c51c07dc8e620c7023d
Author: ukai <ukai>
Date:   Thu, 31 Jan 2002 17:54:47 +0000

w3m-img merge (w3m-0.2.4+cvs-1.278-img-2.2.patch.gz)
* NEWS: w3m-img merge
* .cvsignore: add w3mimgdisplay, w3mimgsize
* XMakefile: add image.c to SRCS
	     add image.o to OBJS
             add IMGDISPLAY, IMGSIZE
* config.h.dist: USE_IMAGE, IMGSIZE, IMGDISPLAY
* configure: add find_imlib
		ask use_image
	(config.h) add $imgtarget to EXT_TARGETS
		   $def_use_image
		   IMGSIZE, IMGDISPLAY
* fm.h (MAX_IMAGE): added
* fm.h (DEFAULT_PIXEL_PER_CHAR): fix for USE_IMAGE
* fm.h (DEFAULT_PIXEL_PER_LINE): added
* fm.h (B_REDRAW_IMAGE): added
* fm.h (IMG_FLAG_SKIP): added
* fm.h (IMG_FLAG_AUTO): added
* fm.h (IMG_FLAG_START): added
* fm.h (IMG_FLAG_STOP): added
* fm.h (IMG_FLAG_NEXT): added
* fm.h (IMG_FLAG_UNLOADED): added
* fm.h (IMG_FLAG_LOADED): added
* fm.h (IMG_FLAG_ERROR): added
* fm.h (MapArea): added
* fm.h (MapList): s/urls/alts/, add area
* fm.h (ImageCache): added
* fm.h (Image): added
* fm.h (Anchor): add image
* fm.h (Buffer): add imarklist, image_flag, need_reshape
* fm.h (RG_FRAME_SRC): added
* fm.h (ALIGN_MIDDLE): added
* fm.h (ALIGN_TOP): added
* fm.h (ALIGN_BOTTOM): added
* fm.h (QuietMessage): added
* fm.h (Imgdisplay): added
* fm.h (Imgsize): added
* fm.h (activeImage): added
* fm.h (displayImage): added
* fm.h (autoImage): added
* fm.h (useExtImageViewer): added
* fm.h (image_source): added
* fm.h (view_unseenobject): change default if USE_IMAGE
* fm.h (set_pixel_per_char): added
* fm.h (pixel_per_line): added
* fm.h (set_pixel_per_line): added
* fm.h (image_scale): added
* proto.h (dispI): added
* proto.h (stopI): added
* proto.h (deleteImage): added
* proto.h (getAllImage): added
* proto.h (loadImage): added
* proto.h (getImage): added
* proto.h (getImageSize): added
* proto.h (process_img): add width arg
* proto.h (loadImageBuffer): added
* proto.h (follow_map_menu): add a_img arg
* proto.h (getMapXY): added
* proto.h (newMapArea): added
* proto.h (touch_cursor): added
* proto.h (cURLcode): added
* proto.h (initImage): added
* proto.h (termImage): added
* proto.h (addImage): added
* proto.h (drawImage): added
* proto.h (clearImage): added
* anchor.c (addMultirowsImg): added
* buffer.c (discardBuffer): deleteImage if USE_IMAGE
* buffer.c (reshapeBuffer): buf->need_reshape check
* display.c (fmTerm): if activeImage, stop load image
* display.c (fmInit): if displayImage, initImage
* display.c (image_touch): added
* display.c (draw_image_flag): added
* display.c (redrawLineImage): added
* display.c (displayBuffer): buf->need_reshape = TRUE
			mode == B_REDRAW_IMAGE
			image flag checks
			force redraw image in mode == B_REDRAW_IMAGE
			displayBuffer if need reshape
			drawImage
* display.c (redrawNLine): redrawLineImage
* display.c (redrawLineImage): added
* display.c (disp_message_nsec): return immediately if QuietMessage
* etc.c (reset_signals): ignore SIGUSR1
* file.c (frame_source): added
* file.c (_MoveFile): added
* file.c (cur_baseURL): added
* file.c (cur_document_code): added
* file.c (cur_iseq): added
* file.c (loadGeneralFile): fix fmInitialized and prevtrap checks
			save cur_baseURL
			image_source load
			loadImageBuffer for "image/*"
			frame_source flag
			fix b->type when proc is loadImageBuffer
* file.c (process_img): add width arg
		parse height and width attr, align
		fix for inline-image
* file.c (process_input): fix for form <input type="image">
* file.c (HTMLtagproc1): pass h_env->limit to process_img()
		fix <img_alt> for inline-image
		save cur_baseURL
* file.c (HTMLlineproc2body): fix <img_alt> for inline-image
* file.c (loadHTMLstream): fix for inline-image
		fix fmInitialized and prevtrap checks
		save cur_document_code
		save image_flag
* file.c (loadGopherDir): save cur_document_code
		fix fmInitialized and prevtrap checks
* file.c (loadImageBuffer): added for inline-image
* file.c (save2tmp): fix fmInitialized and prevtrap checks
* frame.c (frame_download_source): set RG_FRAME_SRC flag
		image check
* funcname.tab (DISPLAY_IMAGE): added
* funcname.tab (STOP_IMAGE): added
* html.c (ALST_IMG): add align, ismap
* html.c (ALST_AREA): add shape, coords
* html.c (ALST_IMG_ALT): add width, height, usemap, ismap, hseq,
			xoffset, yoffset, top_margin, bottom_margin
* html.c (AttrMap): add shape, coords, ismap, xoffset, yoffset
* html.h (ATTR_SHAPE): added
* html.h (ATTR_COORDS): added
* html.h (ATTR_ISMAP): added
* html.h (ATTR_XOFFSET): added
* html.h (ATTR_YOFFSET): added
* html.h (ATTR_TOP_MARGIN): added
* html.h (ATTR_BOTTOM_MARGIN): added
* html.h (SHAPE_UNKNOWN): added
* html.h (SHAPE_DEFAULT): added
* html.h (SHAPE_RECT): added
* html.h (SHAPE_CIRCLE): added
* html.h (SHAPE_POLY): added
* image.c: added
* main.c (fversion): add USE_IMAGE
* main.c (fusage): -ppl option
* main.c (MAIN): set_pixel_per_char if ppc specified
		-ppl option
		loadImage
* main.c (pushBuffer): deleteImage
* main.c (quitfm): termImage
* main.c (selBuf): deleteImage
* main.c (followA): fix for inline-image and map area
* main.c (query_from_followform): getMapXY()
* main.c (setOpt): displayBuffer B_REDRAW_IMAGE
* main.c (follow_map): fix calculate x, y
* main.c (dispI): added
* main.c (stopI): added
* map.c: include <math.h>
* map.c (inMapArea): added
* map.c (follow_map_menu): add a_img arg to handle inline-image
* map.c (follow_map_panel): use MapArea
* map.c (getMapXY): added
* map.c (newMapArea): added
* menu.c (smChBuf): deleteImage
* parsetagx.c (toAlign): align top, bottom, middle
* rc.c (P_SCALE): added
* rc.c (CMT_PIXEL_PER_LINE): added
* rc.c (CMT_DISP_IMAGE): added
* rc.c (CMT_AUTO_IMAGE): added
* rc.c (CMT_EXT_IMAGE_VIEWER): added
* rc.c (CMT_IMAGE_SCALE): added
* rc.c (CMT_IMGDISPLAY): added
* rc.c (CMT_IMGSIZE): added
* rc.c (show_param): P_PIXELS
* rc.c (set_param): P_PIXELS
* rc.c (sync_with_option): initImage
* rc.c (to_str): P_PIXELS
* table.c (feed_table_tag): fix <img> for inline-image
* tagtable.tab (image): added
* terms.c (wgetch): retry read when EINTR or EAGAIN
* terms.c (touch_cursor): added
* w3mimgdisplay.c: added
* w3mimgsize.c: added
* doc/README.func (DISPLAY_IMAGE): added
* doc/README.func (STOP_IMAGE): added
* doc/README.img: added
* doc-jp/README.func (DISPLAY_IMAGE): added
* doc-jp/README.func (STOP_IMAGE): added
* doc-jp/README.img: added
* scripts/w3mhelp.cgi.in: show dispI, stopI
* scripts/multipart/multipart.cgi.in: inline image support
From: Fumitoshi UKAI  <ukai@debian.or.jp>

Diffstat:
M.cvsignore | 2++
MChangeLog | 184+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
MNEWS | 5+++++
MXMakefile | 20++++++++++++++++++--
Manchor.c | 77+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mbuffer.c | 6++++++
Mconfig.h.dist | 3+++
Mconfigure | 44++++++++++++++++++++++++++++++++++++++++++--
Mdisplay.c | 152+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
Mdoc-jp/README.func | 2++
Adoc-jp/README.img | 253+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mdoc/README.func | 2++
Adoc/README.img | 189+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Metc.c | 1+
Mfile.c | 639++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------------
Mfm.h | 93+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mframe.c | 9+++++++--
Mfuncname.tab | 2++
Mhtml.c | 28+++++++++++++++++-----------
Mhtml.h | 17++++++++++++++---
Aimage.c | 528+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Mmain.c | 126++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---------
Mmap.c | 221++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-------
Mmenu.c | 9+++++++--
Mparsetagx.c | 6++++++
Mproto.h | 44+++++++++++++++++++++++++++++++++++++++++---
Mrc.c | 50+++++++++++++++++++++++++++++++++++++++++++++++++-
Mscripts/multipart/multipart.cgi.in | 22+++++++++++++++-------
Mscripts/w3mhelp.cgi.in | 2+-
Mtable.c | 17++++++++++++++++-
Mtagtable.tab | 1+
Mterms.c | 26+++++++++++++++++++++++++-
Aw3mimgdisplay.c | 369+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Aw3mimgsize.c | 31+++++++++++++++++++++++++++++++
34 files changed, 2987 insertions(+), 193 deletions(-)

diff --git a/.cvsignore b/.cvsignore @@ -11,6 +11,8 @@ mktable w3m w3mbookmark w3mhelperpanel +w3mimgdisplay +w3mimgsize version.c w3mhelp-lynx_en.html w3mhelp-lynx_ja.html diff --git a/ChangeLog b/ChangeLog @@ -1,3 +1,187 @@ +2002-02-01 Hironori Sakamoto <hsaka@mth.biglobe.ne.jp> + + * w3m-img merge (w3m-0.2.4+cvs-1.278-img-2.2.patch.gz) + * NEWS: w3m-img merge + * .cvsignore: add w3mimgdisplay, w3mimgsize + * XMakefile: add image.c to SRCS + add image.o to OBJS + add IMGDISPLAY, IMGSIZE + * config.h.dist: USE_IMAGE, IMGSIZE, IMGDISPLAY + * configure: add find_imlib + ask use_image + (config.h) add $imgtarget to EXT_TARGETS + $def_use_image + IMGSIZE, IMGDISPLAY + * fm.h (MAX_IMAGE): added + * fm.h (DEFAULT_PIXEL_PER_CHAR): fix for USE_IMAGE + * fm.h (DEFAULT_PIXEL_PER_LINE): added + * fm.h (B_REDRAW_IMAGE): added + * fm.h (IMG_FLAG_SKIP): added + * fm.h (IMG_FLAG_AUTO): added + * fm.h (IMG_FLAG_START): added + * fm.h (IMG_FLAG_STOP): added + * fm.h (IMG_FLAG_NEXT): added + * fm.h (IMG_FLAG_UNLOADED): added + * fm.h (IMG_FLAG_LOADED): added + * fm.h (IMG_FLAG_ERROR): added + * fm.h (MapArea): added + * fm.h (MapList): s/urls/alts/, add area + * fm.h (ImageCache): added + * fm.h (Image): added + * fm.h (Anchor): add image + * fm.h (Buffer): add imarklist, image_flag, need_reshape + * fm.h (RG_FRAME_SRC): added + * fm.h (ALIGN_MIDDLE): added + * fm.h (ALIGN_TOP): added + * fm.h (ALIGN_BOTTOM): added + * fm.h (QuietMessage): added + * fm.h (Imgdisplay): added + * fm.h (Imgsize): added + * fm.h (activeImage): added + * fm.h (displayImage): added + * fm.h (autoImage): added + * fm.h (useExtImageViewer): added + * fm.h (image_source): added + * fm.h (view_unseenobject): change default if USE_IMAGE + * fm.h (set_pixel_per_char): added + * fm.h (pixel_per_line): added + * fm.h (set_pixel_per_line): added + * fm.h (image_scale): added + * proto.h (dispI): added + * proto.h (stopI): added + * proto.h (deleteImage): added + * proto.h (getAllImage): added + * proto.h (loadImage): added + * proto.h (getImage): added + * proto.h (getImageSize): added + * proto.h (process_img): add width arg + * proto.h (loadImageBuffer): added + * proto.h (follow_map_menu): add a_img arg + * proto.h (getMapXY): added + * proto.h (newMapArea): added + * proto.h (touch_cursor): added + * proto.h (cURLcode): added + * proto.h (initImage): added + * proto.h (termImage): added + * proto.h (addImage): added + * proto.h (drawImage): added + * proto.h (clearImage): added + * anchor.c (addMultirowsImg): added + * buffer.c (discardBuffer): deleteImage if USE_IMAGE + * buffer.c (reshapeBuffer): buf->need_reshape check + * display.c (fmTerm): if activeImage, stop load image + * display.c (fmInit): if displayImage, initImage + * display.c (image_touch): added + * display.c (draw_image_flag): added + * display.c (redrawLineImage): added + * display.c (displayBuffer): buf->need_reshape = TRUE + mode == B_REDRAW_IMAGE + image flag checks + force redraw image in mode == B_REDRAW_IMAGE + displayBuffer if need reshape + drawImage + * display.c (redrawNLine): redrawLineImage + * display.c (redrawLineImage): added + * display.c (disp_message_nsec): return immediately if QuietMessage + * etc.c (reset_signals): ignore SIGUSR1 + * file.c (frame_source): added + * file.c (_MoveFile): added + * file.c (cur_baseURL): added + * file.c (cur_document_code): added + * file.c (cur_iseq): added + * file.c (loadGeneralFile): fix fmInitialized and prevtrap checks + save cur_baseURL + image_source load + loadImageBuffer for "image/*" + frame_source flag + fix b->type when proc is loadImageBuffer + * file.c (process_img): add width arg + parse height and width attr, align + fix for inline-image + * file.c (process_input): fix for form <input type="image"> + * file.c (HTMLtagproc1): pass h_env->limit to process_img() + fix <img_alt> for inline-image + save cur_baseURL + * file.c (HTMLlineproc2body): fix <img_alt> for inline-image + * file.c (loadHTMLstream): fix for inline-image + fix fmInitialized and prevtrap checks + save cur_document_code + save image_flag + * file.c (loadGopherDir): save cur_document_code + fix fmInitialized and prevtrap checks + * file.c (loadImageBuffer): added for inline-image + * file.c (save2tmp): fix fmInitialized and prevtrap checks + * frame.c (frame_download_source): set RG_FRAME_SRC flag + image check + * funcname.tab (DISPLAY_IMAGE): added + * funcname.tab (STOP_IMAGE): added + * html.c (ALST_IMG): add align, ismap + * html.c (ALST_AREA): add shape, coords + * html.c (ALST_IMG_ALT): add width, height, usemap, ismap, hseq, + xoffset, yoffset, top_margin, bottom_margin + * html.c (AttrMap): add shape, coords, ismap, xoffset, yoffset + * html.h (ATTR_SHAPE): added + * html.h (ATTR_COORDS): added + * html.h (ATTR_ISMAP): added + * html.h (ATTR_XOFFSET): added + * html.h (ATTR_YOFFSET): added + * html.h (ATTR_TOP_MARGIN): added + * html.h (ATTR_BOTTOM_MARGIN): added + * html.h (SHAPE_UNKNOWN): added + * html.h (SHAPE_DEFAULT): added + * html.h (SHAPE_RECT): added + * html.h (SHAPE_CIRCLE): added + * html.h (SHAPE_POLY): added + * image.c: added + * main.c (fversion): add USE_IMAGE + * main.c (fusage): -ppl option + * main.c (MAIN): set_pixel_per_char if ppc specified + -ppl option + loadImage + * main.c (pushBuffer): deleteImage + * main.c (quitfm): termImage + * main.c (selBuf): deleteImage + * main.c (followA): fix for inline-image and map area + * main.c (query_from_followform): getMapXY() + * main.c (setOpt): displayBuffer B_REDRAW_IMAGE + * main.c (follow_map): fix calculate x, y + * main.c (dispI): added + * main.c (stopI): added + * map.c: include <math.h> + * map.c (inMapArea): added + * map.c (follow_map_menu): add a_img arg to handle inline-image + * map.c (follow_map_panel): use MapArea + * map.c (getMapXY): added + * map.c (newMapArea): added + * menu.c (smChBuf): deleteImage + * parsetagx.c (toAlign): align top, bottom, middle + * rc.c (P_SCALE): added + * rc.c (CMT_PIXEL_PER_LINE): added + * rc.c (CMT_DISP_IMAGE): added + * rc.c (CMT_AUTO_IMAGE): added + * rc.c (CMT_EXT_IMAGE_VIEWER): added + * rc.c (CMT_IMAGE_SCALE): added + * rc.c (CMT_IMGDISPLAY): added + * rc.c (CMT_IMGSIZE): added + * rc.c (show_param): P_PIXELS + * rc.c (set_param): P_PIXELS + * rc.c (sync_with_option): initImage + * rc.c (to_str): P_PIXELS + * table.c (feed_table_tag): fix <img> for inline-image + * tagtable.tab (image): added + * terms.c (wgetch): retry read when EINTR or EAGAIN + * terms.c (touch_cursor): added + * w3mimgdisplay.c: added + * w3mimgsize.c: added + * doc/README.func (DISPLAY_IMAGE): added + * doc/README.func (STOP_IMAGE): added + * doc/README.img: added + * doc-jp/README.func (DISPLAY_IMAGE): added + * doc-jp/README.func (STOP_IMAGE): added + * doc-jp/README.img: added + * scripts/w3mhelp.cgi.in: show dispI, stopI + * scripts/multipart/multipart.cgi.in: inline image support + 2002-02-01 Fumitoshi UKAI <ukai@debian.or.jp> * version.c.in: 0.2.5+cvs diff --git a/NEWS b/NEWS @@ -1,3 +1,8 @@ +w3m 0.3? + +* w3m-img merged: w3m now can display images! see doc/README.img + +---------------------------------------------------------------- w3m 0.2.5 - 2002-01-31 * RFC2617: HTTP Digest authentication diff --git a/XMakefile b/XMakefile @@ -1,9 +1,9 @@ # $Id$ SRCS=main.c file.c buffer.c display.c etc.c search.c linein.c table.c local.c \ - form.c map.c frame.c rc.c menu.c mailcap.c\ + form.c map.c frame.c rc.c menu.c mailcap.c image.c\ func.c cookie.c history.c backend.c $(KEYBIND_SRC) OBJS=main.o file.o buffer.o display.o etc.o search.o linein.o table.o local.o\ - form.o map.o frame.o rc.o menu.o mailcap.o\ + form.o map.o frame.o rc.o menu.o mailcap.o image.o\ func.o cookie.o history.o backend.o $(KEYBIND_OBJ) LSRCS=terms.c conv.c url.c ftp.c anchor.c mimehead.c parsetagx.c\ tagtable.c istream.c @@ -18,6 +18,8 @@ TARGET=w3m$(EXT) BOOKMARKER=w3mbookmark$(EXT) HELPER=w3mhelperpanel$(EXT) INFLATE=inflate$(EXT) +IMGDISPLAY=w3mimgdisplay$(EXT) +IMGSIZE=w3mimgsize$(EXT) TARGETS=$(TARGET) $(EXT_TARGETS) HELP_ALLFILES=w3mhelp-w3m_en.html w3mhelp-w3m_ja.html \ w3mhelp-lynx_en.html w3mhelp-lynx_ja.html @@ -88,6 +90,20 @@ $(INFLATE): inflate.o inflate.o: inflate.c $(CC) $(CFLAGS) $(Z_CFLAGS) -c inflate.c +$(IMGDISPLAY): w3mimgdisplay.o + $(CC) $(CFLAGS) `imlib-config --cflags` -o $(IMGDISPLAY) \ + w3mimgdisplay.o `imlib-config --libs` + +$(IMGSIZE): w3mimgsize.o + $(CC) $(CFLAGS) `imlib-config --cflags` -o $(IMGSIZE) \ + w3mimgsize.o `imlib-config --libs` + +w3mimgdisplay.o: w3mimgdisplay.c + $(CC) $(CFLAGS) `imlib-config --cflags` -c w3mimgdisplay.c + +w3mimgsize.o: w3mimgsize.c + $(CC) $(CFLAGS) `imlib-config --cflags` -c w3mimgsize.c + gc/gc.a: cd gc; $(MAKE) CC='$(CC)' CFLAGS='$(GCCFLAGS) $(GC_CFLAGS)' SPECIALCFLAGS='-I./\$(srcdir)/include $(GC_CFLAGS)' diff --git a/anchor.c b/anchor.c @@ -406,6 +406,83 @@ closest_prev_anchor(AnchorList *a, Anchor *an, int x, int y) return an; } +#ifdef USE_IMAGE +void +addMultirowsImg(Buffer *buf, AnchorList *al) +{ + int i, j, k, col, ecol, pos; + Image *img; + Anchor a_img, a_href, a_form, *a; + Line *l, *ls; + + if (al == NULL || al->nanchor == 0) + return; + for (i = 0; i < al->nanchor; i++) { + a_img = al->anchors[i]; + img = a_img.image; + if (a_img.hseq < 0 || !img || img->rows <= 1) + continue; + for (l = buf->firstLine; l != NULL; l = l->next) { + if (l->linenumber == img->y) + break; + } + if (!l) + continue; + if (a_img.y == a_img.start.line) + ls = l; + else { + for (ls = l; ls != NULL; + ls = (a_img.y < a_img.start.line) ? ls->next : ls->prev) { + if (ls->linenumber == a_img.start.line) + break; + } + if (!ls) + continue; + } + a = retrieveAnchor(buf->href, a_img.start.line, a_img.start.pos); + if (a) + a_href = *a; + else + a_href.url = NULL; + a = retrieveAnchor(buf->formitem, a_img.start.line, a_img.start.pos); + if (a) + a_form = *a; + else + a_form.url = NULL; + col = COLPOS(ls, a_img.start.pos); + ecol = COLPOS(ls, a_img.end.pos); + for (j = 0; l && j < img->rows; l = l->next, j++) { + if (a_img.start.line == l->linenumber) + continue; + pos = columnPos(l, col); + a = registerImg(buf, a_img.url, l->linenumber, pos); + a->hseq = -a_img.hseq; + a->image = img; + a->end.pos = pos + ecol - col; + for (k = pos; k < a->end.pos; k++) + l->propBuf[k] |= PE_IMAGE; + if (a_href.url) { + a = registerHref(buf, a_href.url, a_href.target, + a_href.referer, l->linenumber, pos); + a->hseq = a_href.hseq; + a->end.pos = pos + ecol - col; + for (k = pos; k < a->end.pos; k++) + l->propBuf[k] |= PE_ANCHOR; + } + if (a_form.url) { + FormItemList *fi = (FormItemList *)a_form.url; + buf->formitem = putAnchor(buf->formitem, a_form.url, + a_form.target, &a, NULL, + l->linenumber, pos); + a->hseq = a_form.hseq; + a->end.pos = pos + ecol - col; + } + } + img->rows = 0; + } +} +#endif + void addMultirowsForm(Buffer *buf, AnchorList *al) { diff --git a/buffer.c b/buffer.c @@ -80,6 +80,9 @@ discardBuffer(Buffer *buf) int i; Buffer *b; +#ifdef USE_IMAGE + deleteImage(buf); +#endif clearBuffer(buf); for (i = 0; i < MAX_LB; i++) { b = buf->linkBuffer[i]; @@ -489,6 +492,9 @@ reshapeBuffer(Buffer *buf) URLFile f; Buffer sbuf; + if (!buf->need_reshape) + return; + buf->need_reshape = FALSE; if (buf->sourcefile == NULL) return; init_stream(&f, SCM_LOCAL, NULL); diff --git a/config.h.dist b/config.h.dist @@ -121,6 +121,7 @@ MODEL=Linux.i686-monster-ja #undef USE_GOPHER #define USE_EXTERNAL_URI_LOADER #undef USE_ALARM +#undef USE_IMAGE #define USE_HELP_CGI #define DEF_EDITOR "/bin/vi" @@ -140,6 +141,8 @@ MODEL=Linux.i686-monster-ja #define HELP_FILE "w3mhelp.html" #define HELP_CGI "w3mhelp" #define W3MCONFIG "w3mconfig" +#define IMGSIZE "w3mimgsize" +#define IMGDISPLAY "w3mimgdisplay" #define RC_DIR "~/.w3m" #define BOOKMARK "bookmark.html" diff --git a/configure b/configure @@ -418,6 +418,30 @@ find_ssl() { fi } +find_imlib() { + imlib_major=1 + imlib_minor=9 + imlib_micro=8 + imlib_version=$imlib_major.$imlib_minor.$imlib_micro + echo "Checking Imlib." + if [ "x$IMLIB_CONFIG" = x ]; then + IMLIB_CONFIG=imlib-config + fi + version=`$IMLIB_CONFIG --version` + if [ "x$version" = x ]; then + echo "You don't have Imlib. Install Imlib (version >= $imlib_version)." + exit 1 + fi + major=`echo "$version" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\1/'` + minor=`echo "$version" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\2/'` + micro=`echo "$version" | sed 's/\([0-9]*\)\.\([0-9]*\)\.\([0-9]*\).*/\3/'` + echo "The version of Imlib is $version." + if [ "$major" -ne $imlib_major -o "$minor" -ne $imlib_minor -o "$micro" -lt $imlib_micro ]; then + echo "Imlib is too old. Install Imlib (version >= $imlib_version)." + exit 1 + fi +} + #-------------------------------------------------------------- if [ -n "$USER" ]; then user=$USER @@ -693,6 +717,15 @@ else def_param "use_digest_auth" n fi +ask_param "Inline image support (you need Imlib library)" use_image n +if [ "$use_image" = y ]; then + def_use_image="#define USE_IMAGE" + imgtarget='$(IMGDISPLAY) $(IMGSIZE)' +else + def_use_image="#undef USE_IMAGE" + imgtarget='' +fi + if [ "$use_color" = y ]; then ask_param "ANSI color escape sequences support" use_ansi_color n else @@ -1891,6 +1924,10 @@ else echo "You have IPv6 support." fi +if [ "$use_image" = y ]; then + find_imlib +fi + rm -f _zmachdep$extension _zmachdep.c _zmachdep.o echo "------------ Configuration done ------------" @@ -1905,7 +1942,7 @@ case $dmodel in esac cvsver=`awk '\$1 ~ /[$]Id:/ { print \$3}' ChangeLog` -sed -e 's/^#define CURRENT_VERSION "\(.*\)+cvs.*"/#define CURRENT_VERSION "\1+cvs-'$cvsver'"/' version.c.in > version.c +sed -e 's/^#define CURRENT_VERSION "\(.*\)+cvs/#define CURRENT_VERSION "\1+cvs-'$cvsver'/' version.c.in > version.c cur_ver=`sed -n 's/^#define CURRENT_VERSION *"w3m\/\([^"]*\)".*$/\1/p' version.c` for h_in in w3mhelp-*_*.html.in @@ -2016,7 +2053,7 @@ EXT=$extension MATHLIB=$mathlib Z_CFLAGS=$z_cflags ZLIB=$zlib -EXT_TARGETS=\$(BOOKMARKER) \$(HELPER) $inflate +EXT_TARGETS=\$(BOOKMARKER) \$(HELPER) $inflate $imgtarget GC_CFLAGS=$gc_cflags GCLIB=$gclib $pthreadlib GCTARGET=$gctarget @@ -2057,6 +2094,7 @@ $def_use_w3mmailer $def_use_nntp $def_use_gopher $def_use_alarm +$def_use_image $def_use_help_cgi #define DEF_EDITOR "$editor" @@ -2076,6 +2114,8 @@ $def_use_help_cgi #define HELP_FILE "w3mhelp.html" #define HELP_CGI "w3mhelp" #define W3MCONFIG "w3mconfig" +#define IMGSIZE "w3mimgsize" +#define IMGDISPLAY "w3mimgdisplay" #define RC_DIR "~/.w3m" #define BOOKMARK "bookmark.html" diff --git a/display.c b/display.c @@ -162,6 +162,10 @@ fmTerm(void) move(LASTLINE, 0); clrtoeolx(); refresh(); +#ifdef USE_IMAGE + if (activeImage) + loadImage(IMG_FLAG_STOP); +#endif #ifdef USE_MOUSE if (use_mouse) mouse_end(); @@ -182,6 +186,10 @@ fmInit(void) initscr(); term_raw(); term_noecho(); +#ifdef USE_IMAGE + if (displayImage) + initImage(); +#endif } fmInitialized = TRUE; } @@ -208,6 +216,12 @@ static Buffer *save_current_buf = NULL; char *delayed_msg = NULL; +#ifdef USE_IMAGE +static int image_touch = 0; +static int draw_image_flag = FALSE; +static Line *redrawLineImage(Buffer *buf, Line *l, int i); +#endif + void displayBuffer(Buffer *buf, int mode) { @@ -222,9 +236,11 @@ displayBuffer(Buffer *buf, int mode) buf->width = COLS; if (buf->height == 0) buf->height = LASTLINE + 1; - if (buf->width != INIT_BUFFER_WIDTH && buf->type - && !strcmp(buf->type, "text/html")) + if ((buf->width != INIT_BUFFER_WIDTH && buf->type && + !strcmp(buf->type, "text/html")) || buf->need_reshape) { + buf->need_reshape = TRUE; reshapeBuffer(buf); + } if (showLineNum) { if (buf->lastLine && buf->lastLine->real_linenumber > 0) buf->rootX = (int)(log(buf->lastLine->real_linenumber + 0.1) @@ -237,10 +253,16 @@ displayBuffer(Buffer *buf, int mode) else buf->rootX = 0; buf->COLS = COLS - buf->rootX; - if (mode == B_FORCE_REDRAW || - mode == B_SCROLL || + if (mode == B_FORCE_REDRAW || mode == B_SCROLL || +#ifdef USE_IMAGE + mode == B_REDRAW_IMAGE || +#endif cline != buf->topLine || ccolumn != buf->currentColumn) { - if (mode == B_SCROLL && cline && buf->currentColumn == ccolumn) { + if ( +#ifdef USE_IMAGE + !(activeImage && displayImage && draw_image_flag) && +#endif + mode == B_SCROLL && cline && buf->currentColumn == ccolumn) { int n = buf->topLine->linenumber - cline->linenumber; if (n > 0 && n < LASTLINE) { move(LASTLINE, 0); @@ -258,14 +280,34 @@ displayBuffer(Buffer *buf, int mode) } redrawNLine(buf, n); } - else + else { +#ifdef USE_IMAGE + if (activeImage && + (mode == B_REDRAW_IMAGE || + cline != buf->topLine || ccolumn != buf->currentColumn)) { + if (draw_image_flag) + clear(); + clearImage(); + loadImage(IMG_FLAG_STOP); + image_touch++; + draw_image_flag = FALSE; + } +#endif redrawBuffer(buf); + } cline = buf->topLine; ccolumn = buf->currentColumn; } if (buf->topLine == NULL) buf->topLine = buf->firstLine; +#ifdef USE_IMAGE + if (buf->need_reshape) { + displayBuffer(buf, B_FORCE_REDRAW); + return; + } +#endif + #ifdef USE_MOUSE if (use_mouse) #if LANG == JA @@ -337,6 +379,14 @@ displayBuffer(Buffer *buf, int mode) message(msg->ptr, buf->cursorX + buf->rootX, buf->cursorY); standend(); refresh(); +#ifdef USE_IMAGE + if (activeImage && displayImage && buf->img) { + /* + * loadImage(IMG_FLAG_START); + */ + drawImage(); + } +#endif #ifdef USE_BUFINFO if (buf != save_current_buf) { saveBufferInfo(); @@ -377,6 +427,23 @@ redrawNLine(Buffer *buf, int n) } if (n > 0) clrtobotx(); + +#ifdef USE_IMAGE + if (!(activeImage && displayImage && buf->img)) + return; + move(buf->cursorY, buf->cursorX); + for (i = 0, l = buf->topLine; i < LASTLINE; i++) { + if (i >= LASTLINE - n || i < -n) + l0 = redrawLineImage(buf, l, i); + else { + l0 = (l) ? l->next : NULL; + } + if (l0 == NULL && l == NULL) + break; + l = l0; + } + getAllImage(buf); +#endif } #define addKanji(pc,pr) (addChar((pc)[0],(pr)[0]),addChar((pc)[1],(pr)[1])) @@ -549,6 +616,77 @@ redrawLine(Buffer *buf, Line *l, int i) return l->next; } +#ifdef USE_IMAGE +Line * +redrawLineImage(Buffer *buf, Line *l, int i) +{ + int j, pos, rcol, ncol; + int column = buf->currentColumn; + Anchor *a; + int x, y, sx, sy, w, h; + + if (l == NULL) + return NULL; + if (l->width < 0) + l->width = COLPOS(l, l->len); + if (l->len == 0 || l->width - 1 < column) + return l->next; + pos = columnPos(l, column); + rcol = COLPOS(l, pos); + for (j = 0; rcol - column < buf->COLS && pos + j < l->len; j++) { + if (rcol - column < 0) { + rcol = COLPOS(l, pos + j + 1); + continue; + } + a = retrieveAnchor(buf->img, l->linenumber, pos + j); + if (a && a->image && a->image->touch < image_touch) { + Image *image = a->image; + ImageCache *cache; + + cache = image->cache = getImage(image, baseURL(buf), + buf->image_flag); + if (cache) { + if ((image->width < 0 && cache->width > 0) || + (image->height < 0 && cache->height > 0)) { + image->width = cache->width; + image->height = cache->height; + buf->need_reshape = TRUE; + } + x = (int)((rcol - column + buf->rootX) * pixel_per_char); + y = (int)(i * pixel_per_line); + sx = (int)((rcol - COLPOS(l, a->start.pos)) * pixel_per_char); + sy = (int)((l->linenumber - image->y) * pixel_per_line); + if (sx == 0 && x + image->xoffset >= 0) + x += image->xoffset; + else + sx -= image->xoffset; + if (sy == 0 && y + image->yoffset >= 0) + y += image->yoffset; + else + sy -= image->yoffset; + if (image->width > 0) + w = image->width - sx; + else + w = (int)(8 * pixel_per_char - sx); + if (image->height > 0) + h = image->height - sy; + else + h = (int)(pixel_per_line - sy); + if (w > (int)((buf->COLS - rcol + column) * pixel_per_char)) + w = (int)((buf->COLS - rcol + column) * pixel_per_char); + if (h > (int)(LASTLINE * pixel_per_line - y)) + h = (int)(LASTLINE * pixel_per_line - y); + addImage(cache, x, y, sx, sy, w, h); + image->touch = image_touch; + draw_image_flag = TRUE; + } + } + rcol = COLPOS(l, pos + j + 1); + } + return l->next; +} +#endif + int redrawLineRegion(Buffer *buf, Line *l, int i, int bpos, int epos) { @@ -850,6 +988,8 @@ message(char *s, int return_x, int return_y) void disp_message_nsec(char *s, int redraw_current, int sec, int purge, int mouse) { + if (QuietMessage) + return; if (!fmInitialized) { fprintf(stderr, "%s\n", conv_to_system(s)); return; diff --git a/doc-jp/README.func b/doc-jp/README.func @@ -10,6 +10,7 @@ COOKIE DELETE_PREVBUF 前のバッファを消去します(主に local-CGI 用) DICT_WORD 入力した単語を辞書コマンドで調べます DICT_WORD_AT カーソル位置の単語を辞書コマンドで調べます +DISPLAY_IMAGE 画像の読込/表示を再開します DOWN 画面を1行下にスクロールします DOWNLOAD 文書のソースをファイルに保存します EDIT ソースファイルをエディタで編集します @@ -99,6 +100,7 @@ SHELL SHIFT_LEFT 画面全体を左にずらします SHIFT_RIGHT 画面全体を右にずらします SOURCE HTMLのソースを表示します +STOP_IMAGE 画像の読込/表示を停止します SUBMIT フォームにサブミットします SUSPEND サスペンド UP 画面を1行上にスクロールします diff --git a/doc-jp/README.img b/doc-jp/README.img @@ -0,0 +1,253 @@ + +w3m でインライン画像を表示 + 2002/01/31 + 坂本 浩則 + +はじめに + + w3m でインライン画像を表示する拡張です。以下に置いてあります。 + + http://www2u.biglobe.ne.jp/~hsaka/w3m/index-ja.html#img + patch/w3m-0.2.4-img-2.2.patch.gz + patch/README.img-ja + +機能 + + ・X11 上の端末(xterm,kterm,rxvt,...)上に画像(GIF,PNG,JPEG 等)を表示します。 + ・img タグで指定されたインライン画像を表示できます。 + width,height 属性に応じて必要な領域を確保してレンダリングします。 + align 属性に対応しています。 + ・Content-type: image/* な画像ファイルを直接表示できます。 + ・map タグに対応しています。 + area タグの shape, coords 属性を認識し、メニュー表示から選択できます。 + ・img タグの ismap 属性に対応しています。 + 座標値を ?<x>,<y> として URL に追加して送ります。 + ・input タグの type=image 属性で指定されたインライン画像を表示できます。 + 座標値を <name>.x=<x>&<name>.y=<y> として送ります。 + ・非同期に画像を読み込みます。 + ・画像をキャッシュできます。 + +キー操作 + + DISPLAY_IMAGE + 画像の読込/表示を再開します。 + STOP_IMAGE + そのバッファの画像の読込/表示を停止します。 + SET_OPTION display_image=toggle + 画像の読込/表示を切替えます。 + + デフォルトのキーマップはありませんので、~/.w3m/keymap に + keymap X DISPLAY_IMAGE + keymap C-c STOP_IMAGE + keymap t SET_OPTION display_image=toggle + の様に記述して使用してください。 + +コマンドラインオプション + + -ppc <pixel> + 一文字あたりの幅(pixel 値)を指定します。デフォルトは自動設定。 + 正しく設定されない場合は端末の font の大きさに必ず合わせてください。 + -ppl <pixel> + 一行あたりの幅(pixel 値)を指定します。デフォルトは自動設定。 + 正しく設定されない場合は端末の font の大きさに必ず合わせてください。 + +オプションパネル + + pixel_per_char + 一文字あたりの幅(pixel 値)を指定します。デフォルトは自動設定。 + 正しく設定されない場合は端末の font の大きさに必ず合わせてください。 + pixel_per_line + 一行あたりの幅(pixel 値)を指定します。デフォルトは自動設定。 + 正しく設定されない場合は端末の font の大きさに必ず合わせてください。 + display_image + インライン画像を表示します。デフォルトは ON。 + auto_image + インライン画像を自動で読み込みます。デフォルトは ON。 + OFF の場合は、コマンド DISPLAY_IMAGE で読み込みを開始します。 + ext_image_viewer + コマンド VIEW_IMAGE('I')の場合や Content-type: image/* である + 画像ファイルを外部ビューワで表示します。デフォルトは ON。 + OFF の場合は、インライン画像として直接表示します。 + image_scale + 画像のスケールを指定します。デフォルトは 100(%)。 + 小さい font と共に使う場合には値を小さくすると有用。 + imgdisplay + インライン画像を表示するためのコマンド。デフォルトは w3mimgdisplay。 + 下記の "w3mimgdisplay の設定" を参考にしてオプション設定してください。 + imgsize + インライン画像の大きさを得るためのコマンド。デフォルトは w3mimgsize。 + +必要なもの + + * w3m-0.2.4.tar.gz + http://w3m.sourceforge.net/ + http://sourceforge.net/projects/w3m/ + http://prdownloads.sourceforge.net/w3m/ + * Imlib-1.9.8 (1.9.10 以上推奨) + libungif-4.1.0b1 推奨 + +インストール + + gunzip -c DIST/w3m-0.2.4.tar.gz | tar -xvf - + cd w3m-0.2.4 + gunzip -c DIST/w3m-0.2.4-img-2.2.patch.gz | patch -p1 + configure + # Inline image support (you need Imlib library) + # と聞かれますので y と答えてください。 + # menu は有効にしてください。 + make + # w3mimgdisplay, w3mimgsize を make する時に Imlib が必要です。 + make install + # w3mimgdisplay, w3mimgsize は必ず $LIB(PREFIX/lib/w3m) へ + # install してください。 + +w3mimgdisplay の設定 + + w3mimgdisplay は以下のオプションを受け付けますので端末に合わせて + オプション設定パネルで(または -o オプションで)設定してください。 + + -x <offset_x> + 端末上に画像を表示する X 方向の原点。デフォルトは 2 ですが、 + xterm や kterm ではスクロールバーの幅を計算して加えようとします。 + (正しく出来ないかもしれません。) + Eterm では 5 にすべきかもしれません。 + -y <offset_y> + 端末上に画像を表示する Y 方向の原点。デフォルトは 2。 + Eterm では 5 にすべきかもしれません。 + -bg <background> + 端末の背景色。デフォルトは自動設定。 + #RRGGBB で指定する場合は # をエスケープして設定してください。 + + 例) + w3m -o 'imgdisplay=w3mimgdisplay -x 5 -bg "#cccccc"' + +更新記録 + +2002/01/31 w3m-0.2.4-img-2.2 + * w3m-0.2.4+cvs-1.278 ベース。 + +2002/01/29 w3m-0.2.4-img-2.1 + * w3m-0.2.4+cvs-1.268 ベース。 + +2002/01/28 w3m-0.2.4-img-2.0 + * w3m-0.2.4+cvs-1.265 ベース。 + * pixel_per_char, pixel_per_line を自動設定するようにした。 + * 端末の背景色を自動設定するようにした。 + * 画像処理関係のソースを image.c に分離。 + +2002/01/08 w3m-0.2.4-img-1.18 + * w3m-0.2.4 ベース。 + +2001/12/29 w3m-0.2.3.2-img-1.17 + * w3m-0.2.3.2+cvs-1.196 ベース。 + +2001/12/25 w3m-0.2.3.2-img-1.16.1 + * [w3m-dev 02698] Thanks > かずひこ@kondara.org さん + +2001/12/22 w3m-0.2.3.2-img-1.16 + * w3m-0.2.3.2 ベース。 + +2001/12/20 w3m-0.2.3.1-img-1.15 + * w3m-0.2.3.1 ベース。 + * Content-Transfer-Encoding で送られて来た画像を表示可能にした。 + +2001/11/29 + * ChangLog 1.71 時点の CVS ソースに対してマージ開始 + +2001/11/17 w3m-0.2.2-img-1.14 + * w3m-0.2.2 ベース。 + +2001/11/14 w3m-0.2.1-inu-1.6-img-1.13 + * w3m-0.2.1-inu-1.6 ベース。 + +2001/11/05 w3m-0.2.1-inu-1.5-img-1.12 + * w3m-0.2.1-inu-1.5 ベース。 + * <area><map> が使えなくなっていたバグの修正。 + * kterm 上で xwnmo を使った場合に対応。 + +2001/10/03 w3m-0.2.1-inu-1.4-img-1.11 + * w3m-0.2.1-inu-1.4 ベース。 + * 標準入力から読み込む時に落ちるバグの修正。 + * configure の修正。Thanks > 深川さん。 + +2001/08/01 w3m-0.2.1-img-1.10 + * 画像の位置の微調整。 + * スケールのバグ修正。 + +2001/07/31 w3m-0.2.1-img-1.9 + * initImgdisplay() の修正。Thanks > David. + +2001/07/29 w3m-0.2.1-img-1.8 + * configure の修正。Thanks > 坂根さん。 + +2001/07/28 w3m-0.2.1-img-1.7 + * configure, XMakefile が patch に入って無かった。 + * 画像を表示しない場合の処理をオリジナルに近づけた。 + * [w3m-dev 02121] に対応。 + +2001/07/27 w3m-0.2.1-img-1.6 + * README.img を doc-jp へ移動。doc/README.img を作成。 + * インライン画像対応部分を USE_IMAGE マクロで分離。 + * configure でインライン画像対応を選択できる様にした。 + * configure で Imlib をチェックする様にした。 + +2001/07/26 w3m-0.2.1-img-1.5 + * w3mimgdisplay は必要になるまで立ち上げない様にした。 + * w3mimgdisplay が落ちた時に、w3mimgdisplay を再立ち上げできる様にした。 + * <img align=middle の場合の計算間違いの修正。 + * [w3m-dev 02118] に対応。 + * funcname.tab が間違っていたので修正。 + +2001/07/25 w3m-0.2.1-img-1.4 + * w3mimgdisplay を環境変数 WINDOWID を見る様に改良。 + また、text window の推量部分も改良。 + * image タグを img タグと同じものとして追加。 + * [w3m-dev 02090], [w3m-dev 02097] に対応。 + +2001/07/14 w3m-0.2.1-img-1.3 + * ext_image_viewer が OFF の場合は画像を直接フレーム表示可能にした。 + * Option Panel が SEGV するバグの修正。 + +2001/07/13 w3m-0.2.1-img-1.2 + * 画像のスケールを指定出来る様にした。 + * SIGUSR1 のブロックに関する修正。 + +2001/07/12 w3m-0.2.1-img-1.1 + * キー入力中以外は SIGUSR1, SIGWINCH をブロックする様にした。 + * バグ修正。 + +2001/07/11 w3m-0.2.1-img-1.0 + * MGL 版の画像読み込みを採用。 + +2001/07/10 w3m-0.2.1-img-0.5 + * 描画の高速化。w3mimgdisplay で不要な XSync() を止めた。 + 不要な drawImage() を止めた。 + +2001/07/08 w3m-0.2.1-img-0.4 + * w3mimgdisplay での Window の取得や offset_x のデフォルト値の改良。 + * <img align=middle の場合の計算間違いの修正。 + * <img align=left|center|right では <div>〜</div> を使う様にしてみた。 + * w3mimgdisplay では SIGINT を無視する様にした。 + * w3mimgsize もオプション設定できる様にした。 + +2001/07/07 w3m-0.2.1-img-0.3 + * kterm に限らず、X11 上の端末では画像を描画できる様にした。 + +2001/07/06 w3m-0.2.1-img-0.2 + * README.img を作成。 + * kterm-6.2.0-img-0.2.patch を w3m-0.2.1-img-0.2.patch に含める様にした。 + * コードの整理、安全側への修正 + +2001/07/04 w3m-0.2.1-img-0.1 + * バージョン管理開始。 + * Imlib 対応版。 + +2001/06/30 + * XPM 版でほぼ実装完了。 + +2001/06/19 + * MGL 版に刺激を受けて img への対応のテストを開始。 + +----------------------------------- +坂本 浩則 <hsaka@mth.biglobe.ne.jp> + http://www2u.biglobe.ne.jp/~hsaka/ diff --git a/doc/README.func b/doc/README.func @@ -10,6 +10,7 @@ COOKIE View cookie list DELETE_PREVBUF Delete previous buffer (mainly for local-CGI) DICT_WORD Execute dictionary command (see README.dict) DICT_WORD_AT Execute dictionary command for word at cursor +DISPLAY_IMAGE Restart loading and drawing of images DOWN Scroll down one line DOWNLOAD Save document source to file EDIT Edit current document @@ -99,6 +100,7 @@ SHELL Execute shell command SHIFT_LEFT Shift screen left SHIFT_RIGHT Shift screen right SOURCE View HTML source +STOP_IMAGE Stop loading and drawing of images SUBMIT Submit form SUSPEND Stop loading document UP Scroll up one line diff --git a/doc/README.img b/doc/README.img @@ -0,0 +1,189 @@ + +Inline image support of w3m + 2002/01/31 + H. Sakamoto + +Introduction + + This is the extension for w3m to support inline image. + The patch for w3m-0.2.4 is available on the following site. + + http://www2u.biglobe.ne.jp/~hsaka/w3m/index.html#img + patch/w3m-0.2.4-2.2.patch.gz + patch/README.img + +Support + + * Display inline image (GIF,PNG,JPEG, etc.) on terminals + (xterm,rxvt, etc.) of X11. + * Support inline image of <img> tag. + Support of attributes "width", "height", and "align". + * Direct display of image file which header is "Content-type: image/*" + * Support of <map> tag. + Support of attributes "shape" and "coords" of <area> tag. + * Support of an attribute "ismap" of <img> tag. + "w3m" adds coordinate of the cursor as ?<x>,<y> to url, and sends url. + * Support of an attribute "type=image" of <input> tag. + "w3m" sends coordinate of the cursor as <name>.x=<x>&<name>.y=<y>. + * Asynchronous loading of image files. + * Using cache of image file as pixmap. + +Key functions + + DISPLAY_IMAGE + Restart loading and drawing of images. + STOP_IMAGE + Stop loading and drawing of images in the current buffer. + SET_OPTION display_image=toggle + Toggle loading and drawing of images. + + These functions are not keybinded as default. + Specify the following keymaps in ~/.w3m/keymap. + keymap X DISPLAY_IMAGE + keymap C-c STOP_IMAGE + keyamp t SET_OPTION display_image=toggle + +Comandline options + + -ppc <pixel> + # of pixels per character. The default value is automatically + detected. Must fit the width of font of terminal. + -ppl <pixel> + # of pixels per character. The default value is automatically + detected. Must fit the height of font of terminal. + +Option panel + + pixel_per_char + # of pixels per character. The default value is automatically + detected. Must fit the width of font of terminal. + pixel_per_line + # of pixels per character. The default value is automatically + detected. Must fit the height of font of terminal. + display_image + Display of inline image. The default is ON. + auto_image + Automatic loading of inline image. The default is ON. + If it is OFF, loading starts with a command DISPLAY_IMAGE. + ext_image_viewer + Use external image viewer, when a command VIEW_IMAGE or + view of image file which header is "Content-type: image/*". + The default is ON. If it is OFF, the image is directly displaied. + image_scale + Scale of image (%). The default value is 100(%). + imgdisplay + External command to display image". The default value is "w3mimgdisplay". + See "Setting w3mimgdisplay". + imgsize + External command to get size of image. The default value is "w3mimgsize". + +Required programs + + * w3m-0.2.4 + http://w3m.sourceforge.net/ + http://sourceforge.net/projects/w3m/ + http://prdownloads.sourceforge.net/w3m/ + * Imlib-1.9.8 (1.9.10 is recommendable.) + libungif-4.1.0b1 is recommendable. + +Install + + gunzip -c DIST/w3m-0.2.4.tar.gz | tar -xvf - + cd w3m-0.2.4 + gunzip -c DIST/w3m-0.2.4-img-2.2.patch.gz | patch -p1 + configure + # When you are asked "Inline image support (you need Imlib library)", + # answer "y". + # Select menu. + make + # To make "w3mimgdisplay" and "w3mimgsize", Imlib is required. + make install + # Must install "w3mimgdisplay" and "w3mimgsize" to $LIB(PREFIX/lib/w3m). + +Setting w3mimgdisplay + + "w3mimgdisplay" has the following options. Set options to fit terminal. + + -x <offset_x> + The X origin of display of image on terminal. The default value is 2. + If the terminal is "xterm", the width of scroll bar is added. + If the terminal is "Eterm", it may be better to specify 5. + -y <offset_y> + The Y origin of display of image on terminal. The default value is 2. + If the terminal is "Eterm", it may be better to specify 5. + -bg <background> + Background color of terminal. The default value is automatically + detected. When the color is specified as #RRGGBB, escape '#'. + + ex.) + w3m -o 'imgdisplay=w3mimgdisplay -x 5 -bg "#cccccc"' + +Change log + +2002/01/31 w3m-0.2.4-img-2.2 + * Based on w3m-0.2.4+cvs-1.278. + +2002/01/29 w3m-0.2.4-img-2.1 + * Based on w3m-0.2.4+cvs-1.268. + +2002/01/28 w3m-0.2.4-img-2.0 + * Based on w3m-0.2.4+cvs-1.265. + * pixel_per_char and pixel_per_line are automatically detected. + * The bckground color of terminal is automatically detected. + * The source code to display images is moved to image.c + +2002/01/08 w3m-0.2.4-img-1.18 + * Based on w3m-0.2.4 + +2001/12/29 w3m-0.2.3.2-img-1.17 + * Based on w3m-0.2.3.2+cvs-1.196. + +2001/12/25 w3m-0.2.3.2-img-1.16.1 + * [w3m-dev 02698] Thanks > Kazuhiko-san + +2001/12/22 w3m-0.2.3.2-img-1.16 + * Based on w3m-0.2.3.2. + +2001/12/20 w3m-0.2.3.1-img-1.15 + * Based on w3m-0.2.3.1. + * Support display of image with Content-Transfer-Encoding. + +2001/11/29 + * Start merge against CVS source (ChangeLog 1.71) + +2001/11/17 w3m-0.2.2-img-1.14 + * Based on w3m-0.2.2. + +2001/11/14 w3m-0.2.1-inu-1.6-img-1.13 + * Based on w3m-0.2.1-inu-1.6. + +2001/11/05 w3m-0.2.1-inu-1.5-img-1.12 + * Based on w3m-0.2.1-inu-1.5. + * Fixed the bug for <area>, <map>. + * Fixed the problem with xwnmo on kterm. + +2001/10/03 w3m-0.2.1-inu-1.4-img-1.11 + * Based on w3m-0.2.1-inu-1.4. + * Fixed bug when reading from stdin. + * Fixed "configure". Thanks > Fukagawa-san. + +2001/08/01 w3m-0.2.1-img-1.10 + * Adjust image position. + * Fixed scaling image. + +2001/07/31 w3m-0.2.1-img-1.9 + * Fixed initImgdisplay(). Thanks > David. + +2001/07/29 w3m-0.2.1-img-1.8 + * Fixed "configure". + +2001/07/28 w3m-0.2.1-img-1.7 + * Sorry, w3m-0.2.1-img-1.6 is not complete. + * Added "configure" and "Makefile" to the patch. + +2001/07/27 w3m-0.2.1-img-1.6 + * Created doc/README.img. + +------------------------------------------- +Hironori Sakamoto <hsaka@mth.biglobe.ne.jp> + http://www2u.biglobe.ne.jp/~hsaka/ diff --git a/etc.c b/etc.c @@ -1054,6 +1054,7 @@ reset_signals(void) #ifdef SIGPIPE signal(SIGPIPE, SIG_IGN); #endif + signal(SIGUSR1, SIG_IGN); } void diff --git a/file.c b/file.c @@ -25,6 +25,9 @@ #define min(a,b) ((a) > (b) ? (b) : (a)) #endif /* not min */ +static int frame_source = 0; + +static int _MoveFile(char *path1, char *path2); static void uncompress_stream(URLFile *uf); static FILE *lessopen_stream(char *path); static Buffer *loadcmdout(char *cmd, @@ -47,6 +50,13 @@ static JMP_BUF AbortLoading; static struct table *tables[MAX_TABLE]; static struct table_mode table_mode[MAX_TABLE]; +#ifdef USE_IMAGE +static ParsedURL *cur_baseURL = NULL; +#ifdef JP_CHARSET +static char cur_document_code; +#endif +#endif + static Str cur_select; static Str select_str; static int select_is_multiple; @@ -113,6 +123,9 @@ static int form_sp = 0; static int current_content_length; static int cur_hseq; +#ifdef USE_IMAGE +static int cur_iseq; +#endif #define MAX_UL_LEVEL 9 #ifdef KANJI_SYMBOLS @@ -1423,10 +1436,10 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer, /* openURL failure: it means either (1) the requested URL is a directory name * on an FTP server, or (2) is a local directory name. */ - if (fmInitialized && prevtrap) { + if (fmInitialized) term_raw(); + if (prevtrap) signal(SIGINT, prevtrap); - } switch (f.scheme) { case SCM_FTPDIR: { @@ -1501,10 +1514,9 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer, /* openURL() succeeded */ if (SETJMP(AbortLoading) != 0) { /* transfer interrupted */ - if (fmInitialized) { + if (fmInitialized) term_raw(); - signal(SIGINT, prevtrap); - } + signal(SIGINT, prevtrap); if (b) discardBuffer(b); UFclose(&f); @@ -1519,10 +1531,9 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer, } if (header_string) header_string = NULL; - if (fmInitialized) { - prevtrap = signal(SIGINT, KeyAbort); + prevtrap = signal(SIGINT, KeyAbort); + if (fmInitialized) term_cbreak(); - } if (pu.scheme == SCM_HTTP || #ifdef USE_SSL pu.scheme == SCM_HTTPS || @@ -1755,14 +1766,17 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer, if (real_type == NULL) real_type = t; proc = loadBuffer; +#ifdef USE_IMAGE + cur_baseURL = New(ParsedURL); + copyParsedURL(cur_baseURL, &pu); +#endif if (do_download) { /* download only */ char *file; - if (fmInitialized) { + if (fmInitialized) term_raw(); - signal(SIGINT, prevtrap); - } + signal(SIGINT, prevtrap); if (DecodeCTE && IStype(f.stream) != IST_ENCODED) f.stream = newEncodedStream(f.stream, f.encoding); if (pu.scheme == SCM_LOCAL) @@ -1786,11 +1800,33 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer, f.compression = CMP_NOCOMPRESS; } } +#ifdef USE_IMAGE + if (image_source) { + Buffer *b = NULL; + if (IStype(f.stream) != IST_ENCODED) + f.stream = newEncodedStream(f.stream, f.encoding); + if (save2tmp(f, image_source) == 0) { + b = newBuffer(INIT_BUFFER_WIDTH); + b->sourcefile = image_source; + b->real_type = t; + } + if (fmInitialized) + term_raw(); + signal(SIGINT, prevtrap); + UFclose(&f); + return b; + } +#endif if (!strcasecmp(t, "text/html")) proc = loadHTMLBuffer; else if (is_plain_text_type(t)) proc = loadBuffer; +#ifdef USE_IMAGE + else if (activeImage && displayImage && !useExtImageViewer && + !w3m_dump && !strncasecmp(t, "image/", 6)) + proc = loadImageBuffer; +#endif #ifdef USE_GOPHER else if (!strcasecmp(t, "gopher:directory")) { proc = loadGopherDir; @@ -1808,17 +1844,15 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer, copyParsedURL(&b->currentURL, &pu); } UFclose(&f); - if (fmInitialized) { + if (fmInitialized) term_raw(); - signal(SIGINT, prevtrap); - } + signal(SIGINT, prevtrap); return b; } else { - if (fmInitialized) { + if (fmInitialized) term_raw(); - signal(SIGINT, prevtrap); - } + signal(SIGINT, prevtrap); if (pu.scheme == SCM_LOCAL) { UFclose(&f); doFileCopy(pu.real_file, @@ -1852,7 +1886,9 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer, t_buf->ssl_certificate = s->ptr; } #endif + frame_source = flag & RG_FRAME_SRC; b = loadSomething(&f, pu.real_file ? pu.real_file : pu.file, proc, t_buf); + frame_source = 0; UFclose(&f); if (b) { b->real_scheme = f.scheme; @@ -1866,6 +1902,10 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer, Str s = Strnew_charp(t); b->type = s->ptr; } +#ifdef USE_IMAGE + else if (proc == loadImageBuffer) + b->type = b->real_type; +#endif else b->type = "text/plain"; if (pu.label) { @@ -1900,10 +1940,9 @@ loadGeneralFile(char *path, ParsedURL *volatile current, char *referer, } if (header_string) header_string = NULL; - if (fmInitialized) { + if (fmInitialized) term_raw(); - signal(SIGINT, prevtrap); - } + signal(SIGINT, prevtrap); return b; } @@ -2712,12 +2751,16 @@ restore_fonteffect(struct html_feed_environ *h_env, struct readbuffer *obuf) push_tag(obuf, "<u>", HTML_U); } - Str -process_img(struct parsed_tag *tag) +process_img(struct parsed_tag *tag, int width) { char *p, *q, *r, *r2, *s; - int w, i; +#ifdef USE_IMAGE + int w, i, nw, ni, n, w0, i0, align, xoffset, yoffset, top, bottom, ismap; + int use_image = activeImage && displayImage; +#else + int w, i, nw, n; +#endif Str tmp = Strnew(); if (!parsedtag_get_value(tag, ATTR_SRC, &p)) @@ -2725,69 +2768,231 @@ process_img(struct parsed_tag *tag) q = NULL; parsedtag_get_value(tag, ATTR_ALT, &q); w = -1; - parsedtag_get_value(tag, ATTR_WIDTH, &w); - i = -1; - parsedtag_get_value(tag, ATTR_HEIGHT, &i); + if (parsedtag_get_value(tag, ATTR_WIDTH, &w)) { + if (w < 0) { + if (width > 0) + w = (int)(-width * pixel_per_char * w / 100 + 0.5); + else + w = -1; + } +#ifdef USE_IMAGE + if (use_image) { + if (w > 0) { + w = (int)(w * image_scale / 100 + 0.5); + if (w == 0) + w = 1; + } + } +#endif + } +#ifdef USE_IMAGE + if (use_image) { + i = -1; + if (parsedtag_get_value(tag, ATTR_HEIGHT, &i)) { + if (i > 0) { + i = (int)(i * image_scale / 100 + 0.5); + if (i == 0) + i = 1; + } + else { + i = -1; + } + } + align = -1; + parsedtag_get_value(tag, ATTR_ALIGN, &align); + ismap = 0; + if (parsedtag_exists(tag, ATTR_ISMAP)) + ismap = 1; + } + else +#endif + parsedtag_get_value(tag, ATTR_HEIGHT, &i); r = NULL; parsedtag_get_value(tag, ATTR_USEMAP, &r); tmp = Strnew_size(128); +#ifdef USE_IMAGE + if (use_image) { + switch (align) { + case ALIGN_LEFT: + Strcat_charp(tmp, "<div align=left>"); + break; + case ALIGN_CENTER: + Strcat_charp(tmp, "<div align=center>"); + break; + case ALIGN_RIGHT: + Strcat_charp(tmp, "<div align=right>"); + break; + } + } +#endif if (r) { r2 = strchr(r, '#'); s = "<form_int method=internal action=map>"; process_form(parse_tag(&s, TRUE)); - Strcat(tmp, Sprintf("<pre_int><input_alt fid=\"%d\" " + Strcat(tmp, Sprintf("<input_alt fid=\"%d\" " "type=hidden name=link value=\"", cur_form_id)); Strcat_charp(tmp, html_quote((r2) ? r2 + 1 : r)); Strcat(tmp, Sprintf("\"><input_alt hseq=\"%d\" fid=\"%d\" " "type=submit no_effect=true>", cur_hseq++, cur_form_id)); } - if (q != NULL && *q == '\0' && ignore_null_img_alt) - q = NULL; - if (q != NULL || r != NULL) - Strcat_charp(tmp, "<img_alt src=\""); +#ifdef USE_IMAGE + if (use_image) { + w0 = w; + i0 = i; + if (w < 0 || i < 0) { + char *url, *ext; + Image image; + ParsedURL u; + +#ifdef JP_CHARSET + parseURL2(conv(p, InnerCode, cur_document_code)->ptr, &u, + cur_baseURL); +#else + parseURL2(p, &u, cur_baseURL); +#endif + image.url = parsedURL2Str(&u)->ptr; + image.ext = filename_extension(u.file, TRUE); + image.cache = NULL; + image.width = w; + image.height = i; + + image.cache = getImage(&image, cur_baseURL, IMG_FLAG_SKIP); + if (image.cache && image.cache->width > 0 && + image.cache->height > 0) { + w = w0 = image.cache->width; + i = i0 = image.cache->height; + } + if (w < 0) + w = 8 * pixel_per_char; + if (i < 0) + i = pixel_per_line; + } + nw = (w > 3) ? (int)((w - 3) / pixel_per_char + 1) : 1; + ni = (i > 3) ? (int)((i - 3) / pixel_per_line + 1) : 1; + Strcat(tmp, + Sprintf("<pre_int><img_alt hseq=\"%d\" src=\"", cur_iseq++)); + } else - Strcat_charp(tmp, "<nobr><img_alt src=\""); +#endif + { + if (w < 0) + w = 12 * pixel_per_char; + nw = w ? (int)((w - 1) / pixel_per_char + 1) : 1; + if (r) + Strcat_charp(tmp, "<pre_int>"); + Strcat_charp(tmp, "<img_alt src=\""); + } Strcat_charp(tmp, html_quote(p)); - Strcat_charp(tmp, "\">"); + Strcat_charp(tmp, "\""); +#ifdef USE_IMAGE + if (use_image) { + if (w0 >= 0) + Strcat(tmp, Sprintf(" width=%d", w0)); + if (i0 >= 0) + Strcat(tmp, Sprintf(" height=%d", i0)); + switch (align) { + case ALIGN_TOP: + top = 0; + bottom = ni - 1; + yoffset = 0; + break; + case ALIGN_MIDDLE: + top = ni / 2; + bottom = top; + if (top * 2 == ni) + yoffset = (int)(((ni + 1) * pixel_per_line - i) / 2); + else + yoffset = (int)((ni * pixel_per_line - i) / 2); + break; + case ALIGN_BOTTOM: + top = ni - 1; + bottom = 0; + yoffset = (int)(ni * pixel_per_line - i); + break; + default: + top = ni - 1; + bottom = 0; + if (ni == 1 && ni * pixel_per_line > i) + yoffset = 0; + else { + yoffset = (int)(ni * pixel_per_line - i); + if (yoffset <= -2) + yoffset++; + } + break; + } + xoffset = (int)((nw * pixel_per_char - w) / 2); + if (xoffset) + Strcat(tmp, Sprintf(" xoffset=%d", xoffset)); + if (yoffset) + Strcat(tmp, Sprintf(" yoffset=%d", yoffset)); + if (top) + Strcat(tmp, Sprintf(" top_margin=%d", top)); + if (bottom) + Strcat(tmp, Sprintf(" bottom_margin=%d", bottom)); + if (r) { + Strcat_charp(tmp, " usemap=\""); + Strcat_charp(tmp, html_quote((r2) ? r2 + 1 : r)); + Strcat_charp(tmp, "\""); + } + if (ismap) + Strcat_charp(tmp, " ismap"); + } +#endif + Strcat_charp(tmp, ">"); + if (q != NULL && *q == '\0' && ignore_null_img_alt) + q = NULL; if (q != NULL) { - Strcat_charp(tmp, html_quote(q)); - Strcat_charp(tmp, "</img_alt> "); - goto img_end2; + n = strlen(q); +#ifdef USE_IMAGE + if (use_image) { + if (n > nw) { + n = nw; + Strcat_charp(tmp, html_quote(Strnew_charp_n(q, nw)->ptr)); + } + else + Strcat_charp(tmp, q); + } + else +#endif + Strcat_charp(tmp, q); + goto img_end; } if (w > 0 && i > 0) { /* guess what the image is! */ if (w < 32 && i < 48) { /* must be an icon or space */ + n = 1; if (strcasestr(p, "space") || strcasestr(p, "blank")) - Strcat_charp(tmp, "_</img_alt>"); + Strcat_charp(tmp, "_"); else { if (w * i < 8 * 16) - Strcat_charp(tmp, "*</img_alt>"); + Strcat_charp(tmp, "*"); else { #ifdef KANJI_SYMBOLS - Strcat_charp(tmp, "●</img_alt>"); + Strcat_charp(tmp, "●"); + n = 2; #else /* not KANJI_SYMBOLS */ - Strcat_charp(tmp, "#</img_alt>"); + Strcat_charp(tmp, "#"); #endif /* not KANJI_SYMBOLS */ } } - goto img_end1; + goto img_end; } if (w > 200 && i < 13) { /* must be a horizontal line */ #ifndef KANJI_SYMBOLS Strcat_charp(tmp, "<_RULE TYPE=10>"); #endif /* not KANJI_SYMBOLS */ - w /= pixel_per_char; - for (i = 0; i < w - (HR_RULE_WIDTH - 1); i += HR_RULE_WIDTH) + for (i = 0; i < nw - (HR_RULE_WIDTH - 1); i += HR_RULE_WIDTH) Strcat_charp(tmp, HR_RULE); #ifndef KANJI_SYMBOLS Strcat_charp(tmp, "</_RULE>"); #endif /* not KANJI_SYMBOLS */ - Strcat_charp(tmp, "</img_alt>"); - goto img_end1; + n = i; + goto img_end; } } for (q = p; *q; q++) ; @@ -2796,27 +3001,50 @@ process_img(struct parsed_tag *tag) if (*q == '/') q++; Strcat_char(tmp, '['); + n = 1; p = q; for (; *q; q++) { if (!IS_ALNUM(*q) && *q != '_' && *q != '-') { break; } - else if (w > 0 && !IS_ALNUM(*q) - && q - p + 2 > (int)(w / pixel_per_char)) { - Strcat_charp(tmp, ".."); - break; - } Strcat_char(tmp, *q); + n++; + if (n + 1 >= nw) + break; + } + Strcat_char(tmp, ']'); + n++; + img_end: +#ifdef USE_IMAGE + if (use_image) { + for (; n < nw; n++) + Strcat_char(tmp, ' '); } - Strcat_charp(tmp, "]</img_alt>"); - img_end1: - if (r == NULL) - Strcat_charp(tmp, "</nobr>"); - img_end2: +#endif + Strcat_charp(tmp, "</img_alt>"); +#ifdef USE_IMAGE + if (use_image) { + Strcat_charp(tmp, "</pre_int>"); + } + else +#endif + if (r) + Strcat_charp(tmp, "</pre_int>"); if (r) { - Strcat_charp(tmp, "</input_alt></pre_int>"); + Strcat_charp(tmp, "</input_alt>"); process_n_form(); } +#ifdef USE_IMAGE + if (use_image) { + switch (align) { + case ALIGN_RIGHT: + case ALIGN_CENTER: + case ALIGN_LEFT: + Strcat_charp(tmp, "</div>"); + break; + } + } +#endif return tmp; } @@ -2838,8 +3066,7 @@ Str process_input(struct parsed_tag *tag) { int i, w, v, x, y, z, iw, ih; - char *q, *p, *r, *p2; - char *pi = NULL; + char *q, *p, *r, *p2, *s; Str tmp; char *qq = ""; int qlen = 0; @@ -2928,6 +3155,20 @@ process_input(struct parsed_tag *tag) Strcat_charp(tmp, "<u>"); break; case FORM_INPUT_IMAGE: + s = NULL; + parsedtag_get_value(tag, ATTR_SRC, &s); + if (s) { + Strcat(tmp, Sprintf("<img src=\"%s\"", html_quote(s))); + if (p2) + Strcat(tmp, Sprintf(" alt=\"%s\"", html_quote(p2))); + if (parsedtag_get_value(tag, ATTR_WIDTH, &iw)) + Strcat(tmp, Sprintf(" width=\"%d\"", iw)); + if (parsedtag_get_value(tag, ATTR_HEIGHT, &ih)) + Strcat(tmp, Sprintf(" height=\"%d\"", ih)); + Strcat_charp(tmp, ">"); + Strcat_charp(tmp, "</input_alt></pre_int>"); + return tmp; + } case FORM_INPUT_SUBMIT: case FORM_INPUT_BUTTON: case FORM_INPUT_RESET: @@ -2953,23 +3194,6 @@ process_input(struct parsed_tag *tag) Strcat_char(tmp, ' '); } break; - case FORM_INPUT_IMAGE: - parsedtag_get_value(tag, ATTR_SRC, &pi); - if (pi) { - Strcat(tmp, Sprintf("<img_alt src=\"%s\"", html_quote(pi))); - if (parsedtag_get_value(tag, ATTR_WIDTH, &iw)) - Strcat(tmp, Sprintf(" width=\"%d\"", iw)); - if (parsedtag_get_value(tag, ATTR_HEIGHT, &ih)) - Strcat(tmp, Sprintf(" height=\"%d\"", ih)); - Strcat_charp(tmp, ">"); - if (p2) - Strcat_charp(tmp, html_quote(p2)); - else - Strcat_charp(tmp, qq); - Strcat_charp(tmp, "</img_alt>"); - break; - } - /* FALL THROUGH */ case FORM_INPUT_SUBMIT: case FORM_INPUT_BUTTON: if (p2) @@ -3966,12 +4190,24 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env) close_anchor(h_env, obuf); return 1; case HTML_IMG: - tmp = process_img(tag); + tmp = process_img(tag, h_env->limit); HTMLlineproc1(tmp->ptr, h_env); return 1; case HTML_IMG_ALT: if (parsedtag_get_value(tag, ATTR_SRC, &p)) obuf->img_alt = Strnew_charp(p); +#ifdef USE_IMAGE + i = 0; + if (parsedtag_get_value(tag, ATTR_TOP_MARGIN, &i)) { + if (i > obuf->top_margin) + obuf->top_margin = i; + } + i = 0; + if (parsedtag_get_value(tag, ATTR_BOTTOM_MARGIN, &i)) { + if (i > obuf->bottom_margin) + obuf->bottom_margin = i; + } +#endif return 0; case HTML_N_IMG_ALT: if (obuf->img_alt) { @@ -4203,6 +4439,14 @@ HTMLtagproc1(struct parsed_tag *tag, struct html_feed_environ *h_env) } return 1; case HTML_BASE: +#ifdef USE_IMAGE + p = NULL; + if (parsedtag_get_value(tag, ATTR_HREF, &p)) { + if (!cur_baseURL) + cur_baseURL = New(ParsedURL); + parseURL(p, cur_baseURL, NULL); + } +#endif case HTML_MAP: case HTML_N_MAP: case HTML_AREA: @@ -4294,7 +4538,7 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit) { Anchor *a_href = NULL, *a_img = NULL, *a_form = NULL; char outc[LINELEN]; - char *p, *q, *r, *str; + char *p, *q, *r, *s, *str; Lineprop outp[LINELEN], mode, effect; int pos; int nlines; @@ -4450,9 +4694,67 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit) break; case HTML_IMG_ALT: if (parsedtag_get_value(tag, ATTR_SRC, &p)) { +#ifdef USE_IMAGE + int w = -1, h = -1, iseq = 0, ismap = 0; + int xoffset = 0, yoffset = 0, top = 0, bottom = 0; + parsedtag_get_value(tag, ATTR_HSEQ, &iseq); + parsedtag_get_value(tag, ATTR_WIDTH, &w); + parsedtag_get_value(tag, ATTR_HEIGHT, &h); + parsedtag_get_value(tag, ATTR_XOFFSET, &xoffset); + parsedtag_get_value(tag, ATTR_YOFFSET, &yoffset); + parsedtag_get_value(tag, ATTR_TOP_MARGIN, &top); + parsedtag_get_value(tag, ATTR_BOTTOM_MARGIN, &bottom); + if (parsedtag_exists(tag, ATTR_ISMAP)) + ismap = 1; + q = NULL; + parsedtag_get_value(tag, ATTR_USEMAP, &q); + if (iseq > 0) { + buf->imarklist = putHmarker(buf->imarklist, + currentLn(buf), pos, + iseq - 1); + } +#endif p = remove_space(p); p = url_quote_conv(p, buf->document_code); a_img = registerImg(buf, p, currentLn(buf), pos); +#ifdef USE_IMAGE + a_img->hseq = iseq; + a_img->image = NULL; + if (iseq > 0) { + ParsedURL u; + Image *image; + + parseURL2(a_img->url, &u, cur_baseURL); + a_img->image = image = New(Image); + image->url = parsedURL2Str(&u)->ptr; + image->ext = filename_extension(u.file, TRUE); + image->cache = NULL; + image->width = w; + image->height = h; + image->xoffset = xoffset; + image->yoffset = yoffset; + image->y = currentLn(buf) - top; + if (image->xoffset < 0 && pos == 0) + image->xoffset = 0; + if (image->yoffset < 0 && image->y == 1) + image->yoffset = 0; + image->rows = 1 + top + bottom; + image->map = q; + image->ismap = ismap; + image->touch = 0; + image->cache = getImage(image, cur_baseURL, + IMG_FLAG_SKIP); + } + else if (iseq < 0) { + BufferPoint *po = buf->imarklist->marks - iseq - 1; + Anchor *a = retrieveAnchor(buf->img, + po->line, po->pos); + if (a) { + a_img->url = a->url; + a_img->image = a->image; + } + } +#endif } effect |= PE_IMAGE; break; @@ -4514,9 +4816,8 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit) if (parsedtag_get_value(tag, ATTR_NAME, &p)) { MapList *m = New(MapList); m->name = Strnew_charp(p); + m->area = newGeneralList(); m->next = buf->maplist; - m->urls = newTextList(); - m->alts = newTextList(); buf->maplist = m; } break; @@ -4527,13 +4828,19 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit) if (buf->maplist == NULL) /* outside of <map>..</map> */ break; if (parsedtag_get_value(tag, ATTR_HREF, &p)) { + MapArea *a; p = remove_space(p); p = url_quote_conv(p, buf->document_code); - pushText(buf->maplist->urls, p); - if (parsedtag_get_value(tag, ATTR_ALT, &q)) - pushText(buf->maplist->alts, q); - else - pushText(buf->maplist->alts, ""); + q = ""; + parsedtag_get_value(tag, ATTR_ALT, &q); + r = NULL; + s = NULL; +#ifdef USE_IMAGE + parsedtag_get_value(tag, ATTR_SHAPE, &r); + parsedtag_get_value(tag, ATTR_COORDS, &s); +#endif + a = newMapArea(p, q, r, s); + pushValue(buf->maplist->area, (void *)a); } break; case HTML_FRAMESET: @@ -4634,6 +4941,9 @@ HTMLlineproc2body(Buffer *buf, Str (*feed) (), int llimit) fclose(debug); if (n_textarea) addMultirowsForm(buf, buf->formitem); +#ifdef USE_IMAGE + addMultirowsImg(buf, buf->img); +#endif } void @@ -5415,6 +5725,9 @@ loadHTMLstream(URLFile *f, Buffer *newBuf, FILE * src, int internal) char code; struct html_feed_environ htmlenv1; struct readbuffer obuf; +#ifdef USE_IMAGE + int image_flag; +#endif MySignalHandler(*volatile prevtrap) (SIGNAL_ARG) = NULL; n_textarea = 0; @@ -5432,6 +5745,17 @@ loadHTMLstream(URLFile *f, Buffer *newBuf, FILE * src, int internal) forms_size = 0; forms = NULL; cur_hseq = 1; +#ifdef USE_IMAGE + cur_iseq = 1; + if (newBuf->image_flag) + image_flag = newBuf->image_flag; + else if (activeImage && displayImage && autoImage) + image_flag = IMG_FLAG_AUTO; + else + image_flag = IMG_FLAG_SKIP; + if (newBuf->currentURL.file) + cur_baseURL = baseURL(newBuf); +#endif if (w3m_halfload) { newBuf->buffername = "---"; @@ -5440,10 +5764,9 @@ loadHTMLstream(URLFile *f, Buffer *newBuf, FILE * src, int internal) #endif /* JP_CHARSET */ HTMLlineproc3(newBuf, f->stream); w3m_halfload = FALSE; - if (fmInitialized) { + if (fmInitialized) term_raw(); - signal(SIGINT, prevtrap); - } + signal(SIGINT, prevtrap); return; } @@ -5458,10 +5781,9 @@ loadHTMLstream(URLFile *f, Buffer *newBuf, FILE * src, int internal) HTMLlineproc1("<br>Transfer Interrupted!<br>", &htmlenv1); goto phase2; } - if (fmInitialized) { - prevtrap = signal(SIGINT, KeyAbort); + prevtrap = signal(SIGINT, KeyAbort); + if (fmInitialized) term_cbreak(); - } #ifdef JP_CHARSET if (newBuf != NULL && newBuf->document_code != '\0') @@ -5482,16 +5804,32 @@ loadHTMLstream(URLFile *f, Buffer *newBuf, FILE * src, int internal) if (src) Strfputs(lineBuf2, src); linelen += lineBuf2->length; + if (w3m_dump & DUMP_SOURCE) + continue; showProgress(&linelen, &trbyte); + /* + * if (frame_source) + * continue; + */ #ifdef JP_CHARSET if (meta_charset != '\0') { /* <META> */ - if (content_charset == '\0' && UseContentCharset) + if (content_charset == '\0' && UseContentCharset) { code = meta_charset; +#ifdef USE_IMAGE + cur_document_code = code; +#endif + } meta_charset = '\0'; } #endif - if (!internal) + if (!internal) { lineBuf2 = convertLine(f, lineBuf2, &code, HTML_MODE); +#ifdef JP_CHARSET +#ifdef USE_IMAGE + cur_document_code = code; +#endif +#endif + } #ifdef USE_NNTP if (f->scheme == SCM_NEWS) { if (Str_news_endline(lineBuf2)) { @@ -5510,22 +5848,23 @@ loadHTMLstream(URLFile *f, Buffer *newBuf, FILE * src, int internal) if (htmlenv1.title) newBuf->buffername = htmlenv1.title; if (w3m_halfdump) { - if (fmInitialized) { + if (fmInitialized) term_raw(); - signal(SIGINT, prevtrap); - } + signal(SIGINT, prevtrap); return; } phase2: newBuf->trbyte = trbyte + linelen; - if (fmInitialized) { + if (fmInitialized) term_raw(); - signal(SIGINT, prevtrap); - } + signal(SIGINT, prevtrap); #ifdef JP_CHARSET newBuf->document_code = code; content_charset = '\0'; #endif /* JP_CHARSET */ +#ifdef USE_IMAGE + newBuf->image_flag = image_flag; +#endif if (w3m_backend) backend_halfdump_buf = htmlenv1.buf; HTMLlineproc2(newBuf, htmlenv1.buf); @@ -5545,15 +5884,18 @@ loadHTMLString(Str page) newBuf = newBuffer(INIT_BUFFER_WIDTH); if (SETJMP(AbortLoading) != 0) { + if (fmInitialized) + term_raw(); + signal(SIGINT, prevtrap); discardBuffer(newBuf); return NULL; } + prevtrap = signal(SIGINT, KeyAbort); + if (fmInitialized) + term_cbreak(); + init_stream(&f, SCM_LOCAL, newStrStream(page)); - if (fmInitialized) { - prevtrap = signal(SIGINT, KeyAbort); - term_cbreak(); - } if (w3m_dump & DUMP_FRAME) { tmp = tmpfname(TMPF_SRC, ".html"); pushText(fileToDelete, tmp->ptr); @@ -5564,10 +5906,9 @@ loadHTMLString(Str page) loadHTMLstream(&f, newBuf, src, TRUE); - if (fmInitialized) { + if (fmInitialized) term_raw(); - signal(SIGINT, prevtrap); - } + signal(SIGINT, prevtrap); newBuf->topLine = newBuf->firstLine; newBuf->lastLine = newBuf->currentLine; newBuf->currentLine = newBuf->firstLine; @@ -5611,6 +5952,9 @@ loadGopherDir(URLFile *uf, Buffer *newBuf) code = content_charset; else code = DocumentCode; +#ifdef USE_IMAGE + cur_document_code = code; +#endif content_charset = '\0'; #endif while (1) { @@ -5714,10 +6058,9 @@ loadBuffer(URLFile *uf, Buffer *volatile newBuf) if (SETJMP(AbortLoading) != 0) { goto _end; } - if (fmInitialized) { - prevtrap = signal(SIGINT, KeyAbort); + prevtrap = signal(SIGINT, KeyAbort); + if (fmInitialized) term_cbreak(); - } if (newBuf->sourcefile == NULL && (uf->scheme != SCM_LOCAL || newBuf->mailcap)) { @@ -5743,7 +6086,11 @@ loadBuffer(URLFile *uf, Buffer *volatile newBuf) if (src) Strfputs(lineBuf2, src); linelen += lineBuf2->length; + if (w3m_dump & DUMP_SOURCE) + continue; showProgress(&linelen, &trbyte); + if (frame_source) + continue; lineBuf2 = convertLine(uf, lineBuf2, &code, PAGER_MODE); if (squeezeBlankLine) { if (lineBuf2->ptr[0] == '\n' && pre_lbuf == '\n') { @@ -5774,10 +6121,9 @@ loadBuffer(URLFile *uf, Buffer *volatile newBuf) lineBuf2->length, nlines); } _end: - if (fmInitialized) { - signal(SIGINT, prevtrap); + if (fmInitialized) term_raw(); - } + signal(SIGINT, prevtrap); newBuf->topLine = newBuf->firstLine; newBuf->lastLine = newBuf->currentLine; newBuf->currentLine = newBuf->firstLine; @@ -5791,6 +6137,67 @@ loadBuffer(URLFile *uf, Buffer *volatile newBuf) return newBuf; } +#ifdef USE_IMAGE +Buffer * +loadImageBuffer(URLFile *uf, Buffer *newBuf) +{ + Image *image; + ImageCache *cache; + Str tmp, tmpf; + FILE *src = NULL; + URLFile f; + MySignalHandler(*prevtrap) (); + + loadImage(IMG_FLAG_STOP); + image = New(Image); + image->url = parsedURL2Str(cur_baseURL)->ptr; + image->ext = filename_extension(cur_baseURL->file, 1); + image->width = -1; + image->height = -1; + cache = getImage(image, cur_baseURL, IMG_FLAG_AUTO); + if (!cur_baseURL->is_nocache && cache->loaded == IMG_FLAG_LOADED) + goto image_buffer; + + prevtrap = signal(SIGINT, KeyAbort); + if (fmInitialized) + term_cbreak(); + if (IStype(uf->stream) != IST_ENCODED) + uf->stream = newEncodedStream(uf->stream, uf->encoding); + if (save2tmp(*uf, cache->file) < 0) { + if (fmInitialized) + term_raw(); + signal(SIGINT, prevtrap); + return NULL; + } + if (fmInitialized) + term_raw(); + signal(SIGINT, prevtrap); + + cache->loaded = IMG_FLAG_LOADED; + getImageSize(cache); + + image_buffer: + tmp = Sprintf("<img src=\"%s\"><br><br>", html_quote(image->url)); + if (newBuf == NULL) + newBuf = newBuffer(INIT_BUFFER_WIDTH); + if (frame_source) { + tmpf = tmpfname(TMPF_SRC, ".html"); + src = fopen(tmpf->ptr, "w"); + newBuf->sourcefile = tmpf->ptr; + pushText(fileToDelete, tmpf->ptr); + } + init_stream(&f, SCM_LOCAL, newStrStream(tmp)); + loadHTMLstream(&f, newBuf, src, TRUE); + if (src) + fclose(src); + + newBuf->topLine = newBuf->firstLine; + newBuf->lastLine = newBuf->currentLine; + newBuf->currentLine = newBuf->firstLine; + return newBuf; +} +#endif + /* * saveBuffer: write buffer to file */ @@ -6165,10 +6572,9 @@ save2tmp(URLFile uf, char *tmpf) if (SETJMP(AbortLoading) != 0) { goto _end; } - if (fmInitialized) { - prevtrap = signal(SIGINT, KeyAbort); + prevtrap = signal(SIGINT, KeyAbort); + if (fmInitialized) term_cbreak(); - } check = 0; current_content_length = 0; #ifdef USE_NNTP @@ -6204,10 +6610,9 @@ save2tmp(URLFile uf, char *tmpf) } _end: bcopy(env_bak, AbortLoading, sizeof(JMP_BUF)); - if (fmInitialized) { + if (fmInitialized) term_raw(); - signal(SIGINT, prevtrap); - } + signal(SIGINT, prevtrap); fclose(ff); if (uf.scheme == SCM_FTP) FTPhalfclose(uf.stream); diff --git a/fm.h b/fm.h @@ -73,7 +73,14 @@ void bzero(void *, int); #define PAGER_MAX_LINE 10000 /* Maximum line kept as pager */ #define FNLEN 80 +#ifdef USE_IMAGE +#define MAX_IMAGE 1000 + +#define DEFAULT_PIXEL_PER_CHAR 7.0 /* arbitrary */ +#define DEFAULT_PIXEL_PER_LINE 14.0 /* arbitrary */ +#else #define DEFAULT_PIXEL_PER_CHAR 8.0 /* arbitrary */ +#endif #define MINIMUM_PIXEL_PER_CHAR 4.0 #define MAXIMUM_PIXEL_PER_CHAR 32.0 @@ -157,6 +164,7 @@ void bzero(void *, int); #define B_FORCE_REDRAW 1 #define B_REDRAW 2 #define B_SCROLL 3 +#define B_REDRAW_IMAGE 4 /* Buffer Property */ #define BP_NORMAL 0x0 @@ -219,6 +227,17 @@ extern int REV_LB[]; #define IN_URL 0x100 #define IN_CHAR 0x200 +#define IMG_FLAG_SKIP 1 +#define IMG_FLAG_AUTO 2 + +#define IMG_FLAG_START 0 +#define IMG_FLAG_STOP 1 +#define IMG_FLAG_NEXT 2 + +#define IMG_FLAG_UNLOADED 0 +#define IMG_FLAG_LOADED 1 +#define IMG_FLAG_ERROR 2 + /* * Macros. */ @@ -263,10 +282,21 @@ typedef unsigned short Lineprop; typedef unsigned char Linecolor; #endif +typedef struct _MapArea { + char *url; + char *alt; +#ifdef MENU_MAP +#ifdef USE_IMAGE + char shape; + short *coords; + int ncoords; +#endif +#endif +} MapArea; + typedef struct _MapList { Str name; - TextList *urls; - TextList *alts; + GeneralList *area; struct _MapList *next; } MapList; @@ -290,6 +320,33 @@ typedef struct { short pos; } BufferPoint; +#ifdef USE_IMAGE +typedef struct _imageCache { + char *url; + ParsedURL *current; + char *file; + char loaded; + int index; + short width; + short height; +} ImageCache; + +typedef struct _image { + char *url; + char *ext; + short width; + short height; + short xoffset; + short yoffset; + short y; + short rows; + char *map; + char ismap; + int touch; + ImageCache *cache; +} Image; +#endif + typedef struct _anchor { char *url; char *target; @@ -299,6 +356,9 @@ typedef struct _anchor { int hseq; short y; short rows; +#ifdef USE_IMAGE + Image *image; +#endif } Anchor; #define NO_REFERER ((char*)-1) @@ -347,6 +407,7 @@ typedef struct _Buffer { FormList *formlist; MapList *maplist; HmarkerList *hmarklist; + HmarkerList *imarklist; ParsedURL currentURL; ParsedURL *baseURL; char *baseTarget; @@ -371,6 +432,8 @@ typedef struct _Buffer { #ifdef USE_SSL char *ssl_certificate; #endif + char image_flag; + char need_reshape; } Buffer; @@ -515,6 +578,7 @@ struct readbuffer { /* flags for loadGeneralFile */ #define RG_NOCACHE 1 #define RG_FRAME 2 +#define RG_FRAME_SRC 4 struct html_feed_environ { struct readbuffer *obuf; @@ -587,6 +651,9 @@ struct cookie { #define ALIGN_CENTER 0 #define ALIGN_LEFT 1 #define ALIGN_RIGHT 2 +#define ALIGN_MIDDLE 4 +#define ALIGN_TOP 5 +#define ALIGN_BOTTOM 6 #define VALIGN_MIDDLE 0 #define VALIGN_TOP 1 @@ -647,6 +714,7 @@ global char ArgvIsURL init(FALSE); global char MetaRefresh init(FALSE); global char fmInitialized init(FALSE); +global char QuietMessage init(FALSE); extern char GlobalKeymap[]; extern char EscKeymap[]; @@ -746,6 +814,14 @@ global int displayLink init(FALSE); global int retryAsHttp init(TRUE); global int showLineNum init(FALSE); global int show_srch_str init(TRUE); +#ifdef USE_IMAGE +global char *Imgdisplay init(IMGDISPLAY); +global char *Imgsize init(IMGSIZE); +global int activeImage init(FALSE); +global int displayImage init(TRUE); +global int autoImage init(TRUE); +global int useExtImageViewer init(TRUE); +#endif global char *Editor init(DEF_EDITOR); #ifndef USE_W3MMAILER global char *Mailer init(DEF_MAILER); @@ -759,6 +835,9 @@ global char *ftppasswd init(NULL); global int ftppass_hostnamegen init(TRUE); #endif global int do_download init(FALSE); +#ifdef USE_IMAGE +global char *image_source init(NULL); +#endif global char *UserAgent init(NULL); global int NoSendReferer init(FALSE); global char *AcceptLang init(NULL); @@ -857,7 +936,11 @@ global TextList *Cookie_reject_domains; global TextList *Cookie_accept_domains; #endif /* USE_COOKIE */ +#ifdef USE_IMAGE +global int view_unseenobject init(FALSE); +#else global int view_unseenobject init(TRUE); +#endif #if defined(USE_SSL) && defined(USE_SSL_VERIFY) global int ssl_verify_server init(FALSE); @@ -875,6 +958,12 @@ global char *ssl_forbid_method init(NULL); global int is_redisplay init(FALSE); global int clear_buffer init(TRUE); global double pixel_per_char init(DEFAULT_PIXEL_PER_CHAR); +global int set_pixel_per_char init(FALSE); +#ifdef USE_IMAGE +global double pixel_per_line init(DEFAULT_PIXEL_PER_LINE); +global int set_pixel_per_line init(FALSE); +global double image_scale init(100); +#endif global int use_lessopen init(FALSE); #ifdef JP_CHARSET diff --git a/frame.c b/frame.c @@ -385,7 +385,7 @@ frame_download_source(struct frame_body *b, ParsedURL *currentURL, w3m_dump |= DUMP_FRAME; buf = loadGeneralFile(b->url, baseURL ? baseURL : currentURL, - b->referer, flag, b->request); + b->referer, flag | RG_FRAME_SRC, b->request); w3m_dump &= ~DUMP_FRAME; is_redisplay = FALSE; break; @@ -399,7 +399,12 @@ frame_download_source(struct frame_body *b, ParsedURL *currentURL, b->url = parsedURL2Str(&buf->currentURL)->ptr; b->source = buf->sourcefile; b->type = buf->type; - if (buf->real_scheme != SCM_LOCAL) { + if ((buf->real_scheme != SCM_LOCAL) +#ifdef USE_IMAGE + || (activeImage && !useExtImageViewer && + buf->real_type && !strncasecmp(buf->real_type, "image/", 6)) +#endif + ) { tmp = tmpfname(TMPF_FRAME, NULL); rename(buf->sourcefile, tmp->ptr); b->source = tmp->ptr; diff --git a/funcname.tab b/funcname.tab @@ -14,6 +14,7 @@ COOKIE cooLst DELETE_PREVBUF deletePrevBuf DICT_WORD dictword DICT_WORD_AT dictwordat +DISPLAY_IMAGE dispI DOWN ldown1 DOWNLOAD svSrc EDIT editBf @@ -107,6 +108,7 @@ SHELL execsh SHIFT_LEFT shiftl SHIFT_RIGHT shiftr SOURCE vwSrc +STOP_IMAGE stopI SUBMIT submitForm SUSPEND susp UP lup1 diff --git a/html.c b/html.c @@ -23,8 +23,10 @@ unsigned char ALST_DL[] = { ATTR_COMPACT, ATTR_CORE }; unsigned char ALST_PRE[] = { ATTR_FOR_TABLE, ATTR_CORE }; #define MAXA_PRE MAXA_CORE + 1 unsigned char ALST_IMG[] = - { ATTR_SRC, ATTR_ALT, ATTR_WIDTH, ATTR_HEIGHT, ATTR_USEMAP, ATTR_CORE }; -#define MAXA_IMG MAXA_CORE + 5 + { ATTR_SRC, ATTR_ALT, ATTR_WIDTH, ATTR_HEIGHT, ATTR_ALIGN, ATTR_USEMAP, + ATTR_ISMAP, ATTR_CORE +}; +#define MAXA_IMG MAXA_CORE + 7 unsigned char ALST_TABLE[] = { ATTR_BORDER, ATTR_WIDTH, ATTR_HBORDER, ATTR_CELLSPACING, ATTR_CELLPADDING, ATTR_VSPACE, ATTR_CORE @@ -61,8 +63,9 @@ unsigned char ALST_ISINDEX[] = { ATTR_ACTION, ATTR_PROMPT, ATTR_CORE }; #define MAXA_ISINDEX MAXA_CORE + 2 unsigned char ALST_MAP[] = { ATTR_NAME, ATTR_CORE }; #define MAXA_MAP MAXA_CORE + 1 -unsigned char ALST_AREA[] = { ATTR_HREF, ATTR_ALT, ATTR_CORE }; -#define MAXA_AREA MAXA_CORE + 2 +unsigned char ALST_AREA[] = + { ATTR_HREF, ATTR_ALT, ATTR_SHAPE, ATTR_COORDS, ATTR_CORE }; +#define MAXA_AREA MAXA_CORE + 4 unsigned char ALST_BASE[] = { ATTR_HREF, ATTR_TARGET, ATTR_CORE }; #define MAXA_BASE MAXA_CORE + 2 unsigned char ALST_BODY[] = { ATTR_BACKGROUND, ATTR_CORE }; @@ -94,8 +97,11 @@ unsigned char ALST_INPUT_ALT[] = ATTR_SELECTNUMBER, ATTR_ROWS, ATTR_TOP_MARGIN, ATTR_BOTTOM_MARGIN }; #define MAXA_INPUT_ALT 16 -unsigned char ALST_IMG_ALT[] = { ATTR_SRC }; -#define MAXA_IMG_ALT 1 +unsigned char ALST_IMG_ALT[] = + { ATTR_SRC, ATTR_WIDTH, ATTR_HEIGHT, ATTR_USEMAP, ATTR_ISMAP, ATTR_HSEQ, + ATTR_XOFFSET, ATTR_YOFFSET, ATTR_TOP_MARGIN, ATTR_BOTTOM_MARGIN +}; +#define MAXA_IMG_ALT 10 unsigned char ALST_NOP[] = { ATTR_CORE }; #define MAXA_NOP MAXA_CORE @@ -278,16 +284,16 @@ TagAttrInfo AttrMAP[MAX_TAGATTR] = { {"selected", VTYPE_NONE, 0}, /* 41 ATTR_SELECTED */ {"label", VTYPE_STR, 0}, /* 42 ATTR_LABEL */ {"readonly", VTYPE_NONE, 0}, /* 43 ATTR_READONLY */ + {"shape", VTYPE_STR, 0}, /* 44 ATTR_SHAPE */ + {"coords", VTYPE_STR, 0}, /* 45 ATTR_COORDS */ + {"ismap", VTYPE_NONE, 0}, /* 46 ATTR_ISMAP */ - {NULL, VTYPE_NONE, 0}, /* 44 Undefined */ - {NULL, VTYPE_NONE, 0}, /* 45 Undefined */ - {NULL, VTYPE_NONE, 0}, /* 46 Undefined */ {NULL, VTYPE_NONE, 0}, /* 47 Undefined */ {NULL, VTYPE_NONE, 0}, /* 48 Undefined */ - {NULL, VTYPE_NONE, 0}, /* 49 Undefined */ - {NULL, VTYPE_NONE, 0}, /* 50 Undefined */ /* Internal attribute */ + {"xoffset", VTYPE_NUMBER, AFLG_INT}, /* 49 ATTR_XOFFSET */ + {"yoffset", VTYPE_NUMBER, AFLG_INT}, /* 50 ATTR_YOFFSET */ {"top_margin", VTYPE_NUMBER, AFLG_INT}, /* 51 ATTR_TOP_MARGIN, */ {"bottom_margin", VTYPE_NUMBER, AFLG_INT}, /* 52 ATTR_BOTTOM_MARGIN, */ {"tid", VTYPE_NUMBER, AFLG_INT}, /* 53 ATTR_TID */ diff --git a/html.h b/html.h @@ -248,11 +248,16 @@ typedef struct { #define ATTR_START 40 #define ATTR_SELECTED 41 #define ATTR_LABEL 42 -#define ATTR_READONLY 43 +#define ATTR_READONLY 43 +#define ATTR_SHAPE 44 +#define ATTR_COORDS 45 +#define ATTR_ISMAP 46 /* Internal attribute */ -#define ATTR_TOP_MARGIN 51 -#define ATTR_BOTTOM_MARGIN 52 +#define ATTR_XOFFSET 49 +#define ATTR_YOFFSET 50 +#define ATTR_TOP_MARGIN 51 +#define ATTR_BOTTOM_MARGIN 52 #define ATTR_TID 53 #define ATTR_FID 54 #define ATTR_FOR_TABLE 55 @@ -301,6 +306,12 @@ typedef struct tag_attribute_info { #define VTYPE_MLENGTH 9 #define VTYPE_TYPE 10 +#define SHAPE_UNKNOWN 0 +#define SHAPE_DEFAULT 1 +#define SHAPE_RECT 2 +#define SHAPE_CIRCLE 3 +#define SHAPE_POLY 4 + extern TagInfo TagMAP[]; extern TagAttrInfo AttrMAP[]; diff --git a/image.c b/image.c @@ -0,0 +1,528 @@ +/* $Id$ */ + +#include "fm.h" +#include <sys/types.h> +#include <signal.h> +#include <errno.h> +#include <unistd.h> +#ifdef HAVE_WAITPID +#include <sys/wait.h> +#endif + +#ifdef USE_IMAGE + +static image_index = 0; + +/* display image */ + +typedef struct _termialImage { + ImageCache *cache; + short x; + short y; + short sx; + short sy; + short width; + short height; +} TerminalImage; + +static TerminalImage *terminal_image = NULL; +static int n_terminal_image = 0; +static int max_terminal_image = 0; +static FILE *Imgdisplay_rf = NULL, *Imgdisplay_wf = NULL; +static pid_t Imgdisplay_pid = 0; +static int openImgdisplay(); +static void closeImgdisplay(); + +void +initImage() +{ + if (activeImage) + return; + if (getCharSize()) + activeImage = TRUE; +} + +int +getCharSize() +{ + FILE *f; + Str tmp; + int w = 0, h = 0; + + tmp = Strnew(); + if (!strchr(Imgdisplay, '/')) + Strcat_m_charp(tmp, LIB_DIR, "/", NULL); + Strcat_m_charp(tmp, Imgdisplay, " -test 2> /dev/null", NULL); + f = popen(tmp->ptr, "r"); + if (!f) + return FALSE; + fscanf(f, "%d %d", &w, &h); + pclose(f); + if (!(w > 0 && h > 0)) + return FALSE; + if (! set_pixel_per_char) + pixel_per_char = (int)(1.0 * w / COLS + 0.5); + if (! set_pixel_per_line) + pixel_per_line = (int)(1.0 * h / LINES + 0.5); + return TRUE; +} + +void +termImage() +{ + if (!activeImage) + return; + clearImage(); + if (Imgdisplay_wf) { + fputs("2;\n", Imgdisplay_wf); /* ClearImage() */ + fflush(Imgdisplay_wf); + } + closeImgdisplay(); +} + +static int +openImgdisplay() +{ + int fdr[2], fdw[2]; + char *cmd; + + if (pipe(fdr) < 0) + goto err0; + if (pipe(fdw) < 0) + goto err1; + + flush_tty(); + Imgdisplay_pid = fork(); + if (Imgdisplay_pid < 0) + goto err2; + if (Imgdisplay_pid == 0) { + /* child */ + reset_signals(); + signal(SIGINT, SIG_IGN); +#ifdef HAVE_SETPGRP + setpgrp(); +#endif + close_tty(); + close(fdr[0]); + close(fdw[1]); + dup2(fdw[0], 0); + dup2(fdr[1], 1); + close(2); + if (!strchr(Imgdisplay, '/')) + cmd = Strnew_m_charp(LIB_DIR, "/", Imgdisplay, NULL)->ptr; + else + cmd = Imgdisplay; + execl("/bin/sh", "sh", "-c", cmd, NULL); + exit(1); + } + close(fdr[1]); + close(fdw[0]); + Imgdisplay_rf = fdopen(fdr[0], "r"); + Imgdisplay_wf = fdopen(fdw[1], "w"); + activeImage = TRUE; + return TRUE; + err2: + close(fdw[0]); + close(fdw[1]); + err1: + close(fdr[0]); + close(fdr[1]); + err0: + Imgdisplay_rf = NULL; + Imgdisplay_wf = NULL; + Imgdisplay_pid = 0; + activeImage = FALSE; + return FALSE; +} + +static void +closeImgdisplay() +{ + if (Imgdisplay_rf) + fclose(Imgdisplay_rf); + if (Imgdisplay_wf) + fclose(Imgdisplay_wf); + if (Imgdisplay_pid) + kill(Imgdisplay_pid, SIGKILL); + Imgdisplay_rf = NULL; + Imgdisplay_wf = NULL; + Imgdisplay_pid = 0; +} + +void +addImage(ImageCache * cache, int x, int y, int sx, int sy, int w, int h) +{ + TerminalImage *i; + + if (!activeImage) + return; + if (n_terminal_image >= max_terminal_image) { + max_terminal_image = max_terminal_image ? (2 * max_terminal_image) : 8; + terminal_image = New_Reuse(TerminalImage, terminal_image, + max_terminal_image); + } + i = &terminal_image[n_terminal_image]; + i->cache = cache; + i->x = x; + i->y = y; + i->sx = sx; + i->sy = sy; + i->width = w; + i->height = h; + n_terminal_image++; +} + +void +drawImage() +{ + static char buf[64]; + int j, draw = FALSE; + TerminalImage *i; + + if (!activeImage) + return; + if (!n_terminal_image) + return; + for (j = 0; j < n_terminal_image; j++) { + i = &terminal_image[j]; + if (!(i->cache->loaded == IMG_FLAG_LOADED && + i->width > 0 && i->height > 0)) + continue; + if (!(Imgdisplay_rf && Imgdisplay_wf)) { + if (!openImgdisplay()) + return; + } + if (!draw) { + fputs("3;\n", Imgdisplay_wf); /* XSync() */ + draw = TRUE; + } + if (i->cache->index > 0) { + i->cache->index *= -1; + fputs("0;", Imgdisplay_wf); /* DrawImage() */ + } + else + fputs("1;", Imgdisplay_wf); /* DrawImage(redraw) */ + sprintf(buf, "%d;%d;%d;%d;%d;%d;%d;%d;%d;", + (-i->cache->index - 1) % MAX_IMAGE + 1, i->x, i->y, + (i->cache->width > 0) ? i->cache->width : 0, + (i->cache->height > 0) ? i->cache->height : 0, + i->sx, i->sy, i->width, i->height); + fputs(buf, Imgdisplay_wf); + fputs(i->cache->file, Imgdisplay_wf); + fputs("\n", Imgdisplay_wf); + fputs("4;\n", Imgdisplay_wf); /* put '\n' */ + again: + if (fflush(Imgdisplay_wf) != 0) { + switch (errno) { + case EINTR: + goto again; + default: + goto err; + } + } + if (!fgetc(Imgdisplay_rf)) + goto err; + } + if (!draw) + return; + fputs("3;\n", Imgdisplay_wf); /* XSync() */ + fputs("4;\n", Imgdisplay_wf); /* put '\n' */ + again2: + if (fflush(Imgdisplay_wf) != 0) { + switch (errno) { + case EINTR: + goto again2; + default: + goto err; + } + } + if (!fgetc(Imgdisplay_rf)) + goto err; +/* + touch_line(); + touch_column(CurColumn); +#ifdef JP_CHARSET + if (CurColumn > 0 && + CHMODE(ScreenImage[CurLine]->lineprop[CurColumn]) == C_WCHAR2) + touch_column(CurColumn - 1); + else if (CurColumn < COLS - 1 && + CHMODE(ScreenImage[CurLine]->lineprop[CurColumn]) == C_WCHAR1) + touch_column(CurColumn + 1); +#endif +*/ + touch_cursor(); + refresh(); + return; + err: + closeImgdisplay(); + image_index += MAX_IMAGE; +} + +void +clearImage() +{ + if (!activeImage) + return; + n_terminal_image = 0; +} + +/* load image */ + +static Hash_sv *image_hash = NULL; +static Hash_sv *image_file = NULL; +static GeneralList *image_list = NULL; +static ImageCache *image_cache = NULL; +static pid_t image_pid = 0; +static int need_load_image = FALSE; + +static MySignalHandler +load_image_handler(SIGNAL_ARG) +{ + need_load_image = TRUE; + SIGNAL_RETURN; +} + +static MySignalHandler +load_image_next(SIGNAL_ARG) +{ + need_load_image = TRUE; + loadImage(IMG_FLAG_NEXT); + SIGNAL_RETURN; +} + +void +deleteImage(Buffer *buf) +{ + AnchorList *al; + Anchor *a; + int i; + + if (!buf) + return; + al = buf->img; + if (!al) + return; + for (i = 0, a = al->anchors; i < al->nanchor; i++, a++) { + if (a->image && a->image->cache && + a->image->cache->loaded != IMG_FLAG_UNLOADED && + a->image->cache->index < 0) + unlink(a->image->cache->file); + } + loadImage(IMG_FLAG_STOP); +} + +void +getAllImage(Buffer *buf) +{ + AnchorList *al; + Anchor *a; + ParsedURL *current; + int i; + + if (!buf) + return; + al = buf->img; + if (!al) + return; + current = baseURL(buf); + for (i = 0, a = al->anchors; i < al->nanchor; i++, a++) { + if (a->image) + a->image->cache = getImage(a->image, current, buf->image_flag); + } +} + +void +loadImage(int flag) +{ + int wait_st; + + if (flag == IMG_FLAG_STOP) { + if (image_pid) { + kill(image_pid, SIGKILL); +#ifdef HAVE_WAITPID + waitpid(image_pid, &wait_st, 0); +#else + wait(&wait_st); +#endif + image_pid = 0; + } + image_cache = NULL; + image_list = NULL; + image_file = NULL; + need_load_image = FALSE; + return; + } + + if (flag == IMG_FLAG_NEXT && need_load_image) { + struct stat st; + if (image_pid) { +#ifdef HAVE_WAITPID + waitpid(image_pid, &wait_st, 0); +#else + wait(&wait_st); +#endif + image_pid = 0; + } + if (!stat(image_cache->file, &st)) { + image_cache->loaded = IMG_FLAG_LOADED; + if (getImageSize(image_cache)) { + if (Currentbuf) + Currentbuf->need_reshape = TRUE; + } + } + else { + image_cache->loaded = IMG_FLAG_ERROR; + } + image_cache = NULL; + drawImage(); + } + + need_load_image = FALSE; + if (flag == IMG_FLAG_START) + signal(SIGUSR1, load_image_handler); + else + signal(SIGUSR1, load_image_next); + + if (image_cache) + return; + + image_pid = 0; + if (!image_list) + return; + while (1) { + image_cache = (ImageCache *) popValue(image_list); + if (!image_cache) { + if (Currentbuf && Currentbuf->need_reshape) + displayBuffer(Currentbuf, B_NORMAL); + return; + } + if (image_cache->loaded == IMG_FLAG_UNLOADED) + break; + } + + flush_tty(); + if ((image_pid = fork()) == 0) { + Buffer *b; + + reset_signals(); + signal(SIGINT, SIG_IGN); + close_tty(); + QuietMessage = TRUE; + fmInitialized = FALSE; + image_source = image_cache->file; + b = loadGeneralFile(image_cache->url, image_cache->current, NULL, 0, + NULL); + if (!b || !b->real_type || strncasecmp(b->real_type, "image/", 6)) + unlink(image_cache->file); + kill(getppid(), SIGUSR1); + exit(0); + } +} + +ImageCache * +getImage(Image * image, ParsedURL *current, int flag) +{ + Str key; + ImageCache *cache; + + if (!activeImage) + return; + if (!image_hash) + image_hash = newHash_sv(100); + if (image->cache) + cache = image->cache; + else { + key = Sprintf("%d;%d;%s", image->width, image->height, image->url); + cache = (ImageCache *) getHash_sv(image_hash, key->ptr, NULL); + } + if (cache && cache->index && abs(cache->index) <= image_index - MAX_IMAGE) { + struct stat st; + if (stat(cache->file, &st)) + cache->loaded = IMG_FLAG_UNLOADED; + cache->index = 0; + } + + if (!cache) { + if (flag == IMG_FLAG_SKIP) + return NULL; + + cache = New(ImageCache); + cache->url = image->url; + cache->current = current; + cache->file = tmpfname(TMPF_DFL, image->ext)->ptr; + cache->index = 0; + cache->loaded = IMG_FLAG_UNLOADED; + cache->width = image->width; + cache->height = image->height; + putHash_sv(image_hash, key->ptr, (void *)cache); + pushText(fileToDelete, cache->file); + } + if (flag != IMG_FLAG_SKIP) { + if (cache->loaded == IMG_FLAG_UNLOADED) { + if (!image_file) + image_file = newHash_sv(100); + if (!getHash_sv(image_file, cache->file, NULL)) { + putHash_sv(image_file, cache->file, (void *)cache); + if (!image_list) + image_list = newGeneralList(); + pushValue(image_list, (void *)cache); + } + } + if (!cache->index) + cache->index = ++image_index; + } + if (cache->loaded == IMG_FLAG_LOADED) + getImageSize(cache); + return cache; +} + +int +getImageSize(ImageCache * cache) +{ + Str tmp; + FILE *f; + int w = 0, h = 0; + + if (!activeImage) + return 0; + if (!cache || cache->loaded != IMG_FLAG_LOADED || + (cache->width > 0 && cache->height > 0)) + return 0; + tmp = Strnew(); + if (!strchr(Imgsize, '/')) + Strcat_m_charp(tmp, LIB_DIR, "/", NULL); + Strcat_m_charp(tmp, Imgsize, " ", shell_quote(cache->file), " 2> /dev/null", + NULL); + f = popen(tmp->ptr, "r"); + if (!f) + return 0; + fscanf(f, "%d %d", &w, &h); + pclose(f); + + if (!(w > 0 && h > 0)) + return 0; + w = (int)(w * image_scale / 100 + 0.5); + if (w == 0) + w = 1; + h = (int)(h * image_scale / 100 + 0.5); + if (h == 0) + h = 1; + if (cache->width < 0 && cache->height < 0) { + cache->width = w; + cache->height = h; + } + else if (cache->width < 0) { + cache->width = (int)((double)cache->height * w / h + 0.5); + } + else if (cache->height < 0) { + cache->height = (int)((double)cache->width * h / w + 0.5); + } + if (cache->width == 0) + cache->width = 1; + if (cache->height == 0) + cache->height = 1; + tmp = Sprintf("%d;%d;%s", cache->width, cache->height, cache->url); + putHash_sv(image_hash, tmp->ptr, (void *)cache); + return 1; +} +#endif diff --git a/main.c b/main.c @@ -109,6 +109,9 @@ fversion(FILE * f) #else "lang=en" #endif +#ifdef USE_IMAGE + ",image" +#endif #ifdef USE_COLOR ",color" #ifdef USE_ANSI_COLOR @@ -193,6 +196,10 @@ fusage(FILE * f, int err) " -cols width specify column width (used with -dump)\n"); fprintf(f, " -ppc count specify the number of pixels per character (4.0...32.0)\n"); +#ifdef USE_IMAGE + fprintf(f, + " -ppl count specify the number of pixels per line (4.0...64.0)\n"); +#endif fprintf(f, " -dump dump formatted page into stdout\n"); fprintf(f, " -dump_head dump response of HEAD request into stdout\n"); @@ -582,9 +589,24 @@ MAIN(int argc, char **argv, char **envp) usage(); ppc = atof(argv[i]); if (ppc >= MINIMUM_PIXEL_PER_CHAR && - ppc <= MAXIMUM_PIXEL_PER_CHAR) + ppc <= MAXIMUM_PIXEL_PER_CHAR) { pixel_per_char = ppc; + set_pixel_per_char = TRUE; + } + } +#ifdef USE_IMAGE + else if (!strcmp("-ppl", argv[i])) { + double ppc; + if (++i >= argc) + usage(); + ppc = atof(argv[i]); + if (ppc >= MINIMUM_PIXEL_PER_CHAR && + ppc <= MAXIMUM_PIXEL_PER_CHAR * 2) { + pixel_per_line = ppc; + set_pixel_per_line = TRUE; + } } +#endif else if (!strcmp("-num", argv[i])) showLineNum = TRUE; else if (!strcmp("-no-proxy", argv[i])) @@ -962,7 +984,15 @@ MAIN(int argc, char **argv, char **envp) } signal(SIGWINCH, resize_handler); #endif +#ifdef USE_IMAGE + if (activeImage && displayImage) + loadImage(IMG_FLAG_NEXT); +#endif c = getch(); +#ifdef USE_IMAGE + if (activeImage && displayImage) + loadImage(IMG_FLAG_START); +#endif #ifdef SIGWINCH signal(SIGWINCH, resize_hook); #endif @@ -1145,6 +1175,9 @@ pushBuffer(Buffer *buf) { Buffer *b; +#ifdef USE_IMAGE + deleteImage(Currentbuf); +#endif if (clear_buffer) tmpClearBuffer(Currentbuf); if (Firstbuf == Currentbuf) { @@ -2121,6 +2154,10 @@ qquitfm(void) void quitfm(void) { +#ifdef USE_IMAGE + if (activeImage) + termImage(); +#endif fmTerm(); #ifdef USE_COOKIE save_cookies(); @@ -2169,8 +2206,13 @@ selBuf(void) } } while (!ok); - if (clear_buffer) { - for (buf = Firstbuf; buf != NULL; buf = buf->nextBuffer) + for (buf = Firstbuf; buf != NULL; buf = buf->nextBuffer) { + if (buf == Currentbuf) + continue; +#ifdef USE_IMAGE + deleteImage(buf); +#endif + if (clear_buffer) tmpClearBuffer(buf); } displayBuffer(Currentbuf, B_FORCE_REDRAW); @@ -2632,11 +2674,26 @@ followA(void) Line *l; Anchor *a; ParsedURL u; +#ifdef USE_IMAGE + int x = 0, y = 0, map = 0; +#endif + char *url; if (Currentbuf->firstLine == NULL) return; l = Currentbuf->currentLine; +#ifdef USE_IMAGE + a = retrieveCurrentImg(Currentbuf); + if (a && a->image && a->image->map) { + _followForm(FALSE); + return; + } + if (a && a->image && a->image->ismap) { + getMapXY(Currentbuf, retrieveCurrentImg(Currentbuf), &x, &y); + map = 1; + } +#endif a = retrieveCurrentAnchor(Currentbuf); if (a == NULL) { _followForm(FALSE); @@ -2672,7 +2729,12 @@ followA(void) return; } #endif /* USE_NNTP */ - loadLink(a->url, a->target, a->referer, NULL); + url = a->url; +#ifdef USE_IMAGE + if (map) + url = Sprintf("%s?%d,%d", a->url, x, y)->ptr; +#endif + loadLink(url, a->target, a->referer, NULL); displayBuffer(Currentbuf, B_NORMAL); } @@ -2842,14 +2904,18 @@ query_from_followform(Str *query, FormItemList *fi, int multipart) } if (multipart) { if (f2->type == FORM_INPUT_IMAGE) { + int x = 0, y = 0; +#ifdef USE_IMAGE + getMapXY(Currentbuf, retrieveCurrentImg(Currentbuf), &x, &y); +#endif *query = Strdup(conv_form_encoding(f2->name, fi, Currentbuf)); Strcat_charp(*query, ".x"); form_write_data(body, fi->parent->boundary, (*query)->ptr, - "1"); + Sprintf("%d", x)->ptr); *query = Strdup(conv_form_encoding(f2->name, fi, Currentbuf)); Strcat_charp(*query, ".y"); form_write_data(body, fi->parent->boundary, (*query)->ptr, - "1"); + Sprintf("%d", y)->ptr); } else if (f2->name && f2->name->length > 0 && f2->value != NULL) { /* not IMAGE */ @@ -2870,14 +2936,18 @@ query_from_followform(Str *query, FormItemList *fi, int multipart) else { /* not multipart */ if (f2->type == FORM_INPUT_IMAGE) { + int x = 0, y = 0; +#ifdef USE_IMAGE + getMapXY(Currentbuf, retrieveCurrentImg(Currentbuf), &x, &y); +#endif Strcat(*query, Str_form_quote(conv_form_encoding (f2->name, fi, Currentbuf))); - Strcat_charp(*query, ".x=1&"); + Strcat(*query, Sprintf(".x=%d&", x)); Strcat(*query, Str_form_quote(conv_form_encoding (f2->name, fi, Currentbuf))); - Strcat_charp(*query, ".y=1"); + Strcat(*query, Sprintf(".y=%d", y)); } else { /* not IMAGE */ @@ -3776,6 +3846,10 @@ setOpt(void) } if (set_param_option(opt)) sync_with_option(); +#ifdef USE_IMAGE + if (activeImage) + displayBuffer(Currentbuf, B_REDRAW_IMAGE); +#endif displayBuffer(Currentbuf, B_FORCE_REDRAW); } @@ -3817,12 +3891,8 @@ follow_map(struct parsed_tagarg *arg) ParsedURL p_url; a = retrieveCurrentImg(Currentbuf); - if (a != NULL) - x = Currentbuf->cursorX - Currentbuf->pos + a->start.pos + - Currentbuf->rootX; - else - x = Currentbuf->cursorX + Currentbuf->rootX; - url = follow_map_menu(Currentbuf, arg, x, Currentbuf->cursorY + 2); + x = Currentbuf->cursorX + Currentbuf->rootX; + url = follow_map_menu(Currentbuf, arg, a, x, Currentbuf->cursorY); if (url == NULL || *url == '\0') return; if (*url == '#') { @@ -4448,6 +4518,34 @@ curlno() disp_message(tmp->ptr, FALSE); } +#ifdef USE_IMAGE +void +dispI(void) +{ + if (!displayImage) + initImage(); + if (!activeImage) + return; + if (!displayImage || Currentbuf->image_flag == IMG_FLAG_SKIP) { + displayImage = TRUE; + if (!(Currentbuf->type && !strcmp(Currentbuf->type, "text/html"))) + return; + Currentbuf->image_flag = IMG_FLAG_AUTO; + Currentbuf->need_reshape = TRUE; + displayBuffer(Currentbuf, B_REDRAW_IMAGE); + } +} + +void +stopI(void) +{ + if (!activeImage) + return; + Currentbuf->image_flag = IMG_FLAG_SKIP; + displayBuffer(Currentbuf, B_NORMAL); +} +#endif + #ifdef USE_MOUSE static void diff --git a/map.c b/map.c @@ -3,16 +3,73 @@ * client-side image maps */ #include "fm.h" +#include <math.h> #ifdef MENU_MAP +#ifdef USE_IMAGE +static int +inMapArea(MapArea * a, int x, int y) +{ + int i; + double r1, r2, s, c, t; + + if (!a) + return FALSE; + switch (a->shape) { + case SHAPE_RECT: + if (x >= a->coords[0] && y >= a->coords[1] && + x <= a->coords[2] && y <= a->coords[3]) + return TRUE; + break; + case SHAPE_CIRCLE: + if ((x - a->coords[0]) * (x - a->coords[0]) + + (y - a->coords[1]) * (y - a->coords[1]) + <= a->coords[2] * a->coords[2]) + return TRUE; + break; + case SHAPE_POLY: + for (t = 0, i = 0; i < a->ncoords; i += 2) { + r1 = sqrt((double)(x - a->coords[i]) * (x - a->coords[i]) + + (double)(y - a->coords[i + 1]) * (y - + a->coords[i + 1])); + r2 = sqrt((double)(x - a->coords[i + 2]) * (x - a->coords[i + 2]) + + (double)(y - a->coords[i + 3]) * (y - + a->coords[i + 3])); + if (r1 == 0 || r2 == 0) + return TRUE; + s = ((double)(x - a->coords[i]) * (y - a->coords[i + 3]) + - (double)(x - a->coords[i + 2]) * (y - + a->coords[i + + 1])) / r1 / r2; + c = ((double)(x - a->coords[i]) * (x - a->coords[i + 2]) + + (double)(y - a->coords[i + 1]) * (y - + a->coords[i + + 3])) / r1 / r2; + t += atan2(s, c); + } + if (fabs(t) > 2 * 3.14) + return TRUE; + break; + case SHAPE_DEFAULT: + return TRUE; + default: + break; + } + return FALSE; +} +#endif + char * -follow_map_menu(Buffer *buf, struct parsed_tagarg *arg, int x, int y) +follow_map_menu(Buffer *buf, struct parsed_tagarg *arg, Anchor *a_img, int x, + int y) { MapList *ml; + ListItem *al; + MapArea *a; char *name; - TextListItem *t, *s; - int i, n, selected = -1; + int i, n, selected = -1, initial; char **label; + int px, py, map = 0; name = tag_get_value(arg, "link"); if (name == NULL) @@ -22,24 +79,49 @@ follow_map_menu(Buffer *buf, struct parsed_tagarg *arg, int x, int y) if (!Strcmp_charp(ml->name, name)) break; } - if (ml == NULL) + if (ml == NULL || ml->area == NULL) return NULL; - for (n = 0, t = ml->urls->first; t != NULL; n++, t = t->next) ; + n = ml->area->nitem; if (n == 0) return NULL; label = New_N(char *, n + 1); - for (i = 0, t = ml->urls->first, s = ml->alts->first; t != NULL; - i++, t = t->next, s = s->next) - label[i] = *s->ptr ? s->ptr : t->ptr; +#ifdef USE_IMAGE + if (getMapXY(buf, a_img, &px, &py)) + map = 1; +#endif + initial = -n; + for (i = 0, al = ml->area->first; al != NULL; i++, al = al->next) { + a = (MapArea *) al->ptr; + if (a) { + label[i] = *a->alt ? a->alt : a->url; +#ifdef USE_IMAGE + if (initial < 0 && map && inMapArea(a, px, py)) { + if (a->shape == SHAPE_DEFAULT) { + if (initial == -n) + initial = -i; + } + else + initial = i; + } +#endif + } + else + label[i] = ""; + } label[n] = NULL; + if (initial == -n) + initial = 0; + else if (initial < 0) + initial *= -1; - optionMenu(x, y, label, &selected, 0, NULL); + optionMenu(x, y, label, &selected, initial, NULL); if (selected >= 0) { - for (i = 0, t = ml->urls->first; t != NULL; i++, t = t->next) - if (i == selected) - return t->ptr; + for (i = 0, al = ml->area->first; al != NULL; i++, al = al->next) { + if (al->ptr && i == selected) + return ((MapArea *) al->ptr)->url; + } } return NULL; } @@ -53,8 +135,9 @@ follow_map_panel(Buffer *buf, struct parsed_tagarg *arg) { Str mappage; MapList *ml; + ListItem *al; + MapArea *a; char *name; - TextListItem *t, *s; ParsedURL pu; name = tag_get_value(arg, "link"); @@ -69,15 +152,17 @@ follow_map_panel(Buffer *buf, struct parsed_tagarg *arg) return NULL; mappage = Strnew_charp(map1); - for (t = ml->urls->first, s = ml->alts->first; t != NULL; - t = t->next, s = s->next) { - parseURL2(t->ptr, &pu, baseURL(buf)); + for (al = ml->area->first; al != NULL; al = al->next) { + a = (MapArea *) al->ptr; + if (!a) + continue; + parseURL2(a->url, &pu, baseURL(buf)); Strcat_charp(mappage, "<a href=\""); Strcat_charp(mappage, html_quote(parsedURL2Str(&pu)->ptr)); Strcat_charp(mappage, "\">"); - Strcat_charp(mappage, html_quote(s->ptr)); + Strcat_charp(mappage, html_quote(a->alt)); Strcat_charp(mappage, " "); - Strcat_charp(mappage, html_quote(t->ptr)); + Strcat_charp(mappage, html_quote(a->url)); Strcat_charp(mappage, "</a><br>\n"); } Strcat_charp(mappage, "</body></html>"); @@ -86,6 +171,106 @@ follow_map_panel(Buffer *buf, struct parsed_tagarg *arg) } #endif +#ifdef USE_IMAGE +int +getMapXY(Buffer *buf, Anchor *a, int *x, int *y) +{ + if (!buf || !a || !a->image || !x || !y) + return 0; + *x = (int)((buf->currentColumn + buf->cursorX + - COLPOS(buf->currentLine, a->start.pos) + 0.5) + * pixel_per_char) - a->image->xoffset; + *y = (int)((buf->currentLine->linenumber - a->image->y + 0.5) + * pixel_per_line) - a->image->yoffset; + if (*x <= 0) + *x = 1; + if (*y <= 0) + *y = 1; + return 1; +} +#endif + +MapArea * +newMapArea(char *url, char *alt, char *shape, char *coords) +{ + MapArea *a = New(MapArea); +#ifdef MENU_MAP + char *p; + int i, max; +#endif + + a->url = url; + a->alt = alt ? alt : ""; +#ifdef MENU_MAP +#ifdef USE_IMAGE + a->shape = SHAPE_RECT; + if (shape) { + if (!strcasecmp(shape, "default")) + a->shape = SHAPE_DEFAULT; + else if (!strncasecmp(shape, "rect", 4)) + a->shape = SHAPE_RECT; + else if (!strncasecmp(shape, "circ", 4)) + a->shape = SHAPE_CIRCLE; + else if (!strncasecmp(shape, "poly", 4)) + a->shape = SHAPE_POLY; + else + a->shape = SHAPE_UNKNOWN; + } + a->coords = NULL; + a->ncoords = 0; + if (a->shape == SHAPE_UNKNOWN || a->shape == SHAPE_DEFAULT) + return a; + if (!coords) { + a->shape = SHAPE_UNKNOWN; + return a; + } + if (a->shape == SHAPE_RECT) { + a->coords = New_N(short, 4); + a->ncoords = 4; + } + else if (a->shape == SHAPE_CIRCLE) { + a->coords = New_N(short, 3); + a->ncoords = 3; + } + max = a->ncoords; + for (i = 0, p = coords; (a->shape == SHAPE_POLY || i < a->ncoords) && *p;) { + while (IS_SPACE(*p)) + p++; + if (!IS_DIGIT(*p)) + break; + if (a->shape == SHAPE_POLY) { + if (max <= i) { + max = i ? i * 2 : 6; + a->coords = New_Reuse(short, a->coords, max + 2); + } + a->ncoords++; + } + a->coords[i] = (short)atoi(p); + i++; + while (IS_DIGIT(*p)) + p++; + if (*p != ',' && !IS_SPACE(*p)) + break; + while (IS_SPACE(*p)) + p++; + if (*p == ',') + p++; + } + if (i != a->ncoords || (a->shape == SHAPE_POLY && a->ncoords < 6)) { + a->shape = SHAPE_UNKNOWN; + a->coords = NULL; + a->ncoords = 0; + } + if (a->shape == SHAPE_POLY) { + a->ncoords = a->ncoords / 2 * 2; + a->coords[a->ncoords] = a->coords[0]; + a->coords[a->ncoords + 1] = a->coords[1]; + } +#endif +#endif + return a; +} + /* append frame URL */ static void append_frame_info(Buffer *buf, Str html, struct frameset *set, int level) diff --git a/menu.c b/menu.c @@ -1327,8 +1327,13 @@ smChBuf(void) return; for (i = 0, buf = Firstbuf; i < SelectV; i++, buf = buf->nextBuffer) ; Currentbuf = buf; - if (clear_buffer) { - for (buf = Firstbuf; buf != NULL; buf = buf->nextBuffer) + for (buf = Firstbuf; buf != NULL; buf = buf->nextBuffer) { + if (buf == Currentbuf) + continue; +#ifdef USE_IMAGE + deleteImage(buf); +#endif + if (clear_buffer) tmpClearBuffer(buf); } } diff --git a/parsetagx.c b/parsetagx.c @@ -73,6 +73,12 @@ toAlign(char *oval, int *align) *align = ALIGN_RIGHT; else if (strcasecmp(oval, "center") == 0) *align = ALIGN_CENTER; + else if (strcasecmp(oval, "top") == 0) + *align = ALIGN_TOP; + else if (strcasecmp(oval, "bottom") == 0) + *align = ALIGN_BOTTOM; + else if (strcasecmp(oval, "middle") == 0) + *align = ALIGN_MIDDLE; else return 0; return 1; diff --git a/proto.h b/proto.h @@ -102,6 +102,13 @@ extern void rFrame(void); extern void extbrz(void); extern void linkbrz(void); extern void curlno(void); +#ifdef USE_IMAGE +extern void dispI(void); +extern void stopI(void); +#else +#define dispI nulcmd +#define stopI nulcmd +#endif #ifdef USE_ALARM extern void setAlarm(void); extern void setAlarmEvent(int sec, short status, int cmd, void *data); @@ -137,7 +144,14 @@ extern void save_fonteffect(struct html_feed_environ *h_env, struct readbuffer *obuf); extern void restore_fonteffect(struct html_feed_environ *h_env, struct readbuffer *obuf); -extern Str process_img(struct parsed_tag *tag); +#ifdef USE_IMAGE +extern void deleteImage(Buffer *buf); +extern void getAllImage(Buffer *buf); +extern void loadImage(int flag); +extern ImageCache *getImage(Image * image, ParsedURL *current, int flag); +extern int getImageSize(ImageCache * cache); +#endif +extern Str process_img(struct parsed_tag *tag, int width); extern Str process_anchor(struct parsed_tag *tag, char *tagbuf); extern Str process_input(struct parsed_tag *tag); extern void process_select(struct parsed_tag *tag); @@ -168,6 +182,9 @@ extern Buffer *loadHTMLString(Str page); extern Buffer *loadGopherDir(URLFile *uf, Buffer *newBuf); #endif /* USE_GOPHER */ extern Buffer *loadBuffer(URLFile *uf, Buffer *newBuf); +#ifdef USE_IMAGE +extern Buffer *loadImageBuffer(URLFile *uf, Buffer *newBuf); +#endif extern void saveBuffer(Buffer *buf, FILE * f); extern void saveBufferDelNum(Buffer *buf, FILE * f, int del); extern Buffer *getshell(char *cmd); @@ -316,11 +333,15 @@ extern void form_write_from_file(FILE * f, char *boundary, char *name, char *filename, char *file); extern void follow_map(struct parsed_tagarg *arg); #ifdef MENU_MAP -extern char *follow_map_menu(Buffer *buf, struct parsed_tagarg *arg, int x, - int y); +extern char *follow_map_menu(Buffer *buf, struct parsed_tagarg *arg, + Anchor *a_img, int x, int y); #else extern Buffer *follow_map_panel(Buffer *buf, struct parsed_tagarg *arg); #endif +#ifdef USE_IMAGE +extern int getMapXY(Buffer *buf, Anchor *a, int *x, int *y); +#endif +extern MapArea *newMapArea(char *url, char *alt, char *shape, char *coords); extern Buffer *page_info_panel(Buffer *buf); extern struct frame_body *newFrame(struct parsed_tag *tag, Buffer *buf); extern struct frameset *newFrameSet(struct parsed_tag *tag); @@ -397,6 +418,9 @@ extern void toggle_stand(void); extern char getch(void); extern void bell(void); extern void sleep_till_anykey(int sec, int purge); +#ifdef USE_IMAGE +extern void touch_cursor(); +#endif #ifdef JP_CHARSET extern char *GetSICode(char key); extern char *GetSOCode(char key); @@ -526,6 +550,11 @@ extern void reMark(void); #define prevMk nulcmd #define reMark nulcmd #endif /* not USE_MARK */ +#ifdef JP_CHARSET +extern char *cURLcode(char *url, char code); +#else +#define cURLcode(url,buf) (url) +#endif #ifdef USE_MOUSE extern void mouse(void); @@ -539,6 +568,15 @@ extern void msToggle(void); #define msToggle nulcmd #endif /* not USE_MOUSE */ +#ifdef USE_IMAGE +extern void initImage(void); +extern void termImage(void); +extern void addImage(ImageCache * cache, int x, int y, int sx, int sy, int w, + int h); +extern void drawImage(void); +extern void clearImage(void); +#endif + extern char *searchKeyData(void); extern void initKeymap(void); diff --git a/rc.c b/rc.c @@ -52,11 +52,13 @@ static char *config_file = NULL; #endif #define P_PIXELS 8 #define P_NZINT 9 +#define P_SCALE 10 #if LANG == JA #define CMT_HELPER "外部ビューアの編集" #define CMT_TABSTOP "タブ幅" #define CMT_PIXEL_PER_CHAR "文字幅 (4.0...32.0)" +#define CMT_PIXEL_PER_LINE "一行の高さ (4.0...64.0)" #define CMT_PAGERLINE "ページャとして利用した時に保存される行数" #define CMT_HISTSIZE "保持するURL履歴の数" #define CMT_SAVEHIST "URL履歴の保存" @@ -65,6 +67,14 @@ static char *config_file = NULL; #define CMT_ARGV_IS_URL "scheme のない引数も URL とみなす" #define CMT_TSELF "targetが未指定の場合に_selfを使用する" #define CMT_DISPLINK "リンク先の自動表示" +#ifdef USE_IMAGE +#define CMT_DISP_IMAGE "インライン画像を表示" +#define CMT_AUTO_IMAGE "インライン画像を自動で読み込む" +#define CMT_EXT_IMAGE_VIEWER "画像を外部ビューワで表示" +#define CMT_IMAGE_SCALE "画像のスケール(%)" +#define CMT_IMGDISPLAY "画像を表示するためのコマンド" +#define CMT_IMGSIZE "画像の大きさを得るためのコマンド" +#endif #define CMT_MULTICOL "ファイル名のマルチカラム表示" #define CMT_ALT_ENTITY "エンティティを ASCII の代替表現で表す" #define CMT_FOLD_TEXTAREA "TEXTAREA の行を折り返して表示" @@ -181,6 +191,7 @@ static char *config_file = NULL; #define CMT_HELPER "External Viewer Setup" #define CMT_TABSTOP "Tab width" #define CMT_PIXEL_PER_CHAR "# of pixels per character (4.0...32.0)" +#define CMT_PIXEL_PER_LINE "# of pixels per line (4.0...64.0)" #define CMT_PAGERLINE "# of reserved line when w3m is used as a pager" #define CMT_HISTSIZE "# of reserved URL" #define CMT_SAVEHIST "Save URL history" @@ -189,6 +200,14 @@ static char *config_file = NULL; #define CMT_ARGV_IS_URL "Force argument without scheme to URL" #define CMT_TSELF "Use _self as default target" #define CMT_DISPLINK "Automatic display of link URL" +#ifdef USE_IMAGE +#define CMT_DISP_IMAGE "Display of inline image" +#define CMT_AUTO_IMAGE "Automatic loading of inline image" +#define CMT_EXT_IMAGE_VIEWER "Use external image viewer" +#define CMT_IMAGE_SCALE "Scale of image (%)" +#define CMT_IMGDISPLAY "External command to display image" +#define CMT_IMGSIZE "External command to get size of image" +#endif #define CMT_MULTICOL "Multi-column output of file names" #define CMT_ALT_ENTITY "Use alternate expression with ASCII for entity" #define CMT_FOLD_TEXTAREA "Fold lines of TEXTAREA" @@ -413,6 +432,10 @@ struct param_ptr params1[] = { {"tabstop", P_NZINT, PI_TEXT, (void *)&Tabstop, CMT_TABSTOP, NULL}, {"pixel_per_char", P_PIXELS, PI_TEXT, (void *)&pixel_per_char, CMT_PIXEL_PER_CHAR, NULL}, +#ifdef USE_IMAGE + {"pixel_per_line", P_PIXELS, PI_TEXT, (void *)&pixel_per_line, + CMT_PIXEL_PER_LINE, NULL}, +#endif #ifdef JP_CHARSET {"kanjicode", P_CODE, PI_SEL_C, (void *)&DisplayCode, CMT_KANJICODE, kcodestr}, @@ -438,6 +461,18 @@ struct param_ptr params1[] = { CMT_IGNORE_NULL_IMG_ALT, NULL}, {"view_unseenobject", P_INT, PI_ONOFF, (void *)&view_unseenobject, CMT_VIEW_UNSEENOBJECTS, NULL}, +#ifdef USE_IMAGE + {"display_image", P_INT, PI_ONOFF, (void *)&displayImage, CMT_DISP_IMAGE, + NULL}, + {"auto_image", P_INT, PI_ONOFF, (void *)&autoImage, CMT_AUTO_IMAGE, NULL}, + {"ext_image_viewer", P_INT, PI_ONOFF, (void *)&useExtImageViewer, + CMT_EXT_IMAGE_VIEWER, NULL}, + {"image_scale", P_SCALE, PI_TEXT, (void *)&image_scale, CMT_IMAGE_SCALE, + NULL}, + {"imgdisplay", P_STRING, PI_TEXT, (void *)&Imgdisplay, CMT_IMGDISPLAY, + NULL}, + {"imgsize", P_STRING, PI_TEXT, (void *)&Imgsize, CMT_IMGSIZE, NULL}, +#endif {"show_lnum", P_INT, PI_ONOFF, (void *)&showLineNum, CMT_SHOW_NUM, NULL}, {"show_srch_str", P_INT, PI_ONOFF, (void *)&show_srch_str, CMT_SHOW_SRCH_STR, NULL}, @@ -818,6 +853,9 @@ show_params(FILE * fp) case P_PIXELS: t = "number"; break; + case P_SCALE: + t = "percent"; + break; } #ifdef JP_CHARSET if (InnerCode != DisplayCode) @@ -1019,7 +1057,12 @@ set_param(char *name, char *value) #endif case P_PIXELS: ppc = atof(value); - if (ppc >= MINIMUM_PIXEL_PER_CHAR && ppc <= MAXIMUM_PIXEL_PER_CHAR) + if (ppc >= MINIMUM_PIXEL_PER_CHAR && ppc <= MAXIMUM_PIXEL_PER_CHAR * 2) + *(double *)p->varptr = ppc; + break; + case P_SCALE: + ppc = atof(value); + if (ppc >= 10 && ppc <= 1000) *(double *)p->varptr = ppc; break; } @@ -1159,6 +1202,10 @@ sync_with_option(void) #ifdef USE_MIGEMO init_migemo(); #endif +#ifdef USE_IMAGE + if (fmInitialized && displayImage) + initImage(); +#endif if (AcceptLang == NULL || *AcceptLang == '\0') { #if LANG == JA @@ -1261,6 +1308,7 @@ to_str(struct param_ptr *p) #endif return Strnew_charp(*(char **)p->varptr); case P_PIXELS: + case P_SCALE: return Sprintf("%g", *(double *)p->varptr); } /* not reached */ diff --git a/scripts/multipart/multipart.cgi.in b/scripts/multipart/multipart.cgi.in @@ -155,11 +155,14 @@ while(! $end) { } $type = $header{"content-type"}; $dispos = $header{"content-disposition"}; - if ((! $type || $type =~ /^text\/plain/i) && - (! $dispos || $dispos =~ /^inline/i)) { - $plain = 1; - } else { - $plain = 0; + $plain = 0; + $image = 0; + if (! $dispos || $dispos =~ /^inline/i) { + if (! $type || $type =~ /^text\/plain/i) { + $plain = 1; + } elsif ($type =~ /^image\//i) { + $image = 1; + } } $body = ''; while(<F>) { @@ -193,8 +196,13 @@ while(! $end) { print "<input type=hidden name=file value=\"$qfile\">\n"; print "<input type=hidden name=boundary value=\"$qboundary\">\n"; print "<input type=hidden name=count value=\"$count\">\n"; - print "<input type=submit name=submit value=\"", - &html_quote($name), "\">\n"; + if ($image) { + print "<input type=image name=submit src=\"$CGI?file=$qfile&amp;boundary=$qboundary&amp;count=$count\" alt=\"", + &html_quote($name), "\">\n"; + } else { + print "<input type=submit name=submit value=\"", + &html_quote($name), "\">\n"; + } print "</form>\n" } if ($plain) { diff --git a/scripts/w3mhelp.cgi.in b/scripts/w3mhelp.cgi.in @@ -132,7 +132,7 @@ for $otherlang (@docdirs) { &show_keymap("Buffer operation", split(" ", "backBf selMn selBuf vwSrc svSrc svBuf - editBf editScr reload rdrwSc")); + editBf editScr reload rdrwSc dispI stopI")); &show_keymap("Bookmark operation", split(" ", "ldBmark adBmark")); diff --git a/table.c b/table.c @@ -2786,7 +2786,22 @@ feed_table_tag(struct table *tbl, char *line, struct table_mode *mode, mode->pre_mode &= ~TBLM_PRE_INT; break; case HTML_IMG: - tok = process_img(tag); + w = tbl->fixed_width[tbl->col]; + if (w < 0) { + if (tbl->total_width > 0) + w = -tbl->total_width * w / 100; + else if (width > 0) + w = -width * w / 100; + else + w = 0; + } + else if (w == 0) { + if (tbl->total_width > 0) + w = tbl->total_width; + else if (width > 0) + w = width; + } + tok = process_img(tag, w); feed_table1(tbl, tok, mode, width); break; case HTML_FORM: diff --git a/tagtable.tab b/tagtable.tab @@ -45,6 +45,7 @@ pre HTML_PRE blockquote HTML_BLQ /blockquote HTML_N_BLQ img HTML_IMG +image HTML_IMG code HTML_NOP /code HTML_NOP dfn HTML_NOP diff --git a/terms.c b/terms.c @@ -1865,7 +1865,14 @@ wgetch(void) { char c; - read(tty, &c, 1); + /* read(tty, &c, 1); */ + while (read(tty, &c, 1) < (ssize_t) 1) { + if (errno == EINTR || errno == EAGAIN) + continue; + /* error happend on read(2) */ + quitfm(); + break; /* unreachable */ + } return c; } @@ -2159,3 +2166,20 @@ flush_tty() { fflush(ttyf); } + +#ifdef USE_IMAGE +void +touch_cursor() +{ + touch_line(); + touch_column(CurColumn); +#ifdef JP_CHARSET + if (CurColumn > 0 && + CHMODE(ScreenImage[CurLine]->lineprop[CurColumn]) == C_WCHAR2) + touch_column(CurColumn - 1); + else if (CurColumn < COLS - 1 && + CHMODE(ScreenImage[CurLine]->lineprop[CurColumn]) == C_WCHAR1) + touch_column(CurColumn + 1); +#endif +} +#endif diff --git a/w3mimgdisplay.c b/w3mimgdisplay.c @@ -0,0 +1,369 @@ +/* $Id$ */ +#include <stdio.h> +#include <stdlib.h> +#include <Imlib.h> + +static Display *display; +static Window window, parent; +static unsigned long background_pixel; +static char *background = NULL; +static int offset_x = 2, offset_y = 2; +static int defined_bg = 0, defined_x = 0, defined_y = 0, defined_test = 0; +static int defined_debug = 0; + +#define MAX_IMAGE 1000 +typedef struct { + Pixmap pixmap; + int width; + int height; +} Image; +static Image *imageBuf = NULL; +static int maxImage = 0; +static GC imageGC = NULL; + +static void GetOption(int argc, char **argv); +static void DrawImage(char *buf, int redraw); +static void ClearImage(void); + +/* *INDENT-OFF* */ +/* + xterm/kterm/hanterm/cxterm + top window (WINDOWID) + +- text window + +- scrollbar + rxvt/aterm/Eterm/wterm + top window (WINDOWID) + +- text window + +- scrollbar + +- menubar (etc.) + gnome-terminal + top window + +- text window (WINDOWID) + +- scrollbar + +- menubar + mlterm (-s) + top window + +- text window (WINDOWID) + +- scrollbar + mlterm + top window = text window (WINDOWID) + + powershell + top window + +- window + | +- text window + | +- scrollbar + +- menubar (etc.) + dtterm + top window + +- window + +- window + | +- window + | +- text window + | +- scrollbar + +- menubar + hpterm + top window + +- window + +- text window + +- scrollbar + +- (etc.) +*/ +/* *INDENT-ON* */ + +int +main(int argc, char **argv) +{ + Window root, *children; + XWindowAttributes attr; + XColor screen_def, exact_def; + int revert, nchildren, len, width, height, i; + char buf[1024 + 128]; + char *id; + + GetOption(argc, argv); + if (!defined_debug) + fclose(stderr); + + display = XOpenDisplay(NULL); + if (!display) + exit(1); + if ((id = getenv("WINDOWID")) != NULL) + window = (Window) atoi(id); + else + XGetInputFocus(display, &window, &revert); + if (!window) + exit(1); + + XGetWindowAttributes(display, window, &attr); + width = attr.width; + height = attr.height; + while (1) { + Window p_window; + + XQueryTree(display, window, &root, &parent, &children, &nchildren); + if (defined_debug) + fprintf(stderr, + "window=%x root=%x parent=%x nchildren=%d width=%d height=%d\n", + window, root, parent, nchildren, width, height); + p_window = window; + for (i = 0; i < nchildren; i++) { + XGetWindowAttributes(display, children[i], &attr); + if (defined_debug) + fprintf(stderr, + "children[%d]=%x x=%d y=%d width=%d height=%d\n", i, + children[i], attr.x, attr.y, attr.width, attr.height); + if (attr.width > width * 0.7 && attr.height > height * 0.7) { + /* maybe text window */ + width = attr.width; + height = attr.height; + window = children[i]; + } + } + if (p_window == window) + break; + } + if (!defined_x) { + for (i = 0; i < nchildren; i++) { + XGetWindowAttributes(display, children[i], &attr); + if (attr.x <= 0 && attr.width < 30 && attr.height > height * 0.7) { + if (defined_debug) + fprintf(stderr, + "children[%d]=%x x=%d y=%d width=%d height=%d\n", + i, children[i], attr.x, attr.y, attr.width, + attr.height); + /* scrollbar of xterm/kterm ? */ + offset_x += attr.x + attr.width + attr.border_width * 2; + break; + } + } + } + + if (defined_test) { + printf("%d %d\n", width - offset_x, height - offset_y); + exit(0); + } + + if (defined_bg && XAllocNamedColor(display, DefaultColormap(display, 0), + background, &screen_def, &exact_def)) + background_pixel = screen_def.pixel; + else { + Pixmap p; + GC gc; + XImage *i; + + p = XCreatePixmap(display, window, 1, 1, DefaultDepth(display, 0)); + gc = XCreateGC(display, window, 0, NULL); + if (!p || !gc) + exit(1); + XCopyArea(display, window, p, gc, (offset_x >= 1) ? (offset_x - 1) : 0, + (offset_y >= 1) ? (offset_y - 1) : 0, 1, 1, 0, 0); + i = XGetImage(display, p, 0, 0, 1, 1, -1, ZPixmap); + if (!i) + exit(1); + background_pixel = XGetPixel(i, 0, 0); + XDestroyImage(i); + XFreeGC(display, gc); + XFreePixmap(display, p); +/* + background_pixel = WhitePixel(display, 0); +*/ + } + + while (fgets(buf, sizeof(buf), stdin) != NULL) { + if (!(isdigit(buf[0]) && buf[1] == ';')) { + fputc('\n', stdout); + fflush(stdout); + continue; + } + len = strlen(buf); + if (buf[len - 1] == '\n') { + buf[--len] = '\0'; + if (buf[len - 1] == '\r') + buf[--len] = '\0'; + } + switch (buf[0]) { + case '0': + DrawImage(&buf[2], 0); + break; + case '1': + DrawImage(&buf[2], 1); + break; + case '2': + ClearImage(); + break; + case '3': + XSync(display, False); + break; + case '4': + fputs("\n", stdout); + fflush(stdout); + break; + } + } + ClearImage(); + /* + * XCloseDisplay(display); + */ + exit(0); +} + +static void +GetOption(int argc, char **argv) +{ + int i; + + for (i = 1; i < argc; i++) { + if (!strcmp("-bg", argv[i])) { + if (++i >= argc) + exit(1); + background = argv[i]; + defined_bg = 1; + } + else if (!strcmp("-x", argv[i])) { + if (++i >= argc) + exit(1); + offset_x = atoi(argv[i]); + defined_x = 1; + } + else if (!strcmp("-y", argv[i])) { + if (++i >= argc) + exit(1); + offset_y = atoi(argv[i]); + defined_y = 1; + } + else if (!strcmp("-test", argv[i])) { + defined_test = 1; + } + else if (!strcmp("-debug", argv[i])) { + defined_debug = 1; + } + else { + exit(1); + } + } +} + +void +DrawImage(char *buf, int redraw) +{ + static ImlibData *id = NULL; + ImlibImage *im; + char *p = buf; + int n = 0, x = 0, y = 0, w = 0, h = 0, sx = 0, sy = 0, sw = 0, sh = 0; + + if (!p) + return; + for (; isdigit(*p); p++) + n = 10 * n + (*p - '0'); + if (*(p++) != ';') + return; + for (; isdigit(*p); p++) + x = 10 * x + (*p - '0'); + if (*(p++) != ';') + return; + for (; isdigit(*p); p++) + y = 10 * y + (*p - '0'); + if (*(p++) != ';') + return; + for (; isdigit(*p); p++) + w = 10 * w + (*p - '0'); + if (*(p++) != ';') + return; + for (; isdigit(*p); p++) + h = 10 * h + (*p - '0'); + if (*(p++) != ';') + return; + for (; isdigit(*p); p++) + sx = 10 * sx + (*p - '0'); + if (*(p++) != ';') + return; + for (; isdigit(*p); p++) + sy = 10 * sy + (*p - '0'); + if (*(p++) != ';') + return; + for (; isdigit(*p); p++) + sw = 10 * sw + (*p - '0'); + if (*(p++) != ';') + return; + for (; isdigit(*p); p++) + sh = 10 * sh + (*p - '0'); + if (*(p++) != ';') + return; + + n--; + if (n < 0 || n >= MAX_IMAGE) + return; + if (redraw) { + if (!imageGC || n >= maxImage || !imageBuf[n].pixmap) + return; + goto draw_image; + } + if (!id) { + id = Imlib_init(display); + if (!id) + return; + } + if (!imageGC) { + imageGC = XCreateGC(display, parent, 0, NULL); + if (!imageGC) + return; + } + if (n >= maxImage) { + int i = maxImage; + maxImage = i ? (i * 2) : 2; + if (maxImage > MAX_IMAGE) + maxImage = MAX_IMAGE; + else if (n >= maxImage) + maxImage = n + 1; + imageBuf = (Image *) realloc((void *)imageBuf, + sizeof(Image) * maxImage); + for (; i < maxImage; i++) + imageBuf[i].pixmap = NULL; + } + if (imageBuf[n].pixmap) { + XFreePixmap(display, imageBuf[n].pixmap); + imageBuf[n].pixmap = NULL; + } + + im = Imlib_load_image(id, p); + if (!im) + return; + if (!w) + w = im->rgb_width; + if (!h) + h = im->rgb_height; + imageBuf[n].pixmap = XCreatePixmap(display, parent, w, h, + DefaultDepth(display, 0)); + if (!imageBuf[n].pixmap) + return; + XSetForeground(display, imageGC, background_pixel); + XFillRectangle(display, imageBuf[n].pixmap, imageGC, 0, 0, w, h); + Imlib_paste_image(id, im, imageBuf[n].pixmap, 0, 0, w, h); + Imlib_kill_image(id, im); + imageBuf[n].width = w; + imageBuf[n].height = h; + draw_image: + XCopyArea(display, imageBuf[n].pixmap, window, imageGC, + sx, sy, (sw ? sw : imageBuf[n].width), + (sh ? sh : imageBuf[n].height), x + offset_x, y + offset_y); +} + +void +ClearImage(void) +{ + if (imageGC) { + XFreeGC(display, imageGC); + imageGC = NULL; + } + if (imageBuf) { + int i; + for (i = 0; i < maxImage; i++) { + if (imageBuf[i].pixmap) + XFreePixmap(display, imageBuf[i].pixmap); + } + free(imageBuf); + imageBuf = NULL; + } + maxImage = 0; +} diff --git a/w3mimgsize.c b/w3mimgsize.c @@ -0,0 +1,31 @@ +/* $Id$ */ +#include <stdio.h> +#include <stdlib.h> +#include <Imlib.h> + +int +main(int argc, char **argv) +{ + Display *display; + ImlibData *id; + ImlibImage *im; + + fclose(stderr); + if (argc < 2) + exit(1); + display = XOpenDisplay(NULL); + if (!display) + exit(1); + id = Imlib_init(display); + if (!id) + exit(1); + im = Imlib_load_image(id, argv[1]); + if (!im) + exit(1); + printf("%d %d\n", im->rgb_width, im->rgb_height); + /* + * Imlib_kill_image(id, im); + * XCloseDisplay(display); + */ + exit(0); +}