#include /* Motif Toolkit and MRM */ #include "midaslist.h" #include "midasoperand.h" #include "midaswidget.h" #include "midasshell.h" #include MidasOperand MidasConvertFromInteger(); MidasOperand MidasConvertFromString(); MidasOperand MidasConvertFromBoolean(); MidasWidget *MidasWidgetToMW(); MidasShell *MidasGetShell(); char *MidasGetWidgetName(); char *MidasConvertToString(); static char *Option = "ExecuteWhenCreated"; typedef struct _IR {char *Command; Boolean ExecuteWhenCreated; } IngotParm; #define Offset(field) XtOffsetOf(IngotParm,field) static XtResource resources[] = { {"midasIngots","MidasIngots",XtRString ,sizeof(char *) ,Offset(Command) ,XtRImmediate,(XtPointer)0}, {"midasIngots","MidasIngots",XtRBoolean,sizeof(Boolean),Offset(ExecuteWhenCreated),XtRImmediate,(XtPointer)True}}; #undef Offset static List *IngotRList; struct Ingot { Boolean Valued; MidasOperand Operand; char *Command; Widget Parent; struct Ingot *ValueOwner; List *CallbackList; Boolean ExecuteWhenCreated; }; typedef struct Ingot Ingot; static XtConvertArgRec ConvertWidgetArg[] = {{XtBaseOffset,0,sizeof(Widget)}}; Ingot *MidasFindIngotHere(w,Name) Widget w; char *Name; { MidasWidget *mw = MidasWidgetToMW(w); ListItem *i; List *TList = mw->IngotList; if (TList != NULL) { i = MidasFindItemInList(TList,Name); if (i != 0) return i->Pointer; } return 0; } Ingot *MidasFindIngot(w,Name) Widget w; char *Name; { MidasShell *ms = MidasGetShell(w); for (;; w = XtParent(w)) { Ingot *T = MidasFindIngotHere(w,Name); if (T != 0) return T; if (w == ms->Widget) break; } return 0; } static void MidasDestroyIngot(T) Ingot *T; /* This routine is called from MidasDestroyIngots during the destruction of a widget that has ingots. It assumes that all child widgets are also being destroyed and therefore does not worry about them. */ { if (!T->Valued) { Ingot *ValueOwner = T->ValueOwner; List *CallbackList = ValueOwner->CallbackList; if (CallbackList != 0) { ListItem *item; for (item = CallbackList->First; item != 0 ; item = item->Next) { if (item->Pointer == T) { item->Pointer = 0; MidasRemoveItemFromList(CallbackList,item); break; } } } } else if (T->Operand.Dynamic) XtFree((char *)T->Operand.Value.P); if (T->CallbackList != 0) MidasDestroyList(T->CallbackList); XtFree(T->Command); } void MidasDestroyIngots(mw) MidasWidget *mw; /* * This routine is called whenever a widget that has ingots * goes and gets itself destroyed. */ { ListItem *item; List *TList = mw->IngotList; for (item = TList->First; item != 0; item = item->Next) { Ingot *T = item->Pointer; MidasDestroyIngot(T); item->Pointer = 0; } MidasDestroyList(TList); } Ingot *MidasCreateIngot(w,Name) Widget w; char *Name; /* If this ingot does not already have an explicit ingot of this name it is created. A pointer to the (newly created) ingot is returned; A created ingot initially has no value and no callbacks; */ { MidasWidget *mw = MidasWidgetToMW(w); Ingot *T; ListItem *item; List *TList = mw->IngotList; if (TList == NULL) { mw->IngotList = TList = MidasCreateEmptyList(XtName(w)); } item = MidasFindItemInList(TList,Name); if (item == 0) { T = XtNew(Ingot); T->CallbackList = 0; T->Command = 0; T->Parent = w; T->ValueOwner = 0; T->Valued = FALSE; T->ExecuteWhenCreated = TRUE; item = MidasAddItemToList(TList,Name); item->Pointer = T; } else T = item->Pointer; return T; } void MidasInheritIngotValue(T,Name) Ingot *T; char *Name; { Ingot *ValueOwner; MidasShell *ms = MidasGetShell(T->Parent); if (strncmp(Name,"Midas",5) && ms->Widget != T->Parent) ValueOwner = MidasFindIngot(XtParent(T->Parent),Name); else ValueOwner = 0; if (ValueOwner == 0) { T->Valued = TRUE; T->Operand.Value.P = (XtPointer)""; T->Operand.Dynamic = FALSE; T->Operand.Type = MString; } else { if (ValueOwner->Valued == 0) ValueOwner = ValueOwner->ValueOwner; T->ValueOwner = ValueOwner; } #ifdef debug if (T->Valued) printf("Ingot %s in %s did not ingerit a value\n",Name,XtName(T->Parent)); else printf("Ingot %s inherited value %s from %s\n",Name,ValueOwner->Operand.Value, XtName(ValueOwner->Parent)); #endif } void MidasSetIngotValue(T,Operand) Ingot *T; MidasOperand Operand; /* This routine sets the value of the specified ingot and calls the value changed callbacks belonging to the ingot */ { if (T->Valued && T->Operand.Dynamic) XtFree((char *)T->Operand.Value.P); T->Operand = Operand; /* * BIG KLUGE .. must be fixed soon */ if (strcmp(Operand.Type,MString)==0 && Operand.Dynamic==FALSE) { T->Operand.Value.P = XtNewString(Operand.Value.P); T->Operand.Dynamic = TRUE; } T->Valued = TRUE; if (T->Command != 0) MidasDispatchCommandCallback(T->Parent,T->Command,0); if (T->CallbackList != 0) { ListItem *item; for (item = T->CallbackList->First; item != 0; item = item->Next) { Ingot *T = item->Pointer; MidasDispatchCommandCallback(T->Parent,T->Command,0); } } } void MidasSetCallbackValue(T,Command) Ingot *T; char *Command; { Widget SW, w = T->Parent; MidasShell *ms = MidasGetShell(w); if (T->Command == 0) { if (T->Valued == 0) { ListItem *item; Ingot *ValueOwner = T->ValueOwner; if (ValueOwner->CallbackList == 0) ValueOwner->CallbackList = MidasCreateEmptyList(""); item = MidasAddItemToListPos(ValueOwner->CallbackList,XtName(w),0); item->Pointer = T; } } else XtFree(T->Command); T->Command = XtNewString(Command); } MidasOperand MidasGetIngotValue(T) Ingot *T; { MidasOperand Temp; if (T->Valued == 0) T = T->ValueOwner; Temp = T->Operand; Temp.Dynamic = FALSE; /* The ingot retains ownership of the operand */ return Temp; } char *MidasGetCallbackValue(T) Ingot *T; { if (T->Command == 0) return XtNewString(""); else return XtNewString(T->Command); } MidasOperand MidasGetCallback(w,Name) Widget w; char *Name; { MidasOperand Temp; Ingot *T = MidasFindIngotHere(w,Name); if (T == 0) { Temp.Value.P = ""; Temp.Dynamic = FALSE; } else { Temp.Value.P = MidasGetCallbackValue(T); Temp.Dynamic = TRUE; } Temp.Type = MString; return Temp; } MidasOperand MidasGetCreateCallback(w) Widget w; { Ingot *T = MidasFindIngotHere(w,"midasCreateCallback"); if (T == 0) { MidasOperand Temp; Temp.Value.P = ""; Temp.Dynamic = FALSE; Temp.Type = MString; return Temp; } else return MidasGetIngotValue(T); } MidasOperand MidasGetIngot(w,Name) Widget w; char *Name; { Ingot *T = MidasFindIngot(w,Name); if (T == 0) MidasError("Can not find ingot %s",Name); return MidasGetIngotValue(T); } MidasOperand MidasGetValueOwner(w,Name) Widget w; char *Name; { MidasOperand Temp; Ingot *T = MidasFindIngot(w,Name); if (T == 0) MidasError("Can not find ingot %s",Name); if (T->Valued) Temp.Value.P = (XtPointer) T->Parent; else Temp.Value.P = (XtPointer) T->ValueOwner->Parent; Temp.Type = MWidget; Temp.Dynamic = FALSE; return Temp; } MidasOperand MidasGetIngotOption(w,Name) Widget w; char *Name; { MidasOperand Temp; Ingot *T = MidasFindIngot(w,Name); if (T == 0) MidasError("Can not find ingot %s",Name); Temp.Value.I = T->ExecuteWhenCreated; Temp.Type = MBoolean; Temp.Dynamic = FALSE; return Temp; } void MidasSetIngotOption(w,Name,Opt) Widget w; char *Name; Boolean Opt; { MidasOperand Temp; Ingot *T = MidasFindIngot(w,Name); if (T == 0) MidasError("Can not find ingot %s",Name); T->ExecuteWhenCreated = Opt; } void MidasSetIngot(w,Name,Temp) Widget w; char *Name; MidasOperand Temp; { Ingot *T = MidasCreateIngot(w, Name); MidasSetIngotValue(T, Temp); #ifdef debug printf("Set Ingot %s in %s to value %s\n",Name,XtName(w),Temp.Value.I); #endif } void MidasSetIngotString(w,Name,Value) Widget w; char *Name; char *Value; { MidasSetIngot(w,Name,MidasConvertFromString(Value)); } void MidasSetIngotP(w,Name,Temp) Widget w; char *Name; MidasOperand *Temp; { MidasSetIngot(w,Name,*Temp); } void MidasSetCallback(w,Name,Command) Widget w; char *Name; char *Command; { Ingot *T = MidasCreateIngot(w, Name); MidasInheritIngotValue(T,Name); MidasSetCallbackValue(T,Command); } void MidasGetIngots(L,w) List *L; Widget w; { MidasShell *ms = MidasGetShell(w); MidasEmptyList(L); for (;; w = XtParent(w)) { MidasWidget *mw = MidasWidgetToMW(w); ListItem *i; List *TList = mw->IngotList; if (TList != NULL) for (i = TList->First; i != 0; i = i->Next) if (strncmp(i->Entry,"midas",5)) if (MidasFindItemInList(L,i->Entry) == 0) MidasAddItemToList(L,i->Entry); if (w == ms->Widget) break; } } static void MidasStoreCallback(w,cname) Widget w; char *cname; { char *result; char *name = MidasGetWidgetName(w); char *value = MidasConvertToString(MidasGetCallback(w,cname)); char *new = XtMalloc(strlen(name)+strlen(cname)+strlen(Option)+2); MidasShell *ms = MidasGetShell(w); XtGetApplicationResources(w,(XtPointer) &result,resources,1,NULL,0); strcpy(new,name); strcat(new,"."); strcat(new,cname); XrmPutStringResource(&ms->Database,new,value); strcat(new,Option); value = MidasConvertToString(MidasGetIngotOption(w,cname)); XrmPutStringResource(&ms->Database,new,value); ms->Changes++; XtFree(new); XtFree(value); if (result != 0) { Boolean found = FALSE; char *token, *old = XtNewString(result); for (token = strtok(old," "); token != NULL; token = strtok(NULL," ")) if (strcmp(token,cname)==0) found = TRUE; XtFree(old); if (found) { XtFree(name); return; } value = XtMalloc(strlen(result)+strlen(cname)+2); strcpy(value,result); strcat(value," "); strcat(value,cname); } else value = XtNewString(cname); new = XtMalloc(strlen(name)+strlen(".midasIngots")+1); strcpy(new,name); strcat(new,".midasIngots"); XrmPutStringResource(&ms->Database,new,value); XtFree(new); XtFree(value); XtFree(name); } void MidasSetupIngots(mw,IngotNames) MidasWidget *mw; char *IngotNames; { List *TList; ListItem *item; char *Input = XtNewString(IngotNames); char *VerbVector[100]; int VerbCount, i; Widget w = mw->Widget; MidasShell *ms = MidasGetShell(w); mw->IngotList = TList = MidasCreateEmptyList(XtName(w)); MidasTokenizeCommand(Input,VerbVector,&VerbCount,XtNumber(VerbVector)," "); /* This could be made more efficient by fetching all the ingots at once */ for (i = 0; i < VerbCount; i++) { IngotParm result; Ingot *T = XtNew(Ingot); XtResource *temp; ListItem *item = MidasFindItemInList(IngotRList,VerbVector[i]); if (item == 0) { temp = (XtResource *) XtMalloc(sizeof(XtResource)*2); temp[0] = resources[0]; temp[1] = resources[1]; temp[0].resource_name = XtNewString(VerbVector[i]); temp[1].resource_name = strcpy(XtMalloc(strlen(VerbVector[i])+strlen(Option)+1),VerbVector[i]); strcat(temp[1].resource_name,Option); item = MidasAddItemToList(IngotRList,temp->resource_name); item->Pointer = temp; } else temp = item->Pointer; XtGetApplicationResources(w,(XtPointer) &result,temp,XtNumber(resources), NULL,0); if (result.Command == 0 || *result.Command == '\0') T->Command = 0; else T->Command = XtNewString(result.Command); T->Valued = 0; T->Parent = w; T->ValueOwner = 0; T->CallbackList = 0; T->ExecuteWhenCreated = result.ExecuteWhenCreated; item = MidasAddItemToList(TList,VerbVector[i]); item->Pointer = T; } XtFree(Input); for (item = TList->First; item != 0; item = item->Next) { Widget SW; Ingot *T = item->Pointer; if (T->Valued == 0) MidasInheritIngotValue(T,item->Entry); if (T->Command != 0) { if (T->Valued == 0) { ListItem *item; Ingot *ValueOwner = T->ValueOwner; if (ValueOwner->CallbackList == 0) ValueOwner->CallbackList = MidasCreateEmptyList(""); item = MidasAddItemToListPos(ValueOwner->CallbackList,XtName(w),0); item->Pointer = T; } if (T->ExecuteWhenCreated) MidasQueueCommand(w,T->Command); } } } void MidasInitializeIngots() { IngotRList = MidasCreateEmptyList("IngotResourceList"); MidasDeclareFunction("GETINGOT(Widget,name)" ,MidasGetIngot); MidasDeclareFunction("GETCALLBACK(Widget,name)" ,MidasGetCallback); MidasDeclareFunction("GETVALUEOWNER(Widget,name)" ,MidasGetValueOwner); MidasDeclareFunction("GETINGOTOPTION(Widget,name)" ,MidasGetIngotOption); MidasDeclareVerb("SET INGOT Widget *name any..." ,MidasSetIngotP); MidasDeclareVerb("GET INGOTS list Widget" ,MidasGetIngots); MidasDeclareVerb("SET CALLBACK Widget name name...", MidasSetCallback); MidasDeclareVerb("SET INGOT OPTION Widget name Boolean",MidasSetIngotOption); MidasDeclareVerb("STORE CALLBACK Widget name", MidasStoreCallback); }