earlybrowserreborn - Rev 1

Subversion Repositories:
Rev:
#include <Mrm/MrmAppl.h>                        /* Motif Toolkit and MRM */
#include "midaslist.h"    
#include "midasoperand.h"
#include "midaswidget.h"
#include "midasshell.h"
#include <string.h>

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->Application->Database,new,value);

    strcat(new,Option);
    value = MidasConvertToString(MidasGetIngotOption(w,cname));
    XrmPutStringResource(&ms->Application->Database,new,value);

    ms->Application->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->Application->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);
}