#import "Puppeteer.h"

void
define(id puppet, char *word)
{
	id speaker = [puppet appSpeaker], pb;
	int msgDelivered, fileOpened, length;
	char *data;

	/*
	 * Unhide Webster. Things don't work properly if the target application is
	 * hidden.
	 */
	[speaker selectorRPC:"unhide" paramTypes:""];

	/*
	 * Make Webster the active application.
	 */
	[puppet postActivate:YES];
	
	/*
	 * Ask Webster to define the word.
	 */
	msgDelivered = [speaker openFile:word ok:&fileOpened]; 
	if (msgDelivered != 0) {
		fprintf(stderr, "Could not send message to Webster, code = %d\n",
			msgDelivered);
		return;
	}
	if (fileOpened == NO) {
		fprintf(stderr, "Webster could not open %s\n", word);
		return;
	}
		
	/*
	 * Simulate a click in the lower scroll view.
	 */
	[puppet postSingleClick:NX_KEYWINDOW flags:0 x:40.0 y:40.0];
	
	/*
	 * Now ask Webster to copy the definition to the pasteboard. This is done by
	 * cmd-a (select all) followed by cmd-c (copy).
	 */
	[puppet postKeyCode:'a' window:NX_KEYWINDOW flags:NX_COMMANDMASK];
	[puppet postKeyCode:'c' window:NX_KEYWINDOW flags:NX_COMMANDMASK];
	[puppet ping];		// Make sure requests have been processed.
	
	/*
	 * Finally, read data from the pasteboard.
	 */
	pb = [Pasteboard new];
	[pb types];
	if ([pb readType:NXAsciiPboardType data:&data length:&length]) {
		printf("%s", data);
		[pb deallocatePasteboardData:data length:length];
	} else
		fprintf(stderr, "No data on pasteboard!\n");

}

void
main(argc, argv)
int argc;
char **argv;
{
	int c, errflg = 0;
	id puppet;
	DPSContext ctxt;
	extern int optind;

	while ((c = getopt(argc, argv, "")) != EOF)
	switch (c) {
	case '?':
	default:
		errflg++;
		break;
	}
	if (errflg || !argv[optind]) {
		fprintf(stderr, "Usage: websterPuppet word\n");
		exit(2);
	}
	
	/*
	 * Because the WindowInfo object sends postscript commands, we have to
	 * create a postscript context for it to run in.
	 */
	ctxt = DPSCreateContext(0, 0, NULL, NULL);
	DPSSetContext(ctxt);
	
	/*
	 * Create the Webster puppet, launching Webster if necessary.
	 */
	puppet = [Puppeteer connectToApp:"Webster" launch:YES];
	if (!puppet) {
		fprintf(stderr, "Could not connect to Webster\n");
		exit(1);
	}
	
	/*
	 * Attach the strings. Webster will then be ready to accept events.
	 */	
	[puppet attachStrings];
	
	/*
	 * Now call Webster to define the word.
	 */
	define(puppet, argv[optind]);

	/*
	 * Release strings. This is necessary for Webster to continue to respond to
	 * real user events.
	 */
	[puppet releaseStrings];
	
	DPSDestroyContext(ctxt);
}