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 / popup / basicwin.c next >
C/C++ Source or Header  |  1989-11-27  |  13KB  |  409 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/keysym.h>
  9.  
  10. #include <stdio.h>
  11.  
  12. #include "../bitmaps/icon_bitmap"
  13. #define BITMAPDEPTH 1
  14. #define SMALL 1
  15. #define OK 0
  16. #define MAX_POPUP_STRING_LENGTH 40
  17. #define MAX_MAPPED_STRING_LENGTH 10
  18.  
  19. /* These are used as arguments to nearly every Xlib routine, so it saves 
  20.  * routine arguments to declare them global.  If there were 
  21.  * additional source files, they would be declared extern there. */
  22. Display *display;
  23. int screen;
  24.  
  25. void main(argc, argv)
  26. int argc;
  27. char **argv;
  28. {
  29.     Window win;
  30.     unsigned int width, height, x = 0, y = 0;     /* window size and position */
  31.     unsigned int border_width = 4;    /* four pixels */
  32.     unsigned int display_width, display_height;
  33.     unsigned int icon_width, icon_height;
  34.     char *window_name = "basicwin";
  35.     char *icon_name = "";
  36.     Pixmap icon_pixmap;
  37.     XSizeHints size_hints;
  38.     XIconSize *size_list;
  39.     int count;
  40.     XEvent report;
  41.     GC gc;
  42.     XFontStruct *font_info;
  43.     char *display_name = NULL;
  44.     int window_size = 0;    /* OK, or too SMALL to display contents */
  45.  
  46.     /* the following are for pop-up window */
  47.     static Window pop_win;
  48.     char buffer[MAX_MAPPED_STRING_LENGTH];
  49.     int bufsize=MAX_MAPPED_STRING_LENGTH;
  50.     int start_x, start_y;
  51.     KeySym keysym;
  52.     XComposeStatus compose;
  53.     int totalcount;
  54.     unsigned int pop_width, pop_height;
  55.     char string[MAX_POPUP_STRING_LENGTH];
  56.     int popped = False;
  57.     int length;
  58.  
  59.     /* added for key rebinding test */
  60. KeySym modlist[2];   /* array of modifier keysyms */
  61. unsigned int string_length;
  62. unsigned int list_length;
  63.  
  64.     /* connect to X server */
  65.  
  66.     if ( (display=XOpenDisplay(display_name)) == NULL )
  67.     {
  68.         (void) fprintf( stderr, "basicwin: cannot connect to X server %s\n", XDisplayName(display_name));
  69.         exit( -1 );
  70.     }
  71.  
  72.     /* get screen size from display structure macro */
  73.     screen = DefaultScreen(display);
  74.     display_width = DisplayWidth(display, screen);
  75.     display_height = DisplayHeight(display, screen);
  76.  
  77.     /* note that x and y are 0, since the default position of the window
  78.      * is the top left corner of the root. This is fine since the window
  79.      * manager often allows the user to position the window before mapping it. */
  80.  
  81.     /* size window with enough room for text */
  82.     width = display_width/3, height = display_height/4;
  83.  
  84.     /* create opaque window */
  85.     win = XCreateSimpleWindow(display, RootWindow(display,screen), x, y, width, height, border_width, BlackPixel(display,
  86.         screen), WhitePixel(display,screen));
  87.  
  88.  
  89. /* map Shift-F1 to "STOP"  */
  90. string_length = 4;
  91. list_length = 1;
  92. modlist[1] = XK_Shift_R;        /* Do right shift key */
  93. XRebindKeysym(display, XK_F1, modlist, list_length, "STOP", string_length);
  94. modlist[1] = XK_Shift_L;        /* Do left shift key */
  95. XRebindKeysym(display, XK_F1, modlist, list_length, "STOP", string_length);
  96.  
  97. /* map Control-Shift-F1 to "ABORT"  */
  98. string_length = 5;
  99. list_length = 2;
  100. modlist[1] = XK_Shift_R; modlist[2] = XK_Control_R; /* Both Right Pressed */
  101. XRebindKeysym(display, XK_F1, modlist, list_length, "STOP", string_length);
  102. modlist[1] = XK_Shift_L; modlist[2] = XK_Control_R; /* Left Shift, 
  103.                                         Right Control */
  104. XRebindKeysym(display, XK_F1, modlist, list_length, "STOP", string_length);
  105. modlist[1] = XK_Shift_R; modlist[2] = XK_Control_L; /* Right Shift, 
  106.                                         Left Control */
  107. XRebindKeysym(display, XK_F1, modlist, list_length, "STOP", string_length);
  108. modlist[1] = XK_Shift_L; modlist[2] = XK_Control_L; /* Both Left Pressed */
  109. XRebindKeysym(display, XK_F1, modlist, list_length, "STOP", string_length);
  110.  
  111.  
  112.     /* Create pixmap of depth 1 (bitmap) for icon */
  113.     icon_pixmap = XCreateBitmapFromData(display, win, icon_bitmap_bits, icon_bitmap_width, icon_bitmap_height);
  114.  
  115.     /* Set resize hints */
  116.     size_hints.flags = PPosition | PSize | PMinSize;
  117.     size_hints.x = x;
  118.     size_hints.y = y;
  119.     size_hints.width = width;
  120.     size_hints.height = height;
  121.     size_hints.min_width = 300;
  122.     size_hints.min_height = 200;
  123.  
  124.     /* set Properties for window manager (always before mapping) */
  125.     XSetStandardProperties(display, win, window_name, icon_name, 
  126.         icon_pixmap, argv, argc, &size_hints);
  127.  
  128.     /* Select event types wanted */
  129.     XSelectInput(display, win, ExposureMask | KeyPressMask | ButtonPressMask | StructureNotifyMask);
  130.  
  131.     load_font(&font_info);
  132.  
  133.     /* create GC for text and drawing */
  134.     getGC(win, &gc, font_info);
  135.  
  136.     /* Display window */
  137.     XMapWindow(display, win);
  138.  
  139.     /* get events, use first to display text and graphics */
  140.     while (1)  {
  141.         XNextEvent(display, &report);
  142.         switch  (report.type) {
  143.         case Expose:
  144.             printf("got expose event\n");
  145.             if (report.xexpose.window == pop_win) {
  146.                 if (popped)
  147.                     XDrawString(display, pop_win, gc, start_x, 
  148.                         start_y, string, strlen(string));
  149.             }
  150.             else { /* it's the main window */
  151.                 while (XCheckTypedEvent(display, Expose, &report));
  152.                 if (window_size == SMALL)
  153.                     TooSmall(win, gc, font_info);
  154.                 else {
  155.                     /* place text in window */
  156.                     place_text(win, gc, font_info, width, height);
  157.     
  158.                     /* place graphics in window, */
  159.                     place_graphics(win, gc, width, height);
  160.                 }
  161.             }
  162.             break;
  163.         case ConfigureNotify:
  164.             printf("got configure event\n");
  165.             /* window has been resized, change width and
  166.              * height to send to place_text and place_graphics
  167.              * in next Expose */
  168.             width = report.xconfigure.width;
  169.             height = report.xconfigure.height;
  170.             if ((width < size_hints.min_width) || (height < size_hints.min_height))
  171.                 window_size = SMALL;
  172.             else
  173.                 window_size = OK;
  174.             break;
  175.         case ButtonPress:
  176.             /* put up popup window */
  177.             if (!pop_win) {  /* create it */
  178.             pop_width = MAX_POPUP_STRING_LENGTH * font_info->max_bounds.width + 4;
  179.             pop_height = font_info->max_bounds.ascent + font_info->max_bounds.descent + 4;
  180.             pop_win = XCreateSimpleWindow(display, win, x, y, pop_width, pop_height, border_width, BlackPixel(display,
  181.                         screen), WhitePixel(display, screen));
  182.             /* calculate starting position of string in window (start_x, start_y) */
  183.             start_x = 2;
  184.             start_y = font_info->max_bounds.ascent + 2;
  185.             XSelectInput(display, pop_win, ExposureMask | KeyPressMask);
  186.             XMapWindow(display, pop_win);
  187.             popped = True;
  188.             break;
  189.             }
  190.             /* trickle down into KeyPress on second press (no break) */
  191.         case KeyPress:
  192.             if (report.xkey.window == win) {
  193.                 XUnloadFont(display, font_info->fid);
  194.                 XFreeGC(display, gc);
  195.                 XCloseDisplay(display);
  196.                 exit(1);
  197.             }
  198.             else {
  199. /* pop-up a dialog box big enough for a line in specified font (which
  200.  * was already opened).  If this is the first call of 
  201.  * this routine, create a window of the appropriate size; if a 
  202.  * repeat call, resize the window to accommodate the prompt 
  203.  * and user-provided text.  Get characters until you encounter
  204.  * a carriage return, return number of characters.  Deal with 
  205.  * backspaces, etc.  Deal with Expose events on all windows 
  206.  * associated with this application.  Deal with keyboard remapping. */
  207.  
  208.                 count = XLookupString(&report, buffer, bufsize, &keysym, 
  209.                         &compose);
  210.                 /* now need to do the right thing with
  211.                  * every keysym possibility, as minimum: */
  212.                 if ((keysym == XK_Return) || (keysym == XK_KP_Enter) || (keysym == XK_Linefeed)) {
  213.                     XUnmapWindow(display, pop_win);
  214.                     popped = False;
  215.                     printf("string is %s\n", string);
  216.                     break;
  217.                 }
  218.                 else if (((keysym >= XK_KP_Space) && (keysym <= XK_KP_9))
  219.                   || ((keysym >= XK_space) && (keysym <= XK_asciitilde)))
  220.                      {
  221.                     if (strlen(string) + strlen(buffer)
  222.                        >= MAX_POPUP_STRING_LENGTH)
  223.                         XBell(display, 100);
  224.                     else 
  225.                         strcat(string, buffer);
  226.                     }
  227.                 else if ((keysym >= XK_Shift_L) && (keysym <= XK_Hyper_R))
  228.                     ;/* do nothing because its a modifier key */
  229.                 else if ((keysym >= XK_F1) && (keysym <= XK_F35))
  230.                     if (buffer == NULL)
  231.                         printf("Unmapped function key\n");
  232.                     else if (strlen(string) + strlen(buffer)
  233.                        >= MAX_POPUP_STRING_LENGTH)
  234.                         XBell(display, 100);
  235.                     else 
  236.                         strcat(string, buffer);
  237.                         
  238.                 else if ((keysym == XK_BackSpace) || (keysym == XK_Delete)) {
  239.                     if ((length = strlen(string)) > 0) {
  240.                         string[length - 1] = NULL;
  241.                         XClearWindow(display, pop_win);
  242.                     }
  243.                     else
  244.                         XBell(display, 100);
  245.                 }
  246.                 else {
  247.                     printf("keysym %s is not handled\n", XKeysymToString(keysym));
  248.                     XBell(display, 100);
  249.                 }
  250.                 XDrawString(display, pop_win, gc, start_x, 
  251.                     start_y, string, strlen(string));
  252.                 /* clear buffer so multi-character strings
  253.                  * are properly supported, even though
  254.                  * they can only be deleted on char at a
  255.                  * time */
  256.                 buffer[1] = NULL;
  257.                 break;
  258.             }
  259.         case MappingNotify:
  260.              XRefreshKeyboardMapping(&report);
  261.             break;
  262.         default:
  263.             /* all events selected by StructureNotifyMask
  264.              * except ConfigureNotify are thrown away here,
  265.              * since nothing is done with them */
  266.             break;
  267.         } /* end switch */
  268.     } /* end while */
  269. }
  270.  
  271. getGC(win, gc, font_info)
  272. Window win;
  273. GC *gc;
  274. XFontStruct *font_info;
  275. {
  276.     unsigned long valuemask = 0; /* ignore XGCvalues and use defaults */
  277.     XGCValues values;
  278.     unsigned int line_width = 6;
  279.     int line_style = LineOnOffDash;
  280.     int cap_style = CapRound;
  281.     int join_style = JoinRound;
  282.     int dash_offset = 0;
  283.     static char dash_list[] = {12, 24};
  284.     int list_length = 2;
  285.  
  286.     /* Create default Graphics Context */
  287.     *gc = XCreateGC(display, win, valuemask, &values);
  288.  
  289.     /* specify font */
  290.     XSetFont(display, *gc, font_info->fid);
  291.  
  292.     /* specify black foreground since default may be white on white */
  293.     XSetForeground(display, *gc, BlackPixel(display,screen));
  294.  
  295.     /* set line attributes */
  296.     XSetLineAttributes(display, *gc, line_width, line_style, cap_style, join_style);
  297.  
  298.     /* set dashes to be line_width in length */
  299.     XSetDashes(display, *gc, dash_offset, dash_list, list_length);
  300. }
  301.  
  302. load_font(font_info)
  303. XFontStruct **font_info;
  304. {
  305.     char *fontname = "9x15";
  306.  
  307.     /* Access font */
  308.     if ((*font_info = XLoadQueryFont(display,fontname)) == NULL)
  309.     {
  310.         (void) fprintf( stderr, "Basic: Cannot open 9x15 font\n");
  311.         exit( -1 );
  312.     }
  313. }
  314.  
  315. place_text(win, gc, font_info, win_width, win_height)
  316. Window win;
  317. GC gc;
  318. XFontStruct *font_info;
  319. unsigned int win_width, win_height;
  320. {
  321.     int y = 20;     /* offset from corner of window*/
  322.     char *string1 = "Hi! I'm a window, who are you?";
  323.     char *string2 = "To terminate program; Press any key";
  324.     char *string3 = "or button while in this window.";
  325.     char *string4 = "Screen Dimensions:";
  326.     int len1, len2, len3, len4;
  327.     int width1, width2, width3;
  328.     char cd_height[50], cd_width[50], cd_depth[50];
  329.     int font_height;
  330.     int initial_y_offset, x_offset;
  331.  
  332.  
  333.     /* need length for both XTextWidth and XDrawString */
  334.     len1 = strlen(string1);
  335.     len2 = strlen(string2);
  336.     len3 = strlen(string3);
  337.  
  338.     /* get string widths for centering */
  339.     width1 = XTextWidth(font_info, string1, len1);
  340.     width2 = XTextWidth(font_info, string2, len2);
  341.     width3 = XTextWidth(font_info, string3, len3);
  342.  
  343.     /* output text, centered on each line */
  344.     XDrawString(display,win,gc,(win_width - width1)/2,y,string1,len1);
  345.     XDrawString(display,win,gc,(win_width - width2)/2, (int)(win_height - 35),string2,len2);
  346.     XDrawString(display,win,gc,(win_width - width3)/2, (int)(win_height - 15),string3,len3);
  347.  
  348.     /* copy numbers into string variables */
  349.     (void) sprintf(cd_height, " Height - %d pixels", DisplayHeight(display,screen));
  350.     (void) sprintf(cd_width, " Width  - %d pixels", DisplayWidth(display,screen));
  351.     (void) sprintf(cd_depth, " Depth  - %d plane(s)", DefaultDepth(display, screen));
  352.  
  353.     /* reuse these for same purpose */
  354.     len4 = strlen(string4);
  355.     len1 = strlen(cd_height);
  356.     len2 = strlen(cd_width);
  357.     len3 = strlen(cd_depth);
  358.  
  359.     font_height = font_info->max_bounds.ascent + font_info->max_bounds.descent;
  360.  
  361.     /* To center strings vertically, we place the first string
  362.      * so that the top of it is two font_heights above the center
  363.      * of the window.  Since the baseline of the string is what we
  364.      * need to locate for XDrawString, and the baseline is one
  365.      * font_info->max_bounds.ascent below the top of the chacter,
  366.      * the final offset of the origin up from the center of the 
  367.      * window is one font_height + one descent. */
  368.  
  369.     initial_y_offset = win_height/2 - font_height - font_info->max_bounds.descent;
  370.     x_offset = (int) win_width/4;
  371.     XDrawString(display, win, gc, x_offset, (int) initial_y_offset, string4,len4);
  372.  
  373.     XDrawString(display, win, gc, x_offset, (int) initial_y_offset + font_height,cd_height,len1);
  374.     XDrawString(display, win, gc, x_offset, (int) initial_y_offset + 2 * font_height,cd_width,len2);
  375.     XDrawString(display, win, gc, x_offset, (int) initial_y_offset + 3 * font_height,cd_depth,len3);
  376. }
  377.  
  378.  
  379. place_graphics(win, gc, window_width, window_height)
  380. Window win;
  381. GC gc;
  382. unsigned int window_width, window_height;
  383. {
  384.     int x, y;
  385.     int width, height;
  386.  
  387.     height = window_height/2;
  388.     width = 3 * window_width/4;
  389.     x = window_width/2 - width/2;  /* center */
  390.     y = window_height/2 - height/2;
  391.     XDrawRectangle(display, win, gc, x, y, width, height);
  392. }
  393.  
  394. TooSmall(win, gc, font_info)
  395. Window win;
  396. GC gc;
  397. XFontStruct *font_info;
  398. {
  399.     char *string1 = "Too Small";
  400.     int y_offset, x_offset;
  401.  
  402.     y_offset = font_info->max_bounds.ascent + 2;
  403.     x_offset = 2;
  404.  
  405.     /* output text, centered on each line */
  406.     XDrawString(display, win, gc, x_offset, y_offset, string1, strlen(string1));
  407. }
  408.  
  409.