/* linepos.c - record where lines are in file
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <time.h>
#include "mstring.h"
#include "terminal.h"
#include "viewfile.h"


/* Scan through the open file, recording where in the file each line starts,
 * as well as the values of any datestamps found.
 */
void rf_get_line_positions(rf_data_t data)
{
	struct Line_Array *ptr = 0;
	struct Line_Array *newptr;
	int found;
	long lines_allocated = 0;
	long lines = 0;
	long in_buffer = 0;
	long bytes_read;
	long prev_read = 0;
	long offset = 0;
	int eof = 0;
	long i, x;

	lseek(data->fd, 0, SEEK_SET);

	t_bored(0);

	do {

		t_bored(1);

		if ((!eof) && (in_buffer < sizeof(data->linebuf))) {
			bytes_read =
			    read(data->fd, data->linebuf + in_buffer,
				 sizeof(data->linebuf) - in_buffer);
			if (bytes_read > 0)
				in_buffer += bytes_read;
			else
				eof = 1;
		}

		found = 0;
		for (x = 0; (data->linebuf[x] != 10) && (x < in_buffer);
		     x++);
		if (x < in_buffer)
			found = 1;

		if (!found) {

			if ((!eof) && (in_buffer < sizeof(data->linebuf)))
				continue;

			prev_read += in_buffer;
			in_buffer = 0;
			data->linebuf[0] = 0;
			if (!eof)
				continue;
			bytes_read = prev_read;

		} else {

			bytes_read = x + 1 + prev_read;
			prev_read = 0;
			data->linebuf[x] = 0;

		}

		if (lines >= lines_allocated) {
			lines_allocated += 4096;
			newptr =
			    realloc(ptr, lines_allocated * sizeof(*ptr));
			if (!newptr) {
				fprintf(stderr,
					"memory reallocation failed\n\r");
				eof = 1;
				in_buffer = 0;
				continue;
			}
			ptr = newptr;
		}

		ptr[lines].offset = offset;
		ptr[lines].datestamp = 0;
		ptr[lines].len = bytes_read;
		ptr[lines].type = MFILE_LINE_NORMAL;

		if ((bytes_read >= 17)
		    && (strncmp(data->linebuf, "Message: ", 9) == 0)) {
			ptr[lines].datestamp = mstrtol(data->linebuf + 9);
			ptr[lines].type = MFILE_LINE_DATESTAMP;
		} else if (strncmp(data->linebuf, "Message:", 8) == 0) {
			ptr[lines].type = MFILE_LINE_DATESTAMP;
		} else if (strncmp(data->linebuf, "From: ", 6) == 0) {
			ptr[lines].type = MFILE_LINE_FROM;
		} else if (strncmp(data->linebuf, "To: ", 4) == 0) {
			ptr[lines].type = MFILE_LINE_TO;
		} else if (strncmp(data->linebuf, "Subject:", 8) == 0) {
			ptr[lines].type = MFILE_LINE_SUBJECT;
		} else {
			i = 0;
			while (((data->linebuf[i] == ' ')
				|| (data->linebuf[i] == 9))
			       && (i < in_buffer))
				i++;
			if ((i >= in_buffer) || (data->linebuf[i] == 0)) {
				ptr[lines].type = MFILE_LINE_BLANK;
			}
		}

		lines++;
		offset += bytes_read;

		if (found) {
			memmove(data->linebuf, data->linebuf + x + 1,
				in_buffer - (x + 1));
			in_buffer -= (x + 1);
		} else
			in_buffer = 0;

	} while (!(eof && (in_buffer < 1)));

	data->line_pos = ptr;
	data->num_lines = lines;
	data->last_scanned = time(0);
	data->ldb_entry->last_accessed = time(0);

	t_bored(0);
}

/* EOF */
