/* * * ProLinga-Run * * Copyright (C) 2002-2008 Xobas Software. * All rights reserved. * * This file is part of ProLinga-Run. * * ProLinga-Run 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 3 of the License, or * (at your option) any later version. * * ProLinga-Run is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with ProLinga-Run. If not, see . * * More information is available at the following addresses: * * Website : http://www.prolinga.org * * Email : prolinga-list@prolinga.org * * */ #include "RunCommon.h" #include #include #include #include #include #include #include "RunShare.hpp" #include "RepositoryCommand.hpp" #include "LogicCommands.hpp" #include "DataRef.hpp" #include "ScreenRef.hpp" #include "Screen.hpp" #include "Limits.hpp" #include "CmdList.hpp" extern GtkWidget *activeScreen; extern pthread_t mainThreadId; extern BiAppnPtr biAppnPtr; /* Global variable (V-) */ extern VariablePtr varPtr; /* VariableGroup (G-) */ extern VariableGroupPtr vgrpPtr; /* Table.Record (F-) */ extern TablePtr tablePtr; /* Pick List (P-) */ extern PickListPtr pickPtr; /* List Store */ extern ListStorePtr listStorePtr; /* Screens open on Desktop Ptr */ extern DesktopScreenPtr desktopScreenPtr; /* Active Screen Dialog stack Ptr */ extern ScreenStackPtr dialogStackPtr; extern BiQuitLastScreenPtr biQuitLastScreenPtr; extern "C" gboolean X_HANDLER_DREF_X (GtkObject *object, gpointer user_data, int callBack); typedef struct widget_handler { char screenId[80]; char widgetType[80]; char widgetName[80]; char signalName[80]; char signalHandler[80]; }; typedef struct screen_wdgPtr { char screenName[32]; GtkWidget *screenWdg; }; typedef struct idle_command_event { GtkObject *object; char *signalData; char *screen; bool isMainThread; }; gboolean ExecuteDrefEvent(GtkObject *object, char *signalData, bool isMainThread) { const gchar *screenObject; const gchar *dataRef; char dataGetPut; char retValue[255], *retBigValue; int i, listCount, columns, sortCol; GtkListStore *storePtr; GtkTreeViewColumn *column; GtkCellRenderer *renderer; GtkTreeSelection *select; //printf("This is object : %s\n", glade_get_widget_name(GTK_WIDGET(object))); screenObject = G_OBJECT_TYPE_NAME(G_OBJECT(object)); //printf("Screen Object is : %s\n", screenObject); /* Execute Command */ if (signalData == NULL) return FALSE; if ((signalData[0] != 'D') && (signalData[0] != 'P') && (signalData[0] != 'I')) return FALSE; /* PickList Rebuild/Refresh List (GtkComboBox, GtkComboBoxEntry) */ if (signalData[0] == 'P') { //dataGetPut = 'P'; /* Get DataRef */ dataRef = signalData+2; if ( (strcmp(screenObject, "GtkComboBox")==0) || (strcmp(screenObject, "GtkComboBoxEntry")==0)) { /* get GTK thread lock */ if (isMainThread == false) gdk_threads_enter(); /* Unset active selection if applicable */ if (strcmp(screenObject, "GtkComboBox")==0) gtk_combo_box_set_active(GTK_COMBO_BOX(object), -1); listCount = gtk_tree_model_iter_n_children(GTK_TREE_MODEL(gtk_combo_box_get_model(GTK_COMBO_BOX(object))), NULL); /* Remove existing values */ for (i=(listCount-1); i>=0; i--) gtk_combo_box_remove_text(GTK_COMBO_BOX(object),i); /* Get number of pick list entries */ listCount = pickPtr->tableCount(&pickPtr, dataRef); /* Add new values */ for (i=1; i<=listCount; i++) gtk_combo_box_append_text(GTK_COMBO_BOX(object), pickPtr->getValueEntryPtr(&pickPtr, dataRef, i)); /* release GTK thread lock */ if (isMainThread == false) { /* Sync with X server */ gdk_flush(); /* release GTK thread lock */ gdk_threads_leave(); } /* Return */ return FALSE; } else if (strcmp(screenObject, "GtkToggleButton") == 0) { /* get GTK thread lock */ if (isMainThread == false) gdk_threads_enter(); /* Get number of pick list entries */ listCount = pickPtr->tableCount(&pickPtr, dataRef); if ((gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(object)) == TRUE) && (listCount > 0)) gtk_button_set_label(GTK_BUTTON(object), pickPtr->getValueEntryPtr(&pickPtr, dataRef, 1)); else if ((gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(object)) == FALSE) && (listCount > 1)) gtk_button_set_label(GTK_BUTTON(object), pickPtr->getValueEntryPtr(&pickPtr, dataRef, 2)); else gtk_button_set_label(GTK_BUTTON(object), ""); if (isMainThread == false) { /* Sync with X server */ gdk_flush(); /* release GTK thread lock */ gdk_threads_leave(); } /* Return */ return FALSE; } else /* Return */ return FALSE; } else if (signalData[0] == 'I') { dataGetPut = 'I'; /* Get DataRef */ dataRef = signalData+2; } else { if (signalData[2] == 'G') dataGetPut = 'G'; else if (signalData[2] == 'P') dataGetPut = 'P'; else { printf("ERROR -- UNKNOWN DATA MOVE\n"); printf("%s\n", signalData); return FALSE; } /* Get DataRef */ dataRef = signalData+6; } /* Data move depending on screen object */ if ( (strcmp(screenObject, "GtkTreeView")==0) && (dataGetPut =='I')) { /* List Store / View */ /* Expand name */ getDataRef((char *)dataRef, isMainThread, retValue, false); // printf("!!!%sQQQQ\n", retValue); /* Get Store */ storePtr = listStorePtr->getStore(&listStorePtr, retValue, isMainThread); /* Get Columns */ columns = listStorePtr->getNumberColumns(listStorePtr, retValue); /* Get Sort Column (if set) */ sortCol = listStorePtr->getSortColumn(listStorePtr, retValue); /* get GTK thread lock */ if (isMainThread == false) gdk_threads_enter(); /* Link Store to view */ gtk_tree_view_set_model(GTK_TREE_VIEW(object), GTK_TREE_MODEL(storePtr)); /* Clear the view */ for (;;) { column = gtk_tree_view_get_column(GTK_TREE_VIEW(object), 0); if (column == NULL) break; gtk_tree_view_remove_column(GTK_TREE_VIEW(object), column); } renderer = gtk_cell_renderer_text_new(); /* Get and present Column Data */ for (i = 1; i <= columns; i++) { column = gtk_tree_view_column_new_with_attributes(listStorePtr->getHeaderValue(listStorePtr, retValue, i),renderer, "text",(i-1),NULL); if (sortCol > 0) gtk_tree_view_column_set_sort_column_id(GTK_TREE_VIEW_COLUMN(column), (i-1)); gtk_tree_view_column_set_resizable(GTK_TREE_VIEW_COLUMN (column), TRUE); gtk_tree_view_append_column (GTK_TREE_VIEW(object), column); } /* Set sort order default column */ if (sortCol > 0) { if (listStorePtr->getSortDirection(listStorePtr, retValue) == LIST_SORTING_DESCENDING) gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(storePtr), (sortCol-1), GTK_SORT_DESCENDING); else gtk_tree_sortable_set_sort_column_id(GTK_TREE_SORTABLE(storePtr), (sortCol-1), GTK_SORT_ASCENDING); } /* Set up selection handler */ select = gtk_tree_view_get_selection (GTK_TREE_VIEW (object)); gtk_tree_selection_set_mode (select, GTK_SELECTION_SINGLE); g_signal_connect (G_OBJECT (select), "changed", \ G_CALLBACK (tree_selection_changed_cb), \ NULL); /* release GTK thread lock */ if (isMainThread == false) { /* Sync with X server */ gdk_flush(); /* release GTK thread lock */ gdk_threads_leave(); } } else { if (dataGetPut == 'G') { retBigValue = getDataRef((char *)dataRef, isMainThread, retBigValue, true); //getDataRef((char *)dataRef, isMainThread, retBigValue, false); if (retBigValue == NULL) { retBigValue = new char[2]; strcpy(retBigValue, ""); } putWidgetValue(GTK_WIDGET(object), retBigValue, isMainThread); delete retBigValue; } else if (dataGetPut == 'P') { retBigValue = getWidgetValue(GTK_WIDGET(object), isMainThread, retBigValue, true); if (retBigValue != NULL) { putDataRef((char *)dataRef, (char *)retBigValue, 0, isMainThread); delete retBigValue; } } } /* Return */ return FALSE; } extern "C" gboolean X_HANDLER_DREF_X (GtkObject *object, gpointer user_data, int callBack) { GSignalInvocationHint *ihint; gchar signalName[255]; int i; char sigKey[255]; char *signalData; gboolean retStatus; bool isMainThread; /* Determine if call comes from main thread */ if (pthread_equal(mainThreadId, pthread_self()) == 0) isMainThread = false; else isMainThread = true; /* Determine if user event or application event */ if ( callBack == -1) { strcpy(signalName, (gchar *)"focus-in-event"); } else { ihint = g_signal_get_invocation_hint(object); strcpy(signalName,g_signal_name(ihint->signal_id)); } //printf("Signal: %s Callback %d\n", signalName, callBack); /* Replace "-" with "_" in event name */ ReplaceCharInString((char *)signalName, '-', '_'); /* Determine number of callbacks */ i = 1; for (;;) { sprintf(sigKey,"%s_%d", signalName, i); signalData = (char *)g_object_get_data(G_OBJECT(object), sigKey); /*DISPLAY ALL triggers map_event for ever object */ if ((signalData == NULL) && (i == 1)) return FALSE; /* Break if no more */ if (signalData == NULL) break; /* When refresh, map_event move only */ if ((callBack == -1) && (strcmp(signalName, "focus_in_event") != 0)) continue; /* DEBUG */ //printf("DREF SIGNAL : %s_%d\n", signalName, i); /* Execute Command */ retStatus = ExecuteDrefEvent(object, signalData, isMainThread); /* Raise Counter */ i++; } /* Return */ return FALSE; } gboolean ExecuteCommandEvent(GtkObject *object, char *signalData, char *screen, bool isMainThread, bool idleEvent) { char actionPrefix, *actionCommand[255]; /* Get action prefix */ actionPrefix = signalData[0]; actionCommand[1] = signalData+2; if (actionPrefix == 'C') { CmdControl(actionCommand, 1, isMainThread, activeScreen); } else if (actionPrefix == 'S') { CmdScreen(actionCommand, 1, isMainThread, activeScreen); } else if (actionPrefix == 'L') { CmdCall(actionCommand,1, isMainThread, idleEvent); } else if (actionPrefix == 'X') { /* Special Hidden Internal Settings */ if (strcmp(actionCommand[1], "SetActiveScreen") == 0) { //printf("FOCUS BEFORE %s!!!!!!\n", screen); activeScreen = LookupWidget(GTK_WIDGET(object), screen); } } return FALSE; } gboolean IdleExecuteCommandEvent(gpointer data) { struct idle_command_event *ce; /* Cast struct */ ce = (struct idle_command_event *)data; /* Execute function */ ExecuteCommandEvent(ce->object, ce->signalData, ce->screen, ce->isMainThread, true); /* Clean up */ delete ce; /* Return */ return FALSE; } extern "C" gboolean X_HANDLER_ACTION_X (GtkObject *object, GdkEventButton *event, gpointer user_data, int callBack) { char *screen, *signalData; char sigKey[80]; int i; GtkWidget *tmpScreen = NULL; GSignalInvocationHint *ihint; gchar signalName[255]; gboolean retStatus; bool isMainThread; struct idle_command_event *ce; /* Determine if call comes from main thread */ if (pthread_equal(mainThreadId, pthread_self()) == 0) isMainThread = false; else isMainThread = true; /* Determine if user event or application event */ if ( callBack == -1) { strcpy(signalName, (gchar *)"realize"); } else { ihint = g_signal_get_invocation_hint(object); strcpy(signalName,g_signal_name(ihint->signal_id)); } //printf("signal %s - %d\n", signalName, callBack); /* Replace "-" with "_" in event name */ ReplaceCharInString((char *)signalName, '-', '_'); /* Event button_press hard coded as double click for the time being */ /* Introduce Comm Area *BUTTONCLICK or smth similar */ if (strcmp(signalName, "button_press_event") == 0) { if (event->type!=GDK_2BUTTON_PRESS) return FALSE; } //printf("Event is : %s\n", signalName); // printf("This is object : %s\n", glade_get_widget_name(GTK_WIDGET(object))); screen = (char *)g_object_get_data(G_OBJECT(object), "screenId"); // printf("Screen is : %s\n", screen); /* FIXME: Review */ /* Container screens on multiple instance screens will generate warning */ tmpScreen = desktopScreenPtr->getOneValue(&desktopScreenPtr, screen); if ((tmpScreen != NULL) && (desktopScreenPtr->isOnDesktop(desktopScreenPtr, screen) <= 1)) activeScreen = tmpScreen; else { tmpScreen = LookupWidget(GTK_WIDGET(object), screen); if (tmpScreen != NULL) activeScreen = tmpScreen; } /* Determine number of callbacks */ i = 1; for (;;) { sprintf(sigKey,"%s_%d", signalName, i); signalData = (char *)g_object_get_data(G_OBJECT(object), sigKey); /* new screen triggers realize event for screen */ if ((signalData == NULL) && (i == 1)) return FALSE; /* Break if no more */ if (signalData == NULL) break; /* When realize, realize event only */ if ((callBack == -1) && (strcmp(signalName, "realize") != 0)) continue; /* Execute Command */ if (strcmp(signalName, "focus_out_event") == 0) { /* Workaround GTK+ limitation */ /* gtk_run_dialog can not be called from non-idle function */ ce = new idle_command_event; ce->object = object; ce->signalData = signalData; ce->screen = screen; ce->isMainThread = isMainThread; g_idle_add(IdleExecuteCommandEvent, ce); } else retStatus = ExecuteCommandEvent(object, signalData, screen, isMainThread, false); /* Raise Counter */ i++; } /* Return */ return FALSE; } void DisplayRefresh(GtkObject *object) { X_HANDLER_DREF_X(object, NULL, -1); } void DisplayRealize(GtkObject *object) { X_HANDLER_ACTION_X(object, NULL, NULL, -1); } bool IsDialogScreen(xmlDocPtr docRes) { xmlXPathContextPtr ctxt; xmlXPathObjectPtr res; /* Init XPath */ xmlXPathInit(); /* Create XPath environment */ ctxt = xmlXPathNewContext(docRes); /* Find out if screen is modal */ res = xmlXPathEval((const xmlChar *)"/ProLinga/Repository/Command/Object/Screen/DisplayData/glade-interface/widget/@class", ctxt); if (strcmp((char *)xmlXPathCastToString(res), "GtkDialog") == 0) return true; else return false; } bool AllowMultipleInstances(xmlDocPtr docRes) { xmlXPathContextPtr ctxt; xmlXPathObjectPtr res; /* Init XPath */ xmlXPathInit(); /* Create XPath environment */ ctxt = xmlXPathNewContext(docRes); /* Find out if screen is modal */ res = xmlXPathEval((const xmlChar *)"/ProLinga/Repository/Command/Object/Screen/AllowMultipleInstances", ctxt); if (strcmp((char *)xmlXPathCastToString(res), "True") == 0) return true; else return false; } int SetSignalHandlers(xmlDocPtr *docRes, struct widget_handler *wh) { xmlNodePtr curTmp, curXPath, curBox, curLast; xmlXPathContextPtr ctxt; xmlXPathObjectPtr resFocus, resScreen, resSignal, resBox; int i=0, j; bool boxHasItems=false; xmlChar *attributeValue; /* Init XPath */ xmlXPathInit(); /* Create XPath environment */ ctxt = xmlXPathNewContext(*docRes); /* Get Screen id */ resScreen = xmlXPathEval((const xmlChar *)"/ProLinga/Repository/Command/Object/Screen/DisplayData/glade-interface/widget/@id", ctxt); /* Insert focus-in signal to keep track of active screen */ resFocus = xmlXPathEval((const xmlChar *)"/ProLinga/Repository/Command/Object/Screen/DisplayData/glade-interface/widget/child", ctxt); curXPath = resFocus->nodesetval->nodeTab[0]; curTmp = curXPath; curXPath = curXPath->parent; xmlUnlinkNode(curTmp); curXPath = xmlNewTextChild(curXPath, NULL, (const xmlChar *)"signal", (const xmlChar *)""); xmlNewProp(curXPath, (const xmlChar *)"name", (const xmlChar *)"focus_in_event"); xmlNewProp(curXPath, (const xmlChar *)"handler", (const xmlChar *)"X-SetActiveScreen"); xmlNewProp(curXPath, (const xmlChar *)"last_modification_time", (const xmlChar *)"Wed, 01 Jan 2003 00:00:00 GMT"); xmlAddChildList(curXPath->parent, curTmp); /* Get all signal elements */ resSignal = xmlXPathEval((const xmlChar *)"//*/signal", ctxt); /* Process signals */ curXPath = resSignal->nodesetval->nodeTab[0]; for (i=1; i<=resSignal->nodesetval->nodeNr; i++) { // i++; /* Get Widget Info */ curTmp = curXPath; curTmp = curTmp->parent; strcpy(wh[i].widgetType, (char *)xmlGetProp(curTmp, (const xmlChar *)"class")); strcpy(wh[i].widgetName, (char *)xmlGetProp(curTmp, (const xmlChar *)"id")); /* Get Screen Id and Signal */ strcpy(wh[i].screenId, (char *)xmlXPathCastToString(resScreen)); strcpy(wh[i].signalName, (char *)xmlGetProp(curXPath, (const xmlChar *)"name")); strcpy(wh[i].signalHandler, (char *)xmlGetProp(curXPath, (const xmlChar *)"handler")); /* Set signal handler to generic Action or Dataref function */ if ((wh[i].signalHandler[0] == 'D') || (wh[i].signalHandler[0] == 'P')) xmlSetProp(curXPath, (const xmlChar *)"handler", (const xmlChar *)"X_HANDLER_DREF_X"); else xmlSetProp(curXPath, (const xmlChar *)"handler", (const xmlChar *)"X_HANDLER_ACTION_X"); /* Get next signal */ curXPath = resSignal->nodesetval->nodeTab[i]; } /* Check if all ComboBox entries have "items" property so data model gets build at screen creation time */ boxHasItems=false; resBox = xmlXPathEval((const xmlChar *)"//*/widget[@class='GtkComboBox']|//*/widget[@class='GtkComboBoxEntry']", ctxt); if ((resBox!=NULL) && (resBox->nodesetval->nodeNr > 0)) { /* Found GtkComboBoxEntry */ curLast = NULL; /* Check if it has items property */ for (j=0; jnodesetval->nodeNr; j++) { curBox = resBox->nodesetval->nodeTab[j]; curTmp = curBox; curBox = curBox->xmlChildrenNode; while (curBox != NULL) { if ((!xmlStrcmp(curBox->name, (const xmlChar *)"property"))) { /* Keep pointer to last property, to insert at correct point */ curLast = curBox; /* Check Attributes */ attributeValue = (xmlChar *)xmlGetProp(curBox, (const xmlChar *)"name"); if ((!xmlStrcmp(attributeValue, (const xmlChar *)"items"))) { boxHasItems=true; xmlFree(attributeValue); break; } xmlFree(attributeValue); } curBox=curBox->next; } if (boxHasItems==false) { curBox=curTmp; curBox=xmlNewTextChild(curBox, NULL, (const xmlChar *)"property", NULL); if (curLast != NULL) curBox = xmlAddNextSibling(curLast, curBox); xmlNewProp(curBox, (const xmlChar *)"name", (const xmlChar *)"items"); xmlNewProp(curBox, (const xmlChar *)"translatable", (const xmlChar *)"yes"); } } } /* Return */ return i-1; } void DestroyScreenName(gpointer data) { struct screen_wdgPtr *sw; int numDesktop; /* This function is only been called once when destroying any window/dialog */ /* Cast struct */ sw = (struct screen_wdgPtr *)data; /* Remove screen from screens on desktop list */ desktopScreenPtr->deleteValue(&desktopScreenPtr, sw->screenName, sw->screenWdg); /* Clean up */ delete sw; numDesktop = desktopScreenPtr->numberOnDesktop(desktopScreenPtr); if (numDesktop < 1) { if (biQuitLastScreenPtr->getQuitLastScreen() == 0) { gtk_main_quit(); return; } } } void DestroyScreen(gpointer data) { char *string; // printf("NOTIFIER!!!!!\n"); string = (char *)data; // printf("!!!%s\n", string); delete string; } void CloseAllScreens(bool isMainThread) { GtkWidget *wdgTmp; char *screenType; /* get GTK thread lock */ if (isMainThread == false) gdk_threads_enter(); for(;;) { wdgTmp = desktopScreenPtr->getFirstValue(&desktopScreenPtr); if (wdgTmp == NULL) break; screenType = (char *)g_object_get_data(G_OBJECT(wdgTmp), "screenType"); if (strcmp(screenType, "DIALOG") == 0) { gtk_dialog_response(GTK_DIALOG(wdgTmp), GTK_RESPONSE_CLOSE); } else { gtk_widget_destroy(wdgTmp); gtk_widget_destroyed(wdgTmp, &wdgTmp); } } /* release GTK thread lock */ if (isMainThread == false) { /* Sync with X server */ gdk_flush(); /* release GTK thread lock */ gdk_threads_leave(); } } void CmdScreen(char **argList, int argHits, bool isMainThread, GtkWidget *outputScreen) { struct widget_handler wh[255] = {}; struct screen_wdgPtr *sw; xmlDocPtr docRes; xmlXPathContextPtr ctxRes; xmlXPathObjectPtr resRes; char *screenId, *screen, *signalHandler, returnRef[255], *screenType; char sigKey[80], screenName[64], *returnStatus, *errorList[5]; char titleString[LM_TITLE_STRING_LENGTH]; GladeXML *xml; GtkWidget *wdg, *wdgTmp, *dialogScreen, *wdgSrc, *wdgDest, *wdgScreen; int i,j, numberSignals = 0; bool isDialog = false, allowMultiple = false; gint result; /* Fall back */ if (outputScreen == NULL) outputScreen = activeScreen; if (argHits == 1) { /* Display New Screen */ /* Exec RC Get */ getDataRef(argList[1], isMainThread, screenName, false); docRes = RC_Get(biAppnPtr->getAppn(), "Screen", screenName); /* Create XPath environment */ ctxRes = xmlXPathNewContext(docRes); /* Check status */ resRes = xmlXPathEval((const xmlChar *)"/ProLinga/Repository/Command/@Status", ctxRes); returnStatus = (char *)xmlXPathCastToString(resRes); if ( strcmp(returnStatus, "Ok") != 0) { errorList[1] = "Screen ["; errorList[2] = screenName; errorList[3] = "] does not exist."; CmdError(errorList, 3, isMainThread, NULL, false); return; } /* Find out if Screen already on desktop */ if (desktopScreenPtr->isOnDesktop(desktopScreenPtr, screenName) != 0) { /* Find out if Multiple Instances are allowed */ allowMultiple = AllowMultipleInstances(docRes); if (allowMultiple == false) { /* Grab Screen widget Ptr */ wdgTmp = desktopScreenPtr->getOneValue(&desktopScreenPtr, screenName); /* get GTK thread lock */ if (isMainThread == false) gdk_threads_enter(); /* Bring window to foreground */ gtk_window_present(GTK_WINDOW(wdgTmp)); /* release GTK thread lock */ if (isMainThread == false) { /* Sync with X server */ gdk_flush(); /* release GTK thread lock */ gdk_threads_leave(); } /* Return */ return; } } /* Set Signal Handlers */ numberSignals = SetSignalHandlers(&docRes, wh); /* Find out if Modal Screen */ isDialog = IsDialogScreen(docRes); /* Extract Glade screen from response */ screen = CreateGladeString(docRes); /* dump = fopen("./dump.txt", "w"); fprintf(dump,"%s",screen); fclose(dump); */ /* get GTK thread lock */ if (isMainThread == false) gdk_threads_enter(); /* Display Screen */ xml = glade_xml_new_from_buffer(screen, strlen(screen), NULL, NULL); /* release GTK thread lock */ if (isMainThread == false) { /* Sync with X server */ gdk_flush(); /* release GTK thread lock */ gdk_threads_leave(); } if (!xml) { g_warning("something bad happened while creating the interface"); return; } /* get GTK thread lock */ if (isMainThread == false) gdk_threads_enter(); /* Set Signal Data */ for (i = 1; i <= numberSignals; i++) { wdg = glade_xml_get_widget(xml, wh[i].widgetName); screenId = new char[255]; strcpy(screenId, wh[i].screenId); /* Attach screen name to widget (only once) */ if( (char *)g_object_get_data(G_OBJECT(wdg), "screenId") == NULL) g_object_set_data_full(G_OBJECT(wdg), "screenId", screenId, DestroyScreen); /* Attach screen type (window or dialog) to widget (only once) */ screenType = new char[10]; if (isDialog == true) { if( (char *)g_object_get_data(G_OBJECT(wdg), "screenType") == NULL) { strcpy(screenType,"DIALOG"); g_object_set_data_full(G_OBJECT(wdg), "screenType", screenType, DestroyScreen); } } else { if( (char *)g_object_get_data(G_OBJECT(wdg), "screenType") == NULL) { strcpy(screenType,"WINDOW"); g_object_set_data_full(G_OBJECT(wdg), "screenType", screenType, DestroyScreen); } } /* Get signal handler data */ signalHandler = new char[255]; strcpy(signalHandler, wh[i].signalHandler); //wdgTmp = glade_xml_get_widget(xml, screenName); /* Set key to signalname + seq no */ j = 1; for(;;) { //printf("SIGNAL %s_%d HANDLER %s\n", wh[i].signalName, j, signalHandler); sprintf(sigKey,"%s_%d", wh[i].signalName, j); if( (char *)g_object_get_data(G_OBJECT(wdg), sigKey) == NULL) { if ((strcmp(wh[i].widgetType, "GtkComboBoxEntry") == 0) && (strncmp(wh[i].signalName, "child_",6) == 0)) { g_object_set_data_full(G_OBJECT(GTK_BIN(wdg)->child), sigKey+6, signalHandler, DestroyScreen); /* Connect all non-clicked signals to GtkEntry part of ComboBoxEntry */ /* Future versions of Glade should split this up */ if ((wh[i].signalHandler[0] == 'D') || (wh[i].signalHandler[0] == 'P')) g_signal_connect ((gpointer) GTK_BIN(wdg)->child, wh[i].signalName+6, G_CALLBACK (X_HANDLER_DREF_X), NULL); else g_signal_connect ((gpointer) GTK_BIN(wdg)->child, wh[i].signalName+6, G_CALLBACK (X_HANDLER_ACTION_X), NULL); } else { g_object_set_data_full(G_OBJECT(wdg), sigKey, signalHandler, DestroyScreen); if ((wh[i].signalHandler[0] == 'D') || (wh[i].signalHandler[0] == 'P')) g_signal_connect ((gpointer) G_OBJECT(wdg), wh[i].signalName, G_CALLBACK (X_HANDLER_DREF_X), NULL); else g_signal_connect ((gpointer) G_OBJECT(wdg), wh[i].signalName, G_CALLBACK (X_HANDLER_ACTION_X), NULL); } break; } j++; } } /* Call function DestroyScreenName only once when destroyed */ // !!!!!!! //wdg = glade_xml_get_widget(xml, screenName); //wdgTmp = LookupWidget(GTK_WIDGET(wdg), screenName); wdgTmp = glade_xml_get_widget(xml, screenName); if( (char *)g_object_get_data(G_OBJECT(wdgTmp), "screenName") == NULL) { sw = new screen_wdgPtr; strcpy(sw->screenName, screenName); sw->screenWdg = wdgTmp; g_object_set_data_full(G_OBJECT(wdgTmp), "screenName", sw, DestroyScreenName); //g_object_set_data_full(G_OBJECT(wdgTmp), "screenName", screenName, DestroyScreenName); /* Add screen to list 'on desktop' */ desktopScreenPtr->putValue(&desktopScreenPtr, screenName, wdgTmp); //printf("On desktop %d times is %s\n", desktopScreenPtr->isOnDesktop(desktopScreenPtr, screenName), screenName); } /* Connect signals */ //glade_xml_signal_autoconnect(xml); /* release GTK thread lock */ if (isMainThread == false) { /* Sync with X server */ gdk_flush(); /* release GTK thread lock */ gdk_threads_leave(); } if (isDialog == true) { /* Put active screen on stack */ dialogStackPtr->push(&dialogStackPtr, activeScreen); //tempScreen = activeScreen; /* Block in loop */ //dialogScreen = glade_xml_get_widget(xml, screenId); dialogScreen = glade_xml_get_widget(xml, screenName); DisplayRealize(GTK_OBJECT(dialogScreen)); /* get GTK thread lock */ if (isMainThread == false) gdk_threads_enter(); for (;;) { result = gtk_dialog_run(GTK_DIALOG(dialogScreen)); //if ((tempScreen == activeScreen) || (result == GTK_RESPONSE_CLOSE)) if (result == GTK_RESPONSE_CLOSE) { gtk_widget_destroy(dialogScreen); gtk_widget_destroyed(dialogScreen, &dialogScreen); break; } } /* release GTK thread lock */ if (isMainThread == false) { /* Sync with X server */ gdk_flush(); /* release GTK thread lock */ gdk_threads_leave(); } /* Get active screen from stack */ dialogStackPtr->pop(&dialogStackPtr, &activeScreen); } else DisplayRealize(GTK_OBJECT(wdgTmp)); /* Free object */ //g_object_unref(G_OBJECT(xml)); /*Clean up */ delete screen; /* Cleanup */ //xmlFreeDoc(docRes); } else { /* Change Screen Property */ if (strcmp(argList[1], "CLOSE") == 0) { if (argHits == 1) { /* get GTK thread lock */ if (isMainThread == false) gdk_threads_enter(); /* Close active screen */ screenType = (char *)g_object_get_data(G_OBJECT(outputScreen), "screenType"); if (strcmp(screenType, "DIALOG") == 0) { gtk_dialog_response(GTK_DIALOG(outputScreen), GTK_RESPONSE_CLOSE); } else { gtk_widget_destroy(outputScreen); gtk_widget_destroyed(outputScreen, &outputScreen); } /* release GTK thread lock */ if (isMainThread == false) { /* Sync with X server */ gdk_flush(); /* release GTK thread lock */ gdk_threads_leave(); } } else { if (strcmp(argList[2], "ALL") == 0) { CloseAllScreens(isMainThread); } else { /* get GTK thread lock */ if (isMainThread == false) gdk_threads_enter(); /* Get widgetptr screen */ for (;;) { wdgTmp = desktopScreenPtr->getOneValue(&desktopScreenPtr, argList[2]); if (wdgTmp == NULL) break; screenType = (char *)g_object_get_data(G_OBJECT(wdgTmp), "screenType"); if (strcmp(screenType, "DIALOG") == 0) { gtk_dialog_response(GTK_DIALOG(wdgTmp), GTK_RESPONSE_CLOSE); } else { gtk_widget_destroy(wdgTmp); gtk_widget_destroyed(wdgTmp, &wdgTmp); } } /* release GTK thread lock */ if (isMainThread == false) { /* Sync with X server */ gdk_flush(); /* release GTK thread lock */ gdk_threads_leave(); } } } } else if (strcmp(argList[1], "TITLE") == 0) { /* Concatenate Title */ for (i = 2; i<= argHits; i++) { getDataRef(argList[i], isMainThread, returnRef, false); if (strcmp(returnRef, "TARGET") == 0) break; if (i == 2) strcpy(titleString, returnRef); else strcat(titleString, returnRef); } if (argHits == 2) { /* get GTK thread lock */ if (isMainThread == false) gdk_threads_enter(); /* Set title current/active screen*/ gtk_window_set_title(GTK_WINDOW(outputScreen),(gchar *)titleString); /* release GTK thread lock */ if (isMainThread == false) { /* Sync with X server */ gdk_flush(); /* release GTK thread lock */ gdk_threads_leave(); } } else { /* Get screen name */ getDataRef(argList[4], isMainThread, returnRef, false); /* Get Pointer(s) to screens */ // for (;;) // { wdgTmp = desktopScreenPtr->getOneValue(&desktopScreenPtr, returnRef); // if (wdgTmp == NULL) // break; /* get GTK thread lock */ if (isMainThread == false) gdk_threads_enter(); /* Set title */ gtk_window_set_title(GTK_WINDOW(wdgTmp),(gchar *)titleString); /* release GTK thread lock */ if (isMainThread == false) { /* Sync with X server */ gdk_flush(); /* release GTK thread lock */ gdk_threads_leave(); } // } } } else if (strcmp(argList[2], "CONTAINER") == 0) { /* Lookup container control */ wdgDest = LookupWidget(GTK_WIDGET(outputScreen), argList[3]); if (wdgDest == NULL) { /*ERROR */ printf("Target container does not exist in active screen.\n"); return; } /* get GTK thread lock */ if (isMainThread == false) gdk_threads_enter(); /* If bin contains child, remove it */ wdgTmp = gtk_bin_get_child(GTK_BIN(wdgDest)); if (isMainThread == false) { /* Sync with X server */ gdk_flush(); /* release GTK thread lock */ gdk_threads_leave(); } if (wdgTmp != NULL) { /* get GTK thread lock */ if (isMainThread == false) gdk_threads_enter(); /* remove object from container */ gtk_container_remove(GTK_CONTAINER(wdgDest), wdgTmp); /* release GTK thread lock */ if (isMainThread == false) { /* Sync with X server */ gdk_flush(); /* release GTK thread lock */ gdk_threads_leave(); } /* Destroy inclusion object */ //gtk_widget_destroy(GTK_WIDGET(wdgTmp)); } /* Create socket and link to destination widget */ /* FUTURE ?? */ //wdgSocket = gtk_socket_new (); //gtk_widget_show (wdgSocket); //gtk_container_add (GTK_CONTAINER (wdgDest), wdgSocket); /* Load inclusion screen */ getDataRef(argList[1], isMainThread, screenName, false); docRes = RC_Get(biAppnPtr->getAppn(), "Screen", screenName); /* Set Signal Handlers */ numberSignals = SetSignalHandlers(&docRes, wh); /* Extract Glade screen from response */ screen = CreateGladeString(docRes); /* get GTK thread lock */ if (isMainThread == false) { gdk_threads_enter(); /* FIXME: Strange timing issue */ sleep(1); } /* Load Screen */ xml = glade_xml_new_from_buffer(screen, strlen(screen), NULL, NULL); if (isMainThread == false) { /* Sync with X server */ gdk_flush(); /* release GTK thread lock */ gdk_threads_leave(); } if (!xml) { g_warning("something bad happened while creating the interface"); return; } /* Set Signal Data */ for (i = 1; i <= numberSignals; i++) { wdg = glade_xml_get_widget(xml, wh[i].widgetName); screenId = new char[255]; strcpy(screenId, (char *)g_object_get_data(G_OBJECT(outputScreen), "screenId")); g_object_set_data_full(G_OBJECT(wdg), "screenId", screenId, DestroyScreen); screenType = new char[10]; strcpy(screenType, (char *)g_object_get_data(G_OBJECT(outputScreen), "screenType")); g_object_set_data_full(G_OBJECT(wdg), "screenType", screenType, DestroyScreen); /* Get signal handler data */ signalHandler = new char[255]; strcpy(signalHandler, wh[i].signalHandler); /* Set key to signalname + seq no */ j = 1; for(;;) { sprintf(sigKey,"%s_%d", wh[i].signalName, j); if( (char *)g_object_get_data(G_OBJECT(wdg), sigKey) == NULL) { /* Connect all child signals to GtkEntry part of ComboBoxEntry */ /* Future versions of Glade should split this up */ if ((strcmp(wh[i].widgetType, "GtkComboBoxEntry") == 0) && (strncmp(wh[i].signalName, "child_",6) == 0)) { g_object_set_data_full(G_OBJECT(GTK_BIN(wdg)->child), sigKey+6, signalHandler, DestroyScreen); if ((wh[i].signalHandler[0] == 'D') || (wh[i].signalHandler[0] == 'P')) g_signal_connect ((gpointer) GTK_BIN(wdg)->child, wh[i].signalName+6, G_CALLBACK (X_HANDLER_DREF_X), NULL); else g_signal_connect ((gpointer) GTK_BIN(wdg)->child, wh[i].signalName+6, G_CALLBACK (X_HANDLER_ACTION_X), NULL); } else { g_object_set_data_full(G_OBJECT(wdg), sigKey, signalHandler, DestroyScreen); if ((wh[i].signalHandler[0] == 'D') || (wh[i].signalHandler[0] == 'P')) g_signal_connect ((gpointer) G_OBJECT(wdg), wh[i].signalName, G_CALLBACK (X_HANDLER_DREF_X), NULL); else g_signal_connect ((gpointer) G_OBJECT(wdg), wh[i].signalName, G_CALLBACK (X_HANDLER_ACTION_X), NULL); } break; } j++; } } /* Connect signals */ //glade_xml_signal_autoconnect(xml); /* Get Source widget */ wdgScreen = glade_xml_get_widget(xml, screenName); wdgSrc = glade_xml_get_widget(xml, argList[5]); DisplayRealize(GTK_OBJECT(wdgScreen)); //gtk_widget_ref(wdgSrc); /* get GTK thread lock */ if (isMainThread == false) gdk_threads_enter(); gtk_widget_reparent(wdgSrc, wdgDest); //gtk_container_remove(GTK_CONTAINER(wdgScreen), wdgSrc); //gtk_widget_unparent(wdgSrc); //gtk_container_add(GTK_CONTAINER(wdgDest), GTK_WIDGET(wdgSrc)); //gtk_widget_unref(wdgSrc); /* Destroy source inclusion screen */ gtk_widget_destroy(wdgScreen); /* release GTK thread lock */ if (isMainThread == false) { /* Sync with X server */ gdk_flush(); /* release GTK thread lock */ gdk_threads_leave(); } /* Free */ delete screen; /* Create "empty" plug */ //wdgPlug = gtk_plug_new (gtk_socket_get_id (GTK_SOCKET(wdgSocket))); //gtk_widget_show (wdgPlug); } } }