/* mtink.c
 *
 * Copyright (C) 2001 Jean-Jacques Sarton jj.sarton@t-online.de
 */
/*
 * 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.
 *
 * This program 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.
 */


#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <ctype.h>
#include <strings.h>
#include <signal.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <unistd.h>

#include <X11/Intrinsic.h>
#include <X11/StringDefs.h>
#include <X11/Xlib.h>
#include <Xm/Xm.h>
#include <Xm/MwmUtil.h>
#include <X11/Core.h>
#include <X11/Shell.h>
#include <Xm/PanedW.h>
#include <Xm/MainW.h>
#include <Xm/Form.h>
#include <Xm/ScrollBar.h>
#include <Xm/ScrolledW.h>
#include <Xm/List.h>
#include <Xm/Separator.h>
#include <Xm/RowColumn.h>
#include <Xm/TextF.h>
#include <Xm/Display.h>


#include <Xm/Text.h>
#include <Xm/RowColumn.h>
#include <Xm/ToggleB.h>
#include <Xm/PushB.h>
#include <Xm/Label.h>
#include <Xm/Frame.h>
#include <Xm/MessageB.h>
#include <Xm/MwmUtil.h>
#include <Xm/Scale.h>
#include <Xm/Protocols.h>

#include "mtink.h"
#include "rcfile.h"
#include "cfg1.h"
#include "cfg2.h"
#include "alignbt.h"
#include "scrtxt.h"
#include "cmd.h"
#include "version.h"

#include "d4lib.h"
#include "tooltip.h"
#include "checkenv.h"
#include "access.h"

#ifdef MACOS
#include "usbHlp.h"
#endif
#ifndef TEST
#define TEST 1
#endif

#include "micon.h"

#include "rdPrtDesc.h"
#define defaultConfigData configData
#define defaultConfigDataSize configEntries


int           deviceHdl = -1; /* for write / read to / from printer */
char         *prgName;
int           pc1 = 0; /* black */
int           pc2 = 0; /* cyan  */
int           pc3 = 0; /* magenta */
int           pc4 = 0; /* yellow */
int           pc5 = 0; /* light cyan or red*/
int           pc6 = 0; /* light magenta or blue*/
int           pc7 = 0; /* photo black or glossy */
int           pc8 = 0; /* glossy if 8 inks */

char         *printerName;
char         *printerState;
char         *displayStr;
int           configFileIdx = 0;
int           doCyclicScan  = 0; /* ask IQ peridically allowed */
char          guiLanguage[10];

char         *testFile = NULL; /* test */
extern int    inFromFile;      /* test */

Widget        topLevel;
Widget        mainForm;
Widget        mainWindow;

Widget        clean_PB;
Widget        check_PB;
Widget        reset_PB;
Widget        cartridge_PB;
Widget        align_PB;
int           usePopup = False;

XtAppContext  theApp;
Display      *display;

Widget createLayout(char *language);
static Widget CreateScale(Widget parent, char *name, Widget top);
static void help_CB(Widget w, XtPointer clientData, XtPointer callData);
static void pref_CB(Widget w, XtPointer clientData, XtPointer callData);
void setProgressBarColor(char colorModel);

Widget title_LB;
Widget legend_LB;

/* scale widgets */
Widget scaleC;
Widget scaleB;
Widget scaleM;
Widget scaleY;
Widget scaleLc;
Widget scaleLm;
Widget scaleLb;
Widget scalePh;

/* scale labels */
Widget scaleCLb;
Widget scaleBLb;
Widget scaleMLb;
Widget scaleYLb;
Widget scaleLcLb;
Widget scaleLmLb;
Widget scaleLbLb;
Widget scalePhLb;

Widget pref_PB;
Widget ok_PB;
Widget help_PB;
Widget about_PB;
Widget printerState_LB;
Widget state_LB;
Widget pref_LB;

XtIntervalId tid = 0;
void handleTi(XtPointer closure, XtIntervalId *tidp);

configData_t actConfig;
char *mainResource;
static   int  x,y;
static int cmdCount = 0;
#define ASK_EVERY 10
long inkTimer = ASK_EVERY;
Widget miconOK;
Widget displayW;

#define NAME "EpsonUtil"

appResourceRec_t appResourceRec = {
"error",
"self test",
"busy",
"printing",
"ok",
"cleaning",
"unknown",
"Other Printer",
"Save",
"About",
"Cancel",
"Next",
"Back",
"ctTxt0",
"ctTxt00",
"ctTxt1",
"ctTxt2",
"ctTxt3",
"ctTxt3",
"ctTxtL",
"ctTxt5",
"ctTxt6",
"ctTxt7",
"ctTxt8",
"ctTxt9",
"ctTxtC",
"exTxt0",
"exTxt00",
"exTxt1",
"exTxt2",
"exTxt3",
};

XtResource resources[] = {

  {"error", "error", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, error), XtRImmediate, (XtPointer) "error" },

  {"selfTest", "selfTest", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, selfTest), XtRImmediate, (XtPointer) "self test" },

  {"busy", "busy", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, busy), XtRImmediate, (XtPointer) "busy" },

  {"printing", "printing", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, printing), XtRImmediate, (XtPointer) "printing" },

  {"ok", "ok", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, ok), XtRImmediate, (XtPointer) "ok" },

  {"cleaning", "cleaning", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, cleaning), XtRImmediate, (XtPointer) "cleaning" },

  {"unknown", "unknown", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, unknown), XtRImmediate, (XtPointer) "unknown" },
  {"addPrinterTxt", "*AddPrinterTxt", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, addPrinterTxt), XtRImmediate, (XtPointer)"Other Printer" },

  {"save", "save", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, save), XtRImmediate, (XtPointer)NULL },
  {"about", "about", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, about), XtRImmediate, (XtPointer)NULL },
  {"cancel", "cancel", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, cancel), XtRImmediate, (XtPointer)NULL },
  {"next", "next", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, next), XtRImmediate, (XtPointer)NULL },
  {"previous", "previous", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, previous), XtRImmediate, (XtPointer)NULL },

  {"ctTxt0", "ctTxt0", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, ctTxt0), XtRImmediate, (XtPointer)NULL },
  {"ctTxtC0", "ctTxtC0", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, ctTxtC0), XtRImmediate, (XtPointer)NULL },
  {"ctTxt1", "ctTxt1", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, ctTxt1), XtRImmediate, (XtPointer)NULL },
  {"ctTxt2", "ctTxt2", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, ctTxt2), XtRImmediate, (XtPointer)NULL },
  {"ctTxt3", "ctTxt3", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, ctTxt3), XtRImmediate, (XtPointer)NULL },

  {"ctTxt1_1", "ctTxt1_1", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, ctTxt1_1), XtRImmediate, (XtPointer)NULL },
  {"ctTxt1_2", "ctTxt1_2", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, ctTxt1_2), XtRImmediate, (XtPointer)NULL },
  {"ctTxt1_3", "ctTxt1_3", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, ctTxt1_3), XtRImmediate, (XtPointer)NULL },
    
  {"ctTxtP", "ctTxtP", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, ctTxtP), XtRImmediate, (XtPointer)NULL },
  {"ctTxtL", "ctTxtL", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, ctTxtL), XtRImmediate, (XtPointer)NULL },
  {"ctTxt4", "ctTxt4", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, ctTxt4), XtRImmediate, (XtPointer)NULL },
  {"ctTxt5", "ctTxt5", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, ctTxt5), XtRImmediate, (XtPointer)NULL },
  {"ctTxt6", "ctTxt6", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, ctTxt6), XtRImmediate, (XtPointer)NULL },
  {"ctTxt7", "ctTxt7", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, ctTxt7), XtRImmediate, (XtPointer)NULL },
  {"ctTxt8", "ctTxt8", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, ctTxt8), XtRImmediate, (XtPointer)NULL },
  {"ctTxt9", "ctTxt9", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, ctTxt9), XtRImmediate, (XtPointer)NULL },
  {"ctTxtC", "ctTxtC", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, ctTxtC), XtRImmediate, (XtPointer)NULL },

  {"exTxt0", "exTxt0", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, exTxt0), XtRImmediate, (XtPointer)NULL },
  {"exTxt00", "exTxt00", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, exTxt00), XtRImmediate, (XtPointer)NULL },
  {"exTxt1", "exTxt1", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, exTxt1), XtRImmediate, (XtPointer)NULL },
  {"exTxt2", "exTxt2", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, exTxt2), XtRImmediate, (XtPointer)NULL },
  {"exTxt3", "exTxt3", XtRString, sizeof(String),
    XtOffsetOf(appResourceRec_t, exTxt3), XtRImmediate, (XtPointer)NULL },

};

extern char *fallbackResources[];


int decodePrinterType(unsigned char *buf, int len);
int getPrinterInfo();
int decodeStatus(unsigned char *buf, int len);
Widget createNoPrinterBox(char *message);
Widget cfg1, cfg2, algn, stxt, port;
char  *browser;
char  *autodetect;
char  *miniHelp;
int    noAutoDetect;

int    waitForConfigWindow = 0;

int setConfig(void);


/*******************************************************************/
/* Function sigKill(int code)                                      */
/*                                                                 */
/* terminate gacefully if a sigkill occured                        */
/*                                                                 */
/*******************************************************************/

static void sigKill(int code)
{
   callPrg(TERMINATE,NULL, 0, 0, 0, NULL, NULL);
   exit(0);
}

/*******************************************************************/
/* Function setPrinterStateLabel(int state)                        */
/*                                                                 */
/* set the printer state label accpording to state                 */
/*                                                                 */
/*******************************************************************/

void setPrinterStateLabel(int state)
{
   char *oldState = printerState;
   XmString xms;
   switch(state)
   {
      case 0:  printerState = appResourceRec.error;    break;
      case 1:  printerState = appResourceRec.selfTest; break;
      case 2:  printerState = appResourceRec.busy;     break;
      case 3:  printerState = appResourceRec.printing; break;
      case 4:  printerState = appResourceRec.ok;       break;
      case 7:  printerState = appResourceRec.cleaning; break;
      default: printerState = appResourceRec.unknown;
   }
   if ( oldState !=  printerState )
   {
      xms = XmStringCreateSimple(printerState);
      XtVaSetValues(state_LB, XmNlabelString, xms, NULL);
      XmStringFree(xms);
   }
}

/*******************************************************************/
/* Function handleTi()                                             */
/*                                                                 */
/* Timer function for reading the remaining ink quantity           */
/*                                                                 */
/*******************************************************************/

void handleTi(XtPointer closure, XtIntervalId *tidp)
{
   char *retBuf;
   int ret = 0;
   
   /* call the get ink function */
   if ( doCyclicScan )
   {
      retBuf = NULL;
      if ( cmdCount >= inkTimer )
      {
         ret = callPrg(GET_IQ, actConfig.dev, actConfig.prot, 0, 0, &retBuf, NULL);
         cmdCount = 0;
      }
      else
      {
         ret = callPrg(RELEASE, actConfig.dev, actConfig.prot, 0, 0, &retBuf, NULL);
         cmdCount++;
      }

      if ( retBuf != NULL &&  *retBuf != '\0' )
      {
         decodeStatus((unsigned char*)retBuf, strlen(retBuf));
         refreshMainWindow();
         inkTimer=ASK_EVERY;
      }
      else
      {
         if ( ! XtIsManaged(topLevel) )
         {
            tid = XtAppAddTimeOut(theApp, CYCLE_TIME, handleTi, (XtPointer)NULL);
         }
         if ( ret )
         {
            inkTimer=1;
            cmdCount = 0;
            /* tell that we have errors */
            chgIcon(0);
            setPrinterStateLabel(0);
         }
      }
   }
   else
   {
       tid = XtAppAddTimeOut(theApp, CYCLE_TIME, handleTi, (XtPointer)NULL);
   }
}

/*******************************************************************/
/* Function exit_CB(...)                                           */
/*                                                                 */
/* terminate the programm                                          */
/*                                                                 */
/*******************************************************************/

void exit_CB(Widget w, XtPointer clientData, XtPointer callData)
{
#ifndef MACOS
   if ( actConfig.dev && strncmp(actConfig.dev,"/var",4) == 0 && miconOK )
   {
      popupIcon(x,y);
      if ( tid == 0 )
      {
        doCyclicScan = 1;
        inkTimer=1;
        tid = XtAppAddTimeOut(theApp, CYCLE_TIME, handleTi, (XtPointer)NULL);
      }
   }
   else
#endif
   {
      callPrg(TERMINATE,NULL, 0, 0, 0, NULL, NULL);
#ifdef MACOS
      unlinkFiles();
#endif
      exit(0);
   }
}

/*******************************************************************/
/* Function deleteWindow_CB(...)                                   */
/*                                                                 */
/* The WM tell us that we have to terminate, save a few values     */
/*                                                                 */
/*******************************************************************/

void deleteWindow_CB(Widget w, XtPointer clientData, XtPointer callData)
{
   int x, y;
   FILE *fp;
   char *home = getenv("HOME");
   char *fileName;

   callPrg(TERMINATE,NULL, 0, 0, 0, NULL, NULL);
   if ( iconAskPos(&x, &y) )
   {
      fileName= calloc(strlen(ConfigFile)+ strlen(home) + 50,1);
      if ( fileName )
      {
          if ( ! configFileIdx )
          {
             sprintf(fileName, "%s/.mtinksess", home);
          }
          else
          {
             sprintf(fileName, "%s/.mtinksess.%d", home, configFileIdx);
          }

          if ( fork() == 0 )
          {
             seteuid(getuid());
             if ( (fp = fopen(fileName,"w")) )
             {
                fprintf(fp,"%d %d\n",x,y);
                fclose(fp);
             }
             exit(0);
          }
          else
             wait(&x);
          free(fileName);
      }
   }
   exit(0);
}

/*******************************************************************/
/* Function readSessFile(...)                                      */
/*                                                                 */
/* Read the value for the position of our icon window              */
/*                                                                 */
/*******************************************************************/

void rdSessFile(int *x, int *y)
{
   FILE *fp;
   char *home = getenv("HOME");
   char *fileName;
   char  line[2048];

   *x = *y = -1;

   fileName= calloc(strlen(ConfigFile)+ strlen(home) + 50,1);
   if ( fileName )
   {
       if ( ! configFileIdx )
       {
          sprintf(fileName, "%s/.mtinksess", home);
       }
       else
       {
          sprintf(fileName, "%s/.mtinksess.%d", home, configFileIdx);
       }
       if ( (fp = fopen(fileName,"r")) )
       {
          if (fgets(line, sizeof(line), fp))
          {
             sscanf(line, "%d %d",x, y);
          }
          fclose(fp);
       }
       free(fileName);
   }
}

/*******************************************************************/
/* Function about_CB(...)                                          */
/*                                                                 */
/* display the about window                                        */
/*                                                                 */
/*******************************************************************/

void about_CB(Widget w, XtPointer clientData, XtPointer callData)
{
   wConfig_data_t data;

   data.printerName    = actConfig.name;
   data.bt1            = NULL;
   data.bt2            = NULL;
   data.bt3            = appResourceRec.ok;
   data.message        = appResourceRec.about;
   data.wait           = &waitForConfigWindow;
   data.colTb          = 0;
   /* show the about mask */
   popupScrolledTextWindow(mainWindow, &data);

   XtManageChild(mainWindow);

}

/*******************************************************************/
/* Function check_CB(...)                                          */
/*                                                                 */
/* Call the check nozzle code                                      */
/*                                                                 */
/*******************************************************************/

void check_CB(Widget w, XtPointer clientData, XtPointer callData)
{
   callPrg(CHECK_NOZZLE, actConfig.dev,actConfig.prot|STAY_RESIDENT, 0, actConfig.checkNeedReset, NULL, NULL);
}

/*******************************************************************/
/* Function clean_CB(...)                                          */
/*                                                                 */
/* Call the clean head  code                                       */
/*                                                                 */
/*******************************************************************/

void clean_CB(Widget w, XtPointer clientData, XtPointer callData)
{
   callPrg(CLEAN_NOZZLE, actConfig.dev,actConfig.prot|STAY_RESIDENT, 0, 0, NULL, NULL);
}

/*******************************************************************/
/* Function exchange_CB()                                          */
/*                                                                 */
/* Call the exchange cartridge code                                */
/*                                                                 */
/*******************************************************************/

void exchange_CB(Widget w, XtPointer clientData, XtPointer callData)
{
   wConfig_data_t data[10];
   Widget  actWindow = mainWindow;
   int     idx       = 0;
   int     colHead   = 0;
   char   *command   = NULL;

   doCyclicScan    = 0; /* disable IQ cyclic scan */

   data[0].printerName = actConfig.name;
   data[0].bt1     = NULL;
   data[0].bt2     = appResourceRec.cancel;
   data[0].bt3     = appResourceRec.next;
   if ( actConfig.cleanSeparate )
   {
      data[0].message = appResourceRec.exTxt00;
      data[0].colTb   = 1;
   }
   else
   {
      data[0].message = appResourceRec.exTxt0;
      data[0].colTb   = 0;
   }
   data[0].wait    = &waitForConfigWindow;

   data[1].printerName = actConfig.name;
   data[1].bt1     = NULL;
   data[1].bt2     = NULL;
   data[1].bt3     = NULL;
   data[1].message = appResourceRec.exTxt1;
   data[1].wait    = NULL;
   data[1].colTb   = 0;

   data[2].printerName = actConfig.name;
   data[2].bt1     = NULL;
   data[2].bt2     = NULL;
   data[2].bt3     = appResourceRec.next;
   data[2].message = appResourceRec.exTxt2;
   data[2].wait    = &waitForConfigWindow;
   data[2].colTb   = 0;

   data[3].printerName = actConfig.name;
   data[3].bt1     = NULL;
   data[3].bt2     = NULL;
   data[3].bt3     = NULL;
   data[3].message = appResourceRec.exTxt3;
   data[3].wait    = NULL;
   data[3].colTb   = 0;

   data[4].bt1     = NULL;
   data[4].bt2     = NULL;
   data[4].bt3     = NULL;
   data[4].message = NULL;
   data[4].wait    = NULL;
   data[4].colTb   = 0;

   for(;;)
   {
      command = NULL;
      switch (idx)
      {
         case 0:
            popupScrolledTextWindow(actWindow, &data[idx]);
            colHead = data[0].intVal;
            if ( *data[idx].wait == 1 )
            {
               if ( actConfig.cleanSeparate )
                  callPrg(colHead ? EXCHANGE_C : EXCHANGE_B,
                          actConfig.dev, actConfig.prot, 0, 0, &command, NULL);
               else
                  callPrg( EXCHANGE_ALL,
                           actConfig.dev, actConfig.prot, 0, 0, &command, NULL);
            }
            idx = -1;
            if ( command )
            {
               if ( command[0] == 'x' && command[1] == 'i' )
               {
                  if ( command[6] == 'O' && command[7] == 'K' )
                  {
                     idx = 0;
                  }
               }
            }
            if ( idx == -1 )
            {
               XtUnmanageChild(actWindow);
               XtManageChild(mainWindow);
               doCyclicScan = 1;
               return;
            }
            break;
         case 1:
            popupScrolledTextWindow(actWindow, &data[idx]);
            usleep(20);
            callPrg(EXCHANGE_NEXT, actConfig.dev, actConfig.prot, 1, 0,(char**)&command, NULL);
            data[idx].wait  = &waitForConfigWindow;
            *data[idx].wait = 1;
            break;
         case 2:
            /* tell exchange cartridge */
            popupScrolledTextWindow(actWindow, &data[idx]);
            break;
         case 3:
            popupScrolledTextWindow(actWindow, &data[idx]);
            callPrg(EXCHANGE_NEXT, actConfig.dev, actConfig.prot, 3, 0, (char**)&command, NULL);
            data[idx].wait  = &waitForConfigWindow;
            *data[idx].wait = 1;
            break;
         case 4:
            callPrg(EXCHANGE_NEXT, actConfig.dev, actConfig.prot, 4, 0, NULL, NULL);
            XtUnmanageChild(actWindow);
            XtManageChild(mainWindow);
            callPrg(RELEASE, actConfig.dev, 0, 0, 0, NULL, NULL);
            doCyclicScan = 1;
            return;
            break;
         case -1:
            XtUnmanageChild(actWindow);
            XtManageChild(mainWindow);
            callPrg(RELEASE, actConfig.dev, 0, 0, 0, NULL, NULL);
            return;
      }

      actWindow = data[idx].actWindow;
      idx += *data[idx].wait;
   }
   doCyclicScan = 1;
}

/*******************************************************************/
/* Function reset_CB()                                             */
/*                                                                 */
/* Call the reset printer code                                     */
/*                                                                 */
/*******************************************************************/

void reset_CB(Widget w, XtPointer clientData, XtPointer callData)
{
   callPrg(RESET_PRT, actConfig.dev, actConfig.reset, 0, 0, NULL, NULL);
   /* avoid that anythings called before the printer was really reseted */
   cmdCount = - 10;
}

/*******************************************************************/
/* Function align_CB()                                             */
/*                                                                 */
/* Call the align head code                                        */
/*                                                                 */
/*******************************************************************/

void align_CB(Widget w, XtPointer clientData, XtPointer callData)
{
   wConfig_data_t data[10];
   Widget  actWindow = mainWindow;
   int     idx       = 0;
   int     colHead   = 0;
   int     command   = ALIGN_HEAD; /* make gcc happy */
   int     passes    = 0;
   int     choices   = 0;
   int     val       = 0;
   char   *function  = colHead ? NULL : actConfig.alignFunction;

   doCyclicScan = 0;

   data[0].printerName = actConfig.name;
   data[0].bt1         = NULL;
   data[0].bt2         = appResourceRec.cancel;
   data[0].bt3         = appResourceRec.next;
   if ( actConfig.color_passes )
   {
      data[0].message  = appResourceRec.ctTxtC0;
      data[0].colTb    = 1;
   }
   else
   {
      data[0].message  = appResourceRec.ctTxt0;
      data[0].colTb    = 0;
   }
   data[0].wait        = &waitForConfigWindow;
   data[0].choices     = actConfig.choices;


   data[1].printerName = actConfig.name;
   data[1].bt1         = NULL;
   data[1].bt2         = NULL;
   data[1].bt3         = appResourceRec.next;
   data[1].message     = appResourceRec.ctTxt1;
   data[1].wait        = &waitForConfigWindow;
   data[1].colTb       = 0;
   data[1].choices     = actConfig.choices;

   data[2].printerName = actConfig.name;
   data[2].bt1         = NULL;
   data[2].bt2         = NULL;
   data[2].bt3         = appResourceRec.next;
   data[2].message     = appResourceRec.ctTxt1;
   data[2].wait        = &waitForConfigWindow;
   data[2].colTb       = 0;
   data[2].choices     = actConfig.choices;

   data[3].printerName = actConfig.name;
   data[3].bt1         = NULL;
   data[3].bt2         = NULL;
   data[3].bt3         = appResourceRec.next;
   data[3].message     = appResourceRec.ctTxt1;
   data[3].wait        = &waitForConfigWindow;
   data[3].colTb       = 0;
   data[3].choices     = actConfig.choices;

   data[4].printerName = actConfig.name;
   data[4].bt1         = NULL;
   data[4].bt2         = NULL;
   data[4].bt3         = appResourceRec.next;
   data[4].message     = appResourceRec.ctTxt4;
   data[4].wait        = &waitForConfigWindow;
   data[4].colTb       = 0;
   data[4].choices     = actConfig.choices;

   data[5].printerName = actConfig.name;
   data[5].bt1         = NULL;
   data[5].bt2         = appResourceRec.cancel;
   data[5].bt3         = appResourceRec.save;
   data[5].message     = appResourceRec.ctTxt5;
   data[5].wait        = &waitForConfigWindow;
   data[5].colTb       = 0;
   data[5].choices     = actConfig.choices;

   data[6].bt1         = NULL;
   data[6].bt2         = NULL;
   data[6].bt3         = NULL;
   data[6].message     = NULL;
   data[6].wait        = NULL;
   data[6].colTb       = 0;
   data[6].choices     = actConfig.choices;

   /* wait for printer */
   data[7].printerName = actConfig.name;
   data[7].bt1         = NULL;
   data[7].bt2         = NULL;
   data[7].bt3         = appResourceRec.next;
   data[7].message     = appResourceRec.ctTxtP;
   data[7].wait        = &waitForConfigWindow;
   data[7].colTb       = 0;
   data[7].choices     = actConfig.choices;

   /* enter all values  */
   data[8].printerName = actConfig.name;
   data[8].bt1         = NULL;
   data[8].bt2         = NULL;
   data[8].bt3         = appResourceRec.next;
   data[8].message     = appResourceRec.ctTxtP;
   data[8].wait        = &waitForConfigWindow;
   data[8].colTb       = 0;
   data[8].choices     = actConfig.choices;

   for(;;)
   {
      switch (idx)
      {
         case 0: /* tell insert sheet and send DT command */
            popupScrolledTextWindow(actWindow, &data[idx]);
            colHead = data[0].intVal;
            if ( *data[idx].wait == 1 )
            {
               command = colHead ? ALIGN_HEAD_C : ALIGN_HEAD;
               passes  = colHead ? actConfig.color_passes - 1 : actConfig.passes;
               choices = colHead ? actConfig.color_choices : actConfig.choices;
               data[1].choices = choices;
               data[2].choices = choices;
               data[3].choices = choices;
               data[4].choices = choices;
               data[5].choices = choices;
               data[7].choices = choices;
               if ( colHead )
               {
                  data[1].message = appResourceRec.ctTxtC; 
                  data[2].message = appResourceRec.ctTxtC;
                  data[3].message = appResourceRec.ctTxtC;
               }
               else if ( passes == 1 )
               {
                  data[1].message = appResourceRec.ctTxt1;
               }
               if ( actConfig.passes > 0 )
                  callPrg(command, actConfig.dev, actConfig.align, 1, 0, NULL, function);
            }
            break;
         case 1: case 2: case 3: /* send DA cmd and tell choose pattern, send DT command */

            if ( actConfig.passes > 0 )
            {
               popupScrolledTextWindow(actWindow, &data[7]);
               popupAlignNextWindow(actWindow, &data[idx]);
               /* send the DA */
               callPrg(command, actConfig.dev, actConfig.align, idx, data[idx].intVal+1, NULL, function);
               /* and possibly the DT + FF cmd */
               if ( idx != passes )
               {
                  callPrg(command, actConfig.dev, actConfig.align, idx+1, 0, NULL, function);
               }
               if ( idx == passes )
               {
                  *data[idx].wait = 4 - idx;
               }
            }
            else
            {
      
                switch ( idx )
                {
                   case 1:
                      callPrg(command, actConfig.dev, actConfig.align, actConfig.passes, 0, NULL, function);
                      popupScrolledTextWindow(actWindow, &data[7]);
                      data[idx].message     = appResourceRec.ctTxt1_1;
                      popupAlignNextWindow(actWindow, &data[idx]);
                      val = data[idx].intVal+1;
                   break;
                   case 2:
                      data[idx].message     = appResourceRec.ctTxt1_2;
                      popupAlignNextWindow(actWindow, &data[idx]);
                      val |= (data[idx].intVal+1)<<8;
                   break;
                   case 3:
                      data[idx].message     = appResourceRec.ctTxt1_3;
                      popupAlignNextWindow(actWindow, &data[idx]);
                      val |= (data[idx].intVal+1)<<16;
                      callPrg(command, actConfig.dev, actConfig.align, actConfig.passes, val, NULL, function);
                   break;
                }
                 
                if ( idx == -passes )
                {
                   *data[idx].wait = 5 - idx;
                }
            }
            break;
         case 4: /* send DA cmd from last pass */
            callPrg(command, actConfig.dev, actConfig.align, passes, -1, NULL, function);
            idx++;
         case 5: /*  print all pattern and ask for save */
            popupScrolledTextWindow(actWindow, &data[idx]);
            /* send  DT for all pattern and FF */
            if ( *data[idx].wait == 1 )
            {
               callPrg( command,actConfig.dev, actConfig.align, -1 ,0 , NULL, function);
            }
            *data[idx].wait = 1;
            break;
         case 6:
            XtUnmanageChild(actWindow);
            XtManageChild(mainWindow);
            callPrg( RELEASE,actConfig.dev, 0, 0 ,0 , NULL, NULL);
            return;
            break;
         case -1:
            XtUnmanageChild(actWindow);
            XtManageChild(mainWindow);
            callPrg( RELEASE,actConfig.dev, 0, 0 ,0 , NULL, NULL);
            doCyclicScan = 1;
            return;
      }

      actWindow = data[idx].actWindow;
      idx += *data[idx].wait;
   }
   doCyclicScan = 1;
}

/*******************************************************************/
/* Function parseArgs(int argc, char **argv)                       */
/*                                                                 */
/* check for call parameters                                       */
/*                                                                 */
/*******************************************************************/

void parseArgs(int argc, char **argv)
{
   while ( argc )
   {
      if ( strcmp("-noAutoDetect", argv[0]) == 0 )
      {
         noAutoDetect = 1;
      }
      else if ( strncmp("-h", argv[0], 2) == 0 ||
                strncmp("--h", argv[0], 3) == 0 )
      {
         printf("Syntax: %s [%s] [-config #]\n",prgName,"-noAutoDetect");
         exit(0);
      }
      else if ( strncmp("-v", argv[0], 2) == 0 ||
                strncmp("--v", argv[0], 3) == 0 )
      {
         printf("%-8s: %s\n",prgName,VERSION);
         printf("compiled: %s %s\n",__DATE__,__TIME__);
         printf("Author  : Jean-Jacques Sarton\n");
         printf("URL     : http://xwtools.automatix.de\n");
         exit(0);
      }
      else if ( strncmp("-c",argv[0], 2) == 0 ||
                strncmp("--c", argv[0], 3) == 0 )
      {
         argc--;
         argv++;
         if ( argc )
            configFileIdx = atoi(argv[0]);
         else
         {
            printf("Syntax: %s [%s] [-config #]\n",prgName,"-noAutoDetect");
            exit(1);
         }            
      }
      else if ( strncmp("-L",argv[0], 2) == 0 )
      {
         debugD4 = 1;
      }
      else if ( strncmp("-f",argv[0], 2) == 0 )
      {
         inFromFile = 1; /* for devel purpose */
         argc--;
         argv++;
         if ( argc )
            testFile = argv[0]; /* intead of /dev/... */
         else
         {
            printf("Syntax: %s -f <log_file>\n",prgName);
            exit(1);
         }            
         
      }
      argc--;
      argv++;
   }
}

/*******************************************************************/
/* Function SetSensitive(int flag)                                 */
/*                                                                 */
/* Set the 'actions button' sensitive or not sensitive             */
/*                                                                 */
/*******************************************************************/

void SetSensitive(int flag)
{
   XtSetSensitive(reset_PB,     flag);
   XtSetSensitive(cartridge_PB, flag);
   XtSetSensitive(align_PB,     flag);
   XtSetSensitive(clean_PB,     flag);
   XtSetSensitive(check_PB,     flag);

   if ( ! actConfig.reset )
      XtSetSensitive(reset_PB,  False);

   if ( ! actConfig.exchange )
      XtSetSensitive(cartridge_PB, False);
   if ( ! actConfig.passes )
      XtSetSensitive(align_PB, False);
}

/*******************************************************************/
/* Function refreshMainWindow()                                    */
/*                                                                 */
/* Set the scrollbar and the precent widget to the proper value    */
/*                                                                 */
/*******************************************************************/

void refreshMainWindow()
{
   char buf[200];
   XmString xms;

   XtVaSetValues(scaleB, XmNsliderSize, pc1?pc1:1, NULL);
   sprintf(buf,"%3d %%",pc1);
   xms = XmStringCreateSimple(buf);
   XtVaSetValues(scaleBLb,XmNlabelString,xms,NULL);
   XmStringFree(xms);

   if ( actConfig.colors > 1 )
   {
      XtManageChild(XtParent(scaleC));
      XtManageChild(scaleCLb);
      XtManageChild(XtParent(scaleM));
      XtManageChild(scaleMLb);
      XtManageChild(XtParent(scaleY));
      XtManageChild(scaleYLb);

      XtVaSetValues(scaleC, XmNsliderSize, pc2?pc2:1, NULL);
      sprintf(buf,"%3d %%",pc2);
      xms = XmStringCreateSimple(buf);
      XtVaSetValues(scaleCLb,XmNlabelString,xms,NULL);
      XmStringFree(xms);

      XtVaSetValues(scaleM, XmNsliderSize, pc3?pc3:1, NULL);
      sprintf(buf,"%3d %%",pc3);
      xms = XmStringCreateSimple(buf);
      XtVaSetValues(scaleMLb,XmNlabelString,xms,NULL);
      XmStringFree(xms);

      XtVaSetValues(scaleY, XmNsliderSize, pc4?pc4:1, NULL);
      sprintf(buf,"%3d %%",pc4);
      xms = XmStringCreateSimple(buf);
      XtVaSetValues(scaleYLb,XmNlabelString,xms,NULL);
      XmStringFree(xms);
   }
   else
   {
      XtUnmanageChild(XtParent(scaleC));
      XtUnmanageChild(scaleCLb);
      XtUnmanageChild(XtParent(scaleM));
      XtUnmanageChild(scaleMLb);
      XtUnmanageChild(XtParent(scaleY));
      XtUnmanageChild(scaleYLb);
   }

   if ( actConfig.colors > 4 )
   {
      /* 5.and 6. color, normaly light Cyan/Magenta */
      XtManageChild(XtParent(scaleLc));
      XtManageChild(scaleLcLb);
      XtManageChild(XtParent(scaleLm));
      XtManageChild(scaleLmLb);

      XtVaSetValues(scaleLc, XmNsliderSize, pc5?pc5:1, NULL);
      sprintf(buf,"%3d %%",pc5);
      xms = XmStringCreateSimple(buf);
      XtVaSetValues(scaleLcLb,XmNlabelString,xms,NULL);
      XmStringFree(xms);

      XtVaSetValues(scaleLm, XmNsliderSize, pc6?pc6:1, NULL);
      sprintf(buf,"%3d %%",pc6);
      xms = XmStringCreateSimple(buf);
      XtVaSetValues(scaleLmLb,XmNlabelString,xms,NULL);
      XmStringFree(xms);

      if ( actConfig.colors > 6 )
      {
         /* more colors, this will depend on model */
         /* 7. color */
         XtManageChild(XtParent(scaleLb));
         XtManageChild(scaleLbLb);
         XtVaSetValues(scaleLb, XmNsliderSize, pc7?pc7:1, NULL);
         sprintf(buf,"%3d %%",pc7);
         xms = XmStringCreateSimple(buf);
         XtVaSetValues(scaleLbLb,XmNlabelString,xms,NULL);
         XmStringFree(xms);

         if ( actConfig.colors > 7 )
         {
            /* 8. color */
            XtManageChild(XtParent(scalePh));
            XtManageChild(scalePhLb);
            XtVaSetValues(scalePh, XmNsliderSize, pc8?pc8:1, NULL);
            sprintf(buf,"%3d %%",pc8);
            xms = XmStringCreateSimple(buf);
            XtVaSetValues(scalePhLb,XmNlabelString,xms,NULL);
            XmStringFree(xms);
         }
         else
         {
            XtUnmanageChild(XtParent(scalePh));
            XtUnmanageChild(scalePhLb);
            /* seven color, model ? */
            /* to be set later      */
         }
      }
      else if ( actConfig.colors == 6 )
      {
         setProgressBarColor(MODEL_KCMycm);
         XtUnmanageChild(XtParent(scaleLb));
         XtUnmanageChild(scaleLbLb);
         XtUnmanageChild(XtParent(scalePh));
         XtUnmanageChild(scalePhLb);
      }
      else
      {
         XtUnmanageChild(XtParent(scalePh));
         XtUnmanageChild(scalePhLb);
      }
   }
   else
   {
      XtUnmanageChild(XtParent(scaleLc));
      XtUnmanageChild(scaleLcLb);
      XtUnmanageChild(XtParent(scaleLm));
      XtUnmanageChild(scaleLmLb);
      XtUnmanageChild(XtParent(scaleLb));
      XtUnmanageChild(scaleLbLb);
      XtUnmanageChild(XtParent(scalePh));
      XtUnmanageChild(scalePhLb);
   }

   /* display the state of our printer */
   if ( printerState )
   {
      xms = XmStringCreateSimple(printerState);
      XtVaSetValues(state_LB, XmNlabelString,xms,NULL);
      XmStringFree(xms);
   }
}

/*******************************************************************/
/* Function main()                                                 */
/*                                                                 */
/* The begin of the world                                          */
/*                                                                 */
/*******************************************************************/

int main(int argc, char **argv, char **env)
{
   ArgList       init_args      = (ArgList)NULL;
   Cardinal      num_init_args  = (Cardinal)0;
   Dimension     w1 = 0, w2 = 0, h1 = 0, h2 = 0;
   Window        win;
   XmString      xms;
   char         *s;
   int           state;
   char         *lang;
   char          printerFound = 0;
   char          tmpBuf[20];
   Widget        mainWid;
   int           prot = 0;
   int           i;
   char         *deviceFile = NULL; /* make gcc happy */
   char         *retBuf = NULL;
   wConfig_data_t data;
   int           configured = 0;
   char         *errorMessage = NULL;
   Atom          myAtom;
   char          atomName[1024];
   Atom          wm_delete_window;
#ifdef MACOS
   char          prtFile[512];
#endif
   data.actWindow = NULL;

   /* check the environment first (avoid possibly vulnerability */
   /* problems due to errors within the used libraries          */
   if ( checkEnv(env) == 0 )
   {
      fprintf(stderr,"Sorry corrupted environment\n");
      exit(1);
   }

   /* preset for building of windows */
   actConfig.colors    = 8;
   actConfig.state     = 1;
   actConfig.reset     = 1;
   actConfig.exchange  = 1;
   strcpy(tmpBuf,"En");

   lang = getenv("LANG");
   if ( lang == NULL )
   {
      lang = getenv("LC_MESSAGES");
      if ( lang == NULL )
      {
         lang = getenv("LC_ALL");
      }
   }

   if ( lang )
   {
      if ( strcmp("german", lang) == 0 )
      {
         strcpy(tmpBuf,"De");
      }
      else
      {
         tmpBuf[0] = toupper(lang[0]);
         tmpBuf[1] = lang[1];
         tmpBuf[3] = '\0';
      }
   }

   /* for help files */
   strcpy(guiLanguage, tmpBuf);
   xmTooltipSetLang(guiLanguage);

   prgName = argv[0];
   if ( (s = strrchr(prgName, '/')) != NULL )
   {
      prgName = s + 1;
   }
   parseArgs(argc,argv);

   /* make the topLevel */
   mainResource = (char*)calloc(strlen(NAME)+3,1);
   strcpy(mainResource,NAME);

   topLevel = XtAppInitialize(&theApp,
                              mainResource,
                              NULL,
                              0,
                              &argc,
                              argv,
                              fallbackResources,
                              init_args,
                              num_init_args);

   if ( topLevel == (Widget) NULL )
   {
      fprintf(stderr,"%s: can't connect to X11\n", prgName);
      exit(1);
   }

   XtVaSetValues(topLevel, XmNmappedWhenManaged, False, NULL);

   /* disable drag and drop */
   displayW = XmGetXmDisplay(XtDisplay(topLevel));
   XtVaSetValues(displayW, XmNdragInitiatorProtocolStyle, XmDRAG_NONE, NULL);

   /* put DISPLAY to the environment */
   s = DisplayString(XtDisplay(topLevel));
   if ( s )
   {
      displayStr = (char*)calloc(strlen(s)+10,1);
      sprintf(displayStr,"DISPLAY=%s",s);
      putenv(displayStr);
   }

   createLayout(tmpBuf);
   cfg2 = createConfigureForm(topLevel, &waitForConfigWindow );
   cfg1 = createConfigurePrinter(mainForm, &waitForConfigWindow );
   algn = createAlignButtons(topLevel,  &waitForConfigWindow );
   stxt = createScrTxt_MW(topLevel,  &waitForConfigWindow );
   XtUnmanageChild(cfg2);
   XtUnmanageChild(cfg1);
   XtUnmanageChild(algn);
   XtUnmanageChild(stxt);
   XtRealizeWidget(topLevel);
   xmAddtooltipGlobal(topLevel);

   rdSessFile(&x,&y);
   miconOK = createIconLayout(topLevel, theApp, mainResource, guiLanguage, usePopup);

   /* pass the main window and not the toplevel, if we don't made */
   /* this we will alltime get the default (english texts         */

   XtGetApplicationResources(mainForm, (XtPointer)&appResourceRec,
                             resources, XtNumber(resources),
                             NULL, 0);

   if ( configFileIdx )
   {
      sprintf(atomName,"MTINK_ATOM_%d",configFileIdx );
   }
   else
   {
      strcpy(atomName,"MTINK_ATOM");
   }

   myAtom = XInternAtom(XtDisplay(topLevel), atomName, False);
   if ( (win = XGetSelectionOwner(XtDisplay(topLevel), myAtom)) == None )
   {
      XSetSelectionOwner(XtDisplay(topLevel),myAtom, XtWindow(topLevel), CurrentTime);
   }
   else
   {
      /* one instance is present, pop up this instance and */
      /* terminate                                         */
      XMapRaised(XtDisplay(topLevel), win);
      XFlush(XtDisplay(topLevel));
      exit(2);
   }

   /* add protocol for closing of app */
   wm_delete_window = XInternAtom(XtDisplay(topLevel), "WM_DELETE_WINDOW", False);
   XmAddWMProtocolCallback(topLevel, wm_delete_window, deleteWindow_CB, NULL);


   /* put the main window on the middle of the screen */
   h2 = DisplayHeight(XtDisplay(topLevel),0);
   w2 = DisplayWidth(XtDisplay(topLevel),0);

   XtVaGetValues(topLevel,
                 XmNwidth,  &w1,
                 XmNheight, &h1,
                 NULL);

   XMoveWindow(XtDisplay(topLevel),
               XtWindow(topLevel),
               (w2-w1)/2,(h2-h1)/2);


   XtVaSetValues(topLevel,
                 XmNminHeight, h1,
                 XmNmaxHeight, h1,
                 XmNminWidth,  w1,
                 XmNmaxWidth,  w1,
                 NULL);

   XtMapWidget(topLevel);

   XtUnmanageChild(XtParent(scalePh));
   XtUnmanageChild(scalePhLb);

   signal(SIGINT,  sigKill);
   signal(SIGQUIT, sigKill);
   signal(SIGSEGV, sigKill);

   /* read the printer description file */
   readPrinterData();
   /* read the configuration file */
   readRc(configFileIdx);

   /* set the behaviour accordingly and complete */
   if ( noAutoDetect )
   {
      if ( autodetect )
         free(autodetect);
      autodetect = (char*)strdup("no");
   }

   /* for the case the given printer is not found into our knowledge table */
   if ( autodetect && *autodetect == 'n' )
   {
      /* assume printer is not able to return identification */
      actConfig.id = False;
   }
   else
   {
      /* assume printer is able to return identification */
      actConfig.id = True;
   }

   XmToggleButtonSetState(autodetect_TB, actConfig.id, False);

   if ( miniHelp && *miniHelp == 'n' )
   {
      XmToggleButtonSetState(tooltip_TB, False, False);
      xmEnableTooltip(False);
   }
   else
   {
      XmToggleButtonSetState(tooltip_TB, True, False);
      xmEnableTooltip(True);
   }

   if ( setConfig() )
   {
      /* the configuration contain a printer and dev entry */
      data.ptrVal  = actConfig.dev;
      printerName  = actConfig.name;
      deviceFile   = actConfig.dev;
      
      if ( inFromFile )
      {
         deviceFile = actConfig.dev = testFile;
      }
      retBuf = NULL;
#ifndef MACOS
      /* check for permission on the device */
      if ( fileAccess(actConfig.dev, R_OK|W_OK) == -1 )
      {
         errorMessage = "noAccess";
         goto errorLabel;
      }
#endif

#ifdef MACOS
      actConfig.id = True;
#else
      if ( autodetect && *autodetect == 'n' )
      {
         actConfig.id = False;
      }
#endif

      if ( actConfig.id )
      {
#ifdef MACOS
         if ( (state = usbInit()) > 0 )
         {
            /* printers detected */
            if ( createFiles() == 0 )
            {
               if ( state > 1 )
               {
                  /* choose dev number according to given dev */
                  int i;
                  if ( (s=strstr(deviceFile, USB_PRT_NAME_PREFIX)) )
                  {
                     s += strlen(USB_PRT_NAME_PREFIX);
                     i = atoi(s);
                  }
                  else for(i=0;i < state; i++)
                  {
                     if ( strcmp(getPrinterName(i),printerName) == 0 )
                     {
                        break;
                     }
                  }
                  state = i+1;
               }
               else
               {
                  /* choose dev number according to given dev */
                  int i;
                  if ( (s=strstr(deviceFile, USB_PRT_NAME_PREFIX)) )
                  {
                     s += strlen(USB_PRT_NAME_PREFIX);
                     state = atoi(s)+1;
                     s = strchr(s,':');
                     if (*s)
                        s++;
                  }
               }
               /* build device file name */
               if ((s = getPrinterName(state-1)))
               {
                  snprintf(prtFile, sizeof(prtFile),USB_PRT_NAME_PREFIX"%02d:%s",state-1,s);
                  printerName = strdup(s);
                  deviceFile  = strdup(prtFile);
                  printerFound = 2;
               }
            }
            else
            {
               state = -1;
            }
         }
         else
         {
            state = -1;
         }
         if ( state == -1 )
         {
            errorMessage = "noPrinter";
            goto errorLabel;
         }
#else
         state = callPrg(TEST_DEV, data.ptrVal, NO_PROT, 0, 0, &retBuf, NULL );
         if ( state == -1 )
         {
            printerFound = 0;
         }
         else if ( state == 0 )
         {
            /* may be OK, ID is not always returned (C40,C62) */
            printerFound = 1;
         }
         else if ( state == 1 )
         {
            /* may be OK but no answer from device */
            printerFound = 2;
         }
         else if ( state == 2 )
         {
            /* may be OK and a D4 device */
            printerFound = 2;
         }
#endif
      }
      else
      {
         /* for unknown printers found via previous autodetect */
         printerFound = 1;
      }
      configured = 1;
   }
   else /* no configuration file printer found = 0 */
   {
      configured = 0;
   }

#ifdef MACOS
   if ( ! configured )
   {
      if ( (state = usbInit()) > 0 )
      {
         /* printers detected */
         if ( createFiles() == 0 )
         {
            if ( state > 1 )
            {
               /* choose printer model */
            }
            /* build device file name */
            else if ((s = getPrinterName(state-1)))
            {
               snprintf(prtFile, sizeof(prtFile),USB_PRT_NAME_PREFIX"%02d:%s",state-1,s);
               printerName = strdup(s);
               deviceFile  = strdup(prtFile);
               printerFound = 0;
            }
         }
         else
         {
            state = -1;
         }
      }
      else
      {
         state = -1;
      }
      configured = 1;
      if ( state == -1 )
      {
         errorMessage = "noPrinter";
         goto errorLabel;
      }
   }
#endif

   /* not configured or open of device ... failed */
   if ( ! printerFound )
   {
      /* in this case we have to ask for device file */
      data.ptrVal      = NULL;
      data.printerName = actConfig.name;
      data.wait        = &waitForConfigWindow;
      data.wType       = QUERY_DEVICE;
      data.bt1         = data.bt2 = NULL;
      data.bt3         = appResourceRec.ok;
      data.message     = NULL;

      popupCfg1(mainWindow, &data, &actConfig);

      if ( *data.wait == -1 )
      {
         errorMessage = "noAccess";
         goto errorLabel;
      }
      if ( actConfig.dev )
         free(actConfig.dev);
      deviceFile       = data.ptrVal;
      actConfig.dev    = data.ptrVal;

      XtUnmanageChild(data.actWindow);
      XtManageChild(mainWindow);
   }

   /* try to detect printer, data.ptrVal preset from setConfig */
   /* OK or ask for device                                      */

   if ( data.ptrVal != NULL )
   {
      /* ask for the printer, not configured */
      if ( ! configured && ! printerFound )
      {
         deviceFile       = data.ptrVal;
         data.printerName = actConfig.name;
         data.ptrVal      = NULL;
         data.wait        = &waitForConfigWindow;
         data.wType       = QUERY_PRINTER;
         data.bt1         = data.bt2 = NULL;
         data.bt3         = NULL;
         data.message     = NULL;
         popupCfg1(mainWindow, &data, &actConfig);

         XtUnmanageChild(data.actWindow);
         XtManageChild(mainWindow);
         
         printerName      = ((configData_t*)data.ptrVal)->name;
         actConfig.name   = printerName;
         actConfig.id     = ((configData_t*)data.ptrVal)->id;
         actConfig.prot   = ((configData_t*)data.ptrVal)->prot;

         if ( autodetect && *autodetect == 'n' )
         {
            actConfig.id  = False;
         }
         printerFound     = 1;
      }

      /* check if the printer is available and the right printer */
      if ( printerFound == 0 )
      {
         retBuf = NULL;
         if ( callPrg(TEST_DEV, deviceFile, NO_PROT, 0, 0, &retBuf, NULL ) == -1 )
         {
            /* open or write not OK -> critical error */
            printerFound = 0;
            XtUnmanageChild(data.actWindow);
            XtManageChild(mainWindow);
            goto errorLabel;
         }
      }

      /* TBD don't do this if no autodetection */
      if ( printerFound == 1 && actConfig.id )
      {
         /* first try with old command */
         retBuf = NULL;
         callPrg(GET_ID, deviceFile, PROT_OLD, 0, 0, &retBuf, NULL );
         if ( retBuf != NULL && *retBuf != '\0' )
         {
            printerFound = decodePrinterType((unsigned char*)retBuf, strlen(retBuf));
            prot = NO_PROT;
         }
         else if ( retBuf != NULL && *retBuf == '\0' )
         {
            /* some printer (C40, C62 require the D4 ID command */
            printerFound = 2;
         }
      }

      if ( (printerFound == 0 || printerFound == 2) && actConfig.id  )
      {
         retBuf = NULL;
         callPrg(GET_ID, deviceFile, PROT_D4, 0, 0, &retBuf, NULL );
         if ( retBuf != NULL )
         {
            printerFound = decodePrinterType((unsigned char*)retBuf, strlen(retBuf));
            prot = PROT_D4;
         }
      }

      if ( printerName == NULL  )
      {
         if ( !printerFound )
         {
            /* detection failed, ask the user */
            data.wait = &waitForConfigWindow;
            data.wType = QUERY_PRINTER;
            data.bt1 = data.bt2 = NULL;
            data.bt2 = appResourceRec.ok;
            data.message = "Select Printer";
            data.ptrVal  = NULL;
            XtMapWidget(topLevel);
            popupCfg1(mainWindow, &data, &actConfig);
         }

         if ( data.ptrVal )
         {
            memcpy(&actConfig,(configData_t*)(data.ptrVal), sizeof(configData_t));
            actConfig.dev = deviceFile;
         }
         else
         {

         }
      }
      else
      {
         actConfig.name = printerName;
      }
   }
   else
   {
      actConfig.name = printerName;
   }

   /* search and load configuration data */

   if  ( actConfig.name )
   {
      for ( i = 0; i < defaultConfigDataSize; i++ )
      {
         if ( strcasecmp(defaultConfigData[i].name,actConfig.name) == 0 )
         {
            memcpy(&actConfig,&defaultConfigData[i], sizeof(configData_t));
            actConfig.dev = deviceFile;
            break;
         }
      }
      /* unknown printer, assume that D4 mode, disable aligment */
      if ( i == defaultConfigDataSize )
      {
         i--;
         memcpy(&actConfig,&defaultConfigData[i], sizeof(configData_t));
         actConfig.dev  = deviceFile;
         actConfig.name = printerName;
         XtSetSensitive(align_PB, False);
      }
   }

   if ( actConfig.name )
   {
      /* read status and ink quantity */
      retBuf = NULL;

      /* For test with a log file from ttink -d /dev/usb/lp0 -L */
      if  ( inFromFile )
      {
         callPrg(GET_ID, actConfig.dev, actConfig.prot, 0, 0, &retBuf, NULL);
      }

      i = callPrg(GET_IQ, actConfig.dev, actConfig.prot, 0, 0, &retBuf, NULL);
      cmdCount = 0;

      /* may be that we have not found a device */      
      if ( i == -1 )
      {
         printerFound = 0;
      }

      if ( retBuf != NULL )
      {
         if ( *retBuf == '\0' )
         {
            printerFound = 0;
         }
         else
         {
            if ( decodeStatus((unsigned char*)retBuf, strlen(retBuf)) )
            {
               printerFound = 1;
            }
            else
            {
               printerFound = 0;
            }
         }
      }
      else
      {
         if ( !actConfig.id )
         {
            printerFound = 0;
         }
      }

      if ( data.actWindow )
      {
         XtUnmanageChild(data.actWindow);
      }
      XtManageChild(mainWindow);
   }

   /* save these data */
   if (  actConfig.name )
   {
      saveConfig(configFileIdx);
   }

   XtManageChild(mainWindow);
   XtMapWidget(topLevel);

   /* put the value we have read to the scale widgets */
   refreshMainWindow();

   /* advertise that the printer was not reached */

errorLabel: /* sorry */

   if ( actConfig.name )
   {
      if ( actConfig.name[0] != '?' )
      {
         xms = XmStringCreateSimple(actConfig.name);
         XtVaSetValues(title_LB, XmNlabelString, xms, NULL);
         XmStringFree(xms);
         iconAddTooltip(actConfig.name);
      }
   }

   doCyclicScan = 1;
#ifndef MACOS
   if ( actConfig.dev && strncmp(actConfig.dev,"/var",4) == 0 )
   {
      usePopup = 1;
   }
#endif

   if ( printerFound == 0 )
   {
      if ( actConfig.dev && strncmp(actConfig.dev,"/var",4) == 0 )
      {
         tid = XtAppAddTimeOut(theApp, CYCLE_TIME, handleTi, (XtPointer)NULL);
      }
      else
      {
         doCyclicScan = 0;
      }
      mainWid = createNoPrinterBox(errorMessage);
      XtManageChild(mainWid);
      XtVaGetValues(XtParent(mainWid),
                    XmNwidth,  &w1,
                    XmNheight, &h1,
                    NULL);
      XMoveWindow(XtDisplay(topLevel),
                  XtWindow(XtParent(mainWid)),
                  (w2-w1)/2,(h2-h1)/2);
      XtSetSensitive(reset_PB ,False);
      XtSetSensitive(cartridge_PB ,False);
      XtSetSensitive(align_PB ,False);
      XtSetSensitive(clean_PB ,False);
      XtSetSensitive(check_PB ,False);
      if ( actConfig.dev && strncmp(actConfig.dev,"/var",4) )
      {
         usePopup = False;
      }
   }

   if ( ! actConfig.reset    ) XtSetSensitive(reset_PB,     False);
   if ( ! actConfig.exchange ) XtSetSensitive(cartridge_PB, False);
   if ( ! actConfig.passes   ) XtSetSensitive(align_PB, False);

   /* set the focus to the exit button */
   XmProcessTraversal(ok_PB, XmTRAVERSE_CURRENT);

   /* main loop */
   XtAppMainLoop(theApp);

   /* never reached */
   exit(0);
   return 0;
}

/******************************************************************
 * Function createLayout()
 *
 * Build the main window
 *
 * The color models may be as follow
 *  KCMY                         4 colors
 *  KCMYcm                       6 colors
 *  CMYcmK  (matte  K)           6 colors
 *  KCMYcmy (y = dark yellow!)   7 colors
 *  KCMYcmk                      7 colors
 *  CMYcmKk (matte and light K)  7 colors
 *  KCMYrb  (red + blue)         6 colors
 *  KCMYrbx (red + blue + gloss) 7 colors
 *  KCMyRBkX (matte + red + blue + gloss) 8 colors
 *
 *  The progress bar clolors shall be
 *         KCMy    KCMycm   KCMycmY KCMycmk   KCMyRB  KCMyRBx  KCMyRBkX    KCMycmGg
 *    1    Black   Black    Black   Black     Black   Black    Black       Black
 *    2    Cyan    Cyan     Cyan    Cyan      Cyan    Cyan     Cyan        Cyan
 *    3    Magenta Magenta  Magenta Magenta   Magenta Magenta  Magenta     Magenta
 *    4    Yellow  Yellow   Yellow  Yellow    Yellow  Yellow   Yellow      Yellow
 *    5    -       cyan     cyan    cyan      red     red      red         cyan
 *    6    -       magenta  magenta magenta   blue    blue     blue        magenta
 *    7    -       -        dark Y  dark grey         X        Photo Black Grey
 *    8                                                        X           grey
 *
 ******************************************************************/

Widget createLayout(char *language)
{
   Widget      wid;
   Widget      separator;
   XmString    xms = NULL;

   mainForm = XtVaCreateWidget(language,
                                 xmFormWidgetClass,
                                 topLevel,
                                 XmNmarginHeight, 0,
                                 XmNmarginWidth,  0,
                                 XmNresizePolicy, XmRESIZE_GROW,
                                 XmNresizable,    True,
                                 NULL);
   XtManageChild(mainForm);

   mainWindow = XtVaCreateWidget("mainWindow",
                                 xmFormWidgetClass,
                                 mainForm ,
                                 XmNmarginHeight, 0,
                                 XmNmarginWidth,  0,
                                 XmNresizePolicy, XmRESIZE_GROW,
                                 XmNresizable,    True,
                                 NULL);


   if (mainWindow == NULL)
   {
      return False;
   }
   XtManageChild(mainWindow);

   if ( printerName && printerName[0] != '?' )
   {
      xms = XmStringCreateSimple(printerName);
   }
   else if ( actConfig.name && actConfig.name[0] != '?' )
   {
      xms = XmStringCreateSimple(actConfig.name);
   }

   if ( xms )
   {
      title_LB = XtVaCreateWidget("title_LB",
                                xmLabelWidgetClass,
                                mainWindow,
                                XmNleftAttachment,   XmATTACH_FORM,
                                XmNleftOffset,       5,
                                XmNrightAttachment,  XmATTACH_FORM,
                                XmNrightOffset,      5,
                                XmNtopAttachment,    XmATTACH_FORM,
                                XmNtopOffset,        10,
                                XmNalignment,        XmALIGNMENT_CENTER,
                                XmNlabelString,      xms,
                                NULL);
      XmStringFree(xms);
   }
   else
   {
      title_LB = XtVaCreateWidget("title_LB",
                                xmLabelWidgetClass,
                                mainWindow,
                                XmNleftAttachment,   XmATTACH_FORM,
                                XmNleftOffset,       5,
                                XmNrightAttachment,  XmATTACH_FORM,
                                XmNrightOffset,      5,
                                XmNtopAttachment,    XmATTACH_FORM,
                                XmNtopOffset,        10,
                                XmNalignment,        XmALIGNMENT_CENTER,
                                NULL);
   }

   XtManageChild(title_LB);

   legend_LB = XtVaCreateWidget("legend_LB",
                                xmLabelWidgetClass,
                                mainWindow,
                                XmNleftAttachment,   XmATTACH_FORM,
                                XmNleftOffset,       5,
                                XmNrightAttachment,  XmATTACH_FORM,
                                XmNrightOffset,      5,
                                XmNtopAttachment,    XmATTACH_WIDGET,
                                XmNtopOffset,        5,
                                XmNalignment,        XmALIGNMENT_CENTER,
                                XmNtopWidget,        title_LB,
                                NULL);
   XtManageChild(legend_LB);
   scaleB = CreateScale(mainWindow,"scaleB",legend_LB);
   wid = XtParent(scaleB);

   xms = XmStringCreateSimple("100 %");

   scaleBLb = XtVaCreateWidget("scaleBLb",
                               xmLabelWidgetClass,
                               mainWindow,
                               XmNrightAttachment,       XmATTACH_FORM,
                               XmNrightOffset,           1,
                               XmNtopAttachment,         XmATTACH_WIDGET,
                               XmNtopWidget,             legend_LB,
                               XmNtopOffset,             10,
                               XmNlabelString,           xms,
                               XmNrecomputeSize,         False,
                               XmNalignment,             XmALIGNMENT_END,
                               NULL);
   XtManageChild(scaleBLb);

   XtVaSetValues(XtParent(scaleB),
                 XmNrightAttachment,  XmATTACH_WIDGET,
                 XmNrightWidget,      scaleBLb,
                 XmNrightOffset,      0,
                 NULL);

   scaleC = CreateScale(mainWindow,"scaleC",XtParent(scaleB));

   scaleCLb = XtVaCreateWidget("scaleCLb",
                               xmLabelWidgetClass,
                               mainWindow,
                               XmNrightAttachment,       XmATTACH_FORM,
                               XmNrightOffset,           1,
                               XmNtopAttachment,         XmATTACH_WIDGET,
                               XmNtopWidget,             XtParent(scaleB),
                               XmNtopOffset,             10,
                               XmNlabelString,           xms,
                               XmNrecomputeSize,         False,
                               XmNalignment,             XmALIGNMENT_END,
                               NULL);
   XtManageChild(scaleCLb);

   XtVaSetValues(XtParent(scaleC),
                 XmNrightAttachment,  XmATTACH_WIDGET,
                 XmNrightWidget,      scaleCLb,
                 XmNrightOffset,      0,
                 NULL);



   scaleM = CreateScale(mainWindow,"scaleM",XtParent(scaleC));

   scaleMLb = XtVaCreateWidget("scaleMLb",
                               xmLabelWidgetClass,
                               mainWindow,
                               XmNrightAttachment,       XmATTACH_FORM,
                               XmNrightOffset,           1,
                               XmNtopAttachment,         XmATTACH_WIDGET,
                               XmNtopWidget,             XtParent(scaleC),
                               XmNtopOffset,             10,
                               XmNlabelString,           xms,
                               XmNrecomputeSize,         False,
                               XmNalignment,             XmALIGNMENT_END,
                               NULL);
   XtManageChild(scaleMLb);

   XtVaSetValues(XtParent(scaleM),
                 XmNrightAttachment,  XmATTACH_WIDGET,
                 XmNrightWidget,      scaleMLb,
                 XmNrightOffset,      0,
                 NULL);



   scaleY = CreateScale(mainWindow,"scaleY",XtParent(scaleM));

   scaleYLb = XtVaCreateWidget("scaleYLb",
                               xmLabelWidgetClass,
                               mainWindow,
                               XmNrightAttachment,       XmATTACH_FORM,
                               XmNrightOffset,           1,
                               XmNtopAttachment,         XmATTACH_WIDGET,
                               XmNtopWidget,             XtParent(scaleM),
                               XmNtopOffset,             10,
                               XmNlabelString,           xms,
                               XmNrecomputeSize,         False,
                               XmNalignment,             XmALIGNMENT_END,
                               NULL);
   XtManageChild(scaleYLb);

   XtVaSetValues(XtParent(scaleY),
                 XmNrightAttachment,  XmATTACH_WIDGET,
                 XmNrightWidget,      scaleYLb,
                 XmNrightOffset,      0,
                 NULL);

   wid = XtParent(scaleY);

   scaleLc = CreateScale(mainWindow,"scaleLc",XtParent(scaleY));

   scaleLcLb = XtVaCreateWidget("scaleLcLb",
                               xmLabelWidgetClass,
                               mainWindow,
                               XmNrightAttachment,       XmATTACH_FORM,
                               XmNrightOffset,           1,
                               XmNtopAttachment,         XmATTACH_WIDGET,
                               XmNtopWidget,             XtParent(scaleY),
                               XmNtopOffset,             10,
                               XmNlabelString,           xms,
                               XmNrecomputeSize,         False,
                               XmNalignment,             XmALIGNMENT_END,
                               NULL);
   XtManageChild(scaleLcLb);

   XtVaSetValues(XtParent(scaleLc),
                 XmNrightAttachment,  XmATTACH_WIDGET,
                 XmNrightWidget,      scaleLcLb,
                 XmNrightOffset,      0,
                 NULL);

   scaleLm = CreateScale(mainWindow,"scaleLm",XtParent(scaleLc));

   scaleLmLb = XtVaCreateWidget("scaleLmLb",
                               xmLabelWidgetClass,
                               mainWindow,
                               XmNrightAttachment,       XmATTACH_FORM,
                               XmNrightOffset,           1,
                               XmNtopAttachment,         XmATTACH_WIDGET,
                               XmNtopWidget,             XtParent(scaleLc),
                               XmNtopOffset,             10,
                               XmNlabelString,           xms,
                               XmNrecomputeSize,         False,
                               XmNalignment,             XmALIGNMENT_END,
                               NULL);
   XtManageChild(scaleLmLb);


   XtVaSetValues(XtParent(scaleLm),
                 XmNrightAttachment,  XmATTACH_WIDGET,
                 XmNrightWidget,      scaleLmLb,
                 XmNrightOffset,      0,
                 NULL);

   wid = XtParent(scaleLm);

   scaleLb = CreateScale(mainWindow,"scaleLb",XtParent(scaleLm));

   scaleLbLb = XtVaCreateWidget("scaleLbLb",
                               xmLabelWidgetClass,
                               mainWindow,
                               XmNrightAttachment,       XmATTACH_FORM,
                               XmNrightOffset,           1,
                               XmNtopAttachment,         XmATTACH_WIDGET,
                               XmNtopWidget,             XtParent(scaleLm),
                               XmNtopOffset,             10,
                               XmNlabelString,           xms,
                               XmNrecomputeSize,         False,
                               XmNalignment,             XmALIGNMENT_END,
                               NULL);
   XtManageChild(scaleLbLb);

   XtVaSetValues(XtParent(scaleLb),
                 XmNrightAttachment,  XmATTACH_WIDGET,
                 XmNrightWidget,      scaleLbLb,
                 XmNrightOffset,      0,
                 NULL);

   wid = XtParent(scaleLb);

   scalePh = CreateScale(mainWindow,"scalePh",XtParent(scaleLb));

   scalePhLb = XtVaCreateWidget("scalePhLb",
                               xmLabelWidgetClass,
                               mainWindow,
                               XmNrightAttachment,       XmATTACH_FORM,
                               XmNrightOffset,           1,
                               XmNtopAttachment,         XmATTACH_WIDGET,
                               XmNtopWidget,             XtParent(scaleLb),
                               XmNtopOffset,             10,
                               XmNlabelString,           xms,
                               XmNrecomputeSize,         False,
                               XmNalignment,             XmALIGNMENT_END,
                               NULL);
   XtManageChild(scalePhLb);

   XmStringFree(xms);

   XtVaSetValues(XtParent(scalePh),
                 XmNrightAttachment,  XmATTACH_WIDGET,
                 XmNrightWidget,      scalePhLb,
                 XmNrightOffset,      0,
                 NULL);

   wid = XtParent(scalePh);

   if ( actConfig.state )
   {
       printerState_LB = XtVaCreateWidget("printerState_LB",
                                    xmLabelWidgetClass,
                                    mainWindow,
                                    XmNleftAttachment,   XmATTACH_FORM,
                                    XmNleftOffset,       5,
                                    XmNtopAttachment,    XmATTACH_WIDGET,
                                    XmNtopOffset,        10,
                                    XmNalignment,        XmALIGNMENT_BEGINNING,
                                    XmNtopWidget,        wid,
                                    NULL);
       XtManageChild(printerState_LB);
       wid = printerState_LB;

       state_LB = XtVaCreateWidget("state_LB",
                                    xmLabelWidgetClass,
                                    mainWindow,
                                    XmNleftAttachment,   XmATTACH_WIDGET,
                                    XmNleftOffset,       5,
                                    XmNleftWidget,       printerState_LB,
                                    XmNtopAttachment,    XmATTACH_OPPOSITE_WIDGET,
                                    XmNtopOffset,        0,
                                    XmNalignment,        XmALIGNMENT_BEGINNING,
                                    XmNtopWidget,        printerState_LB,
                                    NULL);
       XtManageChild(state_LB);
   }

   /* add a few push button */
   check_PB = XtVaCreateWidget("check_PB",
                               xmPushButtonWidgetClass,
                               mainWindow,
                               XmNtopAttachment,   XmATTACH_WIDGET,
                               XmNtopOffset,       5,
                               XmNtopWidget,       wid,
                               XmNleftAttachment,  XmATTACH_POSITION,
                               XmNleftOffset,      2,
                               XmNleftPosition,    0,
                               XmNrightAttachment, XmATTACH_POSITION,
                               XmNrightOffset,     2,
                               XmNrightPosition,   20,
                               NULL);
   XtManageChild(check_PB);

   clean_PB = XtVaCreateWidget("clean_PB",
                               xmPushButtonWidgetClass,
                               mainWindow,
                               XmNtopAttachment,   XmATTACH_WIDGET,
                               XmNtopOffset,       5,
                               XmNtopWidget,       wid,
                               XmNleftAttachment,  XmATTACH_POSITION,
                               XmNleftOffset,      2,
                               XmNleftPosition,    20,
                               XmNrightAttachment, XmATTACH_POSITION,
                               XmNrightOffset,     2,
                               XmNrightPosition,   40,
                               NULL);
   XtManageChild(clean_PB);

   align_PB = XtVaCreateWidget("align_PB",
                               xmPushButtonWidgetClass,
                               mainWindow,
                               XmNtopAttachment,   XmATTACH_WIDGET,
                               XmNtopOffset,       5,
                               XmNtopWidget,       wid,
                               XmNleftAttachment,  XmATTACH_POSITION,
                               XmNleftOffset,      2,
                               XmNleftPosition,    40,
                               XmNrightAttachment, XmATTACH_POSITION,
                               XmNrightOffset,     2,
                               XmNrightPosition,   60,
                               NULL);
   XtManageChild(align_PB);

   reset_PB = XtVaCreateWidget("reset_PB",
                               xmPushButtonWidgetClass,
                               mainWindow,
                               XmNtopAttachment,   XmATTACH_WIDGET,
                               XmNtopOffset,       5,
                               XmNtopWidget,       wid,
                               XmNleftAttachment,  XmATTACH_POSITION,
                               XmNleftOffset,      2,
                               XmNleftPosition,    60,
                               XmNrightAttachment, XmATTACH_POSITION,
                               XmNrightOffset,     2,
                               XmNrightPosition,   80,
                               NULL);
   XtManageChild(reset_PB);

   cartridge_PB = XtVaCreateWidget("cartridge_PB",
                               xmPushButtonWidgetClass,
                               mainWindow,
                               XmNtopAttachment,   XmATTACH_WIDGET,
                               XmNtopOffset,       5,
                               XmNtopWidget,       wid,
                               XmNleftAttachment,  XmATTACH_POSITION,
                               XmNleftOffset,      2,
                               XmNleftPosition,    80,
                               XmNrightAttachment, XmATTACH_POSITION,
                               XmNrightOffset,     2,
                               XmNrightPosition,   100,
                               NULL);
   XtManageChild(cartridge_PB);
   wid = check_PB;

   separator = XtVaCreateWidget("separator",
                               xmSeparatorWidgetClass,
                               mainWindow,
                               XmNtopAttachment,   XmATTACH_WIDGET,
                               XmNtopOffset,       5,
                               XmNtopWidget,       wid,
                               XmNleftAttachment,  XmATTACH_FORM,
                               XmNleftOffset,      0,
                               XmNrightAttachment, XmATTACH_FORM,
                               XmNrightOffset,     0,
                               NULL);
   XtManageChild(separator);

   pref_PB = XtVaCreateWidget("pref_PB",
                              xmPushButtonWidgetClass,
                              mainWindow,
                              XmNtopAttachment,    XmATTACH_WIDGET,
                              XmNtopOffset,        5,
                              XmNtopWidget,        separator,
                              XmNleftAttachment,   XmATTACH_POSITION,
                              XmNleftOffset,       5,
                              XmNleftPosition,     0,//40,
                              XmNrightAttachment,  XmATTACH_POSITION,
                              XmNrightOffset,      5,
                              XmNrightPosition,    25,//60,
                              XmNbottomAttachment, XmATTACH_FORM,
                              XmNbottomOffset,     5,
                              NULL);
   XtManageChild(pref_PB);

   about_PB = XtVaCreateWidget("about_PB",
                              xmPushButtonWidgetClass,
                              mainWindow,
                              XmNtopAttachment,    XmATTACH_WIDGET,
                              XmNtopOffset,        5,
                              XmNtopWidget,        separator,
                              XmNleftAttachment,   XmATTACH_POSITION,
                              XmNleftOffset,       5,
                              XmNleftPosition,     25,//5,
                              XmNrightAttachment,  XmATTACH_POSITION,
                              XmNrightOffset,      5,
                              XmNrightPosition,    50,//25,
                              XmNbottomAttachment, XmATTACH_FORM,
                              XmNbottomOffset,     5,
                              NULL);
   XtManageChild(about_PB);

   help_PB = XtVaCreateWidget("help_PB",
                              xmPushButtonWidgetClass,
                              mainWindow,
                              XmNtopAttachment,    XmATTACH_WIDGET,
                              XmNtopOffset,        5,
                              XmNtopWidget,        separator,
                              XmNleftAttachment,   XmATTACH_POSITION,
                              XmNleftOffset,       5,
                              XmNleftPosition,     50,//40,
                              XmNrightAttachment,  XmATTACH_POSITION,
                              XmNrightOffset,      5,
                              XmNrightPosition,    75,//60,
                              XmNbottomAttachment, XmATTACH_FORM,
                              XmNbottomOffset,     5,
                              NULL);
   XtManageChild(help_PB);

   ok_PB = XtVaCreateWidget("ok_PB",
                            xmPushButtonWidgetClass,
                            mainWindow,
                            XmNtopAttachment,    XmATTACH_WIDGET,
                            XmNtopOffset,        5,
                            XmNtopWidget,        separator,
                            XmNleftAttachment,   XmATTACH_POSITION,
                            XmNleftOffset,       5,
                            XmNleftPosition,     75,//75,
                            XmNrightAttachment,  XmATTACH_POSITION,
                            XmNrightOffset,      5,
                            XmNrightPosition,    100,//95,
                            XmNbottomAttachment, XmATTACH_FORM,
                            XmNbottomOffset,     5,
                            NULL);
   XtManageChild(ok_PB);

   XtAddCallback(ok_PB,        XmNactivateCallback, exit_CB,     NULL);
   XtAddCallback(pref_PB,      XmNactivateCallback, pref_CB,     NULL);
   XtAddCallback(about_PB,     XmNactivateCallback, about_CB,    NULL);
   XtAddCallback(help_PB,      XmNactivateCallback, help_CB,     NULL);
   XtAddCallback(align_PB,     XmNactivateCallback, align_CB,    NULL);
   XtAddCallback(check_PB,     XmNactivateCallback, check_CB,    NULL);
   XtAddCallback(clean_PB,     XmNactivateCallback, clean_CB,    NULL);
   XtAddCallback(reset_PB,     XmNactivateCallback, reset_CB,    NULL);
   XtAddCallback(cartridge_PB, XmNactivateCallback, exchange_CB, NULL);

   xms = XmStringCreateSimple("");
   XtVaSetValues(scaleCLb,  XmNlabelString, xms, NULL);
   XtVaSetValues(scaleBLb,  XmNlabelString, xms, NULL);
   XtVaSetValues(scaleMLb,  XmNlabelString, xms, NULL);
   XtVaSetValues(scaleYLb,  XmNlabelString, xms, NULL);
   XtVaSetValues(scaleLcLb, XmNlabelString, xms, NULL);
   XtVaSetValues(scaleLmLb, XmNlabelString, xms, NULL);
   XtVaSetValues(scaleLbLb, XmNlabelString, xms, NULL);
   XtVaSetValues(scalePhLb, XmNlabelString, xms, NULL);
   XmStringFree(xms);

   return mainWindow;
}

void unmapErrBox_CB(Widget w, XtPointer a, XtPointer b)
{
   XtDestroyWidget(w);
}

/*******************************************************************/
/* Function createNoPrinterBox()                                   */
/*                                                                 */
/* Build the error message box for printer not found               */
/*                                                                 */
/*******************************************************************/

Widget createNoPrinterBox(char *message)
{
   Widget  errorBox;
   Widget  tmp;
   Arg     arg[20];
   int     n;

   n = 0;
   XtSetArg(arg[n], XmNdialogStyle, XmDIALOG_FULL_APPLICATION_MODAL); n++;

   if ( message != NULL )
   {
      errorBox = XmCreateMessageDialog(mainWindow, message, arg, n);
   }
   else
   {
      errorBox = XmCreateMessageDialog(mainWindow, "noPrinter", arg, n);
   }
   tmp = XtNameToWidget(errorBox, "*Cancel");
   XtUnmanageChild(tmp);
   tmp = XtNameToWidget(errorBox, "*Help");
   XtUnmanageChild(tmp);
   XtAddCallback(errorBox,XmNunmapCallback, unmapErrBox_CB, NULL);
   return errorBox;
}

/*******************************************************************/
/* Function percent                                                */
/*                                                                 */
/* translate the value passed as HEX (2 chars) in decimal          */
/*                                                                 */
/* Input: unsigned char *buf The hex value to be translated        */
/*                                                                 */
/* Return: the decimal value according to hex value                */
/*                                                                 */
/*******************************************************************/

int percent(unsigned char *buf, int *iconNr)
{
   int val = 0;

   if ( buf[0] >= '0' &&  buf[0] <= '9' )
      val = (buf[0] - '0') * 16;
   else if ( buf[0] >= 'A' &&  buf[0] <= 'F' )
      val = (buf[0] - 'A' + 10 ) * 16;
   else if ( buf[0] >= 'a' &&  buf[0] <= 'f' )
      val = (buf[0] - 'a' + 10 ) * 16;

   if ( buf[1] >= '0' &&  buf[1] <= '9' )
      val += (buf[1] - '0');
   else if ( buf[1] >= 'A' &&  buf[1] <= 'F' )
      val += (buf[1] - 'A' + 10 );
   else if ( buf[1] >= 'a' &&  buf[1] <= 'f' )
      val += (buf[1] - 'a' + 10 );

   if ( val < 5 )
     *iconNr = 0;
   else if ( val < 20 && *iconNr == 2 )
     *iconNr = 1;
   return val;
}


/*******************************************************************/
/* Function setProgressBarColor                                    */
/*                                                                 */
/* set the color of the progress bar according to the given        */
/* color model. modifie the number of colors if applicable         */
/*                                                                 */
/* Input: char colorModel                                          */
/*                                                                 */
/* Return: -                                                       */
/*                                                                 */
/*******************************************************************/

void setProgressBarColor(char colorModel)
{
   /* scaleB, scaleC, scaleM, scaleY: nochanges */
   /* scaleLc  light cyan or red */
   /* scaleLm  light magenta or blue */
   /* scaleLb  grey, dark yellow or white */

   switch (colorModel)
   {
      case MODEL_KCMycmY:
         XtVaSetValues(scaleLc, XtVaTypedArg, XmNbackground,XmRString,"#80ffff",8,NULL);
         XtVaSetValues(scaleLm, XtVaTypedArg, XmNbackground,XmRString,"#ff80ff",8,NULL);
         XtVaSetValues(scaleLb, XtVaTypedArg, XmNbackground,XmRString,"#ffff80",8,NULL);
      break;
      case MODEL_KCMycmk:
         XtVaSetValues(scaleLc, XtVaTypedArg, XmNbackground,XmRString,"#80ffff",8,NULL);
         XtVaSetValues(scaleLm, XtVaTypedArg, XmNbackground,XmRString,"#ff80ff",8,NULL);
         XtVaSetValues(scaleLb, XtVaTypedArg, XmNbackground,XmRString,"#808080",8,NULL);
      break;
      case MODEL_KCMycm:
         XtVaSetValues(scaleLc, XtVaTypedArg, XmNbackground,XmRString,"#80ffff",8,NULL);
         XtVaSetValues(scaleLm, XtVaTypedArg, XmNbackground,XmRString,"#ff80ff",8,NULL);
      break;
      case MODEL_KCMycmGg: /* Photo R2400 */
         XtVaSetValues(scaleLc, XtVaTypedArg, XmNbackground,XmRString,"#80ffff",8,NULL);
         XtVaSetValues(scaleLm, XtVaTypedArg, XmNbackground,XmRString,"#ff80ff",8,NULL);
         XtVaSetValues(scaleLb, XtVaTypedArg, XmNbackground,XmRString,"#ffff80",8,NULL);
         
         XtVaSetValues(scaleLb, XtVaTypedArg, XmNbackground,XmRString,"#808080",8,NULL);
         XtVaSetValues(scalePh, XtVaTypedArg, XmNbackground,XmRString,"#c0c0c0",8,NULL);
      break;
      case MODEL_KCMyRBkX:
         XtVaSetValues(scaleLc, XtVaTypedArg, XmNbackground,XmRString,"#0000ff",8,NULL);
         XtVaSetValues(scaleLm, XtVaTypedArg, XmNbackground,XmRString,"#ff0000",8,NULL);
         XtVaSetValues(scaleLb, XtVaTypedArg, XmNbackground,XmRString,"#808080",8,NULL);
      case MODEL_KCMyRBX:
         XtVaSetValues(scalePh, XtVaTypedArg, XmNbackground,XmRString,"#ffffff",8,NULL);
      case MODEL_KCMyRB:
         XtVaSetValues(scaleLc, XtVaTypedArg, XmNbackground,XmRString,"red",4,NULL);
         XtVaSetValues(scaleLm, XtVaTypedArg, XmNbackground,XmRString,"blue",5,NULL);
      break;
   }
   
   switch (colorModel)
   {
      case MODEL_KCMycmY:  actConfig.colors = 7; break;
      case MODEL_KCMycmk:  actConfig.colors = 7; break;
      case MODEL_KCMycm:   actConfig.colors = 6; break;
      case MODEL_KCMyRBkX: actConfig.colors = 8; break;
      case MODEL_KCMyRBX:  actConfig.colors = 7; break;
      case MODEL_KCMyRB:   actConfig.colors = 6; break;
      case MODEL_KCMycmGg: actConfig.colors = 8; break;
   }
}

/*******************************************************************/
/* Function decodeStatus                                           */
/*                                                                 */
/* decode the string returned from printer and print the           */
/* informations in an human readable way                           */
/*                                                                 */
/* Input: unsigned char *buf The String returned from printer      */
/*        int            len Size of string                        */
/*                                                                 */
/* Return: 1 if any info found                                     */
/*                                                                 */
/*******************************************************************/

int decodeStatus(unsigned char *buf, int len)
{
   int           i;
   int           infOk = 0;
   char         *s;
   char          code[3];
   char          colorModel;
   static char  *color[11] =
   {
      "Black",
      "Cyan",
      "Magenta",
      "Yellow",
      "Light Cyan",
      "Light Magenta"
      "Dark Yellow",
      "Light Black",
      "Red",
      "Blue",
      "Gloss Optimizer",
      "Photo Black",
   };
   
   int iconNr = 2;

   int colIdx;
   pc1 = 0;
   pc2 = 0;
   pc3 = 0;
   pc4 = 0;
   pc5 = 0;
   pc6 = 0;
   pc7 = 0;
   pc8 = 0;

   for ( i = 0; i < len;)
   {
      if ( strncmp((char*)&buf[i], "ST:", 3 ) == 0 )
      {
         infOk = 1;
         i += 3;
         printerState = appResourceRec.unknown;
         switch( buf[i+1] )
         {
            case '0': printerState = appResourceRec.error;    break;
            case '1': printerState = appResourceRec.selfTest; break;
            case '2': printerState = appResourceRec.busy;     break;
            case '3': printerState = appResourceRec.printing; break;
            case '4': printerState = appResourceRec.ok;       break;
            case '7': printerState = appResourceRec.cleaning; break;
         }
         i +=3;
      }
      else if ( strncmp((char*)&buf[i], "ER:", 3 ) == 0 )
      {
         i += 3;
         s = NULL;
         switch( buf[i+1] )
         {
            case '1': s = "Interface not selected"; break;
            case '4': s = "Paper jam error";        break;
            case '5': s = "Ink out error";          break;
            case '6': s = "Paper out error";        break;
            default: s = code;
                    code[0] = buf[i];
                    code[1] = buf[i+1];
                    code[2] = 0;
         }

         i +=3;
      }
      else if ( strncmp((char*)&buf[i], "IQ:", 3 ) == 0 )
      {
         infOk = 1;
         i += 3;
         colIdx = 0;
         while ( i < len && colIdx < 7 && buf[i] != ';' )
         {
            switch(colIdx)
            {
               case 0: pc1 = percent(buf+i, &iconNr);break;
               case 1: pc2 = percent(buf+i, &iconNr);break;
               case 2: pc3 = percent(buf+i, &iconNr);break;
               case 3: pc4 = percent(buf+i, &iconNr);break;
               case 4: pc5 = percent(buf+i, &iconNr);break;
               case 5: pc6 = percent(buf+i, &iconNr);break;
               case 6: pc7 = percent(buf+i, &iconNr);break;
            }
            colIdx++;
            i += 2;
         }
         chgIcon(iconNr);
      }
      else if ( strncmp((char*)&buf[i], "INQ:", 4 ) == 0 )
      {
         infOk = 1;
         i += 4;
         colIdx = 0;
         colorModel = buf[i];
         i++;
         while ( i < len && colIdx < 8 && buf[i] != ';' )
         {
            switch(colIdx)
            {
               case 0: pc1 = percent(buf+i, &iconNr);break;
               case 1: pc2 = percent(buf+i, &iconNr);break;
               case 2: pc3 = percent(buf+i, &iconNr);break;
               case 3: pc4 = percent(buf+i, &iconNr);break;
               case 4: pc5 = percent(buf+i, &iconNr);break;
               case 5: pc6 = percent(buf+i, &iconNr);break;
               case 6: pc7 = percent(buf+i, &iconNr);break;
               case 7: pc8 = percent(buf+i, &iconNr);break;
            }
            colIdx++;
            i += 2;
         }
         chgIcon(iconNr);
         setProgressBarColor(colorModel);
      }
      else if ( strncmp((char*)&buf[i], "WR:", 3 ) == 0 )
      {
         infOk = 1;
         i += 3;
         colIdx = 0;
         while ( i < len && colIdx < 6 && buf[i] != ';' )
         {
            switch( buf[i+1] )
            {
               case '0':
               case '1':
               case '2':
               case '3':
               case '4':
               case '5':
                  s = color[buf[i+1]-'0'];
                  /* color[buf[i+1] (color) is LOW */
                  break;
               default: s = code;
                  code[0] = buf[i];
                  code[1] = buf[i+1];
                  code[2] = 0;
            }
            if ( buf[i+2] == ';' )
            {
               i += 3;
               break;
            }
            i += 3;
         }
      }
      else
      {
         i++;
      }
   }
   return infOk;
}

/*******************************************************************/
/* Function decodePrinterType                                      */
/*                                                                 */
/* decode the string returned from printer and print the           */
/* informations in an human readable way                           */
/*                                                                 */
/* Input: unsigned char *buf The String returned from printer      */
/*        int            len Size of string                        */
/*                                                                 */
/* Return: -                                                       */
/*                                                                 */
/*******************************************************************/

int decodePrinterType(unsigned char *buf, int len)
{
   char *s = (char*)buf;
   char *t = (char*)buf;
   int   i;

   for (i=0; i < len; i++)
   {
      if ( strncmp(s, "DES:", 4) == 0 || strncmp(s, "MDL:", 4) == 0 )
      {
         s +=4;
         t = s;
         while(*t && *t != ';')
            t++;
         *t = '\0';
         printerName = strdup(s);
         return 1;
      }
      else
      {
         s++;
      }
   }
   return 0;
}

/*******************************************************************/
/* Function setConfig                                              */
/*                                                                 */
/* Find the printer data and fill actConfig                        */
/*                                                                 */
/*******************************************************************/

int setConfig(void)
{
   int retVal = False;
   if ( actConfig.dev && actConfig.name )
   {
      retVal = True;
   }

   /* if the printer name was found, preset the id field */
   if  ( actConfig.name )
   {
      int i;
      for ( i = 0; i < defaultConfigDataSize; i++ )
      {
         if ( strcasecmp(defaultConfigData[i].name,actConfig.name) == 0 )
         {
            actConfig.id = defaultConfigData[i].id;
            actConfig.colors = defaultConfigData[i].colors;
            actConfig.prot = defaultConfigData[i].prot;
            actConfig.state = defaultConfigData[i].state;
            actConfig.exchange = defaultConfigData[i].exchange;
            actConfig.exchangeSeparate = defaultConfigData[i].exchangeSeparate;
            actConfig.cleanSeparate = defaultConfigData[i].cleanSeparate;
            actConfig.passes = defaultConfigData[i].passes;
            actConfig.choices = defaultConfigData[i].choices;
            actConfig.color_passes = defaultConfigData[i].color_passes;
            actConfig.color_choices = defaultConfigData[i].color_choices;
            break;
         }
      }
   }
   return retVal;
}

/*******************************************************************/
/* Function scale_CB                                               */
/*                                                                 */
/* Set the scale position to zero if he user modify this           */
/*                                                                 */
/*******************************************************************/

static void scale_CB(Widget w, XtPointer clientData, XtPointer callData)
{
    XtVaSetValues(w, XmNvalue,0,NULL);
}


/*******************************************************************/
/* Function pref_CB                                                */
/*                                                                 */
/* window for setting of preferences                               */
/*                                                                 */
/*******************************************************************/

static void pref_CB(Widget w, XtPointer clientData, XtPointer callData)
{
   XmString  xms;

   wConfig_data_t data;
   data.printerName    = actConfig.name;
   data.bt1            = NULL;
   data.bt2            = NULL;
   data.bt3            = appResourceRec.ok;
   data.message        = appResourceRec.about;
   data.wait           = &waitForConfigWindow;
   data.colTb          = 0;

   popupCfg2(mainWindow, &data);
   XtUnmanageChild(data.actWindow);
   XtManageChild(mainWindow);

   if ( actConfig.name != data.printerName && actConfig.name[0] != '?' )
   {
      xms = XmStringCreateSimple(actConfig.name);
      XtVaSetValues(title_LB,XmNlabelString,xms,NULL);
      XmStringFree(xms);
   }
}

/*******************************************************************/
/* Function callBrowser                                            */
/*                                                                 */
/* open the file in the given browser                              */
/*                                                                 */
/*******************************************************************/

static void callBrowser(char *file)
{
   char   command[4096];
   int    isNetscape = False;
   int    isMozilla  = False;
   int    isGaleon   = False;
   char  *s;
#ifdef MACOS
   /* use default application */
   snprintf(command,sizeof(command),"/usr/bin/open %s",file);
#else
   if ( browser && *browser )
   {
      s = strrchr(browser, '/');
      if ( s )
      {
         s++;
         if ( strcmp(s, "netscape") == 0 ||
              strcmp(s, "Netscape") == 0 )
         {
            isNetscape = True;
         }
         else if ( strcmp(s, "mozilla") == 0  ||
                   strcmp(s, "Mozilla") == 0   )
         {
            isMozilla = True;
         }
         else if ( strcmp(s, "galeon") == 0  )
         {
            isGaleon = True;
         }
      }
      else
      {
         if ( strcmp(browser, "netscape") == 0 ||
              strcmp(browser, "Netscape") == 0 )
         {
            isNetscape = True;
         }
         if ( strcmp(browser, "mozilla") == 0  ||
              strcmp(browser, "Mozilla") == 0   )
         {
            isMozilla = True;
         }
         else if ( strcmp(browser, "galeon") == 0  )
         {
            isGaleon = True;
         }
      }
   }
   else
   {
      browser = strdup("netscape");
      isNetscape = True;
   }

   /* remark about starting of netscape / mozilla                  */
   /* Solaris don't like "if ! netscape ...;then netscape ...;fi   */
   /* we use instead an if netscape ... then :;else netscape...;fi */
   /* : is a no op instruction for the shell                       */
   if ( isNetscape )
   {
      /* call netscape */
       sprintf(command,
            "if %s -remote \"openURL(file://%s)\";then :;else %s file://%s;fi &",
            browser, file, browser, file);
   }
   else  if ( isGaleon )
   {
      snprintf(command,sizeof(command),"%s -x %s &",browser, file);
   }
   else  if ( isMozilla )
   {
       /* previous version of mozilla require file:///path/file */
       snprintf(command,sizeof(command),
            "if %s -remote \"openURL(file://%s)\";then :;else %s file://%s; fi &",
            browser, file, browser, file);
   }
   else
   {
      /* most browser don't need an extra option */
      sprintf(command,"%s %s &",browser, file);
   }
#endif
   /* if we have root or lp rights, we have to get the uid instead */
   /* of the euid. start the browser as "daemon" */
   if ( fork() == 0 )
   {
      if ( fork() == 0 )
      {
         seteuid(getuid());
         system(command);
         exit(0);
      }
      exit(0);
      /* exit first subprocess */
   }
   /* wait for the first sub process and avoid a zomby */
   wait(&isGaleon);
}

/*******************************************************************/
/* Function help_CB                                                */
/*                                                                 */
/* try to find the mtink documentation and open this in netscape   */
/*                                                                 */
/*******************************************************************/

static void help_CB(Widget w, XtPointer clientData, XtPointer callData)
{
   char  *myCastel = getenv("HOME");
   char   home[1024];
   char   localDir[1024];
   char   file[1024];

   char **dir;
   char  *dirs [] = {
       localDir,
#if defined PREFIX
       PREFIX"/doc/mtink",
#endif
       "/usr/share/doc/printer-utils-1.0/EpsonInkjetMaintenance", /* Mandriva */
       "/usr/local/share/doc/mtink",
       "/usr/local/share/doc",
       "/usr/local/doc/mtink",
       "/usr/local/doc",
       "/usr/local/mtink",
       "/usr/share/doc/mtink",
       "/usr/share/doc/mtink-doc", /* ubuntu - debian */
       "/usr/share/doc",
       "/usr/doc/mtink",
       "/usr/doc",
       "/opt/mtink",
       "/usr/mtink",
       home,
       NULL
    };

    getcwd(localDir, sizeof(localDir));
    home[0] = '\0';
    if ( myCastel )
       snprintf(home,sizeof(localDir)-100,"%s/mtink",myCastel);
    dir = dirs;
    /* look for the mtink.html file */
    while( dir[0] )
    {
       sprintf(file,"%s/mtink.%s.html", dir[0],guiLanguage );
       if ( access(file,R_OK) == 0 )
       {
          callBrowser(file);
          return;
       }
       else
       {
          sprintf(file,"%s/mtink.html", dir[0]);
          if ( access(file,R_OK) == 0 )
          {
             callBrowser(file);
             return;
          }
       }
       dir++;
   }
   /* not found */
}

/*******************************************************************/
/* Function CreateScale                                            */
/*                                                                 */
/* Create our scale "widget"                                       */
/*                                                                 */
/*******************************************************************/

static Widget CreateScale(Widget parent, char *name, Widget top)
{
   Widget      wid;
   Widget      scale;
   Widget      sep;
   int         i = 0;
   Pixel       pix;
   int         sz = 0;  /* make gcc happy */
   char        sepName[10];

   wid = XtVaCreateWidget("scaleForm",
                          xmFormWidgetClass,   parent,
                          XmNleftAttachment,   XmATTACH_FORM,
                          XmNtopAttachment,    XmATTACH_WIDGET,
                          XmNtopOffset,        5,
                          XmNtopWidget,        top,
                          XmNleftAttachment,   XmATTACH_FORM,
                          XmNleftOffset,       5,
                          XmNrightAttachment,  XmATTACH_FORM,
                          XmNrightOffset,      5,
                          XmNrightOffset,      5,
                          XmNshadowThickness,  0,
                          XmNborderWidth,      0,
                          XmNmarginWidth,      0,
                          XmNfractionBase,     101,
                          NULL);
   XtManageChild(wid);

   XtVaGetValues(wid, XmNbackground, &pix, NULL);

   /* build separators */
   for ( i = 0; i < 101; i += 2 )
   {
      if ( i == 0 || i == 50 || i == 100 )
         sz = 10;
      else if ( i % 10 == 0 )
         sz = 6;
      else if ( i % 2 == 0 )
         sz = 3;

      sprintf(sepName,"sep_%d",i);

      sep = XtVaCreateWidget(sepName,
                           xmSeparatorWidgetClass, wid,
                           XmNorientation,         XmVERTICAL,
                           XmNheight,              sz,
                           XmNwidth,               2,
                           XmNtopAttachment,       XmATTACH_FORM,
                           XmNtopOffset,           10-sz,
                           XmNleftAttachment,      XmATTACH_POSITION,
                           XmNleftPosition,        i,
                           XmNshadowThickness,     1,
                           XmNseparatorType,       XmSINGLE_LINE,
                                                   NULL);
       XtManageChild(sep);
   }

   /* Scrollbar */
   scale = XtVaCreateWidget(name,
                            xmScrollBarWidgetClass, wid,
                            XmNeditable,            False,
                            XmNtopAttachment,       XmATTACH_WIDGET,
                            XmNtopWidget,           sep,
                            XmNtopOffset,           0,
                            XmNleftAttachment,      XmATTACH_FORM,
                            XmNleftAttachment,      XmATTACH_FORM,
                            XmNrightAttachment,     XmATTACH_FORM,
                            XmNminimum,             0,
                            XmNmaximum,             100,
                            XmNsliderSize,          1,
                            XmNorientation,         XmHORIZONTAL,
                            XmNshowArrows,          XmNONE,
                            XmNtroughColor,         pix,
                            XmNshadowThickness,     1,
                            XmNborderWidth,         0,
                            XmNvalue,               0,
                            NULL);
   XtManageChild(scale);
   XtAddCallback(scale,XmNvalueChangedCallback, scale_CB, NULL);

   return scale;
}
