/* 
 * $Id: x11gui.c,v 1.7 2003/02/16 12:43:37 isizaka Exp isizaka $
 * 
 * This file is part of "Ngraph for X11".
 * 
 * Copyright (C) 2002, Satoshi ISHIZAKA. isizaka@msa.biglobe.ne.jp
 * 
 * "Ngraph for X11" 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.
 * 
 * "Ngraph for X11" 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 this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 * 
 */

/**
 *
 * $Log: x11gui.c,v $
 * Revision 1.7  2003/02/16 12:43:37  isizaka
 * for release 6.13.18
 *
 * Revision 1.6  2002/07/06 08:57:25  isizaka
 * change to GPL.
 *
 * Revision 1.5  2001/07/14 17:44:50  isizaka
 * for 6.03.14
 *
 * Revision 1.4  2001/03/23 12:17:43  isizaka
 * for 6.3.13
 *
 * Revision 1.3  1999/04/11 06:09:20  isizaka
 * *** empty log message ***
 *
 * Revision 1.2  1999/03/20 12:32:54  isizaka
 * minor change
 *
 * Revision 1.1  1999/03/17 13:29:01  isizaka
 * Initial revision
 *
 *
 **/

#include <Xm/XmAll.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include <limits.h>

#include "motif12.h"
#include "x11gui.h"

extern XtAppContext Application;
void ResetEvent();

struct nGetOpenFileData {
  Widget parent,widget;
  int ret;
  char *title;
  char **initdir;
  char *initfil;
  int chdir;
  char *filter;
  char *ext;
  char *file;
  int mustexist;
  int multi;
  int changedir;
} FileSelection={NULL,NULL};

struct ColorDialog {
  Widget parent,widget;
  int ret;  
  char *resource;
  void (*SetupWindow)(Widget w,void *data,int makewidget);
  void (*CloseWindow)(Widget w,void *data);
  int R,G,B;
  Widget RS,GS,BS;
  Widget CB[24]; 
} ColorSelection={NULL,NULL};

struct DialogType {
  Widget parent,widget;
  int ret;
  char *resource;
  int (*SetupWindow)(Widget w,void *data,int makewidget);
  int (*CloseWindow)(Widget w,void *data);
};

void DialogOkCallback(Widget w,XtPointer client_data,XtPointer call_data)
{
  struct DialogType *data;
  data=(struct DialogType *)client_data;
  data->ret=IDOK;
  if (data->CloseWindow!=NULL) data->CloseWindow(w,data);
}

void DialogCancelCallback(Widget w,XtPointer client_data,XtPointer call_data)
{
  struct DialogType *data;
  data=(struct DialogType *)client_data;
  data->ret=IDCANCEL;
  if (data->CloseWindow!=NULL) data->CloseWindow(w,data);
}

int DialogExecute(Widget parent,void *dialog)
{
  Arg al[20];
  Cardinal ac;
  Widget dlg;
  XEvent event;
  struct DialogType *data;

  data=(struct DialogType *)dialog;
  if ((data->widget!=NULL) && (data->parent!=parent)) {
    XtDestroyWidget(data->widget);
    ResetEvent();
    data->widget=NULL;
  }
  if (data->widget==NULL) {
    ac=0;
    XtSetArg(al[ac],XmNdialogStyle,XmDIALOG_FULL_APPLICATION_MODAL); ac++;
    XtSetArg(al[ac],XmNautoUnmanage,FALSE); ac++;
    dlg=XmCreateMessageDialog(parent,data->resource,al,ac); 
    XtVaSetValues(dlg,XmNnoResize,True,NULL);
    XtUnmanageChild(XmMessageBoxGetChild(dlg,XmDIALOG_HELP_BUTTON));
    XtUnmanageChild(XmMessageBoxGetChild(dlg,XmDIALOG_MESSAGE_LABEL));
    XtAddCallback(dlg,XmNokCallback,DialogOkCallback,data);
    XtAddCallback(dlg,XmNcancelCallback,DialogCancelCallback,data);
    data->parent=parent;
    data->widget=dlg;
    data->SetupWindow(dlg,data,TRUE);
  } else {
    dlg=data->widget;
    data->SetupWindow(dlg,data,FALSE);
  }
  if (data->widget!=NULL) XtManageChild(dlg);
  data->widget=dlg;
  data->ret=IDLOOP;
  while (XtIsManaged(dlg) && (data->ret==IDLOOP)) {
    XtAppNextEvent(Application,&event);
    XtDispatchEvent(&event);
  }
  if (XtIsManaged(dlg)) XtUnmanageChild(dlg);
  if (data->ret==IDLOOP) data->ret=IDCANCEL;
  return data->ret;
}

void MessageBeep(Widget parent)
{
  XBell(XtDisplay(parent),0);
}

void MBOkCallback(Widget w,XtPointer client_data,XtPointer call_data)
{
  *(int *)client_data=IDOK;
}

void MBCancelCallback(Widget w,XtPointer client_data,XtPointer call_data)
{
  *(int *)client_data=IDCANCEL;
}

void MBYesCallback(Widget w,XtPointer client_data,XtPointer call_data)
{
  *(int *)client_data=IDYES;
}

void MBNoCallback(Widget w,XtPointer client_data,XtPointer call_data)
{
  *(int *)client_data=IDNO;
}

int MessageBox(Widget parent,char *message,char *title,int mode)
{
  Arg al[20];
  Cardinal ac;
  Widget dlg,yes,no,cancel;
  XmString msg,tt;
  XEvent event;
  int data;

  ac=0;
  XtSetArg(al[ac],XmNdialogStyle,XmDIALOG_FULL_APPLICATION_MODAL); ac++;
  msg=XmStringCreateLtoR(message,XmFONTLIST_DEFAULT_TAG);
  XtSetArg(al[ac],XmNmessageString,msg); ac++;
  if (title==NULL) title="Error";
  tt=XmStringCreate(title,XmFONTLIST_DEFAULT_TAG);
  XtSetArg(al[ac],XmNdialogTitle,tt); ac++;
  if ((mode==MB_YESNOCANCEL) || (mode==MB_YESNO)) {
    dlg=XmCreateQuestionDialog(parent,"messagebox",al,ac);
  } else if (mode==MB_ERROR) {
    dlg=XmCreateErrorDialog(parent,"messagebox",al,ac);
  } else {
    dlg=XmCreateMessageDialog(parent,"messagebox",al,ac);
  }
  XtVaSetValues(dlg,XmNnoResize,TRUE,NULL);
  XmStringFree(msg);
  XmStringFree(tt);
  if ((mode==MB_YESNOCANCEL) || (mode==MB_YESNO)) {
    XtUnmanageChild(XmMessageBoxGetChild(dlg,XmDIALOG_OK_BUTTON));
    XtUnmanageChild(XmMessageBoxGetChild(dlg,XmDIALOG_CANCEL_BUTTON));
    XtUnmanageChild(XmMessageBoxGetChild(dlg,XmDIALOG_HELP_BUTTON));
    ac=0;
/*    XtSetArg(al[ac],XmNshowAsDefault,TRUE); ac++; */
    yes=XmCreatePushButton(dlg,"Yes",al,ac);
    XtManageChild(yes);
    ac=0;
    no=XmCreatePushButton(dlg,"No",al,ac);
    XtManageChild(no);
    XtAddCallback(yes,XmNdisarmCallback,MBYesCallback,&data);
    XtAddCallback(no,XmNdisarmCallback,MBNoCallback,&data);
    if (mode==MB_YESNOCANCEL) {
      ac=0;
      cancel=XmCreatePushButton(dlg,"Cancel",al,ac);
      XtManageChild(cancel);
      XtAddCallback(cancel,XmNdisarmCallback,MBCancelCallback,&data);
    }
  } else if (mode==MB_OKCANCEL) {
    XtUnmanageChild(XmMessageBoxGetChild(dlg,XmDIALOG_HELP_BUTTON));
    XtAddCallback(dlg,XmNokCallback,MBOkCallback,&data);
    XtAddCallback(dlg,XmNcancelCallback,MBCancelCallback,&data);
  } else {
    XtUnmanageChild(XmMessageBoxGetChild(dlg,XmDIALOG_CANCEL_BUTTON));
    XtUnmanageChild(XmMessageBoxGetChild(dlg,XmDIALOG_HELP_BUTTON));
    XtAddCallback(dlg,XmNokCallback,MBOkCallback,&data);
  }
  XtManageChild(dlg);
  data=IDLOOP;
  while (XtIsManaged(dlg) && (data==IDLOOP)) {
    XtAppNextEvent(Application,&event);
    XtDispatchEvent(&event);
  }
  if (data==IDLOOP) {
    if ((mode==MB_OK) || (mode==MB_ERROR)) data=IDOK;
    else if (mode==MB_YESNO) data=IDNO;
    else data=IDCANCEL; 
  }
  XtUnmanageChild(dlg);
  XtDestroyWidget(dlg);
  ResetEvent();
  return data;
}

int DialogInput(Widget parent,char *title,char *mes,char **s)
{
  Arg al[20];
  Cardinal ac;
  Widget dlg,rc,text;
  XmString tt;
  XEvent event;
  int data;

  ac=0;
  XtSetArg(al[ac],XmNdialogStyle,XmDIALOG_FULL_APPLICATION_MODAL); ac++;
  tt=XmStringCreate(title,XmFONTLIST_DEFAULT_TAG);
  XtSetArg(al[ac],XmNdialogTitle,tt); ac++;
  dlg=XmCreateMessageDialog(parent,NULL,al,ac);
  XtVaSetValues(dlg,XmNnoResize,TRUE,NULL);
  XmStringFree(tt);
  XtUnmanageChild(XmMessageBoxGetChild(dlg,XmDIALOG_HELP_BUTTON));
  XtAddCallback(dlg,XmNokCallback,MBOkCallback,&data);
  XtAddCallback(dlg,XmNcancelCallback,MBCancelCallback,&data);
  ac=0;
  XtSetArg(al[ac],XmNorientation,XmVERTICAL); ac++;
  XtManageChild(rc=XmCreateRowColumn(dlg,NULL,al,ac));
  ac=0;
  XtManageChild(XmCreateLabel(rc,mes,al,ac));
  ac=0;
  XtManageChild(text=XmCreateTextField(rc,"text",al,ac));
  XtManageChild(dlg);
  data=IDLOOP;
  while (XtIsManaged(dlg) && (data==IDLOOP)) {
    XtAppNextEvent(Application,&event);
    XtDispatchEvent(&event);
  }
  if (data==IDLOOP) data=IDCANCEL; 
  if (data==IDOK) XtVaGetValues(text,XmNvalue,s,NULL);
  else *s=NULL;
  if (XtIsManaged(dlg)) XtUnmanageChild(dlg);
  XtDestroyWidget(dlg);
  ResetEvent();
  return data;
}

void FSOkCallback(Widget w,XtPointer client_data,XtPointer call_data)
{
  struct nGetOpenFileData *data;
  XmFileSelectionBoxCallbackStruct *fs;
  char *dir,*file,*file2,*file3;
  int i,len;
  struct stat buf;

  data=&FileSelection;
  fs=(XmFileSelectionBoxCallbackStruct *)call_data;
  XmStringGetLtoR(fs->value,XmFONTLIST_DEFAULT_TAG,&file);
  if ((file!=NULL) && (strlen(file)>0)) {
    for (i=strlen(file)-1;(i>0)&&(file[i]!='/')&&(file[i]!='.');i--);
    if ((file[i]!='.') && (data->ext!=NULL)) len=strlen(data->ext)+1;
    else len=0;
    if ((file2=malloc(strlen(file)+len+1))!=NULL) {
      strcpy(file2,file);
      if (len!=0) {
        file2[strlen(file)]='.';
        strcpy(file2+strlen(file)+1,data->ext);
      }
      if (data->mustexist) {
        if ((stat(file2,&buf)!=0) || ((buf.st_mode & S_IFMT)!=S_IFREG) 
        || (access(file2,R_OK)!=0)) {
          XBell(XtDisplay(w),0);
          free(file2);
          XtFree(file);
          return;
        }
      } else {
	if ((stat(file2,&buf)==0) && ((buf.st_mode & S_IFMT)!=S_IFREG)) {
          XBell(XtDisplay(w),0);
          free(file2);
          XtFree(file);
          return;
        }
      }
      if (data->file==NULL) {
        data->file=file2;
      } else {
        len=strlen(data->file);
        if ((file3=malloc(len+strlen(file2)+2))!=NULL) {
          strcpy(file3,data->file);
          file3[len]=' ';
          strcpy(file3+len+1,file2);
          free(data->file);
          data->file=file3;
        }
        free(file2);
      }
      XtFree(file);
    }
  } else {
    XBell(XtDisplay(w),0);
    XtFree(file);
    return;
  }
  if (data->changedir) {
    data->chdir=XmToggleButtonGetState(
                XtNameToWidget(data->widget,"*Change_current_directory"));
    if (data->chdir) {
      if (data->initdir!=NULL) {
        free(*(data->initdir));
        XmStringGetLtoR(fs->dir,XmFONTLIST_DEFAULT_TAG,&dir);
        if ((*(data->initdir)=malloc(strlen(dir)+1))!=NULL) {
          strcpy(*(data->initdir),dir);
          XtFree(dir);
        }
      }
    }
  }
  data->ret=IDOK;
}

void FSCancelCallback(Widget w,XtPointer client_data,XtPointer call_data)
{
  struct nGetOpenFileData *data;

  data=&FileSelection;
  data->ret=IDCANCEL;
}

int FileSelectionDialog(Widget parent)
{
  struct nGetOpenFileData *data;
  Arg al[20];
  Cardinal ac;
  Widget dlg,rc,fil;
  XmString tt,pat,dir;
  XEvent event;

  data=&FileSelection;
  if ((data->widget!=NULL) && (data->parent!=parent)) {
    XtDestroyWidget(data->widget);
    ResetEvent();
    data->widget=NULL;
  }
  data->parent=parent;
  if (data->widget==NULL) {
    ac=0;
    XtSetArg(al[ac],XmNdialogStyle,XmDIALOG_FULL_APPLICATION_MODAL); ac++;
    XtSetArg(al[ac],XmNautoUnmanage,FALSE); ac++;
    dlg=XmCreateFileSelectionDialog(data->parent,"FileSelectionBox",al,ac);
    data->widget=dlg;
    ac=0;
    XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
    XtManageChild(rc=XmCreateRowColumn(dlg,NULL,al,ac));
    ac=0;
    XtManageChild(XmCreateToggleButton(rc,"Change_current_directory",al,ac));
    XtUnmanageChild(XmFileSelectionBoxGetChild(dlg,XmDIALOG_HELP_BUTTON));
    XtVaSetValues(XmFileSelectionBoxGetChild(dlg,XmDIALOG_LIST),
                  XmNlistMarginWidth,5,NULL);
    XtVaSetValues(XmFileSelectionBoxGetChild(dlg,XmDIALOG_DIR_LIST),
                  XmNlistMarginWidth,5,NULL);
    XtAddCallback(dlg,XmNokCallback,FSOkCallback,data);
    XtAddCallback(dlg,XmNcancelCallback,FSCancelCallback,data);
  } else {
    dlg=data->widget;
    XmListDeselectAllItems(XmFileSelectionBoxGetChild(dlg,XmDIALOG_LIST));
  }
/*
  if (data->multi) {
    XtVaSetValues(XmFileSelectionBoxGetChild(dlg,XmDIALOG_LIST),
                  XmNselectionPolicy,XmEXTENDED_SELECT,NULL);
  } else {
    XtVaSetValues(XmFileSelectionBoxGetChild(dlg,XmDIALOG_LIST),
                  XmNselectionPolicy,XmBROWSE_SELECT,NULL);
  }
*/
  data->widget=dlg;
  tt=XmStringCreate(data->title,XmFONTLIST_DEFAULT_TAG);
  XtVaSetValues(dlg,XmNdialogTitle,tt,NULL);
  XmStringFree(tt);
  pat=XmStringCreate(data->filter,XmFONTLIST_DEFAULT_TAG);
  XtVaSetValues(dlg,XmNpattern,pat,NULL);
  XmStringFree(pat);
  if (data->initdir!=NULL) {
    dir=XmStringCreate(*(data->initdir),XmFONTLIST_DEFAULT_TAG);
    XtVaSetValues(dlg,XmNdirectory,dir,NULL);
    XmStringFree(dir);
  }
  if (data->changedir) {
    XtManageChild(XtNameToWidget(dlg,"*Change_current_directory"));
    if (data->chdir) 
      XtVaSetValues(XtNameToWidget(dlg,"*Change_current_directory"),
                    XmNset,XmSET,NULL);
    else
      XtVaSetValues(XtNameToWidget(dlg,"*Change_current_directory"),
                    XmNset,XmUNSET,NULL);
  } else {
    XtUnmanageChild(XtNameToWidget(dlg,"*Change_current_directory"));
  }
  if (data->initfil!=NULL) {
    fil=XmFileSelectionBoxGetChild(dlg,XmDIALOG_TEXT);
    XtVaSetValues(fil,XmNvalue,data->initfil,NULL);
  }
  XtManageChild(dlg);
  data->ret=IDLOOP;
  while (XtIsManaged(dlg) && (data->ret==IDLOOP)) {
    XtAppNextEvent(Application,&event);
    XtDispatchEvent(&event);
  }
  if (XtIsManaged(dlg)) XtUnmanageChild(dlg);
  if (data->ret==IDLOOP) data->ret=IDCANCEL;
  return data->ret;
}

int nGetOpenFileNameMulti(Widget parent,
                     char *title,char *defext,char **initdir,char *initfil,
                     char **file,char *filter,int chd)
{
  struct nGetOpenFileData *data;
  int ret;
  
  data=&FileSelection;
  data->title=title;
  data->initdir=initdir;
  data->initfil=initfil;
  data->filter=filter;
  data->file=NULL;
  data->chdir=chd;
  data->ext=defext;
  data->mustexist=TRUE;
  data->multi=TRUE;
  data->changedir=TRUE;
  ret=FileSelectionDialog(parent);
  *file=data->file;
  if (data->chdir && (initdir!=NULL)) chdir(*initdir);
  return ret;
}

int nGetOpenFileName(Widget parent,
                     char *title,char *defext,char **initdir,char *initfil,
                     char **file,char *filter,int exist,int chd)
{
  struct nGetOpenFileData *data;
  int ret;
  
  data=&FileSelection;
  data->title=title;
  data->initdir=initdir;
  data->initfil=initfil;
  data->filter=filter;
  data->file=NULL;
  data->chdir=chd;
  data->ext=defext;
  data->mustexist=exist;
  data->multi=FALSE;
  data->changedir=TRUE;
  ret=FileSelectionDialog(parent);
  *file=data->file;
  if (data->chdir && (initdir!=NULL)) chdir(*initdir);
  return ret;
}

int nGetSaveFileName(Widget parent,
                     char *title,char *defext,char **initdir,char *initfil,
                     char **file,char *filter,int chd)
{
  struct nGetOpenFileData *data;
  int ret;
  
  data=&FileSelection;
  data->title=title;
  data->initdir=initdir;
  data->initfil=initfil;
  data->filter=filter;
  data->file=NULL;
  data->chdir=chd;
  data->ext=defext;
  data->mustexist=FALSE;
  data->multi=FALSE;
  data->changedir=TRUE;
  ret=FileSelectionDialog(parent);
  *file=data->file;
  if (data->chdir && (initdir!=NULL)) chdir(*initdir);
  return ret;
}

unsigned long RGB(int R,int G,int B);

void ColorDialogScale(Widget w,XtPointer client_data,XtPointer call_data)
{
  struct ColorDialog *d;
  XmScaleCallbackStruct *dd;

  d=&ColorSelection;
  dd=(XmScaleCallbackStruct *)call_data;
  if (w==d->RS) {
    d->R=dd->value;
  } else if (w==d->GS) {
    d->G=dd->value;
  } else if (w==d->BS) {
    d->B=dd->value;
  }
  XtVaSetValues(XtNameToWidget(d->widget,"*color"),
                XmNbackground,RGB(d->R,d->G,d->B),NULL);
}

void ColorDialogCB(Widget w,XtPointer client_data,XtPointer call_data)
{
  struct ColorDialog *d;
  int i;

  d=&ColorSelection;
  for (i=0;i<24;i++) if (w==d->CB[i]) break;
  switch (i) {
  case 0:
    d->R=0; d->G=0; d->B=0;
    break;
  case 1:
    d->R=0; d->G=0; d->B=255;
    break;
  case 2:
    d->R=0; d->G=255; d->B=0;
    break;
  case 3:
    d->R=0; d->G=255; d->B=255;
    break;
  case 4:
    d->R=255; d->G=0; d->B=0;
    break;
  case 5:
    d->R=255; d->G=0; d->B=255;
    break;
  case 6:
    d->R=255; d->G=255; d->B=0;
    break;
  case 7:
    d->R=255; d->G=255; d->B=255;
    break;
  case 8:
    d->R=63; d->G=63; d->B=63;
    break;
  case 9:
    d->R=127; d->G=127; d->B=255;
    break;
  case 10:
    d->R=127; d->G=255; d->B=127;
    break;
  case 11:
    d->R=127; d->G=255; d->B=255;
    break;
  case 12:
    d->R=255; d->G=127; d->B=127;
    break;
  case 13:
    d->R=255; d->G=127; d->B=255;
    break;
  case 14:
    d->R=255; d->G=255; d->B=127;
    break;
  case 15:
    d->R=191; d->G=191; d->B=191;
    break;
  case 16:
    d->R=127; d->G=127; d->B=127;
    break;
  case 17:
    d->R=0; d->G=0; d->B=127;
    break;
  case 18:
    d->R=0; d->G=127; d->B=0;
    break;
  case 19:
    d->R=0; d->G=127; d->B=127;
    break;
  case 20:
    d->R=127; d->G=0; d->B=0;
    break;
  case 21:
    d->R=127; d->G=0; d->B=127;
    break;
  case 22:
    d->R=127; d->G=127; d->B=0;
    break;
  case 23:
    d->R=127; d->G=127; d->B=127;
    break;
  }
  XtVaSetValues(XtNameToWidget(d->widget,"*R"),XmNvalue,d->R,NULL);
  XtVaSetValues(XtNameToWidget(d->widget,"*G"),XmNvalue,d->G,NULL);
  XtVaSetValues(XtNameToWidget(d->widget,"*B"),XmNvalue,d->B,NULL);
  XtVaSetValues(XtNameToWidget(d->widget,"*color"),
                XmNbackground,RGB(d->R,d->G,d->B),NULL);
}

void ColorDialogSetup(Widget w,void *data,int makewidget)
{
  Arg al[20];
  Cardinal ac;
  Widget rc,rc2,rc3,urc,frame;
  struct ColorDialog *d;
  int i;
  
  d=&ColorSelection;
  if (makewidget) {
  ac=0;
  XtSetArg(al[ac],XmNorientation,XmVERTICAL); ac++;
  XtManageChild(rc=XmCreateRowColumn(w,"rc",al,ac));

  ac=0;
  XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
  XtManageChild(urc=XmCreateRowColumn(rc,"urc",al,ac));

  ac=0;
  XtManageChild(frame=XmCreateFrame(urc,"buttonf",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNorientation,XmVERTICAL); ac++;
  XtManageChild(rc2=XmCreateRowColumn(frame,"buttonrc",al,ac));

  ac=0;
  XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
  XtManageChild(rc3=XmCreateRowColumn(rc2,"buttonrc1",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(0,0,0)); ac++;
  XtManageChild(d->CB[0]=XmCreatePushButton(rc3,"   ",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(0,0,255)); ac++;
  XtManageChild(d->CB[1]=XmCreatePushButton(rc3,"   ",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(0,255,0)); ac++;
  XtManageChild(d->CB[2]=XmCreatePushButton(rc3,"   ",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(0,255,255)); ac++;
  XtManageChild(d->CB[3]=XmCreatePushButton(rc3,"   ",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(255,0,0)); ac++;
  XtManageChild(d->CB[4]=XmCreatePushButton(rc3,"   ",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(255,0,255)); ac++;
  XtManageChild(d->CB[5]=XmCreatePushButton(rc3,"   ",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(255,255,0)); ac++;
  XtManageChild(d->CB[6]=XmCreatePushButton(rc3,"   ",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(255,255,255)); ac++;
  XtManageChild(d->CB[7]=XmCreatePushButton(rc3,"   ",al,ac));

  ac=0;
  XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
  XtManageChild(rc3=XmCreateRowColumn(rc2,"buttonrc2",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(63,63,63)); ac++;
  XtManageChild(d->CB[8]=XmCreatePushButton(rc3,"   ",al,ac));
  ac=0;
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(127,127,255)); ac++;
  XtManageChild(d->CB[9]=XmCreatePushButton(rc3,"   ",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(127,255,127)); ac++;
  XtManageChild(d->CB[10]=XmCreatePushButton(rc3,"   ",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(127,255,255)); ac++;
  XtManageChild(d->CB[11]=XmCreatePushButton(rc3,"   ",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(255,127,127)); ac++;
  XtManageChild(d->CB[12]=XmCreatePushButton(rc3,"   ",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(255,127,255)); ac++;
  XtManageChild(d->CB[13]=XmCreatePushButton(rc3,"   ",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(255,255,127)); ac++;
  XtManageChild(d->CB[14]=XmCreatePushButton(rc3,"   ",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(191,191,191)); ac++;
  XtManageChild(d->CB[15]=XmCreatePushButton(rc3,"   ",al,ac));

  ac=0;
  XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
  XtManageChild(rc3=XmCreateRowColumn(rc2,"buttonrc3",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(127,127,127)); ac++;
  XtManageChild(d->CB[16]=XmCreatePushButton(rc3,"   ",al,ac));
  ac=0;
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(0,0,127)); ac++;
  XtManageChild(d->CB[17]=XmCreatePushButton(rc3,"   ",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(0,127,0)); ac++;
  XtManageChild(d->CB[18]=XmCreatePushButton(rc3,"   ",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(0,127,127)); ac++;
  XtManageChild(d->CB[19]=XmCreatePushButton(rc3,"   ",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(127,0,0)); ac++;
  XtManageChild(d->CB[20]=XmCreatePushButton(rc3,"   ",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(127,0,127)); ac++;
  XtManageChild(d->CB[21]=XmCreatePushButton(rc3,"   ",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(127,127,0)); ac++;
  XtManageChild(d->CB[22]=XmCreatePushButton(rc3,"   ",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNbackground,RGB(127,127,127)); ac++;
  XtManageChild(d->CB[23]=XmCreatePushButton(rc3,"   ",al,ac));

  ac=0;
  XtManageChild(frame=XmCreateFrame(urc,"colorf",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNrecomputeSize,FALSE); ac++;
  XtSetArg(al[ac],XmNlabelType,XmPIXMAP); ac++;
  XtManageChild(XmCreateLabel(frame,"color",al,ac));

  ac=0;
  XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
  XtManageChild(rc2=XmCreateRowColumn(rc,"rrc",al,ac));
  ac=0;
  XtManageChild(XmCreateLabel(rc2,"Red",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNminimum,0); ac++;
  XtSetArg(al[ac],XmNmaximum,255); ac++;
  XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
  XtSetArg(al[ac],XmNshowValue,XmNEAR_SLIDER); ac++;
  XtManageChild(d->RS=XmCreateScale(rc2,"R",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
  XtManageChild(rc2=XmCreateRowColumn(rc,"grc",al,ac));
  ac=0;
  XtManageChild(XmCreateLabel(rc2,"Green",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNminimum,0); ac++;
  XtSetArg(al[ac],XmNmaximum,255); ac++;
  XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
  XtSetArg(al[ac],XmNshowValue,XmNEAR_SLIDER); ac++;
  XtManageChild(d->GS=XmCreateScale(rc2,"G",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
  XtManageChild(rc2=XmCreateRowColumn(rc,"brc",al,ac));
  ac=0;
  XtManageChild(XmCreateLabel(rc2,"Blue",al,ac));
  ac=0;
  XtSetArg(al[ac],XmNminimum,0); ac++;
  XtSetArg(al[ac],XmNmaximum,255); ac++;
  XtSetArg(al[ac],XmNorientation,XmHORIZONTAL); ac++;
  XtSetArg(al[ac],XmNshowValue,XmNEAR_SLIDER); ac++;
  XtManageChild(d->BS=XmCreateScale(rc2,"B",al,ac));

  XtAddCallback(d->RS,XmNvalueChangedCallback,ColorDialogScale,d);
  XtAddCallback(d->GS,XmNvalueChangedCallback,ColorDialogScale,d);
  XtAddCallback(d->BS,XmNvalueChangedCallback,ColorDialogScale,d);
  for (i=0;i<24;i++)
    XtAddCallback(d->CB[i],XmNdisarmCallback,ColorDialogCB,d);
  }
  XtVaSetValues(XtNameToWidget(w,"*R"),XmNvalue,d->R,NULL);
  XtVaSetValues(XtNameToWidget(w,"*G"),XmNvalue,d->G,NULL);
  XtVaSetValues(XtNameToWidget(w,"*B"),XmNvalue,d->B,NULL);
  XtVaSetValues(XtNameToWidget(w,"*color"),XmNbackground,RGB(d->R,d->G,d->B),NULL);
}

void ColorDialogClose(Widget w,void *data)
{
}

int GetColor(Widget parent,int *r,int *g,int *b)
{
  struct ColorDialog *d;
  int ret;

  d=&ColorSelection;
  d->resource="color";
  d->SetupWindow=ColorDialogSetup;
  d->CloseWindow=ColorDialogClose;
  d->R=*r;
  d->G=*g;
  d->B=*b;
  if ((ret=DialogExecute(parent,d))==IDOK) {
    *r=d->R;
    *g=d->G;
    *b=d->B;
  }
  return ret;
}

