1 /* $Id: buffer.c,v 1.29 2003/09/26 17:59:51 ukai Exp $ */
8 #if defined(USE_GPM) || defined(USE_SYSMOUSE)
10 #define getch() do_getch()
12 #endif /* USE_MOUSE */
15 #include <sys/kbdscan.h>
19 Lineprop NullProp[] = { 0 };
32 bzero((void *)n, sizeof(Buffer));
36 n->currentURL.scheme = SCM_UNKNOWN;
40 n->bufferprop = BP_NORMAL;
45 n->ssl_certificate = NULL;
48 n->auto_detect = WcOption.auto_detect;
62 b->buffername = "*Null*";
67 * clearBuffer: clear buffer content
70 clearBuffer(Buffer *buf)
72 buf->firstLine = buf->topLine = buf->currentLine = buf->lastLine = NULL;
77 * discardBuffer: free buffer structure
81 discardBuffer(Buffer *buf)
90 for (i = 0; i < MAX_LB; i++) {
91 b = buf->linkBuffer[i];
94 b->linkBuffer[REV_LB[i]] = NULL;
97 unlink(buf->savecache);
100 if (buf->pagerSource)
101 ISclose(buf->pagerSource);
102 if (buf->sourcefile &&
103 (!buf->real_type || strncasecmp(buf->real_type, "image/", 6))) {
104 if (buf->real_scheme != SCM_LOCAL || buf->bufferprop & BP_FRAME)
105 unlink(buf->sourcefile);
107 if (buf->header_source)
108 unlink(buf->header_source);
109 if (buf->mailcap_source)
110 unlink(buf->mailcap_source);
111 while (buf->frameset) {
112 deleteFrameSet(buf->frameset);
113 buf->frameset = popFrameTree(&(buf->frameQ));
118 * namedBuffer: Select buffer which have specified name
121 namedBuffer(Buffer *first, char *name)
125 if (!strcmp(first->buffername, name)) {
128 for (buf = first; buf->nextBuffer != NULL; buf = buf->nextBuffer) {
129 if (!strcmp(buf->nextBuffer->buffername, name)) {
130 return buf->nextBuffer;
137 * deleteBuffer: delete buffer
140 deleteBuffer(Buffer *first, Buffer *delbuf)
144 if (first == delbuf && first->nextBuffer != NULL) {
145 buf = first->nextBuffer;
146 discardBuffer(first);
149 if ((buf = prevBuffer(first, delbuf)) != NULL) {
151 buf->nextBuffer = b->nextBuffer;
158 * replaceBuffer: replace buffer
161 replaceBuffer(Buffer *first, Buffer *delbuf, Buffer *newbuf)
165 if (delbuf == NULL) {
166 newbuf->nextBuffer = first;
169 if (first == delbuf) {
170 newbuf->nextBuffer = delbuf->nextBuffer;
171 discardBuffer(delbuf);
174 if (delbuf && (buf = prevBuffer(first, delbuf))) {
175 buf->nextBuffer = newbuf;
176 newbuf->nextBuffer = delbuf->nextBuffer;
177 discardBuffer(delbuf);
180 newbuf->nextBuffer = first;
185 nthBuffer(Buffer *firstbuf, int n)
188 Buffer *buf = firstbuf;
192 for (i = 0; i < n; i++) {
195 buf = buf->nextBuffer;
201 writeBufferName(Buffer *buf, int n)
207 if (all == 0 && buf->lastLine != NULL)
208 all = buf->lastLine->linenumber;
210 /* FIXME: gettextize? */
211 msg = Sprintf("<%s> [%d lines]", buf->buffername, all);
212 if (buf->filename != NULL) {
213 switch (buf->currentURL.scheme) {
216 if (strcmp(buf->currentURL.file, "-")) {
217 Strcat_char(msg, ' ');
218 Strcat_charp(msg, conv_from_system(buf->currentURL.real_file));
225 Strcat_char(msg, ' ');
226 Strcat(msg, parsedURL2Str(&buf->currentURL));
230 addnstr_sup(msg->ptr, COLS - 1);
235 * gotoLine: go to line number
238 gotoLine(Buffer *buf, int n)
241 Line *l = buf->firstLine;
245 if (buf->pagerSource && !(buf->bufferprop & BP_CLOSE)) {
246 if (buf->lastLine->linenumber < n)
247 getNextPage(buf, n - buf->lastLine->linenumber);
248 while ((buf->lastLine->linenumber < n) &&
249 (getNextPage(buf, 1) != NULL)) ;
251 if (l->linenumber > n) {
252 /* FIXME: gettextize? */
253 sprintf(msg, "First line is #%ld", l->linenumber);
254 set_delayed_message(msg);
255 buf->topLine = buf->currentLine = l;
258 if (buf->lastLine->linenumber < n) {
260 /* FIXME: gettextize? */
261 sprintf(msg, "Last line is #%ld", buf->lastLine->linenumber);
262 set_delayed_message(msg);
263 buf->currentLine = l;
264 buf->topLine = lineSkip(buf, buf->currentLine, -(buf->LINES - 1),
268 for (; l != NULL; l = l->next) {
269 if (l->linenumber >= n) {
270 buf->currentLine = l;
271 if (n < buf->topLine->linenumber ||
272 buf->topLine->linenumber + buf->LINES <= n)
273 buf->topLine = lineSkip(buf, l, -(buf->LINES + 1) / 2, FALSE);
280 * gotoRealLine: go to real line number
283 gotoRealLine(Buffer *buf, int n)
286 Line *l = buf->firstLine;
290 if (buf->pagerSource && !(buf->bufferprop & BP_CLOSE)) {
291 if (buf->lastLine->real_linenumber < n)
292 getNextPage(buf, n - buf->lastLine->real_linenumber);
293 while ((buf->lastLine->real_linenumber < n) &&
294 (getNextPage(buf, 1) != NULL)) ;
296 if (l->real_linenumber > n) {
297 /* FIXME: gettextize? */
298 sprintf(msg, "First line is #%ld", l->real_linenumber);
299 set_delayed_message(msg);
300 buf->topLine = buf->currentLine = l;
303 if (buf->lastLine->real_linenumber < n) {
305 /* FIXME: gettextize? */
306 sprintf(msg, "Last line is #%ld", buf->lastLine->real_linenumber);
307 set_delayed_message(msg);
308 buf->currentLine = l;
309 buf->topLine = lineSkip(buf, buf->currentLine, -(buf->LINES - 1),
313 for (; l != NULL; l = l->next) {
314 if (l->real_linenumber >= n) {
315 buf->currentLine = l;
316 if (n < buf->topLine->real_linenumber ||
317 buf->topLine->real_linenumber + buf->LINES <= n)
318 buf->topLine = lineSkip(buf, l, -(buf->LINES + 1) / 2, FALSE);
326 listBuffer(Buffer *top, Buffer *current)
334 setfcolor(basic_color);
337 #endif /* USE_BG_COLOR */
339 #endif /* USE_COLOR */
341 for (i = 0; i < LASTLINE; i++) {
342 if (buf == current) {
346 writeBufferName(buf, i);
347 if (buf == current) {
355 if (buf->nextBuffer == NULL) {
360 buf = buf->nextBuffer;
363 /* FIXME: gettextize? */
364 message("Buffer selection mode: SPC for select / D for delete buffer", 0,
368 * move(LASTLINE, COLS - 1); */
371 return buf->nextBuffer;
376 * Select buffer visually
379 selectBuffer(Buffer *firstbuf, Buffer *currentbuf, char *selectchar)
381 int i, cpoint, /* Current Buffer Number */
382 spoint, /* Current Line on Screen */
383 maxbuf, sclimit = LASTLINE; /* Upper limit of line * number in
385 Buffer *buf, *topbuf;
389 for (buf = firstbuf; buf != NULL; buf = buf->nextBuffer) {
390 if (buf == currentbuf)
396 if (cpoint >= sclimit) {
397 spoint = sclimit / 2;
398 topbuf = nthBuffer(firstbuf, cpoint - spoint);
404 listBuffer(topbuf, currentbuf);
407 if ((c = getch()) == ESC_CODE) {
408 if ((c = getch()) == '[' || c == 'O') {
409 switch (c = getch()) {
444 if (spoint < sclimit - 1) {
445 if (currentbuf->nextBuffer == NULL)
447 writeBufferName(currentbuf, spoint);
448 currentbuf = currentbuf->nextBuffer;
452 writeBufferName(currentbuf, spoint);
457 else if (cpoint < maxbuf - 1) {
459 currentbuf = currentbuf->nextBuffer;
462 listBuffer(topbuf, currentbuf);
468 writeBufferName(currentbuf, spoint);
469 currentbuf = nthBuffer(topbuf, --spoint);
472 writeBufferName(currentbuf, spoint);
477 else if (cpoint > 0) {
478 i = cpoint - sclimit;
483 currentbuf = nthBuffer(firstbuf, cpoint);
484 topbuf = nthBuffer(firstbuf, i);
485 listBuffer(topbuf, currentbuf);
493 * move(LASTLINE, COLS - 1);
501 * Reshape HTML buffer
504 reshapeBuffer(Buffer *buf)
509 wc_uint8 old_auto_detect = WcOption.auto_detect;
512 if (!buf->need_reshape)
514 buf->need_reshape = FALSE;
515 buf->width = INIT_BUFFER_WIDTH;
516 if (buf->sourcefile == NULL)
518 init_stream(&f, SCM_LOCAL, NULL);
519 examineFile(buf->mailcap_source ? buf->mailcap_source : buf->sourcefile,
521 if (f.stream == NULL)
523 copyBuffer(&sbuf, buf);
525 while (buf->frameset) {
526 deleteFrameSet(buf->frameset);
527 buf->frameset = popFrameTree(&(buf->frameQ));
533 buf->formitem = NULL;
534 buf->formlist = NULL;
535 buf->linklist = NULL;
538 buf->hmarklist->nmark = 0;
540 buf->imarklist->nmark = 0;
542 if (buf->header_source) {
543 if (buf->currentURL.scheme != SCM_LOCAL ||
544 buf->mailcap_source || !strcmp(buf->currentURL.file, "-")) {
546 init_stream(&h, SCM_LOCAL, NULL);
547 examineFile(buf->header_source, &h);
549 readHeader(&h, buf, TRUE, NULL);
553 else if (buf->search_header) /* -m option */
554 readHeader(&f, buf, TRUE, NULL);
558 WcOption.auto_detect = WC_OPT_DETECT_OFF;
559 UseContentCharset = FALSE;
561 if (!strcasecmp(buf->type, "text/html"))
562 loadHTMLBuffer(&f, buf);
567 WcOption.auto_detect = old_auto_detect;
568 UseContentCharset = TRUE;
571 buf->height = LASTLINE + 1;
572 if (buf->firstLine && sbuf.firstLine) {
573 Line *cur = sbuf.currentLine;
576 buf->pos = sbuf.pos + cur->bpos;
577 while (cur->bpos && cur->prev)
579 if (cur->real_linenumber > 0)
580 gotoRealLine(buf, cur->real_linenumber);
582 gotoLine(buf, cur->linenumber);
583 n = (buf->currentLine->linenumber - buf->topLine->linenumber)
584 - (cur->linenumber - sbuf.topLine->linenumber);
586 buf->topLine = lineSkip(buf, buf->topLine, n, FALSE);
587 if (cur->real_linenumber > 0)
588 gotoRealLine(buf, cur->real_linenumber);
590 gotoLine(buf, cur->linenumber);
592 buf->pos -= buf->currentLine->bpos;
593 if (FoldLine && strcasecmp(buf->type, "text/html"))
594 buf->currentColumn = 0;
596 buf->currentColumn = sbuf.currentColumn;
599 if (buf->check_url & CHK_URL)
602 if (buf->check_url & CHK_NMID)
604 if (buf->real_scheme == SCM_NNTP || buf->real_scheme == SCM_NEWS)
605 reAnchorNewsheader(buf);
607 formResetBuffer(buf, sbuf.formitem);
612 copyBuffer(Buffer *a, Buffer *b)
615 bcopy((void *)b, (void *)a, sizeof(Buffer));
619 prevBuffer(Buffer *first, Buffer *buf)
623 for (b = first; b != NULL && b->nextBuffer != buf; b = b->nextBuffer) ;
627 #define fwrite1(d, f) (fwrite(&d, sizeof(d), 1, f)==0)
628 #define fread1(d, f) (fread(&d, sizeof(d), 1, f)==0)
631 writeBufferCache(Buffer *buf)
636 #ifdef USE_ANSI_COLOR
643 if (buf->firstLine == NULL)
646 tmp = tmpfname(TMPF_CACHE, NULL);
647 buf->savecache = tmp->ptr;
648 cache = fopen(buf->savecache, "w");
652 if (fwrite1(buf->currentLine->linenumber, cache) ||
653 fwrite1(buf->topLine->linenumber, cache))
656 for (l = buf->firstLine; l; l = l->next) {
657 if (fwrite1(l->real_linenumber, cache) ||
658 fwrite1(l->usrflags, cache) ||
659 fwrite1(l->width, cache) ||
660 fwrite1(l->len, cache) ||
661 fwrite1(l->size, cache) ||
662 fwrite1(l->bpos, cache) || fwrite1(l->bwidth, cache))
665 if (fwrite(l->lineBuf, 1, l->size, cache) < l->size ||
666 fwrite(l->propBuf, sizeof(Lineprop), l->size, cache) < l->size)
669 #ifdef USE_ANSI_COLOR
670 colorflag = l->colorBuf ? 1 : 0;
671 if (fwrite1(colorflag, cache))
675 if (fwrite(l->colorBuf, sizeof(Linecolor), l->size, cache) <
687 unlink(buf->savecache);
689 buf->savecache = NULL;
694 readBufferCache(Buffer *buf)
697 Line *l = NULL, *prevl = NULL, *basel = NULL;
698 long lnum = 0, clnum, tlnum;
699 #ifdef USE_ANSI_COLOR
703 if (buf->savecache == NULL)
706 cache = fopen(buf->savecache, "r");
707 if (cache == NULL || fread1(clnum, cache) || fread1(tlnum, cache)) {
708 buf->savecache = NULL;
712 while (!feof(cache)) {
721 l->linenumber = lnum;
723 buf->currentLine = l;
726 if (fread1(l->real_linenumber, cache) ||
727 fread1(l->usrflags, cache) ||
728 fread1(l->width, cache) ||
729 fread1(l->len, cache) ||
730 fread1(l->size, cache) ||
731 fread1(l->bpos, cache) || fread1(l->bwidth, cache))
735 l->lineBuf = NewAtom_N(char, l->size + 1);
736 fread(l->lineBuf, 1, l->size, cache);
737 l->lineBuf[l->size] = '\0';
738 l->propBuf = NewAtom_N(Lineprop, l->size);
739 fread(l->propBuf, sizeof(Lineprop), l->size, cache);
742 l->lineBuf = basel->lineBuf + l->bpos;
743 l->propBuf = basel->propBuf + l->bpos;
747 #ifdef USE_ANSI_COLOR
748 if (fread1(colorflag, cache))
752 l->colorBuf = NewAtom_N(Linecolor, l->size);
753 fread(l->colorBuf, sizeof(Linecolor), l->size, cache);
756 l->colorBuf = basel->colorBuf + l->bpos;
763 buf->lastLine = prevl;
764 buf->lastLine->next = NULL;
766 unlink(buf->savecache);
767 buf->savecache = NULL;