position.c revision 60786
160786Sps/*
260786Sps * Copyright (C) 1984-2000  Mark Nudelman
360786Sps *
460786Sps * You may distribute under the terms of either the GNU General Public
560786Sps * License or the Less License, as specified in the README file.
660786Sps *
760786Sps * For more information about less, or for information on how to
860786Sps * contact the author, see the README file.
960786Sps */
1060786Sps
1160786Sps
1260786Sps/*
1360786Sps * Routines dealing with the "position" table.
1460786Sps * This is a table which tells the position (in the input file) of the
1560786Sps * first char on each currently displayed line.
1660786Sps *
1760786Sps * {{ The position table is scrolled by moving all the entries.
1860786Sps *    Would be better to have a circular table
1960786Sps *    and just change a couple of pointers. }}
2060786Sps */
2160786Sps
2260786Sps#include "less.h"
2360786Sps#include "position.h"
2460786Sps
2560786Spsstatic POSITION *table = NULL;	/* The position table */
2660786Spsstatic int table_size;
2760786Sps
2860786Spsextern int sc_width, sc_height;
2960786Sps
3060786Sps/*
3160786Sps * Return the starting file position of a line displayed on the screen.
3260786Sps * The line may be specified as a line number relative to the top
3360786Sps * of the screen, but is usually one of these special cases:
3460786Sps *	the top (first) line on the screen
3560786Sps *	the second line on the screen
3660786Sps *	the bottom line on the screen
3760786Sps *	the line after the bottom line on the screen
3860786Sps */
3960786Sps	public POSITION
4060786Spsposition(where)
4160786Sps	int where;
4260786Sps{
4360786Sps	switch (where)
4460786Sps	{
4560786Sps	case BOTTOM:
4660786Sps		where = sc_height - 2;
4760786Sps		break;
4860786Sps	case BOTTOM_PLUS_ONE:
4960786Sps		where = sc_height - 1;
5060786Sps		break;
5160786Sps	case MIDDLE:
5260786Sps		where = (sc_height - 1) / 2;
5360786Sps	}
5460786Sps	return (table[where]);
5560786Sps}
5660786Sps
5760786Sps/*
5860786Sps * Add a new file position to the bottom of the position table.
5960786Sps */
6060786Sps	public void
6160786Spsadd_forw_pos(pos)
6260786Sps	POSITION pos;
6360786Sps{
6460786Sps	register int i;
6560786Sps
6660786Sps	/*
6760786Sps	 * Scroll the position table up.
6860786Sps	 */
6960786Sps	for (i = 1;  i < sc_height;  i++)
7060786Sps		table[i-1] = table[i];
7160786Sps	table[sc_height - 1] = pos;
7260786Sps}
7360786Sps
7460786Sps/*
7560786Sps * Add a new file position to the top of the position table.
7660786Sps */
7760786Sps	public void
7860786Spsadd_back_pos(pos)
7960786Sps	POSITION pos;
8060786Sps{
8160786Sps	register int i;
8260786Sps
8360786Sps	/*
8460786Sps	 * Scroll the position table down.
8560786Sps	 */
8660786Sps	for (i = sc_height - 1;  i > 0;  i--)
8760786Sps		table[i] = table[i-1];
8860786Sps	table[0] = pos;
8960786Sps}
9060786Sps
9160786Sps/*
9260786Sps * Initialize the position table, done whenever we clear the screen.
9360786Sps */
9460786Sps	public void
9560786Spspos_clear()
9660786Sps{
9760786Sps	register int i;
9860786Sps
9960786Sps	for (i = 0;  i < sc_height;  i++)
10060786Sps		table[i] = NULL_POSITION;
10160786Sps}
10260786Sps
10360786Sps/*
10460786Sps * Allocate or reallocate the position table.
10560786Sps */
10660786Sps	public void
10760786Spspos_init()
10860786Sps{
10960786Sps	struct scrpos scrpos;
11060786Sps
11160786Sps	if (sc_height <= table_size)
11260786Sps		return;
11360786Sps	/*
11460786Sps	 * If we already have a table, remember the first line in it
11560786Sps	 * before we free it, so we can copy that line to the new table.
11660786Sps	 */
11760786Sps	if (table != NULL)
11860786Sps	{
11960786Sps		get_scrpos(&scrpos);
12060786Sps		free((char*)table);
12160786Sps	} else
12260786Sps		scrpos.pos = NULL_POSITION;
12360786Sps	table = (POSITION *) ecalloc(sc_height, sizeof(POSITION));
12460786Sps	table_size = sc_height;
12560786Sps	pos_clear();
12660786Sps	if (scrpos.pos != NULL_POSITION)
12760786Sps		table[scrpos.ln-1] = scrpos.pos;
12860786Sps}
12960786Sps
13060786Sps/*
13160786Sps * See if the byte at a specified position is currently on the screen.
13260786Sps * Check the position table to see if the position falls within its range.
13360786Sps * Return the position table entry if found, -1 if not.
13460786Sps */
13560786Sps	public int
13660786Spsonscreen(pos)
13760786Sps	POSITION pos;
13860786Sps{
13960786Sps	register int i;
14060786Sps
14160786Sps	if (pos < table[0])
14260786Sps		return (-1);
14360786Sps	for (i = 1;  i < sc_height;  i++)
14460786Sps		if (pos < table[i])
14560786Sps			return (i-1);
14660786Sps	return (-1);
14760786Sps}
14860786Sps
14960786Sps/*
15060786Sps * See if the entire screen is empty.
15160786Sps */
15260786Sps	public int
15360786Spsempty_screen()
15460786Sps{
15560786Sps	return (empty_lines(0, sc_height-1));
15660786Sps}
15760786Sps
15860786Sps	public int
15960786Spsempty_lines(s, e)
16060786Sps	int s;
16160786Sps	int e;
16260786Sps{
16360786Sps	register int i;
16460786Sps
16560786Sps	for (i = s;  i <= e;  i++)
16660786Sps		if (table[i] != NULL_POSITION)
16760786Sps			return (0);
16860786Sps	return (1);
16960786Sps}
17060786Sps
17160786Sps/*
17260786Sps * Get the current screen position.
17360786Sps * The screen position consists of both a file position and
17460786Sps * a screen line number where the file position is placed on the screen.
17560786Sps * Normally the screen line number is 0, but if we are positioned
17660786Sps * such that the top few lines are empty, we may have to set
17760786Sps * the screen line to a number > 0.
17860786Sps */
17960786Sps	public void
18060786Spsget_scrpos(scrpos)
18160786Sps	struct scrpos *scrpos;
18260786Sps{
18360786Sps	register int i;
18460786Sps
18560786Sps	/*
18660786Sps	 * Find the first line on the screen which has something on it,
18760786Sps	 * and return the screen line number and the file position.
18860786Sps	 */
18960786Sps	for (i = 0; i < sc_height;  i++)
19060786Sps		if (table[i] != NULL_POSITION)
19160786Sps		{
19260786Sps			scrpos->ln = i+1;
19360786Sps			scrpos->pos = table[i];
19460786Sps			return;
19560786Sps		}
19660786Sps	/*
19760786Sps	 * The screen is empty.
19860786Sps	 */
19960786Sps	scrpos->pos = NULL_POSITION;
20060786Sps}
20160786Sps
20260786Sps/*
20360786Sps * Adjust a screen line number to be a simple positive integer
20460786Sps * in the range { 0 .. sc_height-2 }.
20560786Sps * (The bottom line, sc_height-1, is reserved for prompts, etc.)
20660786Sps * The given "sline" may be in the range { 1 .. sc_height-1 }
20760786Sps * to refer to lines relative to the top of the screen (starting from 1),
20860786Sps * or it may be in { -1 .. -(sc_height-1) } to refer to lines
20960786Sps * relative to the bottom of the screen.
21060786Sps */
21160786Sps	public int
21260786Spsadjsline(sline)
21360786Sps	int sline;
21460786Sps{
21560786Sps	/*
21660786Sps	 * Negative screen line number means
21760786Sps	 * relative to the bottom of the screen.
21860786Sps	 */
21960786Sps	if (sline < 0)
22060786Sps		sline += sc_height;
22160786Sps	/*
22260786Sps	 * Can't be less than 1 or greater than sc_height-1.
22360786Sps	 */
22460786Sps	if (sline <= 0)
22560786Sps		sline = 1;
22660786Sps	if (sline >= sc_height)
22760786Sps		sline = sc_height - 1;
22860786Sps	/*
22960786Sps	 * Return zero-based line number, not one-based.
23060786Sps	 */
23160786Sps	return (sline-1);
23260786Sps}
233