
/***************************************************************************
 *   Copyright (C) 1997 to 2004 by Jonathan Duddington                     *
 *   email: jonsd@users.sourceforge.net                                    *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 3 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write see:                           *
 *               <http://www.gnu.org/licenses/>.                           *
 ***************************************************************************/

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>

#include "werr.h"
#include "bbc.h"
#include "menu.h"
#include "dbox.h"
#include "narc.h"
#include "hdrs.h"

int  fopen_errnum=0;

static visdelay_value=-2;
static visdelay_showing = 0;


unsigned int gethash32(char *string)
/**********************************/
/* 32 bit hash function on a string. Use for msgids */
{
	char *p;
	unsigned int  acc=0;
	unsigned int  acc2=0;
	int  carry;
	int  c;

	if((p = string) == NULL)
		return(0);

	while((c = *p++) != 0)
	{
		carry = (acc2) & 0x1f;
		acc2 = (acc2 << 5) | (acc >> 27);
		acc = ((acc << 5) + c) ^ carry;

	}

	if((acc == 0) && (string[0] != 0))
		return(gethash32(&string[1]));   /* try again to get a non-zero result */

	return(acc);
}   /* end of gethash32 */




void visdelay2_begin()
/********************/
{
	os_swi1(0x406c0,0);   /* Hourglass_On */
	visdelay_showing = 1;
	visdelay_value = -1;
}   /* end of visdelay2_begin */

void visdelay2_end()
/******************/
{
	os_swi1(0x406c1,0);   /* Hourglass_Off */
	visdelay_showing = 0;
	visdelay_value = -2;
}   /* end of visdelay2_end */


void visdelay2_percent(int percent)
/*********************************/
{
	os_swi1(0x406c4,percent);   /* Hourglass_Percentage */
	visdelay_value = percent;
}   /* end of visdelay2_percent */


void visdelay2_leave()
/********************/
{
	if(visdelay_value >= -1)
		os_swi1(0x406c1,0);    /* Hourglass_Off */
	visdelay_showing = 0;
}   /* end of visdelay2_enter */


void visdelay2_enter()
/********************/
{
	if(visdelay_showing)
		return;

	if(visdelay_value >= -1)
	{
		os_swi1(0x406c3,1);   /* Hourglass_Start */
		visdelay_showing = 1;
	}

	if(visdelay_value >= 0)
		os_swi1(0x406c4,visdelay_value);   /* Hourglass_Percentage */
}   /* end of visdelay2_enter */





int memcmp_lc(char *p1, char *p2, int n)
/**************************************/
{
	int  i;
	int  x;

	for(i=0; i<n; i++)
	{
		if((x = (tolower(p1[i]) - p2[i])) != 0)
			return(x);
	}
	return(0);
}   /* end of memcmp_lc */




int memcmp_lc2(char *p1, char *p2, int n)
/**************************************/
{
	int  i;
	int  x;

	for(i=0; i<n; i++)
	{
		if((x = (tolower(p1[i]) - tolower(p2[i]))) != 0)
			return(x);
	}
	return(0);
}   /* end of memcmp_lc2 */


char chars_lc[256] = {
	0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,
	16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,

	32,33,34,35,36,37,38,39,40,41,42,43,44,45,46,47,
	48,49,50,51,52,53,54,55,56,57,58,59,60,61,62,63,

	'@','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
	'p','q','r','s','t','u','v','w','x','y','z','[','\'',']','^','_',

	'`','a','b','c','d','e','f','g','h','i','j','k','l','m','n','o',
	'p','q','r','s','t','u','v','w','x','y','z','{','|','}','~',127,

	128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143,
	144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159,

	160,161,162,163,164,165,166,167,168,169,170,171,172,173,174,175,
	176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191,

	'a','a','a','a','a','a','a','c','e','e','e','e','i','i','i','i',
	'd','n','o','o','o','o','o',0xd7,'o','u','u','u','u',0xdd,0xde,0xdf,

	'a','a','a','a','a','a','a','c','e','e','e','e','i','i','i','i',
	'd','n','o','o','o','o','o',0xf7,'o','u','u','u','u',0xfd,0xfe,0xff
};


int strcmp_lc(char *s1, char *s2)
/*****************************/
/* Strcmp but ignore case, also remove accents */
{
	while(chars_lc[*s1] ==  chars_lc[*s2])
	{
		if(*s1 == 0)
			return(0);
		s1++;
		s2++;
	}
	return(chars_lc[*s1] - chars_lc[*s2]);
}   /* end of strcmp_lc */



int Xstrcmp_lc(char *s1, char *s2)
/*******************************/
{
	os_regset regs;

	regs.r[0] = -1;
	regs.r[1] = (int)s1;
	regs.r[2] = (int)s2;
	regs.r[3] = 3;   /* ignore case and accents */

	os_swi(0x4305d,&regs);  /* Territory_Collate */
	return(regs.r[0]);
}   /* end of strcmp_lc */




void strcpy_lc(char *dest, char *string)
/**************************************/
/* Convert string to lower case */
{
	int  c;

	do {
		c = *string++;
		*dest++ = tolower(c);
	} while(c != 0);

}   /* end of strcpy_lc */




void strcpy_no_accents(char *dest, char *string)
/**********************************************/
/* Convert string to lower case and remove accents */
{
	int  c;

	do {
		c = *string++;
		*dest++ = chars_lc[c];
	} while(c != 0);

}   /* end of strcpy_no_accents */




void strncpy0(char *dest, char *src, int len)
/*******************************************/
/* strncpy with but ensure a zero byte terminator */
{
	strncpy(dest,src,len);
	dest[len-1] = 0;
}   /* end of strncpy0 */



void copy_unfold(char *out,int max,char *src, int length)
/***************************************************/
/* Copy from src to out, deleting NL and following spaces */
{
	int  i;
	int  c;
	char *end;

	end = &out[max-1];

	for(i=0; i<length; i++)
	{
		c = src[i];
		if(c == '\n')
		{
			if(out < end)
				*out++ = ' ';
			while(isspace(c = src[i]) && (i < length))
				i++;
		}

		if(out < end)
			*out++ = c;
	}
	*out = 0;
}   /* end of copy_unfold */



void beep()
/*********/
{
	bbc_vdu(7);
}   /* end of beep */


int hexdig(int c)
/***************/
{
	if(isdigit(c))
		return(c-'0');
	else if(c >= 'a')
		return(c-'a'+10);
	else
		return(c-'A'+10);
}   /* end of hexdig */


int read_hex(char *p)
/*******************/
/* read hex number terminated by non-alpha-numeric */
{
	int  i;
	int  c;
	int  value;
	char buf[12];

	while(*p <= ' ') p++;

	for(i=0; i<(sizeof(buf)-1); i++)
	{
		c = buf[i] = p[i];
		if(!isalnum(c))
			break;
	}
	buf[i] = 0;
	i = sscanf(buf,"%x",&value);
	if(i == 1)
		return(value);
	else
		return(-1);
}   /* end of read_hex */


int search_string(char *string, int length, char **anchor, int from, int len, int case_sensitive)
/**************************************************************************************/
/* Find index position for specified string within text.
   # matches any character
   space matches space, \n, -, or -\n
*/
{
	int  i;
	char *p;
	char *end;
	int  c;
	char *p_start;
	char *p2;

	if(length <= 0)
		return(-1);

	p = p_start = *anchor + from;

	if(len >= 0)
		end = p + len;
	else
		end = p + strlen(p);

	if(!case_sensitive)
	{
		while(p != end)
		{
			p2 = NULL;
			if((chars_lc[p[0]] == string[0]) || ((string[0] == ' ') && (p[0] < ' ')))
			{
				p2 = p;
			}
			else if((string[0] == ' ') && (p == p_start))
			{
				p2 = p - 1;
			}

			if(p2)
			{
				for(i=1; i<length; i++)
				{
					if(((c = chars_lc[p2[i]]) == string[i]) || (string[i] == '#'))
						continue;

					if(string[i] == ' ')
					{
						if(c < ' ')
							continue;


						if(c == '-')
						{
							if(p2[i+1] == '\n')
								i++;
							continue;
						}
					}
					break;
				}
				if(i == length)
				{
					/* found a match */
					return(p - *anchor);
				}
			}
			p++;
		}
	}
	else
	{
		/* case sensitive */
		while(p != end)
		{
			p2 = NULL;
			if((p[0] == string[0]) || ((string[0] == ' ') && (p[0] < ' ')))
			{
				p2 = p;
			}
			else if((string[0] == ' ') && (p == p_start))
			{
				p2 = p - 1;
			}

			if(p2)
			{
				for(i=1; i<length; i++)
				{
					if(((c = p2[i]) == string[i]) || (string[i] == '#'))
						continue;

					if(string[i] == ' ')
					{
						if(c < ' ')
							continue;

						if(c == '-')
						{
							if(p2[i+1] == '\n')
								i++;
							continue;
						}
					}
					break;
				}
				if(i == length)
				{
					/* found a match */
					return(p - *anchor);
				}
			}
			p++;
		}
	}
	return(-1);
}   /* end of search_string */




char *get_message_id(int add_name, int type)
/******************************************/
/* Make unique name, based on the current time
   add_name 0:  return 10 digit number
            2:  filename in wimp$scrapdir

   type  0  8  News
         1  9  Mail
         2  10 Ack
         3  11 Bounce
         4  12 Broadcast
         5  13 Digest

         bit 3 indicates an attachment
*/
{
	unsigned int  *p;
	char date_buf[5];
	os_regset regs;
	static unsigned int timestamp=0;
	static char message_id[80];


	regs.r[0] = 14;       /* OS_Word 14,3 */
	regs.r[1] = (int)date_buf;
	date_buf[0] = 3;      /* reason code */
	os_swi(0x07,&regs);

	p = (unsigned int *)date_buf;
	if(*p <= timestamp) *p = timestamp+1;  /* make sure it's different from the last one */
	timestamp = *p;

	if(add_name==2)
	{
		sprintf(message_id,"<Wimp$ScrapDir>.Pluto.%.8x",timestamp);
	}
	else
	{
#ifdef deleted
//no longer beed X_POP
		if(((type & 0x7) != 0) && (options.mail_transport == X_POP))
		{
			sprintf(message_id,"%.7x",timestamp & 0xfffffff);   /* restrict to 7 chars with POP */
		}
		else
#endif
		{
			sprintf(message_id,"%.2x%.8x",date_buf[4],timestamp);
		}

		if(type > 1)
		{
			message_id[0] = 'Z' - (type - 2);
		}
	}
	return(message_id);
}   /* end of get_message_id */



char *get_temp_fname()
/********************/
/* Give a unique filename in wimp$scrapdir */
{
	return(get_message_id(2,0));
}  /* end of get_temp_fname */





FILE *fopen_werr(char *path,char *access, char *name)
/***************************************************/
/* Open file and show error message if it fails */
{
	FILE *f;
	_kernel_oserror *error;

	if(name == NULL)
		name = "";

	fopen_errnum = 0;

	error = _kernel_last_oserror();
	if(error!=NULL)
		error->errnum=0;

	f = fopen(path,access);
	if((f == NULL) && (memcmp_lc(path,"<wimp$scrapdir>.pluto",21)==0))
	{
		/* create scrap dir and try again */
		os_cli("cdir <Wimp$ScrapDir>.Pluto");
		f = fopen(path,access);
	}

	if(f == NULL)
	{
		error = _kernel_last_oserror();
		if(error != NULL)
		{
			fopen_errnum = error->errnum;

			if(strstr(error->errmess,path)!=NULL)
				werr(0,"%s",error->errmess);   /* error message already contains Path */
			else
				werr(0,"%s. %sFile %s",error->errmess,name,path);
		}
		else
		{
			if(access[0] == 'w')
				werr(0,"Can't write to %sfile %s",name,path);
			else
				werr(0,"Can't read %sfile %s",name,path);
		}
	}
	return(f);
}   /* end of fopen_werr */




FILE *fopen_werr_pluto(char *path,char *access, char *name)
/*********************************************************/
{
	char path2[80];

	sprintf(path2,"%s%s",pluto_path,path);
	return(fopen_werr(path2,access,name));
}   /* end of fopen_werr_pluto */




FILE *fopen_pluto(char *path,char *access)
/****************************************/
{
	char path2[80];

	sprintf(path2,"%s%s",pluto_path,path);
	return(fopen(path2,access));
}   /* end of fopen_werr */





int fwrite_werr(void *p, int size, int num, FILE *f)
/**************************************************/
{
	char *string;
	_kernel_oserror *error;

	if(fwrite(p,size,num,f) != num)
	{
		if((error = _kernel_last_oserror()) != NULL)
			string = error->errmess;
		else
			string = "";
		werr(0,"Error during Save. %s",string);
		return(-1);
	}
	return(0);
}   /* end of fwrite_err */





void file_delete(char *path)
/**************************/
{
	os_swi4(0x29+os_X,27,(int)path,0,0);        /* OS_FSControl 27, wipe */
}   /* end of file_delete */



os_error *file_copy(char *from, char *to)
/***************************************/
{
	return(os_swi4(0x29+os_X,26,(int)from,(int)to,0x2));   /* OS_FSControl 26, copy, bit 1=force overwrite */
}   /* end of file_copy */



os_error *file_move(char *from, char *to)
/***************************************/
{
	os_error *error;

	error = os_swi4(0x29+os_X,25,(int)from,(int)to,0);   /* OS_FSControl 25, rename */
	if(error)
	{
		if(error->errnum==214)
		{
			/* "Not found" */
			return(NULL);
		}

		error = os_swi4(0x29+os_X,26,(int)from,(int)to,0x82);   /* OS_FSControl 26, copy, bit 7=delete source */
	}
	if(error != NULL)
	{
		werr(0,"Failed to move file from: '%s' to: '%s' reason: %s",from,to,error->errmess);
	}
	return(error);
}   /* end of file_move */




