/***************************************************************************
                          gins.c - main entry for gins
                             -------------------
    begin                : ven dic 31 2004
    copyright            : (C) 2004-2005 by Fabrix.xm
    email                : fabrix.xm@lombardiacom.it
 ***************************************************************************/

/***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 **************************************************************************/

#include <stdio.h>
#include <gtk/gtk.h>
#include <glade/glade.h>
#include <glib.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>


#define VERSION "0.0.1"

// globals
GladeXML *xml;

char ginsbuffer1[255];
char ginsbuffer2[255];
char ginsbuffer3[255];

int bufferfull = 0;

//
void removeNL(char *);

// event strings
char* eventTypes[] = {
  "GDK_NOTHING",
  "GDK_DELETE",
  "GDK_DESTROY",
  "GDK_EXPOSE",
  "GDK_MOTION_NOTIFY",
  "GDK_BUTTON_PRESS",
  "GDK_2BUTTON_PRESS",
  "GDK_3BUTTON_PRESS",
  "GDK_BUTTON_RELEASE",
  "GDK_KEY_PRESS",
  "GDK_KEY_RELEASE",
  "GDK_ENTER_NOTIFY",
  "GDK_LEAVE_NOTIFY",
  "GDK_FOCUS_CHANGE",
  "GDK_CONFIGURE",
  "GDK_MAP",
  "GDK_UNMAP",
  "GDK_PROPERTY_NOTIFY",
  "GDK_SELECTION_CLEAR",
  "GDK_SELECTION_REQUEST",
  "GDK_SELECTION_NOTIFY",
  "GDK_PROXIMITY_IN",
  "GDK_PROXIMITY_OUT",
  "GDK_DRAG_ENTER",
  "GDK_DRAG_LEAVE",
  "GDK_DRAG_MOTION",
  "GDK_DRAG_STATUS",
  "GDK_DROP_START",
  "GDK_DROP_FINISHED",
  "GDK_CLIENT_EVENT",
  "GDK_VISIBILITY_NOTIFY",
  "GDK_NO_EXPOSE",
  "GDK_SCROLL",
  "GDK_WINDOW_STATE",
  "GDK_SETTING ",
  "GDK_OWNER_CHANGE"
};


void removeNL(char *text) {
	/*elimino un eventuale "acapo" in fondo alla stringa*/
	if (text[strlen(text)-1]=='\n') text[strlen(text)-1]='\0';
}

void returnstring(char *thestring){


        	wVariant *myvariant;

		myvariant = (wVariant *)wMalloc( sizeof( wVariant ) );

           	//-- create a string
           	wVariantFromChar( myvariant, thestring ,4,4 );

    		//-- return it to wxBasic
    		wVariantMove( wStackPushNothing(), myvariant );

   		//-- cleanup
    		wVariantDeref( myvariant );
    		wFree(myvariant);
}

void wBuiltin_gins_gtkwidgetfunction(){

	char *resultbuffer = "Nothing";

	GtkWidget *obj;
	char objid[255];
	char thefunction[255];
	wVariant *variant;
	char *wstring;
	char result[1024];
	char arg1[255];
	char arg2[255];

	variant = wStackPopString();
    	wstring = wVariantToChar( variant, W_FALSE, 0 );
	sprintf(arg2 , "%s" , wstring);

	variant = wStackPopString();
    	wstring = wVariantToChar( variant, W_FALSE, 0 );
	sprintf(arg1 , "%s" , wstring);

	variant = wStackPopString();
    	wstring = wVariantToChar( variant, W_FALSE, 0 );
	sprintf(thefunction , "%s" , wstring);

	variant = wStackPopString();
    	wstring = wVariantToChar( variant, W_FALSE, 0 );
	sprintf(objid , "%s" , wstring);

	wVariantDeref( variant );
	free(wstring);

	obj = glade_xml_get_widget(xml, objid);

gboolean resultgboolean;
guint resultguint;
gdouble resultgdouble;

//////////////////////

// here a LOT of GTK functions can be added...

//GiNsTaBlE1StArT

	if (!strcmp(thefunction,"gtk_file_chooser_get_current_folder")) {
		resultbuffer = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(obj));
		sprintf(result , "%s" , resultbuffer);
		returnstring(result);
		free(resultbuffer);
		return;
	}

	if (!strcmp(thefunction,"gtk_file_chooser_get_filename")) {
		resultbuffer = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(obj));
		sprintf(result , "%s" , resultbuffer);
		returnstring(result);
		free(resultbuffer);
		return;
	}

	if (!strcmp(thefunction,"gtk_file_chooser_get_select_multiple")) {
		resultbuffer = gtk_file_chooser_get_select_multiple(GTK_FILE_CHOOSER(obj));
		sprintf(result , "%s" , resultbuffer);
		returnstring(result);
		free(resultbuffer);
		return;
	}

	if (!strcmp(thefunction,"gtk_file_chooser_set_select_multiple")) {
		gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(obj) , arg1);
		returnstring("Nothing");
		free(resultbuffer);
		return;
	}

	if (!strcmp(thefunction,"gtk_label_set_selectable")) {
		gtk_label_set_selectable(GTK_LABEL(obj) , arg1);
		returnstring("Nothing");
		free(resultbuffer);

		return;
	}

	if (!strcmp(thefunction,"gtk_label_get_selectable")) {

		resultgboolean = gtk_label_get_selectable(GTK_LABEL(obj));

		sprintf(result , "%d" , resultgboolean);
		returnstring(result);
		free(resultbuffer);

		return;
	}

//GiNsTaBlE1EnD

	returnstring("Nothing");
	free(resultbuffer);
	return;
}


void wBuiltin_gins_glade(){

	char *thefile;
	wVariant *variant;
	variant = wStackPopString();
    	thefile = wVariantToChar( variant, W_FALSE, 0 );
	loadXMLFile(thefile);
	wVariantDeref( variant );

}
void wBuiltin_gins_set(){

	gint intval;
	gboolean bvalue = TRUE;
	gdouble doubleValue;
	GtkWidget *obj;

	char *wstring;

	char objid[255];
	char name[255];
	char value[255];
	char type[255];

	wVariant *variant;

	variant = wStackPopString();
    	wstring = wVariantToChar( variant, W_FALSE, 0 );
	sprintf(type , "%s" , wstring);

	variant = wStackPopString();
    	wstring = wVariantToChar( variant, W_FALSE, 0 );
	sprintf(value , "%s" , wstring);

	variant = wStackPopString();
    	wstring = wVariantToChar( variant, W_FALSE, 0 );
	sprintf(name , "%s" , wstring);

	variant = wStackPopString();
    	wstring = wVariantToChar( variant, W_FALSE, 0 );
	sprintf(objid , "%s" , wstring);

	wVariantDeref( variant );
	free(wstring);

	obj = glade_xml_get_widget(xml, objid);

	if (strncmp(type,"<uposition>", 5)==0) {
		intval = atoi(value); 
		gint intval2 = atoi(name);
	       	gtk_widget_set_uposition(obj, intval2,intval );

		return;
	}

	if (strncmp(type,"<int>", 5)==0) {
		intval = atoi(value); 
		
		g_object_set (obj,name, intval, NULL);
		return;
	}
	if (strncmp(type,"<str>", 5)==0) {
		g_object_set (obj,name, &value, NULL);
		return;
	}
	if (strncmp(type,"<boolean>", 5)==0) {
		if (strncmp(value,"FALSE",5)==0) {
			bvalue = FALSE;
		}
		g_object_set (obj,name, bvalue, NULL);
		return;
	}
	if (strncmp(type,"<double>", 5)==0) {
		doubleValue = strtod(value, NULL); 
		g_object_set (obj,name, doubleValue , NULL);
		return;
	}
}

void wBuiltin_gins_get(){

	gint intval;
	gboolean bvalue = TRUE;
	gdouble doubleValue;
	GtkWidget *obj;

	gdouble dval;
	gboolean bval;
	char bvalstr[255] = "TRUE";
	char *wstring;

	char objid[255];
	char name[255];
	char type[255];
	gchar *value;
	char buffer[300];
	wVariant *variant;

	variant = wStackPopString();
    	wstring = wVariantToChar( variant, W_FALSE, 0 );
	sprintf(type , "%s" , wstring);

	variant = wStackPopString();
    	wstring = wVariantToChar( variant, W_FALSE, 0 );
	sprintf(name , "%s" , wstring);

	variant = wStackPopString();
    	wstring = wVariantToChar( variant, W_FALSE, 0 );
	sprintf(objid , "%s" , wstring);

	wVariantDeref( variant );
	free(wstring);

	obj = glade_xml_get_widget(xml, objid);

	if (obj == NULL) {
		printf("[gins] ERROR INVALID_OBJID\n");
		return;
	}

	if (strncmp(type,"<str>", 5)==0) {
		g_object_get (obj,name, &value, NULL);
		snprintf(buffer, 299, "%s", value);

		g_free(value);

        	wVariant *myvariant;

		myvariant = (wVariant *)wMalloc( sizeof( wVariant ) );

           	//-- create a string
           	wVariantFromChar( myvariant, buffer ,4,4 );

    		//-- return it to wxBasic
    		wVariantMove( wStackPushNothing(), myvariant );

   		//-- cleanup
    		wVariantDeref( myvariant );
    		wFree(myvariant);

		return;
	}

	if (strncmp(type,"<double>", 5)==0) {
		g_object_get (obj,name, &dval, NULL);
		
		snprintf(buffer, 299, "%f", dval);

        	wVariant *myvariant;

		myvariant = (wVariant *)wMalloc( sizeof( wVariant ) );

           	//-- create a string
           	wVariantFromChar( myvariant, buffer ,4,4 );

    		//-- return it to wxBasic
    		wVariantMove( wStackPushNothing(), myvariant );

   		//-- cleanup
    		wVariantDeref( myvariant );
    		wFree(myvariant);
		return;
	}
	
	if (strncmp(type,"<boolean>", 5)==0) {
		g_object_get (obj,name, &bval, NULL);
		if (! bval) { 
			bvalstr[0] = 'F';
			bvalstr[1] = 'A';
			bvalstr[2] = 'L';
			bvalstr[3] = 'S';
			bvalstr[4] = 'E';
			
		}
		snprintf(buffer, 299, "%s", &bvalstr);

        	wVariant *myvariant;

		myvariant = (wVariant *)wMalloc( sizeof( wVariant ) );

           	//-- create a string
           	wVariantFromChar( myvariant, buffer ,4,4 );

    		//-- return it to wxBasic
    		wVariantMove( wStackPushNothing(), myvariant );

   		//-- cleanup
    		wVariantDeref( myvariant );
    		wFree(myvariant);
		return;
	}
	
	
	if (strncmp(type,"<int>", 5)==0) {
		g_object_get (obj,name, &intval, NULL);
		
		snprintf(buffer, 299, "%i", intval);

        	wVariant *myvariant;

		myvariant = (wVariant *)wMalloc( sizeof( wVariant ) );

           	//-- create a string
           	wVariantFromChar( myvariant, buffer ,4,4 );

    		//-- return it to wxBasic
    		wVariantMove( wStackPushNothing(), myvariant );

   		//-- cleanup
    		wVariantDeref( myvariant );
    		wFree(myvariant);
		return;
	}
}
  
gboolean signal_handler(GtkWidget *widget, GdkEvent* event, gpointer data) {
	//char buffer[255];
	if (event==NULL) {
		return FALSE;
	}
	if(bufferfull == 0){
	
		char edata[255];

		if (eventTypes[(int)event->type + 1]!="DROP"){

			// added by //MU
			snprintf(edata, 256, "null");
			if ((GdkEventButton*)event){
				snprintf(edata, 256, "%d" , ((GdkEventButton*)event)->button );
			}


			snprintf(ginsbuffer1, 256, "%s", glade_get_widget_name(widget));
			snprintf(ginsbuffer2, 256, "%s", eventTypes[(int)event->type + 1]);
			snprintf(ginsbuffer3, 256, "%s", edata);



			bufferfull = 1;
		}
	}
	

	return FALSE;
}

void wBuiltin_gins_event(){

	if(bufferfull==1){
        	wVariant *myvariant;

		myvariant = (wVariant *)wMalloc( sizeof( wVariant ) );

           	//-- create a string
           	wVariantFromChar( myvariant, ginsbuffer1 ,4,4 );
    		//-- return it to wxBasic
    		wVariantMove( wStackPushNothing(), myvariant );

           	//-- create a string
           	wVariantFromChar( myvariant, ginsbuffer2 ,4,4 );
    		//-- return it to wxBasic
    		wVariantMove( wStackPushNothing(), myvariant );

           	//-- create a string
           	wVariantFromChar( myvariant, ginsbuffer3 ,4,4 );
    		//-- return it to wxBasic
    		wVariantMove( wStackPushNothing(), myvariant );
   		//-- cleanup
    		wVariantDeref( myvariant );
    		wFree(myvariant);

		bufferfull = 0;
	}

}


void connections(GladeXML *xml){
	/*connect all widgets event*/
	GList* allwidgets=NULL;
	GtkWidget *widget;
	
	allwidgets = glade_xml_get_widget_prefix(xml, "");
	
	while (allwidgets != NULL) {
		g_signal_connect (G_OBJECT (allwidgets->data), "event", G_CALLBACK (signal_handler), NULL);
		allwidgets = allwidgets->next;
	}
	
	g_list_free(allwidgets);

}


int loadXMLFile(char *file){
	
	removeNL(file);
	
	/* load the interface */
	xml = glade_xml_new(file, NULL, NULL);
	if (xml==NULL) return -1;
	connections(xml);
	return 0;
}


void wBuiltin_gins_exit(){

	gtk_main_quit();

}





void wBuiltin_gins_usleep()
{
    int microseconds;
   // sscanf(argv[1], "%d", &microseconds);
microseconds = wStackPopNumber();
//    printf("%d\n" , microseconds);

#ifdef _WIN32
    sleep(microseconds/1000);
#else

    usleep(microseconds);
#endif
}


#ifdef _WIN32
void *mywinthread(){

printf("\n--starting new thread--\n");

	gtk_main();
}

#include <windows.h>
#include <winbase.h>
#include <process.h>
typedef unsigned (__stdcall *PTHREAD_START) (void *);

void wBuiltin_gins_main(){

unsigned long threadId;
//HANDLE hThread = CreateThread(NULL, 2000, (LPTHREAD_START_ROUTINE)mywinthread, 0, CREATE_SUSPENDED, &threadId);


unsigned threadID;
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, (PTHREAD_START) mywinthread, 0, 0, &threadID);

}
#else

void *mythread(void *ch){
	gtk_main();
}

void wBuiltin_gins_main(){
	char ch1='-';
	pthread_t p1;
	pthread_create (&p1, NULL, mythread, &ch1);
}


#endif
