/* curline.c - work out where we should be in the file
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "terminal.h"
#include "viewfile.h"


/* Checks that the "current line" specified in the last access data is up to
 * date, and finds where it should be if it's not.
 *
 * Returns 0 if no change was made, 1 if the file had been altered but the
 * line number wasn't changed (e.g. the file was added to), or 2 if the current
 * line number is different now.
 */
int rf_get_current_line(rf_data_t data)
{
	struct stat statbuf;
	long omax;
	long n;

	statbuf.st_mtime = 0;
	stat(data->ldb_entry->realname, &statbuf);
	data->last_modified = statbuf.st_mtime;	/* get last-modified time */

	if (data->last_modified <= data->last_scanned)
		return (0);		    /* no modification */

	omax = data->num_lines;

	close(data->fd);
	free(data->line_pos);

	data->fd = open(data->ldb_entry->realname, O_RDONLY);

	data->line_pos = 0;
	rf_get_line_positions(data);	    /* scan for line positions */

	/* If the last datestamp seen was on line 0, assume that we're always OK and
	 * that the file has just been added to, not truncated.
	 */

	if (data->ldb_entry->datestamp_line == 0) {
		data->ldb_entry->last_accessed = time(0);
		rf_redraw_screen(data);
		if (data->ldb_entry->current_line >= omax) {
			rf_scroll_forward(data, t_rows / 2);	/* scroll if were at end */
		}
		return (1);		    /* addition only */
	}

	/* Now, we check to see if the last datestamp seen is still where it used
	 * to be, and if it is, assume that we're OK and the file's only been added
	 * to, rather than truncated.
	 */

	if (data->ldb_entry->datestamp_line < data->num_lines) {
		if ((data->line_pos[data->ldb_entry->datestamp_line].type
		     == MFILE_LINE_DATESTAMP)
		    && (data->line_pos[data->ldb_entry->datestamp_line].
			datestamp == data->ldb_entry->last_datestamp)) {
			data->ldb_entry->last_accessed = time(0);
			rf_redraw_screen(data);
			if (data->ldb_entry->current_line >= omax) {
				rf_scroll_forward(data, t_rows / 2);	/* scroll if were at end */
			}
			return (1);	    /* addition only */
		}
	}

	/* Having established that the last datestamp seen is not at the line number
	 * it used to be, we now search backwards through the lines until we hit a
	 * datestamp earlier than or equal to the last one seen.
	 */

	n = data->num_lines - 1;
	while ((n >= 0)
	       && ((data->line_pos[n].type != MFILE_LINE_DATESTAMP)
		   || (data->line_pos[n].datestamp >
		       data->ldb_entry->last_datestamp)))
		n--;

	/* If no suitable datestamps were found, the current line is set to the top
	 * of the file:
	 */

	if (n < 0) {			    /* no likely datestamp found */
		data->ldb_entry->last_datestamp = 0;
		data->ldb_entry->datestamp_line = 0;
		data->ldb_entry->current_line = 0;
		rf_redraw_screen(data);
		return (2);		    /* file truncated */
	}

	/* If the datestamp found doesn't exactly match, the current line is set to
	 * the line the datestamp's on:
	 */

	if (data->line_pos[n].datestamp != data->ldb_entry->last_datestamp) {
		data->ldb_entry->last_datestamp =
		    data->line_pos[n].datestamp;
		data->ldb_entry->datestamp_line = n;
		data->ldb_entry->current_line = n;
		rf_redraw_screen(data);
		return (2);		    /* file truncated */
	}

	/* Otherwise, we've found the original datestamp, so the current line is set
	 * to be the same number of lines away from the datestamp as it used to be.
	 */

	data->ldb_entry->current_line = n + data->ldb_entry->current_line
	    - data->ldb_entry->datestamp_line;
	data->ldb_entry->datestamp_line = n;

	if (data->ldb_entry->current_line > data->num_lines) {
		data->ldb_entry->current_line = data->num_lines;
	}

	rf_redraw_screen(data);
	return (2);			    /* file truncated */
}

/* EOF */
