
#ifdef MACVERSION 
#include <standard.h>
#endif

#ifdef WIN95VERSION 
#include "standard.h"
#endif

#include "kb.h"
#include "memory.h"
#include "mouse.h"
#include "strings.h"
#include "resources.h"
#include "shell.rsrc.h"
#include "lang.h"
#include "langsystem7.h"
#include "miniwindow.h"
#include "process.h"
#include "cancoon.h"
#include "scripts.h"
#include "command.h"



#define cmdtextitem 1



static hdlprocessrecord quickscriptprocess = nil;



static boolean cmdsavestring (short stringnumber, Handle htext) {
	
	/*
	the cmd dialog only has one string, so we ignore the stringnumber param.
	
	set the script string in the cancoondata record, for saving -- so we have 
	a permanent copy of the last script he wrote across invocations of the
	program.
	
	1/21/93 dmb: don't set superglobals manually anymore
	
	5.0d14 dmb: hscriptstring is now a text handle, not a hdlstring.
	*/
	
	register hdlcancoonrecord hc;
	
	assert (cancoonglobals != nil);
	
	hc = cancoonglobals; /*copy into register*/
	
	if (!equalhandles (htext, (**hc).hscriptstring)) {
	
		copyhandlecontents (htext, (**hc).hscriptstring);
		
		(**hc).fldirty = true;
		}
	
	return (true);
	} /*cmdsavestring*/
	
	
static boolean cmdloadstring (short stringnumber, Handle *h) {
	
	/*
	1/21/93 dmb: don't set superglobals manually anymore
	
	5.0d14 dmb: hscriptstring is now a text handle, not a hdlstring.
	*/
	
	assert (cancoonglobals != nil);
	
	return (copyhandle ((**cancoonglobals).hscriptstring, h));
	} /*cmdloadstring*/


static boolean cmderrorroutine (long refcon, long lnum, short charnum, hdlhashtable *htable, bigstring bsname) {
	
	/*
	a lang error occurred; select the offending text in the quickscript window
	*/
	
	#ifdef flnewfeatures
	
	if (bsname != nil) { /*request is for name*/
		
		getstringlist (commandlistnumber, commandtitlestring, bsname);
		
		return (true);
		}
	
	#endif
	
	if (!startcmddialog ())
		return (false);
	
	if (!shellpushglobals (miniwindow))
		return (false);
	
	charnum = langgetsourceoffset (lnum, charnum);
		
	minisetselect (charnum, charnum);
	
	shellpopglobals ();
	
	return (true);
	} /*cmderrorroutine*/


static boolean cmdtexthit (Point pt) {
	
	/*
	2.1b6 dmb: use debugging context for zooming, if available
	*/
	
	if (keyboardstatus.ctmodifiers && mousestatus.fldoubleclick) {
		
		bigstring bs;
		hdlhashtable hcontext = nil;
		
		minigetselstring (0, bs);
		
		if (scriptgetdebuggingcontext (&hcontext)) /*gauranteed to be non-nil*/
			pushhashtable (hcontext);
		
		langzoomobject (bs);
		
		if (hcontext != nil) {
			
			pophashtable ();
			
			scriptunlockdebuggingcontext ();
			}
		}
	
	return (true);
	} /*cmdtexthit*/


static boolean cmdprocesscallback (void) {
	
	miniinvalicon (idcommandconfig);
	
	return (true);
	} /*cmdprocesscallback*/


static pascal void *cmdthreadmain (tythreadmainparams hprocess) {
	
	/*
	2.1b2 dmb: use getobjectmodeldisplaystring to diplay result
	
	2.1b4 dmb: use the debugger context, if available (i.e. a script 
	is currently suspended).
	
	4.0.1b1 dmb: pass name of thread to initprocessthread; call exitprocessthread
	*/
	
	register hdlprocessrecord hp = (hdlprocessrecord) hprocess;
	register hdlhashtable ht = nil;
	tyvaluerecord val;
	bigstring bsresult;
	hdlhashtable hcontext = nil;
	boolean fl;
	
	initprocessthread ("\x0c" "quick script"); /*must call from every thread main*/
	
	if ((**hp).fldisposewhenidle)
		fl = false;
	else {
		
		if (scriptgetdebuggingcontext (&hcontext))
			(**hp).hcontext = hcontext;
		
		fl = processruncode (hp, &val);
		
		if (hcontext != nil)
			scriptunlockdebuggingcontext ();
		}
	
	disposeprocess (hp);
	
	if (!fl)
		setbooleanvalue (false, &val);
	
	getobjectmodeldisplaystring (&val, bsresult); /*hashgetvaluestring (val, bsresult)*/
	
	disposetmpvalue (&val);
	
	minisetwindowmessage (idcommandconfig, bsresult); /*can't assume miniwindow is around anymore*/
	
	quickscriptprocess = nil; /*clear "semaphore"*/
	
	exitprocessthread ();
	
	return (nil);
	} /*cmdthreadmain*/


static boolean cmdiconhit (void) {
	
	/*
	5/21/91 dmb: run the string as a process so we can handle errors nicely.
	
	8/20/91 dmb: when the process completes, we're in another thread and can't 
	assume that the window is around anymore, let alone that its globals are 
	set.  to handle this (crashing) situation, use new minisetwindowmessage 
	to display the result.
	
	10/25/91 dmb: check new process's disposewhenidleflag before running it.
	
	10/27/91 dmb: don't dispose result value if processruncode returns false
	
	12/12/91 dmb: extract the text handle from the dialog record's TE record to 
	overcome the miniwindow's string-oriented architecture.  Unfortunately, the
	text also saved in the database as a string, to this is just a band-aid, not 
	a real fix.
	
	2.1a6 dmb: reworked threading for thread mgr 1.1
	
	2.1b2 dmb: pass -1 for errorrefcon instead of zero to prevent top level 
	lexical scope from being transparent (i.e. visible to subroutines)
	
	5.0d14 dmb: minidialog now uses full text handles, not bigstrings
	
	5.0b17 dmb: minigetstring result is ours to consume
	*/
	
	Handle hscript;
	hdltreenode hcode;
	boolean fl;
	hdlprocessrecord hprocess;
	register hdlprocessrecord hp;
	hdlprocessthread hthread;
	
	if (quickscriptprocess != nil) {
		
		sysbeep ();
		
		return (false);
		}
	
	if (!langpusherrorcallback (&cmderrorroutine, (long) -1))
		return (false);
	
	minigetstring (0, &hscript);
	
	fl = langbuildtree (hscript, false, &hcode); /*consumes htext*/
	
	langpoperrorcallback ();
	
	if (!fl) /*syntax error*/
		return (false);
	
	langerrorclear (); /*compilation produced no error, be sure error window is empty*/
	
	if (!newprocess (hcode, true, &cmderrorroutine, (long) -1, &hprocess)) {
		
		langdisposetree (hcode);
		
		return (false);
		}
	
	hp = hprocess; /*copy into register*/
	
	(**hp).processstartedroutine = &cmdprocesscallback;
	
	(**hp).processkilledroutine = &cmdprocesscallback;
	
	#ifndef oldthreads
	
	if (!newprocessthread (&cmdthreadmain, (tythreadmainparams) hp, &hthread)) {
		
		disposeprocess (hp);
		
		return (false);
		}
	
	quickscriptprocess = hp; /*can only run one of these at a time*/
	
	return (true);	
	
	#else
	
	quickscriptprocess = hp; /*can only run one of these at a time*/
	
	if (!innewprocessthread (&hthread)) /*not in new thread -- we're done with synchonous stuff*/
		return (true);
	
	if ((hthread == nil) || (**hp).fldisposewhenidle)
		fl = false;
	else
		fl = processruncode (hp, &val);
	
	disposeprocess (hp);
	
	if (!fl)
		setbooleanvalue (false, &val);
	
	hashgetvaluestring (val, bsresult);
	
	disposetmpvalue (val);
	
	minisetwindowmessage (idcommandconfig, bsresult); /*can't assume miniwindow is around anymore*/
	
	quickscriptprocess = nil; /*clear "semaphore"*/
	
	endprocessthread (hthread);
	
	return (false); /*if we got here, hthread was nil*/
	
	#endif
	} /*cmdiconhit*/


static boolean cmdgettargetdata (short id) {
	
	/*
	we don't want our script to operate on our window
	
	2.1b14 dmb: make sure that the current process and our process aren't 
	both nil before rejecting targetship.

	5.0b6 dmb: allow wp verbs to target QuickScript
	*/
	
	if ((currentprocess != nil) && (currentprocess == quickscriptprocess))
		return (false);
	
	return (id == -1) || (id == idwordprocessor);
	} /*cmdgettargetdata*/


static void cmdcheckrunbutton (void) {
	
	/*
	boolean fl = debuggingcurrentprocess () || !processisoneshot (false);
	*/
	
	boolean fl = (quickscriptprocess == nil) /*&& !processbusy ()*/ ;
	
	(**minidata).fliconenabled = fl;
	} /*cmdcheckrunbutton*/


static boolean cmdsetfields (void) {
	
	register hdlminirecord hm = minidata;
	bigstring bs;
	
	(**hm).idconfig = idcommandconfig;
	
	(**hm).windowtype = ixcommandinfo;
	
	getstringlist (commandlistnumber, runiconstring, bs);
	
	copystring (bs, (**hm).iconlabel);
	
	getstringlist (commandlistnumber, commandtitlestring, bs);
	
	copystring (bs, (**hm).windowtitle);
	
	(**hm).savestringroutine = &cmdsavestring;
	
	(**hm).loadstringroutine = &cmdloadstring;
	
	(**hm).texthitroutine = &cmdtexthit;
	
	(**hm).iconenableroutine = &cmdcheckrunbutton;
	
	(**hm).iconhitroutine = &cmdiconhit;
	
	(**hm).gettargetdataroutine = &cmdgettargetdata;
	
	(**hm).cttextitems = 1;
	
	(**hm).textitems [0] = cmdtextitem;
	
	return (true);
	} /*cmdsetfields*/


boolean startcmddialog (void) {
	
	return (startminidialog (idcommandconfig, &cmdsetfields));
	} /*startcmddialog*/


boolean cmdstart (void) {
	
	return (ministart (idcommandconfig));
	} /*cmdstart*/




