home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / lucid / lemacs-19.6 / src / ScreenWidget.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-03-13  |  21.1 KB  |  672 lines

  1. /* The emacs screen widget.
  2.    Copyright (C) 1992, 1993 Free Software Foundation, Inc.
  3.  
  4. This file is part of GNU Emacs.
  5.  
  6. GNU Emacs is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2, or (at your option)
  9. any later version.
  10.  
  11. GNU Emacs is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with GNU Emacs; see the file COPYING.  If not, write to
  18. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  19.  
  20. #include <stdio.h>
  21. #include "config.h"
  22. #include "lisp.h"
  23. #include "xterm.h"
  24. #include "dispextern.h"
  25. #include "screen.h"
  26.  
  27. #include <X11/StringDefs.h>
  28. #include <X11/IntrinsicP.h>
  29. #include <X11/cursorfont.h>
  30. #include "ScreenWidgetP.h"
  31. #include <X11/Shell.h>
  32.  
  33. /* This sucks: this is the first default that x-faces.el tries.  This won't
  34.    be used unless neither the "Emacs.EmacsScreen.font" resource nor the
  35.    "Emacs.EmacsScreen.default.attributeFont" resource is set; the screen
  36.    may have the wrong default size if this font doesn't exist, but some other
  37.    font that x-faces.el does.  The workaround is to specify some font in the
  38.    resource database; I don't know a solution other than duplicating the font-
  39.    searching code from x-faces.el in this file.
  40.  
  41.    This also means that if "Emacs.EmacsScreen.font" is specified as a non-
  42.    existent font, then Xt is going to substitute "XtDefaultFont" for it,
  43.    which is a different size than this one.  The solution for this is to
  44.    make x-faces.el try to use XtDefaultFont.  The problem with that is that
  45.    XtDefaultFont is almost certainly variable-width.
  46.  
  47.    #### Perhaps we could have this code explicitly set XtDefaultFont to this?
  48.  */
  49. #define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
  50.  
  51. void emacs_Xt_focus_event_handler ();
  52.  
  53. static void EmacsScreenInitialize (Widget, Widget, ArgList, Cardinal *);
  54. static void EmacsScreenDestroy (Widget);
  55. static void EmacsScreenRealize (Widget, XtValueMask*, XSetWindowAttributes*);
  56. void EmacsScreenResize (Widget widget);
  57. static Boolean EmacsScreenSetValues (Widget, Widget, Widget,
  58.                      ArgList, Cardinal *);
  59. static XtGeometryResult EmacsScreenQueryGeometry (Widget, XtWidgetGeometry*,
  60.                           XtWidgetGeometry*);
  61.  
  62. static void
  63. key_press (Widget w, XEvent* event, String *params, Cardinal *n_params);
  64. static void
  65. emacs_screen_focus_handler (Widget w, XEvent *event, String *params,
  66.                 Cardinal *n_params);
  67.  
  68.  
  69. #undef XtOffset
  70. #define XtOffset(p_type,field) \
  71.     ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
  72. #define offset(field) XtOffset(EmacsScreenWidget, emacs_screen.field)
  73.  
  74. static XtResource resources[] = {
  75.   {XtNminibuffer, XtCMinibuffer, XtRInt, sizeof (int),
  76.      offset (minibuffer), XtRImmediate, (XtPointer)0},
  77.   {XtNunsplittable, XtCUnsplittable, XtRBoolean, sizeof (Boolean),
  78.      offset (unsplittable), XtRImmediate, (XtPointer)0},
  79.   {XtNinternalBorderWidth, XtCInternalBorderWidth, XtRInt, sizeof (int),
  80.      offset (internal_border_width), XtRImmediate, (XtPointer)4},
  81.   {XtNinterline, XtCInterline, XtRInt, sizeof (int),
  82.      offset (interline), XtRImmediate, (XtPointer)0},
  83.   {XtNfont,  XtCFont, XtRFontStruct, sizeof(XFontStruct *),
  84.      offset(font),XtRString, DEFAULT_FACE_FONT},
  85.   {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
  86.      offset(foreground_pixel), XtRString, "XtDefaultForeground"},
  87.   {XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel),
  88.      offset(cursor_color), XtRString, "XtDefaultForeground"},
  89.   {XtNbarCursor, XtCBarCursor, XtRBoolean, sizeof (Boolean),
  90.      offset (bar_cursor), XtRImmediate, (XtPointer)0},
  91.   {XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof (Boolean),
  92.      offset (visual_bell), XtRImmediate, (XtPointer)0},
  93.   {XtNbellVolume, XtCBellVolume, XtRInt, sizeof (int),
  94.      offset (bell_volume), XtRImmediate, (XtPointer)0},
  95.   {XtNgeometry, XtCGeometry, XtRString, sizeof(char *),
  96.      offset (emacs_geometry), XtRImmediate, 0},
  97.   {XtNemacsScreen, XtCEmacsScreen, XtRPointer, sizeof (XtPointer),
  98.      offset (screen), XtRImmediate, 0},
  99. };
  100.  
  101. static XtResource initial_geometry_resources[] = {
  102.   {XtNinitialGeometry, XtCInitialGeometry, XtRString, sizeof(char *),
  103.      0, XtRImmediate, 0},
  104. };
  105. #undef offset
  106.  
  107. static XtActionsRec
  108. emacsScreenActionsTable [] = {
  109.   {"keypress",  key_press},
  110.   {"focus_in",  emacs_screen_focus_handler},
  111.   {"focus_out", emacs_screen_focus_handler},
  112. };
  113.  
  114. static char
  115. emacsScreenTranslations [] = "\
  116. <KeyPress>: keypress()\n\
  117. <FocusIn>:  focus_in()\n\
  118. <FocusOut>: focus_out()\n\
  119. ";
  120.  
  121. EmacsScreenClassRec emacsScreenClassRec = {
  122.     { /* core fields */
  123.     /* superclass        */    &widgetClassRec,
  124.     /* class_name        */    "EmacsScreen",
  125.     /* widget_size        */    sizeof(EmacsScreenRec),
  126.     /* class_initialize        */    0,
  127.     /* class_part_initialize    */    0,
  128.     /* class_inited        */    FALSE,
  129.     /* initialize        */    EmacsScreenInitialize,
  130.     /* initialize_hook        */    0,
  131.     /* realize            */    EmacsScreenRealize,
  132.     /* actions            */    emacsScreenActionsTable,
  133.     /* num_actions        */    XtNumber (emacsScreenActionsTable),
  134.     /* resources        */    resources,
  135.     /* resource_count        */    XtNumber(resources),
  136.     /* xrm_class        */    NULLQUARK,
  137.     /* compress_motion        */    TRUE,
  138.     /* compress_exposure    */    TRUE,
  139.     /* compress_enterleave    */    TRUE,
  140.     /* visible_interest        */    FALSE,
  141.     /* destroy            */    EmacsScreenDestroy,
  142.     /* resize            */    EmacsScreenResize,
  143.     /* expose            */    XtInheritExpose,
  144.     /* set_values        */    EmacsScreenSetValues,
  145.     /* set_values_hook        */    0,
  146.     /* set_values_almost    */    XtInheritSetValuesAlmost,
  147.     /* get_values_hook        */    0,
  148.     /* accept_focus        */    XtInheritAcceptFocus,
  149.     /* version            */    XtVersion,
  150.     /* callback_private        */    0,
  151.     /* tm_table            */    emacsScreenTranslations,
  152.     /* query_geometry        */    EmacsScreenQueryGeometry,
  153.     /* display_accelerator    */    XtInheritDisplayAccelerator,
  154.     /* extension        */    0
  155.     }
  156. };
  157.  
  158. WidgetClass emacsScreenWidgetClass = (WidgetClass) &emacsScreenClassRec;
  159.  
  160. static void
  161. get_default_char_pixel_size (EmacsScreenWidget ew, int* pixel_width,
  162.                  int* pixel_height)
  163. {
  164.   *pixel_width = XTextWidth (ew->emacs_screen.font, "n", 1);
  165.   if (ew->emacs_screen.screen->display.x->text_height)
  166.     *pixel_height = ew->emacs_screen.screen->display.x->text_height;
  167.   else
  168.     *pixel_height =
  169.       ew->emacs_screen.font->ascent + ew->emacs_screen.font->descent;
  170. }
  171.  
  172. static void
  173. pixel_to_char_size (EmacsScreenWidget ew,
  174.             Dimension pixel_width, Dimension pixel_height,
  175.             int* char_width, int* char_height)
  176. {
  177.   int cpw;
  178.   int cph;
  179.  
  180.   get_default_char_pixel_size (ew, &cpw, &cph);
  181.   *char_width =
  182.     (pixel_width - 2 * ew->emacs_screen.internal_border_width) / cpw;
  183.   *char_height =
  184.     (pixel_height - 2 * ew->emacs_screen.internal_border_width) / cph; 
  185. }
  186.  
  187. static void
  188. char_to_pixel_size (EmacsScreenWidget ew, int char_width, int char_height,
  189.             Dimension* pixel_width, Dimension* pixel_height)
  190. {
  191.   int cpw;
  192.   int cph;
  193.  
  194.   get_default_char_pixel_size (ew, &cpw, &cph);
  195.   *pixel_width =
  196.     char_width * cpw + 2 * ew->emacs_screen.internal_border_width;
  197.   *pixel_height =
  198.     char_height * cph + 2 * ew->emacs_screen.internal_border_width;
  199. }
  200.  
  201. static void
  202. round_size_to_char (EmacsScreenWidget ew,
  203.             Dimension in_width, Dimension in_height,
  204.             Dimension* out_width, Dimension* out_height)
  205. {
  206.   int char_width;
  207.   int char_height;
  208.   pixel_to_char_size (ew, in_width, in_height, &char_width, &char_height);
  209.   char_to_pixel_size (ew, char_width, char_height, out_width, out_height);
  210. }
  211.  
  212. static Widget
  213. get_wm_shell (Widget w)
  214. {
  215.   Widget wmshell;
  216.  
  217.   for (wmshell = XtParent (w);
  218.        wmshell && !XtIsWMShell (wmshell);
  219.        wmshell = XtParent (wmshell));
  220.  
  221.   return wmshell;
  222. }
  223.  
  224. static void
  225. set_screen_size (EmacsScreenWidget ew)
  226. {
  227.   int x = 0;
  228.   int y = 0;
  229.   unsigned int columns = 80;
  230.   unsigned int rows = 40;
  231.   int parse_result = 0;
  232.   struct screen* screen = ew->emacs_screen.screen;
  233.   Dimension pixel_width, pixel_height;
  234.   Widget wmshell;
  235.   char shell_position [32];
  236.  
  237.   static Boolean is_first_screen = True;
  238.  
  239.   wmshell = get_wm_shell ((Widget)ew);
  240.  
  241.   /* The widget hierarchy is
  242.  
  243.     argv[0]            screen_name    pane    screen
  244.     ApplicationShell    EmacsShell    Paned    EmacsScreen
  245.  
  246.      We accept geometry specs in this order:
  247.  
  248.     *screen-name.geometry
  249.     *EmacsScreen.geometry
  250.     Emacs.geometry
  251.  
  252.      This is bad.  screen-name and EmacsScreen should be at the same
  253.      level of the hierarchy.  Possibilities would be
  254.  
  255.     argv[0]            screen        pane    screen-name
  256.     ApplicationShell    EmacsShell    Paned    EmacsScreen
  257.      or
  258.     argv[0]            screen-name    pane    screen-name
  259.     ApplicationShell    EmacsShell    Paned    EmacsScreen
  260.      or
  261.     argv[0]            screen-name    pane    textPane
  262.     ApplicationShell    EmacsScreen    Paned    EmacsTextPane
  263.    */
  264.  
  265.  
  266.   /* If Emacs.this_screen.geometry was not specified, default to the
  267.      parent's geometry, so that the resource "Emacs.geometry" is the
  268.      same as the resource "Emacs.EmacsScreen.geometry".
  269.    */
  270.   if (!ew->emacs_screen.emacs_geometry)
  271.     {
  272.       XtVaGetValues (XtParent (wmshell),
  273.              XtNgeometry, &ew->emacs_screen.emacs_geometry, 0);
  274.       if (!ew->emacs_screen.emacs_geometry)
  275.     XtVaGetValues (wmshell,
  276.                XtNgeometry, &ew->emacs_screen.emacs_geometry, 0);
  277.     }
  278.  
  279.   /* -geometry overrides all other resources, but only applies to
  280.      the first screen. */
  281.   if (is_first_screen)
  282.     {
  283.       char *geom = 0;
  284.       XtGetSubresources ((Widget) ew, (XtPointer) &geom,
  285.              ew->core.name,
  286.              ew->core.widget_class->core_class.class_name,
  287.              initial_geometry_resources,
  288.              XtNumber (initial_geometry_resources), 0, 0);
  289.       if (geom)
  290.     ew->emacs_screen.emacs_geometry = geom;
  291.       is_first_screen = False;
  292.     }
  293.  
  294.   if (ew->emacs_screen.emacs_geometry)
  295.     parse_result = XParseGeometry (ew->emacs_screen.emacs_geometry,
  296.                    &x, &y, &columns, &rows);
  297.   else
  298.     parse_result = 0;
  299.  
  300.   change_screen_size (screen, rows, columns, 0);
  301.   char_to_pixel_size (ew, columns, rows, &pixel_width, &pixel_height);
  302.   ew->core.width = pixel_width;
  303.   ew->core.height = pixel_height;
  304.  
  305.   /* If a position was specified, assign it to the shell widget. */
  306.   if (parse_result & (XValue | YValue))
  307.     {
  308.       /* the tricky things with the sign is to make sure that
  309.      -0 is printed -0. */
  310.       int len;
  311.       char *tem;
  312.       sprintf (shell_position, "=%c%d%c%d",
  313.            parse_result & XNegative ? '-' : '+', x < 0 ? -x : x,
  314.            parse_result & YNegative ? '-' : '+', y < 0 ? -y : y);
  315.       len = strlen (shell_position) + 1;
  316.       tem = xmalloc (len);
  317.       strncpy (tem, shell_position, len);
  318.       XtVaSetValues (wmshell, XtNgeometry, tem, 0);
  319.     }
  320.   else if (parse_result & (WidthValue | HeightValue))
  321.     {
  322.       int len;
  323.       char *tem;
  324.       sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
  325.       len = strlen (shell_position) + 1;
  326.       tem = xmalloc (len);
  327.       strncpy (tem, shell_position, len);
  328.       XtVaSetValues (wmshell, XtNgeometry, tem, 0);
  329.     }
  330. }
  331.  
  332. static void
  333. update_wm_hints (EmacsScreenWidget ew)
  334. {
  335.   Widget wmshell = get_wm_shell ((Widget)ew);
  336.   int cw;
  337.   int ch;
  338.   Dimension rounded_width;
  339.   Dimension rounded_height;
  340.   int char_width;
  341.   int char_height;
  342.   int base_width;
  343.   int base_height;
  344.  
  345.   pixel_to_char_size (ew, ew->core.width, ew->core.height,
  346.               &char_width, &char_height);
  347.   char_to_pixel_size (ew, char_width, char_height,
  348.               &rounded_width, &rounded_height);
  349.   get_default_char_pixel_size (ew, &cw, &ch);
  350.  
  351.   base_width = (wmshell->core.width - ew->core.width
  352.         + (rounded_width - (char_width * cw)));
  353.   base_height = (wmshell->core.height - ew->core.height
  354.         + (rounded_height - (char_height * ch)));
  355.  
  356.   XtVaSetValues (wmshell,
  357.          XtNbaseWidth, base_width,
  358.          XtNbaseHeight, base_height,
  359.          XtNwidthInc, cw, 
  360.          XtNheightInc, ch,
  361.          XtNminWidth, base_width + 10 * cw,
  362.          XtNminHeight, base_height + 4 * ch,
  363.          0);
  364. }
  365.  
  366. static void
  367. create_screen_gcs (EmacsScreenWidget ew)
  368. {
  369.   struct screen* s = ew->emacs_screen.screen;
  370.  
  371.   s->display.x->normal_gc =
  372.     XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
  373.   s->display.x->reverse_gc =
  374.     XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
  375.   s->display.x->cursor_gc =
  376.     XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)), 0, 0);
  377. }
  378.  
  379. static void
  380. setup_screen_gcs (EmacsScreenWidget ew)
  381. {
  382.   XGCValues gc_values;
  383.   struct screen* s = ew->emacs_screen.screen;
  384.  
  385.   static char cursor_bits[] =
  386.     {
  387.       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  388.       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  389.       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  390.       0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  391.     };
  392.  
  393.  
  394.   /* Normal video */
  395.   gc_values.font = ew->emacs_screen.font->fid;
  396.   gc_values.foreground = ew->emacs_screen.foreground_pixel;
  397.   gc_values.background = ew->core.background_pixel;
  398.   gc_values.graphics_exposures = False;
  399.   XChangeGC (XtDisplay (ew), s->display.x->normal_gc,
  400.          (GCFont | GCForeground | GCBackground | GCGraphicsExposures),
  401.          &gc_values);
  402.  
  403.   /* Reverse video style. */
  404.   gc_values.font = ew->emacs_screen.font->fid;
  405.   gc_values.foreground = ew->core.background_pixel;
  406.   gc_values.background = ew->emacs_screen.foreground_pixel;
  407.   gc_values.graphics_exposures = False;
  408.   XChangeGC (XtDisplay (ew), s->display.x->reverse_gc,
  409.          (GCFont | GCForeground | GCBackground | GCGraphicsExposures),
  410.          &gc_values);
  411.  
  412.   /* Cursor has to have an empty stipple. */
  413.   gc_values.font = ew->emacs_screen.font->fid;
  414.   gc_values.foreground = ew->core.background_pixel;
  415.   gc_values.background = ew->emacs_screen.cursor_color;
  416.   gc_values.graphics_exposures = False;
  417.   gc_values.stipple =
  418.     XCreateBitmapFromData (XtDisplay (ew),
  419.                RootWindowOfScreen (XtScreen (ew)),
  420.                cursor_bits, 16, 16);
  421.   XChangeGC (XtDisplay (ew), s->display.x->cursor_gc,
  422.          (GCFont | GCForeground | GCBackground | GCGraphicsExposures
  423.           | GCStipple),
  424.          &gc_values);
  425. }
  426.  
  427. static void
  428. update_various_screen_slots (EmacsScreenWidget ew)
  429. {
  430.   struct x_display* x = ew->emacs_screen.screen->display.x;
  431.   x->pixel_height = ew->core.height;
  432.   x->pixel_width = ew->core.width;
  433.   x->internal_border_width = ew->emacs_screen.internal_border_width;
  434. }
  435.  
  436. static void 
  437. EmacsScreenInitialize (Widget request, Widget new,
  438.                ArgList dum1, Cardinal *dum2)
  439. {
  440.   EmacsScreenWidget ew = (EmacsScreenWidget)new;
  441.  
  442.   if (!ew->emacs_screen.screen)
  443.     {
  444.       fprintf (stderr,
  445.            "can't create an emacs screen widget without a screen\n");
  446.       exit (1);
  447.     }
  448.  
  449.   /* If the "Emacs.EmacsScreen.{default,Face}.{attributeFont,AttributeFont}"
  450.      resource is set, then it always overrides "Emacs.EmacsScreen.{font,Font}".
  451.      It's unfortunate that we have to do this, but we need to know the font
  452.      size for screen-sizing purposes before the faces get initialized.  If
  453.      the "default.attributeFont" isn't set, then we use the font of this
  454.      ScreenWidget itself, defaulting to XtDefaultFont.  Up in the lisp code,
  455.      the "default" face will use the screen's font if its own is not set,
  456.      so everything stays in sync -- it's not possible for the screen's font
  457.      and the default face's font to be different.
  458.    */
  459.   {
  460.     XFontStruct *f = 0;
  461.     XtResource face_res;
  462.     face_res.resource_name = "attributeFont";
  463.     face_res.resource_class = "AttributeFont";
  464.     face_res.resource_type = XtRFontStruct;
  465.     face_res.resource_size = sizeof (XFontStruct *);
  466.     face_res.resource_offset = 0;
  467.     face_res.default_type = XtRImmediate;
  468.     face_res.default_addr = 0;
  469.     XtGetSubresources ((Widget) ew, (XtPointer) &f, "default", "Face",
  470.                &face_res, 1, NULL, 0);
  471.       
  472.     if (f)
  473.       ew->emacs_screen.font = f;
  474.     else if (! ew->emacs_screen.font)
  475.       {
  476.     fprintf (stderr, "emacs screen widget could not load a font\n");
  477.     exit (1);
  478.       }
  479.   }
  480.  
  481.   set_screen_size (ew);
  482.   create_screen_gcs (ew);
  483.   setup_screen_gcs (ew);
  484.   update_various_screen_slots (ew);
  485. }
  486.  
  487.  
  488. static void
  489. EmacsScreenRealize (Widget widget, XtValueMask *mask,
  490.             XSetWindowAttributes *attrs)
  491. {
  492.   EmacsScreenWidget ew = (EmacsScreenWidget)widget;
  493.  
  494.   attrs->event_mask = (KeyPressMask | ExposureMask | ButtonPressMask |
  495.                ButtonReleaseMask | StructureNotifyMask |
  496.                FocusChangeMask | PointerMotionHintMask |
  497.                PointerMotionMask | LeaveWindowMask | EnterWindowMask |
  498.                VisibilityChangeMask | PropertyChangeMask |
  499.                StructureNotifyMask | SubstructureNotifyMask |
  500.                SubstructureRedirectMask);
  501.   *mask |= CWEventMask;
  502.   XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
  503.           attrs);
  504.   update_wm_hints (ew);
  505. }
  506.  
  507. extern void free_screen_faces (struct screen *);
  508.  
  509. static void
  510. EmacsScreenDestroy (Widget widget)
  511. {
  512.   EmacsScreenWidget ew = (EmacsScreenWidget) widget;
  513.   struct screen* s = ew->emacs_screen.screen;
  514.  
  515.   if (! s) abort ();
  516.   if (! s->display.x) abort ();
  517.   if (! s->display.x->normal_gc) abort ();
  518.  
  519.   /* this would be called from Fdelete_screen() but it needs to free some
  520.      stuff after the widget has been finalized but before the widget has
  521.      been freed. */
  522.   free_screen_faces (s);
  523.  
  524.   /* need to be careful that the face-freeing code doesn't free these too */
  525.   XFreeGC (XtDisplay (widget), s->display.x->normal_gc);
  526.   XFreeGC (XtDisplay (widget), s->display.x->reverse_gc);
  527.   XFreeGC (XtDisplay (widget), s->display.x->cursor_gc);
  528. }
  529.  
  530. void
  531. EmacsScreenResize (Widget widget)
  532. {
  533.   EmacsScreenWidget ew = (EmacsScreenWidget)widget;
  534.   struct screen *s = ew->emacs_screen.screen;
  535.   int columns;
  536.   int rows;
  537.   
  538.   pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
  539.   change_screen_size (s, rows, columns, 0);
  540.   update_wm_hints (ew);
  541.   update_various_screen_slots (ew);
  542. }
  543.  
  544. static Boolean
  545. EmacsScreenSetValues (Widget cur_widget, Widget req_widget, Widget new_widget,
  546.               ArgList dum1, Cardinal *dum2)
  547. {
  548.   EmacsScreenWidget cur = (EmacsScreenWidget)cur_widget;
  549.   EmacsScreenWidget new = (EmacsScreenWidget)new_widget;
  550.  
  551.   Boolean needs_a_refresh = False;
  552.   Boolean has_to_recompute_size;
  553.   Boolean has_to_recompute_gcs;
  554.   Boolean has_to_update_hints;
  555.  
  556.   int char_width, char_height;
  557.   Dimension pixel_width;
  558.   Dimension pixel_height;
  559.   
  560.   has_to_recompute_gcs = (cur->emacs_screen.font != new->emacs_screen.font
  561.               || (cur->emacs_screen.foreground_pixel
  562.                   != new->emacs_screen.foreground_pixel)
  563.               || (cur->core.background_pixel
  564.                   != new->core.background_pixel)
  565.               );
  566.   
  567.   has_to_recompute_size = (cur->emacs_screen.font != new->emacs_screen.font
  568.                && cur->core.width == new->core.width
  569.                && cur->core.height == new->core.height);
  570.  
  571.   has_to_update_hints = (cur->emacs_screen.font != new->emacs_screen.font);
  572.  
  573.   if (has_to_recompute_gcs)
  574.     {
  575.       setup_screen_gcs (new);
  576.       needs_a_refresh = True;
  577.     }
  578.               
  579.   if (has_to_recompute_size)
  580.     {
  581.       pixel_width = new->core.width;
  582.       pixel_height = new->core.height;
  583.       pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
  584.               &char_height);
  585.       char_to_pixel_size (new, char_width, char_height, &pixel_width,
  586.               &pixel_height);
  587.       new->core.width = pixel_width;
  588.       new->core.height = pixel_height;
  589.  
  590.       change_screen_size (new->emacs_screen.screen, char_height, char_width,
  591.               0);
  592.       needs_a_refresh = True;
  593.     }
  594.  
  595.   if (has_to_update_hints)
  596.     update_wm_hints (new);
  597.  
  598.   update_various_screen_slots (new);
  599.  
  600.   return needs_a_refresh;
  601. }
  602.  
  603. static XtGeometryResult
  604. EmacsScreenQueryGeometry (Widget widget, XtWidgetGeometry* request,
  605.               XtWidgetGeometry* result)
  606. {
  607.   EmacsScreenWidget ew = (EmacsScreenWidget)widget;
  608.  
  609.   int mask = request->request_mode;
  610.   Dimension ok_width, ok_height;
  611.  
  612.   if (mask & (CWWidth | CWHeight))
  613.     {
  614.       round_size_to_char (ew,
  615.               (mask & CWWidth) ? request->width : ew->core.width,
  616.               ((mask & CWHeight) ? request->height
  617.                : ew->core.height),
  618.               &ok_width, &ok_height);
  619.       if ((mask & CWWidth) && (ok_width != request->width))
  620.     {
  621.       result->request_mode |= CWWidth;
  622.       result->width = ok_width;
  623.     }
  624.       if ((mask & CWHeight) && (ok_height != request->height))
  625.     {
  626.       result->request_mode |= CWHeight;
  627.       result->height = ok_height;
  628.     }
  629.     }
  630.   return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
  631. }
  632.  
  633.  
  634. /* I don't know why this is necessary; Matthieu said he had to do
  635.    it to make the focus handlers work??
  636.  */
  637. static void
  638. key_press (Widget w, XEvent* event, String *params, Cardinal *n_params)
  639. {
  640. }
  641.  
  642. static void
  643. emacs_screen_focus_handler (Widget w, XEvent *event, String *params,
  644.                 Cardinal *n_params)
  645. {
  646.   emacs_Xt_focus_event_handler (event, 0);
  647. }
  648.  
  649. /* Special entrypoints */
  650. void
  651. EmacsScreenSetCharSize (Widget widget, int columns, int rows)
  652. {
  653.   EmacsScreenWidget ew = (EmacsScreenWidget) widget;
  654.   Dimension pixel_width, pixel_height, granted_width, granted_height;
  655.   XtGeometryResult result;
  656.   if (columns < 3) columns = 3;  /* no way buddy */
  657.   if (rows < 3) rows = 3;
  658.   char_to_pixel_size (ew, columns, rows, &pixel_width, &pixel_height);
  659.   result = XtMakeResizeRequest ((Widget)ew,
  660.                 pixel_width, pixel_height,
  661.                 &granted_width, &granted_height);
  662.   if (result == XtGeometryAlmost)
  663.     XtMakeResizeRequest ((Widget) ew, granted_width, granted_height,
  664.              NULL, NULL);
  665.   /* damn Paned widget won't ever change its width.  Force it. */
  666.   if (ew->core.width != pixel_width)
  667.     {
  668.       XtVaSetValues (XtParent ((Widget) ew), XtNwidth, pixel_width, 0);
  669.       XtVaSetValues ((Widget) ew, XtNwidth, pixel_width, 0);
  670.     }
  671. }
  672.