#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <gtk/gtk.h>
#include <unistd.h>

//////////////////////////////////////////////////////////////////////////////////////
// GTK program by http://www.garyshood.com
// Requires the gtk library and xvkbd
// This is licensed under the BSD license.
// 
// Copyright (c) 2007, Gary's Hood
//////////////////////////////////////////////////////////////////////////////////////

void static check_dupe() {
	FILE *fp;
	if((fp = fopen(".startlock","r"))!=NULL) {
		printf("Dupe detected.\n");
		unlink(".lock");
		unlink(".startlock");
	}
}

void static start_autotype() {
	int fork_return;
	int count = 0;
	printf("Process %d about to fork a child.\n", getpid());
	fork_return = fork();
	if(fork_return < 0) {
		printf("Unable to create child process, exiting.\n");
		exit(0);
	}
	if(fork_return > 0) {
		printf("Created child process %d.\n", fork_return);
		while(count++ > -1) {
			char lcount;
			FILE *fp;
			FILE *fpcheck;
			char line[1000];
			char autotype[300] = "xvkbd -text \"";
			char message[255] = "";
			char endautotype[300] = "\\r\"\n";
			char sleep[300] = "sleep ";
			char delaynum[300] = "";

			if((fp = fopen(".lock","r")) == NULL) {
				printf("Cannot open file.\n");
				exit(1);
			}

			FILE *fplock = fopen(".startlock","w");
			if(fplock) {
				fprintf(fplock, " ");
			}
			fclose(fplock);

			while(fgets(line, sizeof(line), fp) != NULL ) {
				lcount++;

				if(lcount == 1) {
					strcat(delaynum, line);
					strcat(sleep, delaynum);
					printf(sleep);
					if((fpcheck = fopen(".lock","r")) == NULL) {
						printf("Cannot open file.\n");
						exit(1);
					}
					system(sleep);
				}
				if(lcount == 2) {
					strcat(message, line);
					strcat(autotype, message);
					strcat(autotype, endautotype);
					printf(autotype);
					if((fpcheck = fopen(".lock","r")) == NULL) {
						printf("Cannot open file.\n");
						exit(1);
					}
					system(autotype);
				}
			}
			fclose(fp);
		}
	}
}

void static delay_callback( GtkWidget *widget, GtkWidget *delay) {
	const gchar *delaynum;
	delaynum  = gtk_entry_get_text(GTK_ENTRY(delay));
	int num;
	sscanf(delaynum,"%d", &num);

	if(num > 0 && num < 1000) {
		FILE *fp = fopen(".lock","w");
		if(fp) {
			fprintf(fp, delaynum);
			fprintf(fp, "\n");
		}
		fclose(fp);
	}
}

void static enter_callback( GtkWidget *widget, GtkWidget *entry) {
	const gchar *message;
	message = gtk_entry_get_text(GTK_ENTRY(entry));

	FILE *fp = fopen(".lock","a");
	if(fp) {
		fprintf(fp, message);
		fprintf(fp, "\n");
	}
	fclose(fp);
}

void static stop_autotype() {
	unlink(".lock");
	unlink(".startlock");
}

int main(int argc, char *argv[]) {
	unlink(".lock");
	unlink(".startlock");
	GtkWidget *window;
	GtkWidget *vbox;
	GtkWidget *entry;
	GtkWidget *delay;
	GtkWidget *button;
	GtkWidget *frame;
	GtkWidget *label;
	GtkAdjustment *adj;
	gint tmp_pos;
	FILE *fp;
	GtkWidget *dialog;

	gtk_init (&argc, &argv);

	window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
	gtk_widget_set_size_request (GTK_WIDGET (window), 400, 240);
	gtk_window_set_title (GTK_WINDOW (window), "Auto Typer");
	g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (gtk_main_quit), NULL);
	g_signal_connect_swapped (G_OBJECT (window), "delete_event", G_CALLBACK (gtk_widget_destroy), G_OBJECT (window));

	vbox = gtk_vbox_new (FALSE, 0);
	gtk_container_add (GTK_CONTAINER (window), vbox);
	gtk_widget_show (vbox);
	gtk_container_set_border_width (GTK_CONTAINER (window), 10);

	frame = gtk_frame_new ("Instructions");
	label = gtk_label_new ("Set a message, set a speed, and hit start.");
	gtk_container_add (GTK_CONTAINER (frame), label);
	gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
	gtk_widget_show (label);
	gtk_widget_show (frame);

	entry = gtk_entry_new ();
	gtk_entry_set_max_length (GTK_ENTRY (entry), 255);
	gtk_entry_set_text (GTK_ENTRY (entry), "Enter your message here.");
	tmp_pos = GTK_ENTRY (entry)->text_length;
	gtk_editable_insert_text (GTK_EDITABLE (entry), "", -1, &tmp_pos);
	gtk_editable_select_region (GTK_EDITABLE (entry), 0, GTK_ENTRY (entry)->text_length);
	gtk_box_pack_start (GTK_BOX (vbox), entry, TRUE, TRUE, 0);
	gtk_widget_show (entry);

	adj = (GtkAdjustment *) gtk_adjustment_new (1.0, 1.0, 60.0, 1.0, 5.0, 0.0);
	delay = gtk_spin_button_new (adj, 0, 0);
	gtk_spin_button_set_wrap (GTK_SPIN_BUTTON (delay), TRUE);
	gtk_box_pack_start (GTK_BOX (vbox), delay, FALSE, TRUE, 0);
	gtk_widget_show (delay);

	button = gtk_button_new_with_label ("Start");

	g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (delay_callback), (gpointer) (delay));
	g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (enter_callback), (gpointer) (entry));
	g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (check_dupe), NULL);
	g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (start_autotype), NULL);

	gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 10);
	GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
	gtk_widget_grab_default (button);
	gtk_widget_show (button);

	button = gtk_button_new_with_label ("Stop");
	g_signal_connect (G_OBJECT (button), "clicked", G_CALLBACK (stop_autotype), NULL);
	gtk_box_pack_start (GTK_BOX (vbox), button, TRUE, TRUE, 0);
	gtk_widget_show (button);

	frame = gtk_frame_new ("\nCreated by: Gary's Hood");
	label = gtk_label_new ("http://www.garyshood.com");
	gtk_container_add (GTK_CONTAINER (frame), label);
	gtk_box_pack_start (GTK_BOX (vbox), frame, FALSE, FALSE, 0);
	gtk_widget_show (label);
	gtk_widget_show (frame);

	if((fp = fopen("/usr/bin/xvkbd","r"))==NULL && (fp = fopen("/usr/local/bin/xvkbd","r")) == NULL) {
		dialog = gtk_message_dialog_new (GTK_WINDOW (window), GTK_DIALOG_DESTROY_WITH_PARENT, GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "The program xvkbd was not detected. If it was installed, link xvkbd to /usr/bin/xvkbd or /usr/local/bin/xvkbd and restart this application.");
		gtk_window_set_title (GTK_WINDOW (dialog), "xvkbd not found");
		gtk_dialog_run (GTK_DIALOG (dialog));
		gtk_widget_destroy (dialog);
	}
	gtk_widget_show (window);
	gtk_main();
	return 0;
}