position.c revision 251154
11573Srgrimes/*
21573Srgrimes * Copyright (C) 1984-2012  Mark Nudelman
31573Srgrimes *
41573Srgrimes * You may distribute under the terms of either the GNU General Public
51573Srgrimes * License or the Less License, as specified in the README file.
61573Srgrimes *
71573Srgrimes * For more information, see the README file.
81573Srgrimes */
91573Srgrimes
101573Srgrimes
111573Srgrimes/*
121573Srgrimes * Routines dealing with the "position" table.
131573Srgrimes * This is a table which tells the position (in the input file) of the
141573Srgrimes * first char on each currently displayed line.
151573Srgrimes *
161573Srgrimes * {{ The position table is scrolled by moving all the entries.
171573Srgrimes *    Would be better to have a circular table
181573Srgrimes *    and just change a couple of pointers. }}
191573Srgrimes */
201573Srgrimes
211573Srgrimes#include "less.h"
221573Srgrimes#include "position.h"
231573Srgrimes
241573Srgrimesstatic POSITION *table = NULL;	/* The position table */
251573Srgrimesstatic int table_size;
261573Srgrimes
271573Srgrimesextern int sc_width, sc_height;
281573Srgrimes
291573Srgrimes/*
301573Srgrimes * Return the starting file position of a line displayed on the screen.
311573Srgrimes * The line may be specified as a line number relative to the top
321573Srgrimes * of the screen, but is usually one of these special cases:
3350476Speter *	the top (first) line on the screen
341573Srgrimes *	the second line on the screen
35200019Sbrueffer *	the bottom line on the screen
361573Srgrimes *	the line after the bottom line on the screen
371573Srgrimes */
381573Srgrimes	public POSITION
39189356Sdasposition(where)
40189356Sdas	int where;
411573Srgrimes{
4259460Sphantom	switch (where)
4359460Sphantom	{
441573Srgrimes	case BOTTOM:
45189356Sdas		where = sc_height - 2;
4684306Sru		break;
471573Srgrimes	case BOTTOM_PLUS_ONE:
48103012Stjr		where = sc_height - 1;
491573Srgrimes		break;
50103012Stjr	case MIDDLE:
511573Srgrimes		where = (sc_height - 1) / 2;
52103012Stjr	}
531573Srgrimes	return (table[where]);
54103012Stjr}
5515931Speter
5615931Speter/*
57189356Sdas * Add a new file position to the bottom of the position table.
58200019Sbrueffer */
5984306Sru	public void
601573Srgrimesadd_forw_pos(pos)
61103012Stjr	POSITION pos;
621573Srgrimes{
63103012Stjr	register int i;
641573Srgrimes
65103012Stjr	/*
661573Srgrimes	 * Scroll the position table up.
67103012Stjr	 */
6815931Speter	for (i = 1;  i < sc_height;  i++)
6915931Speter		table[i-1] = table[i];
70189356Sdas	table[sc_height - 1] = pos;
71189356Sdas}
721573Srgrimes
731573Srgrimes/*
741573Srgrimes * Add a new file position to the top of the position table.
751573Srgrimes */
761573Srgrimes	public void
771573Srgrimesadd_back_pos(pos)
78108037Sru	POSITION pos;
79108037Sru{
801573Srgrimes	register int i;
811573Srgrimes
82108037Sru	/*
831573Srgrimes	 * Scroll the position table down.
84107619Sru	 */
851573Srgrimes	for (i = sc_height - 1;  i > 0;  i--)
861573Srgrimes		table[i] = table[i-1];
871573Srgrimes	table[0] = pos;
881573Srgrimes}
891573Srgrimes
901573Srgrimes/*
91189356Sdas * Initialize the position table, done whenever we clear the screen.
92189356Sdas */
93189356Sdas	public void
94189356Sdaspos_clear()
951573Srgrimes{
961573Srgrimes	register int i;
971573Srgrimes
981573Srgrimes	for (i = 0;  i < sc_height;  i++)
991573Srgrimes		table[i] = NULL_POSITION;
1001573Srgrimes}
10115931Speter
10215931Speter/*
10315931Speter * Allocate or reallocate the position table.
10415931Speter */
10515931Speter	public void
10615931Speterpos_init()
10749082Shoek{
10815931Speter	struct scrpos scrpos;
1091573Srgrimes
1101573Srgrimes	if (sc_height <= table_size)
1111573Srgrimes		return;
1121573Srgrimes	/*
1131573Srgrimes	 * If we already have a table, remember the first line in it
1141573Srgrimes	 * before we free it, so we can copy that line to the new table.
11515931Speter	 */
116108037Sru	if (table != NULL)
117108037Sru	{
11815931Speter		get_scrpos(&scrpos);
11915931Speter		free((char*)table);
120108037Sru	} else
12170553Sben		scrpos.pos = NULL_POSITION;
12270553Sben	table = (POSITION *) ecalloc(sc_height, sizeof(POSITION));
12370553Sben	table_size = sc_height;
12415931Speter	pos_clear();
12515931Speter	if (scrpos.pos != NULL_POSITION)
12615931Speter		table[scrpos.ln-1] = scrpos.pos;
12778180Sschweikh}
12815931Speter
12915931Speter/*
13015931Speter * See if the byte at a specified position is currently on the screen.
13187735Sru * Check the position table to see if the position falls within its range.
13215931Speter * Return the position table entry if found, -1 if not.
13379199Sru */
13479199Sru	public int
13579199Sruonscreen(pos)
13615931Speter	POSITION pos;
137108037Sru{
138108037Sru	register int i;
1391573Srgrimes
1401573Srgrimes	if (pos < table[0])
141108037Sru		return (-1);
14277794Simp	for (i = 1;  i < sc_height;  i++)
14377794Simp		if (pos < table[i])
14477794Simp			return (i-1);
14577794Simp	return (-1);
14677794Simp}
14777794Simp
14877794Simp/*
14977794Simp * See if the entire screen is empty.
15077794Simp */
15177794Simp	public int
15277794Simpempty_screen()
153234530Sdas{
154234530Sdas	return (empty_lines(0, sc_height-1));
155234530Sdas}
15615931Speter
157108037Sru	public int
158108037Sruempty_lines(s, e)
1591573Srgrimes	int s;
1601573Srgrimes	int e;
161108037Sru{
162234530Sdas	register int i;
163234530Sdas
164234530Sdas	for (i = s;  i <= e;  i++)
165234530Sdas		if (table[i] != NULL_POSITION && table[i] != 0)
1661573Srgrimes			return (0);
1671573Srgrimes	return (1);
1681573Srgrimes}
1691573Srgrimes
1701573Srgrimes/*
1711573Srgrimes * Get the current screen position.
1721573Srgrimes * The screen position consists of both a file position and
1731573Srgrimes * a screen line number where the file position is placed on the screen.
1741573Srgrimes * Normally the screen line number is 0, but if we are positioned
1751573Srgrimes * such that the top few lines are empty, we may have to set
17679199Sru * the screen line to a number > 0.
17779199Sru */
17879199Sru	public void
1791573Srgrimesget_scrpos(scrpos)
1801573Srgrimes	struct scrpos *scrpos;
1811573Srgrimes{
1821573Srgrimes	register int i;
1831573Srgrimes
1841573Srgrimes	/*
1851573Srgrimes	 * Find the first line on the screen which has something on it,
18621674Sjkh	 * and return the screen line number and the file position.
18721674Sjkh	 */
18879199Sru	for (i = 0; i < sc_height;  i++)
18921674Sjkh		if (table[i] != NULL_POSITION)
19021674Sjkh		{
19121674Sjkh			scrpos->ln = i+1;
19221674Sjkh			scrpos->pos = table[i];
19321674Sjkh			return;
19421674Sjkh		}
19521674Sjkh	/*
1961573Srgrimes	 * The screen is empty.
19787735Sru	 */
19887113Sfenner	scrpos->pos = NULL_POSITION;
19987113Sfenner}
20079199Sru
20178180Sschweikh/*
20279199Sru * Adjust a screen line number to be a simple positive integer
2031573Srgrimes * in the range { 0 .. sc_height-2 }.
20479199Sru * (The bottom line, sc_height-1, is reserved for prompts, etc.)
2051573Srgrimes * The given "sline" may be in the range { 1 .. sc_height-1 }
20678180Sschweikh * to refer to lines relative to the top of the screen (starting from 1),
2071573Srgrimes * or it may be in { -1 .. -(sc_height-1) } to refer to lines
2081573Srgrimes * relative to the bottom of the screen.
209187809Sdas */
2101573Srgrimes	public int
2111573Srgrimesadjsline(sline)
2121573Srgrimes	int sline;
2131573Srgrimes{
2141573Srgrimes	/*
2151573Srgrimes	 * Negative screen line number means
2161573Srgrimes	 * relative to the bottom of the screen.
2171573Srgrimes	 */
2181573Srgrimes	if (sline < 0)
2191573Srgrimes		sline += sc_height;
2201573Srgrimes	/*
2211573Srgrimes	 * Can't be less than 1 or greater than sc_height-1.
22287113Sfenner	 */
2231573Srgrimes	if (sline <= 0)
22479199Sru		sline = 1;
2251573Srgrimes	if (sline >= sc_height)
2261573Srgrimes		sline = sc_height - 1;
2271573Srgrimes	/*
2281573Srgrimes	 * Return zero-based line number, not one-based.
2291573Srgrimes	 */
2301573Srgrimes	return (sline-1);
2311573Srgrimes}
2321573Srgrimes