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 | ++ |
M | ChangeLog | | | 184 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | NEWS | | | 5 | +++++ |
M | XMakefile | | | 20 | ++++++++++++++++++-- |
M | anchor.c | | | 77 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | buffer.c | | | 6 | ++++++ |
M | config.h.dist | | | 3 | +++ |
M | configure | | | 44 | ++++++++++++++++++++++++++++++++++++++++++-- |
M | display.c | | | 152 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++---- |
M | doc-jp/README.func | | | 2 | ++ |
A | doc-jp/README.img | | | 253 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | doc/README.func | | | 2 | ++ |
A | doc/README.img | | | 189 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | etc.c | | | 1 | + |
M | file.c | | | 639 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------- |
M | fm.h | | | 93 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- |
M | frame.c | | | 9 | +++++++-- |
M | funcname.tab | | | 2 | ++ |
M | html.c | | | 28 | +++++++++++++++++----------- |
M | html.h | | | 17 | ++++++++++++++--- |
A | image.c | | | 528 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
M | main.c | | | 126 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------- |
M | map.c | | | 221 | ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- |
M | menu.c | | | 9 | +++++++-- |
M | parsetagx.c | | | 6 | ++++++ |
M | proto.h | | | 44 | +++++++++++++++++++++++++++++++++++++++++--- |
M | rc.c | | | 50 | +++++++++++++++++++++++++++++++++++++++++++++++++- |
M | scripts/multipart/multipart.cgi.in | | | 22 | +++++++++++++++------- |
M | scripts/w3mhelp.cgi.in | | | 2 | +- |
M | table.c | | | 17 | ++++++++++++++++- |
M | tagtable.tab | | | 1 | + |
M | terms.c | | | 26 | +++++++++++++++++++++++++- |
A | w3mimgdisplay.c | | | 369 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ |
A | w3mimgsize.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&boundary=$qboundary&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);
+}