aboutsummaryrefslogtreecommitdiffstats
path: root/display.c
diff options
context:
space:
mode:
authorTatsuya Kinoshita <tats@vega.ocn.ne.jp>2011-05-04 07:18:09 +0000
committerTatsuya Kinoshita <tats@vega.ocn.ne.jp>2011-05-04 07:18:09 +0000
commit5f8e0f8ef9a422691dd72e8a953a42a41478fcb4 (patch)
tree4b2df4796a534793648b3c4fc532fc36bd0cd525 /display.c
parentReleasing debian version 0.3-2.4 (diff)
downloadw3m-debian/0.5.1-1.tar.gz
w3m-debian/0.5.1-1.zip
Releasing debian version 0.5.1-1debian/0.5.1-1
Diffstat (limited to '')
-rw-r--r--display.c1586
1 files changed, 1586 insertions, 0 deletions
diff --git a/display.c b/display.c
new file mode 100644
index 0000000..507f22b
--- /dev/null
+++ b/display.c
@@ -0,0 +1,1586 @@
+/* $Id: display.c,v 1.68 2003/09/26 17:59:51 ukai Exp $ */
+#include <signal.h>
+#include "fm.h"
+
+#define MAX(a, b) ((a) > (b) ? (a) : (b))
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+
+/* *INDENT-OFF* */
+#ifdef USE_COLOR
+
+#define EFFECT_ANCHOR_START effect_anchor_start()
+#define EFFECT_ANCHOR_END effect_anchor_end()
+#define EFFECT_IMAGE_START effect_image_start()
+#define EFFECT_IMAGE_END effect_image_end()
+#define EFFECT_FORM_START effect_form_start()
+#define EFFECT_FORM_END effect_form_end()
+#define EFFECT_ACTIVE_START effect_active_start()
+#define EFFECT_ACTIVE_END effect_active_end()
+#define EFFECT_VISITED_START effect_visited_start()
+#define EFFECT_VISITED_END effect_visited_end()
+#define EFFECT_MARK_START effect_mark_start()
+#define EFFECT_MARK_END effect_mark_end()
+
+/*-
+ * color:
+ * 0 black
+ * 1 red
+ * 2 green
+ * 3 yellow
+ * 4 blue
+ * 5 magenta
+ * 6 cyan
+ * 7 white
+ */
+
+#define EFFECT_ANCHOR_START_C setfcolor(anchor_color)
+#define EFFECT_IMAGE_START_C setfcolor(image_color)
+#define EFFECT_FORM_START_C setfcolor(form_color)
+#define EFFECT_ACTIVE_START_C (setfcolor(active_color), underline())
+#define EFFECT_VISITED_START_C setfcolor(visited_color)
+#ifdef USE_BG_COLOR
+#define EFFECT_MARK_START_C setbcolor(mark_color)
+#else
+#define EFFECT_MARK_START_C standout()
+#endif
+
+#define EFFECT_IMAGE_END_C setfcolor(basic_color)
+#define EFFECT_ANCHOR_END_C setfcolor(basic_color)
+#define EFFECT_FORM_END_C setfcolor(basic_color)
+#define EFFECT_ACTIVE_END_C (setfcolor(basic_color), underlineend())
+#define EFFECT_VISITED_END_C setfcolor(basic_color)
+#ifdef USE_BG_COLOR
+#define EFFECT_MARK_END_C setbcolor(bg_color)
+#else
+#define EFFECT_MARK_END_C standend()
+#endif
+
+#define EFFECT_ANCHOR_START_M underline()
+#define EFFECT_ANCHOR_END_M underlineend()
+#define EFFECT_IMAGE_START_M standout()
+#define EFFECT_IMAGE_END_M standend()
+#define EFFECT_FORM_START_M standout()
+#define EFFECT_FORM_END_M standend()
+#define EFFECT_ACTIVE_START_NC underline()
+#define EFFECT_ACTIVE_END_NC underlineend()
+#define EFFECT_ACTIVE_START_M bold()
+#define EFFECT_ACTIVE_END_M boldend()
+#define EFFECT_VISITED_START_M /**/
+#define EFFECT_VISITED_END_M /**/
+#define EFFECT_MARK_START_M standout()
+#define EFFECT_MARK_END_M standend()
+#define define_effect(name_start,name_end,color_start,color_end,mono_start,mono_end) \
+static void name_start { if (useColor) { color_start; } else { mono_start; }}\
+static void name_end { if (useColor) { color_end; } else { mono_end; }}
+
+define_effect(EFFECT_ANCHOR_START, EFFECT_ANCHOR_END, EFFECT_ANCHOR_START_C,
+ EFFECT_ANCHOR_END_C, EFFECT_ANCHOR_START_M, EFFECT_ANCHOR_END_M)
+define_effect(EFFECT_IMAGE_START, EFFECT_IMAGE_END, EFFECT_IMAGE_START_C,
+ EFFECT_IMAGE_END_C, EFFECT_IMAGE_START_M, EFFECT_IMAGE_END_M)
+define_effect(EFFECT_FORM_START, EFFECT_FORM_END, EFFECT_FORM_START_C,
+ EFFECT_FORM_END_C, EFFECT_FORM_START_M, EFFECT_FORM_END_M)
+define_effect(EFFECT_MARK_START, EFFECT_MARK_END, EFFECT_MARK_START_C,
+ EFFECT_MARK_END_C, EFFECT_MARK_START_M, EFFECT_MARK_END_M)
+
+/*****************/
+static void
+EFFECT_ACTIVE_START
+{
+ if (useColor) {
+ if (useActiveColor) {
+#ifdef __EMX__
+ if(!getenv("WINDOWID"))
+ setfcolor(active_color);
+ else
+#endif
+ {
+ EFFECT_ACTIVE_START_C;
+ }
+ } else {
+ EFFECT_ACTIVE_START_NC;
+ }
+ } else {
+ EFFECT_ACTIVE_START_M;
+ }
+}
+
+static void
+EFFECT_ACTIVE_END
+{
+ if (useColor) {
+ if (useActiveColor) {
+ EFFECT_ACTIVE_END_C;
+ } else {
+ EFFECT_ACTIVE_END_NC;
+ }
+ } else {
+ EFFECT_ACTIVE_END_M;
+ }
+}
+
+static void
+EFFECT_VISITED_START
+{
+ if (useVisitedColor) {
+ if (useColor) {
+ EFFECT_VISITED_START_C;
+ } else {
+ EFFECT_VISITED_START_M;
+ }
+ }
+}
+
+static void
+EFFECT_VISITED_END
+{
+ if (useVisitedColor) {
+ if (useColor) {
+ EFFECT_VISITED_END_C;
+ } else {
+ EFFECT_VISITED_END_M;
+ }
+ }
+}
+
+#else /* not USE_COLOR */
+
+#define EFFECT_ANCHOR_START underline()
+#define EFFECT_ANCHOR_END underlineend()
+#define EFFECT_IMAGE_START standout()
+#define EFFECT_IMAGE_END standend()
+#define EFFECT_FORM_START standout()
+#define EFFECT_FORM_END standend()
+#define EFFECT_ACTIVE_START bold()
+#define EFFECT_ACTIVE_END boldend()
+#define EFFECT_VISITED_START /**/
+#define EFFECT_VISITED_END /**/
+#define EFFECT_MARK_START standout()
+#define EFFECT_MARK_END standend()
+#endif /* not USE_COLOR */
+/* *INDENT-ON* */
+
+void
+fmTerm(void)
+{
+ if (fmInitialized) {
+ move(LASTLINE, 0);
+ clrtoeolx();
+ refresh();
+#ifdef USE_IMAGE
+ if (activeImage)
+ loadImage(NULL, IMG_FLAG_STOP);
+#endif
+#ifdef USE_MOUSE
+ if (use_mouse)
+ mouse_end();
+#endif /* USE_MOUSE */
+ reset_tty();
+ fmInitialized = FALSE;
+ }
+}
+
+
+/*
+ * Initialize routine.
+ */
+void
+fmInit(void)
+{
+ if (!fmInitialized) {
+ initscr();
+ term_raw();
+ term_noecho();
+#ifdef USE_IMAGE
+ if (displayImage)
+ initImage();
+#endif
+ }
+ fmInitialized = TRUE;
+}
+
+/*
+ * Display some lines.
+ */
+static Line *cline = NULL;
+static int ccolumn = -1;
+
+static int ulmode = 0, somode = 0, bomode = 0;
+static int anch_mode = 0, emph_mode = 0, imag_mode = 0, form_mode = 0,
+ active_mode = 0, visited_mode = 0, mark_mode = 0, graph_mode = 0;
+#ifdef USE_ANSI_COLOR
+static Linecolor color_mode = 0;
+#endif
+
+#ifdef USE_BUFINFO
+static Buffer *save_current_buf = NULL;
+#endif
+
+static char *delayed_msg = NULL;
+
+static void drawAnchorCursor(Buffer *buf);
+#define redrawBuffer(buf) redrawNLine(buf, LASTLINE)
+static void redrawNLine(Buffer *buf, int n);
+static Line *redrawLine(Buffer *buf, Line *l, int i);
+#ifdef USE_IMAGE
+static int image_touch = 0;
+static int draw_image_flag = FALSE;
+static Line *redrawLineImage(Buffer *buf, Line *l, int i);
+#endif
+static int redrawLineRegion(Buffer *buf, Line *l, int i, int bpos, int epos);
+static void do_effects(Lineprop m);
+#ifdef USE_ANSI_COLOR
+static void do_color(Linecolor c);
+#endif
+
+static Str
+make_lastline_link(Buffer *buf, char *title, char *url)
+{
+ Str s = NULL, u;
+#ifdef USE_M17N
+ Lineprop *pr;
+#endif
+ ParsedURL pu;
+ char *p;
+ int l = COLS - 1, i;
+
+ if (title && *title) {
+ s = Strnew_m_charp("[", title, "]", NULL);
+ for (p = s->ptr; *p; p++) {
+ if (IS_CNTRL(*p) || IS_SPACE(*p))
+ *p = ' ';
+ }
+ if (url)
+ Strcat_charp(s, " ");
+ l -= get_Str_strwidth(s);
+ if (l <= 0)
+ return s;
+ }
+ if (!url)
+ return s;
+ parseURL2(url, &pu, baseURL(buf));
+ u = parsedURL2Str(&pu);
+ if (DecodeURL)
+ u = Strnew_charp(url_unquote_conv(u->ptr, buf->document_charset));
+#ifdef USE_M17N
+ u = checkType(u, &pr, NULL);
+#endif
+ if (l <= 4 || l >= get_Str_strwidth(u)) {
+ if (!s)
+ return u;
+ Strcat(s, u);
+ return s;
+ }
+ if (!s)
+ s = Strnew_size(COLS);
+ i = (l - 2) / 2;
+#ifdef USE_M17N
+ while (i && pr[i] & PC_WCHAR2)
+ i--;
+#endif
+ Strcat_charp_n(s, u->ptr, i);
+ Strcat_charp(s, "..");
+ i = get_Str_strwidth(u) - (COLS - 1 - get_Str_strwidth(s));
+#ifdef USE_M17N
+ while (i < u->length && pr[i] & PC_WCHAR2)
+ i++;
+#endif
+ Strcat_charp(s, &u->ptr[i]);
+ return s;
+}
+
+static Str
+make_lastline_message(Buffer *buf)
+{
+ Str msg, s = NULL;
+ int sl = 0;
+
+ if (displayLink) {
+#ifdef USE_IMAGE
+ MapArea *a = retrieveCurrentMapArea(buf);
+ if (a)
+ s = make_lastline_link(buf, a->alt, a->url);
+ else
+#endif
+ {
+ Anchor *a = retrieveCurrentAnchor(buf);
+ char *p = NULL;
+ if (a && a->title && *a->title)
+ p = a->title;
+ else {
+ Anchor *a_img = retrieveCurrentImg(buf);
+ if (a_img && a_img->title && *a_img->title)
+ p = a_img->title;
+ }
+ if (p || a)
+ s = make_lastline_link(buf, p, a ? a->url : NULL);
+ }
+ if (s) {
+ sl = get_Str_strwidth(s);
+ if (sl >= COLS - 3)
+ return s;
+ }
+ }
+
+#ifdef USE_MOUSE
+ if (use_mouse && mouse_action.lastline_str)
+ msg = Strnew_charp(mouse_action.lastline_str);
+ else
+#endif /* not USE_MOUSE */
+ msg = Strnew();
+ if (displayLineInfo && buf->currentLine != NULL && buf->lastLine != NULL) {
+ int cl = buf->currentLine->real_linenumber;
+ int ll = buf->lastLine->real_linenumber;
+ int r = (int)((double)cl * 100.0 / (double)(ll ? ll : 1) + 0.5);
+ Strcat(msg, Sprintf("%d/%d (%d%%)", cl, ll, r));
+ }
+ else
+ /* FIXME: gettextize? */
+ Strcat_charp(msg, "Viewing");
+#ifdef USE_SSL
+ if (buf->ssl_certificate)
+ Strcat_charp(msg, "[SSL]");
+#endif
+ Strcat_charp(msg, " <");
+ Strcat_charp(msg, buf->buffername);
+
+ if (s) {
+ int l = COLS - 3 - sl;
+ if (get_Str_strwidth(msg) > l) {
+#ifdef USE_M17N
+ char *p;
+ for (p = msg->ptr; *p; p += get_mclen(p)) {
+ l -= get_mcwidth(p);
+ if (l < 0)
+ break;
+ }
+ l = p - msg->ptr;
+#endif
+ Strtruncate(msg, l);
+ }
+ Strcat_charp(msg, "> ");
+ Strcat(msg, s);
+ }
+ else {
+ Strcat_charp(msg, ">");
+ }
+ return msg;
+}
+
+void
+displayBuffer(Buffer *buf, int mode)
+{
+ Str msg;
+ int ny = 0;
+
+ if (!buf)
+ return;
+ if (buf->topLine == NULL && readBufferCache(buf) == 0) { /* clear_buffer */
+ mode = B_FORCE_REDRAW;
+ }
+
+ if (buf->width == 0)
+ buf->width = INIT_BUFFER_WIDTH;
+ if (buf->height == 0)
+ buf->height = LASTLINE + 1;
+ if ((buf->width != INIT_BUFFER_WIDTH &&
+ ((buf->type && !strcmp(buf->type, "text/html")) || FoldLine))
+ || 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)
+ / log(10)) + 2;
+ if (buf->rootX < 5)
+ buf->rootX = 5;
+ if (buf->rootX > COLS)
+ buf->rootX = COLS;
+ }
+ else
+ buf->rootX = 0;
+ buf->COLS = COLS - buf->rootX;
+ if (nTab > 1
+#ifdef USE_MOUSE
+ || mouse_action.menu_str
+#endif
+ ) {
+ if (mode == B_FORCE_REDRAW || mode == B_REDRAW_IMAGE)
+ calcTabPos();
+ ny = LastTab->y + 2;
+ if (ny > LASTLINE)
+ ny = LASTLINE;
+ }
+ if (buf->rootY != ny || buf->LINES != LASTLINE - ny) {
+ buf->rootY = ny;
+ buf->LINES = LASTLINE - ny;
+ arrangeCursor(buf);
+ mode = B_REDRAW_IMAGE;
+ }
+ if (mode == B_FORCE_REDRAW || mode == B_SCROLL || mode == B_REDRAW_IMAGE ||
+ cline != buf->topLine || ccolumn != buf->currentColumn) {
+#ifdef USE_RAW_SCROLL
+ 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 < buf->LINES) {
+ move(LASTLINE, 0);
+ clrtoeolx();
+ refresh();
+ scroll(n);
+ }
+ else if (n < 0 && n > -buf->LINES) {
+#if defined(__CYGWIN__) && LANG == JA
+ move(LASTLINE + n + 1, 0);
+ clrtoeolx();
+ refresh();
+#endif /* defined(__CYGWIN__) && LANG == JA */
+ rscroll(-n);
+ }
+ redrawNLine(buf, n);
+ }
+ else
+#endif
+ {
+#ifdef USE_IMAGE
+ if (activeImage &&
+ (mode == B_REDRAW_IMAGE ||
+ cline != buf->topLine || ccolumn != buf->currentColumn)) {
+ if (draw_image_flag)
+ clear();
+ clearImage();
+ loadImage(buf, 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
+
+ drawAnchorCursor(buf);
+
+ msg = make_lastline_message(buf);
+ if (buf->firstLine == NULL) {
+ /* FIXME: gettextize? */
+ Strcat_charp(msg, "\tNo Line");
+ }
+ if (delayed_msg != NULL) {
+ disp_message(delayed_msg, FALSE);
+ delayed_msg = NULL;
+ refresh();
+ }
+ standout();
+ message(msg->ptr, buf->cursorX + buf->rootX, buf->cursorY + buf->rootY);
+ standend();
+ term_title(conv_to_system(buf->buffername));
+ refresh();
+#ifdef USE_IMAGE
+ if (activeImage && displayImage && buf->img) {
+ drawImage();
+ }
+#endif
+#ifdef USE_BUFINFO
+ if (buf != save_current_buf) {
+ saveBufferInfo();
+ save_current_buf = buf;
+ }
+#endif
+}
+
+static void
+drawAnchorCursor0(Buffer *buf, AnchorList *al, int hseq, int prevhseq,
+ int tline, int eline, int active)
+{
+ int i, j;
+ Line *l;
+ Anchor *an;
+
+ l = buf->topLine;
+ for (j = 0; j < al->nanchor; j++) {
+ an = &al->anchors[j];
+ if (an->start.line < tline)
+ continue;
+ if (an->start.line >= eline)
+ return;
+ for (;; l = l->next) {
+ if (l == NULL)
+ return;
+ if (l->linenumber == an->start.line)
+ break;
+ }
+ if (hseq >= 0 && an->hseq == hseq) {
+ for (i = an->start.pos; i < an->end.pos; i++) {
+ if (l->propBuf[i] & (PE_IMAGE | PE_ANCHOR | PE_FORM)) {
+ if (active)
+ l->propBuf[i] |= PE_ACTIVE;
+ else
+ l->propBuf[i] &= ~PE_ACTIVE;
+ }
+ }
+ if (active)
+ redrawLineRegion(buf, l, l->linenumber - tline + buf->rootY,
+ an->start.pos, an->end.pos);
+ }
+ else if (prevhseq >= 0 && an->hseq == prevhseq) {
+ if (active)
+ redrawLineRegion(buf, l, l->linenumber - tline + buf->rootY,
+ an->start.pos, an->end.pos);
+ }
+ }
+}
+
+static void
+drawAnchorCursor(Buffer *buf)
+{
+ Anchor *an;
+ int hseq, prevhseq;
+ int tline, eline;
+
+ if (!buf->firstLine || !buf->hmarklist)
+ return;
+ if (!buf->href && !buf->formitem)
+ return;
+
+ an = retrieveCurrentAnchor(buf);
+ if (!an)
+ an = retrieveCurrentMap(buf);
+ if (an)
+ hseq = an->hseq;
+ else
+ hseq = -1;
+ tline = buf->topLine->linenumber;
+ eline = tline + buf->LINES;
+ prevhseq = buf->hmarklist->prevhseq;
+
+ if (buf->href) {
+ drawAnchorCursor0(buf, buf->href, hseq, prevhseq, tline, eline, 1);
+ drawAnchorCursor0(buf, buf->href, hseq, -1, tline, eline, 0);
+ }
+ if (buf->formitem) {
+ drawAnchorCursor0(buf, buf->formitem, hseq, prevhseq, tline, eline, 1);
+ drawAnchorCursor0(buf, buf->formitem, hseq, -1, tline, eline, 0);
+ }
+ buf->hmarklist->prevhseq = hseq;
+}
+
+static void
+redrawNLine(Buffer *buf, int n)
+{
+ Line *l;
+ int i;
+
+#ifdef USE_COLOR
+ if (useColor) {
+ EFFECT_ANCHOR_END_C;
+#ifdef USE_BG_COLOR
+ setbcolor(bg_color);
+#endif /* USE_BG_COLOR */
+ }
+#endif /* USE_COLOR */
+ if (nTab > 1
+#ifdef USE_MOUSE
+ || mouse_action.menu_str
+#endif
+ ) {
+ TabBuffer *t;
+ int l;
+
+ move(0, 0);
+#ifdef USE_MOUSE
+ if (mouse_action.menu_str)
+ addstr(mouse_action.menu_str);
+#endif
+ clrtoeolx();
+ for (t = FirstTab; t; t = t->nextTab) {
+ move(t->y, t->x1);
+ if (t == CurrentTab)
+ bold();
+ addch('[');
+ l = t->x2 - t->x1 - 1 - get_strwidth(t->currentBuffer->buffername);
+ if (l < 0)
+ l = 0;
+ if (l / 2 > 0)
+ addnstr_sup(" ", l / 2);
+ if (t == CurrentTab)
+ EFFECT_ACTIVE_START;
+ addnstr(t->currentBuffer->buffername, t->x2 - t->x1 - l);
+ if (t == CurrentTab)
+ EFFECT_ACTIVE_END;
+ if ((l + 1) / 2 > 0)
+ addnstr_sup(" ", (l + 1) / 2);
+ move(t->y, t->x2);
+ addch(']');
+ if (t == CurrentTab)
+ boldend();
+ }
+#if 0
+ move(0, COLS - 2);
+ addstr(" x");
+#endif
+ move(LastTab->y + 1, 0);
+ for (i = 0; i < COLS; i++)
+ addch('~');
+ }
+ for (i = 0, l = buf->topLine; i < buf->LINES; i++, l = l->next) {
+ if (i >= buf->LINES - n || i < -n)
+ l = redrawLine(buf, l, i + buf->rootY);
+ if (l == NULL)
+ break;
+ }
+ if (n > 0) {
+ move(i + buf->rootY, 0);
+ clrtobotx();
+ }
+
+#ifdef USE_IMAGE
+ if (!(activeImage && displayImage && buf->img))
+ return;
+ move(buf->cursorY + buf->rootY, buf->cursorX + buf->rootX);
+ for (i = 0, l = buf->topLine; i < buf->LINES && l; i++, l = l->next) {
+ if (i >= buf->LINES - n || i < -n)
+ redrawLineImage(buf, l, i + buf->rootY);
+ }
+ getAllImage(buf);
+#endif
+}
+
+static Line *
+redrawLine(Buffer *buf, Line *l, int i)
+{
+ int j, pos, rcol, ncol, delta = 1;
+ int column = buf->currentColumn;
+ char *p;
+ Lineprop *pr;
+#ifdef USE_ANSI_COLOR
+ Linecolor *pc;
+#endif
+#ifdef USE_COLOR
+ Anchor *a;
+ ParsedURL url;
+ int k, vpos = -1;
+#endif
+
+ if (l == NULL) {
+ if (buf->pagerSource) {
+ l = getNextPage(buf, buf->LINES + buf->rootY - i);
+ if (l == NULL)
+ return NULL;
+ }
+ else
+ return NULL;
+ }
+ move(i, 0);
+ if (showLineNum) {
+ char tmp[16];
+ if (!buf->rootX) {
+ if (buf->lastLine->real_linenumber > 0)
+ buf->rootX = (int)(log(buf->lastLine->real_linenumber + 0.1)
+ / log(10)) + 2;
+ if (buf->rootX < 5)
+ buf->rootX = 5;
+ if (buf->rootX > COLS)
+ buf->rootX = COLS;
+ buf->COLS = COLS - buf->rootX;
+ }
+ if (l->real_linenumber && !l->bpos)
+ sprintf(tmp, "%*ld:", buf->rootX - 1, l->real_linenumber);
+ else
+ sprintf(tmp, "%*s ", buf->rootX - 1, "");
+ addstr(tmp);
+ }
+ move(i, buf->rootX);
+ if (l->width < 0)
+ l->width = COLPOS(l, l->len);
+ if (l->len == 0 || l->width - 1 < column) {
+ clrtoeolx();
+ return l;
+ }
+ /* need_clrtoeol(); */
+ pos = columnPos(l, column);
+ p = &(l->lineBuf[pos]);
+ pr = &(l->propBuf[pos]);
+#ifdef USE_ANSI_COLOR
+ if (useColor && l->colorBuf)
+ pc = &(l->colorBuf[pos]);
+ else
+ pc = NULL;
+#endif
+ rcol = COLPOS(l, pos);
+
+ for (j = 0; rcol - column < buf->COLS && pos + j < l->len; j += delta) {
+#ifdef USE_COLOR
+ if (useVisitedColor && vpos <= pos + j && !(pr[j] & PE_VISITED)) {
+ a = retrieveAnchor(buf->href, l->linenumber, pos + j);
+ if (a) {
+ parseURL2(a->url, &url, baseURL(buf));
+ if (getHashHist(URLHist, parsedURL2Str(&url)->ptr)) {
+ for (k = a->start.pos; k < a->end.pos; k++)
+ pr[k - pos] |= PE_VISITED;
+ }
+ vpos = a->end.pos;
+ }
+ }
+#endif
+#ifdef USE_M17N
+ delta = wtf_len((wc_uchar *) & p[j]);
+#endif
+ ncol = COLPOS(l, pos + j + delta);
+ if (ncol - column > buf->COLS)
+ break;
+#ifdef USE_ANSI_COLOR
+ if (pc)
+ do_color(pc[j]);
+#endif
+ if (rcol < column) {
+ for (rcol = column; rcol < ncol; rcol++)
+ addChar(' ', 0);
+ continue;
+ }
+ if (p[j] == '\t') {
+ for (; rcol < ncol; rcol++)
+ addChar(' ', 0);
+ }
+ else {
+#ifdef USE_M17N
+ addMChar(&p[j], pr[j], delta);
+#else
+ addChar(p[j], pr[j]);
+#endif
+ }
+ rcol = ncol;
+ }
+ if (somode) {
+ somode = FALSE;
+ standend();
+ }
+ if (ulmode) {
+ ulmode = FALSE;
+ underlineend();
+ }
+ if (bomode) {
+ bomode = FALSE;
+ boldend();
+ }
+ if (emph_mode) {
+ emph_mode = FALSE;
+ boldend();
+ }
+
+ if (anch_mode) {
+ anch_mode = FALSE;
+ EFFECT_ANCHOR_END;
+ }
+ if (imag_mode) {
+ imag_mode = FALSE;
+ EFFECT_IMAGE_END;
+ }
+ if (form_mode) {
+ form_mode = FALSE;
+ EFFECT_FORM_END;
+ }
+ if (visited_mode) {
+ visited_mode = FALSE;
+ EFFECT_VISITED_END;
+ }
+ if (active_mode) {
+ active_mode = FALSE;
+ EFFECT_ACTIVE_END;
+ }
+ if (mark_mode) {
+ mark_mode = FALSE;
+ EFFECT_MARK_END;
+ }
+ if (graph_mode) {
+ graph_mode = FALSE;
+ graphend();
+ }
+#ifdef USE_ANSI_COLOR
+ if (color_mode)
+ do_color(0);
+#endif
+ if (rcol - column < buf->COLS)
+ clrtoeolx();
+ return l;
+}
+
+#ifdef USE_IMAGE
+static Line *
+redrawLineImage(Buffer *buf, Line *l, int i)
+{
+ int j, pos, rcol;
+ 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;
+ 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->rootX + buf->COLS) * pixel_per_char - x))
+ w = (int)((buf->rootX + buf->COLS) * pixel_per_char - x);
+ 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;
+}
+#endif
+
+static int
+redrawLineRegion(Buffer *buf, Line *l, int i, int bpos, int epos)
+{
+ int j, pos, rcol, ncol, delta = 1;
+ int column = buf->currentColumn;
+ char *p;
+ Lineprop *pr;
+#ifdef USE_ANSI_COLOR
+ Linecolor *pc;
+#endif
+ int bcol, ecol;
+#ifdef USE_COLOR
+ Anchor *a;
+ ParsedURL url;
+ int k, vpos = -1;
+#endif
+
+ if (l == NULL)
+ return 0;
+ pos = columnPos(l, column);
+ p = &(l->lineBuf[pos]);
+ pr = &(l->propBuf[pos]);
+#ifdef USE_ANSI_COLOR
+ if (useColor && l->colorBuf)
+ pc = &(l->colorBuf[pos]);
+ else
+ pc = NULL;
+#endif
+ rcol = COLPOS(l, pos);
+ bcol = bpos - pos;
+ ecol = epos - pos;
+
+ for (j = 0; rcol - column < buf->COLS && pos + j < l->len; j += delta) {
+#ifdef USE_COLOR
+ if (useVisitedColor && vpos <= pos + j && !(pr[j] & PE_VISITED)) {
+ a = retrieveAnchor(buf->href, l->linenumber, pos + j);
+ if (a) {
+ parseURL2(a->url, &url, baseURL(buf));
+ if (getHashHist(URLHist, parsedURL2Str(&url)->ptr)) {
+ for (k = a->start.pos; k < a->end.pos; k++)
+ pr[k - pos] |= PE_VISITED;
+ }
+ vpos = a->end.pos;
+ }
+ }
+#endif
+#ifdef USE_M17N
+ delta = wtf_len((wc_uchar *) & p[j]);
+#endif
+ ncol = COLPOS(l, pos + j + delta);
+ if (ncol - column > buf->COLS)
+ break;
+#ifdef USE_ANSI_COLOR
+ if (pc)
+ do_color(pc[j]);
+#endif
+ if (j >= bcol && j < ecol) {
+ if (rcol < column) {
+ move(i, buf->rootX);
+ for (rcol = column; rcol < ncol; rcol++)
+ addChar(' ', 0);
+ continue;
+ }
+ move(i, rcol - column + buf->rootX);
+ if (p[j] == '\t') {
+ for (; rcol < ncol; rcol++)
+ addChar(' ', 0);
+ }
+ else
+#ifdef USE_M17N
+ addMChar(&p[j], pr[j], delta);
+#else
+ addChar(p[j], pr[j]);
+#endif
+ }
+ rcol = ncol;
+ }
+ if (somode) {
+ somode = FALSE;
+ standend();
+ }
+ if (ulmode) {
+ ulmode = FALSE;
+ underlineend();
+ }
+ if (bomode) {
+ bomode = FALSE;
+ boldend();
+ }
+ if (emph_mode) {
+ emph_mode = FALSE;
+ boldend();
+ }
+
+ if (anch_mode) {
+ anch_mode = FALSE;
+ EFFECT_ANCHOR_END;
+ }
+ if (imag_mode) {
+ imag_mode = FALSE;
+ EFFECT_IMAGE_END;
+ }
+ if (form_mode) {
+ form_mode = FALSE;
+ EFFECT_FORM_END;
+ }
+ if (visited_mode) {
+ visited_mode = FALSE;
+ EFFECT_VISITED_END;
+ }
+ if (active_mode) {
+ active_mode = FALSE;
+ EFFECT_ACTIVE_END;
+ }
+ if (mark_mode) {
+ mark_mode = FALSE;
+ EFFECT_MARK_END;
+ }
+ if (graph_mode) {
+ graph_mode = FALSE;
+ graphend();
+ }
+#ifdef USE_ANSI_COLOR
+ if (color_mode)
+ do_color(0);
+#endif
+ return rcol - column;
+}
+
+#define do_effect1(effect,modeflag,action_start,action_end) \
+if (m & effect) { \
+ if (!modeflag) { \
+ action_start; \
+ modeflag = TRUE; \
+ } \
+}
+
+#define do_effect2(effect,modeflag,action_start,action_end) \
+if (modeflag) { \
+ action_end; \
+ modeflag = FALSE; \
+}
+
+static void
+do_effects(Lineprop m)
+{
+ /* effect end */
+ do_effect2(PE_UNDER, ulmode, underline(), underlineend());
+ do_effect2(PE_STAND, somode, standout(), standend());
+ do_effect2(PE_BOLD, bomode, bold(), boldend());
+ do_effect2(PE_EMPH, emph_mode, bold(), boldend());
+ do_effect2(PE_ANCHOR, anch_mode, EFFECT_ANCHOR_START, EFFECT_ANCHOR_END);
+ do_effect2(PE_IMAGE, imag_mode, EFFECT_IMAGE_START, EFFECT_IMAGE_END);
+ do_effect2(PE_FORM, form_mode, EFFECT_FORM_START, EFFECT_FORM_END);
+ do_effect2(PE_VISITED, visited_mode, EFFECT_VISITED_START,
+ EFFECT_VISITED_END);
+ do_effect2(PE_ACTIVE, active_mode, EFFECT_ACTIVE_START, EFFECT_ACTIVE_END);
+ do_effect2(PE_MARK, mark_mode, EFFECT_MARK_START, EFFECT_MARK_END);
+ if (graph_mode) {
+ graphend();
+ graph_mode = FALSE;
+ }
+
+ /* effect start */
+ do_effect1(PE_UNDER, ulmode, underline(), underlineend());
+ do_effect1(PE_STAND, somode, standout(), standend());
+ do_effect1(PE_BOLD, bomode, bold(), boldend());
+ do_effect1(PE_EMPH, emph_mode, bold(), boldend());
+ do_effect1(PE_ANCHOR, anch_mode, EFFECT_ANCHOR_START, EFFECT_ANCHOR_END);
+ do_effect1(PE_IMAGE, imag_mode, EFFECT_IMAGE_START, EFFECT_IMAGE_END);
+ do_effect1(PE_FORM, form_mode, EFFECT_FORM_START, EFFECT_FORM_END);
+ do_effect1(PE_VISITED, visited_mode, EFFECT_VISITED_START,
+ EFFECT_VISITED_END);
+ do_effect1(PE_ACTIVE, active_mode, EFFECT_ACTIVE_START, EFFECT_ACTIVE_END);
+ do_effect1(PE_MARK, mark_mode, EFFECT_MARK_START, EFFECT_MARK_END);
+}
+
+#ifdef USE_ANSI_COLOR
+static void
+do_color(Linecolor c)
+{
+ if (c & 0x8)
+ setfcolor(c & 0x7);
+ else if (color_mode & 0x8)
+ setfcolor(basic_color);
+#ifdef USE_BG_COLOR
+ if (c & 0x80)
+ setbcolor((c >> 4) & 0x7);
+ else if (color_mode & 0x80)
+ setbcolor(bg_color);
+#endif
+ color_mode = c;
+}
+#endif
+
+#ifdef USE_M17N
+void
+addChar(char c, Lineprop mode)
+{
+ addMChar(&c, mode, 1);
+}
+
+void
+addMChar(char *p, Lineprop mode, size_t len)
+#else
+void
+addChar(char c, Lineprop mode)
+#endif
+{
+ Lineprop m = CharEffect(mode);
+#ifdef USE_M17N
+ char c = *p;
+
+ if (mode & PC_WCHAR2)
+ return;
+#endif
+ do_effects(m);
+ if (mode & PC_SYMBOL) {
+ char **symbol;
+#ifdef USE_M17N
+ int w = (mode & PC_KANJI) ? 2 : 1;
+
+ c = ((char)wtf_get_code((wc_uchar *) p) & 0x7f) - SYMBOL_BASE;
+#else
+ c -= SYMBOL_BASE;
+#endif
+ if (graph_ok() && c < N_GRAPH_SYMBOL) {
+ if (!graph_mode) {
+ graphstart();
+ graph_mode = TRUE;
+ }
+#ifdef USE_M17N
+ if (w == 2 && WcOption.use_wide)
+ addstr(graph2_symbol[(int)c]);
+ else
+#endif
+ addch(*graph_symbol[(int)c]);
+ }
+ else {
+#ifdef USE_M17N
+ symbol = get_symbol(DisplayCharset, &w);
+ addstr(symbol[(int)c]);
+#else
+ symbol = get_symbol();
+ addch(*symbol[(int)c]);
+#endif
+ }
+ }
+ else if (mode & PC_CTRL) {
+ switch (c) {
+ case '\t':
+ addch(c);
+ break;
+ case '\n':
+ addch(' ');
+ break;
+ case '\r':
+ break;
+ case DEL_CODE:
+ addstr("^?");
+ break;
+ default:
+ addch('^');
+ addch(c + '@');
+ break;
+ }
+ }
+#ifdef USE_M17N
+ else if (mode & PC_UNKNOWN) {
+ char buf[5];
+ sprintf(buf, "[%.2X]",
+ (unsigned char)wtf_get_code((wc_uchar *) p) | 0x80);
+ addstr(buf);
+ }
+ else
+ addmch(p, len);
+#else
+ else if (0x80 <= (unsigned char)c && (unsigned char)c <= NBSP_CODE)
+ addch(' ');
+ else
+ addch(c);
+#endif
+}
+
+static GeneralList *message_list = NULL;
+
+void
+record_err_message(char *s)
+{
+ if (fmInitialized) {
+ if (!message_list)
+ message_list = newGeneralList();
+ if (message_list->nitem >= LINES)
+ popValue(message_list);
+ pushValue(message_list, allocStr(s, -1));
+ }
+}
+
+/*
+ * List of error messages
+ */
+Buffer *
+message_list_panel(void)
+{
+ Str tmp = Strnew_size(LINES * COLS);
+ ListItem *p;
+
+ /* FIXME: gettextize? */
+ Strcat_charp(tmp,
+ "<html><head><title>List of error messages</title></head><body>"
+ "<h1>List of error messages</h1><table cellpadding=0>\n");
+ if (message_list)
+ for (p = message_list->last; p; p = p->prev)
+ Strcat_m_charp(tmp, "<tr><td><pre>", html_quote(p->ptr),
+ "</pre></td></tr>\n", NULL);
+ else
+ Strcat_charp(tmp, "<tr><td>(no message recorded)</td></tr>\n");
+ Strcat_charp(tmp, "</table></body></html>");
+ return loadHTMLString(tmp);
+}
+
+void
+message(char *s, int return_x, int return_y)
+{
+ if (!fmInitialized)
+ return;
+ move(LASTLINE, 0);
+ addnstr(s, COLS - 1);
+ clrtoeolx();
+ move(return_y, return_x);
+}
+
+void
+disp_err_message(char *s, int redraw_current)
+{
+ record_err_message(s);
+ disp_message(s, redraw_current);
+}
+
+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;
+ }
+ if (CurrentTab != NULL && Currentbuf != NULL)
+ message(s, Currentbuf->cursorX + Currentbuf->rootX,
+ Currentbuf->cursorY + Currentbuf->rootY);
+ else
+ message(s, LASTLINE, 0);
+ refresh();
+#ifdef USE_MOUSE
+ if (mouse && use_mouse)
+ mouse_active();
+#endif
+ sleep_till_anykey(sec, purge);
+#ifdef USE_MOUSE
+ if (mouse && use_mouse)
+ mouse_inactive();
+#endif
+ if (CurrentTab != NULL && Currentbuf != NULL && redraw_current)
+ displayBuffer(Currentbuf, B_NORMAL);
+}
+
+void
+disp_message(char *s, int redraw_current)
+{
+ disp_message_nsec(s, redraw_current, 10, FALSE, TRUE);
+}
+#ifdef USE_MOUSE
+void
+disp_message_nomouse(char *s, int redraw_current)
+{
+ disp_message_nsec(s, redraw_current, 10, FALSE, FALSE);
+}
+#endif
+
+void
+set_delayed_message(char *s)
+{
+ delayed_msg = allocStr(s, -1);
+}
+
+void
+cursorUp0(Buffer *buf, int n)
+{
+ if (buf->cursorY > 0)
+ cursorUpDown(buf, -1);
+ else {
+ buf->topLine = lineSkip(buf, buf->topLine, -n, FALSE);
+ if (buf->currentLine->prev != NULL)
+ buf->currentLine = buf->currentLine->prev;
+ arrangeLine(buf);
+ }
+}
+
+void
+cursorUp(Buffer *buf, int n)
+{
+ Line *l = buf->currentLine;
+ if (buf->firstLine == NULL)
+ return;
+ while (buf->currentLine->prev && buf->currentLine->bpos)
+ cursorUp0(buf, n);
+ if (buf->currentLine == buf->firstLine) {
+ gotoLine(buf, l->linenumber);
+ arrangeLine(buf);
+ return;
+ }
+ cursorUp0(buf, n);
+ while (buf->currentLine->prev && buf->currentLine->bpos &&
+ buf->currentLine->bwidth >= buf->currentColumn + buf->visualpos)
+ cursorUp0(buf, n);
+}
+
+void
+cursorDown0(Buffer *buf, int n)
+{
+ if (buf->cursorY < buf->LINES - 1)
+ cursorUpDown(buf, 1);
+ else {
+ buf->topLine = lineSkip(buf, buf->topLine, n, FALSE);
+ if (buf->currentLine->next != NULL)
+ buf->currentLine = buf->currentLine->next;
+ arrangeLine(buf);
+ }
+}
+
+void
+cursorDown(Buffer *buf, int n)
+{
+ Line *l = buf->currentLine;
+ if (buf->firstLine == NULL)
+ return;
+ while (buf->currentLine->next && buf->currentLine->next->bpos)
+ cursorDown0(buf, n);
+ if (buf->currentLine == buf->lastLine) {
+ gotoLine(buf, l->linenumber);
+ arrangeLine(buf);
+ return;
+ }
+ cursorDown0(buf, n);
+ while (buf->currentLine->next && buf->currentLine->next->bpos &&
+ buf->currentLine->bwidth + buf->currentLine->width <
+ buf->currentColumn + buf->visualpos)
+ cursorDown0(buf, n);
+}
+
+void
+cursorUpDown(Buffer *buf, int n)
+{
+ Line *cl = buf->currentLine;
+
+ if (buf->firstLine == NULL)
+ return;
+ if ((buf->currentLine = currentLineSkip(buf, cl, n, FALSE)) == cl)
+ return;
+ arrangeLine(buf);
+}
+
+void
+cursorRight(Buffer *buf, int n)
+{
+ int i, delta = 1, cpos, vpos2;
+ Line *l = buf->currentLine;
+ Lineprop *p;
+
+ if (buf->firstLine == NULL)
+ return;
+ if (buf->pos == l->len && !(l->next && l->next->bpos))
+ return;
+ i = buf->pos;
+ p = l->propBuf;
+#ifdef USE_M17N
+ while (i + delta < l->len && p[i + delta] & PC_WCHAR2)
+ delta++;
+#endif
+ if (i + delta < l->len) {
+ buf->pos = i + delta;
+ }
+ else if (l->len == 0) {
+ buf->pos = 0;
+ }
+ else if (l->next && l->next->bpos) {
+ cursorDown0(buf, 1);
+ buf->pos = 0;
+ arrangeCursor(buf);
+ return;
+ }
+ else {
+ buf->pos = l->len - 1;
+#ifdef USE_M17N
+ while (buf->pos && p[buf->pos] & PC_WCHAR2)
+ buf->pos--;
+#endif
+ }
+ cpos = COLPOS(l, buf->pos);
+ buf->visualpos = l->bwidth + cpos - buf->currentColumn;
+ delta = 1;
+#ifdef USE_M17N
+ while (buf->pos + delta < l->len && p[buf->pos + delta] & PC_WCHAR2)
+ delta++;
+#endif
+ vpos2 = COLPOS(l, buf->pos + delta) - buf->currentColumn - 1;
+ if (vpos2 >= buf->COLS && n) {
+ columnSkip(buf, n + (vpos2 - buf->COLS) - (vpos2 - buf->COLS) % n);
+ buf->visualpos = l->bwidth + cpos - buf->currentColumn;
+ }
+ buf->cursorX = buf->visualpos - l->bwidth;
+}
+
+void
+cursorLeft(Buffer *buf, int n)
+{
+ int i, delta = 1, cpos;
+ Line *l = buf->currentLine;
+ Lineprop *p;
+
+ if (buf->firstLine == NULL)
+ return;
+ i = buf->pos;
+ p = l->propBuf;
+#ifdef USE_M17N
+ while (i - delta > 0 && p[i - delta] & PC_WCHAR2)
+ delta++;
+#endif
+ if (i >= delta)
+ buf->pos = i - delta;
+ else if (l->prev && l->bpos) {
+ cursorUp0(buf, -1);
+ buf->pos = buf->currentLine->len - 1;
+ arrangeCursor(buf);
+ return;
+ }
+ else
+ buf->pos = 0;
+ cpos = COLPOS(l, buf->pos);
+ buf->visualpos = l->bwidth + cpos - buf->currentColumn;
+ if (buf->visualpos - l->bwidth < 0 && n) {
+ columnSkip(buf,
+ -n + buf->visualpos - l->bwidth - (buf->visualpos -
+ l->bwidth) % n);
+ buf->visualpos = l->bwidth + cpos - buf->currentColumn;
+ }
+ buf->cursorX = buf->visualpos - l->bwidth;
+}
+
+void
+cursorHome(Buffer *buf)
+{
+ buf->visualpos = 0;
+ buf->cursorX = buf->cursorY = 0;
+}
+
+
+/*
+ * Arrange line,column and cursor position according to current line and
+ * current position.
+ */
+void
+arrangeCursor(Buffer *buf)
+{
+ int col, col2, pos;
+ int delta = 1;
+ if (buf == NULL || buf->currentLine == NULL)
+ return;
+ /* Arrange line */
+ if (buf->currentLine->linenumber - buf->topLine->linenumber >= buf->LINES
+ || buf->currentLine->linenumber < buf->topLine->linenumber) {
+ /*
+ * buf->topLine = buf->currentLine;
+ */
+ buf->topLine = lineSkip(buf, buf->currentLine, 0, FALSE);
+ }
+ /* Arrange column */
+ while (buf->pos < 0 && buf->currentLine->prev && buf->currentLine->bpos) {
+ pos = buf->pos + buf->currentLine->prev->len;
+ cursorUp0(buf, 1);
+ buf->pos = pos;
+ }
+ while (buf->pos >= buf->currentLine->len && buf->currentLine->next &&
+ buf->currentLine->next->bpos) {
+ pos = buf->pos - buf->currentLine->len;
+ cursorDown0(buf, 1);
+ buf->pos = pos;
+ }
+ if (buf->currentLine->len == 0 || buf->pos < 0)
+ buf->pos = 0;
+ else if (buf->pos >= buf->currentLine->len)
+ buf->pos = buf->currentLine->len - 1;
+#ifdef USE_M17N
+ while (buf->pos > 0 && buf->currentLine->propBuf[buf->pos] & PC_WCHAR2)
+ buf->pos--;
+#endif
+ col = COLPOS(buf->currentLine, buf->pos);
+#ifdef USE_M17N
+ while (buf->pos + delta < buf->currentLine->len &&
+ buf->currentLine->propBuf[buf->pos + delta] & PC_WCHAR2)
+ delta++;
+#endif
+ col2 = COLPOS(buf->currentLine, buf->pos + delta);
+ if (col < buf->currentColumn || col2 > buf->COLS + buf->currentColumn) {
+ buf->currentColumn = 0;
+ if (col2 > buf->COLS)
+ columnSkip(buf, col);
+ }
+ /* Arrange cursor */
+ buf->cursorY = buf->currentLine->linenumber - buf->topLine->linenumber;
+ buf->visualpos = buf->currentLine->bwidth +
+ COLPOS(buf->currentLine, buf->pos) - buf->currentColumn;
+ buf->cursorX = buf->visualpos - buf->currentLine->bwidth;
+#ifdef DISPLAY_DEBUG
+ fprintf(stderr,
+ "arrangeCursor: column=%d, cursorX=%d, visualpos=%d, pos=%d, len=%d\n",
+ buf->currentColumn, buf->cursorX, buf->visualpos, buf->pos,
+ buf->currentLine->len);
+#endif
+}
+
+void
+arrangeLine(Buffer *buf)
+{
+ int i, cpos;
+
+ if (buf->firstLine == NULL)
+ return;
+ buf->cursorY = buf->currentLine->linenumber - buf->topLine->linenumber;
+ i = columnPos(buf->currentLine, buf->currentColumn + buf->visualpos
+ - buf->currentLine->bwidth);
+ cpos = COLPOS(buf->currentLine, i) - buf->currentColumn;
+ if (cpos >= 0) {
+ buf->cursorX = cpos;
+ buf->pos = i;
+ }
+ else if (buf->currentLine->len > i) {
+ buf->cursorX = 0;
+ buf->pos = i + 1;
+ }
+ else {
+ buf->cursorX = 0;
+ buf->pos = 0;
+ }
+#ifdef DISPLAY_DEBUG
+ fprintf(stderr,
+ "arrangeLine: column=%d, cursorX=%d, visualpos=%d, pos=%d, len=%d\n",
+ buf->currentColumn, buf->cursorX, buf->visualpos, buf->pos,
+ buf->currentLine->len);
+#endif
+}
+
+void
+cursorXY(Buffer *buf, int x, int y)
+{
+ int oldX;
+
+ cursorUpDown(buf, y - buf->cursorY);
+
+ if (buf->cursorX > x) {
+ while (buf->cursorX > x)
+ cursorLeft(buf, buf->COLS / 2);
+ }
+ else if (buf->cursorX < x) {
+ while (buf->cursorX < x) {
+ oldX = buf->cursorX;
+
+ cursorRight(buf, buf->COLS / 2);
+
+ if (oldX == buf->cursorX)
+ break;
+ }
+ if (buf->cursorX > x)
+ cursorLeft(buf, buf->COLS / 2);
+ }
+}
+
+void
+restorePosition(Buffer *buf, Buffer *orig)
+{
+ buf->topLine = lineSkip(buf, buf->firstLine, TOP_LINENUMBER(orig) - 1,
+ FALSE);
+ gotoLine(buf, CUR_LINENUMBER(orig));
+ buf->pos = orig->pos;
+ if (buf->currentLine && orig->currentLine)
+ buf->pos += orig->currentLine->bpos - buf->currentLine->bpos;
+ buf->currentColumn = orig->currentColumn;
+ arrangeCursor(buf);
+}
+
+/* Local Variables: */
+/* c-basic-offset: 4 */
+/* tab-width: 8 */
+/* End: */