home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume10 / xt-examples / part01 / xcalc.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-11-04  |  9.2 KB  |  350 lines

  1. /***********************************************************
  2. Copyright 1990 by Digital Equipment Corporation, Maynard, Massachusetts.
  3.  
  4.                         All Rights Reserved
  5.  
  6. Permission to use, copy, modify, and distribute these examples for any
  7. purpose and without fee is hereby granted, provided that the above
  8. copyright notice appear in all copies and that both that copyright
  9. notice and this permission notice appear in supporting documentation,
  10. and that the name of Digital not be used in advertising or publicity
  11. pertaining to distribution of the software without specific, written
  12. prior permission.
  13.  
  14. DIGITAL AND THE AUTHORS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
  15. SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
  16. FITNESS, IN NO EVENT SHALL DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT
  17. OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS
  18. OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
  19. OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE
  20. OR PERFORMANCE OF THIS SOFTWARE.
  21.  
  22. ******************************************************************/
  23.  
  24. #include <X11/Intrinsic.h>
  25. #include <X11/StringDefs.h>
  26. #include <X11/Shell.h>
  27. #include <X11/Xatom.h>
  28.  
  29. #include "Box.h"
  30. #include "Pushbutton.h"
  31. #include "MenuItem.h"
  32. #include "Menu.h"
  33.  
  34. /* Calculator variables */
  35. double currentInput = 0, total = 0;
  36. Boolean inputDecimal = FALSE, inputNumber = FALSE;
  37. double scale;
  38. double *numberToDisplay = &total;
  39.  
  40. /* Pending operation */
  41. typedef enum {Start, Equal, Add, Sub, Mul, Div} operation;
  42. operation lastOp = Start;
  43.  
  44. /* Interface variables */
  45. XtAppContext app;
  46. Widget display;        /* Calculator's display */
  47. Widget menuShell;
  48. Boolean hasSelection = FALSE;
  49.  
  50. void CreateInterface(), InputDigit(), InputDecimal(), Function(),
  51.     Clear(), RefreshDisplay(), RepositionMenu(), Quit(), Select(),
  52.     Paste(), PasteData(), LoseSelection();
  53.  
  54. XtActionsRec actions[] = {
  55.     {"RepositionMenu", RepositionMenu}
  56. };
  57.  
  58. int main(argc, argv)
  59.     int argc;
  60.     char *argv[];
  61. {
  62.     Widget toplevel;
  63.  
  64.     toplevel = XtAppInitialize(&app, "DemoCalc",
  65.         (XrmOptionDescList) NULL, 0, &argc, argv,
  66.             (String *) NULL, (ArgList) NULL, 0);
  67.  
  68.     XtAppAddActions(app, actions, XtNumber(actions));
  69.  
  70.     /* Make XtMenuPopup synchronous */
  71.     XtRegisterGrabAction(XtMenuPopupAction, FALSE,
  72.         ButtonPressMask | ButtonReleaseMask, GrabModeSync,
  73.         GrabModeAsync);
  74.  
  75.     CreateInterface(toplevel);
  76.     RefreshDisplay();
  77.     XtRealizeWidget(toplevel);
  78.     XtAppMainLoop(app);
  79. }
  80.  
  81. void CreateInterface(toplevel)
  82.     Widget toplevel;
  83. {
  84.     Widget main, widget, menu;
  85.  
  86.     main = XtCreateManagedWidget("main", boxWidgetClass,
  87.         toplevel, (Arg *) NULL, 0);
  88.     display = XtCreateManagedWidget("display", pushbuttonWidgetClass, 
  89.         main, (Arg *) NULL, 0);
  90.     XtAddCallback(display, XtNloseSelection,
  91.         LoseSelection, (XtPointer) NULL);
  92.  
  93. #define CreatePushbutton(name, callback, data) \
  94.     widget = XtCreateManagedWidget(name, pushbuttonWidgetClass, \
  95.         main, (Arg *) NULL, 0); \
  96.     XtAddCallback(widget, XtNcallback, callback, (XtPointer) data);
  97.  
  98.     CreatePushbutton("button0", InputDigit, 0);
  99.     CreatePushbutton("button1", InputDigit, 1);
  100.     CreatePushbutton("button2", InputDigit, 2);
  101.     CreatePushbutton("button3", InputDigit, 3);
  102.     CreatePushbutton("button4", InputDigit, 4);
  103.     CreatePushbutton("button5", InputDigit, 5);
  104.     CreatePushbutton("button6", InputDigit, 6);
  105.     CreatePushbutton("button7", InputDigit, 7);
  106.     CreatePushbutton("button8", InputDigit, 8);
  107.     CreatePushbutton("button9", InputDigit, 9);
  108.  
  109.     CreatePushbutton("decimal", InputDecimal, NULL);
  110.  
  111.     CreatePushbutton("plus", Function, Add);
  112.     CreatePushbutton("minus", Function, Sub);
  113.     CreatePushbutton("times", Function, Mul);
  114.     CreatePushbutton("divide", Function, Div);
  115.     CreatePushbutton("equals", Function, Equal);
  116.  
  117.     CreatePushbutton("clearEntry", Clear, FALSE);
  118.     CreatePushbutton("clear", Clear, TRUE);
  119. #undef CreatePushbutton
  120.  
  121.     menuShell = XtCreatePopupShell("menuShell",
  122.         overrideShellWidgetClass, main, (Arg *) NULL, 0);
  123.     menu = XtCreateManagedWidget("menu", menuWidgetClass, menuShell,
  124.         (Arg *) NULL, 0);
  125.  
  126. #define CreateMenuItem(name, callback) \
  127.     widget = XtCreateManagedWidget(name, menuItemWidgetClass, \
  128.         menu, (Arg *) NULL, 0); \
  129.     XtAddCallback(widget, XtNcallback, callback, (XtPointer) NULL);
  130.  
  131.     CreateMenuItem("select", Select);
  132.     CreateMenuItem("paste", Paste);
  133.     CreateMenuItem("quit", Quit);
  134. #undef CreateMenuItem
  135.     XtInstallAllAccelerators(main, main);
  136. }
  137.  
  138. void InputDigit(w, client_data, call_data)
  139.     Widget w;
  140.     XtPointer client_data;    /* Digit to input */
  141.     XtPointer call_data;
  142. {
  143.     int num = (int) client_data;
  144.  
  145.     if (inputDecimal) {
  146.     currentInput += num * scale;
  147.     scale /= 10;
  148.     } else currentInput = currentInput * 10 + num;
  149.  
  150.     numberToDisplay = ¤tInput;
  151.     RefreshDisplay();
  152.     inputNumber = TRUE;
  153. }
  154.  
  155. void InputDecimal(w, client_data, call_data)
  156.     Widget w;
  157.     XtPointer client_data, call_data;
  158. {
  159.     inputDecimal = inputNumber = TRUE;
  160.     scale = 0.1;
  161.     numberToDisplay = ¤tInput;
  162.     RefreshDisplay();
  163. }
  164.  
  165. void Function(w, client_data, call_data)
  166.     Widget w;
  167.     XtPointer client_data;    /* Operation code */
  168.     XtPointer call_data;
  169. {
  170.     switch (lastOp) {
  171.     case Add:
  172.         total += currentInput;
  173.         break;
  174.     case Sub:
  175.         total -= currentInput;
  176.         break;
  177.     case Mul:
  178.         total *= currentInput;
  179.         break;
  180.     case Div:
  181.         if (currentInput == 0.0) XBell(XtDisplay(display), 100);
  182.         else total /= currentInput;
  183.         break;
  184.     case Equal:
  185.         if (inputNumber) total = currentInput;
  186.         break;
  187.     case Start:
  188.         total = currentInput;
  189.         break;
  190.     }
  191.     lastOp = (operation) client_data;
  192.     currentInput = 0;
  193.     inputDecimal = inputNumber = FALSE;
  194.  
  195.     numberToDisplay = &total;
  196.     RefreshDisplay();
  197. }
  198.  
  199. void Clear(w, client_data, call_data)
  200.     Widget w;
  201.     XtPointer client_data;    /* FALSE for Clear Entry */
  202.     XtPointer call_data;
  203. {
  204.     currentInput = 0;
  205.     if ((Boolean) client_data) {
  206.     total = 0;
  207.     lastOp = Start;
  208.     }
  209.     inputDecimal = inputNumber = FALSE;
  210.  
  211.     numberToDisplay = ¤tInput;
  212.     RefreshDisplay();
  213. }
  214.  
  215. void RefreshDisplay()
  216. {
  217.     char buffer[100];
  218.     Arg args[10];
  219.     int i = 0;
  220.  
  221.     if (hasSelection) {        /* Get rid of it */
  222.     LabelSelectText(display, XA_PRIMARY, FALSE);
  223.     /* LoseSelection resets hasSelection and uninverts display */
  224.     }
  225.  
  226.     sprintf(buffer, "%g", *numberToDisplay);
  227.     XtSetArg(args[i], XtNlabel, buffer);    i++;
  228.     XtSetValues(display, args, i);
  229. }
  230.  
  231. void RepositionMenu(w, event, params, num_params)
  232.     Widget w;
  233.     XEvent *event;
  234.     String *params;
  235.     Cardinal *num_params;
  236. {
  237.     XButtonEvent *b = &event->xbutton;
  238.     Dimension width, height, border;
  239.     Arg arg[25];
  240.     int n;
  241.  
  242.     if (event->type != ButtonPress) return;
  243.  
  244.     /* Size isn't valid before realizing */
  245.     XtRealizeWidget(menuShell);
  246.  
  247.     /* Fetch size */
  248.     n = 0;
  249.     XtSetArg(arg[n], XtNwidth, &width);        n++;
  250.     XtSetArg(arg[n], XtNheight, &height);    n++;
  251.     XtSetArg(arg[n], XtNborderWidth, &border);    n++;
  252.     XtGetValues(menuShell, arg, n);
  253.  
  254.     /* Reposition menu */
  255.     n = 0;
  256.     XtSetArg(arg[n], XtNx, b->x_root - width/2 - border);    n++;
  257.     XtSetArg(arg[n], XtNy, b->y_root - height/2 - border);    n++;
  258.     XtSetValues(menuShell, arg, n);
  259. }
  260.  
  261. void Quit(w, client_data, call_data)
  262.     Widget w;
  263.     XtPointer client_data, call_data;
  264. {
  265.     exit(0);
  266. }
  267.  
  268. void Select(w, client_data, call_data)
  269.     Widget w;
  270.     XtPointer client_data, call_data;
  271. {
  272.     if (hasSelection) return;
  273.  
  274.     /* Ask for selection */
  275.     if (LabelSelectText(display, XA_PRIMARY, TRUE)) {
  276.     hasSelection = TRUE;
  277.  
  278.     /* Invert display widget */
  279.     XtCallActionProc(display, "invert", (XEvent *) NULL,
  280.         (String *) NULL, 0);
  281.     }
  282. }
  283.  
  284. void LoseSelection(w, client_data, call_data)
  285.     Widget w;
  286.     XtPointer client_data, call_data;
  287. {
  288.     hasSelection = FALSE;
  289.  
  290.     /* Uninvert the display */
  291.     XtCallActionProc(display, "uninvert", (XEvent *) NULL,
  292.         (String *) NULL, 0);
  293. }
  294.  
  295. void Paste(w, client_data, call_data)
  296.     Widget w;
  297.     XtPointer client_data, call_data;
  298. {
  299.     XtGetSelectionValue(display, XA_PRIMARY, XA_STRING, PasteData,
  300.         (XtPointer) NULL, XtLastTimestampProcessed(XtDisplay(w)));
  301. }
  302.  
  303. void PasteData(w, client_data, selection, type, value, length, format)
  304.     Widget w;
  305.     XtPointer client_data;
  306.     Atom *selection, *type;
  307.     XtPointer value;
  308.     unsigned long *length;
  309.     int *format;
  310. {
  311.     register int i;
  312.     char *ch = (char *) value;
  313.  
  314.     /* Make sure we got what we expected */
  315.     if (*selection != XA_PRIMARY || *type != XA_STRING ||
  316.         *format != 8 || value == NULL) return;
  317.  
  318.     for (i = 0; i < *length; i++) {
  319.     if (ch[i] >= '0' && ch[i] <= '9') {
  320.         InputDigit(display, (XtPointer) (ch[i] - '0'),
  321.             (XtPointer) NULL);
  322.     } else switch (ch[i]) {
  323.         case '+':
  324.         Function(display, (XtPointer) Add, (XtPointer) NULL);
  325.         break;
  326.         case '-':
  327.         Function(display, (XtPointer) Sub, (XtPointer) NULL);
  328.         break;
  329.         case '*':
  330.         Function(display, (XtPointer) Mul, (XtPointer) NULL);
  331.         break;
  332.         case '/':
  333.         Function(display, (XtPointer) Div, (XtPointer) NULL);
  334.         break;
  335.         case '=':
  336.         Function(display, (XtPointer) Equal, (XtPointer) NULL);
  337.         break;
  338.         case '.':
  339.         InputDecimal(display, (XtPointer) NULL,
  340.             (XtPointer) NULL);
  341.         break;
  342.         default:
  343.         return;
  344.     }
  345.     }
  346.     Function(display, (XtPointer) Equal, (XtPointer) NULL);
  347.  
  348.     XtFree((XtPointer) value);
  349. }
  350.