"Fossies" - the Fresh Open Source Software Archive

Member "pcemu/xstuff.c" (22 Jan 2001, 22381 Bytes) of package /linux/privat/old/pcemu-1.2.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "xstuff.c" see the Fossies "Dox" file reference documentation.

    1 /****************************************************************************
    2 *                                                                           *
    3 *                            Third Year Project                             *
    4 *                                                                           *
    5 *                            An IBM PC Emulator                             *
    6 *                          For Unix and X Windows                           *
    7 *                                                                           *
    8 *                             By David Hedley                               *
    9 *                                                                           *
   10 *                                                                           *
   11 * This program is Copyrighted.  Consult the file COPYRIGHT for more details *
   12 *                                                                           *
   13 ****************************************************************************/
   14 
   15 #include "global.h"
   16 
   17 #include <X11/Xlib.h>
   18 #include <X11/Xutil.h>
   19 #include <X11/Xos.h>
   20 #include <X11/Xatom.h>
   21 #include <X11/keysym.h>
   22 #include <stdio.h>
   23 
   24 #include "icon.h"
   25 /* #include "xstuff.h" */
   26 #include "vgahard.h"
   27 #include "hardware.h"
   28 #include "bios.h"
   29 #include "video.h"
   30 
   31 /*
   32 #include <sun/dkio.h>
   33 */
   34 #define BITMAPDEPTH 1
   35 
   36 void process_menu(void);
   37 void drawmenuitem(Window, GC, int, char *, int, int);
   38 void menu_selected(int);
   39 
   40 static Display *display;
   41 static int screen_num;
   42 static XFontStruct *font_info;
   43 static XFontStruct *menu_font1;
   44 static XFontStruct *menu_font2;
   45 static GC gc, cursorgc;
   46 static Pixmap under_cursor;
   47 static Window win;
   48 static XSizeHints size_hints;
   49 
   50 static int font_height;
   51 static int font_width;
   52 static int font_descent;
   53 
   54 static int menu_font_height;
   55 static int menu_font_width;
   56 static int menu_font_descent;
   57 
   58 static int cx, cy, cs, chgt;
   59 
   60 int blink, graphics;
   61 extern int mono;
   62 
   63 struct 
   64 {
   65     unsigned r,g,b;
   66 } text_cols[] = 
   67 {
   68     {0,0,0},{10,10,185},{10,195,10},{20,160,160},
   69     {167,10,10},{167,0,167},{165,165,40},{197,197,197},
   70     {100,100,100},{10,10,255},{10,255,10},{10,255,255},
   71     {255,10,10},{255,10,255},{255,255,0},{255,255,255}
   72 };
   73 
   74 unsigned col_vals[16];
   75 unsigned blink_vals[16];
   76 
   77 #ifdef AUTOEJECT
   78 void eject(void);
   79 #endif
   80 
   81 void get_colours(void)
   82 {
   83     XColor col;
   84     int i;
   85 
   86     if (mono)
   87     {
   88         col_vals[0] = BlackPixel(display, screen_num);
   89 
   90         for (i = 1; i < 16; i++)
   91             col_vals[i] = WhitePixel(display, screen_num);
   92     }
   93     else
   94     {
   95         col.flags = DoRed | DoGreen | DoBlue;
   96         for(i = 0; i < 16; i++)
   97         {
   98             col.red=text_cols[i].r << 8;
   99             col.green=text_cols[i].g << 8;
  100             col.blue=text_cols[i].b << 8;
  101             XAllocColor(display, DefaultColormap(display, screen_num),
  102                         &col);
  103             col_vals[i] = col.pixel;
  104         }
  105     }
  106 }
  107 
  108 
  109 static void x_put_cursor(unsigned x, unsigned y)
  110 {
  111     if (chgt < 1)
  112         return;
  113 
  114     cx = x*font_width;
  115     cy = y*font_height+cs+font_descent;
  116 
  117     XCopyArea(display, win, under_cursor, cursorgc, cx, cy, font_width, 
  118               chgt, 0, 0);
  119     XFillRectangle(display, win, cursorgc, cx, cy, font_width, chgt);
  120 }
  121 
  122 
  123 static void x_unput_cursor(void)
  124 {
  125     if (chgt < 1)
  126         return;
  127 
  128     XCopyArea(display, under_cursor, win, cursorgc, 0, 0, font_width, chgt,
  129               cx, cy);
  130 }
  131 
  132 static void x_new_cursor(int st, int end)
  133 {
  134     cs = st;
  135     chgt = end - st + 1;
  136 }
  137 
  138 static void setGC(void)
  139 {
  140     unsigned long valuemask = 0; /* ignore XGCvalues and use defaults */
  141     XGCValues values;
  142     unsigned int line_width = 6;
  143     int line_style = LineOnOffDash;
  144     int cap_style = CapRound;
  145     int join_style = JoinRound;
  146 
  147     gc = XCreateGC(display, win, valuemask, &values);
  148     cursorgc = XCreateGC(display, win, valuemask, &values);
  149     
  150     XSetFont(display, gc, font_info->fid);
  151     XSetForeground(display, gc, WhitePixel(display,screen_num));
  152     XSetBackground(display, gc, BlackPixel(display,screen_num));
  153 
  154     XSetLineAttributes(display, gc, line_width, line_style, 
  155                        cap_style, join_style);
  156     
  157     XSetForeground(display, cursorgc, WhitePixel(display,screen_num));
  158     XSetBackground(display, cursorgc, BlackPixel(display,screen_num));
  159 }
  160 
  161 
  162 static void setcursor(void)
  163 {
  164     under_cursor = XCreatePixmap(display, win, font_width, font_height, 
  165                                  DefaultDepth(display, screen_num));
  166 }
  167 
  168 static void load_fonts(void)
  169 {
  170     static char *fontname = "vga";
  171     static char *fontname2 = "fixed";
  172     static char *menu_font2_name = "lucidasans-bold-12";
  173     static char *menu_font1_name = "lucidasans-12";
  174     char string[] = "W";
  175     
  176     if ((font_info = XLoadQueryFont(display, fontname)) == NULL)
  177     {
  178         fprintf(stderr, "Warning: cannot locate correct VGA font\n");
  179         fprintf(stderr, "Reverting to standard 8x16 font\n");
  180         if ((font_info = XLoadQueryFont(display, fontname2)) == NULL)
  181         {
  182             fprintf(stderr, "%s: Cannot open 8x16 font\n", 
  183                     progname);
  184             exit(1);
  185         }
  186     }
  187     font_height = font_info->ascent + font_info->descent;
  188     font_width = XTextWidth(font_info, string, 1);
  189     font_descent = font_info->descent;
  190 
  191     if ((menu_font1 = XLoadQueryFont(display, menu_font1_name)) == NULL)
  192     {
  193         fprintf(stderr, "Warning: cannot locate %s font\n", menu_font1_name);
  194         fprintf(stderr, "Reverting to standard 8x16 font\n");
  195         if ((menu_font1 = XLoadQueryFont(display, fontname2)) == NULL)
  196         {
  197             fprintf(stderr, "%s: Cannot open 8x16 font\n", 
  198                     progname);
  199             exit(1);
  200         }
  201     }
  202 
  203     if ((menu_font2 = XLoadQueryFont(display, menu_font2_name)) == NULL)
  204     {
  205         fprintf(stderr, "Warning: cannot locate %s font\n", menu_font2_name);
  206         fprintf(stderr, "Reverting to standard 8x16 font\n");
  207         if ((menu_font2 = XLoadQueryFont(display, fontname2)) == NULL)
  208         {
  209             fprintf(stderr, "%s: Cannot open 8x16 font\n", 
  210                     progname);
  211             exit(1);
  212         }
  213     }
  214     menu_font_height = menu_font1->ascent + menu_font1->descent;
  215     menu_font_width = XTextWidth(menu_font1, string, 1);
  216     menu_font_descent = menu_font1->descent;
  217 }
  218 
  219 
  220 void clear_screen(void)
  221 {
  222     XClearWindow(display, win);
  223 }
  224 
  225 
  226 static void x_copy(unsigned x1, unsigned y1, unsigned x2, unsigned y2,
  227            unsigned nx, unsigned ny)
  228 {
  229     x1 *= font_width;
  230     y1 *= font_height;
  231     x2 = (x2+1)*font_width;
  232     y2 = (y2+1)*font_height;
  233     nx *= font_width;
  234     ny *= font_height;
  235 
  236     XCopyArea(display, win, win, gc, x1, y1+font_descent, x2-x1, y2-y1, nx,
  237               ny+font_descent);
  238 }
  239           
  240 
  241 static void x_draw_line(unsigned x, unsigned y, const char *text, unsigned len, BYTE attr)
  242 {
  243     XSetForeground(display, gc, col_vals[attr & 0xf]);
  244     XSetBackground(display, gc, col_vals[(attr & 0x70) >> 4]);
  245     XDrawImageString(display, win, gc, 
  246                      x*font_width, (y+1)*font_height, text, len);
  247 }
  248 
  249     
  250 void draw_char(unsigned x, unsigned y, char c, BYTE attr)
  251 {
  252     XSetForeground(display, gc, col_vals[attr & 0xf]);
  253     XSetBackground(display, gc, col_vals[(attr & 0x70) >> 4]);
  254     XDrawImageString(display, win, gc, 
  255                      x*font_width, (y+1)*font_height, &c, 1);
  256 }
  257 
  258 
  259 static void x_window_size(unsigned width, unsigned height)
  260 {
  261     width *= font_width;
  262     height = height*font_height+4;
  263 
  264     D(printf("Window size = %dx%d\n", width, height););
  265     XResizeWindow(display, win, width, height);
  266     
  267     size_hints.flags = PSize | PMinSize | PMaxSize;
  268     size_hints.max_width = size_hints.min_width = width;
  269     size_hints.max_height = size_hints.min_height = height;
  270 
  271     XSetWMNormalHints(display, win, &size_hints);
  272 }
  273 
  274 
  275 static void x_init(void)
  276 {
  277     unsigned int width, height; /* window size */
  278     int x, y;   /* window position */
  279     unsigned int border_width = 4;  /* four pixels */
  280     unsigned int display_width, display_height;
  281     char *display_name = NULL;
  282     XWMHints wm_hints;
  283     char *window_name = "PC Emulator";
  284     char *icon_name = "PC";
  285     XClassHint class_hints;
  286     XTextProperty windowName, iconName;
  287     Pixmap icon_pixmap;
  288 
  289     if ((display=XOpenDisplay(display_name)) == NULL)
  290     {
  291         fprintf(stderr, "%s: cannot connect to X server %s\n", 
  292                 progname, XDisplayName(display_name));
  293         exit(1);
  294     }
  295     
  296     screen_num = DefaultScreen(display);
  297     display_width = DisplayWidth(display, screen_num);
  298     display_height = DisplayHeight(display, screen_num);
  299     
  300     x = y = 0;
  301     
  302     load_fonts();
  303     
  304     width = 80*font_width;
  305     height = 25*font_height+4;
  306     
  307     win = XCreateSimpleWindow(display, RootWindow(display,screen_num), 
  308                               x, y, width, height, border_width,
  309                               WhitePixel(display, screen_num),
  310                               BlackPixel(display,screen_num));
  311     
  312     icon_pixmap = XCreateBitmapFromData(display, win, icon_bits, 
  313                                         icon_width, icon_height);
  314     
  315     if (XStringListToTextProperty(&window_name, 1, &windowName) == 0)
  316     {
  317         fprintf(stderr, "%s: structure allocation for windowName failed.\n", 
  318                 progname);
  319         exit(1);
  320     }
  321     
  322     if (XStringListToTextProperty(&icon_name, 1, &iconName) == 0)
  323     {
  324         fprintf(stderr, "%s: structure allocation for iconName failed.\n", 
  325                 progname);
  326         exit(1);
  327     }
  328     
  329     size_hints.flags = PSize | PMinSize | PMaxSize;
  330     size_hints.max_width = size_hints.min_width = width;
  331     size_hints.max_height = size_hints.min_height = height;
  332 
  333     wm_hints.initial_state = NormalState;
  334     wm_hints.input = True;
  335     wm_hints.icon_pixmap = icon_pixmap;
  336     wm_hints.flags = StateHint | IconPixmapHint | InputHint;
  337     
  338     class_hints.res_name = progname;
  339     class_hints.res_class = "PCEmulator";
  340     
  341     XSetWMProperties(display, win, &windowName, &iconName, 
  342                      &progname, 1, &size_hints, &wm_hints, 
  343                      &class_hints);
  344     
  345     XSelectInput(display, win, ExposureMask | KeyPressMask | KeyReleaseMask |
  346                  StructureNotifyMask | ButtonPressMask | ButtonReleaseMask);
  347     
  348     setGC();
  349     setcursor();
  350 
  351     mono = (DisplayCells(display, screen_num) < 16);
  352     graphics = 0; /* !(DisplayCells(display, screen_num) < 256); */
  353 
  354     get_colours();
  355 
  356     /* Display window */
  357     XMapWindow(display, win);
  358 }
  359 
  360 
  361 static void x_flush(void)
  362 {
  363     XFlush(display);
  364 }
  365 
  366 static BYTE scan_table1[256 - 0x20] =
  367 {
  368     0x39, 0x02, 
  369 #ifdef KBUK             /* double quotes, hash symbol */
  370     0x03, 0x2b,
  371 #else
  372     0x28, 0x04,
  373 #endif
  374     0x05, 0x06, 0x08, 0x28,
  375     0x0a, 0x0b, 0x09, 0x0d, 0x33, 0x0c, 0x34, 0x35,
  376     0x0b, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
  377     0x09, 0x0a, 0x27, 0x27, 0x33, 0x0d, 0x34, 0x35,
  378 #ifdef KBUK             /* at symbol */
  379     0x28, 
  380 #else
  381     0x03,
  382 #endif
  383     0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21, 0x22,
  384     0x23, 0x17, 0x24, 0x25, 0x26, 0x32, 0x31, 0x18,
  385     0x19, 0x10, 0x13, 0x1f, 0x14, 0x16, 0x2f, 0x11,
  386     0x2d, 0x15, 0x2c, 0x1a, 
  387 #ifdef KBUK             /* backslash */
  388     0x56, 
  389 #else
  390     0x2b,
  391 #endif
  392     0x1b, 0x07, 0x0c,
  393     0x29, 0x1e, 0x30, 0x2e, 0x20, 0x12, 0x21, 0x22,
  394     0x23, 0x17, 0x24, 0x25, 0x26, 0x32, 0x31, 0x18,
  395     0x19, 0x10, 0x13, 0x1f, 0x14, 0x16, 0x2f, 0x11,
  396     0x2d, 0x15, 0x2c, 0x1a, 
  397 #ifdef KBUK             /* vertical bar */
  398     0x56, 
  399 #else
  400     0x2b,
  401 #endif
  402 
  403     0x1b, 
  404 
  405 #ifdef KBUK             /* tilde */
  406     0x2b,
  407 #else
  408     0x29,
  409 #endif
  410     0
  411 };
  412 
  413 
  414 static struct
  415 {
  416     KeySym key;
  417     unsigned scan_code;
  418 } scan_table2[] =
  419 {
  420     { XK_BackSpace,     0x0e },
  421     { XK_Tab,           0x0f },
  422     { XK_Return,        0x1c },
  423     { XK_Escape,        0x01 },
  424     { XK_Delete,        0x53e0 },
  425         
  426     { XK_Home,          0x47e0 },
  427     { XK_Left,          0x4be0 },
  428     { XK_Up,            0x48e0 },
  429     { XK_Right,         0x4de0 },
  430     { XK_Down,          0x50e0 },
  431     { XK_Prior,         0x49e0 },
  432     { XK_Next,          0x51e0 },
  433     { XK_End,           0x4fe0 },
  434     { XK_Insert,        0x52e0 },
  435     { XK_Num_Lock,      0x45 },
  436 
  437 /* This block of codes is for Sun Type 4 keyboards... */
  438 
  439     { XK_F27,           0x47e0 },       /* Home/R7/F27 */
  440     { XK_F29,           0x49e0 },       /* Prior/R9/F29 */
  441     { XK_F35,           0x51e0 },       /* Next/R15/F35 */
  442     { XK_F33,           0x4fe0 },       /* End/R13/F33 */
  443 
  444     { XK_F25,           0x36e0 },       /* Keypad divide/R5/F25 */
  445     { XK_F26,           0x37 },         /* Keypad multiply/R6/F26 */
  446 
  447     { XK_F23,           0x46 },         /* Scroll lock/R3/F23 */
  448    
  449     { XK_F31,           0x4c },         /* Keypad 5/R11/F31 */
  450 
  451 /* End of Sun type 4 codes */
  452 
  453     { XK_KP_Enter,      0x1ce0 },
  454     { XK_KP_Multiply,   0x37 },
  455     { XK_KP_Add,        0x4e },
  456     { XK_KP_Subtract,   0x4a },
  457     { XK_KP_Divide,     0x36e0 },
  458     { XK_KP_Decimal,    0x53 },
  459 
  460     { XK_KP_0,          0x52 },
  461     { XK_KP_1,          0x4f },
  462     { XK_KP_2,          0x50 },
  463     { XK_KP_3,          0x51 },
  464     { XK_KP_4,          0x4b },
  465     { XK_KP_5,          0x4c },
  466     { XK_KP_6,          0x4d },
  467     { XK_KP_7,          0x47 },
  468     { XK_KP_8,          0x48 },
  469     { XK_KP_9,          0x49 },
  470 
  471     { XK_F1,            0x3b },
  472     { XK_F2,            0x3c },
  473     { XK_F3,            0x3d },
  474     { XK_F4,            0x3e },
  475     { XK_F5,            0x3f },
  476     { XK_F6,            0x40 },
  477     { XK_F7,            0x41 },
  478     { XK_F8,            0x42 },
  479     { XK_F9,            0x43 },
  480     { XK_F10,           0x44 },
  481     { XK_F11,           0x57 },
  482     { XK_F12,           0x58 },
  483 
  484     { XK_Shift_L,       0x2a },
  485     { XK_Shift_R,       0x36 },
  486     { XK_Control_L,     0x1d },
  487     { XK_Control_R,     0x1de0 },
  488     { XK_Meta_L,        0x38 },
  489     { XK_Alt_L,         0x38 },
  490     { XK_Meta_R,        0x38e0 },
  491     { XK_Alt_R,         0x38e0 },
  492 
  493     { XK_Scroll_Lock,   0x46 },
  494     { XK_Caps_Lock,     0xba3a }
  495 };
  496 
  497 
  498 static unsigned translate(KeySym key)
  499 {
  500     int i;
  501     if (key >= 0x20 && key <= 0x20+sizeof(scan_table1))
  502         return (scan_table1[key - 0x20]);
  503 
  504     for (i = 0; i < sizeof(scan_table2); i++)
  505         if (scan_table2[i].key == key)
  506             return (scan_table2[i].scan_code);
  507 
  508     return 0;
  509 }
  510 
  511 
  512 int put_scan_table(BYTE code, unsigned char c)
  513 {
  514     /* interface to overload scan_table1 from .pcemurc */
  515     if(c < ' ' || c >= ' ' + sizeof scan_table1)
  516         return 1;
  517     scan_table1[c - ' '] = code;
  518     return 0;
  519 }
  520 
  521 
  522 static void x_process_events(void)
  523 {    
  524 #define KEY_BUFFER_SIZE 100
  525 
  526     XEvent event;
  527     KeySym key;
  528     unsigned scan;
  529     static BYTE buffer[4];
  530     XEvent keyeventbuffer[KEY_BUFFER_SIZE];
  531     int keyptr = 0;
  532     int count;
  533 
  534     while (XPending(display) > 0)
  535     {
  536         XNextEvent(display, &event);
  537         switch(event.type)
  538         {
  539         case Expose:
  540             if (event.xexpose.count != 0)
  541                 break;
  542             
  543             pcemu_refresh();
  544             break;
  545         case UnmapNotify:       /* Pause emulator */
  546             stoptimer();
  547             for (;;)
  548             {
  549                 XNextEvent(display, &event);
  550                 switch(event.type)
  551                 {
  552                 case MapNotify:
  553                     starttimer();
  554                     return;
  555                 default:
  556                     break;
  557                 }
  558             }
  559             break;
  560         case KeyPress:
  561         case KeyRelease:
  562             key = XLookupKeysym(&event.xkey, 0);
  563 
  564             D(printf("State = %X. Got keysym number: %X\n", 
  565                      (int)event.xkey.state, (int)key););
  566 
  567                 /* XK_F21 is for sun type 4 keyboards.. */
  568             if (key == XK_Break || key == XK_F21)
  569                 key = XK_Pause;
  570 
  571             if (key == XK_Pause)
  572             {
  573                 D(printf("Pause pressed. State = %02X\n", event.xkey.state););
  574                 if (event.xkey.state & ControlMask)
  575                     scan = 0xc6e046e0;
  576                 else
  577                     scan = 0x451de1;
  578             }                   /* XK_F22 is sun type 4 PrtScr */
  579             else if (key == XK_Print || key == XK_F22)
  580             {
  581                 D(printf("Print pressed. State = %02X\n", event.xkey.state););
  582                 if (event.xkey.state & Mod1Mask)
  583                     scan = 0x54;
  584                 else
  585                     scan = 0x37e02ae0;
  586             }
  587 #ifdef KBUK
  588             else if ((key == XK_numbersign) && (event.xkey.state & ShiftMask))
  589                 scan = 0x4;
  590 #endif
  591             else if (key == XK_sterling)
  592                 scan = 0x4;
  593             else if ((scan = translate(key)) == 0)
  594                 break;
  595 
  596             for (count = 0; scan; count++)
  597             {
  598                 if (key != XK_Caps_Lock && event.type == KeyRelease)                    
  599                     buffer[count] = 0x80 | (scan & 0xff);
  600                 else
  601                     buffer[count] = scan & 0xff;
  602                 
  603                 scan >>= 8;
  604             }
  605 
  606             if (port60_buffer_ok(count))
  607             {
  608                 D(printf("Returning %d scan code bytes\n",count););
  609                 put_scancode(buffer, count);
  610             }
  611             else
  612             {
  613                 D(printf("Port60 buffer full...\n"););
  614 
  615                 if (keyptr < KEY_BUFFER_SIZE)
  616                     keyeventbuffer[keyptr++] = event;
  617             }
  618                   
  619             break;
  620         case ButtonPress:
  621             process_menu();
  622         default:
  623             break;
  624         }
  625     }
  626 
  627     for (count = keyptr; count > 0; count--)
  628         XPutBackEvent(display, &keyeventbuffer[count-1]);
  629 }
  630 
  631 
  632 static void x_end(void)
  633 {
  634     XUnloadFont(display, font_info->fid);
  635     XUnloadFont(display, menu_font1->fid);
  636     XUnloadFont(display, menu_font2->fid);
  637     XFreeGC(display, gc);
  638     XFreeGC(display, cursorgc);
  639     XFreePixmap(display, under_cursor);
  640     XCloseDisplay(display);
  641 }
  642 
  643 void process_menu(void)
  644 {
  645 #define MENUITEMS 7
  646 #define MENUGAP 4
  647         XSetWindowAttributes attributes;
  648         Window window, root, child;
  649         GC gc;
  650     int win_x, win_y;
  651     int root_x, root_y;
  652     unsigned int buttons;
  653     char *menu[] = {"PCEmu Controls", "-", "A", "B", "-", "Reboot", "Shutdown"};
  654     int greyed[] = {1, 1, 0, 0, 1, 1, 0};
  655     int i;
  656     int selection, oldselection;
  657     XGCValues values; /* Unused. Only here because XCreateGC demands it. */
  658 
  659     if (fdisk[0].removable)
  660         if (fdisk[0].mounted)
  661             menu[2] = "Dismount drive A";
  662         else
  663             menu[2] = "Mount drive A";
  664     else
  665     {
  666         menu[2] = "(Drive A not removable)";
  667         greyed[2] = 1;
  668     }
  669     if (fdisk[1].removable)
  670         if (fdisk[1].mounted)
  671             menu[3] = "Dismount drive B";
  672         else
  673             menu[3] = "Mount drive B";
  674     else
  675     {
  676         menu[3] = "(Drive B not removable)";
  677         greyed[3] = 1;
  678     }
  679 
  680     if (!XQueryPointer(display, win, &root, &child, &root_x, &root_y, &win_x, &win_y, &buttons))
  681         return;
  682         window = XCreateSimpleWindow(display, RootWindow(display, screen_num),  
  683                 root_x-100, root_y-10, 201, MENUITEMS*(menu_font_height+MENUGAP)+10, 1, BlackPixel(display, screen_num),
  684         WhitePixel(display, screen_num));
  685         attributes.override_redirect = True;
  686         XChangeWindowAttributes(display, window, CWOverrideRedirect,
  687                 &attributes);
  688         XMapWindow(display, window);
  689     gc = XCreateGC(display, window, 0, &values);
  690     XSetForeground(display, gc, BlackPixel(display, screen_num));
  691     XDrawRectangle(display, window, gc, 2, 2, 196, MENUITEMS*(menu_font_height+MENUGAP)+5);
  692     oldselection = -1;
  693 
  694     for(i=0; i<MENUITEMS; i++)
  695         drawmenuitem(window, gc, (i+1)*(menu_font_height+MENUGAP)+2, menu[i], greyed[i], 0);
  696     do {
  697         XQueryPointer(display, window, &root, &child, &root_x, &root_y, &win_x, &win_y, &buttons);
  698         selection = (win_y-2)/(menu_font_height+4);
  699         if ((selection != oldselection) && (selection>=0) && (selection<MENUITEMS))
  700         {
  701             if (oldselection != -1)
  702                 drawmenuitem(window, gc, (oldselection+1)*(menu_font_height+MENUGAP)+2, menu[oldselection], greyed[oldselection], 0);
  703             if (greyed[selection] == 0)
  704                 drawmenuitem(window, gc, (selection+1)*(menu_font_height+MENUGAP)+2, menu[selection], greyed[selection], 1);
  705             oldselection = selection;
  706         }   
  707     } while (buttons && Button2Mask);
  708     XDestroyWindow(display, window);
  709     if (!greyed[selection])
  710         menu_selected(selection);
  711 }
  712 
  713 void drawmenuitem(Drawable window, GC gc, int y, char *string, int fontnum, int reversed)
  714 {
  715     int width;
  716 
  717     if (fontnum)
  718     {
  719         XSetFont(display, gc, menu_font1->fid);
  720         width = XTextWidth(menu_font1, string, strlen(string));
  721     }
  722     else
  723     {
  724         XSetFont(display, gc, menu_font2->fid);
  725         width = XTextWidth(menu_font2, string, strlen(string));
  726     }
  727     if (!reversed)
  728     {
  729         XSetForeground(display, gc, WhitePixel(display, screen_num));
  730         XSetBackground(display, gc, BlackPixel(display, screen_num));
  731     }
  732     else    
  733     {
  734         XSetBackground(display, gc, WhitePixel(display, screen_num));
  735         XSetForeground(display, gc, BlackPixel(display, screen_num));
  736     }
  737     XFillRectangle(display, window, gc, 5, y-menu_font_height-(MENUGAP/3), 191, menu_font_height+MENUGAP);
  738     if (reversed)
  739     {
  740         XSetForeground(display, gc, WhitePixel(display, screen_num));
  741         XSetBackground(display, gc, BlackPixel(display, screen_num));
  742     }
  743     else    
  744     {
  745         XSetBackground(display, gc, WhitePixel(display, screen_num));
  746         XSetForeground(display, gc, BlackPixel(display, screen_num));
  747     }
  748     if (*string == '-')
  749         XDrawLine(display, window, gc, 3, y-(menu_font_height/2), 197, y-(menu_font_height/2));
  750     else
  751         XDrawString(display, window, gc, 100-(width/2), y, string, strlen(string));
  752 }
  753 
  754 void menu_selected(int selection)
  755 {
  756     switch(selection)
  757     {
  758         case 2: /* Dismount/mount drive A */
  759             if (fdisk[0].mounted)
  760             {
  761                 fdisk[0].mounted = 0;
  762                 close(fdisk[0].fd);
  763 #ifdef AUTOEJECT
  764                 eject();
  765 #endif
  766             }
  767             else
  768                 open_drive(fdisk, 0);
  769             break;
  770         case 3: /* Dismount/mount drive B */
  771             if (fdisk[1].mounted)
  772             {
  773                 fdisk[1].mounted = 0;
  774                 close(fdisk[1].fd);
  775 #ifdef AUTOEJECT
  776                 eject();
  777 #endif
  778             }
  779         else
  780                 open_drive(fdisk, 1);
  781             break;
  782         case 5: /* Reboot */
  783             /* Don't know how to do this yet. */
  784             break;
  785         case 6: /* Shutdown */
  786             exit_emu();
  787             break;
  788     }
  789 }
  790 
  791 #ifdef AUTOEJECT
  792 void eject(void)
  793 {
  794     system(AUTOEJECT);
  795 }
  796 #endif
  797 
  798 VIDEO_DRIVER x_video = {
  799     "X",
  800     x_init,
  801     x_end,
  802     x_flush,
  803     x_put_cursor,
  804     x_unput_cursor,
  805     x_copy,
  806     x_new_cursor,
  807     x_window_size,
  808     x_draw_line,
  809     x_process_events
  810 };
  811