home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / gnu / lucid / lemacs-19.6 / src / EmacsShell.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-12-10  |  14.4 KB  |  502 lines

  1.  
  2. #include <stdio.h>
  3. #include <string.h>
  4. #include <X11/StringDefs.h>
  5. #include <X11/IntrinsicP.h>
  6. #include <X11/Shell.h>
  7. #include <X11/ShellP.h>
  8. #include <X11/Vendor.h>
  9. #include <X11/VendorP.h>
  10. #include "EmacsShellP.h"
  11.  
  12. #ifndef XtCXtToolkitError
  13. #define XtCXtToolkitError "XtToolkitError"
  14. #endif
  15.  
  16. static void emacsShellInitialize ();
  17. static void emacsShellRealize ();
  18. static void EvaluateWMHints ();
  19. static void ComputeWMSizeHints();
  20. static void ComputeWMSizeHints ();
  21. static void Destroy (Widget w);
  22. #define BIGSIZE ((Dimension)32767)  /* from Shell.c */
  23.  
  24. static XtResource resources[] = {
  25. #define offset(field) XtOffset(EmacsShellWidget, emacsShell.field)
  26.   {XtNwindow, XtCWindow, XtRString, sizeof (char*),
  27.      offset (external_window), XtRImmediate, (XtPointer)0},
  28. };
  29.  
  30. EmacsShellClassRec emacsShellClassRec = {
  31.     { /*
  32.        *    core_class fields
  33.        */
  34.     /* superclass      */    (WidgetClass) &applicationShellClassRec,
  35.     /* class_name      */    "EmacsShell",
  36.     /* size          */    sizeof(EmacsShellRec),
  37.     /* Class Initializer  */    NULL,
  38.     /* class_part_initialize*/    NULL, /* XtInheritClassPartInitialize, */
  39.     /* Class init'ed ?      */    FALSE,
  40.     /* initialize      */    emacsShellInitialize,
  41.     /* initialize_notify  */    NULL,
  42.     /* realize          */    emacsShellRealize,
  43.     /* actions          */    NULL,
  44.     /* num_actions      */    0,
  45.     /* resources      */    resources,
  46.     /* resource_count      */    XtNumber (resources),
  47.     /* xrm_class      */    NULLQUARK,
  48.     /* compress_motion      */    FALSE,
  49.     /* compress_exposure  */    TRUE,
  50.     /* compress_enterleave*/    FALSE,
  51.     /* visible_interest      */    TRUE,
  52.     /* destroy          */    Destroy, /* XtInheritDestroy, */
  53.     /* resize          */    XtInheritResize,
  54.     /* expose          */    NULL,
  55.     /* set_values      */    NULL, /* XtInheritSetValues, */
  56.     /* set_values_hook      */    NULL,            
  57.     /* set_values_almost  */    XtInheritSetValuesAlmost,  
  58.     /* get_values_hook      */    NULL,            
  59.     /* accept_focus      */    NULL,
  60.     /* intrinsics version */    XtVersion,
  61.     /* callback offsets      */    NULL,
  62.     /* tm_table          */    NULL,
  63.     /* query_geometry      */    NULL,
  64.     /* display_accelerator*/    NULL,
  65.     /* extension      */    NULL
  66.   },{ /* Composite */
  67.     /* geometry_manager      */    XtInheritGeometryManager,
  68.     /* change_managed      */    XtInheritChangeManaged,
  69.     /* insert_child      */    XtInheritInsertChild,
  70.     /* delete_child      */    XtInheritDeleteChild,
  71.     /* extension      */    NULL
  72.   },{ /* Shell */
  73.     /* extension      */    NULL /* (XtPointer)&shellClassExtRec */
  74.   }
  75. };
  76.  
  77. WidgetClass emacsShellWidgetClass = (WidgetClass) &emacsShellClassRec;
  78.  
  79. static void emacsShellInitialize (req, new, args, num_args)
  80.      Widget req, new;
  81.      ArgList args;
  82.      Cardinal *num_args;
  83. {
  84. /*
  85.   XtAddEventHandler(new, NULL,
  86.             TRUE, emacs_Xt_event_handler, (XtPointer) NULL);
  87.  */
  88. }
  89.  
  90. /* Lifted without alteration from Shell.c
  91.  */
  92. static void EvaluateSizeHints(w)
  93.     WMShellWidget w;
  94. {
  95.     struct _OldXSizeHints *sizep = &w->wm.size_hints;
  96.  
  97.     sizep->x = w->core.x;
  98.     sizep->y = w->core.y;
  99.     sizep->width = w->core.width;
  100.     sizep->height = w->core.height;
  101.  
  102.     if (sizep->flags & USSize) {
  103.         if (sizep->flags & PSize) sizep->flags &= ~PSize;
  104.     } else
  105.         sizep->flags |= PSize;
  106.  
  107.     if (sizep->flags & USPosition) {
  108.         if (sizep->flags & PPosition) sizep->flags &= ~PPosition;
  109.     } else if (w->shell.client_specified & _XtShellPPositionOK)
  110.         sizep->flags |= PPosition;
  111.  
  112.     if (sizep->min_aspect.x != XtUnspecifiedShellInt
  113.         || sizep->min_aspect.y != XtUnspecifiedShellInt
  114.         || sizep->max_aspect.x != XtUnspecifiedShellInt
  115.         || sizep->max_aspect.y != XtUnspecifiedShellInt) {
  116.         sizep->flags |= PAspect;
  117.     }
  118.     if(w->wm.base_width != XtUnspecifiedShellInt
  119.        || w->wm.base_height != XtUnspecifiedShellInt) {
  120.         sizep->flags |= PBaseSize;
  121.         if (w->wm.base_width == XtUnspecifiedShellInt)
  122.         w->wm.base_width = 0;
  123.         if (w->wm.base_height == XtUnspecifiedShellInt)
  124.         w->wm.base_height = 0;
  125.     }
  126.     if (sizep->width_inc != XtUnspecifiedShellInt
  127.         || sizep->height_inc != XtUnspecifiedShellInt) {
  128.         if (sizep->width_inc < 1) sizep->width_inc = 1;
  129.         if (sizep->height_inc < 1) sizep->height_inc = 1;
  130.         sizep->flags |= PResizeInc;
  131.     }
  132.     if (sizep->max_width != XtUnspecifiedShellInt
  133.         || sizep->max_height != XtUnspecifiedShellInt) {
  134.         sizep->flags |= PMaxSize;
  135.         if (sizep->max_width == XtUnspecifiedShellInt)
  136.         sizep->max_width = BIGSIZE;
  137.         if (sizep->max_height == XtUnspecifiedShellInt)
  138.         sizep->max_height = BIGSIZE;
  139.     }
  140.     if(sizep->min_width != XtUnspecifiedShellInt
  141.        || sizep->min_height != XtUnspecifiedShellInt) {
  142.         sizep->flags |= PMinSize;
  143.         if (sizep->min_width == XtUnspecifiedShellInt)
  144.         sizep->min_width = 1;
  145.         if (sizep->min_height == XtUnspecifiedShellInt)
  146.         sizep->min_height = 1;
  147.     }
  148. }
  149.  
  150.  
  151. /* Lifted without alteration from Shell.c
  152.  */
  153. static void GetGeometry(W, child)
  154.     Widget W, child;
  155. {
  156.     register ShellWidget w = (ShellWidget)W;
  157.     Boolean is_wmshell = XtIsWMShell(W);
  158.     int x, y, width, height, win_gravity = -1, flag;
  159.     XSizeHints hints;
  160.  
  161.     if (child != NULL) {
  162.     /* we default to our child's size */
  163.     if (is_wmshell && (w->core.width == 0 || w->core.height == 0))
  164.         ((WMShellWidget)W)->wm.size_hints.flags |= PSize;
  165.     if (w->core.width == 0)        w->core.width = child->core.width;
  166.     if (w->core.height == 0)    w->core.height = child->core.height;
  167.     }
  168.     if(w->shell.geometry != NULL) {
  169.     char def_geom[64];
  170.     x = w->core.x;
  171.     y = w->core.y;
  172.     width = w->core.width;
  173.     height = w->core.height;
  174.     if (is_wmshell) {
  175.         WMShellPart* wm = &((WMShellWidget)w)->wm;
  176.         EvaluateSizeHints((WMShellWidget)w);
  177.         memcpy((char*)&hints, (char*)&wm->size_hints,
  178.            sizeof(struct _OldXSizeHints));
  179.         hints.win_gravity = wm->win_gravity;
  180.         if (wm->size_hints.flags & PBaseSize) {
  181.         width -= wm->base_width;
  182.         height -= wm->base_height;
  183.         hints.base_width = wm->base_width;
  184.         hints.base_height = wm->base_height;
  185.         }
  186.         else if (wm->size_hints.flags & PMinSize) {
  187.         width -= wm->size_hints.min_width;
  188.         height -= wm->size_hints.min_height;
  189.         }
  190.         if (wm->size_hints.flags & PResizeInc) {
  191.         width /= wm->size_hints.width_inc;
  192.         height /= wm->size_hints.height_inc;
  193.         }
  194.     }
  195.     else hints.flags = 0;
  196.  
  197.     sprintf( def_geom, "%dx%d+%d+%d", width, height, x, y );
  198.     flag = XWMGeometry( XtDisplay(W),
  199.                 XScreenNumberOfScreen(XtScreen(W)),
  200.                 w->shell.geometry, def_geom,
  201.                 (unsigned int)w->core.border_width,
  202.                 &hints, &x, &y, &width, &height,
  203.                 &win_gravity
  204.                );
  205.     if (flag) {
  206.         if (flag & XValue) w->core.x = (Position)x;
  207.         if (flag & YValue) w->core.y = (Position)y;
  208.         if (flag & WidthValue) w->core.width = (Dimension)width;
  209.         if (flag & HeightValue) w->core.height = (Dimension)height;
  210.     }
  211.     else {
  212.         String params[2];
  213.         Cardinal num_params = 2;
  214.         params[0] = XtName(W);
  215.         params[1] = w->shell.geometry;
  216.         XtAppWarningMsg(XtWidgetToApplicationContext(W),
  217.        "badGeometry", "shellRealize", XtCXtToolkitError,
  218.        "Shell widget \"%s\" has an invalid geometry specification: \"%s\"",
  219.                 params, &num_params);
  220.     }
  221.     }
  222.     else
  223.     flag = 0;
  224.  
  225.     if (is_wmshell) {
  226.     WMShellWidget wmshell = (WMShellWidget) w;
  227.     if (wmshell->wm.win_gravity == XtUnspecifiedShellInt) {
  228.         if (win_gravity != -1)
  229.         wmshell->wm.win_gravity = win_gravity;
  230.         else
  231.         wmshell->wm.win_gravity = NorthWestGravity;
  232.     }
  233.     wmshell->wm.size_hints.flags |= PWinGravity;
  234.     if ((flag & (XValue|YValue)) == (XValue|YValue))
  235.         wmshell->wm.size_hints.flags |= USPosition;
  236.     if ((flag & (WidthValue|HeightValue)) == (WidthValue|HeightValue))
  237.         wmshell->wm.size_hints.flags |= USSize;
  238.     }
  239.     w->shell.client_specified |= _XtShellGeometryParsed;
  240. }
  241.  
  242.  
  243. /* Lifted almost entirely from Realize() in Shell.c
  244.  */
  245. static void _popup_set_prop();
  246. static void emacsShellRealize (wid, vmask, attr)
  247.     Widget wid;
  248.     Mask *vmask;
  249.     XSetWindowAttributes *attr;
  250. {
  251.     EmacsShellWidget w = (EmacsShellWidget) wid;
  252.         Mask mask = *vmask;
  253.  
  254.     if (! (w->shell.client_specified & _XtShellGeometryParsed)) {
  255.         /* we'll get here only if there was no child the first
  256.            time we were realized.  If the shell was Unrealized
  257.            and then re-Realized, we probably don't want to
  258.            re-evaluate the defaults anyway.
  259.          */
  260.         GetGeometry(wid, (Widget)NULL);
  261.     }
  262.     else if (w->core.background_pixmap == XtUnspecifiedPixmap) {
  263.         /* I attempt to inherit my child's background to avoid screen flash
  264.          * if there is latency between when I get resized and when my child
  265.          * is resized.  Background=None is not satisfactory, as I want the
  266.          * user to get immediate feedback on the new dimensions (most
  267.          * particularly in the case of a non-reparenting wm).  It is
  268.          * especially important to have the server clear any old cruft
  269.          * from the display when I am resized larger.
  270.          */
  271.         register Widget *childP = w->composite.children;
  272.         int i;
  273.         for (i = w->composite.num_children; i; i--, childP++) {
  274.         if (XtIsWidget(*childP) && XtIsManaged(*childP)) {
  275.             if ((*childP)->core.background_pixmap
  276.                 != XtUnspecifiedPixmap) {
  277.             mask &= ~(CWBackPixel);
  278.             mask |= CWBackPixmap;
  279.             attr->background_pixmap =
  280.                 w->core.background_pixmap =
  281.                 (*childP)->core.background_pixmap;
  282.             } else {
  283.             attr->background_pixel = 
  284.                 w->core.background_pixel = 
  285.                 (*childP)->core.background_pixel;
  286.             }
  287.             break;
  288.         }
  289.         }
  290.     }
  291.  
  292.     if(w->shell.save_under) {
  293.         mask |= CWSaveUnder;
  294.         attr->save_under = TRUE;
  295.     }
  296.     if(w->shell.override_redirect) {
  297.         mask |= CWOverrideRedirect;
  298.         attr->override_redirect = TRUE;
  299.     }
  300.     if (wid->core.width == 0 || wid->core.height == 0) {
  301.         Cardinal count = 1;
  302.         XtErrorMsg("invalidDimension", "shellRealize", XtCXtToolkitError,
  303.                "Shell widget %s has zero width and/or height",
  304.                &wid->core.name, &count);
  305.     }
  306.  
  307.     if (w->emacsShell.external_window != 0) {
  308.        wid->core.window = w->emacsShell.external_window;
  309.        XChangeWindowAttributes(XtDisplay(wid), wid->core.window,
  310.                    mask, attr);
  311.        } else {
  312.       wid->core.window = XCreateWindow(XtDisplay(wid),
  313.             wid->core.screen->root, (int)wid->core.x, (int)wid->core.y,
  314.         (unsigned int)wid->core.width, (unsigned int)wid->core.height,
  315.         (unsigned int)wid->core.border_width, (int) wid->core.depth,
  316.         (unsigned int) InputOutput, w->shell.visual,
  317.         mask, attr);
  318.        }
  319.     _popup_set_prop(w);
  320. }
  321.  
  322.  
  323. /* Lifted without alteration from Shell.c
  324.  */
  325. static void EvaluateWMHints(w)
  326.     WMShellWidget w;
  327. {
  328.     XWMHints *hintp = &w->wm.wm_hints;
  329.  
  330.     hintp->flags = StateHint | InputHint;
  331.  
  332.     if (XtIsTopLevelShell((Widget)w)
  333.         && ((TopLevelShellWidget)w)->topLevel.iconic) {
  334.         hintp->initial_state = IconicState;
  335.     }
  336.     if (hintp->icon_x == XtUnspecifiedShellInt)
  337.         hintp->icon_x = -1;
  338.     else
  339.         hintp->flags |= IconPositionHint;
  340.  
  341.     if (hintp->icon_y == XtUnspecifiedShellInt)
  342.         hintp->icon_y = -1;
  343.     else
  344.         hintp->flags |= IconPositionHint;
  345.  
  346.     if (hintp->icon_pixmap) hintp->flags |= IconPixmapHint;
  347.     if (hintp->icon_mask)   hintp->flags |= IconMaskHint;
  348.     if (hintp->icon_window) hintp->flags |= IconWindowHint;
  349.  
  350.     if (hintp->window_group == XtUnspecifiedWindow) {
  351.         if(w->core.parent) {
  352.         Widget p;
  353.         for (p = w->core.parent; p->core.parent; p = p->core.parent);
  354.         if (XtIsRealized(p)) {
  355.             hintp->window_group = XtWindow(p);
  356.             hintp->flags |=  WindowGroupHint;
  357.         }
  358.         }
  359.     } else if (hintp->window_group != XtUnspecifiedWindowGroup)
  360.         hintp->flags |=  WindowGroupHint;
  361. }
  362.  
  363.  
  364. extern void _XtAllocError (char *);
  365.  
  366. /* Lifted without alteration from Shell.c
  367.  */
  368. static void _popup_set_prop(w)
  369.     ShellWidget w;
  370. {
  371.     Widget p;
  372.     WMShellWidget wmshell = (WMShellWidget) w;
  373.     TopLevelShellWidget tlshell = (TopLevelShellWidget) w;
  374.     ApplicationShellWidget appshell = (ApplicationShellWidget) w;
  375.     XTextProperty icon_name;
  376.     XTextProperty window_name;
  377.     char **argv;
  378.     int argc;
  379.     XSizeHints *size_hints;
  380.     Window window_group;
  381.     XClassHint classhint;
  382.  
  383.     if (!XtIsWMShell((Widget)w) || w->shell.override_redirect) return;
  384.  
  385.     if ((size_hints = XAllocSizeHints()) == NULL)
  386.         _XtAllocError("XAllocSizeHints");
  387.  
  388.     window_name.value = (unsigned char*)wmshell->wm.title;
  389.     window_name.encoding = wmshell->wm.title_encoding;
  390.     window_name.format = 8;
  391.     window_name.nitems = strlen((char *) window_name.value) + 1;
  392.  
  393.     if (XtIsTopLevelShell((Widget)w)) {
  394.         icon_name.value = (unsigned char*)tlshell->topLevel.icon_name;
  395.         icon_name.encoding = tlshell->topLevel.icon_name_encoding;
  396.         icon_name.format = 8;
  397.         icon_name.nitems = strlen((char *) icon_name.value) + 1;
  398.     }
  399.  
  400.     EvaluateWMHints(wmshell);
  401.     EvaluateSizeHints(wmshell);
  402.     ComputeWMSizeHints(wmshell, size_hints);
  403.  
  404.     if (wmshell->wm.transient
  405.         && !XtIsTransientShell((Widget)w)
  406.         && (window_group = wmshell->wm.wm_hints.window_group)
  407.            != XtUnspecifiedWindowGroup) {
  408.  
  409.         XSetTransientForHint(XtDisplay((Widget)w),
  410.                  XtWindow((Widget)w),
  411.                  window_group
  412.                  );
  413.     }
  414.  
  415.     classhint.res_name = w->core.name;
  416.     /* For the class, look up to the top of the tree */
  417.     for (p = (Widget)w; p->core.parent != NULL; p = p->core.parent);
  418.     if (XtIsApplicationShell(p)) {
  419.         classhint.res_class =
  420.         ((ApplicationShellWidget)p)->application.class;
  421.     } else classhint.res_class = XtClass(p)->core_class.class_name;
  422.  
  423.     if (XtIsApplicationShell((Widget)w)
  424.         && (argc = appshell->application.argc) != -1)
  425.         argv = (char**)appshell->application.argv;
  426.     else {
  427.         argv = NULL;
  428.         argc = 0;
  429.     }
  430.  
  431.     XSetWMProperties(XtDisplay((Widget)w), XtWindow((Widget)w),
  432.              &window_name,
  433.              (XtIsTopLevelShell((Widget)w)) ? &icon_name : NULL,
  434.              argv, argc,
  435.              size_hints,
  436.              &wmshell->wm.wm_hints,
  437.              &classhint);
  438.     XFree((char*)size_hints);
  439. }
  440.  
  441. /* Lifted without alteration from Shell.c
  442.  */
  443. static void ComputeWMSizeHints(w, hints)
  444.     WMShellWidget w;
  445.     XSizeHints *hints;
  446. {
  447.     register long flags;
  448.     hints->flags = flags = w->wm.size_hints.flags;
  449. #define copy(field) hints->field = w->wm.size_hints.field
  450.     if (flags & (USPosition | PPosition)) {
  451.     copy(x);
  452.     copy(y);
  453.     }
  454.     if (flags & (USSize | PSize)) {
  455.     copy(width);
  456.     copy(height);
  457.     }
  458.     if (flags & PMinSize) {
  459.     copy(min_width);
  460.     copy(min_height);
  461.     }
  462.     if (flags & PMaxSize) {
  463.     copy(max_width);
  464.     copy(max_height);
  465.     }
  466.     if (flags & PResizeInc) {
  467.     copy(width_inc);
  468.     copy(height_inc);
  469.     }
  470.     if (flags & PAspect) {
  471.     copy(min_aspect.x);
  472.     copy(min_aspect.y);
  473.     copy(max_aspect.x);
  474.     copy(max_aspect.y);
  475.     }
  476. #undef copy
  477. #define copy(field) hints->field = w->wm.field
  478.     if (flags & PBaseSize) {
  479.     copy(base_width);
  480.     copy(base_height);
  481.     }
  482.     if (flags & PWinGravity)
  483.     copy(win_gravity);
  484. #undef copy
  485. }
  486.  
  487. extern void _XtUnregisterWindow (Window, Widget);
  488.  
  489. static void Destroy(wid)
  490.     Widget wid;
  491. {
  492.   EmacsShellWidget w = (EmacsShellWidget)wid;
  493.  
  494.   if (XtIsRealized((Widget) w) &&
  495.       w->core.window == w->emacsShell.external_window)
  496.     {
  497.       _XtUnregisterWindow(w->core.window, wid);
  498.       wid->core.window = 0;
  499.     }
  500. }
  501.  
  502.