gui_x11.cpp

Go to the documentation of this file.
00001 /* ES40 emulator.
00002  * Copyright (C) 2007-2008 by the ES40 Emulator Project
00003  *
00004  * WWW    : http://sourceforge.net/projects/es40
00005  * E-mail : camiel@camicom.com
00006  * 
00007  *  This file is based upon Bochs.
00008  *
00009  *  Copyright (C) 2002  MandrakeSoft S.A.
00010  *
00011  *    MandrakeSoft S.A.
00012  *    43, rue d'Aboukir
00013  *    75002 Paris - France
00014  *    http://www.linux-mandrake.com/
00015  *    http://www.mandrakesoft.com/
00016  *
00017  *  This library is free software; you can redistribute it and/or
00018  *  modify it under the terms of the GNU Lesser General Public
00019  *  License as published by the Free Software Foundation; either
00020  *  version 2 of the License, or (at your option) any later version.
00021  *
00022  *  This library is distributed in the hope that it will be useful,
00023  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
00024  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00025  *  Lesser General Public License for more details.
00026  *
00027  *  You should have received a copy of the GNU Lesser General Public
00028  *  License along with this library; if not, write to the Free Software
00029  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
00030 
00031  */
00032 
00055 #define XK_PUBLISHING
00056 #define XK_TECHNICAL
00057 
00058 #include "../StdAfx.h"
00059 
00060 #if defined(HAVE_X11)
00061 #include "gui.h"
00062 #include "keymap.h"
00063 #include "../Configurator.h"
00064 #include "../VGA.h"
00065 #include "../Keyboard.h"
00066 
00067 extern "C"
00068 {
00069 #include <X11/Xlib.h>
00070 #include <X11/Xutil.h>
00071 #include <X11/Xos.h>
00072 #include <X11/Xatom.h>
00073 #include <X11/keysym.h>
00074 }
00075 #include "gui_win32_font.h"
00076 
00077 class bx_x11_gui_c : public bx_gui_c
00078 {
00079   public:
00080     bx_x11_gui_c(CConfigurator* cfg)
00081     {
00082       myCfg = cfg;
00083       bx_keymap = new bx_keymap_c(cfg);
00084     };
00085 
00086     virtual void                  specific_init(unsigned x_tilesize,
00087                                                 unsigned y_tilesize);
00088     virtual void                  text_update(u8*  old_text, u8*  new_text,
00089                                               unsigned long cursor_x,
00090                                               unsigned long cursor_y,
00091                                               bx_vga_tminfo_t tm_info,
00092                                               unsigned rows);
00093     virtual void                  graphics_tile_update(u8*  snapshot, unsigned x,
00094                                                        unsigned y);
00095     virtual void                  handle_events(void);
00096     virtual void                  flush(void);
00097     virtual void                  clear_screen(void);
00098     virtual bool                  palette_change(unsigned index, unsigned red,
00099                                                  unsigned green, unsigned blue);
00100     virtual void                  dimension_update(unsigned x, unsigned y,
00101                                                    unsigned fheight = 0,
00102                                                    unsigned fwidth = 0,
00103                                                    unsigned bpp = 8);
00104     virtual void                  mouse_enabled_changed_specific(bool val);
00105     virtual void                  exit(void);
00106     virtual bx_svga_tileinfo_t*   graphics_tile_info(bx_svga_tileinfo_t* info);
00107     virtual u8*                   graphics_tile_get(unsigned x, unsigned y,
00108                                                     unsigned*  w, unsigned*  h);
00109     virtual void                  graphics_tile_update_in_place(unsigned x,
00110                                                                 unsigned y,
00111                                                                 unsigned w,
00112                                                                 unsigned h);
00113     virtual void                  get_capabilities(u16*  xres, u16*  yres,
00114                                                    u16*  bpp);
00115   private:
00116     CConfigurator*  myCfg;
00117 };
00118 
00119 // declare one instance of the gui object and call macro to insert the
00120 // plugin code
00121 static bx_x11_gui_c*  theGui = NULL;
00122 IMPLEMENT_GUI_PLUGIN_CODE(x11)
00123 #define MAX_MAPPED_STRING_LENGTH  10
00124 
00125 /* These are used as arguments to nearly every Xlib routine, so it saves
00126  * routine arguments to declare them global.  If there were
00127  * additional source files, they would be declared extern there. */
00128 Display*              bx_x_display;
00129 int                   bx_x_screen_num;
00130 static Visual*        default_visual;
00131 static Colormap       default_cmap;
00132 static unsigned long  white_pixel = 0, black_pixel = 0;
00133 
00134 static char*          progname; /* name this program was invoked by */
00135 
00136 static unsigned int   text_rows = 25, text_cols = 80;
00137 static u8             h_panning = 0, v_panning = 0;
00138 static u16            line_compare = 1023;
00139 
00140 static Window         win;
00141 static GC             gc, gc_inv;
00142 static unsigned       font_width, font_height;
00143 static unsigned       dimension_x = 0, dimension_y = 0;
00144 static unsigned       vga_bpp = 8;
00145 
00146 static XImage*        ximage = NULL;
00147 static unsigned       imDepth, imWide, imBPP;
00148 
00149 // current cursor coordinates
00150 static int            prev_x = -1, prev_y = -1;
00151 static int            current_x = -1, current_y = -1, current_z = 0;
00152 static unsigned       mouse_button_state = 0;
00153 static bool           CTRL_pressed = 0;
00154 
00155 static unsigned       prev_cursor_x = 0;
00156 static unsigned       prev_cursor_y = 0;
00157 
00158 static int            warp_home_x = 200;
00159 static int            warp_home_y = 200;
00160 static int            mouse_enable_x = 0;
00161 static int            mouse_enable_y = 0;
00162 static int            warp_dx = 0;
00163 static int            warp_dy = 0;
00164 
00165 static void           warp_cursor(int dx, int dy);
00166 static void           disable_cursor();
00167 static void           enable_cursor();
00168 
00169 static u32            convertStringToXKeysym(const char* string);
00170 
00171 static bool           x_init_done = false;
00172 
00173 static Pixmap         vgafont[256];
00174 
00175 static void           send_keyboard_mouse_status(void);
00176 
00177 static bool           x_keymapping;
00178 static bool           x_private_colormap;
00179 
00180 u32                   ascii_to_key_event[0x5f] = {
00181   //  !"#$%&'
00182   BX_KEY_SPACE,
00183   BX_KEY_1,
00184   BX_KEY_SINGLE_QUOTE,
00185   BX_KEY_3,
00186   BX_KEY_4,
00187   BX_KEY_5,
00188   BX_KEY_7,
00189   BX_KEY_SINGLE_QUOTE,
00190 
00191   // ()*+,-./
00192   BX_KEY_9,
00193   BX_KEY_0,
00194   BX_KEY_8,
00195   BX_KEY_EQUALS,
00196   BX_KEY_COMMA,
00197   BX_KEY_MINUS,
00198   BX_KEY_PERIOD,
00199   BX_KEY_SLASH,
00200 
00201   // 01234567
00202   BX_KEY_0,
00203   BX_KEY_1,
00204   BX_KEY_2,
00205   BX_KEY_3,
00206   BX_KEY_4,
00207   BX_KEY_5,
00208   BX_KEY_6,
00209   BX_KEY_7,
00210 
00211   // 89:;<=>?
00212   BX_KEY_8,
00213   BX_KEY_9,
00214   BX_KEY_SEMICOLON,
00215   BX_KEY_SEMICOLON,
00216   BX_KEY_COMMA,
00217   BX_KEY_EQUALS,
00218   BX_KEY_PERIOD,
00219   BX_KEY_SLASH,
00220 
00221   // @ABCDEFG
00222   BX_KEY_2,
00223   BX_KEY_A,
00224   BX_KEY_B,
00225   BX_KEY_C,
00226   BX_KEY_D,
00227   BX_KEY_E,
00228   BX_KEY_F,
00229   BX_KEY_G,
00230 
00231   // HIJKLMNO
00232   BX_KEY_H,
00233   BX_KEY_I,
00234   BX_KEY_J,
00235   BX_KEY_K,
00236   BX_KEY_L,
00237   BX_KEY_M,
00238   BX_KEY_N,
00239   BX_KEY_O,
00240 
00241   // PQRSTUVW
00242   BX_KEY_P,
00243   BX_KEY_Q,
00244   BX_KEY_R,
00245   BX_KEY_S,
00246   BX_KEY_T,
00247   BX_KEY_U,
00248   BX_KEY_V,
00249   BX_KEY_W,
00250 
00251   // XYZ[\]^_
00252   BX_KEY_X,
00253   BX_KEY_Y,
00254   BX_KEY_Z,
00255   BX_KEY_LEFT_BRACKET,
00256   BX_KEY_BACKSLASH,
00257   BX_KEY_RIGHT_BRACKET,
00258   BX_KEY_6,
00259   BX_KEY_MINUS,
00260 
00261   // `abcdefg
00262   BX_KEY_GRAVE,
00263   BX_KEY_A,
00264   BX_KEY_B,
00265   BX_KEY_C,
00266   BX_KEY_D,
00267   BX_KEY_E,
00268   BX_KEY_F,
00269   BX_KEY_G,
00270 
00271   // hijklmno
00272   BX_KEY_H,
00273   BX_KEY_I,
00274   BX_KEY_J,
00275   BX_KEY_K,
00276   BX_KEY_L,
00277   BX_KEY_M,
00278   BX_KEY_N,
00279   BX_KEY_O,
00280 
00281   // pqrstuvw
00282   BX_KEY_P,
00283   BX_KEY_Q,
00284   BX_KEY_R,
00285   BX_KEY_S,
00286   BX_KEY_T,
00287   BX_KEY_U,
00288   BX_KEY_V,
00289   BX_KEY_W,
00290 
00291   // xyz{|}~
00292   BX_KEY_X,
00293   BX_KEY_Y,
00294   BX_KEY_Z,
00295   BX_KEY_LEFT_BRACKET,
00296   BX_KEY_BACKSLASH,
00297   BX_KEY_RIGHT_BRACKET,
00298   BX_KEY_GRAVE
00299 };
00300 
00301 extern u8             graphics_snapshot[32 * 1024];
00302 
00303 static void           create_internal_vga_font(void);
00304 static void           xkeypress(KeySym keysym, int press_release);
00305 
00306 // extern "C" void select_visual(void);
00307 #define ROUNDUP(nbytes, pad)  ((((nbytes) + ((pad) - 1)) / (pad)) * ((pad) >> 3))
00308 #define MAX_VGA_COLORS        256
00309 
00310 unsigned long   col_vals[MAX_VGA_COLORS]; // 256 VGA colors
00311 unsigned        curr_foreground, curr_background;
00312 
00313 static unsigned x_tilesize, y_tilesize;
00314 
00315 //BxEvent *x11_notify_callback (void *unused, BxEvent *event);
00316 //bxevent_handler old_callback = NULL;
00317 //void *old_callback_arg = NULL;
00318 
00319 // Try to allocate NCOLORS at once in the colormap provided.  If it can
00320 // be done, return true.  If not, return false.  (In either case, free
00321 // up the color cells so that we don't add to the problem!)  This is used
00322 // to determine whether Bochs should use a private colormap even when the
00323 
00324 // user did not specify it.
00325 static bool test_alloc_colors(Colormap cmap, u32 n_tries)
00326 {
00327   XColor        color;
00328   unsigned long pixel[MAX_VGA_COLORS];
00329   bool          pixel_valid[MAX_VGA_COLORS];
00330   u32           n_allocated = 0;
00331   u32           i;
00332   color.flags = DoRed | DoGreen | DoBlue;
00333   for(i = 0; i < n_tries; i++)
00334   {
00335 
00336     // choose weird color values that are unlikely to already be in the
00337     // colormap.
00338     color.red = ((i + 41) % MAX_VGA_COLORS) << 8;
00339     color.green = ((i + 42) % MAX_VGA_COLORS) << 8;
00340     color.blue = ((i + 43) % MAX_VGA_COLORS) << 8;
00341     pixel_valid[i] = false;
00342     if(XAllocColor(bx_x_display, cmap, &color))
00343     {
00344       pixel[i] = color.pixel;
00345       pixel_valid[i] = true;
00346       n_allocated++;
00347     }
00348   }
00349 
00350   BX_INFO(("test_alloc_colors: %d colors available out of %d colors tried",
00351             n_allocated, n_tries));
00352 
00353   // now free them all
00354   for(i = 0; i < n_tries; i++)
00355   {
00356     if(pixel_valid[i])
00357       XFreeColors(bx_x_display, cmap, &pixel[i], 1, 0);
00358   }
00359 
00360   return(n_allocated == n_tries);
00361 }
00362 
00363 void bx_x11_gui_c::specific_init(unsigned tilewidth, unsigned tileheight)
00364 {
00365   unsigned              i;
00366   int                   x;
00367   int                   y;  /* window position */
00368   unsigned int          border_width = 4;         /* four pixels */
00369   const char*           window_name = "ES40 Emulator";
00370   const char*           icon_name = "ES40";
00371   XSizeHints            size_hints;
00372   char*                 display_name = NULL;
00373 
00374   /* create GC for text and drawing */
00375   unsigned long         valuemask = 0;            /* ignore XGCvalues and use defaults */
00376   XGCValues             values;
00377   int                   default_depth;
00378   XEvent                report;
00379   XSetWindowAttributes  win_attr;
00380   unsigned long         plane_masks_return[1];
00381   XColor                color;
00382 
00383   x_tilesize = tilewidth;
00384   y_tilesize = tileheight;
00385 
00386   /* connect to X server */
00387   if((bx_x_display = XOpenDisplay(display_name)) == NULL)
00388   {
00389     BX_PANIC(("%s: cannot connect to X server %s", progname, XDisplayName(
00390                display_name)));
00391   }
00392 
00393   /* get screen size from display structure macro */
00394   bx_x_screen_num = DefaultScreen(bx_x_display);
00395 
00396   /* Note that in a real application, x and y would default to 0
00397    * but would be settable from the command line or resource database.
00398    */
00399   x = y = 0;
00400 
00401   // Temporary values so we can create the window
00402   font_width = 8;
00403   font_height = 16;
00404 
00405   dimension_x = text_cols * font_width;
00406   dimension_y = text_rows * font_height;
00407 
00408   /* create opaque window */
00409   win = XCreateSimpleWindow(bx_x_display,
00410                             RootWindow(bx_x_display, bx_x_screen_num), x, y,
00411                             dimension_x, dimension_y, border_width,
00412                             BlackPixel(bx_x_display, bx_x_screen_num),
00413                             BlackPixel(bx_x_display, bx_x_screen_num));
00414 
00415   // (attempt to) enable backing store
00416   win_attr.save_under = 1;
00417   win_attr.backing_store = Always;
00418   XChangeWindowAttributes(bx_x_display, win, CWSaveUnder | CWBackingStore,
00419                           &win_attr);
00420 
00421   default_depth = DefaultDepth(bx_x_display, bx_x_screen_num);
00422   default_visual = DefaultVisual(bx_x_display, bx_x_screen_num);
00423 
00424   x_private_colormap = myCfg->get_bool_value("private_colormap", true);
00425   if(!x_private_colormap)
00426   {
00427 
00428     //if (!SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get()) {
00429     default_cmap = DefaultColormap(bx_x_display, bx_x_screen_num);
00430 
00431     // try to use default colormap.  If not enough colors are available,
00432     // then switch to private colormap despite the user setting.  There
00433     // are too many cases when no colors are available and ES40 Emulator
00434     // simply draws everything in black on black.
00435     if(!test_alloc_colors(default_cmap, 16))
00436     {
00437       printf("xxx: I can't allocate 16 colors\n");
00438       x_private_colormap = true;
00439     }
00440 
00441     col_vals[0] = BlackPixel(bx_x_display, bx_x_screen_num);
00442     col_vals[15] = WhitePixel(bx_x_display, bx_x_screen_num);
00443     for(i = 1; i < MAX_VGA_COLORS; i++)
00444     {
00445       if(i == 15)
00446         continue;
00447       col_vals[i] = col_vals[0];
00448     }
00449   }
00450 
00451   if(x_private_colormap)
00452   {
00453 
00454     //if (SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get()) {
00455     default_cmap = XCreateColormap(bx_x_display,
00456                                    DefaultRootWindow(bx_x_display),
00457                                    default_visual, AllocNone);
00458     if(XAllocColorCells(bx_x_display, default_cmap, False, plane_masks_return,
00459        0, col_vals, MAX_VGA_COLORS) == 0)
00460     {
00461       BX_PANIC(("XAllocColorCells returns error. Maybe your screen does not support a private colormap?"));
00462     }
00463 
00464     win_attr.colormap = default_cmap;
00465     XChangeWindowAttributes(bx_x_display, win, CWColormap, &win_attr);
00466 
00467     color.flags = DoRed | DoGreen | DoBlue;
00468 
00469     for(i = 0; i < MAX_VGA_COLORS; i++)
00470     {
00471       color.pixel = i;
00472       if(i == 15)
00473       {
00474         color.red = 0xffff;
00475         color.green = 0xffff;
00476         color.blue = 0xffff;
00477       }
00478       else
00479       {
00480         color.red = 0;
00481         color.green = 0;
00482         color.blue = 0;
00483       }
00484 
00485       XStoreColor(bx_x_display, default_cmap, &color);
00486     }
00487   }
00488 
00489   // convenience variables which hold the black & white color indeces
00490   black_pixel = col_vals[0];
00491   white_pixel = col_vals[15];
00492 
00493   BX_INFO(("font %u wide x %u high, display depth = %d", (unsigned) font_width,
00494             (unsigned) font_height, default_depth));
00495 
00496   //select_visual();
00497 
00498   /* Set size hints for window manager.  The window manager may
00499    * override these settings.  Note that in a real
00500    * application if size or position were set by the user
00501    * the flags would be UPosition and USize, and these would
00502    * override the window manager's preferences for this window. 
00503    */
00504 
00505   /* x, y, width, and height hints are now taken from
00506    * the actual settings of the window when mapped. Note
00507    * that PPosition and PSize must be specified anyway. 
00508    */
00509   size_hints.flags = PPosition | PSize | PMinSize | PMaxSize;
00510   size_hints.max_width = size_hints.min_width = dimension_x;
00511   size_hints.max_height = size_hints.min_height = dimension_y;
00512   {
00513     XWMHints      wm_hints;
00514     XClassHint    class_hints;
00515 
00516     /* format of the window name and icon name
00517      * arguments has changed in R4 
00518      */
00519     XTextProperty windowName;
00520 
00521     /* format of the window name and icon name
00522      * arguments has changed in R4 
00523      */
00524     XTextProperty iconName;
00525 
00526     /* These calls store window_name and icon_name into
00527    * XTextProperty structures and set their other
00528    * fields properly. */
00529     if(XStringListToTextProperty((char**) &window_name, 1, &windowName) == 0)
00530     {
00531       BX_PANIC(("%s: structure allocation for windowName failed.", progname));
00532     }
00533 
00534     if(XStringListToTextProperty((char**) &icon_name, 1, &iconName) == 0)
00535     {
00536       BX_PANIC(("%s: structure allocation for iconName failed.", progname));
00537     }
00538 
00539     wm_hints.initial_state = NormalState;
00540     wm_hints.input = True;
00541     class_hints.res_name = progname;
00542     class_hints.res_class = (char*) "ES40 Emulator";
00543 
00544     XSetWMProperties(bx_x_display, win, &windowName, &iconName, NULL /*argv*/,
00545                      0 /*argc*/, &size_hints, &wm_hints, &class_hints);
00546     XFree(windowName.value);
00547     XFree(iconName.value);
00548 
00549     Atom  wm_delete = XInternAtom(bx_x_display, "WM_DELETE_WINDOW", 1);
00550     XSetWMProtocols(bx_x_display, win, &wm_delete, 1);
00551   }
00552 
00553   /* Select event types wanted */
00554   XSelectInput(bx_x_display, win, ExposureMask | KeyPressMask | KeyReleaseMask |
00555                ButtonPressMask | ButtonReleaseMask | StructureNotifyMask |
00556                PointerMotionMask | EnterWindowMask | LeaveWindowMask);
00557 
00558   /* Create default Graphics Context */
00559   gc = XCreateGC(bx_x_display, win, valuemask, &values);
00560   gc_inv = XCreateGC(bx_x_display, win, valuemask, &values);
00561 
00562   XSetState(bx_x_display, gc, white_pixel, black_pixel, GXcopy, AllPlanes);
00563 
00564   XSetState(bx_x_display, gc_inv, black_pixel, white_pixel, GXinvert, AllPlanes);
00565 
00566   /* Display window */
00567   XMapWindow(bx_x_display, win);
00568   XSync(bx_x_display, /* no discard */ 0);
00569 
00570   BX_DEBUG(("waiting for MapNotify"));
00571   while(1)
00572   {
00573     XNextEvent(bx_x_display, &report);
00574     if(report.type == MapNotify)
00575       break;
00576   }
00577 
00578   BX_DEBUG(("MapNotify found."));
00579 
00580   // Create the VGA font
00581   create_internal_vga_font();
00582   {
00583     char*   imagedata;
00584 
00585     ximage = XCreateImage(bx_x_display, default_visual,
00586                           default_depth,          // depth of image (bitplanes)
00587                           ZPixmap, 0,             // offset
00588                           NULL,                   // malloc() space after
00589                           x_tilesize, y_tilesize, // x & y size of image
00590                           32, // # bits of padding
00591                           0); // bytes_per_line, let X11 calculate
00592     if(!ximage)
00593       BX_PANIC(("vga: couldn't XCreateImage()"));
00594 
00595     imDepth = default_depth;
00596     imWide = ximage->bytes_per_line;
00597     imBPP = ximage->bits_per_pixel;
00598 
00599     imagedata = (char*) malloc((size_t) (ximage->bytes_per_line * y_tilesize));
00600     if(!imagedata)
00601       BX_PANIC(("imagedata: malloc returned error"));
00602 
00603     ximage->data = imagedata;
00604 
00605     if(imBPP < imDepth)
00606     {
00607       BX_PANIC(("vga_x: bits_per_pixel < depth ?"));
00608     }
00609 
00610     x_init_done = true;
00611   }
00612 
00613   curr_background = 0;
00614   XSetBackground(bx_x_display, gc, col_vals[curr_background]);
00615   curr_foreground = 1;
00616   XSetForeground(bx_x_display, gc, col_vals[curr_foreground]);
00617 
00618   //XGrabPointer( bx_x_display, win, True, 0, GrabModeAsync, GrabModeAsync,
00619   //  win, None, CurrentTime );
00620   XFlush(bx_x_display);
00621 
00622   // loads keymap for x11
00623   x_keymapping = myCfg->get_bool_value("keyboard.use_mapping", false);
00624   if(x_keymapping)
00625   {
00626 
00627     //if (SIM->get_param_bool(BXPN_KBD_USEMAPPING)->get()) {
00628     bx_keymap->loadKeymap(convertStringToXKeysym);
00629   }
00630 
00631   new_gfx_api = 1;
00632 }
00633 
00634 // This is called whenever the mouse_enabled parameter changes.  It
00635 // can change because of a gui event such as clicking on the mouse-enable
00636 // bitmap or pressing the middle button, or from the configuration interface.
00637 
00638 // In all those cases, setting the parameter value will get you here.
00639 void bx_x11_gui_c::mouse_enabled_changed_specific(bool val)
00640 {
00641   BX_DEBUG(("mouse_enabled=%d, x11 specific code", val ? 1 : 0));
00642   if(val)
00643   {
00644     BX_INFO(("[x] Mouse on"));
00645     mouse_enable_x = current_x;
00646     mouse_enable_y = current_y;
00647     disable_cursor();
00648 
00649     // Move the cursor to a 'safe' place
00650     warp_cursor(warp_home_x - current_x, warp_home_y - current_y);
00651   }
00652   else
00653   {
00654     BX_INFO(("[x] Mouse off"));
00655     enable_cursor();
00656     warp_cursor(mouse_enable_x - current_x, mouse_enable_y - current_y);
00657   }
00658 }
00659 
00663 void create_internal_vga_font(void)
00664 {
00665 
00666   // Default values
00667   font_width = 8;
00668   font_height = 16;
00669 
00670   for(int i = 0; i < 256; i++)
00671   {
00672     vgafont[i] = XCreateBitmapFromData(bx_x_display, win,
00673                                        (const char*) bx_vgafont[i].data,
00674                                        font_width, font_height);
00675     if(vgafont[i] == None)
00676       BX_PANIC(("Can't create vga font [%d]", i));
00677   }
00678 }
00679 
00680 void bx_x11_gui_c::handle_events(void)
00681 {
00682   XEvent                report;
00683   XKeyEvent*            key_event;
00684   KeySym                keysym;
00685   XComposeStatus        compose;
00686   char                  buffer[MAX_MAPPED_STRING_LENGTH];
00687   int                   bufsize = MAX_MAPPED_STRING_LENGTH;
00688   int                   charcount;
00689   bool                  mouse_update;
00690   int                   y;
00691   int                   height;
00692 
00693   XPointerMovedEvent*   pointer_event;
00694   XEnterWindowEvent*    enter_event;
00695   XLeaveWindowEvent*    leave_event;
00696   XButtonEvent*         button_event;
00697   XExposeEvent*         expose_event;
00698 
00699   //current_x = -1;
00700   //current_y = -1;
00701   mouse_update = 0;
00702 
00703   while(XPending(bx_x_display) > 0)
00704   {
00705     XNextEvent(bx_x_display, &report);
00706     current_z = 0;
00707     switch(report.type)
00708     {
00709     case Expose:
00710       expose_event = &report.xexpose;
00711 
00712       /* Adjust y.*/
00713       y = expose_event->y;
00714       height = expose_event->height;
00715       if(y < 0)
00716       {
00717         height += y;
00718         y = 0;
00719       }
00720 
00721       theVGA->redraw_area((unsigned) expose_event->x, y,
00722                           (unsigned) expose_event->width, height);
00723 
00724       break;
00725 
00726     case ConfigureNotify:
00727       BX_DEBUG(("ConfigureNotify Xevent"));
00728       break;
00729 
00730     case ButtonPress:
00731       button_event = (XButtonEvent*) &report;
00732       BX_DEBUG(("xxx: buttonpress"));
00733       current_x = button_event->x;
00734       current_y = button_event->y;
00735       mouse_update = 1;
00736       BX_DEBUG(("xxx:   x,y=(%d,%d)", current_x, current_y));
00737       switch(button_event->button)
00738       {
00739       case Button1:
00740         mouse_button_state |= 0x01;
00741         send_keyboard_mouse_status();
00742         mouse_update = 0;
00743         break;
00744 
00745       case Button2:
00746         if(CTRL_pressed)
00747         {
00748 
00749           //            toggle_mouse_enable();
00750         }
00751         else
00752         {
00753           mouse_button_state |= 0x04;
00754           send_keyboard_mouse_status();
00755           mouse_update = 0;
00756         }
00757         break;
00758 
00759       case Button3:
00760         mouse_button_state |= 0x02;
00761         send_keyboard_mouse_status();
00762         mouse_update = 0;
00763         break;
00764       }
00765       break;
00766 
00767     case ButtonRelease:
00768       button_event = (XButtonEvent*) &report;
00769       current_x = button_event->x;
00770       current_y = button_event->y;
00771       mouse_update = 1;
00772       switch(button_event->button)
00773       {
00774       case Button1:
00775         mouse_button_state &= ~0x01;
00776         send_keyboard_mouse_status();
00777         mouse_update = 0;
00778         break;
00779 
00780       case Button2:
00781         mouse_button_state &= ~0x04;
00782         send_keyboard_mouse_status();
00783         mouse_update = 0;
00784         break;
00785 
00786       case Button3:
00787         mouse_button_state &= ~0x02;
00788         send_keyboard_mouse_status();
00789         mouse_update = 0;
00790         break;
00791 
00792       case Button4:
00793         current_z = 1;
00794         send_keyboard_mouse_status();
00795         mouse_update = 0;
00796         break;
00797 
00798       case Button5:
00799         current_z = -1;
00800         send_keyboard_mouse_status();
00801         mouse_update = 0;
00802         break;
00803       }
00804       break;
00805 
00806     case KeyPress:
00807       key_event = (XKeyEvent*) &report;
00808       charcount = XLookupString(key_event, buffer, bufsize, &keysym, &compose);
00809       xkeypress(keysym, 0);
00810       break;
00811 
00812     case KeyRelease:
00813       key_event = (XKeyEvent*) &report;
00814       charcount = XLookupString(key_event, buffer, bufsize, &keysym, &compose);
00815       xkeypress(keysym, 1);
00816       break;
00817 
00818     case MotionNotify:
00819       pointer_event = (XPointerMovedEvent*) &report;
00820       current_x = pointer_event->x;
00821       current_y = pointer_event->y;
00822       mouse_update = 1;
00823       break;
00824 
00825     case EnterNotify:
00826       enter_event = (XEnterWindowEvent*) &report;
00827       prev_x = current_x = enter_event->x;
00828       prev_y = current_y = enter_event->y;
00829       break;
00830 
00831     case LeaveNotify:
00832       leave_event = (XLeaveWindowEvent*) &report;
00833       prev_x = current_x = -1;
00834       prev_y = current_y = -1;
00835       break;
00836 
00837     case MapNotify:
00838 
00839       /* screen needs redraw, since X would have tossed previous
00840        * requests before window mapped
00841        */
00842 
00843       //retval = 1;
00844       break;
00845 
00846     case ClientMessage:
00847       if(!strcmp(XGetAtomName(bx_x_display, report.xclient.message_type),
00848          "WM_PROTOCOLS"))
00849       {
00850         FAILURE(Graceful,"Emulator stopped from X");
00851 
00852         //bx_stop_simulation();
00853       }
00854       break;
00855 
00856     default:
00857 
00858       // (mch) Ignore...
00859       BX_DEBUG(("XXX: default Xevent type"));
00860 
00861       /* all events selected by StructureNotifyMask are thrown away here,
00862        * since nothing is done with them */
00863       break;
00864     }           /* end switch */
00865   }             /* end while */
00866 
00867   if(mouse_update)
00868   {
00869     BX_DEBUG(("handle_events(): send mouse status"));
00870     send_keyboard_mouse_status();
00871   }
00872 }
00873 
00874 void send_keyboard_mouse_status(void)
00875 {
00876   BX_DEBUG(("XXX: prev=(%d,%d) curr=(%d,%d)", prev_x, prev_y, current_x, current_y));
00877 
00878   if(((prev_x != -1) && (current_x != -1) && (prev_y != -1) && (current_y != -1)
00879      ) || (current_z != 0))
00880   {
00881     int dx;
00882 
00883     int dy;
00884 
00885     int dz;
00886 
00887     // (mch) consider warping here
00888     dx = current_x - prev_x - warp_dx;
00889     dy = -(current_y - prev_y - warp_dy);
00890     dz = current_z;
00891     warp_cursor(warp_home_x - current_x, warp_home_y - current_y);
00892 
00893     //DEV_mouse_motion_ext (dx, dy, dz, mouse_button_state);
00894     prev_x = current_x;
00895     prev_y = current_y;
00896   }
00897   else
00898   {
00899     if((current_x != -1) && (current_y != -1))
00900     {
00901       prev_x = current_x;
00902       prev_y = current_y;
00903     }
00904     else
00905     {
00906       prev_x = current_x = -1;
00907       prev_y = current_y = -1;
00908     }
00909   }
00910 }
00911 
00912 void bx_x11_gui_c::flush(void)
00913 {
00914   if(bx_x_display)
00915     XFlush(bx_x_display);
00916 }
00917 
00918 void xkeypress(KeySym keysym, int press_release)
00919 {
00920   u32 key_event;
00921 
00922   if((keysym == XK_Control_L) || (keysym == XK_Control_R))
00923   {
00924     CTRL_pressed = !press_release;
00925   }
00926 
00927   /* Old (no mapping) behavior */
00928   if(!x_keymapping)
00929   {
00930 
00931     //if (!SIM->get_param_bool(BXPN_KBD_USEMAPPING)->get()) {
00932     // this depends on the fact that the X11 keysyms which
00933     // correspond to the ascii characters space .. tilde
00934     // are in consequtive order.
00935     if((keysym >= XK_space) && (keysym <= XK_asciitilde))
00936     {
00937       key_event = ascii_to_key_event[keysym - XK_space];
00938     }
00939     else
00940     {
00941       switch(keysym)
00942       {
00943       case XK_KP_1:
00944 #ifdef XK_KP_End
00945 
00946       case XK_KP_End:
00947 #endif
00948         key_event = BX_KEY_KP_END;
00949         break;
00950 
00951       case XK_KP_2:
00952 #ifdef XK_KP_Down
00953 
00954       case XK_KP_Down:
00955 #endif
00956         key_event = BX_KEY_KP_DOWN;
00957         break;
00958 
00959       case XK_KP_3:
00960 #ifdef XK_KP_Page_Down
00961 
00962       case XK_KP_Page_Down:
00963 #endif
00964         key_event = BX_KEY_KP_PAGE_DOWN;
00965         break;
00966 
00967       case XK_KP_4:
00968 #ifdef XK_KP_Left
00969 
00970       case XK_KP_Left:
00971 #endif
00972         key_event = BX_KEY_KP_LEFT;
00973         break;
00974 
00975       case XK_KP_5:
00976 #ifdef XK_KP_Begin
00977 
00978       case XK_KP_Begin:
00979 #endif
00980         key_event = BX_KEY_KP_5;
00981         break;
00982 
00983       case XK_KP_6:
00984 #ifdef XK_KP_Right
00985 
00986       case XK_KP_Right:
00987 #endif
00988         key_event = BX_KEY_KP_RIGHT;
00989         break;
00990 
00991       case XK_KP_7:
00992 #ifdef XK_KP_Home
00993 
00994       case XK_KP_Home:
00995 #endif
00996         key_event = BX_KEY_KP_HOME;
00997         break;
00998 
00999       case XK_KP_8:
01000 #ifdef XK_KP_Up
01001 
01002       case XK_KP_Up:
01003 #endif
01004         key_event = BX_KEY_KP_UP;
01005         break;
01006 
01007       case XK_KP_9:
01008 #ifdef XK_KP_Page_Up
01009 
01010       case XK_KP_Page_Up:
01011 #endif
01012         key_event = BX_KEY_KP_PAGE_UP;
01013         break;
01014 
01015       case XK_KP_0:
01016 #ifdef XK_KP_Insert
01017 
01018       case XK_KP_Insert:
01019 #endif
01020         key_event = BX_KEY_KP_INSERT;
01021         break;
01022 
01023       case XK_KP_Decimal:
01024 #ifdef XK_KP_Delete
01025 
01026       case XK_KP_Delete:
01027 #endif
01028         key_event = BX_KEY_KP_DELETE;
01029         break;
01030 
01031 #ifdef XK_KP_Enter
01032 
01033       case XK_KP_Enter:
01034         key_event = BX_KEY_KP_ENTER;
01035         break;
01036 #endif
01037 
01038       case XK_KP_Subtract:
01039         key_event = BX_KEY_KP_SUBTRACT;
01040         break;
01041 
01042       case XK_KP_Add:
01043         key_event = BX_KEY_KP_ADD;
01044         break;
01045 
01046       case XK_KP_Multiply:
01047         key_event = BX_KEY_KP_MULTIPLY;
01048         break;
01049 
01050       case XK_KP_Divide:
01051         key_event = BX_KEY_KP_DIVIDE;
01052         break;
01053 
01054       case XK_Up:
01055         key_event = BX_KEY_UP;
01056         break;
01057 
01058       case XK_Down:
01059         key_event = BX_KEY_DOWN;
01060         break;
01061 
01062       case XK_Left:
01063         key_event = BX_KEY_LEFT;
01064         break;
01065 
01066       case XK_Right:
01067         key_event = BX_KEY_RIGHT;
01068         break;
01069 
01070       case XK_Delete:
01071         key_event = BX_KEY_DELETE;
01072         break;
01073 
01074       case XK_BackSpace:
01075         key_event = BX_KEY_BACKSPACE;
01076         break;
01077 
01078       case XK_Tab:
01079         key_event = BX_KEY_TAB;
01080         break;
01081 #ifdef XK_ISO_Left_Tab
01082 
01083       case XK_ISO_Left_Tab:
01084         key_event = BX_KEY_TAB;
01085         break;
01086 #endif
01087 
01088       case XK_Return:
01089         key_event = BX_KEY_ENTER;
01090         break;
01091 
01092       case XK_Escape:
01093         key_event = BX_KEY_ESC;
01094         break;
01095 
01096       case XK_F1:
01097         key_event = BX_KEY_F1;
01098         break;
01099 
01100       case XK_F2:
01101         key_event = BX_KEY_F2;
01102         break;
01103 
01104       case XK_F3:
01105         key_event = BX_KEY_F3;
01106         break;
01107 
01108       case XK_F4:
01109         key_event = BX_KEY_F4;
01110         break;
01111 
01112       case XK_F5:
01113         key_event = BX_KEY_F5;
01114         break;
01115 
01116       case XK_F6:
01117         key_event = BX_KEY_F6;
01118         break;
01119 
01120       case XK_F7:
01121         key_event = BX_KEY_F7;
01122         break;
01123 
01124       case XK_F8:
01125         key_event = BX_KEY_F8;
01126         break;
01127 
01128       case XK_F9:
01129         key_event = BX_KEY_F9;
01130         break;
01131 
01132       case XK_F10:
01133         key_event = BX_KEY_F10;
01134         break;
01135 
01136       case XK_F11:
01137         key_event = BX_KEY_F11;
01138         break;
01139 
01140       case XK_F12:
01141         key_event = BX_KEY_F12;
01142         break;
01143 
01144       case XK_Control_L:
01145         key_event = BX_KEY_CTRL_L;
01146         break;
01147 #ifdef XK_Control_R
01148 
01149       case XK_Control_R:
01150         key_event = BX_KEY_CTRL_R;
01151         break;
01152 #endif
01153 
01154       case XK_Shift_L:
01155         key_event = BX_KEY_SHIFT_L;
01156         break;
01157 
01158       case XK_Shift_R:
01159         key_event = BX_KEY_SHIFT_R;
01160         break;
01161 
01162       case XK_Alt_L:
01163         key_event = BX_KEY_ALT_L;
01164         break;
01165 #ifdef XK_Alt_R
01166 
01167       case XK_Alt_R:
01168         key_event = BX_KEY_ALT_R;
01169         break;
01170 #endif
01171 
01172       case XK_Caps_Lock:
01173         key_event = BX_KEY_CAPS_LOCK;
01174         break;
01175 
01176       case XK_Num_Lock:
01177         key_event = BX_KEY_NUM_LOCK;
01178         break;
01179 #ifdef XK_Scroll_Lock
01180 
01181       case XK_Scroll_Lock:
01182         key_event = BX_KEY_SCRL_LOCK;
01183         break;
01184 #endif
01185 #ifdef XK_Print
01186 
01187       case XK_Print:
01188         key_event = BX_KEY_PRINT;
01189         break;
01190 #endif
01191 #ifdef XK_Pause
01192 
01193       case XK_Pause:
01194         key_event = BX_KEY_PAUSE;
01195         break;
01196 #endif
01197 
01198       case XK_Insert:
01199         key_event = BX_KEY_INSERT;
01200         break;
01201 
01202       case XK_Home:
01203         key_event = BX_KEY_HOME;
01204         break;
01205 
01206       case XK_End:
01207         key_event = BX_KEY_END;
01208         break;
01209 
01210       case XK_Page_Up:
01211         key_event = BX_KEY_PAGE_UP;
01212         break;
01213 
01214       case XK_Page_Down:
01215         key_event = BX_KEY_PAGE_DOWN;
01216         break;
01217 
01218       default:
01219         BX_ERROR(("xkeypress(): keysym %x unhandled!", (unsigned) keysym));
01220         return;
01221         break;
01222       }
01223     }
01224   }
01225   else
01226   {
01227 
01228     /* use mapping */
01229     BXKeyEntry*   entry = bx_keymap->findHostKey(keysym);
01230     if(!entry)
01231     {
01232       BX_ERROR(("xkeypress(): keysym %x unhandled!", (unsigned) keysym));
01233       return;
01234     }
01235 
01236     key_event = entry->baseKey;
01237   }
01238 
01239   if(press_release)
01240     key_event |= BX_KEY_RELEASED;
01241 
01242   theKeyboard->gen_scancode(key_event);
01243 }
01244 
01245 void bx_x11_gui_c::clear_screen(void)
01246 {
01247   XClearArea(bx_x_display, win, 0, 0, dimension_x, dimension_y, 0);
01248 }
01249 
01250 void bx_x11_gui_c::text_update(u8*  old_text, u8*  new_text,
01251                                unsigned long cursor_x, unsigned long cursor_y,
01252                                bx_vga_tminfo_t tm_info, unsigned nrows)
01253 {
01254   u8*           old_line;
01255 
01256   u8 *new_line;
01257 
01258   u8 *text_base;
01259   u8            cChar;
01260   unsigned int  curs;
01261   unsigned int  hchars;
01262   unsigned int  i;
01263   unsigned int  j;
01264   unsigned int  offset;
01265   unsigned int  rows;
01266   unsigned int  x;
01267   unsigned int  y;
01268   unsigned int  xc;
01269   unsigned int  yc;
01270   unsigned int  yc2;
01271   unsigned int  cs_y;
01272   unsigned      new_foreground;
01273   unsigned      new_background;
01274   u8            cfwidth;
01275   u8            cfheight;
01276   u8            cfheight2;
01277   u8            font_col;
01278   u8            font_row;
01279   u8            font_row2;
01280   u8            split_textrow;
01281   u8            split_fontrows;
01282   bool          forceUpdate = 0;
01283   bool          split_screen;
01284   unsigned char cell[64];
01285   unsigned long text_palette[16];
01286 
01287   if(charmap_updated)
01288   {
01289     BX_INFO(("charmap update. Font Height is %d", font_height));
01290     for(unsigned c = 0; c < 256; c++)
01291     {
01292       if(char_changed[c])
01293       {
01294         XFreePixmap(bx_x_display, vgafont[c]);
01295 
01296         bool  gfxchar = tm_info.line_graphics && ((c & 0xE0) == 0xC0);
01297         j = 0;
01298         memset(cell, 0, sizeof(cell));
01299         for(i = 0; i < font_height * 2; i += 2)
01300         {
01301           cell[i] |= ((vga_charmap[(c << 5) + j] & 0x01) << 7);
01302           cell[i] |= ((vga_charmap[(c << 5) + j] & 0x02) << 5);
01303           cell[i] |= ((vga_charmap[(c << 5) + j] & 0x04) << 3);
01304           cell[i] |= ((vga_charmap[(c << 5) + j] & 0x08) << 1);
01305           cell[i] |= ((vga_charmap[(c << 5) + j] & 0x10) >> 1);
01306           cell[i] |= ((vga_charmap[(c << 5) + j] & 0x20) >> 3);
01307           cell[i] |= ((vga_charmap[(c << 5) + j] & 0x40) >> 5);
01308           cell[i] |= ((vga_charmap[(c << 5) + j] & 0x80) >> 7);
01309           if(gfxchar)
01310           {
01311             cell[i + 1] = (vga_charmap[(c << 5) + j] & 0x01);
01312           }
01313 
01314           j++;
01315         }
01316 
01317         vgafont[c] = XCreateBitmapFromData(bx_x_display, win, (const char*) cell,
01318                                            9, font_height);
01319         if(vgafont[c] == None)
01320           BX_PANIC(("Can't create vga font [%d]", c));
01321         char_changed[c] = 0;
01322       }
01323     }
01324 
01325     forceUpdate = 1;
01326     charmap_updated = 0;
01327   }
01328 
01329   for(i = 0; i < 16; i++)
01330   {
01331     text_palette[i] = col_vals[theVGA->get_actl_palette_idx(i)];
01332   }
01333 
01334   if((tm_info.h_panning != h_panning) || (tm_info.v_panning != v_panning))
01335   {
01336     forceUpdate = 1;
01337     h_panning = tm_info.h_panning;
01338     v_panning = tm_info.v_panning;
01339   }
01340 
01341   if(tm_info.line_compare != line_compare)
01342   {
01343     forceUpdate = 1;
01344     line_compare = tm_info.line_compare;
01345   }
01346 
01347   // first invalidate character at previous and new cursor location
01348   if((prev_cursor_y < text_rows) && (prev_cursor_x < text_cols))
01349   {
01350     curs = prev_cursor_y * tm_info.line_offset + prev_cursor_x * 2;
01351     old_text[curs] = ~new_text[curs];
01352   }
01353 
01354   if((tm_info.cs_start <= tm_info.cs_end) && (tm_info.cs_start < font_height)
01355    && (cursor_y < text_rows) && (cursor_x < text_cols))
01356   {
01357     curs = cursor_y * tm_info.line_offset + cursor_x * 2;
01358     old_text[curs] = ~new_text[curs];
01359   }
01360   else
01361   {
01362     curs = 0xffff;
01363   }
01364 
01365   rows = text_rows;
01366   if(v_panning)
01367     rows++;
01368   y = 0;
01369   cs_y = 0;
01370   text_base = new_text - tm_info.start_address;
01371   split_textrow = (line_compare + v_panning) / font_height;
01372   split_fontrows = ((line_compare + v_panning) % font_height) + 1;
01373   split_screen = 0;
01374   do
01375   {
01376     hchars = text_cols;
01377     if(h_panning)
01378       hchars++;
01379     if(split_screen)
01380     {
01381       yc = line_compare + cs_y * font_height + 1;
01382       font_row = 0;
01383       if(rows == 1)
01384       {
01385         cfheight = (dimension_y - line_compare - 1) % font_height;
01386         if(cfheight == 0)
01387           cfheight = font_height;
01388       }
01389       else
01390       {
01391         cfheight = font_height;
01392       }
01393     }
01394     else if(v_panning)
01395     {
01396       if(y == 0)
01397       {
01398         yc = 0;
01399         font_row = v_panning;
01400         cfheight = font_height - v_panning;
01401       }
01402       else
01403       {
01404         yc = y * font_height - v_panning;
01405         font_row = 0;
01406         if(rows == 1)
01407         {
01408           cfheight = v_panning;
01409         }
01410         else
01411         {
01412           cfheight = font_height;
01413         }
01414       }
01415     }
01416     else
01417     {
01418       yc = y * font_height;
01419       font_row = 0;
01420       cfheight = font_height;
01421     }
01422 
01423     if(!split_screen && (y == split_textrow))
01424     {
01425       if(split_fontrows < cfheight)
01426         cfheight = split_fontrows;
01427     }
01428 
01429     new_line = new_text;
01430     old_line = old_text;
01431     x = 0;
01432     offset = cs_y * tm_info.line_offset;
01433     do
01434     {
01435       if(h_panning)
01436       {
01437         if(hchars > text_cols)
01438         {
01439           xc = 0;
01440           font_col = h_panning;
01441           cfwidth = font_width - h_panning;
01442         }
01443         else
01444         {
01445           xc = x * font_width - h_panning;
01446           font_col = 0;
01447           if(hchars == 1)
01448           {
01449             cfwidth = h_panning;
01450           }
01451           else
01452           {
01453             cfwidth = font_width;
01454           }
01455         }
01456       }
01457       else
01458       {
01459         xc = x * font_width;
01460         font_col = 0;
01461         cfwidth = font_width;
01462       }
01463 
01464       if(forceUpdate || (old_text[0] != new_text[0])
01465        || (old_text[1] != new_text[1]))
01466       {
01467         cChar = new_text[0];
01468         new_foreground = new_text[1] & 0x0f;
01469         new_background = (new_text[1] & 0xf0) >> 4;
01470 
01471         XSetForeground(bx_x_display, gc, text_palette[new_foreground]);
01472         XSetBackground(bx_x_display, gc, text_palette[new_background]);
01473 
01474         XCopyPlane(bx_x_display, vgafont[cChar], win, gc, font_col, font_row,
01475                    cfwidth, cfheight, xc, yc, 1);
01476         if(offset == curs)
01477         {
01478           XSetForeground(bx_x_display, gc, text_palette[new_background]);
01479           XSetBackground(bx_x_display, gc, text_palette[new_foreground]);
01480           if(font_row == 0)
01481           {
01482             yc2 = yc + tm_info.cs_start;
01483             font_row2 = tm_info.cs_start;
01484             cfheight2 = tm_info.cs_end - tm_info.cs_start + 1;
01485             if((yc2 + cfheight2) > (dimension_y))
01486             {
01487               cfheight2 = dimension_y - yc2;
01488             }
01489           }
01490           else
01491           {
01492             if(v_panning > tm_info.cs_start)
01493             {
01494               yc2 = yc;
01495               font_row2 = font_row;
01496               cfheight2 = tm_info.cs_end - v_panning + 1;
01497             }
01498             else
01499             {
01500               yc2 = yc + tm_info.cs_start - v_panning;
01501               font_row2 = tm_info.cs_start;
01502               cfheight2 = tm_info.cs_end - tm_info.cs_start + 1;
01503             }
01504           }
01505 
01506           if(yc2 < (dimension_y))
01507           {
01508             XCopyPlane(bx_x_display, vgafont[cChar], win, gc, font_col,
01509                        font_row2, cfwidth, cfheight2, xc, yc2, 1);
01510           }
01511         }
01512       }
01513 
01514       x++;
01515       new_text += 2;
01516       old_text += 2;
01517       offset += 2;
01518     } while(--hchars);
01519     if(!split_screen && (y == split_textrow))
01520     {
01521       new_text = text_base;
01522       forceUpdate = 1;
01523       cs_y = 0;
01524       if(tm_info.split_hpanning)
01525         h_panning = 0;
01526       rows = ((dimension_y - line_compare + font_height - 2) / font_height) + 1;
01527       split_screen = 1;
01528     }
01529     else
01530     {
01531       y++;
01532       cs_y++;
01533       new_text = new_line + tm_info.line_offset;
01534       old_text = old_line + tm_info.line_offset;
01535     }
01536   } while(--rows);
01537 
01538   h_panning = tm_info.h_panning;
01539   prev_cursor_x = cursor_x;
01540   prev_cursor_y = cursor_y;
01541 
01542   XFlush(bx_x_display);
01543 }
01544 
01545 void bx_x11_gui_c::graphics_tile_update(u8* tile, unsigned x0, unsigned y0)
01546 {
01547   unsigned  x;
01548 
01549   unsigned  y;
01550 
01551   unsigned  y_size;
01552   unsigned  color;
01553   unsigned  offset;
01554   u8        b0;
01555   u8        b1;
01556   u8        b2;
01557   u8        b3;
01558 
01559   if((y0 + y_tilesize) > dimension_y)
01560   {
01561     y_size = dimension_y - y0;
01562   }
01563   else
01564   {
01565     y_size = y_tilesize;
01566   }
01567 
01568   switch(vga_bpp)
01569   {
01570   case 8:       // 8 bits per pixel
01571     for(y = 0; y < y_size; y++)
01572     {
01573       for(x = 0; x < x_tilesize; x++)
01574       {
01575         color = col_vals[tile[y * x_tilesize + x]];
01576         switch(imBPP)
01577         {
01578         case 8: // 8 bits per pixel
01579           ximage->data[imWide * y + x] = color;
01580           break;
01581 
01582         case 16:  // 16 bits per pixel
01583           offset = imWide * y + 2 * x;
01584           b0 = color >> 0;
01585           b1 = color >> 8;
01586           if(ximage->byte_order == LSBFirst)
01587           {
01588             ximage->data[offset + 0] = b0;
01589             ximage->data[offset + 1] = b1;
01590           }
01591           else
01592           {       // MSBFirst
01593             ximage->data[offset + 0] = b1;
01594             ximage->data[offset + 1] = b0;
01595           }
01596           break;
01597 
01598         case 24:  // 24 bits per pixel
01599           offset = imWide * y + 3 * x;
01600           b0 = color >> 0;
01601           b1 = color >> 8;
01602           b2 = color >> 16;
01603           if(ximage->byte_order == LSBFirst)
01604           {
01605             ximage->data[offset + 0] = b0;
01606             ximage->data[offset + 1] = b1;
01607             ximage->data[offset + 2] = b2;
01608           }
01609           else
01610           {       // MSBFirst
01611             ximage->data[offset + 0] = b2;
01612             ximage->data[offset + 1] = b1;
01613             ximage->data[offset + 2] = b0;
01614           }
01615           break;
01616 
01617         case 32:  // 32 bits per pixel
01618           offset = imWide * y + 4 * x;
01619           b0 = color >> 0;
01620           b1 = color >> 8;
01621           b2 = color >> 16;
01622           b3 = color >> 24;
01623           if(ximage->byte_order == LSBFirst)
01624           {
01625             ximage->data[offset + 0] = b0;
01626             ximage->data[offset + 1] = b1;
01627             ximage->data[offset + 2] = b2;
01628             ximage->data[offset + 3] = b3;
01629           }
01630           else
01631           {       // MSBFirst
01632             ximage->data[offset + 0] = b3;
01633             ximage->data[offset + 1] = b2;
01634             ximage->data[offset + 2] = b1;
01635             ximage->data[offset + 3] = b0;
01636           }
01637           break;
01638 
01639         default:
01640           BX_PANIC((
01641                      "X_graphics_tile_update: bits_per_pixel %u not implemented",
01642                      (unsigned) imBPP));
01643           return;
01644         }
01645       }
01646     }
01647     break;
01648 
01649   default:
01650     BX_PANIC((
01651                "X_graphics_tile_update: bits_per_pixel %u handled by new graphics API",
01652            (unsigned) vga_bpp));
01653     return;
01654   }
01655 
01656   XPutImage(bx_x_display, win, gc, ximage, 0, 0, x0, y0, x_tilesize, y_size);
01657 }
01658 
01659 bx_svga_tileinfo_t* bx_x11_gui_c::graphics_tile_info(bx_svga_tileinfo_t* info)
01660 {
01661   if(!info)
01662   {
01663     info = (bx_svga_tileinfo_t*) malloc(sizeof(bx_svga_tileinfo_t));
01664     if(!info)
01665     {
01666       return NULL;
01667     }
01668   }
01669 
01670   info->bpp = ximage->bits_per_pixel;
01671   info->pitch = ximage->bytes_per_line;
01672   info->red_shift = 0;
01673   info->green_shift = 0;
01674   info->blue_shift = 0;
01675   info->red_mask = ximage->red_mask;
01676   info->green_mask = ximage->green_mask;
01677   info->blue_mask = ximage->blue_mask;
01678 
01679   int           i;
01680 
01681   int           rf;
01682 
01683   int           gf;
01684 
01685   int           bf;
01686   unsigned long red;
01687   unsigned long green;
01688   unsigned long blue;
01689 
01690   i = rf = gf = bf = 0;
01691   red = ximage->red_mask;
01692   green = ximage->green_mask;
01693   blue = ximage->blue_mask;
01694 
01695   while(red || rf || green || gf || blue || bf)
01696   {
01697     if(rf)
01698     {
01699       if(!(red & 1))
01700       {
01701         info->red_shift = i;
01702         rf = 0;
01703       }
01704     }
01705     else
01706     {
01707       if(red & 1)
01708       {
01709         rf = 1;
01710       }
01711     }
01712 
01713     if(gf)
01714     {
01715       if(!(green & 1))
01716       {
01717         info->green_shift = i;
01718         gf = 0;
01719       }
01720     }
01721     else
01722     {
01723       if(green & 1)
01724       {
01725         gf = 1;
01726       }
01727     }
01728 
01729     if(bf)
01730     {
01731       if(!(blue & 1))
01732       {
01733         info->blue_shift = i;
01734         bf = 0;
01735       }
01736     }
01737     else
01738     {
01739       if(blue & 1)
01740       {
01741         bf = 1;
01742       }
01743     }
01744 
01745     i++;
01746     red >>= 1;
01747     green >>= 1;
01748     blue >>= 1;
01749   }
01750 
01751   info->is_indexed = (default_visual->c_class != TrueColor)
01752 && (default_visual->c_class != DirectColor);
01753   info->is_little_endian = (ximage->byte_order == LSBFirst);
01754 
01755   return info;
01756 }
01757 
01758 u8* bx_x11_gui_c::graphics_tile_get(unsigned x0, unsigned y0, unsigned*  w,
01759                                     unsigned*  h)
01760 {
01761   if(x0 + x_tilesize > dimension_x)
01762   {
01763     *w = dimension_x - x0;
01764   }
01765   else
01766   {
01767     *w = x_tilesize;
01768   }
01769 
01770   if(y0 + y_tilesize > dimension_y)
01771   {
01772     *h = dimension_y - y0;
01773   }
01774   else
01775   {
01776     *h = y_tilesize;
01777   }
01778 
01779   return (u8*) ximage->data + ximage->xoffset * ximage->bits_per_pixel / 8;
01780 }
01781 
01782 void bx_x11_gui_c::graphics_tile_update_in_place(unsigned x0, unsigned y0,
01783                                                  unsigned w, unsigned h)
01784 {
01785   XPutImage(bx_x_display, win, gc, ximage, 0, 0, x0, y0, w, h);
01786 }
01787 
01788 bool bx_x11_gui_c::palette_change(unsigned index, unsigned red, unsigned green,
01789                                   unsigned blue)
01790 {
01791 
01792   // returns: 0=no screen update needed (color map change has direct effect)
01793   //          1=screen updated needed (redraw using current colormap)
01794   XColor  color;
01795 
01796   color.flags = DoRed | DoGreen | DoBlue;
01797   color.red = red << 8;
01798   color.green = green << 8;
01799   color.blue = blue << 8;
01800 
01801   if(x_private_colormap)
01802   {
01803 
01804     //if (SIM->get_param_bool(BXPN_PRIVATE_COLORMAP)->get()) {
01805     color.pixel = index;
01806     XStoreColor(bx_x_display, default_cmap, &color);
01807     return(0);    // no screen update needed
01808   }
01809   else
01810   {
01811     XAllocColor(bx_x_display, DefaultColormap(bx_x_display, bx_x_screen_num),
01812                 &color);
01813     col_vals[index] = color.pixel;
01814     return(1);    // screen update needed
01815   }
01816 }
01817 
01818 void bx_x11_gui_c::dimension_update(unsigned x, unsigned y, unsigned fheight,
01819                                     unsigned fwidth, unsigned bpp)
01820 {
01821   if((bpp == 8) || (bpp == 15) || (bpp == 16) || (bpp == 24) || (bpp == 32))
01822   {
01823     vga_bpp = bpp;
01824   }
01825   else
01826   {
01827     BX_PANIC(("%d bpp graphics mode not supported", bpp));
01828   }
01829 
01830   if(fheight > 0)
01831   {
01832     font_height = fheight;
01833     font_width = fwidth;
01834     text_cols = x / font_width;
01835     text_rows = y / font_height;
01836   }
01837 
01838   if((x != dimension_x) || (y != dimension_y))
01839   {
01840     XSizeHints  hints;
01841     long        supplied_return;
01842 
01843     if(XGetWMNormalHints(bx_x_display, win, &hints, &supplied_return)
01844      && supplied_return & PMaxSize)
01845     {
01846       hints.max_width = hints.min_width = x;
01847       hints.max_height = hints.min_height = y;
01848       XSetWMNormalHints(bx_x_display, win, &hints);
01849     }
01850 
01851     XResizeWindow(bx_x_display, win, x, y);
01852     dimension_x = x;
01853     dimension_y = y;
01854   }
01855 }
01856 
01857 void bx_x11_gui_c::exit(void)
01858 {
01859   if(!x_init_done)
01860     return;
01861 
01862   // Delete the font bitmaps
01863   for(int i = 0; i < 256; i++)
01864   {
01865 
01866     //if (vgafont[i] != NULL)
01867     XFreePixmap(bx_x_display, vgafont[i]);
01868   }
01869 
01870   if(bx_x_display)
01871     XCloseDisplay(bx_x_display);
01872   BX_INFO(("Exit."));
01873 }
01874 
01875 static void warp_cursor(int dx, int dy)
01876 {
01877   if(warp_dx || warp_dy || dx || dy)
01878   {
01879     warp_dx = dx;
01880     warp_dy = dy;
01881     XWarpPointer(bx_x_display, None, None, 0, 0, 0, 0, dx, dy);
01882   }
01883 }
01884 
01885 static void disable_cursor()
01886 {
01887   static Cursor   cursor;
01888   static unsigned cursor_created = 0;
01889 
01890   static int      shape_width = 16;
01891   static int      shape_height = 16;
01892   static int      mask_width = 16;
01893   static int      mask_height = 16;
01894 
01895   static u32      shape_bits[(16 * 16) / 32] = {
01896     0x00000000, 0x00000000, 0x00000000, 0x00000000,
01897     0x00000000, 0x00000000, 0x00000000, 0x00000000,
01898   };
01899   static u32      mask_bits[(16 * 16) / 32] = {
01900     0x00000000, 0x00000000, 0x00000000, 0x00000000,
01901     0x00000000, 0x00000000, 0x00000000, 0x00000000,
01902   };
01903 
01904   if(!cursor_created)
01905   {
01906     Pixmap  shape;
01907 
01908     Pixmap  mask;
01909     XColor  white;
01910     XColor  black;
01911     shape = XCreatePixmapFromBitmapData(bx_x_display,
01912                                         RootWindow(bx_x_display, bx_x_screen_num),
01913                                           (char*) shape_bits, shape_width,
01914                                           shape_height, 1, 0, 1);
01915     mask = XCreatePixmapFromBitmapData(bx_x_display,
01916                                        RootWindow(bx_x_display, bx_x_screen_num),
01917                                          (char*) mask_bits, mask_width,
01918                                          mask_height, 1, 0, 1);
01919     XParseColor(bx_x_display, default_cmap, "black", &black);
01920     XParseColor(bx_x_display, default_cmap, "white", &white);
01921     cursor = XCreatePixmapCursor(bx_x_display, shape, mask, &white, &black, 1, 1);
01922     cursor_created = 1;
01923   }
01924 
01925   XDefineCursor(bx_x_display, win, cursor);
01926 }
01927 
01928 static void enable_cursor()
01929 {
01930   XUndefineCursor(bx_x_display, win);
01931 }
01932 
01933 /* convertStringToXKeysym is a keymap callback
01934  * used when reading the keymap file.
01935  * It converts a Symblic String to a GUI Constant
01936  *
01937  * It returns a u32 constant or BX_KEYMAP_UNKNOWN if it fails
01938  */
01939 static u32 convertStringToXKeysym(const char* string)
01940 {
01941   if(strncmp("XK_", string, 3) != 0)
01942     return BX_KEYMAP_UNKNOWN;
01943 
01944   KeySym  keysym = XStringToKeysym(string + 3);
01945 
01946   // failure, return unknown
01947   if(keysym == NoSymbol)
01948     return BX_KEYMAP_UNKNOWN;
01949 
01950   return((u32) keysym);
01951 }
01952 
01953 void bx_x11_gui_c::get_capabilities(u16* xres, u16* yres, u16* bpp)
01954 {
01955   *xres = 1024;
01956   *yres = 768;
01957   *bpp = 32;
01958 }
01959 #endif /* if BX_WITH_X11 */

SourceForge.net Logo
Project space on SourceForge.net