line.c revision 128345
1/*
2 * Copyright (C) 1984-2002  Mark Nudelman
3 *
4 * You may distribute under the terms of either the GNU General Public
5 * License or the Less License, as specified in the README file.
6 *
7 * For more information about less, or for information on how to
8 * contact the author, see the README file.
9 */
10
11
12/*
13 * Routines to manipulate the "line buffer".
14 * The line buffer holds a line of output as it is being built
15 * in preparation for output to the screen.
16 */
17
18#include "less.h"
19
20#define IS_CONT(c)  (((c) & 0xC0) == 0x80)
21
22public char *linebuf = NULL;	/* Buffer which holds the current output line */
23static char *attr = NULL;	/* Extension of linebuf to hold attributes */
24public int size_linebuf = 0;	/* Size of line buffer (and attr buffer) */
25
26public int cshift;		/* Current left-shift of output line buffer */
27public int hshift;		/* Desired left-shift of output line buffer */
28public int tabstops[TABSTOP_MAX] = { 0 }; /* Custom tabstops */
29public int ntabstops = 1;	/* Number of tabstops */
30public int tabdefault = 8;	/* Default repeated tabstops */
31
32static int curr;		/* Index into linebuf */
33static int column;		/* Printable length, accounting for
34				   backspaces, etc. */
35static int overstrike;		/* Next char should overstrike previous char */
36static int last_overstrike = AT_NORMAL;
37static int is_null_line;	/* There is no current line */
38static int lmargin;		/* Left margin */
39static int hilites;		/* Number of hilites in this line */
40static char pendc;
41static POSITION pendpos;
42static char *end_ansi_chars;
43
44static int do_append();
45
46extern int bs_mode;
47extern int linenums;
48extern int ctldisp;
49extern int twiddle;
50extern int binattr;
51extern int status_col;
52extern int auto_wrap, ignaw;
53extern int bo_s_width, bo_e_width;
54extern int ul_s_width, ul_e_width;
55extern int bl_s_width, bl_e_width;
56extern int so_s_width, so_e_width;
57extern int sc_width, sc_height;
58extern int utf_mode;
59extern POSITION start_attnpos;
60extern POSITION end_attnpos;
61
62/*
63 * Initialize from environment variables.
64 */
65	public void
66init_line()
67{
68	end_ansi_chars = lgetenv("LESSANSIENDCHARS");
69	if (end_ansi_chars == NULL || *end_ansi_chars == '\0')
70		end_ansi_chars = "m";
71	linebuf = (char *) ecalloc(LINEBUF_SIZE, sizeof(char));
72	attr = (char *) ecalloc(LINEBUF_SIZE, sizeof(char));
73	size_linebuf = LINEBUF_SIZE;
74}
75
76/*
77 * Expand the line buffer.
78 */
79 	static int
80expand_linebuf()
81{
82	int new_size = size_linebuf + LINEBUF_SIZE;
83	char *new_buf = (char *) calloc(new_size, sizeof(char));
84	char *new_attr = (char *) calloc(new_size, sizeof(char));
85	if (new_buf == NULL || new_attr == NULL)
86	{
87		if (new_attr != NULL)
88			free(new_attr);
89		if (new_buf != NULL)
90			free(new_buf);
91		return 1;
92	}
93	memcpy(new_buf, linebuf, size_linebuf * sizeof(char));
94	memcpy(new_attr, attr, size_linebuf * sizeof(char));
95	free(attr);
96	free(linebuf);
97	linebuf = new_buf;
98	attr = new_attr;
99	size_linebuf = new_size;
100	return 0;
101}
102
103/*
104 * Rewind the line buffer.
105 */
106	public void
107prewind()
108{
109	curr = 0;
110	column = 0;
111	overstrike = 0;
112	is_null_line = 0;
113	pendc = '\0';
114	lmargin = 0;
115	if (status_col)
116		lmargin += 1;
117#if HILITE_SEARCH
118	hilites = 0;
119#endif
120}
121
122/*
123 * Insert the line number (of the given position) into the line buffer.
124 */
125	public void
126plinenum(pos)
127	POSITION pos;
128{
129	register LINENUM linenum = 0;
130	register int i;
131
132	if (linenums == OPT_ONPLUS)
133	{
134		/*
135		 * Get the line number and put it in the current line.
136		 * {{ Note: since find_linenum calls forw_raw_line,
137		 *    it may seek in the input file, requiring the caller
138		 *    of plinenum to re-seek if necessary. }}
139		 * {{ Since forw_raw_line modifies linebuf, we must
140		 *    do this first, before storing anything in linebuf. }}
141		 */
142		linenum = find_linenum(pos);
143	}
144
145	/*
146	 * Display a status column if the -J option is set.
147	 */
148	if (status_col)
149	{
150		linebuf[curr] = ' ';
151		if (start_attnpos != NULL_POSITION &&
152		    pos >= start_attnpos && pos < end_attnpos)
153			attr[curr] = AT_STANDOUT;
154		else
155			attr[curr] = 0;
156		curr++;
157		column++;
158	}
159	/*
160	 * Display the line number at the start of each line
161	 * if the -N option is set.
162	 */
163	if (linenums == OPT_ONPLUS)
164	{
165		char buf[INT_STRLEN_BOUND(pos) + 2];
166		int n;
167
168		linenumtoa(linenum, buf);
169		n = strlen(buf);
170		if (n < MIN_LINENUM_WIDTH)
171			n = MIN_LINENUM_WIDTH;
172		sprintf(linebuf+curr, "%*s ", n, buf);
173		n++;  /* One space after the line number. */
174		for (i = 0; i < n; i++)
175			attr[curr+i] = AT_NORMAL;
176		curr += n;
177		column += n;
178		lmargin += n;
179	}
180
181	/*
182	 * Append enough spaces to bring us to the lmargin.
183	 */
184	while (column < lmargin)
185	{
186		linebuf[curr] = ' ';
187		attr[curr++] = AT_NORMAL;
188		column++;
189	}
190}
191
192/*
193 * Determine how many characters are required to shift N columns.
194 */
195	static int
196shift_chars(s, len)
197	char *s;
198	int len;
199{
200	char *p = s;
201
202	/*
203	 * Each char counts for one column, except ANSI color escape
204	 * sequences use no columns since they don't move the cursor.
205	 */
206	while (*p != '\0' && len > 0)
207	{
208		if (*p++ != ESC)
209		{
210			len--;
211		} else
212		{
213			while (*p != '\0')
214			{
215				if (is_ansi_end(*p++))
216					break;
217			}
218		}
219	}
220	return (p - s);
221}
222
223/*
224 * Determine how many characters are required to shift N columns (UTF version).
225 * {{ FIXME: what about color escape sequences in UTF mode? }}
226 */
227	static int
228utf_shift_chars(s, len)
229	char *s;
230	int len;
231{
232	int ulen = 0;
233
234	while (*s != '\0' && len > 0)
235	{
236		if (!IS_CONT(*s))
237			len--;
238		s++;
239		ulen++;
240	}
241	while (IS_CONT(*s))
242	{
243		s++;
244		ulen++;
245	}
246	return (ulen);
247}
248
249/*
250 * Shift the input line left.
251 * This means discarding N printable chars at the start of the buffer.
252 */
253	static void
254pshift(shift)
255	int shift;
256{
257	int i;
258	int nchars;
259
260	if (shift > column - lmargin)
261		shift = column - lmargin;
262	if (shift > curr - lmargin)
263		shift = curr - lmargin;
264
265	if (utf_mode)
266		nchars = utf_shift_chars(linebuf + lmargin, shift);
267	else
268		nchars = shift_chars(linebuf + lmargin, shift);
269	if (nchars > curr)
270		nchars = curr;
271	for (i = 0;  i < curr - nchars;  i++)
272	{
273		linebuf[lmargin + i] = linebuf[lmargin + i + nchars];
274		attr[lmargin + i] = attr[lmargin + i + nchars];
275	}
276	curr -= nchars;
277	column -= shift;
278	cshift += shift;
279}
280
281/*
282 * Return the printing width of the start (enter) sequence
283 * for a given character attribute.
284 */
285	static int
286attr_swidth(a)
287	int a;
288{
289	switch (a)
290	{
291	case AT_BOLD:		return (bo_s_width);
292	case AT_UNDERLINE:	return (ul_s_width);
293	case AT_BLINK:		return (bl_s_width);
294	case AT_STANDOUT:	return (so_s_width);
295	}
296	return (0);
297}
298
299/*
300 * Return the printing width of the end (exit) sequence
301 * for a given character attribute.
302 */
303	static int
304attr_ewidth(a)
305	int a;
306{
307	switch (a)
308	{
309	case AT_BOLD:		return (bo_e_width);
310	case AT_UNDERLINE:	return (ul_e_width);
311	case AT_BLINK:		return (bl_e_width);
312	case AT_STANDOUT:	return (so_e_width);
313	}
314	return (0);
315}
316
317/*
318 * Return the printing width of a given character and attribute,
319 * if the character were added to the current position in the line buffer.
320 * Adding a character with a given attribute may cause an enter or exit
321 * attribute sequence to be inserted, so this must be taken into account.
322 */
323	static int
324pwidth(c, a)
325	int c;
326	int a;
327{
328	register int w;
329
330	if (utf_mode && IS_CONT(c))
331		return (0);
332
333	if (c == '\b')
334		/*
335		 * Backspace moves backwards one position.
336		 */
337		return (-1);
338
339	if (control_char(c))
340		/*
341		 * Control characters do unpredicatable things,
342		 * so we don't even try to guess; say it doesn't move.
343		 * This can only happen if the -r flag is in effect.
344		 */
345		return (0);
346
347	/*
348	 * Other characters take one space,
349	 * plus the width of any attribute enter/exit sequence.
350	 */
351	w = 1;
352	if (curr > 0 && attr[curr-1] != a)
353		w += attr_ewidth(attr[curr-1]);
354	if (a && (curr == 0 || attr[curr-1] != a))
355		w += attr_swidth(a);
356	return (w);
357}
358
359/*
360 * Delete the previous character in the line buffer.
361 */
362	static void
363backc()
364{
365	curr--;
366	column -= pwidth(linebuf[curr], attr[curr]);
367}
368
369/*
370 * Are we currently within a recognized ANSI escape sequence?
371 */
372	static int
373in_ansi_esc_seq()
374{
375	int i;
376
377	/*
378	 * Search backwards for either an ESC (which means we ARE in a seq);
379	 * or an end char (which means we're NOT in a seq).
380	 */
381	for (i = curr-1;  i >= 0;  i--)
382	{
383		if (linebuf[i] == ESC)
384			return (1);
385		if (is_ansi_end(linebuf[i]))
386			return (0);
387	}
388	return (0);
389}
390
391/*
392 * Is a character the end of an ANSI escape sequence?
393 */
394	public int
395is_ansi_end(c)
396	char c;
397{
398	return (strchr(end_ansi_chars, c) != NULL);
399}
400
401/*
402 * Append a character and attribute to the line buffer.
403 */
404#define	STORE_CHAR(c,a,pos) \
405	do { if (store_char((c),(a),(pos))) return (1); else curr++; } while (0)
406
407	static int
408store_char(c, a, pos)
409	int c;
410	int a;
411	POSITION pos;
412{
413	register int w;
414
415	if (a != AT_NORMAL)
416		last_overstrike = a;
417#if HILITE_SEARCH
418	if (is_hilited(pos, pos+1, 0))
419	{
420		/*
421		 * This character should be highlighted.
422		 * Override the attribute passed in.
423		 */
424		a = AT_STANDOUT;
425		hilites++;
426	}
427#endif
428	if (ctldisp == OPT_ONPLUS && in_ansi_esc_seq())
429		w = 0;
430	else
431		w = pwidth(c, a);
432	if (ctldisp != OPT_ON && column + w + attr_ewidth(a) > sc_width)
433		/*
434		 * Won't fit on screen.
435		 */
436		return (1);
437
438	if (curr >= size_linebuf-2)
439	{
440		/*
441		 * Won't fit in line buffer.
442		 * Try to expand it.
443		 */
444		if (expand_linebuf())
445			return (1);
446	}
447
448	/*
449	 * Special handling for "magic cookie" terminals.
450	 * If an attribute enter/exit sequence has a printing width > 0,
451	 * and the sequence is adjacent to a space, delete the space.
452	 * We just mark the space as invisible, to avoid having too
453	 * many spaces deleted.
454	 * {{ Note that even if the attribute width is > 1, we
455	 *    delete only one space.  It's not worth trying to do more.
456	 *    It's hardly worth doing this much. }}
457	 */
458	if (curr > 0 && a != AT_NORMAL &&
459		linebuf[curr-1] == ' ' && attr[curr-1] == AT_NORMAL &&
460		attr_swidth(a) > 0)
461	{
462		/*
463		 * We are about to append an enter-attribute sequence
464		 * just after a space.  Delete the space.
465		 */
466		attr[curr-1] = AT_INVIS;
467		column--;
468	} else if (curr > 0 && attr[curr-1] != AT_NORMAL &&
469		attr[curr-1] != AT_INVIS && c == ' ' && a == AT_NORMAL &&
470		attr_ewidth(attr[curr-1]) > 0)
471	{
472		/*
473		 * We are about to append a space just after an
474		 * exit-attribute sequence.  Delete the space.
475		 */
476		a = AT_INVIS;
477		column--;
478	}
479	/* End of magic cookie handling. */
480
481	linebuf[curr] = c;
482	attr[curr] = a;
483	column += w;
484	return (0);
485}
486
487/*
488 * Append a tab to the line buffer.
489 * Store spaces to represent the tab.
490 */
491#define	STORE_TAB(a,pos) \
492	do { if (store_tab((a),(pos))) return (1); } while (0)
493
494	static int
495store_tab(attr, pos)
496	int attr;
497	POSITION pos;
498{
499	int to_tab = column + cshift - lmargin;
500	int i;
501
502	if (ntabstops < 2 || to_tab >= tabstops[ntabstops-1])
503		to_tab = tabdefault -
504		     ((to_tab - tabstops[ntabstops-1]) % tabdefault);
505	else
506	{
507		for (i = ntabstops - 2;  i >= 0;  i--)
508			if (to_tab >= tabstops[i])
509				break;
510		to_tab = tabstops[i+1] - to_tab;
511	}
512
513	do {
514		STORE_CHAR(' ', attr, pos);
515	} while (--to_tab > 0);
516	return 0;
517}
518
519/*
520 * Append a character to the line buffer.
521 * Expand tabs into spaces, handle underlining, boldfacing, etc.
522 * Returns 0 if ok, 1 if couldn't fit in buffer.
523 */
524	public int
525pappend(c, pos)
526	register int c;
527	POSITION pos;
528{
529	int r;
530
531	if (pendc)
532	{
533		if (do_append(pendc, pendpos))
534			/*
535			 * Oops.  We've probably lost the char which
536			 * was in pendc, since caller won't back up.
537			 */
538			return (1);
539		pendc = '\0';
540	}
541
542	if (c == '\r' && bs_mode == BS_SPECIAL)
543	{
544		/*
545		 * Don't put the CR into the buffer until we see
546		 * the next char.  If the next char is a newline,
547		 * discard the CR.
548		 */
549		pendc = c;
550		pendpos = pos;
551		return (0);
552	}
553
554	r = do_append(c, pos);
555	/*
556	 * If we need to shift the line, do it.
557	 * But wait until we get to at least the middle of the screen,
558	 * so shifting it doesn't affect the chars we're currently
559	 * pappending.  (Bold & underline can get messed up otherwise.)
560	 */
561	if (cshift < hshift && column > sc_width / 2)
562	{
563		linebuf[curr] = '\0';
564		pshift(hshift - cshift);
565	}
566	return (r);
567}
568
569#define IS_UTF8_4BYTE(c) ( ((c) & 0xf8) == 0xf0 )
570#define IS_UTF8_3BYTE(c) ( ((c) & 0xf0) == 0xe0 )
571#define IS_UTF8_2BYTE(c) ( ((c) & 0xe0) == 0xc0 )
572#define IS_UTF8_TRAIL(c) ( ((c) & 0xc0) == 0x80 )
573
574	static int
575do_append(c, pos)
576	int c;
577	POSITION pos;
578{
579	register char *s;
580	register int a;
581
582#define STOREC(c,a) \
583	if ((c) == '\t') STORE_TAB((a),pos); else STORE_CHAR((c),(a),pos)
584
585	if (c == '\b')
586	{
587		switch (bs_mode)
588		{
589		case BS_NORMAL:
590			STORE_CHAR(c, AT_NORMAL, pos);
591			break;
592		case BS_CONTROL:
593			goto do_control_char;
594		case BS_SPECIAL:
595			if (curr == 0)
596				break;
597			backc();
598			overstrike = 1;
599			break;
600		}
601	} else if (overstrike)
602	{
603		/*
604		 * Overstrike the character at the current position
605		 * in the line buffer.  This will cause either
606		 * underline (if a "_" is overstruck),
607		 * bold (if an identical character is overstruck),
608		 * or just deletion of the character in the buffer.
609		 */
610		overstrike--;
611		if (utf_mode && IS_UTF8_4BYTE(c) && curr > 2 && (char)c == linebuf[curr-3])
612		{
613			backc();
614			backc();
615			backc();
616			STORE_CHAR(linebuf[curr], AT_BOLD, pos);
617			overstrike = 3;
618		} else if (utf_mode && (IS_UTF8_3BYTE(c) || (overstrike==2 && IS_UTF8_TRAIL(c))) && curr > 1 && (char)c == linebuf[curr-2])
619		{
620			backc();
621			backc();
622			STORE_CHAR(linebuf[curr], AT_BOLD, pos);
623			overstrike = 2;
624		} else if (utf_mode && curr > 0 && (IS_UTF8_2BYTE(c) || (overstrike==1 && IS_UTF8_TRAIL(c))) && (char)c == linebuf[curr-1])
625		{
626			backc();
627			STORE_CHAR(linebuf[curr], AT_BOLD, pos);
628			overstrike = 1;
629		} else if (utf_mode && curr > 0 && IS_UTF8_TRAIL(c) && attr[curr-1] == AT_UNDERLINE)
630		{
631			STOREC(c, AT_UNDERLINE);
632		} else if ((char)c == linebuf[curr])
633		{
634			/*
635			 * Overstriking a char with itself means make it bold.
636			 * But overstriking an underscore with itself is
637			 * ambiguous.  It could mean make it bold, or
638			 * it could mean make it underlined.
639			 * Use the previous overstrike to resolve it.
640			 */
641			if (c == '_' && last_overstrike != AT_NORMAL)
642				STOREC(c, last_overstrike);
643			else
644				STOREC(c, AT_BOLD);
645		} else if (c == '_')
646		{
647			if (utf_mode)
648			{
649				int i;
650				for (i = 0;  i < 5;  i++)
651				{
652					if (curr <= i || !IS_CONT(linebuf[curr-i]))
653						break;
654					attr[curr-i-1] = AT_UNDERLINE;
655				}
656			}
657			STOREC(linebuf[curr], AT_UNDERLINE);
658		} else if (linebuf[curr] == '_')
659		{
660			if (utf_mode)
661			{
662				if (IS_UTF8_2BYTE(c))
663					overstrike = 1;
664				else if (IS_UTF8_3BYTE(c))
665					overstrike = 2;
666				else if (IS_UTF8_4BYTE(c))
667					overstrike = 3;
668			}
669			STOREC(c, AT_UNDERLINE);
670		} else if (control_char(c))
671			goto do_control_char;
672		else
673			STOREC(c, AT_NORMAL);
674	} else if (c == '\t')
675	{
676		/*
677		 * Expand a tab into spaces.
678		 */
679		switch (bs_mode)
680		{
681		case BS_CONTROL:
682			goto do_control_char;
683		case BS_NORMAL:
684		case BS_SPECIAL:
685			STORE_TAB(AT_NORMAL, pos);
686			break;
687		}
688	} else if (control_char(c))
689	{
690	do_control_char:
691		if (ctldisp == OPT_ON || (ctldisp == OPT_ONPLUS && c == ESC))
692		{
693			/*
694			 * Output as a normal character.
695			 */
696			STORE_CHAR(c, AT_NORMAL, pos);
697		} else
698		{
699			/*
700			 * Convert to printable representation.
701			 */
702			s = prchar(c);
703			a = binattr;
704
705			/*
706			 * Make sure we can get the entire representation
707			 * of the character on this line.
708			 */
709			if (column + (int) strlen(s) +
710			    attr_swidth(a) + attr_ewidth(a) > sc_width)
711				return (1);
712
713			for ( ;  *s != 0;  s++)
714				STORE_CHAR(*s, a, pos);
715		}
716	} else
717	{
718		STOREC(c, AT_NORMAL);
719	}
720
721	return (0);
722}
723
724/*
725 * Terminate the line in the line buffer.
726 */
727	public void
728pdone(endline)
729	int endline;
730{
731	if (pendc && (pendc != '\r' || !endline))
732		/*
733		 * If we had a pending character, put it in the buffer.
734		 * But discard a pending CR if we are at end of line
735		 * (that is, discard the CR in a CR/LF sequence).
736		 */
737		(void) do_append(pendc, pendpos);
738
739	/*
740	 * Make sure we've shifted the line, if we need to.
741	 */
742	if (cshift < hshift)
743		pshift(hshift - cshift);
744
745	/*
746	 * Add a newline if necessary,
747	 * and append a '\0' to the end of the line.
748	 */
749	if (column < sc_width || !auto_wrap || ignaw || ctldisp == OPT_ON)
750	{
751		linebuf[curr] = '\n';
752		attr[curr] = AT_NORMAL;
753		curr++;
754	}
755	linebuf[curr] = '\0';
756	attr[curr] = AT_NORMAL;
757
758#if HILITE_SEARCH
759	if (status_col && hilites > 0)
760	{
761		linebuf[0] = '*';
762		attr[0] = AT_STANDOUT;
763	}
764#endif
765	/*
766	 * If we are done with this line, reset the current shift.
767	 */
768	if (endline)
769		cshift = 0;
770}
771
772/*
773 * Get a character from the current line.
774 * Return the character as the function return value,
775 * and the character attribute in *ap.
776 */
777	public int
778gline(i, ap)
779	register int i;
780	register int *ap;
781{
782	char *s;
783
784	if (is_null_line)
785	{
786		/*
787		 * If there is no current line, we pretend the line is
788		 * either "~" or "", depending on the "twiddle" flag.
789		 */
790		*ap = AT_BOLD;
791		s = (twiddle) ? "~\n" : "\n";
792		return (s[i]);
793	}
794
795	*ap = attr[i];
796	return (linebuf[i] & 0377);
797}
798
799/*
800 * Indicate that there is no current line.
801 */
802	public void
803null_line()
804{
805	is_null_line = 1;
806	cshift = 0;
807}
808
809/*
810 * Analogous to forw_line(), but deals with "raw lines":
811 * lines which are not split for screen width.
812 * {{ This is supposed to be more efficient than forw_line(). }}
813 */
814	public POSITION
815forw_raw_line(curr_pos, linep)
816	POSITION curr_pos;
817	char **linep;
818{
819	register int n;
820	register int c;
821	POSITION new_pos;
822
823	if (curr_pos == NULL_POSITION || ch_seek(curr_pos) ||
824		(c = ch_forw_get()) == EOI)
825		return (NULL_POSITION);
826
827	n = 0;
828	for (;;)
829	{
830		if (c == '\n' || c == EOI)
831		{
832			new_pos = ch_tell();
833			break;
834		}
835		if (n >= size_linebuf-1)
836		{
837			if (expand_linebuf())
838			{
839				/*
840				 * Overflowed the input buffer.
841				 * Pretend the line ended here.
842				 */
843				new_pos = ch_tell() - 1;
844				break;
845			}
846		}
847		linebuf[n++] = c;
848		c = ch_forw_get();
849	}
850	linebuf[n] = '\0';
851	if (linep != NULL)
852		*linep = linebuf;
853	return (new_pos);
854}
855
856/*
857 * Analogous to back_line(), but deals with "raw lines".
858 * {{ This is supposed to be more efficient than back_line(). }}
859 */
860	public POSITION
861back_raw_line(curr_pos, linep)
862	POSITION curr_pos;
863	char **linep;
864{
865	register int n;
866	register int c;
867	POSITION new_pos;
868
869	if (curr_pos == NULL_POSITION || curr_pos <= ch_zero() ||
870		ch_seek(curr_pos-1))
871		return (NULL_POSITION);
872
873	n = size_linebuf;
874	linebuf[--n] = '\0';
875	for (;;)
876	{
877		c = ch_back_get();
878		if (c == '\n')
879		{
880			/*
881			 * This is the newline ending the previous line.
882			 * We have hit the beginning of the line.
883			 */
884			new_pos = ch_tell() + 1;
885			break;
886		}
887		if (c == EOI)
888		{
889			/*
890			 * We have hit the beginning of the file.
891			 * This must be the first line in the file.
892			 * This must, of course, be the beginning of the line.
893			 */
894			new_pos = ch_zero();
895			break;
896		}
897		if (n <= 0)
898		{
899			int old_size_linebuf = size_linebuf;
900			char *fm;
901			char *to;
902			if (expand_linebuf())
903			{
904				/*
905				 * Overflowed the input buffer.
906				 * Pretend the line ended here.
907				 */
908				new_pos = ch_tell() + 1;
909				break;
910			}
911			/*
912			 * Shift the data to the end of the new linebuf.
913			 */
914			for (fm = linebuf + old_size_linebuf,
915			      to = linebuf + size_linebuf;
916			     fm >= linebuf;  fm--, to--)
917				*to = *fm;
918			n = size_linebuf - old_size_linebuf;
919		}
920		linebuf[--n] = c;
921	}
922	if (linep != NULL)
923		*linep = &linebuf[n];
924	return (new_pos);
925}
926