w3m

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

buffer.c (16262B)


      1 /* $Id$ */
      2 #include "fm.h"
      3 
      4 #ifdef USE_MOUSE
      5 #ifdef USE_GPM
      6 #include <gpm.h>
      7 #endif
      8 #if defined(USE_GPM) || defined(USE_SYSMOUSE)
      9 extern int do_getch();
     10 #define getch()	do_getch()
     11 #endif				/* USE_GPM */
     12 #endif				/* USE_MOUSE */
     13 
     14 #ifdef __EMX__
     15 #include <sys/kbdscan.h>
     16 #include <strings.h>
     17 #endif
     18 char *NullLine = "";
     19 Lineprop NullProp[] = { 0 };
     20 
     21 /* 
     22  * Buffer creation
     23  */
     24 Buffer *
     25 newBuffer(int width)
     26 {
     27     Buffer *n;
     28 
     29     n = New(Buffer);
     30     if (n == NULL)
     31 	return NULL;
     32     bzero((void *)n, sizeof(Buffer));
     33     n->width = width;
     34     n->COLS = COLS;
     35     n->LINES = LASTLINE;
     36     n->currentURL.scheme = SCM_UNKNOWN;
     37     n->baseURL = NULL;
     38     n->baseTarget = NULL;
     39     n->buffername = "";
     40     n->bufferprop = BP_NORMAL;
     41     n->clone = New(int);
     42     *n->clone = 1;
     43     n->trbyte = 0;
     44 #ifdef USE_SSL
     45     n->ssl_certificate = NULL;
     46 #endif
     47 #ifdef USE_M17N
     48     n->auto_detect = WcOption.auto_detect;
     49 #endif
     50     return n;
     51 }
     52 
     53 /* 
     54  * Create null buffer
     55  */
     56 Buffer *
     57 nullBuffer(void)
     58 {
     59     Buffer *b;
     60 
     61     b = newBuffer(COLS);
     62     b->buffername = "*Null*";
     63     return b;
     64 }
     65 
     66 /* 
     67  * clearBuffer: clear buffer content
     68  */
     69 void
     70 clearBuffer(Buffer *buf)
     71 {
     72     buf->firstLine = buf->topLine = buf->currentLine = buf->lastLine = NULL;
     73     buf->allLine = 0;
     74 }
     75 
     76 /* 
     77  * discardBuffer: free buffer structure
     78  */
     79 
     80 void
     81 discardBuffer(Buffer *buf)
     82 {
     83     int i;
     84     Buffer *b;
     85 
     86 #ifdef USE_IMAGE
     87     deleteImage(buf);
     88 #endif
     89     clearBuffer(buf);
     90     for (i = 0; i < MAX_LB; i++) {
     91 	b = buf->linkBuffer[i];
     92 	if (b == NULL)
     93 	    continue;
     94 	b->linkBuffer[REV_LB[i]] = NULL;
     95     }
     96     if (buf->savecache)
     97 	unlink(buf->savecache);
     98     if (--(*buf->clone))
     99 	return;
    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);
    106     }
    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));
    114     }
    115 }
    116 
    117 /* 
    118  * namedBuffer: Select buffer which have specified name
    119  */
    120 Buffer *
    121 namedBuffer(Buffer *first, char *name)
    122 {
    123     Buffer *buf;
    124 
    125     if (!strcmp(first->buffername, name)) {
    126 	return first;
    127     }
    128     for (buf = first; buf->nextBuffer != NULL; buf = buf->nextBuffer) {
    129 	if (!strcmp(buf->nextBuffer->buffername, name)) {
    130 	    return buf->nextBuffer;
    131 	}
    132     }
    133     return NULL;
    134 }
    135 
    136 /* 
    137  * deleteBuffer: delete buffer
    138  */
    139 Buffer *
    140 deleteBuffer(Buffer *first, Buffer *delbuf)
    141 {
    142     Buffer *buf, *b;
    143 
    144     if (first == delbuf && first->nextBuffer != NULL) {
    145 	buf = first->nextBuffer;
    146 	discardBuffer(first);
    147 	return buf;
    148     }
    149     if ((buf = prevBuffer(first, delbuf)) != NULL) {
    150 	b = buf->nextBuffer;
    151 	buf->nextBuffer = b->nextBuffer;
    152 	discardBuffer(b);
    153     }
    154     return first;
    155 }
    156 
    157 /* 
    158  * replaceBuffer: replace buffer
    159  */
    160 Buffer *
    161 replaceBuffer(Buffer *first, Buffer *delbuf, Buffer *newbuf)
    162 {
    163     Buffer *buf;
    164 
    165     if (delbuf == NULL) {
    166 	newbuf->nextBuffer = first;
    167 	return newbuf;
    168     }
    169     if (first == delbuf) {
    170 	newbuf->nextBuffer = delbuf->nextBuffer;
    171 	discardBuffer(delbuf);
    172 	return newbuf;
    173     }
    174     if (delbuf && (buf = prevBuffer(first, delbuf))) {
    175 	buf->nextBuffer = newbuf;
    176 	newbuf->nextBuffer = delbuf->nextBuffer;
    177 	discardBuffer(delbuf);
    178 	return first;
    179     }
    180     newbuf->nextBuffer = first;
    181     return newbuf;
    182 }
    183 
    184 Buffer *
    185 nthBuffer(Buffer *firstbuf, int n)
    186 {
    187     int i;
    188     Buffer *buf = firstbuf;
    189 
    190     if (n < 0)
    191 	return firstbuf;
    192     for (i = 0; i < n; i++) {
    193 	if (buf == NULL)
    194 	    return NULL;
    195 	buf = buf->nextBuffer;
    196     }
    197     return buf;
    198 }
    199 
    200 static void
    201 writeBufferName(Buffer *buf, int n)
    202 {
    203     Str msg;
    204     int all;
    205 
    206     all = buf->allLine;
    207     if (all == 0 && buf->lastLine != NULL)
    208 	all = buf->lastLine->linenumber;
    209     move(n, 0);
    210     /* FIXME: gettextize? */
    211     msg = Sprintf("<%s> [%d lines]", buf->buffername, all);
    212     if (buf->filename != NULL) {
    213 	switch (buf->currentURL.scheme) {
    214 	case SCM_LOCAL:
    215 	case SCM_LOCAL_CGI:
    216 	    if (strcmp(buf->currentURL.file, "-")) {
    217 		Strcat_char(msg, ' ');
    218 		Strcat_charp(msg, conv_from_system(buf->currentURL.real_file));
    219 	    }
    220 	    break;
    221 	case SCM_UNKNOWN:
    222 	case SCM_MISSING:
    223 	    break;
    224 	default:
    225 	    Strcat_char(msg, ' ');
    226 	    Strcat(msg, parsedURL2Str(&buf->currentURL));
    227 	    break;
    228 	}
    229     }
    230     addnstr_sup(msg->ptr, COLS - 1);
    231 }
    232 
    233 
    234 /* 
    235  * gotoLine: go to line number
    236  */
    237 void
    238 gotoLine(Buffer *buf, int n)
    239 {
    240     char msg[32];
    241     Line *l = buf->firstLine;
    242 
    243     if (l == NULL)
    244 	return;
    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)) ;
    250     }
    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;
    256 	return;
    257     }
    258     if (buf->lastLine->linenumber < n) {
    259 	l = buf->lastLine;
    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),
    265 				FALSE);
    266 	return;
    267     }
    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);
    274 	    break;
    275 	}
    276     }
    277 }
    278 
    279 /* 
    280  * gotoRealLine: go to real line number
    281  */
    282 void
    283 gotoRealLine(Buffer *buf, int n)
    284 {
    285     char msg[32];
    286     Line *l = buf->firstLine;
    287 
    288     if (l == NULL)
    289 	return;
    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)) ;
    295     }
    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;
    301 	return;
    302     }
    303     if (buf->lastLine->real_linenumber < n) {
    304 	l = buf->lastLine;
    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),
    310 				FALSE);
    311 	return;
    312     }
    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);
    319 	    break;
    320 	}
    321     }
    322 }
    323 
    324 
    325 static Buffer *
    326 listBuffer(Buffer *top, Buffer *current)
    327 {
    328     int i, c = 0;
    329     Buffer *buf = top;
    330 
    331     move(0, 0);
    332 #ifdef USE_COLOR
    333     if (useColor) {
    334 	setfcolor(basic_color);
    335 #ifdef USE_BG_COLOR
    336 	setbcolor(bg_color);
    337 #endif				/* USE_BG_COLOR */
    338     }
    339 #endif				/* USE_COLOR */
    340     clrtobotx();
    341     for (i = 0; i < LASTLINE; i++) {
    342 	if (buf == current) {
    343 	    c = i;
    344 	    standout();
    345 	}
    346 	writeBufferName(buf, i);
    347 	if (buf == current) {
    348 	    standend();
    349 	    clrtoeolx();
    350 	    move(i, 0);
    351 	    toggle_stand();
    352 	}
    353 	else
    354 	    clrtoeolx();
    355 	if (buf->nextBuffer == NULL) {
    356 	    move(i + 1, 0);
    357 	    clrtobotx();
    358 	    break;
    359 	}
    360 	buf = buf->nextBuffer;
    361     }
    362     standout();
    363     /* FIXME: gettextize? */
    364     message("Buffer selection mode: SPC for select / D for delete buffer", 0,
    365 	    0);
    366     standend();
    367     /* 
    368      * move(LASTLINE, COLS - 1); */
    369     move(c, 0);
    370     refresh();
    371     return buf->nextBuffer;
    372 }
    373 
    374 
    375 /* 
    376  * Select buffer visually
    377  */
    378 Buffer *
    379 selectBuffer(Buffer *firstbuf, Buffer *currentbuf, char *selectchar)
    380 {
    381     int i, cpoint,		/* Current Buffer Number */
    382      spoint,			/* Current Line on Screen */
    383      maxbuf, sclimit = LASTLINE;	/* Upper limit of line * number in 
    384 					 * the * screen */
    385     Buffer *buf, *topbuf;
    386     char c;
    387 
    388     i = cpoint = 0;
    389     for (buf = firstbuf; buf != NULL; buf = buf->nextBuffer) {
    390 	if (buf == currentbuf)
    391 	    cpoint = i;
    392 	i++;
    393     }
    394     maxbuf = i;
    395 
    396     if (cpoint >= sclimit) {
    397 	spoint = sclimit / 2;
    398 	topbuf = nthBuffer(firstbuf, cpoint - spoint);
    399     }
    400     else {
    401 	topbuf = firstbuf;
    402 	spoint = cpoint;
    403     }
    404     listBuffer(topbuf, currentbuf);
    405 
    406     for (;;) {
    407 	if ((c = getch()) == ESC_CODE) {
    408 	    if ((c = getch()) == '[' || c == 'O') {
    409 		switch (c = getch()) {
    410 		case 'A':
    411 		    c = 'k';
    412 		    break;
    413 		case 'B':
    414 		    c = 'j';
    415 		    break;
    416 		case 'C':
    417 		    c = ' ';
    418 		    break;
    419 		case 'D':
    420 		    c = 'B';
    421 		    break;
    422 		}
    423 	    }
    424 	}
    425 #ifdef __EMX__
    426 	else if (!c)
    427 	    switch (getch()) {
    428 	    case K_UP:
    429 		c = 'k';
    430 		break;
    431 	    case K_DOWN:
    432 		c = 'j';
    433 		break;
    434 	    case K_RIGHT:
    435 		c = ' ';
    436 		break;
    437 	    case K_LEFT:
    438 		c = 'B';
    439 	    }
    440 #endif
    441 	switch (c) {
    442 	case CTRL_N:
    443 	case 'j':
    444 	    if (spoint < sclimit - 1) {
    445 		if (currentbuf->nextBuffer == NULL)
    446 		    continue;
    447 		writeBufferName(currentbuf, spoint);
    448 		currentbuf = currentbuf->nextBuffer;
    449 		cpoint++;
    450 		spoint++;
    451 		standout();
    452 		writeBufferName(currentbuf, spoint);
    453 		standend();
    454 		move(spoint, 0);
    455 		toggle_stand();
    456 	    }
    457 	    else if (cpoint < maxbuf - 1) {
    458 		topbuf = currentbuf;
    459 		currentbuf = currentbuf->nextBuffer;
    460 		cpoint++;
    461 		spoint = 1;
    462 		listBuffer(topbuf, currentbuf);
    463 	    }
    464 	    break;
    465 	case CTRL_P:
    466 	case 'k':
    467 	    if (spoint > 0) {
    468 		writeBufferName(currentbuf, spoint);
    469 		currentbuf = nthBuffer(topbuf, --spoint);
    470 		cpoint--;
    471 		standout();
    472 		writeBufferName(currentbuf, spoint);
    473 		standend();
    474 		move(spoint, 0);
    475 		toggle_stand();
    476 	    }
    477 	    else if (cpoint > 0) {
    478 		i = cpoint - sclimit;
    479 		if (i < 0)
    480 		    i = 0;
    481 		cpoint--;
    482 		spoint = cpoint - i;
    483 		currentbuf = nthBuffer(firstbuf, cpoint);
    484 		topbuf = nthBuffer(firstbuf, i);
    485 		listBuffer(topbuf, currentbuf);
    486 	    }
    487 	    break;
    488 	default:
    489 	    *selectchar = c;
    490 	    return currentbuf;
    491 	}
    492 	/* 
    493 	 * move(LASTLINE, COLS - 1);
    494 	 */
    495 	move(spoint, 0);
    496 	refresh();
    497     }
    498 }
    499 
    500 /* 
    501  * Reshape HTML buffer
    502  */
    503 void
    504 reshapeBuffer(Buffer *buf)
    505 {
    506     URLFile f;
    507     Buffer sbuf;
    508 #ifdef USE_M17N
    509     wc_uint8 old_auto_detect = WcOption.auto_detect;
    510 #endif
    511 
    512     if (!buf->need_reshape)
    513 	return;
    514     buf->need_reshape = FALSE;
    515     buf->width = INIT_BUFFER_WIDTH;
    516     if (buf->sourcefile == NULL)
    517 	return;
    518     init_stream(&f, SCM_LOCAL, NULL);
    519     examineFile(buf->mailcap_source ? buf->mailcap_source : buf->sourcefile,
    520 		&f);
    521     if (f.stream == NULL)
    522 	return;
    523     copyBuffer(&sbuf, buf);
    524     clearBuffer(buf);
    525     while (buf->frameset) {
    526 	deleteFrameSet(buf->frameset);
    527 	buf->frameset = popFrameTree(&(buf->frameQ));
    528     }
    529 
    530     buf->href = NULL;
    531     buf->name = NULL;
    532     buf->img = NULL;
    533     buf->formitem = NULL;
    534     buf->formlist = NULL;
    535     buf->linklist = NULL;
    536     buf->maplist = NULL;
    537     if (buf->hmarklist)
    538 	buf->hmarklist->nmark = 0;
    539     if (buf->imarklist)
    540 	buf->imarklist->nmark = 0;
    541 
    542     if (buf->header_source) {
    543 	if (buf->currentURL.scheme != SCM_LOCAL ||
    544 	    buf->mailcap_source || !strcmp(buf->currentURL.file, "-")) {
    545 	    URLFile h;
    546 	    init_stream(&h, SCM_LOCAL, NULL);
    547 	    examineFile(buf->header_source, &h);
    548 	    if (h.stream) {
    549 		readHeader(&h, buf, TRUE, NULL);
    550 		UFclose(&h);
    551 	    }
    552 	}
    553 	else if (buf->search_header)	/* -m option */
    554 	    readHeader(&f, buf, TRUE, NULL);
    555     }
    556 
    557 #ifdef USE_M17N
    558     WcOption.auto_detect = WC_OPT_DETECT_OFF;
    559     UseContentCharset = FALSE;
    560 #endif
    561     if (is_html_type(buf->type))
    562 	loadHTMLBuffer(&f, buf);
    563     else
    564 	loadBuffer(&f, buf);
    565     UFclose(&f);
    566 #ifdef USE_M17N
    567     WcOption.auto_detect = old_auto_detect;
    568     UseContentCharset = TRUE;
    569 #endif
    570 
    571     buf->height = LASTLINE + 1;
    572     if (buf->firstLine && sbuf.firstLine) {
    573 	Line *cur = sbuf.currentLine;
    574 	int n;
    575 
    576 	buf->pos = sbuf.pos + cur->bpos;
    577 	while (cur->bpos && cur->prev)
    578 	    cur = cur->prev;
    579 	if (cur->real_linenumber > 0)
    580 	    gotoRealLine(buf, cur->real_linenumber);
    581 	else
    582 	    gotoLine(buf, cur->linenumber);
    583 	n = (buf->currentLine->linenumber - buf->topLine->linenumber)
    584 	    - (cur->linenumber - sbuf.topLine->linenumber);
    585 	if (n) {
    586 	    buf->topLine = lineSkip(buf, buf->topLine, n, FALSE);
    587 	    if (cur->real_linenumber > 0)
    588 		gotoRealLine(buf, cur->real_linenumber);
    589 	    else
    590 		gotoLine(buf, cur->linenumber);
    591 	}
    592 	buf->pos -= buf->currentLine->bpos;
    593 	if (FoldLine && !is_html_type(buf->type))
    594 	    buf->currentColumn = 0;
    595 	else
    596 	    buf->currentColumn = sbuf.currentColumn;
    597 	arrangeCursor(buf);
    598     }
    599     if (buf->check_url & CHK_URL)
    600 	chkURLBuffer(buf);
    601 #ifdef USE_NNTP
    602     if (buf->check_url & CHK_NMID)
    603 	chkNMIDBuffer(buf);
    604     if (buf->real_scheme == SCM_NNTP || buf->real_scheme == SCM_NEWS)
    605 	reAnchorNewsheader(buf);
    606 #endif
    607     formResetBuffer(buf, sbuf.formitem);
    608 }
    609 
    610 /* shallow copy */
    611 void
    612 copyBuffer(Buffer *a, Buffer *b)
    613 {
    614     readBufferCache(b);
    615     bcopy((void *)b, (void *)a, sizeof(Buffer));
    616 }
    617 
    618 Buffer *
    619 prevBuffer(Buffer *first, Buffer *buf)
    620 {
    621     Buffer *b;
    622 
    623     for (b = first; b != NULL && b->nextBuffer != buf; b = b->nextBuffer) ;
    624     return b;
    625 }
    626 
    627 #define fwrite1(d, f) (fwrite(&d, sizeof(d), 1, f)==0)
    628 #define fread1(d, f) (fread(&d, sizeof(d), 1, f)==0)
    629 
    630 int
    631 writeBufferCache(Buffer *buf)
    632 {
    633     Str tmp;
    634     FILE *cache = NULL;
    635     Line *l;
    636 #ifdef USE_ANSI_COLOR
    637     int colorflag;
    638 #endif
    639 
    640     if (buf->savecache)
    641 	return -1;
    642 
    643     if (buf->firstLine == NULL)
    644 	goto _error1;
    645 
    646     tmp = tmpfname(TMPF_CACHE, NULL);
    647     buf->savecache = tmp->ptr;
    648     cache = fopen(buf->savecache, "w");
    649     if (!cache)
    650 	goto _error1;
    651 
    652     if (fwrite1(buf->currentLine->linenumber, cache) ||
    653 	fwrite1(buf->topLine->linenumber, cache))
    654 	goto _error;
    655 
    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))
    663 	    goto _error;
    664 	if (l->bpos == 0) {
    665 	    if (fwrite(l->lineBuf, 1, l->size, cache) < l->size ||
    666 		fwrite(l->propBuf, sizeof(Lineprop), l->size, cache) < l->size)
    667 		goto _error;
    668 	}
    669 #ifdef USE_ANSI_COLOR
    670 	colorflag = l->colorBuf ? 1 : 0;
    671 	if (fwrite1(colorflag, cache))
    672 	    goto _error;
    673 	if (colorflag) {
    674 	    if (l->bpos == 0) {
    675 		if (fwrite(l->colorBuf, sizeof(Linecolor), l->size, cache) <
    676 		    l->size)
    677 		    goto _error;
    678 	    }
    679 	}
    680 #endif
    681     }
    682 
    683     fclose(cache);
    684     return 0;
    685   _error:
    686     fclose(cache);
    687     unlink(buf->savecache);
    688   _error1:
    689     buf->savecache = NULL;
    690     return -1;
    691 }
    692 
    693 int
    694 readBufferCache(Buffer *buf)
    695 {
    696     FILE *cache;
    697     Line *l = NULL, *prevl = NULL, *basel = NULL;
    698     long lnum = 0, clnum, tlnum;
    699 #ifdef USE_ANSI_COLOR
    700     int colorflag;
    701 #endif
    702 
    703     if (buf->savecache == NULL)
    704 	return -1;
    705 
    706     cache = fopen(buf->savecache, "r");
    707     if (cache == NULL || fread1(clnum, cache) || fread1(tlnum, cache)) {
    708 	buf->savecache = NULL;
    709 	return -1;
    710     }
    711 
    712     while (!feof(cache)) {
    713 	lnum++;
    714 	prevl = l;
    715 	l = New(Line);
    716 	l->prev = prevl;
    717 	if (prevl)
    718 	    prevl->next = l;
    719 	else
    720 	    buf->firstLine = l;
    721 	l->linenumber = lnum;
    722 	if (lnum == clnum)
    723 	    buf->currentLine = l;
    724 	if (lnum == tlnum)
    725 	    buf->topLine = 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))
    732 	    break;
    733 	if (l->bpos == 0) {
    734 	    basel = l;
    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);
    740 	}
    741 	else if (basel) {
    742 	    l->lineBuf = basel->lineBuf + l->bpos;
    743 	    l->propBuf = basel->propBuf + l->bpos;
    744 	}
    745 	else
    746 	    break;
    747 #ifdef USE_ANSI_COLOR
    748 	if (fread1(colorflag, cache))
    749 	    break;
    750 	if (colorflag) {
    751 	    if (l->bpos == 0) {
    752 		l->colorBuf = NewAtom_N(Linecolor, l->size);
    753 		fread(l->colorBuf, sizeof(Linecolor), l->size, cache);
    754 	    }
    755 	    else
    756 		l->colorBuf = basel->colorBuf + l->bpos;
    757 	}
    758 	else {
    759 	    l->colorBuf = NULL;
    760 	}
    761 #endif
    762     }
    763     buf->lastLine = prevl;
    764     buf->lastLine->next = NULL;
    765     fclose(cache);
    766     unlink(buf->savecache);
    767     buf->savecache = NULL;
    768     return 0;
    769 }