home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xtici.zip / xtici / xtici.c < prev    next >
C/C++ Source or Header  |  1991-08-28  |  16KB  |  551 lines

  1. /*
  2.  * Code and supporting documentation (c) Copyright 1990 1991 Tektronix, Inc.
  3.  *     All Rights Reserved
  4.  * 
  5.  * This file is a component of an X Window System client which uses the Xcms 
  6.  * Color Management System.  TekColor is a trademark of Tektronix, Inc.  The
  7.  * TekColor Editor is the subject of U.S. and foreign patents pending.  The
  8.  * term "TekHVC" designates a particular color space that is the subject of
  9.  * U.S. Patent No. 4,985,853 (equivalent foreign patents pending).
  10.  * Permission is hereby granted to use, copy, modify, sell, and otherwise
  11.  * distribute this software and its documentation for the X Window System
  12.  * environment, for any purpose and without fee, provided that:
  13.  * 
  14.  * 1.    The code and documentation are only used to implement a 
  15.  *      TekColor Editor in an X Window System environment; and
  16.  * 2.    This copyright and permission notice is reproduced in all copies
  17.  *     of the code and in supporting documentation.
  18.  * 
  19.  * Permission is granted to modify this code as required to allow it to
  20.  * be compiled on any host computer, provided that the functionality of
  21.  * the TekColor Editor is not modified in any way.  A description of any 
  22.  * modifications must be sent to Tektronix, Inc.  Contact 
  23.  * Tektronix Inc., P.O. Box 1000, Mail Station 60-850, 
  24.  * Network Displays Division Engineering, Wilsonville, OR 97070.
  25.  *
  26.  * Tektronix makes no representation about the suitability of this software
  27.  * for any purpose.  It is provided "as is" and with all faults.
  28.  * 
  29.  * TEKTRONIX DISCLAIMS ALL WARRANTIES APPLICABLE TO THIS SOFTWARE,
  30.  * INCLUDING THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
  31.  * PARTICULAR PURPOSE.  IN NO EVENT SHALL TEKTRONIX BE LIABLE FOR ANY
  32.  * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
  33.  * RESULTING FROM LOSS OF USE, DATA, OR PROFITS, WHETHER IN AN ACTION OF
  34.  * CONTRACT, NEGLIGENCE, OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
  35.  * CONNECTION WITH THE USE OR THE PERFORMANCE OF THIS SOFTWARE.
  36.  * 
  37.  *    NAME
  38.  *        xtici.c - the main routine for the the TekColor Editor
  39.  *
  40.  *    SYNOPSIS
  41.  *        xtici [options]
  42.  *        options:
  43.  *            -display {hostname:number.screen}
  44.  *            -huebar {empty | constant | dynamic}
  45.  *            -leaf {empty | filled}
  46.  *            -gamutProc {closest | chroma | value}
  47.  *
  48.  *    DESCRIPTION
  49.  *        xtici is a colormap editor based on the TekColor(TM)
  50.  *        color space.  It provides an intuitive color selection model
  51.  *        based on Hue, Value and Chroma.
  52.  *    
  53.  *        TekColor is a trademark of Tektronix, Inc.
  54.  *
  55.  *    SEE ALSO
  56.  *        <related documentation, programs, and packages>
  57.  *        <not already mentioned>
  58.  *
  59.  *    DIAGNOSTICS
  60.  *        <error messages, meanings, and corrective actions>
  61.  *
  62.  *    BUGS
  63.  *        <currently known loony behavior>
  64.  *
  65.  */
  66. #ifndef LINT
  67. static char *copy_notice = "Copyright 1991 Tektronix, Inc.";
  68. #ifdef RCS_ID
  69. static char *rcsid=  "$Header: xtici.c,v 1.3 91/08/28 10:03:48 adamsc Exp $";
  70. #endif /* RCS_ID */
  71. #endif /* LINT */
  72.  
  73. /*
  74.  *        EXTERNAL INCLUDES
  75.  */
  76.  
  77. /*
  78.  *        INTERNAL INCLUDES
  79.  */
  80. #include <stdio.h>
  81. #include <X11/StringDefs.h>
  82. #include <X11/IntrinsicP.h>
  83. #include <X11/keysym.h>
  84.  
  85. #include "xtici.h"
  86. #include "widgets/VShell.h"
  87.  
  88. /*
  89.  *        EXTERNS
  90.  */
  91. #ifdef XDEBUG
  92. extern int event_error_handler ();
  93. extern int io_error_handler ();
  94. #endif /* XDEBUG */
  95. extern XcmsColorSpace XcmsTekHVCColorSpace;
  96.  
  97. /*
  98.  *        GLOBALS
  99.  */
  100. #ifdef DEC
  101. #  define GLOBAL        global
  102. #else
  103. #  define GLOBAL
  104. #endif
  105. GLOBAL char *exeName = "";
  106. GLOBAL char *versionString = "xtici version 1.0a";
  107. GLOBAL char *dpy_name = NULL;
  108. /* colormap size based on visual selected */
  109. GLOBAL int mapSize = 0;
  110. GLOBAL Time lastTime = 0;
  111.  
  112. /*
  113.  *        LOCAL VARIABLES
  114.  */
  115. #ifdef DEBUG
  116. #  define STATIC
  117. #else
  118. #  define STATIC        static
  119. #endif
  120.  
  121. STATIC XtConvertArgRec convertArgs[] = {
  122.     {XtWidgetBaseOffset, (XtPointer)XtOffset(Widget, core.screen), sizeof(Screen *)},
  123.     {XtWidgetBaseOffset, (XtPointer)XtOffset(Widget, core.colormap), sizeof(Colormap)}
  124. };
  125.  
  126. /*
  127.  * Replacement string-to-pixel converter that assumes all colormap
  128.  * entries are pre-allocated.  It simply translates the string into a color
  129.  * description, then stores that description into the next available
  130.  * color cell.
  131.  */
  132. STATIC String XtNwrongParameters = "wrongParameters";
  133. STATIC String XtCHvcCvtStringToPixelError = "HvcCvtStringToPixelError";
  134.  
  135. #define CvtDone(type, value)                \
  136. {                            \
  137.     if (to->addr != NULL) {                \
  138.     if (to->size < sizeof(type)) {            \
  139.         to->size = sizeof(type);            \
  140.         return False;                \
  141.     } else {                    \
  142.         *(type*)(to->addr) = (value);        \
  143.     }                        \
  144.     } else {                        \
  145.     STATIC type static_val;                \
  146.     static_val = (value);                \
  147.     to->addr = (XtPointer)&static_val;        \
  148.     }                            \
  149.     to->size = sizeof(type);                \
  150.     RegisterIfPixel(*((Pixel *)(to->addr)));            \
  151.     return True;                    \
  152. }
  153.  
  154. STATIC int CompareISOLatin1(first, second)
  155. char *first, *second;
  156. {
  157.     register unsigned char *ap, *bp;
  158.  
  159.     for (ap = (unsigned char *) first, bp = (unsigned char *) second;
  160.     *ap && *bp; ap++, bp++) {
  161.     register unsigned char a, b;
  162.  
  163.     if ((a = *ap) != (b = *bp)) {
  164.         /* try lowercasing and try again */
  165.         if ((a >= XK_A) && (a <= XK_Z))
  166.         a += (XK_a - XK_A);
  167.         else if ((a >= XK_Agrave) && (a <= XK_Odiaeresis))
  168.         a += (XK_agrave - XK_Agrave);
  169.         else if ((a >= XK_Ooblique) && (a <= XK_Thorn))
  170.         a += (XK_oslash - XK_Ooblique);
  171.  
  172.         if ((b >= XK_A) && (b <= XK_Z))
  173.         b += (XK_a - XK_A);
  174.         else if ((b >= XK_Agrave) && (b <= XK_Odiaeresis))
  175.         b += (XK_agrave - XK_Agrave);
  176.         else if ((b >= XK_Ooblique) && (b <= XK_Thorn))
  177.         b += (XK_oslash - XK_Ooblique);
  178.  
  179.         if (a != b) break;
  180.     }
  181.     }
  182.     return (((int) *bp) - ((int) *ap));
  183. }
  184.  
  185. /************************************************************************
  186.  *                                                                      *
  187.  *                      PRIVATE ROUTINES                                *
  188.  *                                                                      *
  189.  ************************************************************************/
  190. STATIC Boolean IsReveseVideo(dsply)
  191. Display *dsply;
  192. {
  193.     XrmDatabase db;
  194.     String name, class;
  195.     XrmName name_list[3];
  196.     XrmName class_list[3];
  197.     XrmRepresentation type;
  198.     XrmValue val;
  199.     XrmQuark QString;
  200.  
  201.     db = XtScreenDatabase(DefaultScreenOfDisplay(dsply));
  202.     XtGetApplicationNameAndClass(dsply, &name, &class);
  203.     name_list[0] = XrmStringToQuark(name);
  204.     name_list[1] = XrmStringToQuark("reverseVideo");
  205.     class_list[0] = XrmStringToQuark(class);
  206.     class_list[1] = XrmStringToQuark("ReverseVideo");
  207.     name_list[2] = class_list[2] = NULLQUARK;
  208.     QString = XrmStringToQuark(XtRString);
  209.     if (XrmQGetResource(db, name_list, class_list, &type, &val) &&
  210.     type == QString) {
  211.     /* printf("We found reverse video on.\n"); */
  212.     return (True);
  213.     }
  214.     /* printf("We found reverse video off.\n"); */
  215.     return (False);
  216. }
  217.  
  218. /* ARGSUSED */
  219. STATIC Boolean HvcCvtStringToPixel(dsply, args, count, from, to, cdata)
  220. Display        *dsply;
  221. XrmValuePtr args;
  222. Cardinal    *count;
  223. XrmValuePtr from, to;
  224. XtPointer   *cdata;
  225. {
  226.     Display        *pDpy;
  227.     String        str = (String)from->addr;
  228.     XcmsColor        change;
  229.     STATIC XColor   target, screenColor;
  230.     Screen        *screen;
  231.     XtAppContext    ac;
  232.     Colormap        map;
  233.     Status        stat;
  234.     String        params[1];
  235.     Cardinal        num_params;
  236.  
  237.     screen = *((Screen**)args[0].addr);
  238.     map = *((Colormap *)args[1].addr);
  239.     /**************************************************************************
  240.     * TODO: sometimes this is passing in NULL values.  I have tracked this
  241.     * to _XtConvert attempting to convert a string into pixel using a gadget.
  242.     * The problem is that a gadget does not have a screen or colormap,
  243.     * so garbage is loaded into the args.  I am lucky that the garbage happens
  244.     * to be zero, so this is easy to detect.
  245.     * Need to find out why a gadget is being called to do this -
  246.     * the conversion should be done by the parent manager and inherited by
  247.     * the gadget!.  This might have something to do with resetting the colormap
  248.     * and visual.
  249.     **************************************************************************/
  250.     if (!screen || !map) {
  251.     if (!screen) 
  252.             screen = DefaultScreenOfDisplay(dpy);
  253.     pDpy = dpy;
  254.         map = cmap;
  255.     } else {
  256.     if (map != cmap)
  257.             map = cmap;
  258.     if (dpy != DisplayOfScreen(screen)) {
  259.         pDpy = dpy;
  260.         screen = DefaultScreenOfDisplay(dpy);
  261.     } else 
  262.         pDpy = DisplayOfScreen(screen);
  263.     }
  264.     ac = XtDisplayToApplicationContext(pDpy);
  265.  
  266.     if (*count != 2) {
  267.     num_params = 0;
  268.     XtAppWarningMsg(ac, XtNwrongParameters, "cvtStringToPixel",
  269.                 XtCHvcCvtStringToPixelError,
  270.     "String to pixel conversion needs screen and colormap arguments",
  271.             (String *)NULL, &num_params);
  272.     }
  273.  
  274.     if (CompareISOLatin1(str, XtDefaultBackground) == 0) {
  275.     if (IsReveseVideo(pDpy))
  276.         CvtDone(Pixel, BlackPixelOfScreen(screen))
  277.     else
  278.         CvtDone(Pixel, WhitePixelOfScreen(screen))
  279.     } else if (CompareISOLatin1(str, XtDefaultForeground) == 0) {
  280.     if (IsReveseVideo(pDpy))
  281.         CvtDone(Pixel, WhitePixelOfScreen(screen))
  282.     else
  283.         CvtDone(Pixel, BlackPixelOfScreen(screen))
  284.     }
  285.  
  286.     /* use parse color to allow rgb database colors and # formatted colors */
  287.     if (*str == '#') {
  288.     stat = XParseColor(pDpy, map, str, &target);
  289.     if (stat == 0) {
  290.         params[0] = str;
  291.         num_params = 1;        
  292.         XtAppWarningMsg(ac, "badFormat", "cvtStringToPixel",
  293.                 XtCHvcCvtStringToPixelError,
  294.             "RGB color specification \"%s\" has invalid format",
  295.                 params, &num_params);
  296.         return False;
  297.     } 
  298.     /*
  299.      * To minimize flashing, allocate the color in the default map,
  300.      * then store the color into that pixel of the target map.
  301.      */
  302.     stat = XAllocColor(pDpy, DefaultColormapOfScreen(screen), &target);
  303.     } else {
  304.     stat = XAllocNamedColor(pDpy, DefaultColormapOfScreen(screen), 
  305.                  (char*)str, &screenColor, &target);
  306.     }
  307.  
  308.     if (stat == 0) {
  309.     String msg, type;
  310.     params[0] = str;
  311.     num_params = 1;
  312.     /* Server returns a specific error code but Xlib discards it.  Ugh */
  313.     if (*str == '#' ||
  314.         XLookupColor(pDpy, DefaultColormapOfScreen(screen), (char*)str,
  315.              &target, &screenColor)) {
  316.         type = "noColormap";
  317.         msg = "Cannot allocate colormap entry for \"%s\"";
  318.     } else {
  319.         type = "badValue";
  320.         msg = "Color name \"%s\" is not defined in server database";
  321.     }
  322.     XtAppWarningMsg(ac, type, "cvtStringToPixel",
  323.             XtCHvcCvtStringToPixelError, msg, params, &num_params);
  324.     return False;
  325.     }
  326.  
  327.     XStoreColor(pDpy, map, &target);
  328.  
  329.     /* Get the current color in HVC space (from default map) */
  330.     change.pixel = target.pixel;
  331.     change.format = XcmsTekHVCFormat;
  332.     change.spec.TekHVC.H =change.spec.TekHVC.V =change.spec.TekHVC.C =0.0;
  333.  
  334.     if (XcmsQueryColor(pDpy, DefaultColormapOfScreen(screen), &change, 
  335.                XcmsTekHVCFormat) == XcmsFailure){
  336. #ifdef XDEBUG
  337.     fprintf(stderr, "Warning: XcmsQueryColor failed in HvcConvertStringtoPixel\n");
  338. #endif
  339.     }
  340.     /* Now change private map to match default */
  341.     ChangeHvcCells(&change, 1, DECREASE_CHROMA);
  342.  
  343.     /* Remember this is used in the interface */
  344.     CvtDone(Pixel, target.pixel)
  345. }
  346.  
  347.  
  348. /*****************************************************************************
  349.  *
  350.  * Replacement routine for XtMainLoop 
  351.  *
  352.  *****************************************************************************/
  353. STATIC void MainLoop(app)
  354. XtAppContext app;
  355. {
  356.  
  357.     Boolean process;
  358.     XEvent evnt;
  359.  
  360.     for (;;) {
  361.     XtAppNextEvent(app, &evnt);
  362.  
  363.     switch (evnt.type) {
  364.     case ButtonPress:
  365.     case ButtonRelease:
  366.         /* lets keep track of time so that selection.c can work */
  367.         lastTime = ((XButtonEvent *)&evnt)->time;
  368.         /* if HandleGrab returns non-zero, it has processed the event */
  369.         if (grabState != GrabNone && HandleGrab((XButtonEvent *)&evnt))
  370.         process = False;
  371.         else
  372.         process = True;
  373.         break;
  374.     case ClientMessage:
  375.         HandleUserMessage((XClientMessageEvent *)&evnt);
  376.         process = True; /* allow rest of toolkit to take a look at it */
  377.         break;
  378.     default:
  379.         process = True;
  380.         break;
  381.     }
  382.  
  383.     if (process)
  384.         XtDispatchEvent(&evnt);
  385.     }
  386. }
  387.  
  388.  
  389. STATIC void Usage()
  390. {
  391.     Error("Usage: xtici [options]\n\
  392. Options:\n\
  393. \t-display {hostname:number.screen_number}\n\
  394. \t-huebar {empty | constant | dynamic}\n\
  395. \t-leaf {filled | empty}\n\
  396. \t-gamutProc {closest | chroma | value}\n");
  397. }
  398.  
  399. STATIC void ParseArgs(ct, list)
  400. int ct;
  401. char **list;
  402. {
  403.     int i;
  404.  
  405.     for (i = 1; i < ct; i++) {
  406.     if (!strcmp(list[i], "-huebar")) {
  407.         i++;
  408.         if (!strcmp(list[i], "empty"))
  409.         huebarState = HuebarEmpty;
  410.         else if ((!strcmp(list[i], "constant")) && (allowFill <= FillHuebar))
  411.         huebarState = HuebarConstant;
  412.         else if ((!strcmp(list[i], "dynamic")) && (allowFill <= FillHuebar))
  413.         huebarState = HuebarDynamic;
  414.         else
  415.         Usage();
  416.     } else if (!strcmp(list[i], "-leaf")) {
  417.         i++;
  418.         if (!strcmp(list[i], "empty"))
  419.         ;
  420.         else if (!strcmp(list[i], "filled"))
  421.         leafState |= LeafFilled;
  422.         else
  423.         Usage();
  424.     } else if (!strcmp(list[i], "-gamutProc")) {
  425.         i++;
  426.         if (!strcmp(list[i], "closest")) 
  427.         GamutComp = GamutCompClosest;
  428.         else if (!strcmp(list[i], "chroma"))
  429.         GamutComp = GamutCompChroma;
  430.         else if (!strcmp(list[i], "value"))
  431.         GamutComp = GamutCompValue;
  432.         else
  433.         Usage();
  434.     } else if (!strcmp(list[i], "-display")) {
  435.         i++;
  436.         dpy_name = list[i];
  437.     } else
  438.         Usage();
  439.     }
  440. }
  441.  
  442.  
  443. /*****************************************************************************
  444.  *
  445.  * This is the main executable.
  446.  *
  447.  *****************************************************************************/
  448. main(argc, argv)
  449. int argc;
  450. char **argv;
  451. {
  452.     Widget top, LayoutWidgets();
  453.     XtAppContext app;
  454.     extern void CreateColormap();   /* A series of routines from resources.c */
  455.     extern void CreateCursors();
  456.     extern void CreateAtoms();
  457.     extern void ValidateDisplay();
  458.     extern void Leave();
  459.     STATIC XtActionsRec leave[] = {
  460.         { "leave", Leave },
  461.     };
  462.  
  463.     /* reqVisual is forced to be PseudoColor */
  464.     reqVisual = PseudoColor;
  465.  
  466.     /* extract executable name */
  467.     exeName = strrchr(argv[0], '/');
  468.     if (exeName)
  469.     exeName++;  /* move past last / in pathname */
  470.     else
  471.     exeName = argv[0];    /* no path portion in name */
  472.     ParseArgs(argc, argv);
  473.  
  474.     /* Init the toolkit */
  475.     /* Startup takes a long time, so print messages to advise of status */
  476.     printf("Initializing toolkit ...\n");
  477.     XtToolkitInitialize();
  478.  
  479.     /* Open and validate display */
  480.     app = XtCreateApplicationContext();
  481.     if (!(dpy = XtOpenDisplay(app, dpy_name, exeName, "Hvc", NULL, 0, 
  482.                   &argc, argv))) {
  483.     Error("No display opened, exiting the program.");
  484.     }
  485.  
  486. #ifdef XDEBUG
  487.     XSetErrorHandler (event_error_handler);
  488.     XSetIOErrorHandler (io_error_handler);
  489.     XSynchronize (dpy, 1);
  490. #endif /* XDEBUG */
  491.  
  492.     if (!dpy)
  493.     Error("Cannot open display.");
  494.  
  495.     /* set the default CCC and check for PseudoColor Visual */
  496.     ValidateDisplay();
  497.  
  498.     if (!XcmsAddColorSpace(&XcmsTekHVCColorSpace)) {
  499.     Error("Failed to find or initialize the TekHVC color space.");
  500.     }
  501.     
  502.     /*
  503.      * Replace the string-to-pixel converter so that we know which colors
  504.      * are used by the interface so we can warn people about certain changes.
  505.      */
  506.     XtSetTypeConverter(XtRString, XtRPixel, HvcCvtStringToPixel,
  507.               convertArgs, XtNumber(convertArgs),
  508.               XtCacheNone, (XtDestructor)NULL);
  509.  
  510.     /* Create resources which do not need windows */
  511.     CreateColormap();
  512.     CreateCursors();
  513.     CreateAtoms();
  514.  
  515.     /* add some actions for gesture completion */
  516.     XtAppAddActions (app, leave, XtNumber(leave));
  517.  
  518.     /* Layout the widgets for the entire interface */
  519.     printf("Creating widgets ...\n");
  520.     top = LayoutWidgets();
  521.  
  522.     /* Setup, must happen after widgets are created */
  523.     SetFirstIndex();
  524.  
  525.     /*
  526.      * Create the windows, and set their attributes according
  527.      * to the Widget data.
  528.      */
  529.     printf("Realizing widgets ...\n");
  530.     XtRealizeWidget(top);
  531.  
  532.     /* There does not seem to be a cursor widget attribute, so do this here */
  533.     SetCursor(normalCursor);
  534.  
  535.     /* use this window to take ownership of the selection */
  536.     InitSelection(top);
  537.  
  538.     /* Build some resources */
  539.     LeafRealize();
  540.  
  541.     /* Make sure the leaf colormap and the local colormap are the same. */
  542.     if (leaf->core.colormap != cmap) {
  543.     leaf->core.colormap = cmap;
  544.     }
  545.  
  546.     /* Now process the events. */
  547.     printf("Running xtici ...\n");
  548.     MainLoop(app);
  549.     /*NOTREACHED*/
  550. }
  551.