home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xlibpr3.zip / basicwin / color / basic.cc.c next >
C/C++ Source or Header  |  1991-10-06  |  13KB  |  431 lines

  1. /*
  2.  * Copyright 1989 O'Reilly and Associates, Inc.
  3.  * See ../Copyright for complete rights and liability information.
  4.  */
  5. #include <X11/Xlib.h>
  6. #include <X11/Xutil.h>
  7. #include <X11/Xos.h>
  8. #include <X11/Xatom.h>
  9.  
  10. #include <stdio.h>
  11.  
  12. #include "../bitmaps/icon_bitmap"
  13. #define BITMAPDEPTH 1
  14. #define MAX_COLORS 3
  15.  
  16. /* Display and screen_num are used as arguments to nearly every Xlib routine, 
  17.  * so it simplifies routine calls to declare them global.  If there were 
  18.  * additional source files, these variables would be declared extern in
  19.  * them. */
  20. Display *display;
  21. int screen_num;
  22. Screen *screen_ptr;
  23.  
  24. /* pixel values */
  25. unsigned long foreground_pixel, background_pixel, border_pixel;
  26.  
  27. /* values for window_size in main, is window big enough to be useful? */
  28. #define SMALL 1
  29. #define OK 0
  30.  
  31. char *progname;
  32.  
  33. #define USE_DEFAULT_COLORMAP 1
  34. #define USE_STANDARD_COLORMAP 0
  35.  
  36. void main(argc, argv)
  37. int argc;
  38. char **argv;
  39. {
  40.     Window win;
  41.     unsigned int width, height, x, y;     /* window size and position */
  42.     unsigned int borderwidth = 4;          /* four pixels */
  43.     unsigned int display_width, display_height;
  44.     unsigned int icon_width, icon_height;
  45.     char *window_name = "Basic Window Program";
  46.     char *icon_name = "basicwin";
  47.     Pixmap icon_pixmap;
  48.     XSizeHints size_hints;
  49.     XEvent report;
  50.     GC gc;
  51.     XFontStruct *font_info;
  52.     char *display_name = NULL;
  53.     int window_size = 0;    /* OK, or too SMALL to display contents */
  54.     XStandardColormap **best_map_info;
  55.     XColor *exact_defs;
  56.     XSetWindowAttributes attrib;
  57.     unsigned long attribmask;
  58.     int i, j, k, l;
  59.     int ncells;
  60.     XVisualInfo *vlist, vinfo_template, *v;
  61.     int num_vis;
  62.     int count;
  63.     Visual *visual;
  64.     int strategy = USE_STANDARD_COLORMAP;
  65.  
  66.     progname = argv[0];
  67.  
  68.     /* connect to X server */
  69.  
  70.     if ( (display=XOpenDisplay(display_name)) == NULL )
  71.     {
  72.         (void) fprintf( stderr, 
  73.                 "basicwin: cannot connect to X server %s\\n",
  74.                 XDisplayName(display_name));
  75.         exit( -1 );
  76.     }
  77.  
  78.     /* get screen_num size from display structure macro */
  79.     screen_num = DefaultScreen(display);
  80.     screen_ptr = DefaultScreenOfDisplay(display);
  81.     display_width = DisplayWidth(display, screen_num);
  82.     display_height = DisplayHeight(display, screen_num);
  83.     visual = DefaultVisual(display, screen_num);
  84.  
  85.     /* place window */
  86.     x = display_width/3, y = display_height/3;
  87.  
  88.     /* size window with enough room for text */
  89.     width = display_width/3, height = display_height/4;
  90.  
  91.     if (XGetRGBColormaps(display, RootWindow(display,
  92.             screen_num), best_map_info, &count, 
  93.             XA_RGB_BEST_MAP) == 0) {
  94.         printf("%s: RGB_BEST_MAP property not set.\n", argv[0]);
  95.         /* give up standard colormaps: use one of 
  96.          * the basic color strategies */
  97.         get_colors();
  98.         strategy = USE_DEFAULT_COLORMAP;
  99.     }
  100.     else if (best_map_info[0]->colormap) {
  101.         /* Someone else created the map we need.
  102.          * Make sure it's valid, then
  103.          * we'll use it below. */
  104.         if (best_map_info[0]->red_max == 0) {
  105.             printf("%s: Standard colormap property", 
  106.                     " is set but is missing data.\n", 
  107.                     argv[0]);
  108.             strategy = USE_DEFAULT_COLORMAP;
  109.         }
  110.         attrib.colormap = best_map_info[0]->colormap;
  111.     }
  112.     else if (best_map_info[0]->visualid == 0) {
  113.         printf("%s: Standard colormap property is set but is missing data.\n", argv[0]);
  114.         /* Some systems define the properties, but don't place
  115.          * any data in them.  This is a server bug, but we'll
  116.          * check for it anyway.  */
  117.         /* Fall back on a basic color strategy. */
  118.         strategy = USE_DEFAULT_COLORMAP;
  119.     }
  120.     else {
  121.         /* 
  122.          * Got info, but the described colormap has not been
  123.          * created yet.  Create it and allocate all cells read/write.
  124.          */
  125.  
  126.         /* XCreateColormap requires a visual argument (pointer
  127.          * to a Visual structure).
  128.          * However, the XStandardColormap structure returns
  129.         * a VisualID, which might not be the default visual.  
  130.         * Converting between these two is painful.
  131.          */
  132.         vlist = XGetVisualInfo(display, VisualNoMask, &vinfo_template, &num_vis);
  133.         for (v = vlist; v < vlist + num_vis; v++) {
  134.             if (v->visualid == best_map_info[0]->visualid) {
  135.                 visual = v->visual;
  136.                 break;
  137.             }
  138.         }
  139.  
  140.         best_map_info[0]->colormap = XCreateColormap(display, RootWindow(display, screen_num), visual, AllocAll);
  141.  
  142.         if (best_map_info[0]->colormap == DefaultColormap(display, screen_num)) {
  143.             printf("%s: hardware colormap is immutable: cannot create new colormap.\n", argv[0]);
  144.         }
  145.  
  146.         attrib.colormap = best_map_info[0]->colormap;
  147.  
  148.         ncells = best_map_info[0]->base_pixel + 
  149.                 ((best_map_info[0]->red_max + 1) * 
  150.                 (best_map_info[0]->green_max + 1) * 
  151.                 (best_map_info[0]->blue_max + 1));
  152.  
  153.         exact_defs = (XColor *) calloc(sizeof(XColor), ncells); 
  154.  
  155.         /* permute the levels of red, green and blue */
  156.         l = best_map_info[0]->base_pixel;
  157.         for (i = 0; i < best_map_info[0]->blue_max; i++) {
  158.             for (j = 0; j < best_map_info[0]->green_max; j++) {
  159.                 for (k = 0; k < best_map_info[0]->red_max; k++) {
  160.                     exact_defs[l].blue = 65535 * i / best_map_info[0]->blue_max;
  161.                     exact_defs[l].green = 65535 * j / best_map_info[0]->green_max;
  162.                     exact_defs[l].red = 65535 * k / best_map_info[0]->red_max;
  163.                     l++;
  164.                 }
  165.             }
  166.         }
  167.  
  168.         XStoreColors (display, best_map_info[0]->colormap, exact_defs, ncells);
  169.         
  170.         /* If to be used in a window not created with the
  171.          * default visual, must create the window first
  172.          * and use instead of RootWindow in this call.
  173.          * Here we assume the default visual. */
  174.         XSetStandardColormap(display, RootWindow(display, screen_num), best_map_info[0], XA_RGB_BEST_MAP);
  175.     }
  176.  
  177.     if (strategy == USE_STANDARD_COLORMAP) {
  178.         /* We must not have called get_colors above, must 
  179.          * be using standard colormaps strategy.
  180.          */
  181.  
  182.         /* note that we act like we have already allocated pixel 
  183.          * values, even though actually another client did. */
  184.         background_pixel = best_map_info[0]->base_pixel  +
  185.                 (best_map_info[0]->red_max * best_map_info[0]->red_mult) +
  186.                 (best_map_info[0]->green_max * best_map_info[0]->green_mult) +
  187.                 (best_map_info[0]->blue_max * best_map_info[0]->blue_mult);
  188.  
  189.         attribmask = CWBackPixel | CWColormap;
  190.  
  191.         foreground_pixel = (best_map_info[0]->green_max * 
  192.                 best_map_info[0]->green_mult / 2) + 
  193.                 best_map_info[0]->base_pixel;
  194.         
  195.         border_pixel = (best_map_info[0]->blue_max * 
  196.                 best_map_info[0]->blue_mult / 2) + 
  197.                 best_map_info[0]->base_pixel;
  198.     }
  199.  
  200.     /* create opaque window */
  201.     win = XCreateWindow(display, RootWindow(display,screen_num), x, y, 
  202.             width, height, borderwidth, 
  203.             DefaultDepth(display, screen_num), 
  204.             InputOutput, visual, attribmask, &attrib);
  205.  
  206.     /* Create pixmap of depth 1 (bitmap) for icon */
  207.     icon_pixmap = XCreateBitmapFromData(display, win, icon_bitmap_bits, 
  208.             icon_bitmap_width, icon_bitmap_height);
  209.  
  210.     /* Set resize hints */
  211.     size_hints.flags = PPosition | PSize | PMinSize;
  212.     size_hints.x = x;
  213.     size_hints.y = y;
  214.     size_hints.width = width;
  215.     size_hints.height = height;
  216.     size_hints.min_width = 350;
  217.     size_hints.min_height = 250;
  218.  
  219.     /* set Properties for window manager (always before mapping) */
  220.     XSetStandardProperties(display, win, window_name, icon_name, 
  221.         icon_pixmap, argv, argc, &size_hints);
  222.  
  223.     /* Select event types wanted */
  224.     XSelectInput(display, win, ExposureMask | KeyPressMask | 
  225.             ButtonPressMask | StructureNotifyMask);
  226.  
  227.     load_font(&font_info);
  228.  
  229.     /* create GC for text and drawing */
  230.     get_GC(win, &gc, font_info);
  231.  
  232.     /* Display window */
  233.     XMapWindow(display, win);
  234.  
  235.     /* get events, use first to display text and graphics */
  236.     while (1)  {
  237.         XNextEvent(display, &report);
  238.         switch  (report.type) {
  239.         case Expose:
  240.             /* get all other Expose events on the queue */
  241.             while (XCheckTypedEvent(display, Expose, &report));
  242.             if (window_size == SMALL)
  243.                    TooSmall(win, gc, font_info);
  244.             else {
  245.                 /* place text in window */
  246.                    place_text(win, gc, font_info, width, height);
  247.  
  248.                 /* place graphics in window, */
  249.                    place_graphics(win, gc, width, height);
  250.             }
  251.             break;
  252.         case ConfigureNotify:
  253.             /* window has been resized, change width and
  254.              * height to send to place_text and place_graphics
  255.              * in next Expose */
  256.             width = report.xconfigure.width;
  257.             height = report.xconfigure.height;
  258.             if ((width < size_hints.min_width) || 
  259.                     (height < size_hints.min_height))
  260.                 window_size = SMALL;
  261.             else
  262.                 window_size = OK;
  263.             break;
  264.         case ButtonPress:
  265.             /* trickle down into KeyPress (no break) */
  266.         case KeyPress:
  267.             XUnloadFont(display, font_info->fid);
  268.             XFreeGC(display, gc);
  269.             XCloseDisplay(display);
  270.             exit(1);
  271.         default:
  272.             /* all events selected by StructureNotifyMask
  273.              * except ConfigureNotify are thrown away here,
  274.              * since nothing is done with them */
  275.             break;
  276.         } /* end switch */
  277.     } /* end while */
  278. }
  279.  
  280. get_GC(win, gc, font_info)
  281. Window win;
  282. GC *gc;
  283. XFontStruct *font_info;
  284. {
  285.     unsigned long valuemask = 0; /* ignore XGCvalues and use defaults */
  286.     XGCValues values;
  287.     unsigned int line_width = 6;
  288.     int line_style = LineOnOffDash;
  289.     int cap_style = CapRound;
  290.     int join_style = JoinRound;
  291.     int dash_offset = 0;
  292.     static char dash_list[] = {
  293.         12, 24    };
  294.     int list_length = 2;
  295.  
  296.     /* Create default Graphics Context */
  297.     *gc = XCreateGC(display, win, valuemask, &values);
  298.  
  299.     /* specify font */
  300.     XSetFont(display, *gc, font_info->fid);
  301.  
  302.     /* specify black foreground since default may be white on white */
  303.     XSetForeground(display, *gc, foreground_pixel);
  304.  
  305.     /* set line attributes */
  306.     XSetLineAttributes(display, *gc, line_width, line_style, cap_style, 
  307.             join_style);
  308.  
  309.     /* set dashes to be line_width in length */
  310.     XSetDashes(display, *gc, dash_offset, dash_list, list_length);
  311. }
  312.  
  313. load_font(font_info)
  314. XFontStruct **font_info;
  315. {
  316.     char *fontname = "9x15";
  317.  
  318.     /* Access font */
  319.     if ((*font_info = XLoadQueryFont(display,fontname)) == NULL)
  320.     {
  321.         (void) fprintf( stderr, "Basic: Cannot open 9x15 font\\n");
  322.         exit( -1 );
  323.     }
  324. }
  325.  
  326. place_text(win, gc, font_info, win_width, win_height)
  327. Window win;
  328. GC gc;
  329. XFontStruct *font_info;
  330. unsigned int win_width, win_height;
  331. {
  332.     int y = 20;     /* offset from corner of window*/
  333.     char *string1 = "Hi! I'm a window, who are you?";
  334.     char *string2 = "To terminate program; Press any key";
  335.     char *string3 = "or button while in this window.";
  336.     char *string4 = "Screen Dimensions:";
  337.     int len1, len2, len3, len4;
  338.     int width1, width2, width3;
  339.     char cd_height[50], cd_width[50], cd_depth[50];
  340.     int font_height;
  341.     int initial_y_offset, x_offset;
  342.  
  343.  
  344.     /* need length for both XTextWidth and XDrawString */
  345.     len1 = strlen(string1);
  346.     len2 = strlen(string2);
  347.     len3 = strlen(string3);
  348.  
  349.     /* get string widths for centering */
  350.     width1 = XTextWidth(font_info, string1, len1);
  351.     width2 = XTextWidth(font_info, string2, len2);
  352.     width3 = XTextWidth(font_info, string3, len3);
  353.  
  354.     /* output text, centered on each line */
  355.     XDrawString(display,win,gc,(win_width - width1)/2,y,string1,len1);
  356.     XDrawString(display,win,gc,(win_width - width2)/2, 
  357.             (int)(win_height - 35),string2,len2);
  358.     XDrawString(display,win,gc,(win_width - width3)/2, 
  359.             (int)(win_height - 15),string3,len3);
  360.  
  361.     /* copy numbers into string variables */
  362.     (void) sprintf(cd_height, " Height - %d pixels", 
  363.             DisplayHeight(display,screen_num));
  364.     (void) sprintf(cd_width, " Width  - %d pixels", 
  365.             DisplayWidth(display,screen_num));
  366.     (void) sprintf(cd_depth, " Depth  - %d plane(s)", 
  367.             DefaultDepth(display, screen_num));
  368.  
  369.     /* reuse these for same purpose */
  370.     len4 = strlen(string4);
  371.     len1 = strlen(cd_height);
  372.     len2 = strlen(cd_width);
  373.     len3 = strlen(cd_depth);
  374.  
  375.     font_height = font_info->max_bounds.ascent + 
  376.             font_info->max_bounds.descent;
  377.  
  378.     /* To center strings vertically, we place the first string
  379.      * so that the top of it is two font_heights above the center
  380.      * of the window.  Since the baseline of the string is what we
  381.      * need to locate for XDrawString, and the baseline is one
  382.      * font_info->max_bounds.ascent below the top of the chacter,
  383.      * the final offset of the origin up from the center of the 
  384.      * window is one font_height + one descent. */
  385.  
  386.     initial_y_offset = win_height/2 - font_height - 
  387.             font_info->max_bounds.descent;
  388.     x_offset = (int) win_width/4;
  389.     XDrawString(display, win, gc, x_offset, (int) initial_y_offset, 
  390.             string4,len4);
  391.  
  392.     XDrawString(display, win, gc, x_offset, (int) initial_y_offset + 
  393.             font_height,cd_height,len1);
  394.     XDrawString(display, win, gc, x_offset, (int) initial_y_offset + 
  395.             2 * font_height,cd_width,len2);
  396.     XDrawString(display, win, gc, x_offset, (int) initial_y_offset + 
  397.             3 * font_height,cd_depth,len3);
  398. }
  399.  
  400.  
  401. place_graphics(win, gc, window_width, window_height)
  402. Window win;
  403. GC gc;
  404. unsigned int window_width, window_height;
  405. {
  406.     int x, y;
  407.     int width, height;
  408.  
  409.     height = window_height/2;
  410.     width = 3 * window_width/4;
  411.     x = window_width/2 - width/2;  /* center */
  412.     y = window_height/2 - height/2;
  413.     XDrawRectangle(display, win, gc, x, y, width, height);
  414. }
  415.  
  416. TooSmall(win, gc, font_info)
  417. Window win;
  418. GC gc;
  419. XFontStruct *font_info;
  420. {
  421.     char *string1 = "Too Small";
  422.     int y_offset, x_offset;
  423.  
  424.     y_offset = font_info->max_bounds.ascent + 2;
  425.     x_offset = 2;
  426.  
  427.     /* output text, centered on each line */
  428.     XDrawString(display, win, gc, x_offset, y_offset, string1, 
  429.             strlen(string1));
  430. }
  431.