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