Logo Search packages:      
Sourcecode: xabacus version File versions  Download package

xabacus.c

/*-
# MOTIF/X-BASED ABACUS
#
#  xabacus.c
#
###
#
#  Copyright (c) 1993 - 2006  David Albert Bagley, bagleyd@tux.org
#
#  Abacus demo and neat pointers from
#  Copyright (c) 1991 - 1998  Luis Fernandes, elf@ee.ryerson.ca
#
#                   All Rights Reserved
#
#  Permission to use, copy, modify, and distribute this software and
#  its documentation for any purpose and without fee is hereby granted,
#  provided that the above copyright notice appear in all copies and
#  that both that copyright notice and this permission notice appear in
#  supporting documentation, and that the name of the author not be
#  used in advertising or publicity pertaining to distribution of the
#  software without specific, written prior permission.
#
#  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.
#
*/

/*-
  Version 7: 03/11/15 X/Windows
  Version 5: 95/09/30 Xt/Motif
  Version 4: 94/05/07 Xt
  Version 3: 93/02/03 Motif
  Version 2: 91/12/17 XView
  Version 1: 91/02/14 SunView
*/

#ifndef WINVER
static const char aboutHelp[] = {
      "Abacus Version 7.1.7\n"
      "Send bugs (reports or fixes) to the author: "
      "David Bagley <bagleyd@tux.org>\n"
      "The latest version is at: "
      "http://www.tux.org/~bagleyd/abacus.html\n"
      "Some coding was also done by Luis Fernandes <elf@ee.ryerson.ca>\n"
      "and Sarat Chandran <saratcmahadevan@yahoo.com>\n"
};

static const char optionsHelp[] = {
      "\t[-geometry [{width}][x{height}] [{+-}{xoff}[{+-}{yoff}]]]\n"
      "\t[-display [{host}]:[{vs}]] [-[no]mono] [-[no]{reverse|rv}]\n"
      "\t[-{foreground|fg} {color}] [-{background|bg} {color}]\n"
      "\t[-bead {color}] [-frame {color}] [-rail {color}]\n"
      "\t[-{border|bd} {color}] [-delay msecs] [-[no]sound]\n"
      "\t[-bumpSound {filename}] [-moveSound {filename}]\n"
      "\t[-[no]demo] [-[no]script] [-demopath {path}]\n"
      "\t[-{demofont|demofn} {fontname}]\n"
      "\t[-{demoforeground|demofg} {color}]\n"
            "\t[-[no]vertical] [-[no]slot] [no]diamond]\n"
            "\t[-[no]torient] [-[no]borient] [-tnumber {int}]\n"
        "\t[-bnumber {int}] [-tfactor {int}] [-bfactor {int}]\n"
      "\t[-tspaces {int}] [-bspaces {int}] [-tpiece {int}]\n"
            "\t[-bpiece {int}] [-tpiecePercent {int}] [-bpiecePercent {int}]\n"
      "\t[-shiftPercent {int}] [-[no]sign] [-decimalPosition {int}]\n"
      "\t[-groupSize {int}] [-rails {int}] [-base {int}] [-anomaly {int}]\n"
        "\t[-shiftAnomaly] [-anomalySq {int}] [-shiftAnomalySq]\n"
      "\t[-displayBase {int}] [-[no]romanNumerals]\n"
      "\t[-{chinese|japanese|korean|roman|russian|other}] [-version]\n"
};
#endif

#ifdef HAVE_MOTIF
static const char options1Help[] = {
      "-geometry {+|-}X{+|-}Y    "
      "This option sets the initial position of the abacus "
      "window (resource name \"geometry\").\n"
      "-display host:dpy    "
      "This option specifies the X server to contact.\n"
      "-[no]mono            "
      "This option allows you to  display on a color screen "
      "as if monochrome (resource name \"mono\").\n"
      "-[no]{reverse|rv}    "
      "This option allows you to see the abacus window in "
      "reverse video (resource name \"reverse\").\n"
      "-{foreground|fg} color    "
      "This option specifies the foreground of  the  abacus "
      "window (resource name \"foreground\").\n"
      "-{background|bg} color    "
      "This option specifies the background of  the  abacus "
      "window (resource name \"background\").\n"
      "-frame color    "
      "This option specifies the foreground  of  the  frame "
      "(resource name \"frameColor\").\n"
      "-rail color     "
      "This option specifies the foreground  of  the  rails "
      "(resource name \"railColor\").\n"
      "-bead color     "
      "This option specifies the foreground  of  the  beads "
      "(resource name \"beadColor\").\n"
      "-{border|bd} color   "
      "This option specifies the foreground of the border "
      "of the beads (resource name \"borderColor\").\n"
      "-delay msecs    "
      "This option specifies the number of milliseconds it "
      "takes to move a bead or a group of beads\n"
      "        one space (resource name \"delay\").\n"
      "-[no]sound      "
      "This option specifies if a sliding bead should "
      "make a sound or not (resource name \"sound\").\n"
      "-bumpSound filename  "
      "This option specifies the file for the bump sound.\n"
      "-moveSound filename  "
      "This option specifies the file for the move sound.\n"
      "-[no]demo       "
      "This option specifies to run in demo mode.  In  this "
      "mode, the abacus is controlled by the current\n"
      "        lesson (resource name \"demo\").  When started with "
      "the demo option, a window contains descriptive text,\n"
      "        and user prompts are displayed in this window.  Pressing "
      "'q' during  the  demo  will quit it.  Clicking the\n"
      "        left mouse-button with the pointer  in  the  window "
      "will restart the demo (beginning of current lesson).\n"
      "-[no]script     "
      "This option specifies to log application to  stdout, "
      "every  time  the  user  clicks  to  move  the\n"
      "        beads (resource name \"script\"). The output  is  a  set  "
      "of deck,  rail,  beads  added  or  subtracted,  and\n"
      "        the number of text lines (4).  This can be edited to add "
      "text to the lesson and used as a new demo keeping\n"
      "        the generated numbers and the number of  lines  constant"
      "  If you want to add a \"do nothing\", the first\n"
      "        line generated is an example of that.  For  example: "
      "\"xabacus -script > Abacus5.les\"\n"
      "-demopath path  "
      "This option specifies the path for the demo,  possibly"
      "  /usr/share/games/xabacus  (resource name\n"
      "        \"demoPath\").  It initially looks for Abacus1.les."
      "  If it finds that, it will later look for Abacus2.les, etc.\n"
      "-{demofont|demofn} fontstring    "
      "This option specifies the font for the "
      "explanatory text that appears in the\n"
      "        secondary window, during the demo.  The default font is "
      "18 point Times-Roman (-*-times-*-r-*-*-*-180-*).\n"
      "        The alternate font is 8x13 (resource name \"demoFont\").\n"
      "-{demoforeground|demofg} color    "
      "This option specifies the foreground of  the  abacus "
      "demo window (resource name\n"
      "        \"demoForeground\").\n"
      "-{demobackground|demobg} color    "
      "This option specifies the background of  the  abacus "
      "demo window (resource name\n"
      "        \"demoBackground\").\n"
      "-[no]vertical   "
      "This option allows you to set the abacus to allow "
      "a Russian orientation (resource name \"vertical\").\n"
      "-[no]slot       "
      "This option allows you to have either slots or rails "
      "(resource name \"slot\").\n"
      "-[no]diamond    "
      "This option allows you to have diamond or round beads "
      "(resource name \"diamond\").\n"
};

static const char options2Help[] = {
      "-[no]torient    "
      "This option specifies the orientation of the beads "
      "on top (resource name \"topOrient\").\n"
      "-[no]borient    "
      "This option specifies the orientation of the beads "
      "on bottom (resource name \"bottomOrient\").\n"
      "-tnumber int    "
      "This option specifies the number  of  beads on top "
      "(resource name \"topNumber\").\n"
      "-bnumber int    "
      "This option specifies the number of beads on  bottom "
      "(resource name \"bottomNumber\").\n"
      "-tfactor int    "
      "This option specifies the multiply  factor  for  the "
      "beads on top (resource name \"topFactor\").\n"
      "-bfactor int    "
      "This option specifies the multiply  factor  for  the "
      "beads on bottom (resource name \"bottomFactor\").\n"
      "-tspaces int    "
      "This option specifies the number of spaces on top "
      "(resource name \"topSpaces\").\n"
      "-bspaces int    "
      "This option specifies the number of spaces on bottom "
      "(resource name \"bottomSpaces\").\n"
      "-tpiece int     "
      "This option specifies the number of pieces on top "
      "(resource name \"topPiece\").\n"
      "-bpiece int     "
      "This option specifies the number of pieces on bottom "
      "(resource name \"bottomPiece\").\n"
      "-tpiecePercent int   "
      "This option specifies the number of piece percents on top "
      "(resource name \"topPiecePercent\").\n"
      "-bpiecePercent int   "
      "This option specifies the number of piece percents on bottom "
      "(resource name \"bottomPiecePercent\").\n"
      "-shiftPercent int    "
      "This option specifies the shift of rails for piece percents "
      "and also may influence the\n"
            "        precision of the calculation (resource name "
            "\"shiftPercent\").\n"
      "-[no]sign       "
      "This option allows you to set the abacus to allow "
      "negatives (resource name \"sign\").\n"
      "-decimalPosition int "
      "This option specifies the number of rails to the "
      "right of the decimal point\n"
            "        (normally 2) (resource name \"decimalPosition\").\n"
      "-groupSize int       "
      "This option specifies the group size to the left of the "
      "decimal point (normally 3) (resource\n"
            "        name \"groupSize\").\n"
      "-rails int      "
      "This option specifies the number of rails (resource "
      "name \"rails\").\n"
      "-base int       "
      "This option specifies the base used (default is base "
      "10) (resource name \"base\").  By default,\n"
      "        one has to set the format mode to not be "
      "Other for this to work (unless you know what you are doing).\n"
      "-anomaly int    "
      "This option specifies the offset from the base for a "
            "multiplicative factor of the rail with the\n"
            "        anomaly (if none, this is set to 0) (resource"
      "name \"anomaly\").  Currently, this only permissable\n"
            "        if carries are not possible on abacus (such as "
            "a Roman or a Japanese abacus without Quarters or Twelfths).\n"
      "-anomalyShift int    "
      "This option specifies the offset from decimal point "
            "for the anomaly (usually 2) (resource name\n"
            "        \"anomalyShift\").\n"
      "-anomalySq int       "
      "This option specifies the offset from base for the "
            "second anomaly (if none, this is set to 0)\n"
            "        (resource name \"anomalySq\").\n"
      "-anomalySqShift int  "
      "This option specifies the offset in rails from the "
            "first anomaly (usually 2) (resource\n"
            "        name \"anomalySqShift\").\n"
      "-displayBase int     "
      "This option specifies the base displayed (default is "
      "base 10) (resource name \"displayBase\").\n"
      "        If this is different then \"base\" then it is "
      "implemented using \"long long\" and the calculation is\n"
      "        limited by its bounds.  Also the fractional "
      "part does not scale with the \"displayBase\" so if the\n"
      "        \"displayBase\" is greater than the \"base\" it "
      "looses some precision.  Also no rounding is done.\n"
      "-[no]romanNumerals   "
      "This option allows you to set the abacus to "
      "allow Roman Numerals (resource name\n"
      "        \"romanNumerals\").  Roman Numerals above 3999 are "
      "normally represented with bars on top, due to ASCII\n"
      "        constraints this is represented instead in lower case "
      "(historically case was ignored).   Roman Numerals above\n"
      "        3,999,999 were not represented historically.  "
      "Roman numerals change with displayBase in an\n"
            "        \"experimental\" way.\n"
      "-chinese    "
      "This option specifies the format of the abacus "
      "(resource name \"format\") to \"Chinese\"\n"
      "        for the Chinese Saun-pan.\n"
      "-japanese   "
      "This option specifies the format of the abacus "
      "(resource name \"format\") to \"Japanese\"\n"
      "        for the Japanese post-WWII Soroban.  "
      "This is also similar to the Roman Hand Abacus.\n"
      "-korean     "
      "This option specifies the format of the abacus "
      "(resource name \"format\") to \"Korean\"\n"
      "        for the Korean Supan or Japanese pre-WWII "
      "Soroban.\n"
      "-roman      "
      "This option specifies the format of the abacus "
      "(resource name \"format\") to \"Roman\"\n"
      "        for the Roman Hand Abacus, note beads will "
      "move in slots.  To complete, specify \"romanNumerals\".\n"
      "-russian    "
      "This option specifies the format of the abacus "
      "(resource name \"format\") to \"Russian\"\n"
      "        for the Russian Schoty.  To complete, "
      "specify \"piece\" resource to be 4.\n"
      "-other      "
      "This option specifies the format of the abacus "
      "(resource name \"format\") to \"Other\".  This option specifies\n"
      "        a format that is more configurable by using "
      "resources, since there are few rules to govern its behavior.\n"
      "-version    "
      "This option tells you what version of xabacus you have.\n"
};
#endif

#if defined(HAVE_MOTIF) || defined(WINVER)
static const char descriptionHelp[] = {
      "This is an implementation of the classic Chinese abacus "
      "(Saun-pan) which has its origins in the 12th century.\n"
      "\n"
      "The device  has two decks.  Each deck, separated by a  partition,"
      " normally  has  13  rails  on which are  mounted  beads.\n"
      "Each rail on the top deck contains 1 or 2  beads,  and  each "
      "rod  on the bottom deck contains 4 or 5 beads.  Each bead on\n"
      "the upper deck has a value of five, while each bead  on  the "
      "lower  deck has value of one.  Beads are considered counted,\n"
      "when moved towards the partition separating the  decks, i.e. "
      "to  add a value of one a bead in the bottom deck is moved up\n"
      "and to add a value of 5 a bead in  the  top  deck  is  moved "
      "down.\n"
      "\n"
      "The basic operations of the abacus are addition and subtraction. "
      "  Multiplication can be done by mentally multiplying the\n"
      "digits  and adding up the intermediate results  on the abacus. "
      " Division would be similar  where the intermediate results\n"
      "are subtracted.  There are techniques like using your thumb "
      "with forefinger  which does not apply with mouse entry.  Also\n"
      "with multiplication,  one can  carry out calculations  on "
            "different parts  of the abacus, here it is nice to  have a long\n"
            "abacus.\n"
      "\n"
      "The pre-WWII Japanese abacus (Soroban)  (or Korean Supan) is "
      "similar to the Chinese abacus but has only one bead per rail\n"
      "on the top deck.  The later Japanese abacus was further "
      "simplified to have only 4 beads per rail on the bottom deck.\n"
      "\n"
      "The Roman hand-abacus predates the  Chinese  abacus  and  is "
      "very similar to the later Japanese abacus, but seems to have\n"
      "fallen out of use with the Fall  of  the  Roman  Empire  (at "
      "least 3 are in existence).  The Roman abaci are brass plates\n"
      "where the beads move in slots.  In addition to the normal  7 "
      "columns  of  beads, they generally have 2 special columns on\n"
      "the right side.  In two examples:  the first  special column "
      "was for 12ths  (12 uncia (ounces) = 1 as) and had one  extra\n"
      "bead in the bottom deck.  Also the last column was a combination "
      "of halves, quarters,  and thirds of an ounce  and had no\n"
      "beads in the top deck and 4 at the bottom (beads did not have "
      "to come to the top  to be  counted  but at one of 3  marked\n"
      "points,  where the top bead was for halves, 1 for  quarters, "
      "and the bottom 2 for thirds).  In another surviving example:\n"
      "the 2 special columns were switched and the combination "
      "column was broken into 3 separate slots.  Currently, its\n"
      "not possible to setup the second special column on this "
            "implementation.\n"
      "\n"
      "The Russian abacus was invented in the 17th  century,  here "
      "the beads are moved from right to left (currently the xabacus\n"
      "can not be oriented that way and  one has to  move the beads "
      "down).   It has colored beads in the middle for ease of use.\n"
      "Quarters represent  1/4  Rubles and are only  present  historically"
      " on  the  Russian  abacus (Schoty).  Some of the older\n"
      "Schoty have a extra place for the 1/4  Kopek  (quarter  percent)"
      " as well as the 1/4 Ruble (quarter).\n"
      "\n"
      "The Mesoamerican Nepohualtzintzin is a Japanese abacus base 20. "
      "  The Mesoamericans had base 20 with the exception of the\n"
            "3rd decimal  place where instead of 20 * 20 = 400 the third place "
            "marked 360  and the 4th place was 20 * 360, etc..  They\n"
            "independently  created their own zero  (only Babylon (base 60) "
            "and  India (base 10) have done this)  but the anomaly took\n"
      "away its true power.  Disable anomaly by setting anomaly to 0.\n"
      "\n"
      "The Chinese Solid-and-Broken-Bar System is a base 12 numbering "
            "system and not really an abacus.  When the abacus is setup\n"
            "in this way though, it is easy to relate the two.\n"
      "\n"
      "An easy way of figuring out time in seconds given hours, "
            "minutes, and seconds,  can be done on the Roman abacus or on the\n"
            "Japanese abacus with special \"anomaly\" settings.\n"
      "\n"
      "The signed bead is an invention of the  author  and  is  not "
      "present  on  any historical abacus (to his knowledge) and is\n"
      "used to represent negatives.  \"New & Improved\" abacus "
      " models have two auxiliary  decks stacked above the principal decks\n"
      "that enable multiplication, division, square-root, and "
      "cube-root computations to be performed with equal ease as addition\n"
      "and subtraction."
};

static const char featuresHelp[] = {
      "Click \"mouse-left\" button on a bead you want to  move.   The "
      "beads  will  shift  themselves  to vacate the row and column\n"
      "that was clicked.\n"
      "\n"
      "Click \"mouse-right\" button, or press \"C\" or \"c\" keys, to "
      "clear the abacus.\n"
      "\n"
      "Press \"O\" or \"o\" keys to toggle the demo mode.\n"
      "\n"
      "Press \"I\" or \"i\" keys to increment the number of rails.\n"
      "\n"
      "Press \"D\" or \"d\" keys to decrement the number of rails.\n"
      "\n"
      "Press \"F\" or \"f\" keys to switch between Chinese, Japanese, "
      "Korean, Roman, and Russian formats.\n"
      "\n"
      "Press \"M\" or \"m\" keys to toggle the availability of Roman "
      "Numerals.\n"
      "\n"
      "Press \"S\" or \"s\" keys to toggle the availability of sign "
      "bead.\n"
      "\n"
      "Press \"U\" or \"u\" keys to toggle the availability of quarter "
      "beads.  (Mutually exclusive to twelfth beads).\n"
      "\n"
      "Press \"P\" or \"p\" keys to toggle the availability of quarter "
      "percent beads.\n"
      "\n"
      "Press \"T\" or \"t\" keys to toggle the availability of twelfth "
      "beads.  (Mutually exclusive to quarter beads).\n"
      "\n"
      "Press \"A\" or \"a\" keys to toggle the availability of anomaly "
      "bars.  (Mutually exclusive to watch bars).\n"
      "\n"
      "Press \"W\" or \"w\" keys to toggle the availability of watch "
      "bars.  (Mutually exclusive to anomaly bars).\n"
      "\n"
      "Press \">\" or \".\" keys to speed up the movement of beads.\n"
      "\n"
      "Press \"<\" or \",\" keys to slow down the movement of beads.\n"
      "\n"
      "Press \"@\" key to toggle the sound.\n"
      "\n"
      "Press \"Esc\" key to hide program.\n"
      "\n"
      "Press \"Q\", \"q\", or \"CTRL-C\" keys to kill program.\n"
      "\n"
      "The abacus may be resized.  Beads will reshape depending  on "
      "the room they have.  Demo Mode:  In this mode, the abacus is\n"
      "controlled by the  program.   When  started  with  the  demo "
      "option,  a  second window is presented that should be placed\n"
      "directly below the abacus-window. Descriptive text, and user "
      "prompts  are  displayed in this window.  Pressing 'q' during\n"
      "the demo will quit it.  Clicking the left mouse-button  with "
      "the  pointer  in the window will restart the demo (beginning\n"
      "of current lesson)."
};

static const char referencesHelp[] = {
      "Luis Fernandes  http://www.ee.ryerson.ca/~elf/abacus/\n"
      "Lee Kai-chen, How to Learn Lee's Abacus, 1958, 58 pages.\n"
      "Abacus Guide Book, 57 pages.\n"
      "Georges Ifrah, The Universal history of Numbers, Wiley Press "
      "2000, pp 209-211, 288-294.\n"
      "Review of above: http://www.ams.org/notices/200201/rev-dauben.pdf\n"
      "David Eugene Smith, History of Mathematics Volume II, "
      "Dover Publications, Inc 1958, pp 156-195.\n"
};
#endif

static const char *formatString[] =
{
      "Chinese", "Japanese", "Korean", "Roman", "Russian", "Other"
};

#ifdef WINVER
#include "AbacusP.h"
#include "wabacus.h"
#define TITLE "wabacus"

static AbacusRec widget;

#define MAXDIGITS 256         /* This limits the number of rails */

static void
forceNormalParams(AbacusWidget w)
{
      int base = DEFAULTBASE;
      int displayBase = DEFAULTBASE;

      w->abacus.base = base;
      w->abacus.displayBase = displayBase;
}

static void
forceDemoParams(AbacusWidget w)
{
      int min, mode;
      int bottomPiece, bottomPiecePercent;
      Boolean demo, sign;

      forceNormalParams(w);
      mode = w->abacus.mode;
      sign = w->abacus.sign;
      bottomPiece = w->abacus.decks[BOTTOM].piece;
      bottomPiecePercent = w->abacus.decks[BOTTOM].piecePercent;
      demo = w->abacus.demo;
      if (mode == OTHER) {
            FormatAbacus(w);
      }
      min = ((sign) ? 1: 0) + ((bottomPiece) ? 1 : 0) +
            ((bottomPiecePercent) ? 1 + w->abacus.shiftPercent : 0) +
            ((demo) ? MINDEMORAILS : MINRAILS);
      while (w->abacus.rails < min) {
            IncrementAbacus(w);
      }
}

void
SetAbacus(AbacusWidget w, int reason)
{
      switch (reason) {
            case ABACUS_SCRIPT:
#if 0
                  {
                        int deck, rail, number;

                        deck = w->abacus.deck;
                        rail = w->abacus.rail;
                        number = w->abacus.number;
                        (void) printf("%d %d %d %d\n", PRIMARY,
                              deck, rail, number);
                  }
#endif
                  break;
            case ABACUS_BASE_DEFAULT:
                  forceNormalParams(w);
                  break;
            case ABACUS_DEMO_DEFAULT:
                  forceDemoParams(w);
                  break;
            case ABACUS_CLEAR:
                  ClearAbacusDemo(w);
                  break;
            case ABACUS_HIDE:
                  ShowWindow(w->core.hWnd, SW_SHOWMINIMIZED);
                  break;
            case ABACUS_CLEAR_QUERY:
                  break;
            case ABACUS_DEMO:
                  DemoAbacusDemo(w);
                  break;
            case ABACUS_NEXT:
                  NextAbacusDemo(w);
                  break;
            case ABACUS_REPEAT:
                  RepeatAbacusDemo(w);
                  break;
            case ABACUS_MORE:
                  MoreAbacusDemo(w);
                  break;
            case ABACUS_INC:
            case ABACUS_DEC:
            case ABACUS_FORMAT:
            case ABACUS_ROMANNUMERAL:
            case ABACUS_SIGN:
            case ABACUS_QUARTER:
            case ABACUS_QUARTERPERCENT:
            case ABACUS_TWELFTH:
            case ABACUS_ANOMALY:
            case ABACUS_WATCH:
                  break;
      }
}

void
SetAbacusString(AbacusWidget w, int reason, char *string)
{
      if (reason == ABACUS_SCRIPT || reason == ABACUS_IGNORE) {
            char szBuf[MAXDIGITS + 67];
            int mode = w->abacus.mode;

            (void) sprintf(szBuf, "%s %s =%s",
                  (mode < 0 || mode > MAXMODES) ? "" :
                  formatString[mode],
                  TITLE, string);
            SetWindowText(w->core.hWnd, (LPSTR) szBuf);
      }
}

static LRESULT CALLBACK
About(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
{
      switch (message) {
            case WM_COMMAND:
                  if (LOWORD(wParam) == IDOK) {
                        (void) EndDialog(hDlg, TRUE);
                        return TRUE;
                  }
                  break;
      }
      return FALSE;
}

static LRESULT CALLBACK
WindowProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
{
      HBRUSH brush = (HBRUSH) NULL;
      PAINTSTRUCT paint;

      widget.core.hWnd = hWnd;
      if (GetFocus()) {
            if (!widget.abacus.focus) {
                  widget.core.hDC = GetDC(hWnd);
                  (void) SelectObject(widget.core.hDC,
                        GetStockObject(NULL_BRUSH));
                  EnterAbacus(&widget);
                  (void) EndPaint(hWnd, &paint);
            }
      } else {
            if (widget.abacus.focus) {
                  widget.core.hDC = GetDC(hWnd);
                  (void) SelectObject(widget.core.hDC,
                        GetStockObject(NULL_BRUSH));
                  LeaveAbacus(&widget);
                  (void) EndPaint(hWnd, &paint);
            }
      }
      switch (message) {
            case WM_CREATE:
                  InitializeAbacus(&widget, brush);
                  InitializeAbacusDemo(&widget);
                  break;
            case WM_DESTROY:
                  DestroyAbacus(&widget, brush);
#if 0
                  if (widget.abacus.demo)
                        DestroyAbacusDemo();
#endif
                  break;
            case WM_SIZE:
                  ResizeAbacus(&widget);
                  (void) InvalidateRect(hWnd, NULL, TRUE);
                  break;
            case WM_PAINT:
                  widget.core.hDC = BeginPaint(hWnd, &paint);
                  (void) SelectObject(widget.core.hDC,
                        GetStockObject(NULL_PEN));
                  ExposeAbacus(&widget);
                  if (widget.abacus.demo) {
                        ExposeAbacusDemo(&widget);
                  }
                  (void) EndPaint(hWnd, &paint);
                  break;
            case WM_LBUTTONDOWN:
                  widget.core.hDC = GetDC(hWnd);
                  (void) SelectObject(widget.core.hDC,
                        GetStockObject(NULL_PEN));
#if 0
                  if (widget.abacus.demo) {
                        ClearAbacus(&widget);
                        ClearAbacusDemo(&widget);
                  } else
#endif
                  {
                        SelectAbacus(&widget, LOWORD(lParam),
                              HIWORD(lParam));
                  }
                  (void) ReleaseDC(hWnd, widget.core.hDC);
                  break;
            case WM_LBUTTONUP:
                  widget.core.hDC = GetDC(hWnd);
                  (void) SelectObject(widget.core.hDC,
                        GetStockObject(NULL_PEN));
                  ReleaseAbacus(&widget);
                  (void) ReleaseDC(hWnd, widget.core.hDC);
                  break;
            case WM_COMMAND:
                  switch (LOWORD(wParam)) {
                        case IDM_EXIT:
                              DestroyAbacus(&widget, brush);
#if 0
                              if (widget.abacus.demo)
                                    DestroyAbacusDemo(brush);
#endif
                              break;
                        case IDM_HIDE:
                              HideAbacus(&widget);
                              break;
                        case IDM_CLEAR:
                              widget.core.hDC = GetDC(hWnd);
                              (void) SelectObject(widget.core.hDC,
                                    GetStockObject(NULL_PEN));
                              ClearAbacus(&widget);
#if 0
                              if (widget.abacus.demo)
                                    clearDemo(&widget);
#endif
                              (void) ReleaseDC(hWnd,
                                    widget.core.hDC);
                              break;
                        case IDM_INCREMENT:
                              widget.core.hDC = GetDC(hWnd);
                              (void) SelectObject(widget.core.hDC,
                                    GetStockObject(NULL_PEN));
                              IncrementAbacus(&widget);
                              (void) ReleaseDC(hWnd,
                                    widget.core.hDC);
                              break;
                        case IDM_DECREMENT:
                              widget.core.hDC = GetDC(hWnd);
                              (void) SelectObject(widget.core.hDC,
                                    GetStockObject(NULL_PEN));
                              DecrementAbacus(&widget);
                              (void) ReleaseDC(hWnd,
                                    widget.core.hDC);
                              break;
                        case IDM_SPEED:
                              SpeedAbacus(&widget);
                              break;
                        case IDM_SLOW:
                              SlowAbacus(&widget);
                              break;
                        case IDM_SOUND:
                              SoundAbacus(&widget);
                              break;
                        case IDM_FORMAT:
                              widget.core.hDC = GetDC(hWnd);
                              (void) SelectObject(widget.core.hDC,
                                    GetStockObject(NULL_PEN));
                              FormatAbacus(&widget);
                              if (widget.abacus.demo) {
                                    ClearAbacusDemo(&widget);
                                    ClearAbacus(&widget);
                              }
                              break;
                        case IDM_ROMANNUMERAL:
                              widget.core.hDC = GetDC(hWnd);
                              (void) SelectObject(widget.core.hDC,
                                    GetStockObject(NULL_PEN));
                              RomanNumeralsAbacus(&widget);
                              (void) ReleaseDC(hWnd,
                                    widget.core.hDC);
                              break;
                        case IDM_SIGN:
                              widget.core.hDC = GetDC(hWnd);
                              (void) SelectObject(widget.core.hDC,
                                    GetStockObject(NULL_PEN));
                              SignAbacus(&widget);
                              (void) ReleaseDC(hWnd,
                                    widget.core.hDC);
                              break;
                        case IDM_QUARTER:
                              widget.core.hDC = GetDC(hWnd);
                              (void) SelectObject(widget.core.hDC,
                                    GetStockObject(NULL_PEN));
                              QuarterAbacus(&widget);
                              (void) ReleaseDC(hWnd,
                                    widget.core.hDC);
                              break;
                        case IDM_QUARTERPERCENT:
                              widget.core.hDC = GetDC(hWnd);
                              (void) SelectObject(widget.core.hDC,
                                    GetStockObject(NULL_PEN));
                              QuarterPercentAbacus(&widget);
                              (void) ReleaseDC(hWnd,
                                    widget.core.hDC);
                              break;
                        case IDM_TWELFTH:
                              widget.core.hDC = GetDC(hWnd);
                              (void) SelectObject(widget.core.hDC,
                                    GetStockObject(NULL_PEN));
                              TwelfthAbacus(&widget);
                              (void) ReleaseDC(hWnd,
                                    widget.core.hDC);
                              break;
                        case IDM_ANOMALY:
                              widget.core.hDC = GetDC(hWnd);
                              (void) SelectObject(widget.core.hDC,
                                    GetStockObject(NULL_PEN));
                              AnomalyAbacus(&widget);
                              (void) ReleaseDC(hWnd,
                                    widget.core.hDC);
                              break;
                        case IDM_WATCH:
                              widget.core.hDC = GetDC(hWnd);
                              (void) SelectObject(widget.core.hDC,
                                    GetStockObject(NULL_PEN));
                              WatchAbacus(&widget);
                              (void) ReleaseDC(hWnd,
                                    widget.core.hDC);
                              break;
#if 0
                        case IDM_VERTICAL:
                              widget.core.hDC = GetDC(hWnd);
                              (void) SelectObject(widget.core.hDC,
                                    GetStockObject(NULL_PEN));
                              VerticalAbacus(&widget);
                              (void) ReleaseDC(hWnd,
                                    widget.core.hDC);
                              break;
#endif
                        case IDM_DEMO:
                              DemoAbacusDemo(&widget);
                              ResizeAbacus(&widget);
                              (void) InvalidateRect(hWnd, NULL,
                                    TRUE);
                              break;
                        case IDM_NEXT:
                              widget.core.hDC = GetDC(hWnd);
                              (void) SelectObject(widget.core.hDC,
                                    GetStockObject(NULL_PEN));
                              /* NextAbacus(&widget); */
                              if (widget.abacus.demo)
                                    NextAbacusDemo(&widget);
                              (void) ReleaseDC(hWnd,
                                    widget.core.hDC);
                              break;
                        case IDM_REPEAT:
                              widget.core.hDC = GetDC(hWnd);
                              (void) SelectObject(widget.core.hDC,
                                    GetStockObject(NULL_PEN));
                              /* RepeatAbacus(&widget); */
                              if (widget.abacus.demo)
                                    RepeatAbacusDemo(&widget);
                              (void) ReleaseDC(hWnd,
                                    widget.core.hDC);
                              break;
                        case IDM_MORE:
                              widget.core.hDC = GetDC(hWnd);
                              (void) SelectObject(widget.core.hDC,
                                    GetStockObject(NULL_PEN));
                              /* MoreAbacus(&widget); */
                              if (widget.abacus.demo)
                                    MoreAbacusDemo(&widget);
                              (void) ReleaseDC(hWnd,
                                    widget.core.hDC);
                              break;
                        case IDM_ABOUT:
                              (void) DialogBox(widget.core.hInstance,
                                    "About", hWnd,
                                    (DLGPROC) About);
                              break;
                        case IDM_DESCRIPTION:
                              (void) MessageBox(hWnd,
                                    descriptionHelp,
                                    "Description", MB_OK);
                              break;
                        case IDM_FEATURES:
                              (void) MessageBox(hWnd, featuresHelp,
                                    "Features", MB_OK);
                              break;
                        case IDM_REFERENCES:
                              (void) MessageBox(hWnd, referencesHelp,
                                    "References", MB_OK);
                              break;
                  }
                  break;
            default:
                  return (DefWindowProc(hWnd, message, wParam, lParam));
      }
      return FALSE;
}

int WINAPI
WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
            int numCmdShow)
{
      HWND hWnd;
      MSG msg;
      WNDCLASS wc;
      HACCEL hAccel;

      if (!hPrevInstance) {
            wc.style = CS_HREDRAW | CS_VREDRAW;
            wc.lpfnWndProc = WindowProc;
            wc.cbClsExtra = 0;
            wc.cbWndExtra = 0;
            wc.hInstance = hInstance;
            wc.hIcon = LoadIcon(hInstance, TITLE);
            wc.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW);
            wc.hbrBackground = (HBRUSH) GetStockObject(GRAY_BRUSH);
            wc.lpszMenuName = TITLE;
            wc.lpszClassName = TITLE;
            if (!RegisterClass(&wc))
                  return FALSE;
      }
      widget.core.hInstance = hInstance;
      hWnd = CreateWindow(TITLE,
            TITLE,
            WS_OVERLAPPEDWINDOW,
            (signed) CW_USEDEFAULT,
            (signed) CW_USEDEFAULT,
            (signed) CW_USEDEFAULT,
            (signed) CW_USEDEFAULT,
            HWND_DESKTOP,
            (HMENU) NULL,
            hInstance,
            (void *) NULL);
      if (!hWnd)
            return FALSE;
      hAccel = (HACCEL) LoadAccelerators(hInstance, TITLE);
      (void) ShowWindow(hWnd, numCmdShow);
      (void) UpdateWindow(hWnd);
      while (GetMessage(&msg, (HWND) NULL, 0, 0)) {
            if (!TranslateAccelerator(hWnd, hAccel, &msg)) {
                  (void) TranslateMessage(&msg);
                  (void) DispatchMessage(&msg);
            }
      }
      return (msg.wParam);
}

#else
#include "xwin.h"
#include <X11/Shell.h>
#include <X11/cursorfont.h>
#ifdef HAVE_MOTIF
#include <Xm/PanedW.h>
#include <Xm/RowColumn.h>
#include <Xm/Text.h>
#include <Xm/LabelG.h>
#include <Xm/MessageB.h>
#include <Xm/PushBG.h>
#include <Xm/CascadeB.h>
#include <Xm/Scale.h>
#include <Xm/ToggleB.h>
#include <Xm/ToggleBG.h>
#include <Xm/Form.h>
#ifdef MOUSEBITMAPS
#include "icons/mouse-l.xbm"
#include "icons/mouse-r.xbm"
#endif
#endif
#include "Abacus.h"
#ifdef HAVE_XPM
#include <X11/xpm.h>
#include "icons/abacus.xpm"
#endif
#include "icons/abacus.xbm"

#define FILENAMELEN 1024

#ifdef HAVE_MOTIF
#define MAXRAILS 24           /* Totally arbitrary */
#define DEMO 0
#define NORMAL 1
#define BASE 2
#define COMPLEXITIES 3
#else
/* Needs Motif */
#ifdef LEE_ABACUS
#undef LEE_ABACUS
#endif
#define MAXDIGITS 256         /* This limits the number of rails */
#define TITLELEN (MAXDIGITS+FILENAMELEN+3)
#endif

#ifdef HAVE_MOTIF
static Widget mainPanel, baseRowCol;
static Widget sizeSlider, abacusBaseSlider, displayBaseSlider;
static Widget complexityMenu, complexitySubMenu;
static Widget formatMenu, formatSubMenu;
static Widget complexityOptions[COMPLEXITIES], formatOptions[MAXMODES];
#ifdef LEE_ABACUS
static Widget leftAuxAbacus, rightAuxAbacus;
static Widget leftAuxTracker, rightAuxTracker;
#endif
#ifdef TOGGLES
static Widget romanNumeralSwitch, signSwitch, pieceSwitch;
static Widget piecePercentSwitch, anomalySwitch;
#endif
static Widget tracker;
static Widget descriptionDialog, featuresDialog;
static Widget optionsDialog, options1Dialog, options2Dialog;
static Widget referencesDialog, aboutDialog;
static Widget clearDialog;
static const char *complexityString[] =
{
      "Demo", "Normal", "Base"
};
static char *mathBuffer = NULL;
static Boolean baseSet = False;
static Arg arg[4];
#else
static Widget shell = NULL;
static char titleDsp[TITLELEN];
#endif
static Pixmap abacusIcon = None;
static char titleDspDemo[FILENAMELEN + 6];
static Widget topLevel, abacus, abacusDemo = NULL;
static char *progDsp;

static void
Usage(char * programName)
{
      (void) fprintf(stderr, "usage: %s\n", programName);
      (void) fprintf(stderr, optionsHelp);
      exit(1);
}

static XrmOptionDescRec options[] =
{
      {(char *) "-mono", (char *) "*abacus.mono", XrmoptionNoArg, (char *) "TRUE"},
      {(char *) "-nomono", (char *) "*abacus.mono", XrmoptionNoArg, (char *) "FALSE"},
      {(char *) "-rv", (char *) "*abacus.reverse", XrmoptionNoArg, (char *) "TRUE"},
      {(char *) "-reverse", (char *) "*abacus.reverse", XrmoptionNoArg, (char *) "TRUE"},
      {(char *) "-norv", (char *) "*abacus.reverse", XrmoptionNoArg, (char *) "FALSE"},
      {(char *) "-noreverse", (char *) "*abacus.reverse", XrmoptionNoArg, (char *) "FALSE"},
      {(char *) "-fg", (char *) "*abacus.Foreground", XrmoptionSepArg, NULL},
      {(char *) "-foreground", (char *) "*abacus.Foreground", XrmoptionSepArg, NULL},
      {(char *) "-bg", (char *) "*Background", XrmoptionSepArg, NULL},
      {(char *) "-background", (char *) "*Background", XrmoptionSepArg, NULL},
      {(char *) "-frame", (char *) "*abacus.frameColor", XrmoptionSepArg, NULL},
      {(char *) "-rail", (char *) "*abacus.railColor", XrmoptionSepArg, NULL},
      {(char *) "-bead", (char *) "*abacus.beadColor", XrmoptionSepArg, NULL},
      {(char *) "-bd", (char *) "*abacus.beadBorder", XrmoptionSepArg, NULL},
      {(char *) "-border", (char *) "*abacus.beadBorder", XrmoptionSepArg, NULL},
      {(char *) "-delay", (char *) "*abacus.delay", XrmoptionSepArg, NULL},
      {(char *) "-sound", (char *) "*abacus.sound", XrmoptionNoArg, (char *) "TRUE"},
      {(char *) "-nosound", (char *) "*abacus.sound", XrmoptionNoArg, (char *) "FALSE"},
      {(char *) "-bumpSound", (char *) "*abacus.bumpSound", XrmoptionSepArg, NULL},
      {(char *) "-moveSound", (char *) "*abacus.moveSound", XrmoptionSepArg, NULL},
      {(char *) "-demo", (char *) "*abacus.demo", XrmoptionNoArg, (char *) "TRUE"},
      {(char *) "-nodemo", (char *) "*abacus.demo", XrmoptionNoArg, (char *) "FALSE"},
      {(char *) "-script", (char *) "*abacus.script", XrmoptionNoArg, (char *) "TRUE"},
      {(char *) "-noscript", (char *) "*abacus.script", XrmoptionNoArg, (char *) "FALSE"},
      {(char *) "-demopath", (char *) "*abacus.demoPath", XrmoptionSepArg, NULL},
      {(char *) "-demofont", (char *) "*abacus.demoFont", XrmoptionSepArg, NULL},
      {(char *) "-demofn", (char *) "*abacus.demoFont", XrmoptionSepArg, NULL},
      {(char *) "-demoforeground", (char *) "*abacus.demoForeground", XrmoptionSepArg, NULL},
      {(char *) "-demofg", (char *) "*abacus.demoForeground", XrmoptionSepArg, NULL},
      {(char *) "-demobackground", (char *) "*abacus.demoBackground", XrmoptionSepArg, NULL},
      {(char *) "-demobg", (char *) "*abacus.demoBackground", XrmoptionSepArg, NULL},
      {(char *) "-vertical", (char *) "*abacus.vertical", XrmoptionNoArg, (char *) "TRUE"},
      {(char *) "-novertical", (char *) "*abacus.vertical", XrmoptionNoArg, (char *) "FALSE"},
      {(char *) "-slot", (char *) "*abacus.slot", XrmoptionNoArg, (char *) "TRUE"},
      {(char *) "-noslot", (char *) "*abacus.slot", XrmoptionNoArg, (char *) "FALSE"},
      {(char *) "-diamond", (char *) "*abacus.diamond", XrmoptionNoArg, (char *) "TRUE"},
      {(char *) "-nodiamond", (char *) "*abacus.diamond", XrmoptionNoArg, (char *) "FALSE"},
      {(char *) "-torient", (char *) "*abacus.topOrient", XrmoptionNoArg, (char *) "TRUE"},
      {(char *) "-notorient", (char *) "*abacus.topOrient", XrmoptionNoArg, (char *) "FALSE"},
      {(char *) "-borient", (char *) "*abacus.bottomOrient", XrmoptionNoArg, (char *) "TRUE"},
      {(char *) "-noborient", (char *) "*abacus.bottomOrient", XrmoptionNoArg, (char *) "FALSE"},
      {(char *) "-tnumber", (char *) "*abacus.topNumber", XrmoptionSepArg, NULL},
      {(char *) "-bnumber", (char *) "*abacus.bottomNumber", XrmoptionSepArg, NULL},
      {(char *) "-tfactor", (char *) "*abacus.topFactor", XrmoptionSepArg, NULL},
      {(char *) "-bfactor", (char *) "*abacus.bottomFactor", XrmoptionSepArg, NULL},
      {(char *) "-tspaces", (char *) "*abacus.topSpaces", XrmoptionSepArg, NULL},
      {(char *) "-bspaces", (char *) "*abacus.bottomSpaces", XrmoptionSepArg, NULL},
      {(char *) "-tpiece", (char *) "*abacus.topPiece", XrmoptionSepArg, NULL},
      {(char *) "-bpiece", (char *) "*abacus.bottomPiece", XrmoptionSepArg, NULL},
      {(char *) "-tpiecePercent", (char *) "*abacus.topPiecePercent", XrmoptionSepArg, NULL},
      {(char *) "-bpiecePercent", (char *) "*abacus.bottomPiecePercent", XrmoptionSepArg, NULL},
      {(char *) "-shiftPercent", (char *) "*abacus.shiftPercent", XrmoptionSepArg, NULL},
      {(char *) "-sign", (char *) "*abacus.sign", XrmoptionNoArg, (char *) "TRUE"},
      {(char *) "-nosign", (char *) "*abacus.sign", XrmoptionNoArg, (char *) "FALSE"},
      {(char *) "-decimalPosition", (char *) "*abacus.decimalPosition", XrmoptionSepArg, NULL},
      {(char *) "-groupSize", (char *) "*abacus.groupSize", XrmoptionSepArg, NULL},
      {(char *) "-rails", (char *) "*abacus.rails", XrmoptionSepArg, NULL},
      {(char *) "-base", (char *) "*abacus.base", XrmoptionSepArg, NULL},
      {(char *) "-anomaly", (char *) "*abacus.anomaly", XrmoptionSepArg, NULL},
      {(char *) "-shiftAnomaly", (char *) "*abacus.shiftAnomaly", XrmoptionSepArg, NULL},
      {(char *) "-anomalySq", (char *) "*abacus.anomalySq", XrmoptionSepArg, NULL},
      {(char *) "-shiftAnomalySq", (char *) "*abacus.shiftAnomalySq", XrmoptionSepArg, NULL},
      {(char *) "-displayBase", (char *) "*abacus.displayBase", XrmoptionSepArg, NULL},
      {(char *) "-romanNumerals", (char *) "*abacus.romanNumerals", XrmoptionNoArg, (char *) "TRUE"},
      {(char *) "-noromanNumerals", (char *) "*abacus.romanNumerals", XrmoptionNoArg, (char *) "FALSE"},
      {(char *) "-chinese", (char *) "*abacus.format", XrmoptionNoArg, (char *) "chinese"},
      {(char *) "-japanese", (char *) "*abacus.format", XrmoptionNoArg, (char *) "japanese"},
      {(char *) "-korean", (char *) "*abacus.format", XrmoptionNoArg, (char *) "korean"},
      {(char *) "-roman", (char *) "*abacus.format", XrmoptionNoArg, (char *) "roman"},
      {(char *) "-russian", (char *) "*abacus.format", XrmoptionNoArg, (char *) "russian"},
      {(char *) "-other", (char *) "*abacus.format", XrmoptionNoArg, (char *) "other"},
      {(char *) "-version", (char *) "*abacus.versionOnly", XrmoptionNoArg, (char *) "TRUE"}
};

static void
PrintState(Widget w, char *msg
#ifndef HAVE_MOTIF
, int mode
#endif
)
{
#ifdef HAVE_MOTIF
      XtVaSetValues(w, XmNvalue, msg, NULL);
#else
      (void) sprintf(titleDsp, "%s %s =%s",
            (mode < 0 || mode > MAXMODES) ? "" : formatString[mode],
            progDsp, msg);
      XtVaSetValues(w, XtNtitle, titleDsp, NULL);
#endif
}

/* There's probably a better way to assure that they are the same but I do
 * not know it off hand. */
static void
InitializeDemo(void)
{
      int mode;
      Boolean mono, reverse;
      Pixel demoForeground, demoBackground;
      String demoPath, demoFont;

      XtVaGetValues(abacus,
            XtNmono, &mono,
            XtNreverse, &reverse,
            XtNmode, &mode,
            XtNdemoForeground, &demoForeground,
            XtNdemoBackground, &demoBackground,
            XtNdemoPath, &demoPath,
            XtNdemoFont, &demoFont, NULL);
      XtVaSetValues(abacusDemo,
            XtNmono, mono,
            XtNreverse, reverse,
            XtNmode, mode,
            XtNdemoForeground, demoForeground,
            XtNdemoBackground, demoBackground,
            XtNdemoPath, demoPath,
            XtNdemoFont, demoFont,
            XtNframed, True, NULL);
}

#ifdef LEE_ABACUS
#define AUXWIN(n) (n == LEFTAUX) ? leftAuxAbacus : ((n == RIGHTAUX ) ? rightAuxAbacus : abacus)
#else
#define AUXWIN(n) abacus
#endif

static void
CallbackAbacusDemo(Widget w, caddr_t clientData, abacusCallbackStruct * callData)
{
#ifndef HAVE_MOTIF
      int mode;

      XtVaGetValues(w,
            XtNmode, &mode, NULL);
#endif
      switch (callData->reason) {
            case ABACUS_BASE_DEFAULT:
#ifdef HAVE_MOTIF
                  XmScaleSetValue(abacusBaseSlider, DEFAULTBASE);
#endif
                  break;
            case ABACUS_HIDE:
                  (void) XIconifyWindow(XtDisplay(topLevel),
                        XtWindow(topLevel),
                        XScreenNumberOfScreen(XtScreen(topLevel)));
#ifndef HAVE_MOTIF
                  (void) XIconifyWindow(XtDisplay(shell),
                        XtWindow(shell),
                        XScreenNumberOfScreen(XtScreen(shell)));
#endif
                  break;
            case ABACUS_MOVE:
#ifndef LEE_ABACUS
                  if (callData->aux == PRIMARY)
#endif
                  {
                        XtVaSetValues(AUXWIN(callData->aux),
                              XtNdeck, callData->deck,
                              XtNrail, callData->rail,
                              XtNnumber, callData->number, NULL);
                  }
                  break;
            case ABACUS_CLEAR:
                  XtVaSetValues(abacus, XtNdeck, ABACUS_CLEAR, NULL);
#ifdef LEE_ABACUS
                  /* Abacus demo clear is more complete */
                  XtVaSetValues(leftAuxAbacus,
                        XtNdeck, ABACUS_CLEAR, NULL);
                  XtVaSetValues(rightAuxAbacus,
                        XtNdeck, ABACUS_CLEAR, NULL);
#endif
                  break;
            case ABACUS_DEMO:
                  XtDestroyWidget(abacusDemo);
#ifndef HAVE_MOTIF
                  XtDestroyWidget(shell);
#endif
                  XtVaSetValues(abacus,
                        XtNdemo, False, NULL);
#ifdef LEE_ABACUS
                  XtVaSetValues(leftAuxAbacus,
                        XtNdemo, False, NULL);
                  XtVaSetValues(rightAuxAbacus,
                        XtNdemo, False, NULL);
#endif
                  break;
      }
      if (callData->reason == ABACUS_SCRIPT || callData->reason == ABACUS_IGNORE) {
#ifdef HAVE_MOTIF
#ifdef LEE_ABACUS
            if (w == leftAuxAbacus)
                  PrintState(leftAuxTracker, callData->buffer);
            else if (w == rightAuxAbacus)
                  PrintState(rightAuxTracker, callData->buffer);
            else
#endif
                  PrintState(tracker, callData->buffer);
#else
            PrintState(XtParent(w), callData->buffer, mode);
#endif
      }
}

static void
forceNormalParams(Widget w)
{
      int base = DEFAULTBASE;
      int displayBase = DEFAULTBASE;

#ifdef HAVE_MOTIF
      if (baseSet) {
            XmScaleSetValue(displayBaseSlider, displayBase);
            XmScaleSetValue(abacusBaseSlider, base);
      }
#endif
      XtVaSetValues(abacus,
            XtNbase, base,
            XtNdisplayBase, displayBase, NULL);
}

static void
forceDemoParams(Widget w)
{
      int rails, min, mode;
      int bottomPiece, bottomPiecePercent, shiftPercent;
      Boolean demo, sign;

      forceNormalParams(w);
      XtVaGetValues(abacus,
            XtNmode, &mode,
            XtNrails, &rails,
            XtNsign, &sign,
            XtNbottomPiece, &bottomPiece,
            XtNbottomPiecePercent, &bottomPiecePercent,
            XtNshiftPercent, &shiftPercent,
            XtNdemo, &demo, NULL);
      if (mode == OTHER) {
            mode = CHINESE;
            XtVaSetValues(abacus,
                  XtNmode, mode, NULL);
#ifdef HAVE_MOTIF
            XtVaSetValues(formatMenu,
                  XmNmenuHistory, formatOptions[mode], NULL);
#endif
      }
      min = ((sign) ? 1: 0) + ((bottomPiece) ? 1 : 0) +
            ((bottomPiecePercent) ? 1 + shiftPercent : 0) +
            ((demo) ? MINDEMORAILS : MINRAILS);
      if (rails < min) {
#ifdef HAVE_MOTIF
            XmScaleSetValue(sizeSlider, min);
#endif
            XtVaSetValues(abacus, XtNrails, min, NULL);
      }
}

static void
Initialize(Widget w)
{
      Boolean versionOnly;

      XtVaGetValues(w, XtNversionOnly, &versionOnly, NULL);
      if (versionOnly) {
            (void) printf(aboutHelp);
            exit(0);
      }
}

static void
createDemo(void)
{
      (void) sprintf(titleDspDemo, "%s-demo", progDsp);
#ifdef HAVE_MOTIF
      abacusDemo = XtCreateManagedWidget(titleDspDemo,
            abacusDemoWidgetClass, mainPanel, NULL, 0);
      XtAddCallback(abacusDemo, XtNselectCallback,
            (XtCallbackProc) CallbackAbacusDemo, (XtPointer) NULL);
#else
      shell = XtCreateApplicationShell(titleDsp,
            topLevelShellWidgetClass, NULL, 0);
      XtVaSetValues(shell,
            XtNiconPixmap, abacusIcon,
            XtNinput, True,
            XtNtitle, titleDspDemo, NULL);
      abacusDemo = XtCreateManagedWidget("abacus",
            abacusDemoWidgetClass, shell, NULL, 0);
      XtAddCallback(abacusDemo, XtNselectCallback,
            (XtCallbackProc) CallbackAbacusDemo,
            (XtPointer) NULL);
#endif
      InitializeDemo();
#ifndef HAVE_MOTIF
      XtRealizeWidget(shell);
#endif
      (void) XGrabButton(XtDisplay(abacusDemo), (unsigned int) AnyButton,
            AnyModifier, XtWindow(abacusDemo), TRUE,
            (unsigned int) (ButtonPressMask |
            ButtonMotionMask | ButtonReleaseMask),
            GrabModeAsync, GrabModeAsync, XtWindow(abacusDemo),
            XCreateFontCursor(XtDisplay(abacusDemo), XC_hand2));
}

static void
CallbackAbacus(Widget w, caddr_t clientData, abacusCallbackStruct * callData)
{
      int rails, mode;
      Boolean romanNumerals, sign, demo;
      int topPiece, bottomPiece, topPiecePercent, bottomPiecePercent;
      int anomaly, anomalySq;

      XtVaGetValues(w,
            XtNdemo, &demo,
            XtNmode, &mode, NULL);
      switch (callData->reason) {
            case ABACUS_HIDE:
                  (void) XIconifyWindow(XtDisplay(topLevel),
                        XtWindow(topLevel),
                        XScreenNumberOfScreen(XtScreen(topLevel)));
#ifndef HAVE_MOTIF
                  if (demo)
                        (void) XIconifyWindow(XtDisplay(shell),
                              XtWindow(shell),
                              XScreenNumberOfScreen(XtScreen(shell)));
#endif
                  break;
            case ABACUS_CLEAR_QUERY:
#ifdef HAVE_MOTIF
                  XtManageChild(clearDialog);
#else
                  XtVaSetValues(w, XtNmenu, 1, NULL); /* menu choice */
#endif
                  break;
            case ABACUS_SCRIPT:
                  (void) printf("%d %d %d %d 4\n",
                        callData->aux, callData->deck,
                        callData->rail, callData->number);
                  (void) printf(
                        "Lesson\n\n\nPress Space-bar to Continue\n");
                  break;
            case ABACUS_MOVE:
#ifndef LEE_ABACUS
                  if (callData->aux == PRIMARY)
#endif
                  {
                        XtVaSetValues(AUXWIN(callData->aux),
                              XtNdeck, callData->deck,
                              XtNrail, callData->rail,
                              XtNnumber, callData->number, NULL);
                  }
                  break;
            case ABACUS_CLEAR:
                  XtVaSetValues(abacusDemo, XtNdeck, ABACUS_CLEAR, NULL);
                  break;
            case ABACUS_DEMO:
                  demo = !demo;
                  if (demo) {
                        forceDemoParams(abacus);
                        createDemo();
                  } else {
                        XtDestroyWidget(abacusDemo);
#ifndef HAVE_MOTIF
                        XtDestroyWidget(shell);
#endif
                  }
                  XtVaSetValues(abacus, XtNdemo, demo, NULL);
#ifdef LEE_ABACUS
                  XtVaSetValues(leftAuxAbacus, XtNdemo, demo, NULL);
                  XtVaSetValues(rightAuxAbacus, XtNdemo, demo, NULL);
#endif
                  break;
            case ABACUS_NEXT:
                  XtVaSetValues(abacusDemo, XtNdeck, ABACUS_NEXT, NULL);
                  break;
            case ABACUS_REPEAT:
                  XtVaSetValues(abacusDemo,
                        XtNdeck, ABACUS_REPEAT, NULL);
                  break;
            case ABACUS_MORE:
                  XtVaSetValues(abacusDemo, XtNdeck, ABACUS_MORE, NULL);
                  break;
            case ABACUS_INC:
                  if (w == abacus) {
                        XtVaGetValues(w,
                              XtNrails, &rails, NULL);
#ifdef HAVE_MOTIF
                        if (rails > MAXRAILS)
                              XtVaSetValues(sizeSlider,
                                    XmNmaximum, rails, NULL);
                        XmScaleSetValue(sizeSlider, rails);
#endif
                  }
                  break;
            case ABACUS_DEC:
                  if (w == abacus) {
                        XtVaGetValues(w,
                              XtNrails, &rails, NULL);
#ifdef HAVE_MOTIF
                        XmScaleSetValue(sizeSlider, rails);
                        if (rails >= MAXRAILS)
                              XtVaSetValues(sizeSlider,
                                    XmNmaximum, rails, NULL);
#endif
                  }
                  break;
            case ABACUS_FORMAT:
                  if (w == abacus) {
#ifdef HAVE_MOTIF
                        XtVaSetValues(formatMenu,
                              XmNmenuHistory, formatOptions[mode],
                              NULL);
#endif
                        if (demo) {
                              XtVaSetValues(abacusDemo,
                                    XtNdeck, ABACUS_CLEAR,
                                    XtNmode, mode, NULL);
                        }
                  }
                  break;
            case ABACUS_ROMANNUMERAL:
                  XtVaGetValues(w,
                        XtNromanNumerals, &romanNumerals,
                        NULL);
#ifdef HAVE_MOTIF
#ifdef TOGGLES
                  XmToggleButtonSetState(romanNumeralSwitch,
                        romanNumerals, False);
#endif
#endif
                  break;
            case ABACUS_SIGN:
                  XtVaGetValues(w,
                        XtNsign, &sign, NULL);
#ifdef HAVE_MOTIF
#ifdef TOGGLES
                  if (w == abacus) {
                        XmToggleButtonSetState(signSwitch, sign, False);
                  }
#endif
#endif
                  break;
            case ABACUS_QUARTER:
                  XtVaGetValues(w,
                        XtNbottomPiece, &bottomPiece,
                        XtNtopPiece, &topPiece, NULL);
#ifdef HAVE_MOTIF
#ifdef TOGGLES
                  if (w == abacus) {
                        XmToggleButtonSetState(pieceSwitch,
                              (bottomPiece == QUARTER), False);
                  }
#endif
#endif
                  break;
            case ABACUS_QUARTERPERCENT:
                  XtVaGetValues(w,
                        XtNbottomPiecePercent, &bottomPiecePercent,
                        XtNtopPiecePercent, &topPiecePercent, NULL);
#ifdef HAVE_MOTIF
#ifdef TOGGLES
                  if (w == abacus) {
                        XmToggleButtonSetState(piecePercentSwitch,
                              (bottomPiecePercent == QUARTERPERCENT), False);
                  }
#endif
#endif
                  break;
            case ABACUS_TWELFTH:
                  XtVaGetValues(w,
                        XtNtopPiece, &topPiece,
                        XtNbottomPiece, &bottomPiece, NULL);
#ifdef HAVE_MOTIF
#ifdef TOGGLES
                  if (w == abacus) {
                        XmToggleButtonSetState(pieceSwitch,
                              (topPiece * bottomPiece == TWELFTH), False);
                  }
#endif
#endif
                  break;
            case ABACUS_ANOMALY:
                  XtVaGetValues(w,
                        XtNanomaly, &anomaly,
                        XtNanomalySq, &anomalySq, NULL);
#ifdef HAVE_MOTIF
#ifdef TOGGLES
                  if (w == abacus) {
                        XmToggleButtonSetState(anomalySwitch,
                              (anomaly == 2 && anomalySq == 0), False);
                  }
#endif
#endif
                  break;
            case ABACUS_WATCH:
                  XtVaGetValues(w,
                        XtNanomaly, &anomaly,
                        XtNanomalySq, &anomalySq, NULL);
#ifdef HAVE_MOTIF
#ifdef TOGGLES
                  if (w == abacus) {
                        XmToggleButtonSetState(anomalySwitch,
                              (anomaly == 4 && anomalySq == 4), False);
                  }
#endif
#endif
                  break;
#if 0
            case ABACUS_VERTICAL:
                  XtVaGetValues(w,
                        XtNvertical, &vertical, NULL);
#ifdef HAVE_MOTIF
#ifdef TOGGLES
                  if (w == abacus) {
                        XmToggleButtonSetState(verticalSwitch,
                              vertical, False);
                  }
#endif
#endif
                  break;
#endif
      }
      if (callData->reason == ABACUS_SCRIPT || callData->reason == ABACUS_IGNORE) {
#ifdef HAVE_MOTIF
#ifdef LEE_ABACUS
            if (w == leftAuxAbacus)
                  PrintState(leftAuxTracker, callData->buffer);
            else if (w == rightAuxAbacus)
                  PrintState(rightAuxTracker, callData->buffer);
            else
#endif
                  PrintState(tracker, callData->buffer);
#else
            PrintState(XtParent(w), callData->buffer, mode);
#endif
      }
}

#ifdef HAVE_MOTIF
static void
CallbackAbacusMath(Widget w, caddr_t clientData, abacusCallbackStruct * callData)
{
      Boolean demo;

      XtVaGetValues(abacus,
            XtNdemo, &demo, NULL);
      if (!demo) {
            unsigned int i, j = 0;

            if (mathBuffer)
                  XtFree(mathBuffer);
            mathBuffer = XmTextGetString(w);
            /* strip out blanks */
            for (i = 0; i < strlen(mathBuffer); i++) {
                  if (mathBuffer[i] == '[' || mathBuffer[i] == ']') {
                        mathBuffer[j] = '\0';
                        break;
                  } else if (mathBuffer[i] != ' ' &&
                              mathBuffer[i] != '\t') {
                        mathBuffer[j] = mathBuffer[i];
                        j++;
                  }
            }
            /* check for math ops */
            XtVaSetValues(abacus,
                  XtNdeck, ABACUS_CALC,
                  XtNmathBuffer, mathBuffer, NULL);
      }
}

static void
CallbackAbacusClear(Widget w, XtPointer clientData, XmAnyCallbackStruct * cbs)
{
      if (cbs->reason == XmCR_OK) {
            XtVaSetValues(abacus, XtNmenu, 1, NULL); /* menu choice */
      }
}

static void
RailSlider(Widget w, XtPointer clientData, XmScaleCallbackStruct * cbs)
{
      int rails = cbs->value, old, min;
      int bottomPiece, bottomPiecePercent, shiftPercent;
      Boolean sign, demo;

      XtVaGetValues(abacus,
            XtNrails, &old,
            XtNsign, &sign,
            XtNbottomPiece, &bottomPiece,
            XtNbottomPiecePercent, &bottomPiecePercent,
            XtNshiftPercent, &shiftPercent,
            XtNdemo, &demo, NULL);
      min = ((sign) ? 1 : 0) + ((bottomPiece) ? 1 : 0) +
            ((bottomPiecePercent) ? 1 + shiftPercent : 0) +
            ((demo) ? MINDEMORAILS : MINRAILS);
      if (rails < min) {
            XmScaleSetValue(sizeSlider, old);
      } else if (old != rails)
            XtVaSetValues(abacus,
                  XtNrails, rails, NULL);
}

static void
AbacusBaseSlider(Widget w, XtPointer clientData, XmScaleCallbackStruct * cbs)
{
      int base = cbs->value, old, bottomSpaces, mode;
      int bottomPiece, bottomPiecePercent;
      Boolean demo;

      XtVaGetValues(abacus,
            XtNbase, &old,
            XtNbottomPiece, &bottomPiece,
            XtNbottomPiecePercent, &bottomPiecePercent,
            XtNbottomSpaces, &bottomSpaces,
            XtNmode, &mode,
            XtNdemo, &demo, NULL);
      if (demo) {
            XmScaleSetValue(abacusBaseSlider, DEFAULTBASE);
      /* Odd bases produce round-off errors but OK */
      /* When base divisible by 4, kind of silly but OK */
      /* Well some of these have enough room in Russian but not others */
      } else if ((base == 2 || base == 4) && bottomSpaces < 3) {
            XtVaSetValues(abacus,
                  XtNbottomSpaces, 3,
                  XtNbase, base, NULL);
      } else if ((base == 3 || base == 6 || base == 9) && bottomSpaces < 2) {
            XtVaSetValues(abacus,
                  XtNbottomSpaces, 2,
                  XtNbase, base, NULL);
      } else {
            XtVaSetValues(abacus,
                  XtNbase, base, NULL);
      }
}

static void
DisplayBaseSlider(Widget w, XtPointer clientData, XmScaleCallbackStruct * cbs)
{
      int displayBase = cbs->value, old;
      Boolean demo;

      XtVaGetValues(abacus,
            XtNdisplayBase, &old,
            XtNdemo, &demo, NULL);
      if (demo) {
            XmScaleSetValue(displayBaseSlider, DEFAULTBASE);
      } else {
            XtVaSetValues(abacus,
                  XtNdisplayBase, displayBase, NULL);
      }
}

#ifdef TOGGLES
#if 0
static void
VerticalToggle(Widget w, XtPointer clientData, XmToggleButtonCallbackStruct * cbs)
{
      Boolean vertical = cbs->set;

      XtVaSetValues(abacus,
            XtNvertical, vertical, NULL);
}
#endif

static void
RomanNumeralToggle(Widget w, XtPointer clientData,
            XmToggleButtonCallbackStruct * cbs)
{
      Boolean romanNumerals = cbs->set;

      XtVaSetValues(abacus,
            XtNromanNumerals, romanNumerals, NULL);
}

static void
SignToggle(Widget w, XtPointer clientData, XmToggleButtonCallbackStruct * cbs)
{
      Boolean sign = cbs->set;

      XtVaSetValues(abacus,
            XtNsign, sign, NULL);
}

static void
QuarterToggle(Widget w, XtPointer clientData, XmToggleButtonCallbackStruct * cbs)
{
      Boolean quarter = cbs->set;

      XtVaSetValues(abacus,
            XtNtopPiece, 0,
            XtNbottomPiece, (quarter) ? QUARTERS : 0, NULL);
}

static void
QuarterPercentToggle(Widget w, XtPointer clientData, XmToggleButtonCallbackStruct * cbs)
{
      Boolean quarterPercent = cbs->set;

      XtVaSetValues(abacus,
            XtNtopPiecePercent, 0,
            XtNbottomPiecePercent, (quarterPercent) ? QUARTERPERCENTS : 0, NULL);
}

static void
TwelfthToggle(Widget w, XtPointer clientData, XmToggleButtonCallbackStruct * cbs)
{
      Boolean twelfth = cbs->set;

      XtVaSetValues(abacus,
            XtNtopPiece, 2,
            XtNbottomPiece, (twelfth) ? TWELFTH / 2 : 0, NULL);
}

static void
AnomalyToggle(Widget w, XtPointer clientData, XmToggleButtonCallbackStruct * cbs)
{
      Boolean anomaly = cbs->set;

      XtVaSetValues(abacus,
            XtNanomaly, (watch) ? 2 : 0,
            XtNanomalySq, 0, NULL);
}

static void
WatchToggle(Widget w, XtPointer clientData, XmToggleButtonCallbackStruct * cbs)
{
      Boolean watch = cbs->set;

      XtVaSetValues(abacus,
            XtNanomaly, (watch) ? 4 : 0,
            XtNanomalySq, 4, NULL);
}
#endif

static void
createBase(int base, int displayBase)
{
      baseRowCol = XtVaCreateManagedWidget("baseRowCol",
            xmRowColumnWidgetClass, mainPanel,
            XmNnumColumns, 1,
            XmNheight, 55,
            XmNorientation, XmHORIZONTAL,
            XmNpacking, XmPACK_COLUMN, NULL);
      abacusBaseSlider = XtVaCreateManagedWidget("abacusBase",
            xmScaleWidgetClass, baseRowCol,
            XtVaTypedArg, XmNtitleString, XmRString, "Abacus Base", 12,
            XmNminimum, MINBASE,
            XmNmaximum, MAXBASE,
            XmNscaleWidth, (MAXBASE - MINBASE + 1) * 3,
            XmNvalue, base,
            XmNshowValue, True,
            XmNorientation, XmHORIZONTAL, NULL);
      XtAddCallback(abacusBaseSlider, XmNvalueChangedCallback,
            (XtCallbackProc) AbacusBaseSlider, (XtPointer) NULL);
      displayBaseSlider = XtVaCreateManagedWidget("displayBase",
            xmScaleWidgetClass, baseRowCol,
            XtVaTypedArg, XmNtitleString, XmRString, "Display Base", 13,
            XmNminimum, MINBASE,
            XmNmaximum, MAXBASE,
            XmNscaleWidth, (MAXBASE - MINBASE + 1) * 3,
            XmNvalue, displayBase,
            XmNshowValue, True,
            XmNorientation, XmHORIZONTAL, NULL);
      XtAddCallback(displayBaseSlider, XmNvalueChangedCallback,
            (XtCallbackProc) DisplayBaseSlider, (XtPointer) NULL);
}

static void
destroyBase(void)
{
      XtDestroyWidget(displayBaseSlider);
      XtDestroyWidget(abacusBaseSlider);
      XtDestroyWidget(baseRowCol);
}

static void
complexityCB(Widget w, void *value, void *clientData)
{
      Boolean wasDemo;
      int val = (int) value;

      XtVaGetValues(abacus,
            XtNdemo, &wasDemo, NULL);
      if (wasDemo && val == DEMO) {
            return;
      }
      if (val == DEMO) {
            if (baseSet) {
                  forceNormalParams(abacus);
                  baseSet = False;
                  destroyBase();
            }
            forceDemoParams(abacus);
            XtVaSetValues(abacus, XtNdemo, !wasDemo, NULL);
            createDemo();
      } else {
            if (wasDemo) {
                  XtVaSetValues(abacus, XtNdemo, !wasDemo, NULL);
                  XtDestroyWidget(abacusDemo);
            }
            if (val == BASE) {
                  if (baseSet)
                        return;
                  baseSet = True;
                  createBase(DEFAULTBASE, DEFAULTBASE);
            } else if (baseSet) {
                  forceNormalParams(abacus);
                  baseSet = False;
                  destroyBase();
            }
      }
}

static void
formatCB(Widget w, void *value, void *clientData)
{
      Boolean demo;
      int mode = (int) value, oldMode;

      XtVaGetValues(abacus,
            XtNmode, &oldMode,
            XtNdemo, &demo, NULL);
      if (mode < 0 && mode > MAXFORMATS)
            mode = OTHER;
      if (demo && mode == OTHER) {
                  XtVaSetValues(formatMenu,
                        XmNmenuHistory, formatOptions[oldMode], NULL);
                  return;
      }
      XtVaSetValues(abacus, XtNmode, mode, NULL);
      if (demo) {
            XtVaSetValues(abacusDemo,
                  XtNdeck, ABACUS_CLEAR,
                  XtNmode, mode, NULL);
      }
}

static void
fileCB(Widget w, void *value, void *clientData)
{
      int val = (int) value;

      if (val == 0)
            exit(0);
      XtVaSetValues(abacus, XtNmenu, val, NULL);
}

static void
controlsCB(Widget w, void *value, void *clientData)
{
      int val = (int) value;
      XtVaSetValues(abacus, XtNmenu, val + 1, NULL); /* Q */
}

static Widget
createQuery(Widget w, char *text, char *title, XtCallbackProc callback)
{
      Widget button, messageBox;
      char titleDsp[FILENAMELEN + 8];
      XmString titleString = NULL, messageString = NULL;
      static XmStringCharSet charSet =
            (XmStringCharSet) XmSTRING_DEFAULT_CHARSET;

      messageString = XmStringCreateLtoR(text, charSet);
      (void) sprintf(titleDsp, "%s: %s\n", progDsp, title);
      titleString = XmStringCreateSimple((char *) titleDsp);
      XtSetArg(arg[0], XmNdialogTitle, titleString);
      XtSetArg(arg[1], XmNmessageString, messageString);
      messageBox = XmCreateWarningDialog(w, (char *) "queryBox",
            arg, 2);
      button = XmMessageBoxGetChild(messageBox, XmDIALOG_HELP_BUTTON);
      XtUnmanageChild(button);
      XmStringFree(titleString);
      XmStringFree(messageString);
      XtAddCallback(messageBox, XmNokCallback,
            (XtCallbackProc) CallbackAbacusClear, (XtPointer) NULL);
      XtAddCallback(messageBox, XmNcancelCallback,
            (XtCallbackProc) CallbackAbacusClear, (XtPointer) NULL);
      return messageBox;
}

static Widget
createHelp(Widget w, char *text, char *title)
{
      Widget button, messageBox;
      char titleDsp[FILENAMELEN + 8];
      XmString titleString = NULL, messageString = NULL, buttonString = NULL;
      static XmStringCharSet charSet =
            (XmStringCharSet) XmSTRING_DEFAULT_CHARSET;

      messageString = XmStringCreateLtoR(text, charSet);
      (void) sprintf(titleDsp, "%s: %s\n", progDsp, title);
      titleString = XmStringCreateSimple((char *) titleDsp);
      buttonString = XmStringCreateSimple((char *) "OK");
      XtSetArg(arg[0], XmNdialogTitle, titleString);
      XtSetArg(arg[1], XmNokLabelString, buttonString);
      XtSetArg(arg[2], XmNmessageString, messageString);
      messageBox = XmCreateInformationDialog(w, (char *) "helpBox",
            arg, 3);
      button = XmMessageBoxGetChild(messageBox, XmDIALOG_CANCEL_BUTTON);
      XtUnmanageChild(button);
      button = XmMessageBoxGetChild(messageBox, XmDIALOG_HELP_BUTTON);
      XtUnmanageChild(button);
      XmStringFree(titleString);
      XmStringFree(buttonString);
      XmStringFree(messageString);
      return messageBox;
}

static void
helpCB(Widget w, XtPointer value, XtPointer clientData)
{
      int val = (int) value;

      switch (val) {
      case 0:
            XtManageChild(descriptionDialog);
            break;
      case 1:
            XtManageChild(featuresDialog);
            break;
      case 2:
            XtManageChild(optionsDialog);
            break;
      case 3:
            XtManageChild(options1Dialog);
            break;
      case 4:
            XtManageChild(options2Dialog);
            break;
      case 5:
            XtManageChild(referencesDialog);
            break;
      case 6:
            XtManageChild(aboutDialog);
            break;
      default:
            {
                  char *buf;

                  intCat(&buf, "helpCB: %d", val);
                  XtWarning(buf);
                  free(buf);
            }
      }
}

#endif

int
main(int argc, char **argv)
{
      Boolean demo;
#ifdef HAVE_MOTIF
      int base = DEFAULTBASE, displayBase = DEFAULTBASE;
      Widget menuBar, pullDownMenu, widget;
      Widget menuBarPanel, controlPanel;
      Widget controlRowCol, trackerRowCol;
#ifdef LEE_ABACUS
      Widget auxForm, auxTrackerRowCol;
      XColor exactDef;
#endif
#ifdef TOGGLES
      Widget toggleRowCol;
#endif
      XmString fileString, controlsString;
      XmString quitString, clearString, incrementString, decrementString;
      XmString romanNumeralString, signString, quarterString, twelfthString;
      XmString quarterPercentString, anomalyString, watchString;
      XmString speedString, slowString, soundString;
      XmString complexity, complexityStrings[COMPLEXITIES];
      XmString format, formatStrings[MAXMODES];
      int rails, mode;
      int bottomPiece, bottomPiecePercent, anomaly;
      Boolean romanNumerals, sign;
      unsigned int i;
#endif

      progDsp = argv[0];
#ifndef HAVE_MOTIF
      (void) sprintf(titleDsp, "%s =%s", progDsp, "0");
#endif
      topLevel = XtInitialize(argv[0], "Abacus",
            options, XtNumber(options), &argc, argv);
      if (argc != 1)
            Usage(argv[0]);

#if HAVE_XPM
      {
            XpmAttributes xpmAttributes;
            XpmColorSymbol transparentColor[1] = {{NULL,
                  (char *) "none", 0 }};
            Pixel bg;

            xpmAttributes.valuemask = XpmColorSymbols | XpmCloseness;
            xpmAttributes.colorsymbols = transparentColor;
            xpmAttributes.numsymbols = 1;
            xpmAttributes.closeness = 40000;
            XtVaGetValues(topLevel, XtNbackground, &bg, NULL);
            transparentColor[0].pixel = bg;
            (void) XpmCreatePixmapFromData(XtDisplay(topLevel),
                  RootWindowOfScreen(XtScreen(topLevel)),
                  (char **) abacus_xpm, &abacusIcon, NULL,
                  &xpmAttributes);
      }
      if (abacusIcon == (Pixmap) NULL)
#endif
            abacusIcon = XCreateBitmapFromData(XtDisplay(topLevel),
                  RootWindowOfScreen(XtScreen(topLevel)),
                  (char *) abacus_bits,
                  abacus_width, abacus_height);
#ifdef HAVE_MOTIF
      XtVaSetValues(topLevel,
            XtNiconPixmap, abacusIcon,
            XmNkeyboardFocusPolicy, XmPOINTER, NULL); /* not XmEXPLICIT */
      menuBarPanel = XtVaCreateManagedWidget("menuBarPanel",
            xmPanedWindowWidgetClass, topLevel,
            XmNseparatorOn, False,
            XmNsashWidth, 1,
            XmNsashHeight, 1, NULL);
      fileString = XmStringCreateSimple((char *) "File");
      controlsString = XmStringCreateSimple((char *) "Controls");
      menuBar = XmVaCreateSimpleMenuBar(menuBarPanel, (char *) "menuBar",
            XmVaCASCADEBUTTON, fileString, 'F',
            XmVaCASCADEBUTTON, controlsString, 'C',
            NULL);
      XmStringFree(fileString);
      XmStringFree(controlsString);
      quitString = XmStringCreateSimple((char *) "Quit");
      (void) XmVaCreateSimplePulldownMenu(menuBar, (char *) "fileMenu",
            0, fileCB,
            XmVaSEPARATOR,
            XmVaPUSHBUTTON, quitString, 'Q', NULL, NULL,
            NULL);
      XmStringFree(quitString);
      clearString = XmStringCreateSimple((char *) "Clear");
      incrementString = XmStringCreateSimple((char *) "Increment");
      decrementString = XmStringCreateSimple((char *) "Decrement");
      format = XmStringCreateSimple((char *) "Format");
      romanNumeralString = XmStringCreateSimple((char *) "RoMan Numerals");
      signString = XmStringCreateSimple((char *) "Sign");
      quarterString = XmStringCreateSimple((char *) "QUarter");
      quarterPercentString = XmStringCreateSimple((char *) "Quarter Percent");
      twelfthString = XmStringCreateSimple((char *) "Twelfth");
      anomalyString = XmStringCreateSimple((char *) "Anomaly");
      watchString = XmStringCreateSimple((char *) "Watch");
      speedString = XmStringCreateSimple((char *) ">Speed");
      slowString = XmStringCreateSimple((char *) "<Slow");
      soundString = XmStringCreateSimple((char *) "@Sound");
      (void) XmVaCreateSimplePulldownMenu(menuBar, (char *) "controlsMenu",
            1, controlsCB,
            XmVaPUSHBUTTON, clearString, 'C', NULL, NULL,
            XmVaPUSHBUTTON, incrementString, 'I', NULL, NULL,
            XmVaPUSHBUTTON, decrementString, 'D', NULL, NULL,
            XmVaPUSHBUTTON, format, 'F', NULL, NULL,
            XmVaPUSHBUTTON, romanNumeralString, 'M', NULL, NULL,
            XmVaPUSHBUTTON, signString, 'S', NULL, NULL,
            XmVaPUSHBUTTON, quarterString, 'U', NULL, NULL,
            XmVaPUSHBUTTON, quarterPercentString, 'P', NULL, NULL,
            XmVaPUSHBUTTON, twelfthString, 'T', NULL, NULL,
            XmVaPUSHBUTTON, anomalyString, 'A', NULL, NULL,
            XmVaPUSHBUTTON, watchString, 'W', NULL, NULL,
            XmVaPUSHBUTTON, speedString, '>', NULL, NULL,
            XmVaPUSHBUTTON, slowString, '<', NULL, NULL,
            XmVaPUSHBUTTON, soundString, '@', NULL, NULL,
            NULL);
      XmStringFree(clearString);
      XmStringFree(incrementString);
      XmStringFree(decrementString);
      XmStringFree(format);
      XmStringFree(romanNumeralString);
      XmStringFree(signString);
      XmStringFree(quarterString);
      XmStringFree(quarterPercentString);
      XmStringFree(twelfthString);
      XmStringFree(anomalyString);
      XmStringFree(watchString);
      XmStringFree(speedString);
      XmStringFree(slowString);
      XmStringFree(soundString);
      pullDownMenu = XmCreatePulldownMenu(menuBar,
            (char *) "helpPullDown", NULL, 0);
      widget = XtVaCreateManagedWidget("Help",
            xmCascadeButtonWidgetClass, menuBar,
            XmNsubMenuId, pullDownMenu,
            XmNmnemonic, 'H', NULL);
      XtVaSetValues(menuBar, XmNmenuHelpWidget, widget, NULL);
      widget = XtVaCreateManagedWidget("Description",
            xmPushButtonGadgetClass, pullDownMenu,
            XmNmnemonic, 'D', NULL);
      XtAddCallback(widget, XmNactivateCallback, helpCB, (char *) 0);
      widget = XtVaCreateManagedWidget("Features",
            xmPushButtonGadgetClass, pullDownMenu,
            XmNmnemonic, 'F', NULL);
      XtAddCallback(widget, XmNactivateCallback, helpCB, (char *) 1);
      widget = XtVaCreateManagedWidget("Options",
            xmPushButtonGadgetClass, pullDownMenu,
            XmNmnemonic, 'O', NULL);
      XtAddCallback(widget, XmNactivateCallback, helpCB, (char *) 2);
      widget = XtVaCreateManagedWidget("Options1",
            xmPushButtonGadgetClass, pullDownMenu,
            XmNmnemonic, '1', NULL);
      XtAddCallback(widget, XmNactivateCallback, helpCB, (char *) 3);
      widget = XtVaCreateManagedWidget("Options2",
            xmPushButtonGadgetClass, pullDownMenu,
            XmNmnemonic, '2', NULL);
      XtAddCallback(widget, XmNactivateCallback, helpCB, (char *) 4);
      widget = XtVaCreateManagedWidget("References",
            xmPushButtonGadgetClass, pullDownMenu,
            XmNmnemonic, 'R', NULL);
      XtAddCallback(widget, XmNactivateCallback, helpCB, (char *) 5);
      widget = XtVaCreateManagedWidget("About",
            xmPushButtonGadgetClass, pullDownMenu,
            XmNmnemonic, 'A', NULL);
      XtAddCallback(widget, XmNactivateCallback, helpCB, (char *) 6);
      XtManageChild(menuBar);
      descriptionDialog = createHelp(menuBar, (char *) descriptionHelp,
            (char *) "Description");
      featuresDialog = createHelp(menuBar, (char *) featuresHelp,
            (char *) "Features");
      optionsDialog = createHelp(menuBar, (char *) optionsHelp,
            (char *) "Options");
      options1Dialog = createHelp(menuBar, (char *) options1Help,
            (char *) "Options1");
      options2Dialog = createHelp(menuBar, (char *) options2Help,
            (char *) "Options2");
      referencesDialog = createHelp(menuBar, (char *) referencesHelp,
            (char *) "References");
      aboutDialog = createHelp(menuBar, (char *) aboutHelp,
            (char *) "About");
      clearDialog = createQuery(topLevel,
            (char *) "Are you sure you want to destroy the calculation?",
            (char *) "Clear Query",
            (XtCallbackProc) CallbackAbacusClear);
      mainPanel = XtCreateManagedWidget("mainPanel",
            xmPanedWindowWidgetClass, menuBarPanel,
            NULL, 0);
      controlPanel = XtVaCreateManagedWidget("controlPanel",
            xmPanedWindowWidgetClass, mainPanel,
            XmNseparatorOn, False,
            XmNsashWidth, 1,
            XmNsashHeight, 1,
            NULL);
#ifdef MOUSEBITMAPS
      {
            /* Takes up valuable real estate. */
            Widget bitmapRowCol;
            Pixmap mouseLeftCursor, mouseRightCursor;
            Pixel fg, bg;

            bitmapRowCol = XtVaCreateManagedWidget("bitmapRowCol",
                  xmRowColumnWidgetClass, controlPanel,
                  XmNnumColumns, 4,
                  XmNpacking, XmPACK_COLUMN, NULL);
            (void) XtVaGetValues(bitmapRowCol,
                  XmNforeground, &fg,
                  XmNbackground, &bg, NULL);
            mouseLeftCursor = XCreatePixmapFromBitmapData(
                  XtDisplay(bitmapRowCol),
                  RootWindowOfScreen(XtScreen(bitmapRowCol)),
                  (char *) mouse_left_bits,
                  mouse_left_width, mouse_left_height, fg, bg,
                  DefaultDepthOfScreen(XtScreen(bitmapRowCol)));
            mouseRightCursor = XCreatePixmapFromBitmapData(
                  XtDisplay(bitmapRowCol),
                  RootWindowOfScreen(XtScreen(bitmapRowCol)),
                  (char *) mouse_right_bits,
                  mouse_right_width, mouse_right_height, fg, bg,
                  DefaultDepthOfScreen(XtScreen(bitmapRowCol)));
            (void) XtVaCreateManagedWidget("mouseLeftText",
                  xmLabelGadgetClass, bitmapRowCol,
                  XtVaTypedArg, XmNlabelString,
                  XmRString, "Move bead", 10, NULL);
            (void) XtVaCreateManagedWidget("mouseLeft",
                  xmLabelGadgetClass, bitmapRowCol,
                  XmNlabelType, XmPIXMAP,
                  XmNlabelPixmap, mouseLeftCursor, NULL);
            (void) XtVaCreateManagedWidget("mouseRightText",
                  xmLabelGadgetClass, bitmapRowCol,
                  XtVaTypedArg, XmNlabelString,
                  XmRString, "    Clear", 10, NULL);
            (void) XtVaCreateManagedWidget("mouseRight",
                  xmLabelGadgetClass, bitmapRowCol,
                  XmNlabelType, XmPIXMAP,
                  XmNlabelPixmap, mouseRightCursor, NULL);
      }
#endif
      controlRowCol = XtVaCreateManagedWidget("controlRowCol",
            xmRowColumnWidgetClass, controlPanel,
            XmNnumColumns, 1,
            XmNorientation, XmHORIZONTAL,
            XmNpacking, XmPACK_COLUMN, NULL);
#ifdef TOGGLES
      toggleRowCol = XtVaCreateManagedWidget("toggleRowCol",
            xmRowColumnWidgetClass, controlPanel,
            XmNorientation, XmHORIZONTAL,
            XmNpacking, XmPACK_COLUMN, NULL);
#endif
#if LEE_ABACUS
      auxTrackerRowCol = XtVaCreateManagedWidget("auxTrackerRowCol",
            xmRowColumnWidgetClass, controlPanel,
            XmNorientation, XmHORIZONTAL,
            XmNnumColumns, 2, NULL);
      leftAuxTracker = XtVaCreateManagedWidget("0",
            xmTextWidgetClass, auxTrackerRowCol,
            NULL);
      rightAuxTracker = XtVaCreateManagedWidget("0",
            xmTextWidgetClass, auxTrackerRowCol,
            NULL);
#endif
      trackerRowCol = XtVaCreateManagedWidget("trackerRowCol",
            xmRowColumnWidgetClass, controlPanel, NULL);
      tracker = XtCreateManagedWidget("0",
            xmTextWidgetClass, trackerRowCol, NULL, 0);
      XtAddCallback(tracker, XmNactivateCallback,
            (XtCallbackProc) CallbackAbacusMath, (XtPointer) NULL);
#if LEE_ABACUS
      auxForm = XtVaCreateManagedWidget("auxForm",
            xmFormWidgetClass, mainPanel,
            XmNfractionBase, 20,
            NULL);
      abacus = XtVaCreateManagedWidget("abacus",
            abacusWidgetClass, auxForm,
            XmNbottomAttachment, XmATTACH_FORM,
            XmNleftAttachment, XmATTACH_FORM,
            XmNrightAttachment, XmATTACH_FORM,
            XmNtopAttachment, XmATTACH_POSITION,
            XmNtopPosition, 5,
            NULL);
      (void) XParseColor(XtDisplay(abacus),
            DefaultColormapOfScreen(XtScreen(abacus)), "LimeGreen",
            &exactDef);
      (void) XAllocColor(XtDisplay(abacus),
            DefaultColormapOfScreen(XtScreen(abacus)), &exactDef);
#if !defined( LEE_CN ) && !defined( LEE_KO ) && !defined( LEE_ELF )
#define LEE_CN
#endif
      leftAuxAbacus = XtVaCreateManagedWidget("leftAuxAbacus",
            abacusWidgetClass, auxForm,
            XmNtopAttachment, XmATTACH_FORM,
            XmNleftAttachment, XmATTACH_FORM,
            XmNbottomAttachment, XmATTACH_WIDGET,
            XmNrightAttachment, XmATTACH_POSITION,
            XmNbottomWidget, abacus,
            XtNformat, "Japanese",
            XtNaux, True,
            XtNbeadColor, exactDef.pixel,
#ifdef LEE_CN
            XmNrightPosition, 7,
            XtNrails, 7,
#else
#ifdef LEE_KO
            XmNrightPosition, 8,
            XtNrails, 7,
#else
            XtNrails, 9,
            XmNrightPosition, 10,
#endif
#endif
            NULL);
      XtAddCallback(leftAuxAbacus, XtNselectCallback,
            (XtCallbackProc) CallbackAbacus, (XtPointer) NULL);
      (void) XParseColor(XtDisplay(abacus),
            DefaultColormapOfScreen(XtScreen(abacus)), "gainsboro",
            &exactDef);
      (void) XAllocColor(XtDisplay(abacus),
            DefaultColormapOfScreen(XtScreen(abacus)), &exactDef);
      rightAuxAbacus = XtVaCreateManagedWidget("rightAuxAbacus",
            abacusWidgetClass, auxForm,
            XmNtopAttachment, XmATTACH_FORM,
            XmNrightAttachment, XmATTACH_FORM,
            XmNbottomAttachment, XmATTACH_WIDGET,
            XmNbottomWidget, abacus,
            XmNleftAttachment, XmATTACH_WIDGET,
            XmNleftWidget, leftAuxAbacus,
            XtNformat, "Japanese",
            XtNaux, True,
            XtNbeadColor, exactDef.pixel,
#ifdef LEE_CN
            XtNrails, 13,
#else
#ifdef LEE_KO
            XtNrails, 11,
#else
            XtNrails, 9,
#endif
#endif
            NULL);
      XtAddCallback(rightAuxAbacus, XtNselectCallback,
            (XtCallbackProc) CallbackAbacus, (XtPointer) NULL);

#else
      abacus = XtVaCreateManagedWidget("abacus",
            abacusWidgetClass, mainPanel,
#ifdef LEE_KO
            XtNformat, "Korean",
#endif
            NULL);
#endif
#else
      XtVaSetValues(topLevel,
            XtNiconPixmap, abacusIcon,
            XtNinput, True, NULL);
      abacus = XtCreateManagedWidget("abacus",
            abacusWidgetClass, topLevel, NULL, 0);
#endif
      XtAddCallback(abacus, XtNselectCallback,
            (XtCallbackProc) CallbackAbacus, (XtPointer) NULL);

      XtVaGetValues(abacus,
#ifdef HAVE_MOTIF
            XtNrails, &rails,
            XtNromanNumerals, &romanNumerals,
            XtNsign, &sign,
            XtNbottomPiece, &bottomPiece,
            XtNbottomPiecePercent, &bottomPiecePercent,
            XtNanomaly, &anomaly,
            XtNbase, &base,
            XtNdisplayBase, &displayBase,
            XtNmode, &mode,
#endif
            XtNdemo, &demo, NULL);
#ifdef HAVE_MOTIF
#ifdef TOGGLES
      {
      romanNumeralSwitch = XtVaCreateManagedWidget("Roman",
            xmToggleButtonGadgetClass, toggleRowCol, NULL);
      XtAddCallback(romanNumeralSwitch, XmNvalueChangedCallback,
            (XtCallbackProc) RomanNumeralToggle, (XtPointer) NULL);
      XmToggleButtonSetState(romanNumeralSwitch, romanNumerals, False);
      signSwitch = XtVaCreateManagedWidget("Signed",
            xmToggleButtonGadgetClass, toggleRowCol, NULL);
      XtAddCallback(signSwitch, XmNvalueChangedCallback,
            (XtCallbackProc) SignToggle, (XtPointer) NULL);
      XmToggleButtonSetState(signSwitch, sign, False);
      pieceSwitch = XtVaCreateManagedWidget("Piece",
            xmToggleButtonGadgetClass, toggleRowCol, NULL);
      XtAddCallback(pieceSwitch, XmNvalueChangedCallback,
            (XtCallbackProc) QuarterToggle, (XtPointer) NULL);
      XmToggleButtonSetState(pieceSwitch, (bottomPiece != 0), False);
      piecePercentSwitch = XtVaCreateManagedWidget("PiecePercent",
            xmToggleButtonGadgetClass, toggleRowCol, NULL);
      XtAddCallback(piecePercentSwitch, XmNvalueChangedCallback,
            (XtCallbackProc) QuarterPercentToggle, (XtPointer) NULL);
      XmToggleButtonSetState(piecePercentSwitch, (bottomPiecePercent != 0),
            False);
      anomalySwitch = XtVaCreateManagedWidget("Anomaly",
            xmToggleButtonGadgetClass, toggleRowCol, NULL);
      XtAddCallback(anomalySwitch, XmNvalueChangedCallback,
            (XtCallbackProc) AnomalyToggle, (XtPointer) NULL);
      XmToggleButtonSetState(anomalySwitch, (anomaly != 0), False);
#if 0
      verticalSwitch= XtVaCreateManagedWidget("Vertical",
            xmToggleButtonGadgetClass, toggleRowCol, NULL);
      XtAddCallback(verticalSwitch, XmNvalueChangedCallback,
            (XtCallbackProc) VerticalToggle, (XtPointer) NULL);
#endif
      }
#endif
      sizeSlider = XtVaCreateManagedWidget("rails",
            xmScaleWidgetClass, controlRowCol,
            XtVaTypedArg, XmNtitleString, XmRString, "Abacus Size", 12,
            XmNminimum, MINRAILS,
            XmNmaximum, MAXRAILS,
            XmNscaleWidth, (MAXRAILS - MINRAILS + 1) * 4,
            XmNvalue, rails,
            XmNshowValue, True,
            XmNorientation, XmHORIZONTAL, NULL);
      XtAddCallback(sizeSlider, XmNvalueChangedCallback,
            (XtCallbackProc) RailSlider, (XtPointer) NULL);
      baseSet = ((base != DEFAULTBASE || displayBase != DEFAULTBASE) &&
            !demo);
      if (mode < 0 || mode > MAXFORMATS)
            mode = OTHER;
      if (demo && mode == OTHER)
            mode = CHINESE;
      complexity = XmStringCreateSimple((char *) "Complexity:");
      complexitySubMenu = XmCreatePulldownMenu(controlRowCol,
            (char *) "complexitySubMenu", NULL, 0);
      for (i = 0; i < COMPLEXITIES; i++) {
            complexityStrings[i] =
                  XmStringCreateSimple((char *) complexityString[i]);
            XtSetArg(arg[0], XmNlabelString, complexityStrings[i]);
            XtSetArg(arg[1], XmNmnemonic, complexityString[i][0]);
            complexityOptions[i] =
                  XmCreatePushButtonGadget(complexitySubMenu,
                  (char *) complexityString[i], arg, 2);
            XtAddCallback(complexityOptions[i],
                  XmNactivateCallback, complexityCB, (char *) i);
      }
      XtManageChildren(complexityOptions, COMPLEXITIES);
      XtSetArg(arg[0], XmNlabelString, complexity);
      XtSetArg(arg[1], XmNmnemonic, 'C');
      XtSetArg(arg[2], XmNsubMenuId, complexitySubMenu);
      XtSetArg(arg[3], XmNmenuHistory,
                  complexityOptions[((demo) ? 0 : ((baseSet) ? 2 : 1))]);
      complexityMenu = XmCreateOptionMenu(controlRowCol,
            (char *) "ComplexityMenu", arg, 4);
      for (i = 0; i < COMPLEXITIES; i++)
            XmStringFree(complexityStrings[i]);
      XmStringFree(complexity);
      XtManageChild(complexityMenu);
      format = XmStringCreateSimple((char *) "Format:");
      formatSubMenu = XmCreatePulldownMenu(controlRowCol,
            (char *) "formatSubMenu", NULL, 0);
      for (i = 0; i < MAXMODES; i++) {
            formatStrings[i] =
                  XmStringCreateSimple((char *) formatString[i]);
            XtSetArg(arg[0], XmNlabelString, formatStrings[i]);
            XtSetArg(arg[1], XmNmnemonic, formatString[i][0]);
            formatOptions[i] = XmCreatePushButtonGadget(formatSubMenu,
                  (char *) formatString[i], arg, 2);
            XtAddCallback(formatOptions[i],
                  XmNactivateCallback, formatCB, (char *) i);
      }
      XtManageChildren(formatOptions, MAXMODES);
      XtSetArg(arg[0], XmNlabelString, format);
      XtSetArg(arg[1], XmNmnemonic, 'F');
      XtSetArg(arg[2], XmNsubMenuId, formatSubMenu);
      XtSetArg(arg[3], XmNmenuHistory, formatOptions[mode]);
      formatMenu = XmCreateOptionMenu(controlRowCol, (char *) "FormatMenu",
            arg, 4);
      for (i = 0; i < MAXMODES; i++)
            XmStringFree(formatStrings[i]);
      XmStringFree(format);
      XtManageChild(formatMenu);
      if (baseSet) {
            createBase(base, displayBase);
      } else {
            forceNormalParams(abacus);
      }
#endif
      Initialize(abacus);
      if (demo)
            forceDemoParams(abacus);
      XtRealizeWidget(topLevel);
      (void) XGrabButton(XtDisplay(abacus), (unsigned int) AnyButton,
            AnyModifier, XtWindow(abacus), TRUE,
            (unsigned int) (ButtonPressMask |
            ButtonMotionMask | ButtonReleaseMask),
            GrabModeAsync, GrabModeAsync, XtWindow(abacus),
            XCreateFontCursor(XtDisplay(abacus), XC_crosshair));
      if (demo) {
            createDemo();
      }
      XtMainLoop();

#ifdef VMS
      return 1;
#else
      return 0;
#endif
}
#endif

Generated by  Doxygen 1.6.0   Back to index