/[rdesktop]/sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Diff of /sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

sourceforge.net/trunk/rdesktop/xwin.c revision 823 by stargo, Mon Feb 28 23:30:00 2005 UTC sourceforge.net/branches/seamlessrdp-branch/rdesktop/xwin.c revision 1058, Tue Mar 7 08:17:41 2006 UTC
# Line 1  Line 1 
1  /* -*- c-basic-offset: 8 -*-  /* -*- c-basic-offset: 8 -*-
2     rdesktop: A Remote Desktop Protocol client.     rdesktop: A Remote Desktop Protocol client.
3     User interface services - X Window System     User interface services - X Window System
4     Copyright (C) Matthew Chapman 1999-2002     Copyright (C) Matthew Chapman 1999-2005
5    
6     This program is free software; you can redistribute it and/or modify     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by     it under the terms of the GNU General Public License as published by
# Line 32  extern int g_width; Line 32  extern int g_width;
32  extern int g_height;  extern int g_height;
33  extern int g_xpos;  extern int g_xpos;
34  extern int g_ypos;  extern int g_ypos;
35    extern int g_pos;
36  extern BOOL g_sendmotion;  extern BOOL g_sendmotion;
37  extern BOOL g_fullscreen;  extern BOOL g_fullscreen;
38  extern BOOL g_grab_keyboard;  extern BOOL g_grab_keyboard;
39  extern BOOL g_hide_decorations;  extern BOOL g_hide_decorations;
40  extern char g_title[];  extern char g_title[];
41  extern int g_server_bpp;  /* Color depth of the RDP session.
42       As of RDP 5.1, it may be 8, 15, 16 or 24. */
43    extern int g_server_depth;
44  extern int g_win_button_size;  extern int g_win_button_size;
45    
46  Display *g_display;  Display *g_display;
# Line 52  static GC g_gc = NULL; Line 55  static GC g_gc = NULL;
55  static GC g_create_bitmap_gc = NULL;  static GC g_create_bitmap_gc = NULL;
56  static GC g_create_glyph_gc = NULL;  static GC g_create_glyph_gc = NULL;
57  static Visual *g_visual;  static Visual *g_visual;
58    /* Color depth of the X11 visual of our window (e.g. 24 for True Color R8G8B visual).
59       This may be 32 for R8G8B8 visuals, and then the rest of the bits are undefined
60       as far as we're concerned. */
61  static int g_depth;  static int g_depth;
62    /* Bits-per-Pixel of the pixmaps we'll be using to draw on our window.
63       This may be larger than g_depth, in which case some of the bits would
64       be kept solely for alignment (e.g. 32bpp pixmaps on a 24bpp visual). */
65  static int g_bpp;  static int g_bpp;
66  static XIM g_IM;  static XIM g_IM;
67  static XIC g_IC;  static XIC g_IC;
# Line 62  static HCURSOR g_null_cursor = NULL; Line 71  static HCURSOR g_null_cursor = NULL;
71  static Atom g_protocol_atom, g_kill_atom;  static Atom g_protocol_atom, g_kill_atom;
72  static BOOL g_focused;  static BOOL g_focused;
73  static BOOL g_mouse_in_wnd;  static BOOL g_mouse_in_wnd;
74  static BOOL g_arch_match = False;       /* set to True if RGB XServer and little endian */  /* Indicates that:
75       1) visual has 15, 16 or 24 depth and the same color channel masks
76          as its RDP equivalent (implies X server is LE),
77       2) host is LE
78       This will trigger an optimization whose real value is questionable.
79    */
80    static BOOL g_compatible_arch;
81    /* Indicates whether RDP's bitmaps and our XImages have the same
82       binary format. If so, we can avoid an expensive translation.
83       Note that this can be true when g_compatible_arch is false,
84       e.g.:
85      
86         RDP(LE) <-> host(BE) <-> X-Server(LE)
87        
88       ('host' is the machine running rdesktop; the host simply memcpy's
89        so its endianess doesn't matter)
90     */
91    static BOOL g_no_translate_image = False;
92    
93  /* endianness */  /* endianness */
94  static BOOL g_host_be;  static BOOL g_host_be;
# Line 78  static Pixmap g_backstore = 0; Line 104  static Pixmap g_backstore = 0;
104  static BOOL g_moving_wnd;  static BOOL g_moving_wnd;
105  static int g_move_x_offset = 0;  static int g_move_x_offset = 0;
106  static int g_move_y_offset = 0;  static int g_move_y_offset = 0;
107    static BOOL g_using_full_workarea = False;
108    
109  #ifdef WITH_RDPSND  #ifdef WITH_RDPSND
110  extern int g_dsp_fd;  extern int g_dsp_fd;
# Line 90  extern BOOL g_rdpsnd; Line 117  extern BOOL g_rdpsnd;
117  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5  #define PROP_MOTIF_WM_HINTS_ELEMENTS    5
118  typedef struct  typedef struct
119  {  {
120          uint32 flags;          unsigned long flags;
121          uint32 functions;          unsigned long functions;
122          uint32 decorations;          unsigned long decorations;
123          sint32 inputMode;          long inputMode;
124          uint32 status;          unsigned long status;
125  }  }
126  PropMotifWmHints;  PropMotifWmHints;
127    
# Line 119  PixelColour; Line 146  PixelColour;
146          XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \          XFillRectangle(g_display, g_ownbackstore ? g_backstore : g_wnd, g_gc, x, y, cx, cy); \
147  }  }
148    
149    #define FILL_POLYGON(p,np)\
150    { \
151            XFillPolygon(g_display, g_wnd, g_gc, p, np, Complex, CoordModePrevious); \
152            if (g_ownbackstore) \
153                    XFillPolygon(g_display, g_backstore, g_gc, p, np, Complex, CoordModePrevious); \
154    }
155    
156    #define DRAW_ELLIPSE(x,y,cx,cy,m)\
157    { \
158            switch (m) \
159            { \
160                    case 0: /* Outline */ \
161                            XDrawArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
162                            if (g_ownbackstore) \
163                                    XDrawArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
164                            break; \
165                    case 1: /* Filled */ \
166                            XFillArc(g_display, g_wnd, g_gc, x, y, cx, cy, 0, 360*64); \
167                            if (g_ownbackstore) \
168                                    XFillArc(g_display, g_backstore, g_gc, x, y, cx, cy, 0, 360*64); \
169                            break; \
170            } \
171    }
172    
173  /* colour maps */  /* colour maps */
174  extern BOOL g_owncolmap;  extern BOOL g_owncolmap;
175  static Colormap g_xcolmap;  static Colormap g_xcolmap;
176  static uint32 *g_colmap = NULL;  static uint32 *g_colmap = NULL;
177    
178  #define TRANSLATE(col)          ( g_server_bpp != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )  #define TRANSLATE(col)          ( g_server_depth != 8 ? translate_colour(col) : g_owncolmap ? col : g_colmap[col] )
179  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));  #define SET_FOREGROUND(col)     XSetForeground(g_display, g_gc, TRANSLATE(col));
180  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));  #define SET_BACKGROUND(col)     XSetBackground(g_display, g_gc, TRANSLATE(col));
181    
# Line 203  mwm_hide_decorations(void) Line 254  mwm_hide_decorations(void)
254  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \  #define BSWAP32(x) { x = (((x & 0xff00ff) << 8) | ((x >> 8) & 0xff00ff)); \
255                          x = (x << 16) | (x >> 16); }                          x = (x << 16) | (x >> 16); }
256    
257    /* The following macros output the same octet sequences
258       on both BE and LE hosts: */
259    
260  #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }  #define BOUT16(o, x) { *(o++) = x >> 8; *(o++) = x; }
261  #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }  #define BOUT24(o, x) { *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
262  #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }  #define BOUT32(o, x) { *(o++) = x >> 24; *(o++) = x >> 16; *(o++) = x >> 8; *(o++) = x; }
# Line 214  static uint32 Line 268  static uint32
268  translate_colour(uint32 colour)  translate_colour(uint32 colour)
269  {  {
270          PixelColour pc;          PixelColour pc;
271          switch (g_server_bpp)          switch (g_server_depth)
272          {          {
273                  case 15:                  case 15:
274                          SPLITCOLOUR15(colour, pc);                          SPLITCOLOUR15(colour, pc);
# Line 225  translate_colour(uint32 colour) Line 279  translate_colour(uint32 colour)
279                  case 24:                  case 24:
280                          SPLITCOLOUR24(colour, pc);                          SPLITCOLOUR24(colour, pc);
281                          break;                          break;
282                    default:
283                            /* Avoid warning */
284                            pc.red = 0;
285                            pc.green = 0;
286                            pc.blue = 0;
287                            break;
288          }          }
289          return MAKECOLOUR(pc);          return MAKECOLOUR(pc);
290  }  }
# Line 276  translate8to16(const uint8 * data, uint8 Line 336  translate8to16(const uint8 * data, uint8
336  {  {
337          uint16 value;          uint16 value;
338    
339          if (g_arch_match)          if (g_compatible_arch)
340          {          {
341                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
342                  REPEAT2                  REPEAT2
# Line 310  translate8to24(const uint8 * data, uint8 Line 370  translate8to24(const uint8 * data, uint8
370  {  {
371          uint32 value;          uint32 value;
372    
373          if (g_xserver_be)          if (g_compatible_arch)
374          {          {
375                  while (out < end)                  while (out < end)
376                  {                  {
# Line 333  translate8to32(const uint8 * data, uint8 Line 393  translate8to32(const uint8 * data, uint8
393  {  {
394          uint32 value;          uint32 value;
395    
396          if (g_arch_match)          if (g_compatible_arch)
397          {          {
398                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
399                  REPEAT4                  REPEAT4
# Line 405  translate15to24(const uint16 * data, uin Line 465  translate15to24(const uint16 * data, uin
465          uint16 pixel;          uint16 pixel;
466          PixelColour pc;          PixelColour pc;
467    
468          if (g_arch_match)          if (g_compatible_arch)
469          {          {
470                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
471                  REPEAT3                  REPEAT3
# Line 455  translate15to32(const uint16 * data, uin Line 515  translate15to32(const uint16 * data, uin
515          uint32 value;          uint32 value;
516          PixelColour pc;          PixelColour pc;
517    
518          if (g_arch_match)          if (g_compatible_arch)
519          {          {
520                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
521                  REPEAT4                  REPEAT4
# Line 563  translate16to24(const uint16 * data, uin Line 623  translate16to24(const uint16 * data, uin
623          uint16 pixel;          uint16 pixel;
624          PixelColour pc;          PixelColour pc;
625    
626          if (g_arch_match)          if (g_compatible_arch)
627          {          {
628                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
629                  REPEAT3                  REPEAT3
# Line 633  translate16to32(const uint16 * data, uin Line 693  translate16to32(const uint16 * data, uin
693          uint32 value;          uint32 value;
694          PixelColour pc;          PixelColour pc;
695    
696          if (g_arch_match)          if (g_compatible_arch)
697          {          {
698                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
699                  REPEAT4                  REPEAT4
# Line 762  translate24to32(const uint8 * data, uint Line 822  translate24to32(const uint8 * data, uint
822          uint32 value;          uint32 value;
823          PixelColour pc;          PixelColour pc;
824    
825          if (g_arch_match)          if (g_compatible_arch)
826          {          {
827                  /* *INDENT-OFF* */                  /* *INDENT-OFF* */
828  #ifdef NEED_ALIGN  #ifdef NEED_ALIGN
# Line 776  translate24to32(const uint8 * data, uint Line 836  translate24to32(const uint8 * data, uint
836  #else  #else
837                  REPEAT4                  REPEAT4
838                  (                  (
839                          *((uint32 *) out) = *((uint32 *) data);                   /* Only read 3 bytes. Reading 4 bytes means reading beyond buffer. */
840                          out += 4;                   *((uint32 *) out) = *((uint16 *) data) + (*((uint8 *) data + 2) << 16);
841                          data += 3;                   out += 4;
842                     data += 3;
843                  )                  )
844  #endif  #endif
845                  /* *INDENT-ON* */                  /* *INDENT-ON* */
# Line 816  translate_image(int width, int height, u Line 877  translate_image(int width, int height, u
877          uint8 *out;          uint8 *out;
878          uint8 *end;          uint8 *end;
879    
880          /* if server and xserver bpp match, */          /*
881          /* and arch(endian) matches, no need to translate */             If RDP depth and X Visual depths match,
882          /* just return data */             and arch(endian) matches, no need to translate:
883          if (g_arch_match)             just return data.
884               Note: select_visual should've already ensured g_no_translate
885               is only set for compatible depths, but the RDP depth might've
886               changed during connection negotiations.
887             */
888            if (g_no_translate_image)
889          {          {
890                  if (g_depth == 15 && g_server_bpp == 15)                  if ((g_depth == 15 && g_server_depth == 15) ||
891                          return data;                      (g_depth == 16 && g_server_depth == 16) ||
892                  if (g_depth == 16 && g_server_bpp == 16)                      (g_depth == 24 && g_server_depth == 24))
                         return data;  
                 if (g_depth == 24 && g_bpp == 24 && g_server_bpp == 24)  
893                          return data;                          return data;
894          }          }
895    
# Line 833  translate_image(int width, int height, u Line 897  translate_image(int width, int height, u
897          out = (uint8 *) xmalloc(size);          out = (uint8 *) xmalloc(size);
898          end = out + size;          end = out + size;
899    
900          switch (g_server_bpp)          switch (g_server_depth)
901          {          {
902                  case 24:                  case 24:
903                          switch (g_bpp)                          switch (g_bpp)
# Line 931  calculate_shifts(uint32 mask, int *shift Line 995  calculate_shifts(uint32 mask, int *shift
995          *shift_r = 8 - ffs(mask & ~(mask >> 1));          *shift_r = 8 - ffs(mask & ~(mask >> 1));
996  }  }
997    
998  BOOL  /* Given a mask of a colour channel (e.g. XVisualInfo.red_mask),
999  ui_init(void)     calculates the bits-per-pixel of this channel (a.k.a. colour weight).
1000     */
1001    static unsigned
1002    calculate_mask_weight(uint32 mask)
1003    {
1004            unsigned weight = 0;
1005            do
1006            {
1007                    weight += (mask & 1);
1008            }
1009            while (mask >>= 1);
1010            return weight;
1011    }
1012    
1013    static BOOL
1014    select_visual()
1015  {  {
         XVisualInfo vi;  
1016          XPixmapFormatValues *pfm;          XPixmapFormatValues *pfm;
1017          uint16 test;          int pixmap_formats_count, visuals_count;
         int i, screen_num, nvisuals;  
1018          XVisualInfo *vmatches = NULL;          XVisualInfo *vmatches = NULL;
1019          XVisualInfo template;          XVisualInfo template;
1020          Bool TrueColorVisual = False;          int i;
1021            unsigned red_weight, blue_weight, green_weight;
1022    
1023          g_display = XOpenDisplay(NULL);          red_weight = blue_weight = green_weight = 0;
1024          if (g_display == NULL)  
1025            pfm = XListPixmapFormats(g_display, &pixmap_formats_count);
1026            if (pfm == NULL)
1027          {          {
1028                  error("Failed to open display: %s\n", XDisplayName(NULL));                  error("Unable to get list of pixmap formats from display.\n");
1029                    XCloseDisplay(g_display);
1030                  return False;                  return False;
1031          }          }
1032    
1033          screen_num = DefaultScreen(g_display);          /* Search for best TrueColor visual */
         g_x_socket = ConnectionNumber(g_display);  
         g_screen = ScreenOfDisplay(g_display, screen_num);  
         g_depth = DefaultDepthOfScreen(g_screen);  
   
         /* Search for best TrueColor depth */  
1034          template.class = TrueColor;          template.class = TrueColor;
1035          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &nvisuals);          vmatches = XGetVisualInfo(g_display, VisualClassMask, &template, &visuals_count);
1036            g_visual = NULL;
1037            g_no_translate_image = False;
1038            g_compatible_arch = False;
1039            if (vmatches != NULL)
1040            {
1041                    for (i = 0; i < visuals_count; ++i)
1042                    {
1043                            XVisualInfo *visual_info = &vmatches[i];
1044    
1045                            /* Try to find a no-translation visual that'll
1046                               allow us to use RDP bitmaps directly as ZPixmaps. */
1047                            if (!g_xserver_be && (((visual_info->depth == 15) &&
1048                                                   /* R5G5B5 */
1049                                                   (visual_info->red_mask == 0x7c00) &&
1050                                                   (visual_info->green_mask == 0x3e0) &&
1051                                                   (visual_info->blue_mask == 0x1f)) ||
1052                                                  ((visual_info->depth == 16) &&
1053                                                   /* R5G6B5 */
1054                                                   (visual_info->red_mask == 0xf800) &&
1055                                                   (visual_info->green_mask == 0x7e0) &&
1056                                                   (visual_info->blue_mask == 0x1f)) ||
1057                                                  ((visual_info->depth == 24) &&
1058                                                   /* R8G8B8 */
1059                                                   (visual_info->red_mask == 0xff0000) &&
1060                                                   (visual_info->green_mask == 0xff00) &&
1061                                                   (visual_info->blue_mask == 0xff))))
1062                            {
1063                                    g_visual = visual_info->visual;
1064                                    g_depth = visual_info->depth;
1065                                    g_compatible_arch = !g_host_be;
1066                                    g_no_translate_image = (visual_info->depth == g_server_depth);
1067                                    if (g_no_translate_image)
1068                                            /* We found the best visual */
1069                                            break;
1070                            }
1071                            else
1072                            {
1073                                    g_compatible_arch = False;
1074                            }
1075    
1076                            if (visual_info->depth > 24)
1077                            {
1078                                    /* Avoid 32-bit visuals and likes like the plague.
1079                                       They're either untested or proven to work bad
1080                                       (e.g. nvidia's Composite 32-bit visual).
1081                                       Most implementation offer a 24-bit visual anyway. */
1082                                    continue;
1083                            }
1084    
1085          nvisuals--;                          /* Only care for visuals, for whose BPPs (not depths!)
1086          while (nvisuals >= 0)                             we have a translateXtoY function. */
1087          {                          BOOL can_translate_to_bpp = False;
1088                  if ((vmatches + nvisuals)->depth > g_depth)                          int j;
1089                  {                          for (j = 0; j < pixmap_formats_count; ++j)
1090                          g_depth = (vmatches + nvisuals)->depth;                          {
1091                                    if (pfm[j].depth == visual_info->depth)
1092                                    {
1093                                            if ((pfm[j].bits_per_pixel == 16) ||
1094                                                (pfm[j].bits_per_pixel == 24) ||
1095                                                (pfm[j].bits_per_pixel == 32))
1096                                            {
1097                                                    can_translate_to_bpp = True;
1098                                            }
1099                                            break;
1100                                    }
1101                            }
1102    
1103                            /* Prefer formats which have the most colour depth.
1104                               We're being truly aristocratic here, minding each
1105                               weight on its own. */
1106                            if (can_translate_to_bpp)
1107                            {
1108                                    unsigned vis_red_weight =
1109                                            calculate_mask_weight(visual_info->red_mask);
1110                                    unsigned vis_green_weight =
1111                                            calculate_mask_weight(visual_info->green_mask);
1112                                    unsigned vis_blue_weight =
1113                                            calculate_mask_weight(visual_info->blue_mask);
1114                                    if ((vis_red_weight >= red_weight)
1115                                        && (vis_green_weight >= green_weight)
1116                                        && (vis_blue_weight >= blue_weight))
1117                                    {
1118                                            red_weight = vis_red_weight;
1119                                            green_weight = vis_green_weight;
1120                                            blue_weight = vis_blue_weight;
1121                                            g_visual = visual_info->visual;
1122                                            g_depth = visual_info->depth;
1123                                    }
1124                            }
1125                  }                  }
1126                  nvisuals--;                  XFree(vmatches);
                 TrueColorVisual = True;  
1127          }          }
1128    
1129          test = 1;          if (g_visual != NULL)
         g_host_be = !(BOOL) (*(uint8 *) (&test));  
         g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);  
   
         if ((g_server_bpp == 8) && ((!TrueColorVisual) || (g_depth <= 8)))  
1130          {          {
1131                  /* we use a colourmap, so the default visual should do */                  g_owncolmap = False;
1132                  g_visual = DefaultVisualOfScreen(g_screen);                  calculate_shifts(g_visual->red_mask, &g_red_shift_r, &g_red_shift_l);
1133                  g_depth = DefaultDepthOfScreen(g_screen);                  calculate_shifts(g_visual->green_mask, &g_green_shift_r, &g_green_shift_l);
1134                    calculate_shifts(g_visual->blue_mask, &g_blue_shift_r, &g_blue_shift_l);
                 /* Do not allocate colours on a TrueColor visual */  
                 if (g_visual->class == TrueColor)  
                 {  
                         g_owncolmap = False;  
                 }  
1135          }          }
1136          else          else
1137          {          {
1138                  /* need a truecolour visual */                  template.class = PseudoColor;
1139                  if (!XMatchVisualInfo(g_display, screen_num, g_depth, TrueColor, &vi))                  template.depth = 8;
1140                  {                  template.colormap_size = 256;
1141                          error("The display does not support true colour - high colour support unavailable.\n");                  vmatches =
1142                            XGetVisualInfo(g_display,
1143                                           VisualClassMask | VisualDepthMask | VisualColormapSizeMask,
1144                                           &template, &visuals_count);
1145                    if (vmatches == NULL)
1146                    {
1147                            error("No usable TrueColor or PseudoColor visuals on this display.\n");
1148                            XCloseDisplay(g_display);
1149                            XFree(pfm);
1150                          return False;                          return False;
1151                  }                  }
1152    
1153                  g_visual = vi.visual;                  /* we use a colourmap, so the default visual should do */
1154                  g_owncolmap = False;                  g_owncolmap = True;
1155                  calculate_shifts(vi.red_mask, &g_red_shift_r, &g_red_shift_l);                  g_visual = vmatches[0].visual;
1156                  calculate_shifts(vi.blue_mask, &g_blue_shift_r, &g_blue_shift_l);                  g_depth = vmatches[0].depth;
1157                  calculate_shifts(vi.green_mask, &g_green_shift_r, &g_green_shift_l);          }
1158    
1159                  /* if RGB video and everything is little endian */          g_bpp = 0;
1160                  if ((vi.red_mask > vi.green_mask && vi.green_mask > vi.blue_mask) &&          for (i = 0; i < pixmap_formats_count; ++i)
1161                      !g_xserver_be && !g_host_be)          {
1162                    XPixmapFormatValues *pf = &pfm[i];
1163                    if (pf->depth == g_depth)
1164                  {                  {
1165                          if (g_depth <= 16 || (g_red_shift_l == 16 && g_green_shift_l == 8 &&                          g_bpp = pf->bits_per_pixel;
1166                                                g_blue_shift_l == 0))  
1167                            if (g_no_translate_image)
1168                          {                          {
1169                                  g_arch_match = True;                                  switch (g_server_depth)
1170                                    {
1171                                            case 15:
1172                                            case 16:
1173                                                    if (g_bpp != 16)
1174                                                            g_no_translate_image = False;
1175                                                    break;
1176                                            case 24:
1177                                                    /* Yes, this will force image translation
1178                                                       on most modern servers which use 32 bits
1179                                                       for R8G8B8. */
1180                                                    if (g_bpp != 24)
1181                                                            g_no_translate_image = False;
1182                                                    break;
1183                                            default:
1184                                                    g_no_translate_image = False;
1185                                                    break;
1186                                    }
1187                          }                          }
                 }  
1188    
1189                  if (g_arch_match)                          /* Pixmap formats list is a depth-to-bpp mapping --
1190                  {                             there's just a single entry for every depth,
1191                          DEBUG(("Architectures match, enabling little endian optimisations.\n"));                             so we can safely break here */
1192                            break;
1193                  }                  }
1194          }          }
1195            XFree(pfm);
1196            pfm = NULL;
1197            return True;
1198    }
1199    
1200          pfm = XListPixmapFormats(g_display, &i);  BOOL
1201          if (pfm != NULL)  ui_init(void)
1202    {
1203            int screen_num;
1204    
1205            g_display = XOpenDisplay(NULL);
1206            if (g_display == NULL)
1207          {          {
1208                  /* Use maximum bpp for this depth - this is generally                  error("Failed to open display: %s\n", XDisplayName(NULL));
1209                     desirable, e.g. 24 bits->32 bits. */                  return False;
                 while (i--)  
                 {  
                         if ((pfm[i].depth == g_depth) && (pfm[i].bits_per_pixel > g_bpp))  
                         {  
                                 g_bpp = pfm[i].bits_per_pixel;  
                         }  
                 }  
                 XFree(pfm);  
1210          }          }
1211    
         if (g_bpp < 8)  
1212          {          {
1213                  error("Less than 8 bpp not currently supported.\n");                  uint16 endianess_test = 1;
1214                  XCloseDisplay(g_display);                  g_host_be = !(BOOL) (*(uint8 *) (&endianess_test));
1215            }
1216    
1217            g_xserver_be = (ImageByteOrder(g_display) == MSBFirst);
1218            screen_num = DefaultScreen(g_display);
1219            g_x_socket = ConnectionNumber(g_display);
1220            g_screen = ScreenOfDisplay(g_display, screen_num);
1221            g_depth = DefaultDepthOfScreen(g_screen);
1222    
1223            if (!select_visual())
1224                  return False;                  return False;
1225    
1226            if (g_no_translate_image)
1227            {
1228                    DEBUG(("Performance optimization possible: avoiding image translation (colour depth conversion).\n"));
1229          }          }
1230    
1231            if (g_server_depth > g_bpp)
1232            {
1233                    warning("Remote desktop colour depth %d higher than display colour depth %d.\n",
1234                            g_server_depth, g_bpp);
1235            }
1236    
1237            DEBUG(("RDP depth: %d, display depth: %d, display bpp: %d, X server BE: %d, host BE: %d\n",
1238                   g_server_depth, g_depth, g_bpp, g_xserver_be, g_host_be));
1239    
1240          if (!g_owncolmap)          if (!g_owncolmap)
1241          {          {
1242                  g_xcolmap =                  g_xcolmap =
1243                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,                          XCreateColormap(g_display, RootWindowOfScreen(g_screen), g_visual,
1244                                          AllocNone);                                          AllocNone);
1245                  if (g_depth <= 8)                  if (g_depth <= 8)
1246                          warning("Screen depth is 8 bits or lower: you may want to use -C for a private colourmap\n");                          warning("Display colour depth is %d bit: you may want to use -C for a private colourmap.\n", g_depth);
1247          }          }
1248    
1249          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))          if ((!g_ownbackstore) && (DoesBackingStore(g_screen) != Always))
1250          {          {
1251                  warning("External BackingStore not available, using internal\n");                  warning("External BackingStore not available. Using internal.\n");
1252                  g_ownbackstore = True;                  g_ownbackstore = True;
1253          }          }
1254    
# Line 1061  ui_init(void) Line 1259  ui_init(void)
1259          {          {
1260                  g_width = WidthOfScreen(g_screen);                  g_width = WidthOfScreen(g_screen);
1261                  g_height = HeightOfScreen(g_screen);                  g_height = HeightOfScreen(g_screen);
1262                    g_using_full_workarea = True;
1263          }          }
1264          else if (g_width < 0)          else if (g_width < 0)
1265          {          {
1266                  /* Percent of screen */                  /* Percent of screen */
1267                    if (-g_width >= 100)
1268                            g_using_full_workarea = True;
1269                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;                  g_height = HeightOfScreen(g_screen) * (-g_width) / 100;
1270                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;                  g_width = WidthOfScreen(g_screen) * (-g_width) / 100;
1271          }          }
# Line 1072  ui_init(void) Line 1273  ui_init(void)
1273          {          {
1274                  /* Fetch geometry from _NET_WORKAREA */                  /* Fetch geometry from _NET_WORKAREA */
1275                  uint32 x, y, cx, cy;                  uint32 x, y, cx, cy;
   
1276                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)                  if (get_current_workarea(&x, &y, &cx, &cy) == 0)
1277                  {                  {
1278                          g_width = cx;                          g_width = cx;
1279                          g_height = cy;                          g_height = cy;
1280                            g_using_full_workarea = True;
1281                  }                  }
1282                  else                  else
1283                  {                  {
1284                          warning("Failed to get workarea: probably your window manager does not support extended hints\n");                          warning("Failed to get workarea: probably your window manager does not support extended hints\n");
1285                          g_width = 800;                          g_width = WidthOfScreen(g_screen);
1286                          g_height = 600;                          g_height = HeightOfScreen(g_screen);
1287                  }                  }
1288          }          }
1289    
# Line 1098  ui_init(void) Line 1299  ui_init(void)
1299    
1300          xclip_init();          xclip_init();
1301    
1302          DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_bpp, g_bpp, g_depth));          DEBUG_RDP5(("server bpp %d client bpp %d depth %d\n", g_server_depth, g_bpp, g_depth));
1303    
1304          return True;          return True;
1305  }  }
# Line 1138  ui_create_window(void) Line 1339  ui_create_window(void)
1339          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;          wndwidth = g_fullscreen ? WidthOfScreen(g_screen) : g_width;
1340          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;          wndheight = g_fullscreen ? HeightOfScreen(g_screen) : g_height;
1341    
1342            /* Handle -x-y portion of geometry string */
1343            if (g_xpos < 0 || (g_xpos == 0 && (g_pos & 2)))
1344                    g_xpos = WidthOfScreen(g_screen) + g_xpos - g_width;
1345            if (g_ypos < 0 || (g_ypos == 0 && (g_pos & 4)))
1346                    g_ypos = HeightOfScreen(g_screen) + g_ypos - g_height;
1347    
1348          attribs.background_pixel = BlackPixelOfScreen(g_screen);          attribs.background_pixel = BlackPixelOfScreen(g_screen);
1349          attribs.border_pixel = WhitePixelOfScreen(g_screen);          attribs.border_pixel = WhitePixelOfScreen(g_screen);
1350          attribs.backing_store = g_ownbackstore ? NotUseful : Always;          attribs.backing_store = g_ownbackstore ? NotUseful : Always;
# Line 1181  ui_create_window(void) Line 1388  ui_create_window(void)
1388          if (sizehints)          if (sizehints)
1389          {          {
1390                  sizehints->flags = PMinSize | PMaxSize;                  sizehints->flags = PMinSize | PMaxSize;
1391                    if (g_pos)
1392                            sizehints->flags |= PPosition;
1393                  sizehints->min_width = sizehints->max_width = g_width;                  sizehints->min_width = sizehints->max_width = g_width;
1394                  sizehints->min_height = sizehints->max_height = g_height;                  sizehints->min_height = sizehints->max_height = g_height;
1395                  XSetWMNormalHints(g_display, g_wnd, sizehints);                  XSetWMNormalHints(g_display, g_wnd, sizehints);
# Line 1193  ui_create_window(void) Line 1402  ui_create_window(void)
1402          }          }
1403    
1404          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |          input_mask = KeyPressMask | KeyReleaseMask | ButtonPressMask | ButtonReleaseMask |
1405                  VisibilityChangeMask | FocusChangeMask;                  VisibilityChangeMask | FocusChangeMask | StructureNotifyMask;
1406    
1407          if (g_sendmotion)          if (g_sendmotion)
1408                  input_mask |= PointerMotionMask;                  input_mask |= PointerMotionMask;
# Line 1307  xwin_toggle_fullscreen(void) Line 1516  xwin_toggle_fullscreen(void)
1516          }          }
1517  }  }
1518    
1519  /* Process all events in Xlib queue  static void
1520    handle_button_event(XEvent xevent, BOOL down)
1521    {
1522            uint16 button, flags = 0;
1523            g_last_gesturetime = xevent.xbutton.time;
1524            button = xkeymap_translate_button(xevent.xbutton.button);
1525            if (button == 0)
1526                    return;
1527    
1528            if (down)
1529                    flags = MOUSE_FLAG_DOWN;
1530    
1531            /* Stop moving window when button is released, regardless of cursor position */
1532            if (g_moving_wnd && (xevent.type == ButtonRelease))
1533                    g_moving_wnd = False;
1534    
1535            /* If win_button_size is nonzero, enable single app mode */
1536            if (xevent.xbutton.y < g_win_button_size)
1537            {
1538                    /*  Check from right to left: */
1539                    if (xevent.xbutton.x >= g_width - g_win_button_size)
1540                    {
1541                            /* The close button, continue */
1542                            ;
1543                    }
1544                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 2)
1545                    {
1546                            /* The maximize/restore button. Do not send to
1547                               server.  It might be a good idea to change the
1548                               cursor or give some other visible indication
1549                               that rdesktop inhibited this click */
1550                            if (xevent.type == ButtonPress)
1551                                    return;
1552                    }
1553                    else if (xevent.xbutton.x >= g_width - g_win_button_size * 3)
1554                    {
1555                            /* The minimize button. Iconify window. */
1556                            if (xevent.type == ButtonRelease)
1557                            {
1558                                    /* Release the mouse button outside the minimize button, to prevent the
1559                                       actual minimazation to happen */
1560                                    rdp_send_input(time(NULL), RDP_INPUT_MOUSE, button, 1, 1);
1561                                    XIconifyWindow(g_display, g_wnd, DefaultScreen(g_display));
1562                                    return;
1563                            }
1564                    }
1565                    else if (xevent.xbutton.x <= g_win_button_size)
1566                    {
1567                            /* The system menu. Ignore. */
1568                            if (xevent.type == ButtonPress)
1569                                    return;
1570                    }
1571                    else
1572                    {
1573                            /* The title bar. */
1574                            if (xevent.type == ButtonPress)
1575                            {
1576                                    if (!g_fullscreen && g_hide_decorations && !g_using_full_workarea)
1577                                    {
1578                                            g_moving_wnd = True;
1579                                            g_move_x_offset = xevent.xbutton.x;
1580                                            g_move_y_offset = xevent.xbutton.y;
1581                                    }
1582                                    return;
1583                            }
1584                    }
1585            }
1586    
1587            rdp_send_input(time(NULL), RDP_INPUT_MOUSE,
1588                           flags | button, xevent.xbutton.x, xevent.xbutton.y);
1589    }
1590    
1591    /* Process events in Xlib queue
1592     Returns 0 after user quit, 1 otherwise */     Returns 0 after user quit, 1 otherwise */
1593  static int  static int
1594  xwin_process_events(void)  xwin_process_events(void)
1595  {  {
1596          XEvent xevent;          XEvent xevent;
1597          KeySym keysym;          KeySym keysym;
         uint16 button, flags;  
1598          uint32 ev_time;          uint32 ev_time;
         key_translation tr;  
1599          char str[256];          char str[256];
1600          Status status;          Status status;
1601            int events = 0;
1602    
1603          while (XPending(g_display) > 0)          while ((XPending(g_display) > 0) && events++ < 20)
1604          {          {
1605                  XNextEvent(g_display, &xevent);                  XNextEvent(g_display, &xevent);
1606    
# Line 1330  xwin_process_events(void) Line 1610  xwin_process_events(void)
1610                          continue;                          continue;
1611                  }                  }
1612    
                 flags = 0;  
   
1613                  switch (xevent.type)                  switch (xevent.type)
1614                  {                  {
1615                          case VisibilityNotify:                          case VisibilityNotify:
# Line 1368  xwin_process_events(void) Line 1646  xwin_process_events(void)
1646                                                        str, sizeof(str), &keysym, NULL);                                                        str, sizeof(str), &keysym, NULL);
1647                                  }                                  }
1648    
1649                                  DEBUG_KBD(("KeyPress for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("KeyPress for keysym (0x%lx, %s)\n", keysym,
1650                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1651    
1652                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1653                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, True))
1654                                          break;                                          break;
1655    
1656                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1657                                                             xevent.xkey.keycode, xevent.xkey.state);                                                    ev_time, True, 0);
   
                                 if (tr.scancode == 0)  
                                         break;  
   
                                 save_remote_modifiers(tr.scancode);  
                                 ensure_remote_modifiers(ev_time, tr);  
                                 rdp_send_scancode(ev_time, RDP_KEYPRESS, tr.scancode);  
                                 restore_remote_modifiers(ev_time, tr.scancode);  
   
1658                                  break;                                  break;
1659    
1660                          case KeyRelease:                          case KeyRelease:
# Line 1393  xwin_process_events(void) Line 1662  xwin_process_events(void)
1662                                  XLookupString((XKeyEvent *) & xevent, str,                                  XLookupString((XKeyEvent *) & xevent, str,
1663                                                sizeof(str), &keysym, NULL);                                                sizeof(str), &keysym, NULL);
1664    
1665                                  DEBUG_KBD(("\nKeyRelease for (keysym 0x%lx, %s)\n", keysym,                                  DEBUG_KBD(("\nKeyRelease for keysym (0x%lx, %s)\n", keysym,
1666                                             get_ksname(keysym)));                                             get_ksname(keysym)));
1667    
1668                                  ev_time = time(NULL);                                  ev_time = time(NULL);
1669                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))                                  if (handle_special_keys(keysym, xevent.xkey.state, ev_time, False))
1670                                          break;                                          break;
1671    
1672                                  tr = xkeymap_translate_key(keysym,                                  xkeymap_send_keys(keysym, xevent.xkey.keycode, xevent.xkey.state,
1673                                                             xevent.xkey.keycode, xevent.xkey.state);                                                    ev_time, False, 0);
   
                                 if (tr.scancode == 0)  
                                         break;  
   
                                 rdp_send_scancode(ev_time, RDP_KEYRELEASE, tr.scancode);  
1674                                  break;                                  break;
1675    
1676                          case ButtonPress:                          case ButtonPress:
1677                                  flags = MOUSE_FLAG_DOWN;                                  handle_button_event(xevent, True);
1678                                  /* fall through */                                  break;
1679    
1680                          case ButtonRelease:                          case ButtonRelease:
1681                                  g_last_gesturetime = xevent.xbutton.time;                                  handle_button_event(xevent, False);
                                 button = xkeymap_translate_button(xevent.xbutton.button);  
                                 if (button == 0)  
                                         break;  
   
                                 /* If win_button_size is nonzero, enable single app mode */  
                                 if (xevent.xbutton.y < g_win_button_size)  
                                 {  
                                         /* Stop moving window when button is released, regardless of cursor position */  
                                         if (g_moving_wnd && (xevent.type == ButtonRelease))  
                                                 g_moving_wnd = False;  
   
                                         /*  Check from right to left: */  
   
                                         if (xevent.xbutton.x >= g_width - g_win_button_size)  
                                         {  
                                                 /* The close button, continue */  
                                                 ;  
                                         }  
                                         else if (xevent.xbutton.x >=  
                                                  g_width - g_win_button_size * 2)  
                                         {  
                                                 /* The maximize/restore button. Do not send to  
                                                    server.  It might be a good idea to change the  
                                                    cursor or give some other visible indication  
                                                    that rdesktop inhibited this click */  
                                                 break;  
                                         }  
                                         else if (xevent.xbutton.x >=  
                                                  g_width - g_win_button_size * 3)  
                                         {  
                                                 /* The minimize button. Iconify window. */  
                                                 XIconifyWindow(g_display, g_wnd,  
                                                                DefaultScreen(g_display));  
                                                 break;  
                                         }  
                                         else if (xevent.xbutton.x <= g_win_button_size)  
                                         {  
                                                 /* The system menu. Ignore. */  
                                                 break;  
                                         }  
                                         else  
                                         {  
                                                 /* The title bar. */  
                                                 if ((xevent.type == ButtonPress) && !g_fullscreen  
                                                     && g_hide_decorations)  
                                                 {  
                                                         g_moving_wnd = True;  
                                                         g_move_x_offset = xevent.xbutton.x;  
                                                         g_move_y_offset = xevent.xbutton.y;  
                                                 }  
                                                 break;  
   
                                         }  
                                 }  
   
                                 rdp_send_input(time(NULL), RDP_INPUT_MOUSE,  
                                                flags | button, xevent.xbutton.x, xevent.xbutton.y);  
1682                                  break;                                  break;
1683    
1684                          case MotionNotify:                          case MotionNotify:
# Line 1564  xwin_process_events(void) Line 1771  xwin_process_events(void)
1771                          case PropertyNotify:                          case PropertyNotify:
1772                                  xclip_handle_PropertyNotify(&xevent.xproperty);                                  xclip_handle_PropertyNotify(&xevent.xproperty);
1773                                  break;                                  break;
1774                            case MapNotify:
1775                                    rdp_send_client_window_status(1);
1776                                    break;
1777                            case UnmapNotify:
1778                                    rdp_send_client_window_status(0);
1779                                    break;
1780                  }                  }
1781          }          }
1782          /* Keep going */          /* Keep going */
# Line 1647  ui_create_bitmap(int width, int height, Line 1860  ui_create_bitmap(int width, int height,
1860          uint8 *tdata;          uint8 *tdata;
1861          int bitmap_pad;          int bitmap_pad;
1862    
1863          if (g_server_bpp == 8)          if (g_server_depth == 8)
1864          {          {
1865                  bitmap_pad = 8;                  bitmap_pad = 8;
1866          }          }
# Line 1679  ui_paint_bitmap(int x, int y, int cx, in Line 1892  ui_paint_bitmap(int x, int y, int cx, in
1892          uint8 *tdata;          uint8 *tdata;
1893          int bitmap_pad;          int bitmap_pad;
1894    
1895          if (g_server_bpp == 8)          if (g_server_depth == 8)
1896          {          {
1897                  bitmap_pad = 8;                  bitmap_pad = 8;
1898          }          }
# Line 2166  ui_rect( Line 2379  ui_rect(
2379          FILL_RECTANGLE(x, y, cx, cy);          FILL_RECTANGLE(x, y, cx, cy);
2380  }  }
2381    
2382    void
2383    ui_polygon(uint8 opcode,
2384               /* mode */ uint8 fillmode,
2385               /* dest */ POINT * point, int npoints,
2386               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2387    {
2388            uint8 style, i, ipattern[8];
2389            Pixmap fill;
2390    
2391            SET_FUNCTION(opcode);
2392    
2393            switch (fillmode)
2394            {
2395                    case ALTERNATE:
2396                            XSetFillRule(g_display, g_gc, EvenOddRule);
2397                            break;
2398                    case WINDING:
2399                            XSetFillRule(g_display, g_gc, WindingRule);
2400                            break;
2401                    default:
2402                            unimpl("fill mode %d\n", fillmode);
2403            }
2404    
2405            if (brush)
2406                    style = brush->style;
2407            else
2408                    style = 0;
2409    
2410            switch (style)
2411            {
2412                    case 0: /* Solid */
2413                            SET_FOREGROUND(fgcolour);
2414                            FILL_POLYGON((XPoint *) point, npoints);
2415                            break;
2416    
2417                    case 2: /* Hatch */
2418                            fill = (Pixmap) ui_create_glyph(8, 8,
2419                                                            hatch_patterns + brush->pattern[0] * 8);
2420                            SET_FOREGROUND(fgcolour);
2421                            SET_BACKGROUND(bgcolour);
2422                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2423                            XSetStipple(g_display, g_gc, fill);
2424                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2425                            FILL_POLYGON((XPoint *) point, npoints);
2426                            XSetFillStyle(g_display, g_gc, FillSolid);
2427                            XSetTSOrigin(g_display, g_gc, 0, 0);
2428                            ui_destroy_glyph((HGLYPH) fill);
2429                            break;
2430    
2431                    case 3: /* Pattern */
2432                            for (i = 0; i != 8; i++)
2433                                    ipattern[7 - i] = brush->pattern[i];
2434                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2435                            SET_FOREGROUND(bgcolour);
2436                            SET_BACKGROUND(fgcolour);
2437                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2438                            XSetStipple(g_display, g_gc, fill);
2439                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2440                            FILL_POLYGON((XPoint *) point, npoints);
2441                            XSetFillStyle(g_display, g_gc, FillSolid);
2442                            XSetTSOrigin(g_display, g_gc, 0, 0);
2443                            ui_destroy_glyph((HGLYPH) fill);
2444                            break;
2445    
2446                    default:
2447                            unimpl("brush %d\n", brush->style);
2448            }
2449    
2450            RESET_FUNCTION(opcode);
2451    }
2452    
2453    void
2454    ui_polyline(uint8 opcode,
2455                /* dest */ POINT * points, int npoints,
2456                /* pen */ PEN * pen)
2457    {
2458            /* TODO: set join style */
2459            SET_FUNCTION(opcode);
2460            SET_FOREGROUND(pen->colour);
2461            XDrawLines(g_display, g_wnd, g_gc, (XPoint *) points, npoints, CoordModePrevious);
2462            if (g_ownbackstore)
2463                    XDrawLines(g_display, g_backstore, g_gc, (XPoint *) points, npoints,
2464                               CoordModePrevious);
2465            RESET_FUNCTION(opcode);
2466    }
2467    
2468    void
2469    ui_ellipse(uint8 opcode,
2470               /* mode */ uint8 fillmode,
2471               /* dest */ int x, int y, int cx, int cy,
2472               /* brush */ BRUSH * brush, int bgcolour, int fgcolour)
2473    {
2474            uint8 style, i, ipattern[8];
2475            Pixmap fill;
2476    
2477            SET_FUNCTION(opcode);
2478    
2479            if (brush)
2480                    style = brush->style;
2481            else
2482                    style = 0;
2483    
2484            switch (style)
2485            {
2486                    case 0: /* Solid */
2487                            SET_FOREGROUND(fgcolour);
2488                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2489                            break;
2490    
2491                    case 2: /* Hatch */
2492                            fill = (Pixmap) ui_create_glyph(8, 8,
2493                                                            hatch_patterns + brush->pattern[0] * 8);
2494                            SET_FOREGROUND(fgcolour);
2495                            SET_BACKGROUND(bgcolour);
2496                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2497                            XSetStipple(g_display, g_gc, fill);
2498                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2499                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2500                            XSetFillStyle(g_display, g_gc, FillSolid);
2501                            XSetTSOrigin(g_display, g_gc, 0, 0);
2502                            ui_destroy_glyph((HGLYPH) fill);
2503                            break;
2504    
2505                    case 3: /* Pattern */
2506                            for (i = 0; i != 8; i++)
2507                                    ipattern[7 - i] = brush->pattern[i];
2508                            fill = (Pixmap) ui_create_glyph(8, 8, ipattern);
2509                            SET_FOREGROUND(bgcolour);
2510                            SET_BACKGROUND(fgcolour);
2511                            XSetFillStyle(g_display, g_gc, FillOpaqueStippled);
2512                            XSetStipple(g_display, g_gc, fill);
2513                            XSetTSOrigin(g_display, g_gc, brush->xorigin, brush->yorigin);
2514                            DRAW_ELLIPSE(x, y, cx, cy, fillmode);
2515                            XSetFillStyle(g_display, g_gc, FillSolid);
2516                            XSetTSOrigin(g_display, g_gc, 0, 0);
2517                            ui_destroy_glyph((HGLYPH) fill);
2518                            break;
2519    
2520                    default:
2521                            unimpl("brush %d\n", brush->style);
2522            }
2523    
2524            RESET_FUNCTION(opcode);
2525    }
2526    
2527  /* warning, this function only draws on wnd or backstore, not both */  /* warning, this function only draws on wnd or backstore, not both */
2528  void  void
2529  ui_draw_glyph(int mixmode,  ui_draw_glyph(int mixmode,
# Line 2221  ui_draw_glyph(int mixmode, Line 2579  ui_draw_glyph(int mixmode,
2579  }  }
2580    
2581  void  void
2582  ui_draw_text(uint8 font, uint8 flags, int mixmode, int x, int y,  ui_draw_text(uint8 font, uint8 flags, uint8 opcode, int mixmode, int x, int y,
2583               int clipx, int clipy, int clipcx, int clipcy,               int clipx, int clipy, int clipcx, int clipcy,
2584               int boxx, int boxy, int boxcx, int boxcy, int bgcolour,               int boxx, int boxy, int boxcx, int boxcy, BRUSH * brush,
2585               int fgcolour, uint8 * text, uint8 length)               int bgcolour, int fgcolour, uint8 * text, uint8 length)
2586  {  {
2587            /* TODO: use brush appropriately */
2588    
2589          FONTGLYPH *glyph;          FONTGLYPH *glyph;
2590          int i, j, xyoffset, x1, y1;          int i, j, xyoffset, x1, y1;
2591          DATABLOB *entry;          DATABLOB *entry;
# Line 2257  ui_draw_text(uint8 font, uint8 flags, in Line 2617  ui_draw_text(uint8 font, uint8 flags, in
2617                  switch (text[i])                  switch (text[i])
2618                  {                  {
2619                          case 0xff:                          case 0xff:
2620                                  if (i + 2 < length)                                  /* At least two bytes needs to follow */
2621                                          cache_put_text(text[i + 1], text, text[i + 2]);                                  if (i + 3 > length)
                                 else  
2622                                  {                                  {
2623                                          error("this shouldn't be happening\n");                                          warning("Skipping short 0xff command:");
2624                                          exit(1);                                          for (j = 0; j < length; j++)
2625                                                    fprintf(stderr, "%02x ", text[j]);
2626                                            fprintf(stderr, "\n");
2627                                            i = length = 0;
2628                                            break;
2629                                  }                                  }
2630                                    cache_put_text(text[i + 1], text, text[i + 2]);
2631                                    i += 3;
2632                                    length -= i;
2633                                  /* this will move pointer from start to first character after FF command */                                  /* this will move pointer from start to first character after FF command */
2634                                  length -= i + 3;                                  text = &(text[i]);
                                 text = &(text[i + 3]);  
2635                                  i = 0;                                  i = 0;
2636                                  break;                                  break;
2637    
2638                          case 0xfe:                          case 0xfe:
2639                                    /* At least one byte needs to follow */
2640                                    if (i + 2 > length)
2641                                    {
2642                                            warning("Skipping short 0xfe command:");
2643                                            for (j = 0; j < length; j++)
2644                                                    fprintf(stderr, "%02x ", text[j]);
2645                                            fprintf(stderr, "\n");
2646                                            i = length = 0;
2647                                            break;
2648                                    }
2649                                  entry = cache_get_text(text[i + 1]);                                  entry = cache_get_text(text[i + 1]);
2650                                  if (entry != NULL)                                  if (entry->data != NULL)
2651                                  {                                  {
2652                                          if ((((uint8 *) (entry->data))[1] ==                                          if ((((uint8 *) (entry->data))[1] == 0)
2653                                               0) && (!(flags & TEXT2_IMPLICIT_X)))                                              && (!(flags & TEXT2_IMPLICIT_X)) && (i + 2 < length))
2654                                          {                                          {
2655                                                  if (flags & TEXT2_VERTICAL)                                                  if (flags & TEXT2_VERTICAL)
2656                                                          y += text[i + 2];                                                          y += text[i + 2];

Legend:
Removed from v.823  
changed lines
  Added in v.1058

  ViewVC Help
Powered by ViewVC 1.1.26