/*  CheckDateBook.c  */

/****************************************************************************
*									    *
*		     CheckDateBook.c					    *
*									    *
*	             by Robert Hardy					    *
*	    								    *
*	Copyright  April  87 -  Port Coquitlam, B.C.			    *
*	 	- released for free distribution as long as 		    *
*		  this copyright notice is retained in the file.	    *
*		  							    *
*   USAGE : CheckDateBook						    *
*									    *
*    NOTE  : Simple Binary File editor. Looks for the DateBook data	    *
*	     file (`s:dates.dat')					    *
*									    *
*									    *
*									    *
*****************************************************************************/

#include "CheckDateBook.h"

int File;
EVENT rec;

void main()
{
    char key;
    int goodbye = FALSE;

    if(  (File = open(FILENAME, O_RDWR | O_CREAT, PROT) ) == ERROR  ) 
    {
	printf("\n\nCannot open date file\n\n");
	exit(0);
    }
    if( Init_Console(HEADER) == NIL)
    {
	printf("\n\nCannot open Window\n\n");
	exit(0);
    }
    clear_rec();		/*  fill record with zeros  */
    get_next_rec();
    putstr(CSR_INVISIBLE);
    print_menu();
    while(!goodbye)
    {
	print_rec();
	key = getchar();
	switch( toupper(key) )
	{
	    case SPECIAL_KEY :		/*  Forward or Backward in file  */
		if( (key = getchar()) == CSR_RT )
		    get_next_rec();
		else if( key == CSR_LFT )
		    get_prev_rec();
		break;
	    case 'D' :			/*  Delete Record  */
	        putstr(MENU_LINE_1);
		putstr("\x1b[K\n\x1b[K\x1b[0m    \x1b[7mOK to DELETE Record ?\x1b[0m  ");
		if( (key = getchar()) == 'y' || key == 'Y' || key == CRET)
		{
		    clear_rec();
		    lseek(  File, -( sizeof(EVENT) ), 2  );
		    write( File, (char *) &rec, sizeof(EVENT) );
		}
		print_menu();
		break;
	    case 'C' :			/*  Update record  */
		if( change_rec() )
		{
		    putstr(MENU_LINE_1);
		    putstr("\x1b[K\n\x1b[K\x1b[0m    \x1b[7mOK to UPDATE Record ?\x1b[0m  ");
		    if( (key = getchar()) == 'y' || key == 'Y' || key == CRET)
		    {
			lseek(  File, -( sizeof(EVENT) ), 1  );
			write( File, (char *) &rec, sizeof(EVENT) );
		    }
		}
		print_menu();
		break;
	    case 'R' :			/*  redraw screen  */
		putchar(CLR);
		print_menu();
		break;
	    case 'A' :			/*  Add Records  */
		add_rec();
		break;
	    case 'Q' :			/*  Thats all folks  */		
		goodbye = TRUE;
		break;
	    case CODE_CLOSEWINDOW :	/*  Thats all folks  */		
		goodbye = TRUE;
		break;
	    case 'E' :			/*  goto end of file  */		
		lseek(  File, -( sizeof(EVENT) ), 2  );
		get_next_rec();
		break;
	    case 'B' :			/*  goto beginning   */
		lseek(  File, 0L, 0 );
		get_next_rec();
		break;
	}
    }
    close(File);
    Close_Console();
}

void get_next_rec()
{
    if(read( File, (char *) &rec, sizeof(EVENT) ) < sizeof(EVENT)  )
    {
	if(   lseek(  File, -( sizeof(EVENT) ), 1  )   != ERROR   )
	    get_next_rec();
    }
}

void get_prev_rec()
{
    if(   lseek(  File, -2 * ( sizeof(EVENT) ), 1  )  == ERROR   )
    {
	lseek(File, 0l, 0);
    }
    read( File, (char *) &rec, sizeof(EVENT) ); 
}

int change_rec()
{
    int field_num = 0, changed = 0;
    char warn[5], freq[5];

    sprintf(warn, "%-4d",rec.warning);
    sprintf(freq, "%-4d",rec.freq);
    putstr(CSR_VISIBLE);
    while(field_num < 5)
    {
	switch(field_num)
	{
	    case 0 :
		changed += edit_field(rec.date, DATE_ROW, &field_num, 5);
		break;
	    case 1 :
		changed += edit_field(rec.time, TIME_ROW, &field_num, 5);
		break;
	    case 2 :
		changed += edit_field(rec.comment, COMMENT_ROW, &field_num, 39);
		break;
	    case 3 :
		changed += edit_field(warn, WARNING_ROW, &field_num, 3);
		break;
	    case 4 :
		changed += edit_field(freq, FREQ_ROW, &field_num, 3);
		break;
	}
    }
    putstr(CSR_INVISIBLE);
    if(changed)
    {
	rec.warning = atoi(warn);
	rec.freq = atoi(freq);
	return TRUE;
    }
    return FALSE; 
}

int edit_field(str, row, next_field, size)
    char *str, *row;
    int *next_field, size;
{
    char c, field[50], save[50], line[100];
    int pos = 0, change = 0, quit = 0;
    short end;

    end = Stccpy(field, str, size+1);
    while(end <= size)
	field[end++] = ' ';
    field[end] = 0;

    strcpy(save, field);
    sprintf(line, "%s%s%s", row, field, row);
    putstr(line); 	/*  position cursor at beginning of field  */ 

    while(!quit)
    {
	c = getchar();
	switch(c)
	{
	    case SPECIAL_KEY :		/*  handle cursor keys  */
		c = getchar();
		switch(c)
		{
		    case CSR_UP :
			if( --(*next_field) < 0)	/*  wrap around  */
			    *next_field = 4;
			++quit;
			break;
		    case CSR_DN :
			if( ++(*next_field) > 4)
			    *next_field = 0;
			++quit;
			break;
		    case CSR_RT :
			if(++pos > size)	/*  wrap around to start  */
			{
			    putstr(row); 
			    pos = 0;
			}
			else
			    putstr("\x1b[1;C");
			break;
		    case CSR_LFT :
			if(--pos < 0)		/* wrap around to end  */
			{
			    sprintf(line, "%s%s%dC", row, CSI, size);
			    putstr(line);
			    pos = size;
			}
			else
			    putstr("\x1b[D");
			break;
		}
		break;
	    case CRET :
		if( ++(*next_field) > 4)
		    *next_field = 0;
		++quit;
		break;
	    case ESCAPE :
		if(pos)
		{
		    Stccpy(field, save, size + 1);
		    sprintf(line, "%s%s%s", row, field, row);
		    putstr(line); 
		    change = FALSE;
		    pos = 0;
		}
		else
		{
		    *next_field = 5;
		    ++quit;
		}
		break;
	    case TAB :		/* Insert  */
		if(pos != size)
		{
		    strins(field + pos, " ");
		    field[size+1] = 0;
		    putstr(&field[pos]);
		    putstr(row);
		    if(pos)
		    {
			sprintf(line, "%s%dC", CSI, pos);
			putstr(line);
		    }
		    change = TRUE;
		}
		break;
	    case  DELETE :
		strcpy(&field[pos], &field[pos+1]);
		field[size] = ' ';
		field[size+1] = 0;
		putstr(&field[pos]);
		putstr(row);
		if(pos)
		{
		    sprintf(line, "%s%dC", CSI, pos);
		    putstr(line);
		}
		change = TRUE;
		break;
	    case  BACK_SPACE :
	        if(pos)
	        {
		    strcpy(&field[pos-1], &field[pos--]);
		    field[size] = ' ';
		    field[size+1] = 0;
		    sprintf(line, "%s%s%s", "\x1b[D", &field[pos], row);
		    putstr(line);
		    if(pos)
		    {
			sprintf(line, "%s%dC", CSI, pos);
			putstr(line);
		    }
		    change = TRUE;
		}
		break;
	    default  :
		if(c >= SPACE && c <= '~') 
		{
		    putchar(c);
		    field[pos++] = c;
		    if(pos > size)
		    {
			putstr(row); 
			pos = 0;
		    }
		change = TRUE;
		}
		break;
	}
    }
    sprintf(line, "%s%s%s", row, NORMAL, field);
    putstr(line); 
    if(change)
    {
	end = size;		/*  strip off Padding  */
	while(end >= 0 && field[end] == ' ')
	    field[end--] = 0;

	strncpy(str, field, size + 1);
	return change;
    }

    return FALSE;
}

void add_rec()
{
    char key;

    clear_rec();
    print_rec();
    if( change_rec() )
    {
	putstr(MENU_LINE_1);
	putstr("\x1b[K\n\x1b[K\x1b[0m    \x1b[7mOK to ADD Record ?\x1b[0m  ");
	if( (key = getchar()) == 'y' || key == 'Y' || key == CRET)
	{
	    lseek(File, 0, 2);
	    write( File, (char *) &rec, sizeof(EVENT) );
	}
    }
    print_menu();
}

void clear_rec()
{
    int i = 0;

    while(i < 51)
	rec.date[i++] = 0;
    rec.warning = 0;
    rec.freq = 0;
}

void print_menu()
{
    putstr(MENU_LINE_1);
    putstr(MENU_LINE_2);
    putstr(MENU_LINE_3);
}

void print_rec()
{
    char line[80];

    sprintf(line, "%s        Date         :  %-6.6s", SETUP, rec.date);
    putstr(line);

    sprintf(line, "\n        Time         :  %-6.5s", rec.time);
    putstr(line);

    sprintf(line, "\n        Event        :  %-40.40s", rec.comment);
    putstr(line);

    sprintf(line, "\n        Days Warning :  %-4d", rec.warning);
    putstr(line);

    sprintf(line, "\n        Frequency    :  %-4d", rec.freq);
    putstr(line);
}

int Stccpy(to, from, limit)
    char *to, *from;
    int limit;
{
    int i = 0;

    while(*from && i < limit)
    {
	*to++ = *from++;
	++i;
    }
    *to = 0;
    return i;
}
