/* --------------------------------------------*\
| ui_text.c (version 1.3) - (C) SichemSoft 1994 |
| Roghorst 160, 6708 KS Wageningen, Netherlands |
| module  for language independent applications |
| author: Anneke Sicherer-Roetman, date: 940311 |
\* --------------------------------------------*/

/*
**
** - changed the delimiter for filenames to / (slash)
**   this may be fixed in the next version
** - the open mode of the .etf file is changed
** The original lines are marked with   original 
** please note also the changes in lingua.h
**   Frank Tegtmeyer (fte@gecko.de)
**
*/


#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include "lingua.h"
#include "files.inc"

char **ui_text;                       /* pointers into memory text buffer */
unsigned _ui_memcount,_ui_filcount;   /* undocumented global variables */
static char *ui_textbuffer;           /* memory text buffer */
static unsigned long *ui_file;        /* pointers into file */
static char *ui_filebuffer;           /* file text buffer */
static char **ui_fileptr;             /* pointers into array from file */
static unsigned itemchecksum=0;       /* for checksumming file items */

/* converts string to all lower case (common ANSI extension) */
static char *strlwr(char *s)
{
   char *p;
   for (p=s; *s; s++) if (isupper(*s)) *s=tolower(*s);
   return p;
}

/* decrypts text and computes checksum */
static unsigned decrypt(char *buffer,unsigned long size)
{
   register unsigned long offset;
   unsigned checksum;
   char *q;

   for (offset=0,checksum=0,q=buffer; offset<size; offset++,q++) {
      *q^=UIT_ENCRYPT; checksum+=(unsigned char)(*q);
   }
   return checksum;
}

/* loads text from file into ui_filebuffer */
static char *loadtext(unsigned long pos,unsigned size)
{
   static unsigned long oldpos=(unsigned long)(-1L);

   if (pos==oldpos) return ui_filebuffer;
   if (!fileseek(pos)) return NULL;
   if (ui_filebuffer) free(ui_filebuffer);
   ui_filebuffer=(char *)malloc(size*sizeof(char));
   if (!ui_filebuffer) return NULL;
   if (!fileread(ui_filebuffer,size*sizeof(char))) return NULL;
   itemchecksum=decrypt(ui_filebuffer,size);
   oldpos=pos; /* next time only load if necessary */
   return ui_filebuffer;
}

/* loads text (no array) from file into ui_filebuffer */
/* note: the programmer should not call this routine directly */
char *ui_filetext(unsigned pos)
{
   return loadtext(ui_file[pos],ui_file[pos+1]-ui_file[pos]);
}

/* loads text array from file into ui_filebuffer */
/* note: the programmer should not call this routine directly */
char **ui_filearray(unsigned pos)
{
   unsigned size; register int i;

   if (!fileseek(ui_file[pos])) return NULL;
   if (!fileread(&size,sizeof(size))) return NULL;
   if (!loadtext(filetell(),ui_file[pos+size]-ui_file[pos]-sizeof(size)))
      return NULL;
   if (ui_fileptr) free(ui_fileptr);
   ui_fileptr=(char **)malloc(size*sizeof(char*));
   if (!ui_fileptr) return NULL;
   ui_fileptr[0]=ui_filebuffer;
   for (i=1; i<size; i++)
      ui_fileptr[i]=ui_filebuffer+ui_file[pos+i]-ui_file[pos]-sizeof(size);
   return ui_fileptr;
}

/* opens file, loads text and offsets into memory */
/* call this routine at the very beginning of the application */
int ui_loadtext(char *fname,char *vers)
/* fname is name of desired .etf file without extension
   vers is optional version number, may also be "" */
{
   char *q;
   unsigned len,i;
   unsigned checksum,checksum1=0,checksum2=0;
   char buf[256],file[81];
   unsigned long offset,size;

   if (ui_text || ui_file) return FALSE;

   /* open encrypted text file */
   strcpy(file,fname);
   if (!strchr(file,'.')) strcat(file,".etf");
/*   if (fileopen(file)) return FALSE;  original line */
   if ((fp=fopen(file,readRO))==0) return FALSE;

   /* read file header */
   if (!vers) vers="";
/* q=strrchr(file,'\\'); if (q) q++; else q=file;  original line */
   q=strrchr(file,'/'); if (q) q++; else q=file;
   len=strlen(q)+strlen(vers);
   if (!fileread(buf,(len+1)*sizeof(char))) return FALSE;
   strlwr(buf); strlwr(q); strlwr(vers);
   if (strncmp(buf,q,strlen(q))) return FALSE;
   if (strncmp(buf+strlen(q),vers,strlen(vers))) return FALSE;

   /* read number of items */
   if (!fileread(&checksum,sizeof(checksum))) return FALSE;
   if (!fileread(&_ui_memcount,sizeof(_ui_memcount))) return FALSE;
   if (!fileread(&_ui_filcount,sizeof(_ui_filcount))) return FALSE;
   if (!fileread(&size,sizeof(size))) return FALSE;
   if (_ui_memcount) {
      /* reserve space */
      ui_text=(char **)malloc(_ui_memcount*sizeof(char *));
      if (!ui_text) return FALSE;
      ui_textbuffer=(char *)malloc(size*sizeof(char));
      if (!ui_textbuffer) return FALSE;

      /* read offsets and compute pointers */
      for (i=0; i<_ui_memcount; i++) {
         if (!fileread(&offset,sizeof(offset))) return FALSE;
         ui_text[i]=ui_textbuffer+offset;
      }
   }

   if (_ui_filcount) {
      /* reserve space */
      ui_file=(unsigned long *)malloc((_ui_filcount+1)*sizeof(unsigned long));
      if (!ui_file) return FALSE;

      /* read offsets of file items */
      for (i=0; i<_ui_filcount+1; i++) {
         if (!fileread(&offset,sizeof(offset))) return FALSE;
         ui_file[i]=offset;
      }
   }

   if (_ui_memcount) {
      /* read text lines and decrypt */
      if (!fileread(ui_textbuffer,size*sizeof(char))) return FALSE;
      checksum1=decrypt(ui_textbuffer,size);
   }

   if (_ui_filcount) {
      /* read file items and decrypt for checksumming */
      for (i=0; i<_ui_filcount; i++) {
         q=ui_filetext(i); if (!q) return FALSE;
         checksum2+=itemchecksum;
      }
   }

   /* close file if no file items present */
   if (!_ui_filcount) fileclose();

   /* succesful load if checksum is ok */
   return (checksum==checksum1+checksum2);
} /* ui_loadtext */

/* frees all space and closes file if necessary */
/* call this routine at the very end of the application */
void ui_unloadtext(void)
{
   if (ui_text) { free(ui_text); ui_text=NULL; }
   if (ui_textbuffer) { free(ui_textbuffer);  ui_textbuffer=NULL; }
   if (ui_file) { free(ui_file); ui_file=NULL; }
   if (ui_filebuffer) { free(ui_filebuffer); ui_filebuffer=NULL; }
   if (ui_fileptr) { free(ui_fileptr); ui_fileptr=NULL; }
   fileclose();
} /* ui_unloadtext */

