/**********************************************/
/*           English Clock 8.5                */
/*           ==================               */
/*                                            */
/*          Coding: Ben Matthew               */
/*            Date: (C) 1996                  */
/*                                            */
/*  based on an UNIX program of similar name  */
/*                                            */
/*    Compiled using SAS/C  by the SAS        */
/*               Institute                    */
/*                                            */
/**********************************************/

static char *vers="$VER: English Clock 8.5 © Ben Matthew (19.05.96)";

#include "globals.h"

/* #define DEBUG_CODE */

BOOL cxsucc, rexxsucc, snsucc;
BOOL reset_all=FALSE;
BOOL no_reset_font=FALSE;

int winx, winy, winh, winw;

long mytextlength(char *string, long len);

extern __near char *__procname="EngClock_8.5";

/********* Main loop *************/

struct TimerDev *my_timer;

short main(int argc, char *argv[]) {
	long sig, winsig, totalsig;
	long cxsig, id, hot1sig, hot2sig, rexxsig, snsig;
	/* Stuff for IDCMP */
	ULONG class;
	USHORT code;
	/* Misc */
	BOOL flag1=FALSE;
	int mem1=70, mem2=70;
	char newline[500];
	BOOL shutdown=FALSE;

	openall();    /* Opens all the libraries required */

	/* Get a lock on the screen we want to open the win on.. */
	/* This lock will be held until we close to avoid nasty crashing ! */

	readprefs();
	loadsnap();
	process_args(argc, argv);

	pubscreen=LockPubScreen(prefs.pub);
	if(!pubscreen) {
		msg(GetCatalogStr(catalog,0,"Cannot lock specified public screen!"));
		pubscreen=LockPubScreen(NULL);
		if(!pubscreen) {
			msg(GetCatalogStr(catalog,1,"Cannot lock Workbench!"));
			closeall();
			return(0);
		}
	} 

	getscreentype(); /* Set up screentype structure */
	getfont();    /* Sets up the font structure */
	getlocale();  /* Sets up the preferred language */
	setupmainwindow(); /* Sets up the win1 NewWindow structure */
	changemenu(); /* Changes the menuitem structures to account font size */
	
	/* Now lets set up LangModBase */

	if(1) {
		char name[100];
		char tmp[80];
		char m[500];
		
		strcpy(name,MOD_PATH);
		sprintf(tmp,"%s.langmod",chosen_lang->name);
		strcat(name,tmp);
	
		LangModBase=OpenLibrary(name,0);
		
		if(!LangModBase) {
			sprintf(m,"%s %s\n",name,GetCatalogStr(catalog,2,"failed to open!"));
			msg(m);
		}
	
	}
	

	
	win_p = (struct Window *) OpenWindow ( &win1 );
	if(!win_p) {
		msg(GetCatalogStr(catalog,3,"Unable to open window!"));
		closeall();
		return(0);
	}
	SetMenuStrip(win_p,&menu1);
	if(win_font) SetFont(win_p->RPort,win_font);

	ispicture=loadpic(prefs.backdrop,pubscreen);

	/* Set up my timer.device look-a-like */
	
	my_timer=GoTimer(100);	
	if(!my_timer) {
		msg(GetCatalogStr(catalog,4,"Oops, couldn't set up a timer!"));
		closeall();
		return(0);
	}

	
	/* End of timer bits */

	exit_flag=FALSE;
	winsig=1<<win_p->UserPort->mp_SigBit;
	totalsig=winsig|my_timer->sig;

	cxsucc=cxinit();
	rexxsucc=arexxinit();
	snsucc=sninit();
	
	if(cxsucc) {
		cxsig=1<<CxMsgPort->mp_SigBit;
		hot1sig=1<<CxHotKey1->mp_SigBit;
		hot2sig=1<<CxHotKey2->mp_SigBit;
		totalsig=totalsig|hot1sig|hot2sig|cxsig;
	}
	if(rexxsucc) {
		rexxsig=1<<RexxPort->mp_SigBit;
		totalsig=totalsig|rexxsig;
	}
	if(snsucc) {
		snsig=1<<SNPort->mp_SigBit;
		totalsig=totalsig|snsig;
	}
	
	gettime();
	refreshwindow();
	
	while(exit_flag==FALSE) {
		sig=Wait(totalsig);
		
		if(sig==my_timer->sig) {
			process_arexx(); // To avoid some nasty provlems with Engprefs

			gettime(); /* Set up the time structure */

			/* Make sure that at least one minute has passed before
			refreshing the window or if language changed. */
	
			flag1=FALSE;

			if(time.hours!=mem2) flag1=TRUE;
			if(time.minutes!=mem1) flag1=TRUE;
			if(!flag1) goto break_away;
			mem1=time.minutes; mem2=time.hours;
	
			refreshwindow();
			goto break_away;
		}  

		if(sig==winsig) {
			while(message = (struct IntuiMessage *)GetMsg(win_p->UserPort)) {
				class=message->Class; code=message->Code;
				ReplyMsg((struct Message *)message);


				/* Now lets see what IDCMP message was sent: */
				switch (class) {
					case CLOSEWINDOW:
						shutdown=TRUE;
					break;
					case NEWSIZE:
						if(win_p) refreshwindow();
					break;
					case MENUPICK:
						if(!win_p) break;
						switch(ITEMNUM(code)) {
							case 0: /* Prefs  */
								system("run <>nil: engprefs");
							break;
							case 1: /* Snapshot */
								savesnap();
							break;
							case 2: /* Jump */
								jump();
								refreshwindow();
							break;
							case 3: /* About */
								about();
							break;
							case 4: /* Quit */
								exit_flag=TRUE;
							break;
						}
					break;
				} /* End of Switch */
			} /* End of while (GetMsg bit) */
		}

		if(sig==cxsig) {
			while(CxMessage=(CxMsg *)GetMsg(CxMsgPort)) {
				id=CxMsgID(CxMessage);
				ReplyMsg((struct Message *)CxMessage);
				
				switch(id) {
					case CXCMD_KILL:
						exit_flag=TRUE;
					break;
					case CXCMD_APPEAR:
						if(!win_p) {
							if(!pubscreen) {
								pubscreen=LockPubScreen(prefs.pub);
								if(!pubscreen) {
									msg(GetCatalogStr(catalog,0,"Cannot lock specified public screen!"));
									pubscreen=LockPubScreen(NULL);
									if(!pubscreen) {
										msg(GetCatalogStr(catalog,1,"Cannot lock Workbench!"));
										closeall();
										return(0);
									}
								} 
							}
							win1.Screen=pubscreen;
							win_p=OpenWindow(&win1);
							if(win_font) SetFont(win_p->RPort,win_font);
							winsig=1<<win_p->UserPort->mp_SigBit;
							totalsig=winsig|my_timer->sig;
							if(cxsucc) totalsig=totalsig|hot1sig|hot2sig|cxsig;
							if(rexxsucc) totalsig=totalsig|rexxsig;
							if(snsucc) totalsig=totalsig|snsig;
							SetMenuStrip(win_p,&menu1);
							ispicture=loadpic(prefs.backdrop,pubscreen);
							refreshwindow();
						} else
							WindowToFront(win_p);
					break;
					case CXCMD_DISABLE:
						// Wait for a CXCMD_ENABLE msg
						while(1) {
							WaitPort(CxMsgPort); 
							CxMessage=(CxMsg *)GetMsg(CxMsgPort);
							id=CxMsgID(CxMessage);
							ReplyMsg((struct Message *)CxMessage);
							if(id==CXCMD_ENABLE) break;
						}		
					break;
					case CXCMD_DISAPPEAR:
						shutdown=TRUE;
					break;
					default:
					break;
				}
			}
		}
	
		if(sig==hot1sig) {
			// Speak to me!
			CxMessage=(CxMsg *)GetMsg(CxHotKey1);
			if(CxMessage) ReplyMsg((struct Message *)CxMessage);
			strcpy(newline,line1);
			if(!strcmp(chosen_lang->name,"english")) newline[strlen(newline)-4]=NULL;  /* Get rid of pm/am */
			strcat(newline,".  ");
			if(prefs.date) {
				strcat(newline,line2);
				newline[strlen(newline)-6]=NULL; /* Get rid of year */
			}
			talk(trans(newline));
		}		

		if(sig==hot2sig) {
			// Open window
			CxMessage=(CxMsg *)GetMsg(CxHotKey2);
			if(CxMessage) ReplyMsg((struct Message *)CxMessage); 
			if(!win_p) {
				if(!pubscreen) {
					pubscreen=LockPubScreen(prefs.pub);
					if(!pubscreen) {
						msg(GetCatalogStr(catalog,0,"Cannot lock specified public screen!"));
						pubscreen=LockPubScreen(NULL);
						if(!pubscreen) {
							msg(GetCatalogStr(catalog,1,"Cannot lock Workbench!"));
							closeall();
							return(0);
						}
					} 
				}
				win1.Screen=pubscreen;
				win_p=OpenWindow(&win1);
				if(win_font) SetFont(win_p->RPort,win_font);
				winsig=1<<win_p->UserPort->mp_SigBit;
				totalsig=winsig|my_timer->sig;
				if(cxsucc) totalsig=totalsig|hot1sig|hot2sig|cxsig;
				if(rexxsucc) totalsig=totalsig|rexxsig;
				if(snsucc) totalsig=totalsig|snsig;
				SetMenuStrip(win_p,&menu1);
				ispicture=loadpic(prefs.backdrop,pubscreen);
				refreshwindow();
			} else
				WindowToFront(win_p);
		}

		if(sig==rexxsig)
			process_arexx();
			
		if(sig==snsig) {
			struct ScreenNotifyMessage *snmsg;
			
			while(snmsg=(struct ScreenNotifyMessage *)GetMsg(SNPort)) { 
				if(snmsg->snm_Type == SCREENNOTIFY_TYPE_WORKBENCH) {
					switch((int)snmsg->snm_Value) {
						case FALSE: /* Close */
							shutdown=TRUE;
							DisplayBeep(NULL);
						break;
						case TRUE: /* Open */
							if(!win_p) {
								if(!pubscreen) {
									pubscreen=LockPubScreen(prefs.pub);
									if(!pubscreen) {
										msg(GetCatalogStr(catalog,0,"Cannot lock specified public screen!"));
										pubscreen=LockPubScreen(NULL);
										if(!pubscreen) {
											msg(GetCatalogStr(catalog,1,"Cannot lock Workbench!"));
											closeall();
											return(0);
										}
									} 
								}
								win1.Screen=pubscreen;
								win_p=OpenWindow(&win1);
								if(win_font) SetFont(win_p->RPort,win_font);
								winsig=1<<win_p->UserPort->mp_SigBit;
								totalsig=winsig|my_timer->sig;
								if(cxsucc) totalsig=totalsig|hot1sig|hot2sig|cxsig;
								if(rexxsucc) totalsig=totalsig|rexxsig;
								if(snsucc) totalsig=totalsig|snsucc;
								SetMenuStrip(win_p,&menu1);
								ispicture=loadpic(prefs.backdrop,pubscreen);
								refreshwindow();
							}
						break;
					}
				}
				if(snmsg->snm_Type == SCREENNOTIFY_TYPE_CLOSESCREEN)
					exit_flag=TRUE;				

				ReplyMsg((struct Message *)snmsg);
			}
		}
			
		if(reset_all) {
	
			reset_all=FALSE;
			if(!win_p) goto break_away;
		
			// shut down
			if(ispicture) { unloadpic(piccy); ispicture=FALSE; }
			ClearMenuStrip(win_p);
			win1.Width=win_p->Width;
			win1.Height=win_p->Height;
			win1.TopEdge=win_p->TopEdge;
			win1.LeftEdge=win_p->LeftEdge;
			CloseWindow(win_p);
			if(cxsucc) cxclose();
			if(rexxsucc) arexxclose();
			if(snsucc) snclose();


			// start up
			if(no_reset_font) {
				no_reset_font=FALSE;
			}
			else
				readprefs();
				
			loadsnap();

			getfont();
			setupmainwindow();
			win_p=OpenWindow(&win1);
			if(win_font) SetFont(win_p->RPort,win_font);
			changemenu();
			SetMenuStrip(win_p,&menu1);
			ispicture=loadpic(prefs.backdrop,pubscreen);
			refreshwindow();
			
				
			// reinitiate some variables

			exit_flag=FALSE;
			winsig=1<<win_p->UserPort->mp_SigBit;
			totalsig=winsig|my_timer->sig;

			cxsucc=cxinit();
			rexxsucc=arexxinit();
			snsucc=sninit();
	
			if(cxsucc) {
				cxsig=1<<CxMsgPort->mp_SigBit;
				hot1sig=1<<CxHotKey1->mp_SigBit;
				hot2sig=1<<CxHotKey2->mp_SigBit;
				totalsig=totalsig|hot1sig|hot2sig|cxsig;
			}
			if(rexxsucc) {
				rexxsig=1<<RexxPort->mp_SigBit;
				totalsig=totalsig|rexxsig;
			}
			if(snsucc) {
				snsig=1<<SNPort->mp_SigBit;
				totalsig=totalsig|snsig;
				
			}
		
		}
		
		if(shutdown) {
			shutdown=FALSE;
			if(!cxsucc) exit_flag=TRUE;
			else {
				win1.Width=win_p->Width;
				win1.Height=win_p->Height;
				win1.TopEdge=win_p->TopEdge;
				win1.LeftEdge=win_p->LeftEdge;
				if(ispicture) { unloadpic(piccy); ispicture=FALSE; }
				ClearMenuStrip(win_p);
				CloseWindow(win_p);
				UnlockPubScreen(NULL,pubscreen);
				win_p=NULL;
				pubscreen=NULL;
			}
		}
				
		
		break_away:
	}    /* End of while we havent quited bit */

	quitbit:

	closeall();
	
	return(0);

} /* End of main() */


void gettime(void) {

/*****************************************/
/*          Gettime() function           */
/*          ==================           */
/*                                       */
/*        By Ben Matthew (C) 1995        */
/*                                       */
/*  Gettime() sets up the time structure */
/*  according to the time stamp on the   */
/*  IntuiMessage IntuiTicks bit          */
/*                                       */
/*****************************************/

	ULONG seconds,micros;
	struct ClockData clock;

	CurrentTime(&seconds,&micros);
	Amiga2Date(seconds,&clock);    /* Utility.library function */

	time.seconds=clock.sec;
	time.hours=clock.hour;
	time.minutes=clock.min;
	time.months=clock.month;
	time.years=clock.year;
	time.days=clock.mday;
	time.wday=clock.wday;
}

short readprefs(void) {
   int bytes=0, i;

   handle=Open(PREFS_FILE,MODE_OLDFILE);
   if(!handle) {
   		msg(GetCatalogStr(catalog,5,"oops, no prefs file!"));
      /* Preferences file NOT found, so set default settings... */
      strcpy(prefs.planguage.name,"english");
      for(i=0; i<8; i++) {
         prefs.date_col[i]=1;
         prefs.time_col[i]=1;
      }
     prefs.just=0;
		for(i=1; i<11; i++) {
			prefs.events[i].used=FALSE;
			prefs.events[i].type=0;
			prefs.events[i].hours=1;
			prefs.events[i].minutes=0;
			prefs.events[i].timecode=1;
			strcpy(prefs.events[i].message,"");
			prefs.events[i].day=1;
			prefs.events[i].month=1;
			prefs.events[i].year=1995;
   	}
		prefs.date=FALSE;
		prefs.wtf=FALSE;
		prefs.autoadjust=FALSE;
		strcpy(prefs.backdrop,"");
		strcpy(prefs.pub,"");
		strcpy(prefs.accent,"locale:accents/english.accent");
		strcpy(prefs.hkey,"CONTROL ALT e");
		strcpy(prefs.tkey,"HELP");
      return(0);
   }
   /* If not returned by now, preferences file is open! */

   bytes=FRead(handle,(char *)&prefs,1,sizeof(struct Prefs));
   if(bytes!=sizeof(struct Prefs)) {
      /* Error reading prefs file */
      DisplayBeep(NULL);
      /* Set the default settings */
      strcpy(prefs.planguage.name,"english");
      for(i=0; i<8; i++) {
         prefs.date_col[i]=1;
         prefs.time_col[i]=1;
      }
      prefs.just=0;
		for(i=1; i<11; i++) {
			prefs.events[i].used=FALSE;
			prefs.events[i].type=0;
			prefs.events[i].hours=1;
			prefs.events[i].minutes=0;
			prefs.events[i].timecode=1;
			strcpy(prefs.events[i].message,"");
			prefs.events[i].day=1;
			prefs.events[i].month=1;
			prefs.events[i].year=1995;
   	}
		prefs.date=FALSE;
		prefs.wtf=FALSE;
		prefs.autoadjust=FALSE;
		strcpy(prefs.backdrop,"");
		strcpy(prefs.pub,"");
		strcpy(prefs.accent,"locale:accents/english.accent");
		strcpy(prefs.hkey,"CONTROL ALT e");
		strcpy(prefs.tkey,"HELP");
	}
   if(strcmp(prefs.header,ID)) {
   	DisplayBeep(NULL);
   	msg(GetCatalogStr(catalog,6,"Error: Corrupt preferences header!"));
   }
   Close(handle);
   return(0);
}

void getfont(void) {

/***************************************************/
/*              Get Font Dimensions                */
/*              ===================                */
/*                                                 */
/* This routine finds out what the default font is */
/* and sets up the structure "font" with the       */
/* dimensions of the default font                  */
/*                                                 */
/***************************************************/

	win_font_a.ta_Name=prefs.fontname;
	win_font_a.ta_YSize=prefs.fontsize;
	win_font_a.ta_Flags=1;
	
	if((prefs.fontstyle >0) && (prefs.fontstyle < 256) )
		win_font_a.ta_Style=prefs.fontstyle;
		
	win_font_a.ta_Style=0;
	
	win_font=OpenDiskFont(&win_font_a);

	if(!win_font) {
		// That font doesn't work!
		font.x=GfxBase->DefaultFont->tf_XSize;
		font.y=GfxBase->DefaultFont->tf_YSize;
		memset(&win_font,0,sizeof(struct TextFont));
		win_font=NULL;
	} else {
		font.x=win_font->tf_XSize;
		font.y=win_font->tf_YSize;
	}

}

void openall(void) {

/**********************************************************/
/*             Open all libraries and devices             */
/*             ==============================             */
/*                                                        */
/*  A very simple routine that opens all the libraries    */
/*  and devices needed by the program.  All the           */
/*  open library/device reqeusts are tested individually  */
/*  since it helps if I know what library/device didn't   */
/*  open when testing                                     */
/**********************************************************/

   /* Some functions used in this program are illegal under KS1.3 so
      just do a quick check to make sure we are running OS 2.x+ */

   /* if(SysBase->LibNode.lib_Version<37) {
      msg("EngClock requires OS 2.0 or higher to run!");
      closeall();
      exit(NULL);
   } */

	// Set up global bases

	IntuitionBase=(struct IntuitionBase *)OpenLibrary("intuition.library",0);
	GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0);
	DiskfontBase=OpenLibrary("diskfont.library",0);
	GadToolsBase=OpenLibrary("gadtools.library",0);
	UtilityBase=OpenLibrary("utility.library",0);
	CxBase=OpenLibrary("commodities.library",0);
	GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0);

	if(!(IntuitionBase && GfxBase && DiskfontBase && GadToolsBase && UtilityBase && GfxBase)) {
		msg("Unable to open needed libs!");
		closeall();
		exit(NULL);
	}

	// Now lets set up the languages

	if(!(available_lang=supported_languages(MOD_PATH))) {
		msg("No supported languages!\n");
		closeall();
		exit(0);
	}

	catalog=OpenCatalog(0,"engclock.catalog",0);

	/* This just wakes up narrator device if available */
	talk(" ");
	
}

void closeall(void) {

/************************************************************/
/*              Close all libraries and devices             */
/*              ===============================             */
/*                                                          */
/*  This simple routine is the opposite to openall().  It   */
/*  closes any libraries/devices that have been opened by   */
/*  the program.  Each library is tested before closing.    */
/************************************************************/

	shutdown_mod(); /* Stop the mod from working (alarm.o and mod.o) */

	if(catalog)	CloseCatalog(catalog);

	if(ispicture) { unloadpic(piccy); ispicture=FALSE; }
	if(win_font) CloseFont(win_font);
	
	if(pubscreen) UnlockPubScreen(NULL,pubscreen);

	if(win_p) {
		ClearMenuStrip(win_p);
		CloseWindow(win_p);
	}
	
	if(my_timer) CloseTimer(my_timer);

	if(cxsucc) cxclose();
	if(rexxsucc) arexxclose();
	if(snsucc) snclose();

	if(GfxBase) CloseLibrary((struct Library *)GfxBase);
	if(UtilityBase) CloseLibrary(UtilityBase);
	if(GfxBase) CloseLibrary((struct Library *)GfxBase);
	if(IntuitionBase) CloseLibrary((struct Library *)IntuitionBase);
	if(GadToolsBase) CloseLibrary(GadToolsBase);
	if(DiskfontBase) CloseLibrary(DiskfontBase);
	if(CxBase)	CloseLibrary(CxBase);
	if(LangModBase)	CloseLibrary(LangModBase);
	
	if(available_lang) dissupported_languages(available_lang);
	

}

void clearwindow(void) {

/*********************************************/
/*               Clear Window                */
/*               ============                */
/*                                           */
/* A very simple routine to clear the main   */
/* window of everything its got!  Part of    */
/* English Clock's refresh routine.  New     */
/* V2.5 feature is that it is now properly   */
/* font sensitive!!                          */
/*********************************************/

   int x,y,width,height;

   y=screentype.s_bar+1;  /* Allow 2 more pixels to be safe */
   x=5; /* Allow room for the fixed width left window line */
   width=win_p->Width-19; /* Allow room for the bigger right line */
   height=win_p->Height-3; /* Allow room for the thin bottom line */
	
	

	if(ispicture) {
      pattern(win_p,pubscreen,piccy);
   }
   else {
      SetAPen(win_p->RPort,0);
      RectFill(win_p->RPort,x,y,width,height);
      SetAPen(win_p->RPort,1);
   }

}

char tit[400];

short setupmainwindow(void) {
	

/**************************************************/
/*            Set up main window                  */
/*            ==================                  */
/*                                                */
/*  This routine makes the main window assignment */
/*  Note that no globally braced assignment is    */
/*  defined previous since for some reason if you */
/*  touch a NewWindow struct after globally       */
/*  assigning it then all hell breaks loose!      */
/**************************************************/

/* Note to coders:  Okay I know that there is probably a much easier and
   nicer way to do this then below but who cares?!!?  It works dunnit? */

   BOOL screenflag=FALSE;

	strcpy(tit,GetCatalogStr(catalog,7,"English Clock 8.5 © 1996 by"));
	strcat(tit," Ben Matthew");

   /* Stuff at beginning (LeftEdge...) assigned below */

   win1.DetailPen=0;
   win1.BlockPen=1;
   win1.IDCMPFlags=CLOSEWINDOW|MENUPICK|NEWSIZE;
   win1.Flags=SMART_REFRESH|WINDOWCLOSE|WINDOWDRAG|WINDOWDEPTH|WINDOWSIZING|ACTIVATE;
   win1.FirstGadget=NULL;
   win1.CheckMark=NULL;
   win1.Title=tit;

   win1.Screen=pubscreen;
   win1.BitMap=NULL;
   win1.MaxWidth=640;
   win1.MaxHeight=256;  /* This should be enough for any font size! */
   win1.Type=CUSTOMSCREEN;

/* First change the window dimensions to the ones specified by prefs */

win1.LeftEdge=winx;
win1.TopEdge=winy;
win1.Width=winw;
win1.Height=winh;

/* The next bit is a wee bit more complex since it has to take into
   account the font size and what not */

/* The maximum length that the time can be is:

      English = 47 total characters */

/* The minimum is 23 chars */

/* Hokay, I have had a brainwave!!  Why dont we be nice and allow users
   who have huge res workbenches to enlarge their windows even more!! */

win1.MaxWidth=screentype.s_width;
win1.MaxHeight=screentype.s_height;

if(prefs.autoadjust) {
	if(!prefs.date) 
		win1.MinHeight=screentype.s_bar+font.y+8;
	else
		win1.MinHeight=screentype.s_bar+(font.y*2)+16;
	win1.MinWidth=40;
	
	if(win1.Width < win1.MinWidth) win1.Width=win1.MinWidth;
	if(win1.Height < win1.MinHeight) win1.Height=win1.MinHeight;
	
	return(1);  
}

win1.MinWidth=mytextlength("It's just gone five and twenty past twelve (pm)",47)+40;

if(prefs.date)
   win1.MinHeight=(font.y*2)+screentype.s_bar+16;
else
   win1.MinHeight=font.y+screentype.s_bar+16;


/* Now if a particularly font is used and the above calculation creates
   Minimum values larger than can be displayed on the current screen then
   EngClock refuses to open and doesn't close the libs proper - not very
   nice!! So do a quick check!! */


if(win1.MinWidth > screentype.s_width)
   screenflag=TRUE;
if(win1.MinHeight > screentype.s_height)
   screenflag=TRUE;
if(screenflag) {
   msg(GetCatalogStr(catalog,8,"Sorry but your screen dimension is too small\nfor EngClock to use with your current font size!"));
   closeall();
   exit(NULL);
}

/* Do a quick check to make sure that the current width and height do not
   exceed the max (+vv).  This should NEVER happen but it could if someone
   or something tampers with the preferences file! */


if(win1.Width > win1.MaxWidth) win1.Width=win1.MaxWidth;
if(win1.Height > win1.MaxHeight) win1.Height=win1.MaxHeight;

if(win1.Width < win1.MinWidth) win1.Width=win1.MinWidth;
if(win1.Height < win1.MinHeight) win1.Height=win1.MinHeight;

/* Now check if the window is in the right place */

while (win1.LeftEdge+win1.Width > screentype.s_width) {
   win1.LeftEdge--;
   if (win1.LeftEdge== -1) {
      msg(GetCatalogStr(catalog,9,"Window too big for screen!"));
      closeall();
      exit(NULL);
   }
}

while (win1.TopEdge+win1.Height > screentype.s_height) {
   win1.TopEdge--;
   if (win1.TopEdge== -1) {
      msg(GetCatalogStr(catalog,9,"Window too big for screen!"));
      closeall();
      exit(NULL);
   }
}

/* Right then, all done.  Return and let main() do its stuff!! */

return(0);

}

short changemenu(void) {

   /* Function changes the Height elements of the MenuItems so that it
      takes into account font sizes */

   int height;
   height = screentype.s_bar; /* Allow a bit of space top and bot */

	menu1.MenuName=GetCatalogStr(catalog,20,"Project");
	menu_text1.IText=GetCatalogStr(catalog,10,"Set Prefs...");
	menu_text2.IText=GetCatalogStr(catalog,11,"Snapshot Win");
	menu_text3.IText=GetCatalogStr(catalog,12,"Jump");
	menu_text4.IText=GetCatalogStr(catalog,13,"About...");
	menu_text5.IText=GetCatalogStr(catalog,14,"Quit");
	
	menu_item1.Command=((char *)(GetCatalogStr(catalog,15,"P")))[0];
	menu_item2.Command=((char *)(GetCatalogStr(catalog,16,"S")))[0];
	menu_item3.Command=((char *)(GetCatalogStr(catalog,17,"J")))[0];
	menu_item4.Command=((char *)(GetCatalogStr(catalog,18,"A")))[0];
	menu_item5.Command=((char *)(GetCatalogStr(catalog,19,"Q")))[0];

   menu_item1.Height=height; /* First item in first menu */
   menu_item2.Height=height; menu_item2.TopEdge=height;
   menu_item3.Height=height; menu_item3.TopEdge=(height*2);
   menu_item4.Height=height; menu_item4.TopEdge=(height*3);
   menu_item5.Height=height; menu_item5.TopEdge=(height*4);

   /* Menu 1 = Project (7), Menu 2 = Preferences (11) */

   /* Note that I am being forced to make the assumption that the font
      being used for the windows has the same width and height dimensions
      although this is highly unlikely I cannot find a way to locate this
      other measurement */


   menu1.Width=(7*(screentype.s_bar-2))+5;

   /* Changes widths to be font sensitive + allow hotkey spacing */

   menu_item1.Width=(19*(screentype.s_bar-2))+COMMWIDTH;
   menu_item2.Width=(19*(screentype.s_bar-2))+COMMWIDTH;
   menu_item3.Width=(19*(screentype.s_bar-2))+COMMWIDTH;
   menu_item4.Width=(19*(screentype.s_bar-2))+COMMWIDTH;
   menu_item5.Width=(19*(screentype.s_bar-2))+COMMWIDTH;

   if((19*(screentype.s_bar-2))+COMMWIDTH > screentype.s_width) {
      msg(GetCatalogStr(catalog,21,"Font size is too big to create menus!!"));
      closeall();
      exit(NULL);
   }

return(0);

}

short refreshwindow(void) {
   /* Simple routine which calls funcs that together redraw the main
      window.  Placed in its own function as of version 2.6 so that I
      can redraw the window's contents any time I want, esp. with NEWSIZE */

   int length, space_avail;
	ULONG error;
	ULONG le, le2,te,te2;
   
	if(LangModBase) {
		ECM_GetTimeStr((UBYTE *)&line1,200,&error,&time);
		ECM_GetDateStr((UBYTE *)&line2,200,&error,&time);
	} else {
		strcpy(line1,GetCatalogStr(catalog,22,"Cannot load language module"));
		strcpy(line2,GetCatalogStr(catalog,23,"Check paths!"));
	}

	if(!win_p) return(0);

   if(prefs.wtf)
      WindowToFront(win_p);

	if(prefs.autoadjust)
		autoadjust();	
	else {
		// Make sure that the MinWidths are not set for autoadjust
		if(win_p->MinWidth != (mytextlength("It's just gone five and twenty past twelve (pm)",47))+40) {
			// N.B Not checking MinHeight due to complicated routine
			// Update win1
			win1.LeftEdge=win_p->LeftEdge;
			win1.TopEdge=win_p->TopEdge;
			win1.Height=win_p->Height;
			win1.Width=win_p->Width;

			win1.MinWidth=(mytextlength("It's just gone five and twenty past twelve (pm)",47))+40;
			if(prefs.date)
			   win1.MinHeight=(font.y*2)+screentype.s_bar+16;
			else
			   win1.MinHeight=font.y+screentype.s_bar+16;

			ClearMenuStrip(win_p);
			CloseWindow(win_p);
		
			if(!(win_p=OpenWindow(&win1))) {
				// There is no reason why this should fail since we updated
				msg(GetCatalogStr(catalog,24,"Error re-opening window (system failure!!)"));
				closeall();	
				exit(NULL);
			}
			if(win_font) SetFont(win_p->RPort,win_font);
			SetMenuStrip(win_p,&menu1);
		}
	}
		switch(prefs.just) {
			case 0: /* Left */
				le=16;
				le2=16;
			break;
			case 1: /* Centre */
				length=mytextlength(line1,strlen(line1));
				space_avail=win_p->Width-20; // was 26
				le=(space_avail-length)/2;
				length=mytextlength(line2,strlen(line2));
				le2=(space_avail-length)/2;
			break;
			case 2: /* Right */
				length=mytextlength(line1,strlen(line1));;
				space_avail=win_p->Width-20;
				le=space_avail-length;
				length=mytextlength(line2,strlen(line2));
				le2=space_avail-length;
			break;
		}
	


   
   clearwindow();
   clearwindow();

   if(prefs.date) {
      if(((win_p->MinHeight < (screentype.s_bar+(font.y*2)+16)) &&!(prefs.autoadjust)) || (prefs.autoadjust && (win_p->Height < (screentype.s_bar+(font.y*2)+16))) ) {
         /* Update the win1 structure to accomodate the new win_p dimensions */
         win1.TopEdge=win_p->TopEdge;
	win1.LeftEdge=win_p->LeftEdge;
	win1.Width=win_p->Width;
	win1.Height=win_p->Height;
         ClearMenuStrip(win_p);
         CloseWindow(win_p);
         if(!prefs.autoadjust) 
		win1.MinHeight=screentype.s_bar+(font.y*2)+16;
         win1.Height=screentype.s_bar+(font.y*2)+16;
         while ((win1.TopEdge+win1.Height) > screentype.s_height) {
            win1.TopEdge--;
            if(win1.TopEdge < 0) {
               DisplayBeep(NULL);
               closeall();
               exit(NULL);
            }
         }
         win_p=OpenWindow(&win1);
         SetMenuStrip(win_p,&menu1);
         if(!win_p) {
            DisplayBeep(NULL);
            closeall();
            exit(NULL);
         }
         if(win_font) SetFont(win_p->RPort,win_font);
         SetMenuStrip(win_p,&menu1); 
         clearwindow();
      }
	//te2=(((win_p->Height-((2*font.y)+(screentype.s_bar-6)))/2)+font.y)+(screentype.s_bar-2);
	//te=(((win_p->Height-((2*font.y)+(screentype.s_bar-6)))/2)-2)+(screentype.s_bar-2);
	te=(screentype.s_bar+16)+(((win_p->Height-screentype.s_bar)-((2*font.y)+6))/2);
	te-=16; // Allow for 2 pixels at the base as well;

	te2=te+font.y+2;
	
	rendertext(line2,le2,te2,prefs.date_col[screentype.s_mode]);

   } else {
      /* Only one line needed */
      if(win_p->MinHeight > (screentype.s_bar+16+font.y)) {
         ClearMenuStrip(win_p);
         CloseWindow(win_p);
         win1.MinHeight=screentype.s_bar+16+font.y;
         win1.Height=screentype.s_bar+16+font.y;
         win_p=OpenWindow(&win1);
         if(!win_p) {
            DisplayBeep(NULL);
            closeall();
            exit(NULL);
         }
         if(win_font) SetFont(win_p->RPort,win_font);
         SetMenuStrip(win_p,&menu1);
      }
	te=(((win_p->Height-font.y-screentype.s_bar)/2)+2)+(screentype.s_bar-6);
   }
   rendertext(line1,le,te,prefs.time_col[screentype.s_mode]);

	process_alarm();

   return(0);
}

void savesnap(void) {
	BPTR fp;
	
	if(!(fp=Open("s:engclock.window",MODE_NEWFILE))) {
		msg("Unable to save window position!");
		return;
	}

	FPrintf(fp,"X: %ld\n",win_p->LeftEdge);
	FPrintf(fp,"Y: %ld\n",win_p->TopEdge);
	FPrintf(fp,"W: %ld\n",win_p->Width);
	FPrintf(fp,"H: %ld\n",win_p->Height);
	
	Close(fp);
}

void loadsnap(void) {

	FILE *fp;
	
	if(!(fp=fopen("s:engclock.window","r"))) {
		winx=0; winy=0; winw=200; winh=30;
		return;
	}
	
	fscanf(fp,"X: %d", &winx);
	fscanf(fp,"Y: %d", &winy);
	fscanf(fp,"W: %d", &winw);
	fscanf(fp,"H: %d", &winh);
	
	fclose(fp);

}

long mytextlength(char *string, long len) {
	struct RastPort rp;

	InitRastPort(&rp);
	if(win_font) {
		long tmp;
		SetFont(&rp,win_font);
		tmp=TextLength(&rp,string,len);
		return(tmp);
	} 
	return(TextLength(&pubscreen->RastPort,string,len));
}

void rendertext(char *txt, long leftedge, long topedge, long col) {
	SetAPen(win_p->RPort,col);
	SetDrMd(win_p->RPort,JAM1);
	
	Move(win_p->RPort,leftedge,topedge+font.y);
	Text(win_p->RPort,txt,strlen(txt));
}