home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / e20313sr.zip / emacs / 20.3.1 / src / widget.c < prev    next >
C/C++ Source or Header  |  1999-07-31  |  32KB  |  981 lines

  1. /* The emacs frame 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, Inc., 59 Temple Place - Suite 330,
  19. Boston, MA 02111-1307, USA.  */
  20.  
  21. /* Emacs 19 face widget ported by Fred Pierresteguy */
  22.  
  23. /* This file has been censored by the Communications Decency Act.
  24.    That law was passed under the guise of a ban on pornography, but
  25.    it bans far more than that.  This file did not contain pornography,
  26.    but it was censored nonetheless.
  27.  
  28.    For information on US government censorship of the Internet, and
  29.    what you can do to bring back freedom of the press, see the web
  30.    site http://www.vtw.org/
  31.    */
  32.  
  33. #include <config.h>
  34. #include <stdio.h>
  35. #include "lisp.h"
  36. #include "xterm.h"
  37.  
  38. #include "frame.h"
  39. #include "window.h"
  40.  
  41. #include "dispextern.h"
  42. #include "blockinput.h"
  43.  
  44. #include <X11/StringDefs.h>
  45. #include <X11/IntrinsicP.h>
  46. #include <X11/cursorfont.h>
  47. #include "widgetprv.h"
  48. #include <X11/ObjectP.h>
  49. #include <X11/Shell.h>
  50. #include <X11/ShellP.h>
  51. #include "../lwlib/lwlib.h"
  52.  
  53. #define max(a, b) ((a) > (b) ? (a) : (b))
  54.  
  55. /* This sucks: this is the first default that x-faces.el tries.  This won't
  56.    be used unless neither the "Emacs.EmacsFrame" resource nor the
  57.    "Emacs.EmacsFrame" resource is set; the frame
  58.    may have the wrong default size if this font doesn't exist, but some other
  59.    font that x-faces.el does.  The workaround is to specify some font in the
  60.    resource database; I don't know a solution other than duplicating the font-
  61.    searching code from x-faces.el in this file.
  62.  
  63.    This also means that if "Emacs.EmacsFrame" is specified as a non-
  64.    existent font, then Xt is going to substitute "XtDefaultFont" for it,
  65.    which is a different size than this one.  The solution for this is to
  66.    make x-faces.el try to use XtDefaultFont.  The problem with that is that
  67.    XtDefaultFont is almost certainly variable-width.
  68.  
  69.    #### Perhaps we could have this code explicitly set XtDefaultFont to this?
  70.  */
  71. #define DEFAULT_FACE_FONT "-*-courier-medium-r-*-*-*-120-*-*-*-*-iso8859-*"
  72.  
  73.  
  74. static void EmacsFrameInitialize (/*Widget, Widget, ArgList, Cardinal * */);
  75. static void EmacsFrameDestroy (/* Widget */);
  76. static void EmacsFrameRealize (/* Widget, XtValueMask*, XSetWindowAttributes* */);
  77. void EmacsFrameResize (/* Widget widget */);
  78. static Boolean EmacsFrameSetValues (/* Widget, Widget, Widget,
  79.                      ArgList, Cardinal * */);
  80. static XtGeometryResult EmacsFrameQueryGeometry (/* Widget, XtWidgetGeometry*,
  81.                           XtWidgetGeometry* */);
  82.  
  83.  
  84. #undef XtOffset
  85. #define XtOffset(p_type,field) \
  86.     ((Cardinal) (((char *) (&(((p_type)0)->field))) - ((char *)0)))
  87. #define offset(field) XtOffset(EmacsFrame, emacs_frame.field)
  88.  
  89. static XtResource resources[] = {
  90.   {XtNgeometry, XtCGeometry, XtRString, sizeof(String),
  91.      offset (geometry), XtRString, (XtPointer) 0},
  92.   {XtNiconic, XtCIconic, XtRBoolean, sizeof(Boolean),
  93.      offset (iconic), XtRImmediate, (XtPointer) False},
  94.  
  95.   {XtNemacsFrame, XtCEmacsFrame, XtRPointer, sizeof (XtPointer),
  96.      offset (frame), XtRImmediate, 0},
  97.  
  98.   {XtNminibuffer, XtCMinibuffer, XtRInt, sizeof (int),
  99.      offset (minibuffer), XtRImmediate, (XtPointer)0},
  100.   {XtNunsplittable, XtCUnsplittable, XtRBoolean, sizeof (Boolean),
  101.      offset (unsplittable), XtRImmediate, (XtPointer)0},
  102.   {XtNinternalBorderWidth, XtCInternalBorderWidth, XtRInt, sizeof (int),
  103.      offset (internal_border_width), XtRImmediate, (XtPointer)4},
  104.   {XtNinterline, XtCInterline, XtRInt, sizeof (int),
  105.      offset (interline), XtRImmediate, (XtPointer)0},
  106.   {XtNfont,  XtCFont, XtRFontStruct, sizeof(XFontStruct *),
  107.      offset(font),XtRString, DEFAULT_FACE_FONT},
  108.   {XtNforeground, XtCForeground, XtRPixel, sizeof(Pixel),
  109.      offset(foreground_pixel), XtRString, "XtDefaultForeground"},
  110.   {XtNcursorColor, XtCForeground, XtRPixel, sizeof(Pixel),
  111.      offset(cursor_color), XtRString, "XtDefaultForeground"},
  112.   {XtNbarCursor, XtCBarCursor, XtRBoolean, sizeof (Boolean),
  113.      offset (bar_cursor), XtRImmediate, (XtPointer)0},
  114.   {XtNvisualBell, XtCVisualBell, XtRBoolean, sizeof (Boolean),
  115.      offset (visual_bell), XtRImmediate, (XtPointer)0},
  116.   {XtNbellVolume, XtCBellVolume, XtRInt, sizeof (int),
  117.      offset (bell_volume), XtRImmediate, (XtPointer)0},
  118. };
  119.  
  120. #undef offset
  121.  
  122. /*
  123. static XtActionsRec
  124. emacsFrameActionsTable [] = {
  125.   {"keypress",  key_press},
  126.   {"focus_in",  emacs_frame_focus_handler},
  127.   {"focus_out", emacs_frame_focus_handler},
  128. };
  129.  
  130. static char
  131. emacsFrameTranslations [] = "\
  132. <KeyPress>: keypress()\n\
  133. <FocusIn>:  focus_in()\n\
  134. <FocusOut>: focus_out()\n\
  135. ";
  136. */
  137.  
  138. EmacsFrameClassRec emacsFrameClassRec = {
  139.     { /* core fields */
  140.     /* superclass        */    &widgetClassRec,
  141.     /* class_name        */    "EmacsFrame",
  142.     /* widget_size        */    sizeof(EmacsFrameRec),
  143.     /* class_initialize        */    0,
  144.     /* class_part_initialize    */    0,
  145.     /* class_inited        */    FALSE,
  146.     /* initialize        */    EmacsFrameInitialize,
  147.     /* initialize_hook        */    0,
  148.     /* realize            */    EmacsFrameRealize,
  149.     /* actions            */    0, /*emacsFrameActionsTable*/
  150.     /* num_actions        */    0, /*XtNumber (emacsFrameActionsTable)*/
  151.     /* resources        */    resources,
  152.     /* resource_count        */    XtNumber(resources),
  153.     /* xrm_class        */    NULLQUARK,
  154.     /* compress_motion        */    TRUE,
  155.     /* compress_exposure    */    TRUE,
  156.     /* compress_enterleave    */    TRUE,
  157.     /* visible_interest        */    FALSE,
  158.     /* destroy            */    EmacsFrameDestroy,
  159.     /* resize            */    EmacsFrameResize,
  160.     /* expose            */    XtInheritExpose,
  161.     /* set_values        */    EmacsFrameSetValues,
  162.     /* set_values_hook        */    0,
  163.     /* set_values_almost    */    XtInheritSetValuesAlmost,
  164.     /* get_values_hook        */    0,
  165.     /* accept_focus        */    XtInheritAcceptFocus,
  166.     /* version            */    XtVersion,
  167.     /* callback_private        */    0,
  168.     /* tm_table            */    0, /*emacsFrameTranslations*/
  169.     /* query_geometry        */    EmacsFrameQueryGeometry,
  170.     /* display_accelerator    */    XtInheritDisplayAccelerator,
  171.     /* extension        */    0
  172.     }
  173. };
  174.  
  175. WidgetClass emacsFrameClass = (WidgetClass) &emacsFrameClassRec;
  176.  
  177. static void
  178. get_default_char_pixel_size (ew, pixel_width, pixel_height)
  179.      EmacsFrame ew;
  180.      int* pixel_width;
  181.      int* pixel_height;
  182. {
  183.   struct frame* f = ew->emacs_frame.frame;
  184.   *pixel_width = FONT_WIDTH (f->output_data.x->font);
  185.   *pixel_height = f->output_data.x->line_height;
  186. }
  187.  
  188. static void
  189. pixel_to_char_size (ew, pixel_width, pixel_height, char_width, char_height)
  190.      EmacsFrame ew;
  191.      Dimension pixel_width;
  192.      Dimension pixel_height;
  193.      int* char_width;
  194.      int* char_height;
  195. {
  196.   struct frame* f = ew->emacs_frame.frame;
  197.   *char_width = PIXEL_TO_CHAR_WIDTH (f, (int) pixel_width);
  198.   *char_height = PIXEL_TO_CHAR_HEIGHT (f, (int) pixel_height);
  199. }
  200.  
  201. static void
  202. char_to_pixel_size (ew, char_width, char_height, pixel_width, pixel_height)
  203.      EmacsFrame ew;
  204.      int char_width;
  205.      int char_height;
  206.      Dimension* pixel_width;
  207.      Dimension* pixel_height;
  208. {
  209.   struct frame* f = ew->emacs_frame.frame;
  210.   *pixel_width = CHAR_TO_PIXEL_WIDTH (f, char_width);
  211.   *pixel_height = CHAR_TO_PIXEL_HEIGHT (f, char_height);
  212. }
  213.  
  214. static void
  215. round_size_to_char (ew, in_width, in_height, out_width, out_height)
  216.      EmacsFrame ew;
  217.      Dimension in_width;
  218.      Dimension in_height;
  219.      Dimension* out_width;
  220.      Dimension* out_height;
  221. {
  222.   int char_width;
  223.   int char_height;
  224.   pixel_to_char_size (ew, in_width, in_height, &char_width, &char_height);
  225.   char_to_pixel_size (ew, char_width, char_height, out_width, out_height);
  226. }
  227.  
  228. static Widget
  229. get_wm_shell (w)
  230.      Widget w;
  231. {
  232.   Widget wmshell;
  233.  
  234.   for (wmshell = XtParent (w);
  235.        wmshell && !XtIsWMShell (wmshell);
  236.        wmshell = XtParent (wmshell));
  237.  
  238.   return wmshell;
  239. }
  240.  
  241. static void
  242. mark_shell_size_user_specified (wmshell)
  243.      Widget wmshell;
  244. {
  245.   if (! XtIsWMShell (wmshell)) abort ();
  246.   /* This is kind of sleazy, but I can't see how else to tell it to make it
  247.      mark the WM_SIZE_HINTS size as user specified when appropriate. */
  248.   ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;
  249. }
  250.  
  251.  
  252. /* Can't have static frame locals because of some broken compilers.
  253.    Normally, initializing a variable like this doesn't work in emacs,
  254.    but it's ok in this file because it must come after lastfile (and
  255.    thus have its data not go into text space) because Xt needs to
  256.    write to initialized data objects too.
  257.  */
  258. static Boolean first_frame_p = True;
  259.  
  260. static void
  261. set_frame_size (ew)
  262.      EmacsFrame ew;
  263. {
  264.   /* The widget hierarchy is
  265.  
  266.     argv[0]            emacsShell    pane    Frame-NAME
  267.     ApplicationShell    EmacsShell    Paned    EmacsFrame
  268.  
  269.      We accept geometry specs in this order:
  270.  
  271.     *Frame-NAME.geometry
  272.     *EmacsFrame.geometry
  273.     Emacs.geometry
  274.  
  275.      Other possibilities for widget hierarchies might be
  276.  
  277.     argv[0]            frame        pane    Frame-NAME
  278.     ApplicationShell    EmacsShell    Paned    EmacsFrame
  279.      or
  280.     argv[0]            Frame-NAME    pane    Frame-NAME
  281.     ApplicationShell    EmacsShell    Paned    EmacsFrame
  282.      or
  283.     argv[0]            Frame-NAME    pane    emacsTextPane
  284.     ApplicationShell    EmacsFrame    Paned    EmacsTextPane
  285.  
  286.      With the current setup, the text-display-area is the part which is
  287.      an emacs "frame", since that's the only part managed by emacs proper
  288.      (the menubar and the parent of the menubar and all that sort of thing
  289.      are managed by lwlib.)
  290.  
  291.      The EmacsShell widget is simply a replacement for the Shell widget 
  292.      which is able to deal with using an externally-supplied window instead
  293.      of always creating its own.  It is not actually emacs specific, and
  294.      should possibly have class "Shell" instead of "EmacsShell" to simplify
  295.      the resources.
  296.  
  297.    */
  298.  
  299.   /* Geometry of the AppShell */
  300.   int app_flags = 0;
  301.   int app_x = 0;
  302.   int app_y = 0;
  303.   unsigned int app_w = 0;
  304.   unsigned int app_h = 0;
  305.   
  306.   /* Geometry of the EmacsFrame */
  307.   int frame_flags = 0;
  308.   int frame_x = 0;
  309.   int frame_y = 0;
  310.   unsigned int frame_w = 0;
  311.   unsigned int frame_h = 0;
  312.   
  313.   /* Hairily merged geometry */
  314.   int x = 0;
  315.   int y = 0;
  316.   unsigned int w = ew->emacs_frame.frame->width;
  317.   unsigned int h = ew->emacs_frame.frame->height;
  318.   int flags = 0;
  319.   
  320.   Widget wmshell = get_wm_shell ((Widget) ew);
  321.   /* Each Emacs shell is now independent and top-level.  */
  322.   Widget app_shell = wmshell;
  323.   
  324.   if (! XtIsSubclass (wmshell, shellWidgetClass)) abort ();
  325.  
  326.   /* We don't need this for the moment. The geometry is computed in 
  327.      xfns.c.  */
  328. #if 0
  329.   /* If the EmacsFrame doesn't have a geometry but the shell does,
  330.      treat that as the geometry of the frame.  (Is this bogus?
  331.      I'm not sure.) */
  332.   if (ew->emacs_frame.geometry == 0)
  333.     XtVaGetValues (wmshell, XtNgeometry, &ew->emacs_frame.geometry, 0);
  334.  
  335.   /* If the Shell is iconic, then the EmacsFrame is iconic.  (Is
  336.      this bogus? I'm not sure.) */
  337.   if (!ew->emacs_frame.iconic)
  338.     XtVaGetValues (wmshell, XtNiconic, &ew->emacs_frame.iconic, 0);
  339.   
  340.   
  341.   {
  342.     char *geom = 0;
  343.     XtVaGetValues (app_shell, XtNgeometry, &geom, 0);
  344.     if (geom)
  345.       app_flags = XParseGeometry (geom, &app_x, &app_y, &app_w, &app_h);
  346.   }
  347.   
  348.   if (ew->emacs_frame.geometry)
  349.     frame_flags = XParseGeometry (ew->emacs_frame.geometry,
  350.                    &frame_x, &frame_y,
  351.                    &frame_w, &frame_h);
  352.   
  353.   if (first_frame_p)
  354.     {
  355.       /* If this is the first frame created:
  356.          ====================================
  357.  
  358.          - Use the ApplicationShell's size/position, if specified.
  359.            (This is "Emacs.geometry", or the "-geometry" command line arg.)
  360.          - Else use the EmacsFrame's size/position.
  361.            (This is "*Frame-NAME.geometry")
  362.  
  363.      - If the AppShell is iconic, the frame should be iconic.
  364.  
  365.      AppShell comes first so that -geometry always applies to the first
  366.      frame created, even if there is an "every frame" entry in the
  367.      resource database.
  368.        */
  369.       if (app_flags & (XValue | YValue))
  370.     {
  371.       x = app_x; y = app_y;
  372.       flags |= (app_flags & (XValue | YValue | XNegative | YNegative));
  373.     }
  374.       else if (frame_flags & (XValue | YValue))
  375.     {
  376.       x = frame_x; y = frame_y;
  377.       flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
  378.     }
  379.  
  380.       if (app_flags & (WidthValue | HeightValue))
  381.     {
  382.       w = app_w; h = app_h;
  383.       flags |= (app_flags & (WidthValue | HeightValue));
  384.     }
  385.       else if (frame_flags & (WidthValue | HeightValue))
  386.     {
  387.       w = frame_w; h = frame_h;
  388.       flags |= (frame_flags & (WidthValue | HeightValue));
  389.     }
  390.  
  391.       /* If the AppShell is iconic, then the EmacsFrame is iconic. */
  392.       if (!ew->emacs_frame.iconic)
  393.     XtVaGetValues (app_shell, XtNiconic, &ew->emacs_frame.iconic, 0);
  394.  
  395.       first_frame_p = False;
  396.     }
  397.   else
  398.     {
  399.       /* If this is not the first frame created:
  400.          ========================================
  401.  
  402.          - use the EmacsFrame's size/position if specified
  403.          - Otherwise, use the ApplicationShell's size, but not position.
  404.  
  405.          So that means that one can specify the position of the first frame
  406.          with "Emacs.geometry" or `-geometry'; but can only specify the
  407.      position of subsequent frames with "*Frame-NAME.geometry".
  408.  
  409.      AppShell comes second so that -geometry does not apply to subsequent
  410.      frames when there is an "every frame" entry in the resource db,
  411.      but does apply to the first frame.
  412.        */
  413.       if (frame_flags & (XValue | YValue))
  414.     {
  415.       x = frame_x; y = frame_y;
  416.       flags |= (frame_flags & (XValue | YValue | XNegative | YNegative));
  417.     }
  418.  
  419.       if (frame_flags & (WidthValue | HeightValue))
  420.     {
  421.       w = frame_w; h = frame_h;
  422.       flags |= (frame_flags & (WidthValue | HeightValue));
  423.     }
  424.       else if (app_flags & (WidthValue | HeightValue))
  425.     {
  426.       w = app_w;
  427.       h = app_h;
  428.       flags |= (app_flags & (WidthValue | HeightValue));
  429.     }
  430.     }
  431. #endif /* 0 */
  432.   {
  433.     struct frame* frame = ew->emacs_frame.frame;
  434.     Dimension pixel_width, pixel_height;
  435.     char shell_position [32];
  436.  
  437.     /* Take into account the size of the scrollbar */
  438.     frame->output_data.x->vertical_scroll_bar_extra
  439.       = (!FRAME_HAS_VERTICAL_SCROLL_BARS (frame)
  440.      ? 0
  441.      : FRAME_SCROLL_BAR_PIXEL_WIDTH (frame) > 0
  442.      ? FRAME_SCROLL_BAR_PIXEL_WIDTH (frame)
  443.      : (FRAME_SCROLL_BAR_COLS (frame)
  444.         * FONT_WIDTH (frame->output_data.x->font)));
  445.  
  446.     change_frame_size (frame, h, w, 1, 0);
  447.     char_to_pixel_size (ew, w, h, &pixel_width, &pixel_height);
  448.     ew->core.width = pixel_width;
  449.     ew->core.height = pixel_height;
  450.  
  451. #if 0 /* xfns.c takes care of this now.  */
  452.     /* If a position was specified, assign it to the shell widget.
  453.        (Else WM won't do anything with it.)
  454.      */
  455.     if (flags & (XValue | YValue))
  456.       {
  457.     /* the tricky things with the sign is to make sure that
  458.        -0 is printed -0. */
  459.     int len;
  460.     char *tem;
  461.     sprintf (shell_position, "=%c%d%c%d",
  462.          flags & XNegative ? '-' : '+', x < 0 ? -x : x,
  463.          flags & YNegative ? '-' : '+', y < 0 ? -y : y);
  464.     len = strlen (shell_position) + 1;
  465.     tem = (char *) xmalloc (len);
  466.     strncpy (tem, shell_position, len);
  467.     XtVaSetValues (wmshell, XtNgeometry, tem, 0);
  468.       }
  469.     else if (flags & (WidthValue | HeightValue))
  470.       {
  471.     int len;
  472.     char *tem;
  473.     sprintf (shell_position, "=%dx%d", pixel_width, pixel_height);
  474.     len = strlen (shell_position) + 1;
  475.     tem = (char *) xmalloc (len);
  476.     strncpy (tem, shell_position, len);
  477.     XtVaSetValues (wmshell, XtNgeometry, tem, 0);
  478.       }
  479.  
  480.     /* If the geometry spec we're using has W/H components, mark the size
  481.        in the WM_SIZE_HINTS as user specified. */
  482.     if (flags & (WidthValue | HeightValue))
  483.       mark_shell_size_user_specified (wmshell);
  484.  
  485.     /* Also assign the iconic status of the frame to the Shell, so that
  486.        the WM sees it. */
  487.     XtVaSetValues (wmshell, XtNiconic, ew->emacs_frame.iconic, 0);
  488. #endif /* 0 */
  489.   }
  490. }
  491.  
  492. /* Nonzero tells update_wm_hints not to do anything
  493.    (the caller should call update_wm_hints explicitly later.)  */
  494. int update_hints_inhibit;
  495.  
  496. static void
  497. update_wm_hints (ew)
  498.      EmacsFrame ew;
  499. {
  500.   Widget wmshell = get_wm_shell ((Widget)ew);
  501.   int cw;
  502.   int ch;
  503.   Dimension rounded_width;
  504.   Dimension rounded_height;
  505.   int char_width;
  506.   int char_height;
  507.   int base_width;
  508.   int base_height;
  509.   int min_rows = 0, min_cols = 0;
  510.  
  511.   if (update_hints_inhibit)
  512.     return;
  513.  
  514. #if 0
  515.   check_frame_size (ew->emacs_frame.frame, &min_rows, &min_cols);
  516. #endif
  517.  
  518.   pixel_to_char_size (ew, ew->core.width, ew->core.height,
  519.               &char_width, &char_height);
  520.   char_to_pixel_size (ew, char_width, char_height,
  521.               &rounded_width, &rounded_height);
  522.   get_default_char_pixel_size (ew, &cw, &ch); 
  523.  
  524.   base_width = (wmshell->core.width - ew->core.width
  525.         + (rounded_width - (char_width * cw)));
  526.   base_height = (wmshell->core.height - ew->core.height
  527.         + (rounded_height - (char_height * ch)));
  528.  
  529.   /* This is kind of sleazy, but I can't see how else to tell it to
  530.      make it mark the WM_SIZE_HINTS size as user specified.
  531.    */
  532. /*  ((WMShellWidget) wmshell)->wm.size_hints.flags |= USSize;*/
  533.  
  534.   XtVaSetValues (wmshell,
  535.          XtNbaseWidth, base_width,
  536.          XtNbaseHeight, base_height,
  537.          XtNwidthInc, cw, 
  538.          XtNheightInc, ch,
  539.          XtNminWidth, base_width + min_cols * cw,
  540.          XtNminHeight, base_height + min_rows * ch,
  541.          0);
  542. }
  543.  
  544. static void
  545. create_frame_gcs (ew)
  546.      EmacsFrame ew;
  547. {
  548.   struct frame *s = ew->emacs_frame.frame;
  549.  
  550.   s->output_data.x->normal_gc
  551.     = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
  552.          (unsigned long)0, (XGCValues *)0);
  553.   s->output_data.x->reverse_gc
  554.     = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
  555.          (unsigned long)0, (XGCValues *)0);
  556.   s->output_data.x->cursor_gc
  557.     = XCreateGC (XtDisplay (ew), RootWindowOfScreen (XtScreen (ew)),
  558.          (unsigned long)0, (XGCValues *)0);
  559. }
  560.  
  561. static char setup_frame_cursor_bits[] =
  562. {
  563.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  564.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  565.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  566.   0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  567. };
  568.  
  569. static void
  570. setup_frame_gcs (ew)
  571.      EmacsFrame ew;
  572. {
  573.   XGCValues gc_values;
  574.   struct frame* s = ew->emacs_frame.frame;
  575.   Pixmap blank_stipple, blank_tile;
  576.  
  577.   /* We have to initialize all of our GCs to have a stipple/tile, otherwise
  578.      XGetGCValues returns uninitialized data when we query the stipple
  579.      (instead of None or something sensible) and it makes things hard.
  580.  
  581.      This should be fixed for real by not querying the GCs but instead having
  582.      some GC-based cache instead of the current face-based cache which doesn't
  583.      effectively cache all of the GC settings we need to use.
  584.    */
  585.  
  586.   blank_stipple
  587.     = XCreateBitmapFromData (XtDisplay (ew),
  588.                  RootWindowOfScreen (XtScreen (ew)),
  589.                  setup_frame_cursor_bits, 2, 2);
  590.  
  591.   /* use fg = 0, bg = 1 below, but it's irrelevant since this pixmap should
  592.      never actually get used as a background tile!
  593.    */
  594.   blank_tile
  595.     = XCreatePixmapFromBitmapData (XtDisplay(ew),
  596.                    RootWindowOfScreen (XtScreen (ew)),
  597.                    setup_frame_cursor_bits, 2, 2,
  598.                    (unsigned long)0, (unsigned long)1,
  599.                    ew->core.depth);
  600.  
  601.   /* Normal video */
  602.   gc_values.font = ew->emacs_frame.font->fid;
  603.   gc_values.foreground = ew->emacs_frame.foreground_pixel;
  604.   gc_values.background = ew->core.background_pixel;
  605.   gc_values.graphics_exposures = False;
  606.   gc_values.stipple = blank_stipple;
  607.   gc_values.tile = blank_tile;
  608.   XChangeGC (XtDisplay (ew), s->output_data.x->normal_gc,
  609.          (GCFont | GCForeground | GCBackground | GCGraphicsExposures
  610.           | GCStipple | GCTile),
  611.          &gc_values);
  612.  
  613.   /* Reverse video style. */
  614.   gc_values.font = ew->emacs_frame.font->fid;
  615.   gc_values.foreground = ew->core.background_pixel;
  616.   gc_values.background = ew->emacs_frame.foreground_pixel;
  617.   gc_values.graphics_exposures = False;
  618.   gc_values.stipple = blank_stipple;
  619.   gc_values.tile = blank_tile;
  620.   XChangeGC (XtDisplay (ew), s->output_data.x->reverse_gc,
  621.          (GCFont | GCForeground | GCBackground | GCGraphicsExposures
  622.           | GCStipple | GCTile),
  623.          &gc_values);
  624.  
  625.   /* Cursor has to have an empty stipple. */
  626.   gc_values.font = ew->emacs_frame.font->fid;
  627.   gc_values.foreground = ew->core.background_pixel;
  628.   gc_values.background = ew->emacs_frame.cursor_color;
  629.   gc_values.graphics_exposures = False;
  630.   gc_values.tile = blank_tile;
  631.   gc_values.stipple
  632.     = XCreateBitmapFromData (XtDisplay (ew),
  633.                  RootWindowOfScreen (XtScreen (ew)),
  634.                  setup_frame_cursor_bits, 16, 16);
  635.   XChangeGC (XtDisplay (ew), s->output_data.x->cursor_gc,
  636.          (GCFont | GCForeground | GCBackground | GCGraphicsExposures
  637.           | GCStipple | GCTile),
  638.          &gc_values);
  639. }
  640.  
  641. static void
  642. update_various_frame_slots (ew)
  643.      EmacsFrame ew;
  644. {
  645.   struct x_output *x = ew->emacs_frame.frame->output_data.x;
  646.   x->pixel_height = ew->core.height + x->menubar_height;
  647.   x->pixel_width = ew->core.width;
  648.   x->internal_border_width = ew->emacs_frame.internal_border_width;
  649.  
  650. }
  651.  
  652. static void
  653. update_from_various_frame_slots (ew)
  654.      EmacsFrame ew;
  655. {
  656.   struct x_output *x = ew->emacs_frame.frame->output_data.x;
  657.   ew->core.height = x->pixel_height - x->menubar_height;
  658.   ew->core.width = x->pixel_width;
  659.   ew->core.background_pixel = x->background_pixel;
  660.   ew->emacs_frame.internal_border_width = x->internal_border_width;
  661.   ew->emacs_frame.font = x->font;
  662.   ew->emacs_frame.foreground_pixel = x->foreground_pixel;
  663.   ew->emacs_frame.cursor_color = x->cursor_pixel;
  664.   ew->core.border_pixel = x->border_pixel;
  665. }
  666.  
  667. static void 
  668. EmacsFrameInitialize (request, new, dum1, dum2)
  669.      Widget request;
  670.      Widget new;
  671.      ArgList dum1;
  672.      Cardinal *dum2;
  673. {
  674.   EmacsFrame ew = (EmacsFrame)new;
  675.  
  676.   if (!ew->emacs_frame.frame)
  677.     {
  678.       fprintf (stderr,
  679.            "can't create an emacs frame widget without a frame\n");
  680.       exit (1);
  681.     }
  682.  
  683. #if 0 /* done in xfns.c */
  684.   /* If the "Emacs.EmacsFrame.{default,Face}.{attributeFont,AttributeFont}"
  685.      resource is set, then it always overrides "Emacs.EmacsFrame.{font,Font}".
  686.      It's unfortunate that we have to do this, but we need to know the font
  687.      size for frame-sizing purposes before the faces get initialized.  If
  688.      the "default.attributeFont" isn't set, then we use the font of this
  689.      EmacsFrame itself, defaulting to XtDefaultFont.  Up in the lisp code,
  690.      the "default" face will use the frame's font if its own is not set,
  691.      so everything stays in sync -- it's not possible for the frame's font
  692.      and the default face's font to be different.
  693.    */
  694.   {
  695.     XFontStruct *f = 0;
  696.     XtResource face_res;
  697.     face_res.resource_name = "attributeFont";
  698.     face_res.resource_class = "AttributeFont";
  699.     face_res.resource_type = XtRFontStruct;
  700.     face_res.resource_size = sizeof (XFontStruct *);
  701.     face_res.resource_offset = 0;
  702.     face_res.default_type = XtRImmediate;
  703.     face_res.default_addr = 0;
  704.     XtGetSubresources ((Widget) ew, (XtPointer) &f, "default", "Face",
  705.                &face_res, 1, NULL, 0);
  706.       
  707.     if (f)
  708.     ew->emacs_frame.font = f;
  709.     else if (! ew->emacs_frame.font)
  710.       {
  711.     fprintf (stderr, "emacs frame widget could not load a font\n");
  712.     exit (1);
  713.       }
  714.   }
  715.  
  716. /* Update the font field in frame */
  717.   ew->emacs_frame.frame->output_data.x->font = ew->emacs_frame.font;
  718. #endif
  719.  
  720.   update_from_various_frame_slots (ew);
  721.   set_frame_size (ew); 
  722. /*create_frame_gcs (ew);
  723.   setup_frame_gcs (ew);
  724.   update_various_frame_slots (ew); */
  725. }
  726.  
  727.  
  728. static void
  729. EmacsFrameRealize (widget, mask, attrs)
  730.      Widget widget;
  731.      XtValueMask *mask;
  732.      XSetWindowAttributes *attrs;
  733. {
  734.   EmacsFrame ew = (EmacsFrame)widget;
  735.  
  736.   attrs->event_mask = (STANDARD_EVENT_SET | PropertyChangeMask
  737.                | SubstructureNotifyMask | SubstructureRedirectMask);
  738.   *mask |= CWEventMask;
  739.   XtCreateWindow (widget, InputOutput, (Visual *)CopyFromParent, *mask,
  740.           attrs);
  741.   update_wm_hints (ew); 
  742. }
  743.  
  744. extern void free_frame_faces (/* struct frame * */);
  745.  
  746. static void
  747. EmacsFrameDestroy (widget)
  748.      Widget widget;
  749. {
  750.   EmacsFrame ew = (EmacsFrame) widget;
  751.   struct frame* s = ew->emacs_frame.frame;
  752.  
  753.   if (! s) abort ();
  754.   if (! s->output_data.x) abort ();
  755.   if (! s->output_data.x->normal_gc) abort ();
  756.  
  757.   /* this would be called from Fdelete_frame() but it needs to free some
  758.      stuff after the widget has been finalized but before the widget has
  759.      been freed. */
  760.   free_frame_faces (s);
  761.  
  762.   BLOCK_INPUT;
  763.   /* need to be careful that the face-freeing code doesn't free these too */
  764.   XFreeGC (XtDisplay (widget), s->output_data.x->normal_gc);
  765.   XFreeGC (XtDisplay (widget), s->output_data.x->reverse_gc);
  766.   XFreeGC (XtDisplay (widget), s->output_data.x->cursor_gc);
  767.   UNBLOCK_INPUT;
  768. }
  769.  
  770. void
  771. EmacsFrameResize (widget)
  772.      Widget widget;
  773. {
  774.   EmacsFrame ew = (EmacsFrame)widget;
  775.   struct frame *f = ew->emacs_frame.frame;
  776.   int columns;
  777.   int rows;
  778.  
  779.   pixel_to_char_size (ew, ew->core.width, ew->core.height, &columns, &rows);
  780.   change_frame_size (f, rows, columns, 0, 1);
  781.   update_wm_hints (ew); 
  782.   update_various_frame_slots (ew);
  783.  
  784.   cancel_mouse_face (f);
  785. }
  786.  
  787. static Boolean
  788. EmacsFrameSetValues (cur_widget, req_widget, new_widget, dum1, dum2)
  789.      Widget cur_widget;
  790.      Widget req_widget;
  791.      Widget new_widget;
  792.      ArgList dum1;
  793.      Cardinal *dum2;
  794. {
  795.   EmacsFrame cur = (EmacsFrame)cur_widget;
  796.   EmacsFrame new = (EmacsFrame)new_widget;
  797.  
  798.   Boolean needs_a_refresh = False;
  799.   Boolean has_to_recompute_size;
  800.   Boolean has_to_recompute_gcs;
  801.   Boolean has_to_update_hints;
  802.  
  803.   int char_width, char_height;
  804.   Dimension pixel_width;
  805.   Dimension pixel_height;
  806.   
  807.   has_to_recompute_gcs = (cur->emacs_frame.font != new->emacs_frame.font
  808.               || (cur->emacs_frame.foreground_pixel
  809.                   != new->emacs_frame.foreground_pixel)
  810.               || (cur->core.background_pixel
  811.                   != new->core.background_pixel)
  812.               );
  813.   
  814.   has_to_recompute_size = (cur->emacs_frame.font != new->emacs_frame.font
  815.                && cur->core.width == new->core.width
  816.                && cur->core.height == new->core.height);
  817.  
  818.   has_to_update_hints = (cur->emacs_frame.font != new->emacs_frame.font);
  819.  
  820.   if (has_to_recompute_gcs)
  821.     {
  822.       setup_frame_gcs (new);
  823.       needs_a_refresh = True;
  824.     }
  825.               
  826.   if (has_to_recompute_size)
  827.     {
  828.       pixel_width = new->core.width;
  829.       pixel_height = new->core.height;
  830.       pixel_to_char_size (new, pixel_width, pixel_height, &char_width,
  831.               &char_height);
  832.       char_to_pixel_size (new, char_width, char_height, &pixel_width,
  833.               &pixel_height);
  834.       new->core.width = pixel_width;
  835.       new->core.height = pixel_height;
  836.  
  837.       change_frame_size (new->emacs_frame.frame, char_height, char_width,
  838.               1, 0);
  839.       needs_a_refresh = True;
  840.     }
  841.  
  842.   if (has_to_update_hints)
  843.     update_wm_hints (new);
  844.  
  845.   update_various_frame_slots (new);
  846.  
  847.   /* #### This doesn't work, I haven't been able to find ANY kludge that
  848.      will let (x-create-frame '((iconic . t))) work.  It seems that changes
  849.      to wm_shell's iconic slot have no effect after it has been realized,
  850.      and calling XIconifyWindow doesn't work either (even though the window
  851.      has been created.)  Perhaps there is some property we could smash
  852.      directly, but I'm sick of this for now.
  853.    */
  854.   if (cur->emacs_frame.iconic != new->emacs_frame.iconic)
  855.     {
  856.       Widget wmshell = get_wm_shell ((Widget) cur);
  857.       XtVaSetValues (wmshell, XtNiconic, new->emacs_frame.iconic, 0);
  858.     }
  859.  
  860.   return needs_a_refresh;
  861. }
  862.  
  863. static XtGeometryResult
  864. EmacsFrameQueryGeometry (widget, request, result)
  865.      Widget widget;
  866.      XtWidgetGeometry* request;
  867.      XtWidgetGeometry* result;
  868. {
  869.   EmacsFrame ew = (EmacsFrame)widget;
  870.  
  871.   int mask = request->request_mode;
  872.   Dimension ok_width, ok_height;
  873.  
  874.   if (mask & (CWWidth | CWHeight))
  875.     {
  876.       round_size_to_char (ew,
  877.               (mask & CWWidth) ? request->width : ew->core.width,
  878.               ((mask & CWHeight) ? request->height
  879.                : ew->core.height),
  880.               &ok_width, &ok_height);
  881.       if ((mask & CWWidth) && (ok_width != request->width))
  882.     {
  883.       result->request_mode |= CWWidth;
  884.       result->width = ok_width;
  885.     }
  886.       if ((mask & CWHeight) && (ok_height != request->height))
  887.     {
  888.       result->request_mode |= CWHeight;
  889.       result->height = ok_height;
  890.     }
  891.     }
  892.   return result->request_mode ? XtGeometryAlmost : XtGeometryYes;
  893. }
  894.  
  895. /* Special entrypoints */
  896. void
  897. EmacsFrameSetCharSize (widget, columns, rows)
  898.      Widget widget;
  899.      int columns;
  900.      int rows;
  901. {
  902.   EmacsFrame ew = (EmacsFrame) widget;
  903.   Dimension pixel_width, pixel_height, granted_width, granted_height;
  904.   XtGeometryResult result;
  905.   struct frame *f = ew->emacs_frame.frame;
  906.   Arg al[2];
  907.   int ac = 0;
  908.   
  909.   if (columns < 3) columns = 3;  /* no way buddy */
  910.  
  911.   check_frame_size (f, &rows, &columns);
  912.   f->output_data.x->vertical_scroll_bar_extra
  913.     = (!FRAME_HAS_VERTICAL_SCROLL_BARS (f)
  914.        ? 0
  915.        : FRAME_SCROLL_BAR_PIXEL_WIDTH (f) > 0
  916.        ? FRAME_SCROLL_BAR_PIXEL_WIDTH (f)
  917.        : (FRAME_SCROLL_BAR_COLS (f) * FONT_WIDTH (f->output_data.x->font)));
  918.  
  919.   char_to_pixel_size (ew, columns, rows, &pixel_width, &pixel_height);
  920.  
  921.   /* Manually change the height and width of all our widgets,
  922.      adjusting each widget by the same increments.  */
  923.   if (ew->core.width != pixel_width || ew->core.height != pixel_height)
  924.     {
  925.       int hdelta = pixel_height - ew->core.height;
  926.       int wdelta = pixel_width - ew->core.width;
  927.       int column_widget_height = f->output_data.x->column_widget->core.height;
  928.       int column_widget_width = f->output_data.x->column_widget->core.width;
  929.       int outer_widget_height = f->output_data.x->widget->core.height;
  930.       int outer_widget_width = f->output_data.x->widget->core.width;
  931.       int old_left = f->output_data.x->widget->core.x;
  932.       int old_top = f->output_data.x->widget->core.y;
  933.  
  934.       lw_refigure_widget (f->output_data.x->column_widget, False);
  935.       update_hints_inhibit = 1;
  936.  
  937.       ac = 0;
  938.       XtSetArg (al[ac], XtNheight, pixel_height); ac++;
  939.       XtSetArg (al[ac], XtNwidth, pixel_width); ac++;
  940.       XtSetValues ((Widget) ew, al, ac);
  941.  
  942.       ac = 0;
  943.       XtSetArg (al[ac], XtNheight, column_widget_height + hdelta); ac++;
  944.       XtSetArg (al[ac], XtNwidth, column_widget_width + wdelta); ac++;
  945.       XtSetValues (f->output_data.x->column_widget, al, ac);
  946.  
  947.       ac = 0;
  948.       XtSetArg (al[ac], XtNheight, outer_widget_height + hdelta); ac++;
  949.       XtSetArg (al[ac], XtNwidth, outer_widget_width + wdelta); ac++;
  950.       XtSetValues (f->output_data.x->widget, al, ac);
  951.  
  952.       lw_refigure_widget (f->output_data.x->column_widget, True);
  953.  
  954.       update_hints_inhibit = 0;
  955.       update_wm_hints (ew);
  956.  
  957.       do_pending_window_change ();
  958.  
  959.       /* These seem to get clobbered.  I don't know why. - rms.  */
  960.       f->output_data.x->widget->core.x = old_left;
  961.       f->output_data.x->widget->core.y = old_top;
  962.     }
  963.  
  964.   /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
  965.      receive in the ConfigureNotify event; if we get what we asked
  966.      for, then the event won't cause the screen to become garbaged, so
  967.      we have to make sure to do it here.  */
  968.   SET_FRAME_GARBAGED (f);
  969. }
  970.  
  971. void
  972. widget_store_internal_border (widget)
  973.      Widget widget;
  974. {
  975.   EmacsFrame ew = (EmacsFrame) widget;
  976.   FRAME_PTR f = ew->emacs_frame.frame;
  977.  
  978.   ew->emacs_frame.internal_border_width
  979.     = f->output_data.x->internal_border_width;
  980. }
  981.