From: tomo Date: Thu, 11 Nov 1999 11:46:22 +0000 (+0000) Subject: Sync with r21-2-20. X-Git-Url: http://git.chise.org/gitweb/?a=commitdiff_plain;h=refs%2Fheads%2Ftomo;p=chise%2Fxemacs-chise.git- Sync with r21-2-20. --- diff --git a/lwlib/ChangeLog b/lwlib/ChangeLog index 9761ceb..807f075 100644 --- a/lwlib/ChangeLog +++ b/lwlib/ChangeLog @@ -1,3 +1,217 @@ +1999-11-10 XEmacs Build Bot + + * XEmacs 21.2.20 is released + +1999-09-09 Andy Piper + + * xlwtabs.c: updated tabs widget from Ed Falk. + * xlwtabs.h: ditto. + * xlwtabsP.h: ditto. + +1999-09-22 Martin Buchholz + + * lwlib-internal.h: + * lwlib-utils.h: + Move declaration of destroy_all_children from lwlib-internal.h to + lwlib-utils.h, where it belongs. + +1999-09-21 Andy Piper + + * lwlib-Xm.c (xm_update_label): don't clobber pixmap type labels + with text. + +1999-09-22 Martin Buchholz + + * xlwtabs.c: Fix C++ compilability. + +1999-09-18 Andy Piper + + * xlwtabs.c: Put in tabs sync because clipping should fix useability + problems. + +1999-09-13 Andy Piper + + * xlwtabs.c: Back out tabs sync because of reported useability + problems. + +1999-09-09 Andy Piper + + * xlwtabs.c: updated tabs widget from Ed Falk. + * xlwtabs.h: ditto. + * xlwtabsP.h: ditto. + * xlwgcs.c: ditto. + * xlwgcs.h: ditto. + +1999-09-03 Martin Buchholz + + * xlwgauge.c: Ansify. + Include to get prototype for atoi(). + (GaugeSelect): Call GaugeExpose with the right number of args. + (GaugeLoseSel): Call GaugeExpose with the right number of args. + (GaugeConvert): This is a XtConvertSelectionProc, + so 5th parameter must be of type XtPointer, not XPointer. + (GaugeGetValue): This is a XtTimerCallbackProc, + so 2nd parameter must be of type XtIntervalId *, not XtIntervalId. + + +1999-09-01 Martin Buchholz + + * lwlib.c (free_widget_value_contents): Use proper type for cast. + + * xlwradio.c: Use function prototypes everywhere. + * xlwcheckbox.c: + * xlwradio.c: + * xlwradioP.h: Move declarations of non-static functions defined + in xlwradio.c into xlwradioP.h. + +1999-09-02 Andy Piper + + * xlwgcs.c: include xmu.h + +1999-09-01 Andy Piper + + * xlwgauge.c: rearrange headers yet again. + * xlwcheckbox.c: ditto. + * xlwradio.c: ditto. + * xlwtabs.c: ditto. + +1999-09-01 Andy Piper + + * xlwgauge.c: use xmu.h + * xlwcheckbox.c: ditto. + * xlwradio.c: ditto. + +1999-08-31 Andy Piper + + * xlwtabs.c: + * xlwgcs.c: + * xlwradio.c: + * xlwcheckbox.c: + * xlwgauge.c: Fix for losing systems without Xmu. + +1999-08-31 Andy Piper + + * lwlib-Xm.c (xm_update_one_widget): fix for AIX compiler lossage. + +1999-08-30 Andy Piper + + * lwlib.c (free_widget_value_contents): be more precise about + freeing user defined args. + + * lwlib-Xaw.c (xaw_update_one_widget): make sure we use val not + its contents for hierarchies one deep. + +1999-08-29 Andy Piper + + * xlwtabs.c: temporary fixes pending a new release. + * xlwtabsP.h: ditto. + + * lwlib-Xm.c (xm_update_one_widget): update user defined args. + (xm_create_label): set args after creation as well as before. + + * lwlib-Xlw.c (xlw_create_tab_control): orient tabs horizontally. + (xlw_update_tab_control): actually update the children rather than + the parent. + + * lwlib-Xaw.c (xaw_update_one_widget): update user defined args. + (xaw_create_label): set args after creation as well as before. + +1999-08-23 Andy Piper + + * lwlib-Xm.c (xm_update_label): don't concatenate value to itself. + + * lwlib-Xm.c (xm_create_label_field): new function for creating labels. + (xm_creation_table): use it. + + * lwlib-Xaw.c (xaw_create_label_field): new function for creating labels. + (xaw_creation_table): use it. + +1999-08-16 Andy Piper + + * lwlib.h: declare free_widget_value_tree. + + * lwlib.c (free_widget_value_tree): make non-static. + + * lwlib-Xm.c (xm_update_label): free val_string when updating. + +1999-08-04 Andy Piper + + * lwlib-Xm.c (mark_dead_instance_destroyed): change so that its + defined for widgets. + (xm_nosel_callback): ditto. + + * xlwtabsP.h: sync with 1.5. + + * xlwtabs.c: sync with 1.18. + +1999-07-28 Andy Piper + + * xlwtabs.c: new lucid tabs widget from Ed Falk. + * xlwtabs.h: ditto. + * xlwtabsP.h: ditto. + * xlwgcs.c: GC manipulation for tab widgets. + * xlwgcs.h: ditto. + + * xlwgauge.c: new athena gauge widget from Ed Falk. + * xlwgauge.h: ditto. + * xlwgaugeP.h: ditto. + + * xlwradio.c: new athena radio widget from Ed Falk. + * xlwradio.h: ditto. + * xlwradioP.h: ditto. + + * xlwcheckbox.c: new athena checkbox widget from Ed Falk. + * xlwcheckbox.h: ditto. + * xlwcheckboxP.h: ditto. + + * lwlib-utils.c (destroy_all_children): moved from lwlib-Xm.c. + + * lwlib-internal.h: declare destroy_all_children. + + * lwlib-config.c: add widget checks. + + * lwlib-Xm.h: declare xm_create_label; + + * lwlib-Xm.c (destroy_all_children): move to lwlib-utils.c. + (xm_update_label): enable for widgets. + (xm_update_one_widget): ditto. + (xm_create_button): rename in line with lwlib-Xaw.c + (xm_create_progress): ditto. + (xm_create_text_field): ditto. + (xm_create_combo_box): ditto. + (xm_create_label): new function. + (xm_creation_table): rename widget creation functions. + (xm_destroy_instance): enable for widgets. + (xm_generic_callback): ditto. + (xm_generic_callback): ditto. + + * lwlib-Xlw.c (xlw_tab_control_callback): new function. a special + callback that calls the correct function depending on what tab is + selected. + (xlw_create_tab_control): new function. + (build_tabs_in_widget): new function. puts tabs in a tab widget, + uses Xaw or Xm depending on how XEmacs was compiled. + (xlw_update_tab_control): update the resources for each + tab. optionally rebuild the contents of the tab widget. + (xlw_creation_table): add tab widget creation function. + (lw_lucid_widget_p): add tab widget. + (xlw_update_one_widget): ditto. + + * lwlib-Xaw.h: declare xaw_create_label; + + * lwlib-Xaw.c (lw_xaw_widget_p): add widgets classes. + (xaw_update_one_widget): ditto. + (xaw_update_one_value): add code from the Xm version. + (xaw_generic_callback): add Xm hack for setting command + states. beef up lookup of call data. + (xaw_create_button): new function. + (xaw_create_label): new function for use by tab widget. + (xaw_create_progress): new function. + (xaw_create_text_field): new function. + (xaw_creation_table): add new widget type creation functions. + + * Makefile.in.in: add dependencies for new lw widgets. + 1999-07-30 XEmacs Build Bot * XEmacs 21.2.19 is released diff --git a/lwlib/Makefile.in.in b/lwlib/Makefile.in.in index 70be7f3..bd01fc8 100644 --- a/lwlib/Makefile.in.in +++ b/lwlib/Makefile.in.in @@ -95,11 +95,18 @@ CONFIG_H = ../src/config.h config.h ## Following correct as of 19980312 -lwlib-Xaw.o: $(CONFIG_H) lwlib-Xaw.h lwlib-internal.h lwlib.h xlwmenu.h -lwlib-Xlw.o: $(CONFIG_H) lwlib-Xlw.h lwlib-internal.h lwlib.h xlwmenu.h xlwscrollbar.h +lwlib-Xaw.o: $(CONFIG_H) lwlib-Xaw.h lwlib-internal.h lwlib.h xlwmenu.h xlwradio.h \ +xlwgauge.h xlwcheckbox.h +lwlib-Xlw.o: $(CONFIG_H) lwlib-Xlw.h lwlib-internal.h lwlib.h xlwmenu.h xlwscrollbar.h \ +xlwtabs.h xlwgcs.h lwlib-Xm.o: $(CONFIG_H) lwlib-Xm.h lwlib-internal.h lwlib-utils.h lwlib.h xlwmenu.h lwlib-config.o: $(CONFIG_H) lwlib.h xlwmenu.h lwlib-utils.o: $(CONFIG_H) lwlib-utils.h lwlib.o: $(CONFIG_H) lwlib-Xaw.h lwlib-Xlw.h lwlib-Xm.h lwlib-internal.h lwlib-utils.h lwlib.h xlwmenu.h xlwmenu.o: $(CONFIG_H) lwlib.h xlwmenu.h xlwmenuP.h xlwscrollbar.o: $(CONFIG_H) xlwscrollbar.h xlwscrollbarP.h +xlwtabs.o: $(CONFIG_H) xlwtabs.h xlwtabsP.h +xlwradio.o: $(CONFIG_H) xlwradio.h xlwradioP.h +xlwcheckbox.o: $(CONFIG_H) xlwcheckbox.h xlwcheckboxP.h +xlwgauge.o: $(CONFIG_H) xlwgauge.h xlwgaugeP.h +xlwgcs.o: $(CONFIG_H) xlwgcs.h diff --git a/lwlib/lwlib-Xaw.c b/lwlib/lwlib-Xaw.c index a0198bc..b19dd8c 100644 --- a/lwlib/lwlib-Xaw.c +++ b/lwlib/lwlib-Xaw.c @@ -41,7 +41,15 @@ Boston, MA 02111-1307, USA. */ #include #include #endif - +#ifdef LWLIB_WIDGETS_ATHENA +#include +#include "xlwradio.h" +#include "xlwcheckbox.h" +#include "xlwgauge.h" +#ifndef NEED_MOTIF +#include +#endif +#endif #include static void xaw_generic_callback (Widget, XtPointer, XtPointer); @@ -57,6 +65,14 @@ lw_xaw_widget_p (Widget widget) #ifdef LWLIB_DIALOGS_ATHENA || XtIsSubclass (widget, dialogWidgetClass) #endif +#ifdef LWLIB_WIDGETS_ATHENA + || XtIsSubclass (widget, labelWidgetClass) + || XtIsSubclass (widget, toggleWidgetClass) + || XtIsSubclass (widget, gaugeWidgetClass) +#if 0 + || XtIsSubclass (widget, textWidgetClass) +#endif +#endif ); } @@ -110,6 +126,9 @@ void xaw_update_one_widget (widget_instance *instance, Widget widget, widget_value *val, Boolean deep_p) { + if (val->nargs) + XtSetValues (widget, val->args, val->nargs); + if (0) ; #ifdef LWLIB_SCROLLBARS_ATHENA @@ -125,6 +144,16 @@ xaw_update_one_widget (widget_instance *instance, Widget widget, XtSetArg (al [0], XtNlabel, val->contents->value); XtSetValues (widget, al, 1); } +#endif /* LWLIB_DIALOGS_ATHENA */ +#ifdef LWLIB_WIDGETS_ATHENA + else if (XtClass (widget) == labelWidgetClass) + { + Arg al [1]; + XtSetArg (al [0], XtNlabel, val->value); + XtSetValues (widget, al, 1); + } +#endif /* LWLIB_WIDGETS_ATHENA */ +#if defined (LWLIB_DIALOGS_ATHENA) || defined (LWLIB_WIDGETS_ATHENA) else if (XtIsSubclass (widget, commandWidgetClass)) { Dimension bw = 0; @@ -154,6 +183,14 @@ xaw_update_one_widget (widget_instance *instance, Widget widget, XtRemoveAllCallbacks (widget, XtNcallback); XtAddCallback (widget, XtNcallback, xaw_generic_callback, instance); +#ifdef LWLIB_WIDGETS_ATHENA + /* set the selected state */ + if (XtIsSubclass (widget, toggleWidgetClass)) + { + XtSetArg (al [0], XtNstate, val->selected); + XtSetValues (widget, al, 1); + } +#endif /* LWLIB_WIDGETS_ATHENA */ } #endif /* LWLIB_DIALOGS_ATHENA */ } @@ -162,9 +199,36 @@ void xaw_update_one_value (widget_instance *instance, Widget widget, widget_value *val) { - /* This function is not used by the scrollbars and those are the only - Athena widget implemented at the moment so do nothing. */ - return; +#ifdef LWLIB_WIDGETS_ATHENA + widget_value *old_wv; + + /* copy the call_data slot into the "return" widget_value */ + for (old_wv = instance->info->val->contents; old_wv; old_wv = old_wv->next) + if (!strcmp (val->name, old_wv->name)) + { + val->call_data = old_wv->call_data; + break; + } + + if (XtIsSubclass (widget, toggleWidgetClass)) + { + Arg al [1]; + XtSetArg (al [0], XtNstate, &val->selected); + XtGetValues (widget, al, 1); + val->edited = True; + } +#ifndef NEED_MOTIF + else if (XtIsSubclass (widget, asciiTextWidgetClass)) + { + Arg al [1]; + if (val->value) + free (val->value); + XtSetArg (al [0], XtNstring, &val->value); + XtGetValues (widget, al, 1); + val->edited = True; + } +#endif +#endif /* LWLIB_WIDGETS_ATHENA */ } void @@ -440,7 +504,21 @@ xaw_generic_callback (Widget widget, XtPointer closure, XtPointer call_data) Widget instance_widget; LWLIB_ID id; XtPointer user_data; +#ifdef LWLIB_WIDGETS_ATHENA + /* We want the selected status to change only when we decide it + should change. Yuck but correct. */ + if (XtIsSubclass (widget, toggleWidgetClass)) + { + Boolean check; + Arg al [1]; + + XtSetArg (al [0], XtNstate, &check); + XtGetValues (widget, al, 1); + XtSetArg (al [0], XtNstate, !check); + XtSetValues (widget, al, 1); + } +#endif /* LWLIB_WIDGETS_ATHENA */ lw_internal_update_other_instances (widget, closure, call_data); if (! instance) @@ -464,17 +542,26 @@ xaw_generic_callback (Widget widget, XtPointer closure, XtPointer call_data) #else /* Damn! Athena doesn't give us a way to hang our own data on the buttons, so we have to go find it... I guess this assumes that - all instances of a button have the same call data. */ + all instances of a button have the same call data. + + ... Which is a totally bogus assumption --andyp */ { - widget_value *val = instance->info->val->contents; - char *name = XtName (widget); - while (val) + widget_value *val = instance->info->val; + /* If the widget is a buffer/gutter widget then we already have + the one we are looking for, so don't try and descend the widget + tree. */ + if (val->contents) { - if (val->name && !strcmp (val->name, name)) - break; - val = val->next; + char *name = XtName (widget); + val = val->contents; + while (val) + { + if (val->name && !strcmp (val->name, name)) + break; + val = val->next; + } + if (! val) abort (); } - if (! val) abort (); user_data = val->call_data; } #endif @@ -614,12 +701,163 @@ xaw_create_horizontal_scrollbar (widget_instance *instance) } #endif /* LWLIB_SCROLLBARS_ATHENA */ +#ifdef LWLIB_WIDGETS_ATHENA +/* glyph widgets */ +static Widget +xaw_create_button (widget_instance *instance) +{ + Arg al[20]; + int ac = 0; + Widget button = 0; + widget_value* val = instance->info->val; + + XtSetArg (al [ac], XtNsensitive, val->enabled); ac++; + XtSetArg (al [ac], XtNmappedWhenManaged, FALSE); ac++; + XtSetArg (al [ac], XtNjustify, XtJustifyCenter); ac++; + /* The highlight doesn't appear to be dynamically set which makes it + look ugly. I think this may be a LessTif bug but for now we just + get rid of it. */ + XtSetArg (al [ac], XtNhighlightThickness, (Dimension)0);ac++; + + /* add any args the user supplied for creation time */ + lw_add_value_args_to_args (val, al, &ac); + + if (!val->call_data) + button = XtCreateManagedWidget (val->name, labelWidgetClass, + instance->parent, al, ac); + + else + { + if (val->type == TOGGLE_TYPE || val->type == RADIO_TYPE) + { + XtSetArg (al [ac], XtNstate, val->selected); ac++; + button = XtCreateManagedWidget + (val->name, + val->type == TOGGLE_TYPE ? checkboxWidgetClass : radioWidgetClass, + instance->parent, al, ac); + } + else + { + button = XtCreateManagedWidget (val->name, commandWidgetClass, + instance->parent, al, ac); + } + XtRemoveAllCallbacks (button, XtNcallback); + XtAddCallback (button, XtNcallback, xaw_generic_callback, (XtPointer)instance); + } + + XtManageChild (button); + + return button; +} + +static Widget +xaw_create_label_field (widget_instance *instance) +{ + return xaw_create_label (instance->parent, instance->info->val); +} + +Widget +xaw_create_label (Widget parent, widget_value* val) +{ + Arg al[20]; + int ac = 0; + Widget label = 0; + + XtSetArg (al [ac], XtNsensitive, val->enabled); ac++; + XtSetArg (al [ac], XtNmappedWhenManaged, FALSE); ac++; + XtSetArg (al [ac], XtNjustify, XtJustifyCenter); ac++; + + /* add any args the user supplied for creation time */ + lw_add_value_args_to_args (val, al, &ac); + + label = XtCreateManagedWidget (val->name, labelWidgetClass, + parent, al, ac); + + /* Do it again for arguments that have no effect until the widget is realized. */ + ac = 0; + lw_add_value_args_to_args (val, al, &ac); + XtSetValues (label, al, ac); + + return label; +} + +static Widget +xaw_create_progress (widget_instance *instance) +{ + Arg al[20]; + int ac = 0; + Widget scale = 0; + widget_value* val = instance->info->val; + + if (!val->call_data) + { + XtSetArg (al [ac], XtNsensitive, False); ac++; + } + else + { + XtSetArg (al [ac], XtNsensitive, val->enabled); ac++; + } + XtSetArg (al [ac], XtNmappedWhenManaged, FALSE); ac++; + XtSetArg (al [ac], XtNorientation, XtorientHorizontal); ac++; + XtSetArg (al [ac], XtNhighlightThickness, (Dimension)0);ac++; + XtSetArg (al [ac], XtNntics, (Cardinal)10);ac++; + + /* add any args the user supplied for creation time */ + lw_add_value_args_to_args (val, al, &ac); + + scale = XtCreateManagedWidget (val->name, gaugeWidgetClass, + instance->parent, al, ac); + /* add the callback */ + if (val->call_data) + XtAddCallback (scale, XtNgetValue, xaw_generic_callback, (XtPointer)instance); + + XtManageChild (scale); + + return scale; +} + +#ifndef NEED_MOTIF +static Widget +xaw_create_text_field (widget_instance *instance) +{ + Arg al[20]; + int ac = 0; + Widget text = 0; + widget_value* val = instance->info->val; + + XtSetArg (al [ac], XtNsensitive, val->enabled && val->call_data); ac++; + XtSetArg (al [ac], XtNmappedWhenManaged, FALSE); ac++; + XtSetArg (al [ac], XtNhighlightThickness, (Dimension)0); ac++; + XtSetArg (al [ac], XtNtype, XawAsciiString); ac++; + XtSetArg (al [ac], XtNeditType, XawtextEdit); ac++; + + /* add any args the user supplied for creation time */ + lw_add_value_args_to_args (val, al, &ac); + + text = XtCreateManagedWidget (val->name, asciiTextWidgetClass, + instance->parent, al, ac); + XtManageChild (text); + + return text; +} +#endif +#endif /* LWLIB_WIDGETS_ATHENA */ + widget_creation_entry xaw_creation_table [] = { #ifdef LWLIB_SCROLLBARS_ATHENA - {"vertical-scrollbar", xaw_create_vertical_scrollbar}, - {"horizontal-scrollbar", xaw_create_horizontal_scrollbar}, + {"vertical-scrollbar", xaw_create_vertical_scrollbar }, + {"horizontal-scrollbar", xaw_create_horizontal_scrollbar }, +#endif +#ifdef LWLIB_WIDGETS_ATHENA + {"button", xaw_create_button }, + { "label", xaw_create_label_field }, +#ifndef NEED_MOTIF + {"text-field", xaw_create_text_field }, +#endif + {"progress", xaw_create_progress }, #endif {NULL, NULL} }; + diff --git a/lwlib/lwlib-Xaw.h b/lwlib/lwlib-Xaw.h index 70e72d4..67c71f9 100644 --- a/lwlib/lwlib-Xaw.h +++ b/lwlib/lwlib-Xaw.h @@ -8,6 +8,9 @@ extern widget_creation_entry xaw_creation_table []; Widget xaw_create_dialog (widget_instance* instance); +Widget +xaw_create_label (Widget parent, widget_value* val); + Boolean lw_xaw_widget_p (Widget widget); diff --git a/lwlib/lwlib-Xlw.c b/lwlib/lwlib-Xlw.c index 127403a..6c3cd34 100644 --- a/lwlib/lwlib-Xlw.c +++ b/lwlib/lwlib-Xlw.c @@ -20,20 +20,35 @@ Boston, MA 02111-1307, USA. */ #include #include /* for abort () */ +#include /* for abort () */ #include #include "lwlib-Xlw.h" +#include "lwlib-utils.h" #include #include #include #include #include +#ifdef HAVE_WIDGETS +#include "../src/EmacsManager.h" +#endif #ifdef LWLIB_MENUBARS_LUCID #include "xlwmenu.h" #endif #ifdef LWLIB_SCROLLBARS_LUCID #include "xlwscrollbar.h" #endif +#ifdef LWLIB_TABS_LUCID +#ifdef NEED_MOTIF +#include "lwlib-Xm.h" +#endif +#ifdef NEED_ATHENA +#include "lwlib-Xaw.h" +#endif +#include "../src/xmu.h" +#include "xlwtabs.h" +#endif @@ -301,6 +316,172 @@ xlw_update_scrollbar (widget_instance *instance, Widget widget, #endif /* LWLIB_SCROLLBARS_LUCID */ +#ifdef LWLIB_TABS_LUCID +/* tab control + + lwlib is such an incredible hairy crock. I just cannot believe + it! There are random dependencies between functions, there is a + total lack of genericity, even though it initially appears to be + generic. It should all be junked and begun again. Building tabs are + an example - in theory we should be able to reuse a lot of the + general stuff because we want to put labels of whatever toolkit we + are using in the tab. Instead we have to hack it by hand. */ +static void +xlw_tab_control_callback (Widget w, XtPointer client_data, XtPointer call_data) +{ + /* call data is the topmost widget */ + widget_instance* instance = (widget_instance*)client_data; + Widget top = (Widget)call_data; + char *name = XtName (top); + widget_value* widget_val; + XtPointer widget_arg; + LWLIB_ID id; + lw_callback post_activate_cb; + + if (w->core.being_destroyed) + return; + + /* Grab these values before running any functions, in case running + the selection_cb causes the widget to be destroyed. */ + id = instance->info->id; + post_activate_cb = instance->info->post_activate_cb; + + /* search for the widget_val for the selected tab */ + for (widget_val = instance->info->val->contents; widget_val; + widget_val = widget_val->next) + { + if (!strcmp (widget_val->name, name)) + break; + } + + widget_arg = widget_val ? widget_val->call_data : NULL; + + if (instance->info->selection_cb && + widget_val && + widget_val->enabled && + !widget_val->contents) + instance->info->selection_cb (w, id, widget_arg); + + if (post_activate_cb) + post_activate_cb (w, id, widget_arg); +} + +static Widget +xlw_create_tab_control (widget_instance *instance) +{ + Arg al[20]; + int ac = 0; + Widget tab = 0; + widget_value* val = instance->info->val; + + XtSetArg (al [ac], XtNsensitive, val->enabled); ac++; + XtSetArg (al [ac], XtNmappedWhenManaged, FALSE); ac++; + XtSetArg (al [ac], XtNorientation, XtorientHorizontal); ac++; + XtSetArg (al [ac], XtNresizable, False); ac++; + + /* add any args the user supplied for creation time */ + lw_add_value_args_to_args (val, al, &ac); + + tab = XtCreateManagedWidget (val->name, tabsWidgetClass, + instance->parent, al, ac); + XtRemoveAllCallbacks (tab, XtNcallback); + XtAddCallback (tab, XtNcallback, xlw_tab_control_callback, (XtPointer)instance); + + XtManageChild (tab); + + return tab; +} + +static void build_tabs_in_widget (widget_instance* instance, Widget widget, + widget_value* val) +{ + widget_value* cur = val; + for (cur = val; cur; cur = cur->next) + { + if (cur->value) + { +#ifdef LWLIB_WIDGETS_MOTIF + xm_create_label (widget, cur); +#else + xaw_create_label (widget, cur); +#endif + } + cur->change = NO_CHANGE; + } +} + +static void +xlw_update_tab_control (widget_instance* instance, Widget widget, widget_value* val) +{ + Widget* children; + unsigned int num_children; + int i; + widget_value *cur = 0; + + XtRemoveAllCallbacks (widget, XtNcallback); + XtAddCallback (widget, XtNcallback, xlw_tab_control_callback, (XtPointer)instance); + + if (val->change == STRUCTURAL_CHANGE + || + (val->contents && val->contents->change == STRUCTURAL_CHANGE)) + { + destroy_all_children (widget); + build_tabs_in_widget (instance, widget, val->contents); + } + + children = XtCompositeChildren (widget, &num_children); + if (children) + { + for (i = 0, cur = val->contents; i < num_children; i++) + { + if (!cur) + abort (); + if (children [i]->core.being_destroyed + || strcmp (XtName (children [i]), cur->name)) + continue; +#ifdef NEED_MOTIF + if (lw_motif_widget_p (children [i])) + xm_update_one_widget (instance, children [i], cur, False); +#endif +#ifdef NEED_ATHENA + if (lw_xaw_widget_p (children [i])) + xaw_update_one_widget (instance, children [i], cur, False); +#endif + cur = cur->next; + } + XtFree ((char *) children); + } + if (cur) + abort (); +} +#endif /* LWLIB_TABS_LUCID */ + +#ifdef HAVE_WIDGETS +static Widget +xlw_create_clip_window (widget_instance *instance) +{ + Arg al[20]; + int ac = 0; + Widget clip = 0; + widget_value* val = instance->info->val; + + XtSetArg (al [ac], XtNmappedWhenManaged, FALSE); ac++; + XtSetArg (al [ac], XtNsensitive, TRUE); ac++; + /* add any args the user supplied for creation time */ + lw_add_value_args_to_args (val, al, &ac); + + /* Create a clip window to contain the subwidget. Incredibly the + XEmacs manager seems to be the most appropriate widget for + this. Nothing else is simple enough and yet does what is + required. */ + clip = XtCreateManagedWidget (val->name, + emacsManagerWidgetClass, + instance->parent, al, ac); + + return clip; +} +#endif + widget_creation_entry xlw_creation_table [] = { @@ -312,6 +493,12 @@ xlw_creation_table [] = {"vertical-scrollbar", xlw_create_vertical_scrollbar}, {"horizontal-scrollbar", xlw_create_horizontal_scrollbar}, #endif +#ifdef LWLIB_TABS_LUCID + {"tab-control", xlw_create_tab_control}, +#endif +#ifdef HAVE_WIDGETS + {"clip-window", xlw_create_clip_window}, +#endif {NULL, NULL} }; @@ -327,6 +514,10 @@ lw_lucid_widget_p (Widget widget) if (the_class == xlwScrollBarWidgetClass) return True; #endif +#ifdef LWLIB_TABS_LUCID + if (the_class == tabsWidgetClass) + return True; +#endif #ifdef LWLIB_MENUBARS_LUCID if (the_class == overrideShellWidgetClass) return @@ -340,9 +531,7 @@ void xlw_update_one_widget (widget_instance* instance, Widget widget, widget_value* val, Boolean deep_p) { - WidgetClass class; - - class = XtClass (widget); + WidgetClass class = XtClass (widget); if (0) ; @@ -365,6 +554,12 @@ xlw_update_one_widget (widget_instance* instance, Widget widget, xlw_update_scrollbar (instance, widget, val); } #endif +#ifdef LWLIB_TABS_LUCID + else if (class == tabsWidgetClass) + { + xlw_update_tab_control (instance, widget, val); + } +#endif } void diff --git a/lwlib/lwlib-Xm.c b/lwlib/lwlib-Xm.c index 48bb2de..85db133 100644 --- a/lwlib/lwlib-Xm.c +++ b/lwlib/lwlib-Xm.c @@ -60,9 +60,11 @@ Boston, MA 02111-1307, USA. */ #include #include #include +#ifdef LWLIB_WIDGETS_MOTIF #include #if XmVERSION > 1 -#include +#include +#endif #endif #ifdef LWLIB_MENUBARS_MOTIF @@ -72,7 +74,9 @@ static void xm_internal_update_other_instances (Widget, XtPointer, XtPointer); static void xm_pop_down_callback (Widget, XtPointer, XtPointer); static void xm_generic_callback (Widget, XtPointer, XtPointer); -#ifdef LWLIB_DIALOGS_MOTIF +static void mark_dead_instance_destroyed (Widget widget, XtPointer closure, + XtPointer call_data); +#if defined (LWLIB_DIALOGS_MOTIF) || defined (LWLIB_WIDGETS_MOTIF) static void xm_nosel_callback (Widget, XtPointer, XtPointer); #endif #ifdef LWLIB_SCROLLBARS_MOTIF @@ -171,35 +175,6 @@ resource_string (Widget widget, char *name) return result; } -#ifdef LWLIB_MENUBARS_MOTIF - -static void -destroy_all_children (Widget widget) -{ - Widget* children; - unsigned int number; - int i; - - children = XtCompositeChildren (widget, &number); - if (children) - { - /* Unmanage all children and destroy them. They will only be - * really destroyed when we get out of DispatchEvent. */ - for (i = 0; i < number; i++) - { - Widget child = children [i]; - if (!child->core.being_destroyed) - { - XtUnmanageChild (child); - XtDestroyWidget (child); - } - } - XtFree ((char *) children); - } -} - -#endif /* LWLIB_MENUBARS_MOTIF */ - #ifdef LWLIB_DIALOGS_MOTIF @@ -221,7 +196,7 @@ is_in_dialog_box (Widget w) #endif /* LWLIB_DIALOGS_MOTIF */ -#if defined (LWLIB_DIALOGS_MOTIF) || defined (LWLIB_MENUBARS_MOTIF) +#if defined (LWLIB_DIALOGS_MOTIF) || defined (LWLIB_MENUBARS_MOTIF) || defined (LWLIB_WIDGETS_MOTIF) /* update the label of anything subclass of a label */ static void @@ -233,6 +208,14 @@ xm_update_label (widget_instance* instance, Widget widget, widget_value* val) XmString name_string = NULL; Arg al [20]; int ac = 0; + int type; + + /* Don't clobber pixmap types. */ + XtSetArg (al [0], XmNlabelType, &type); + XtGetValues (widget, al, 1); + + if (type == XmPIXMAP) + return; if (val->value) { @@ -262,24 +245,30 @@ xm_update_label (widget_instance* instance, Widget widget, widget_value* val) char *res_name = NULL; res_name = resource_string (widget, val->name); + /* Concatenating the value with itself seems just plain daft. */ if (!res_name) - res_name = val->name; - - name_string = - XmStringCreateLtoR (res_name, XmSTRING_DEFAULT_CHARSET); - - value_name = XtMalloc (strlen (val->value) + 2); - *value_name = 0; - strcat (value_name, " "); - strcat (value_name, val->value); - - val_string = - XmStringCreateLtoR (value_name, XmSTRING_DEFAULT_CHARSET); - - built_string = - XmStringConcat (name_string, val_string); - - XtFree (value_name); + { + built_string = + XmStringCreateLtoR (val->value, XmSTRING_DEFAULT_CHARSET); + } + else + { + name_string = + XmStringCreateLtoR (res_name, XmSTRING_DEFAULT_CHARSET); + + value_name = XtMalloc (strlen (val->value) + 2); + *value_name = 0; + strcat (value_name, " "); + strcat (value_name, val->value); + + val_string = + XmStringCreateLtoR (value_name, XmSTRING_DEFAULT_CHARSET); + + built_string = + XmStringConcat (name_string, val_string); + + XtFree (value_name); + } } XtSetArg (al [ac], XmNlabelString, built_string); ac++; @@ -303,6 +292,9 @@ xm_update_label (widget_instance* instance, Widget widget, widget_value* val) if (name_string) XmStringFree (name_string); + + if (val_string) + XmStringFree (val_string); } #endif /* defined (LWLIB_DIALOGS_MOTIF) || defined (LWLIB_MENUBARS_MOTIF) */ @@ -380,7 +372,7 @@ xm_update_toggle (widget_instance* instance, Widget widget, widget_value* val) instance); XtSetArg (al [0], XmNset, val->selected); XtSetArg (al [1], XmNalignment, XmALIGNMENT_BEGINNING); - XtSetValues (widget, al, 2); + XtSetValues (widget, al, 1); } static void @@ -425,6 +417,29 @@ xm_update_radiobox (widget_instance* instance, Widget widget, } } +#if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1 +/* update of combo box */ +static void +xm_update_combo_box (widget_instance* instance, Widget widget, widget_value* val) +{ + widget_value* cur; + int i; + XtRemoveAllCallbacks (widget, XmNselectionCallback); + XtAddCallback (widget, XmNselectionCallback, xm_generic_callback, + instance); + for (cur = val->contents, i = 0; cur; cur = cur->next) + if (cur->value) + { + XmString xmstr = XmStringCreate (cur->value, XmSTRING_DEFAULT_CHARSET); + i += 1; + XmListAddItem (CB_List (widget), xmstr, 0); + if (cur->selected) + XmListSelectPos (CB_List (widget), i, False); + XmStringFree (xmstr); + } +} +#endif + #ifdef LWLIB_MENUBARS_MOTIF /* update a popup menu, pulldown menu or a menubar */ @@ -767,22 +782,24 @@ xm_update_one_widget (widget_instance* instance, Widget widget, widget_value* val, Boolean deep_p) { WidgetClass class; - Arg al [2]; + Arg al [20]; + int ac = 0; /* Mark as not edited */ val->edited = False; /* Common to all widget types */ - XtSetArg (al [0], XmNsensitive, val->enabled); - XtSetArg (al [1], XmNuserData, val->call_data); - XtSetValues (widget, al, 2); + XtSetArg (al [ac], XmNsensitive, val->enabled); ac++; + XtSetArg (al [ac], XmNuserData, val->call_data); ac++; + lw_add_value_args_to_args (val, al, &ac); -#if defined (LWLIB_DIALOGS_MOTIF) || defined (LWLIB_MENUBARS_MOTIF) + XtSetValues (widget, al, ac); + +#if defined (LWLIB_DIALOGS_MOTIF) || defined (LWLIB_MENUBARS_MOTIF) || defined (LWLIB_WIDGETS_MOTIF) /* Common to all label like widgets */ if (XtIsSubclass (widget, xmLabelWidgetClass)) xm_update_label (instance, widget, val); -#endif /* defined (LWLIB_DIALOGS_MOTIF) || defined (LWLIB_MENUBARS_MOTIF) */ - +#endif class = XtClass (widget); /* Class specific things */ if (class == xmPushButtonWidgetClass || @@ -827,6 +844,12 @@ xm_update_one_widget (widget_instance* instance, Widget widget, { xm_update_list (instance, widget, val); } +#if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1 + else if (class == xmComboBoxWidgetClass) + { + xm_update_combo_box (instance, widget, val); + } +#endif #ifdef LWLIB_SCROLLBARS_MOTIF else if (class == xmScrollBarWidgetClass) { @@ -903,11 +926,20 @@ xm_update_one_value (widget_instance* instance, Widget widget, val->edited = True; } } - else if (class == xmListWidgetClass) + else if (class == xmListWidgetClass +#if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1 + || class == xmComboBoxWidgetClass +#endif + ) { int pos_cnt; int* pos_list; - if (XmListGetSelectedPos (widget, &pos_list, &pos_cnt)) + Widget list = widget; +#if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1 + if (class == xmComboBoxWidgetClass) + list = CB_List (widget); +#endif + if (XmListGetSelectedPos (list, &pos_list, &pos_cnt)) { int i; widget_value* cur; @@ -1316,14 +1348,6 @@ find_matching_instance (widget_instance* instance) } static void -mark_dead_instance_destroyed (Widget widget, XtPointer closure, - XtPointer call_data) -{ - destroyed_instance* instance = (destroyed_instance*)closure; - instance->widget = NULL; -} - -static void recenter_widget (Widget widget) { Widget parent = XtParent (widget); @@ -1566,9 +1590,10 @@ make_horizontal_scrollbar (widget_instance *instance) #endif /* LWLIB_SCROLLBARS_MOTIF */ +#ifdef LWLIB_WIDGETS_MOTIF /* glyph widgets */ static Widget -make_button (widget_instance *instance) +xm_create_button (widget_instance *instance) { Arg al[20]; int ac = 0; @@ -1615,14 +1640,21 @@ make_button (widget_instance *instance) } static Widget -make_progress (widget_instance *instance) +xm_create_progress (widget_instance *instance) { Arg al[20]; int ac = 0; Widget scale = 0; widget_value* val = instance->info->val; - XtSetArg (al [ac], XmNsensitive, val->enabled); ac++; + if (!val->call_data) + { + XtSetArg (al [ac], XmNsensitive, False); ac++; + } + else + { + XtSetArg (al [ac], XmNsensitive, val->enabled); ac++; + } XtSetArg (al [ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++; XtSetArg (al [ac], XmNuserData, val->call_data); ac++; XtSetArg (al [ac], XmNmappedWhenManaged, FALSE); ac++; @@ -1631,9 +1663,6 @@ make_progress (widget_instance *instance) look ugly. I think this may be a LessTif bug but for now we just get rid of it. */ XtSetArg (al [ac], XmNhighlightThickness, (Dimension)0);ac++; - if (!val->call_data) - XtSetArg (al [ac], XmNsensitive, False); ac++; - /* add any args the user supplied for creation time */ lw_add_value_args_to_args (val, al, &ac); @@ -1648,7 +1677,7 @@ make_progress (widget_instance *instance) } static Widget -make_text_field (widget_instance *instance) +xm_create_text_field (widget_instance *instance) { Arg al[20]; int ac = 0; @@ -1677,9 +1706,45 @@ make_text_field (widget_instance *instance) return text; } +static Widget +xm_create_label_field (widget_instance *instance) +{ + return xm_create_label (instance->parent, instance->info->val); +} + +Widget +xm_create_label (Widget parent, widget_value* val) +{ + Arg al[20]; + int ac = 0; + Widget label = 0; + + XtSetArg (al [ac], XmNsensitive, val->enabled); ac++; + XtSetArg (al [ac], XmNalignment, XmALIGNMENT_BEGINNING); ac++; + XtSetArg (al [ac], XmNmappedWhenManaged, FALSE); ac++; + /* The highlight doesn't appear to be dynamically set which makes it + look ugly. I think this may be a LessTif bug but for now we just + get rid of it. */ + XtSetArg (al [ac], XmNhighlightThickness, (Dimension)0);ac++; + + /* add any args the user supplied for creation time */ + lw_add_value_args_to_args (val, al, &ac); + + label = XmCreateLabel (parent, val->name, al, ac); + + XtManageChild (label); + + /* Do it again for arguments that have no effect until the widget is realized. */ + ac = 0; + lw_add_value_args_to_args (val, al, &ac); + XtSetValues (label, al, ac); + + return label; +} + #if XmVERSION > 1 static Widget -make_combo_box (widget_instance *instance) +xm_create_combo_box (widget_instance *instance) { Arg al[20]; int ac = 0; @@ -1698,7 +1763,7 @@ make_combo_box (widget_instance *instance) /* add any args the user supplied for creation time */ lw_add_value_args_to_args (val, al, &ac); - combo = XmCreateComboBox (instance->parent, val->name, al, ac); + combo = XmCreateDropDownComboBox (instance->parent, val->name, al, ac); if (val->call_data) XtAddCallback (combo, XmNselectionCallback, xm_generic_callback, (XtPointer)instance); @@ -1708,6 +1773,7 @@ make_combo_box (widget_instance *instance) return combo; } #endif +#endif /* LWLIB_WIDGETS_MOTIF */ /* Table of functions to create widgets */ @@ -1723,11 +1789,14 @@ xm_creation_table [] = {"vertical-scrollbar", make_vertical_scrollbar}, {"horizontal-scrollbar", make_horizontal_scrollbar}, #endif - {"button", make_button}, - {"progress", make_progress}, - {"text-field", make_text_field}, +#ifdef LWLIB_WIDGETS_MOTIF + {"button", xm_create_button}, + {"progress", xm_create_progress}, + {"text-field", xm_create_text_field}, + {"label", xm_create_label_field}, #if XmVERSION > 1 - {"combo-box", make_combo_box}, + {"combo-box", xm_create_combo_box}, +#endif #endif {NULL, NULL} }; @@ -1736,7 +1805,7 @@ xm_creation_table [] = void xm_destroy_instance (widget_instance* instance) { -#ifdef LWLIB_DIALOGS_MOTIF +#if defined (LWLIB_DIALOGS_MOTIF) || defined (LWLIB_WIDGETS_MOTIF) /* It appears that this is used only for dialog boxes. */ Widget widget = instance->widget; /* recycle the dialog boxes */ @@ -1767,7 +1836,7 @@ xm_destroy_instance (widget_instance* instance) XtDestroyWidget (instance->widget); } -#endif /* LWLIB_DIALOGS_MOTIF */ +#endif /* LWLIB_DIALOGS_MOTIF || LWLIB_WIDGETS_MOTIF */ } /* popup utility */ @@ -1920,7 +1989,7 @@ xm_internal_update_other_instances (Widget widget, XtPointer closure, static void xm_generic_callback (Widget widget, XtPointer closure, XtPointer call_data) { -#if (defined (LWLIB_MENUBARS_MOTIF) || defined (LWLIB_DIALOGS_MOTIF)) +#if (defined (LWLIB_MENUBARS_MOTIF) || defined (LWLIB_DIALOGS_MOTIF) || defined (LWLIB_WIDGETS_MOTIF)) /* We want the selected status to change only when we decide it should change. Yuck but correct. */ if (XtClass (widget) == xmToggleButtonWidgetClass @@ -1946,25 +2015,6 @@ xm_pop_down_callback (Widget widget, XtPointer closure, XtPointer call_data) do_call (widget, closure, post_activate); } -#ifdef LWLIB_DIALOGS_MOTIF - -static void -xm_nosel_callback (Widget widget, XtPointer closure, XtPointer call_data) -{ - /* This callback is only called when a dialog box is dismissed with the wm's - destroy button (WM_DELETE_WINDOW.) We want the dialog box to be destroyed - in that case, not just unmapped, so that it releases its keyboard grabs. - But there are problems with running our callbacks while the widget is in - the process of being destroyed, so we set XmNdeleteResponse to XmUNMAP - instead of XmDESTROY and then destroy it ourself after having run the - callback. - */ - do_call (widget, closure, no_selection); - XtDestroyWidget (widget); -} - -#endif - #ifdef LWLIB_MENUBARS_MOTIF static void @@ -2073,6 +2123,31 @@ xm_scrollbar_callback (Widget widget, XtPointer closure, XtPointer call_data) } #endif /* LWLIB_SCROLLBARS_MOTIF */ +#if defined (LWLIB_DIALOGS_MOTIF) || defined (LWLIB_WIDGETS_MOTIF) +static void +mark_dead_instance_destroyed (Widget widget, XtPointer closure, + XtPointer call_data) +{ + destroyed_instance* instance = (destroyed_instance*)closure; + instance->widget = NULL; +} + +static void +xm_nosel_callback (Widget widget, XtPointer closure, XtPointer call_data) +{ + /* This callback is only called when a dialog box is dismissed with the wm's + destroy button (WM_DELETE_WINDOW.) We want the dialog box to be destroyed + in that case, not just unmapped, so that it releases its keyboard grabs. + But there are problems with running our callbacks while the widget is in + the process of being destroyed, so we set XmNdeleteResponse to XmUNMAP + instead of XmDESTROY and then destroy it ourself after having run the + callback. + */ + do_call (widget, closure, no_selection); + XtDestroyWidget (widget); +} +#endif + /* set the keyboard focus */ void diff --git a/lwlib/lwlib-Xm.h b/lwlib/lwlib-Xm.h index 9088838..b030a51 100644 --- a/lwlib/lwlib-Xm.h +++ b/lwlib/lwlib-Xm.h @@ -8,6 +8,9 @@ extern widget_creation_entry xm_creation_table []; Widget xm_create_dialog (widget_instance* instance); +Widget +xm_create_label (Widget parent, widget_value* val); + Boolean lw_motif_widget_p (Widget widget); diff --git a/lwlib/lwlib-config.c b/lwlib/lwlib-config.c index f2c6edf..7da6b51 100644 --- a/lwlib/lwlib-config.c +++ b/lwlib/lwlib-config.c @@ -88,3 +88,13 @@ int lwlib_dialogs_athena; int lwlib_does_not_support_dialogs; # endif #endif + +#ifdef LWLIB_WIDGETS_MOTIF +int lwlib_widgets_motif; +#else +# ifdef LWLIB_WIDGETS_ATHENA +int lwlib_widgets_athena; +# else +int lwlib_does_not_support_widgets; +# endif +#endif diff --git a/lwlib/lwlib-utils.c b/lwlib/lwlib-utils.c index 0df97a6..9728c6a 100644 --- a/lwlib/lwlib-utils.c +++ b/lwlib/lwlib-utils.c @@ -31,6 +31,31 @@ Boston, MA 02111-1307, USA. */ #include #include "lwlib-utils.h" +void +destroy_all_children (Widget widget) +{ + Widget* children; + unsigned int number; + int i; + + children = XtCompositeChildren (widget, &number); + if (children) + { + /* Unmanage all children and destroy them. They will only be + * really destroyed when we get out of DispatchEvent. */ + for (i = 0; i < number; i++) + { + Widget child = children [i]; + if (!child->core.being_destroyed) + { + XtUnmanageChild (child); + XtDestroyWidget (child); + } + } + XtFree ((char *) children); + } +} + /* Redisplay the contents of the widget, without first clearing it. */ void XtNoClearRefreshWidget (Widget widget) diff --git a/lwlib/lwlib-utils.h b/lwlib/lwlib-utils.h index cfba632..3163a5a 100644 --- a/lwlib/lwlib-utils.h +++ b/lwlib/lwlib-utils.h @@ -1,6 +1,7 @@ #ifndef _LWLIB_UTILS_H_ #define _LWLIB_UTILS_H_ +void destroy_all_children (Widget widget); void XtNoClearRefreshWidget (Widget); typedef void (*XtApplyToWidgetsProc) (Widget, XtPointer); diff --git a/lwlib/lwlib.c b/lwlib/lwlib.c index dcbc0b2..69a5c04 100644 --- a/lwlib/lwlib.c +++ b/lwlib/lwlib.c @@ -125,8 +125,6 @@ free_widget_value (widget_value *wv) widget_value_free_list = wv; } -static void free_widget_value_tree (widget_value *wv); - static void free_widget_value_contents (widget_value *wv) { @@ -155,11 +153,13 @@ free_widget_value_contents (widget_value *wv) free_widget_value_tree (wv->contents); wv->contents = (widget_value *) 0xDEADBEEF; } - if (wv->args && wv->free_args) + if (wv->args && wv->nargs) { - free (wv->args); - wv->args = (void *) 0xDEADBEEF; + if (wv->free_args) + free (wv->args); + wv->args = (ArgList) 0xDEADBEEF; wv->nargs = 0; + wv->free_args = 0; } if (wv->next) { @@ -168,7 +168,7 @@ free_widget_value_contents (widget_value *wv) } } -static void +void free_widget_value_tree (widget_value *wv) { if (!wv) @@ -1326,3 +1326,4 @@ void lw_add_value_args_to_args (widget_value* wv, ArgList addto, int* offset) *offset += wv->nargs; } } + diff --git a/lwlib/lwlib.h b/lwlib/lwlib.h index 96dfa56..bca2d64 100644 --- a/lwlib/lwlib.h +++ b/lwlib/lwlib.h @@ -181,6 +181,10 @@ extern int lw_menu_active; /* do this for the other toolkits too */ #endif /* LWLIB_MENUBARS_LUCID */ +#if defined (LWLIB_TABS_LUCID) +#include "xlwtabs.h" +#endif + void lw_register_widget (CONST char* type, CONST char* name, LWLIB_ID id, widget_value* val, lw_callback pre_activate_cb, lw_callback selection_cb, @@ -210,6 +214,7 @@ void lw_add_value_args_to_args (widget_value* wv, ArgList addto, int* offset); widget_value *malloc_widget_value (void); void free_widget_value (widget_value *); +void free_widget_value_tree (widget_value *wv); widget_value *replace_widget_value_tree (widget_value*, widget_value*); void lw_popup_menu (Widget, XEvent *); diff --git a/man/ChangeLog b/man/ChangeLog index b0157a5..47d4e7e 100644 --- a/man/ChangeLog +++ b/man/ChangeLog @@ -1,3 +1,43 @@ +1999-11-10 XEmacs Build Bot + + * XEmacs 21.2.20 is released + +1999-08-30 Robert Pluim + + * xemacs/packages.texi (Using Packages): Added description of + package-get-package-provider. + +1999-07-27 Charles G Waldman + + * xemacs-faq.texi (Q5.0.6): Describe `shell-multiple-shells' + +1999-08-01 Adrian Aichner + + * xemacs/programs.texi (Balanced Editing): Remove broken + line-break. + + * xemacs-faq.texi (Q1.0.6): Provide correct location in XEmacs + menus. + (Q1.4.1): ditto. + (Q1.4.3): ditto. + (Q2.0.5): Hyphenate words. + + * info.texi (Add): Fix one typo. + +1999-08-23 Stephane Epardaud + + * internals/internals.texi (Garbage Collection - Step by Step): + just added some dots to shut up compile warnings. + +1999-08-19 Matthias Neubauer + + * internals/internals.texi (Garbage Collection - Step by Step): + new section in chapter Allocation of Objects in XEmacs Lisp. + +1999-07-28 Andy Piper + + * internals.texi (Glyphs): add some glyph documentation. + 1999-07-30 XEmacs Build Bot * XEmacs 21.2.19 is released diff --git a/man/info.texi b/man/info.texi index d2fda6f..def560e 100644 --- a/man/info.texi +++ b/man/info.texi @@ -3,7 +3,7 @@ @setfilename ../info/info.info @settitle Info 1.0 @comment %**end of header -@comment $Id: info.texi,v 1.4 1997/07/10 21:58:11 karl Exp $ +@comment $Id: info.texi,v 1.4 1998/06/30 06:35:28 steve Exp $ @dircategory Texinfo documentation system @direntry @@ -681,7 +681,7 @@ Put that topic in the menu in the directory. @xref{Menus, Menu}. Usually, the way to create the nodes is with Texinfo @pxref{Top,, Overview of Texinfo, texinfo, Texinfo: The GNU Documentation Format}); this has the advantage that you can also make a printed manual from them. However, -if hyou want to edit an Info file, here is how. +if you want to edit an Info file, here is how. The new node can live in an existing documentation file, or in a new one. It must have a @key{^_} character before it (invisible to the diff --git a/man/internals/internals.texi b/man/internals/internals.texi index 2366573..f6eb892 100644 --- a/man/internals/internals.texi +++ b/man/internals/internals.texi @@ -63,11 +63,12 @@ instead of in the original English. @titlepage @title XEmacs Internals Manual -@subtitle Version 1.2, October 1998 +@subtitle Version 1.3, August 1999 @author Ben Wing @author Martin Buchholz @author Hrvoje Niksic +@author Matthias Neubauer @page @vskip 0pt plus 1fill @@ -78,8 +79,8 @@ Copyright @copyright{} 1994 - 1998 Free Software Foundation. @* Copyright @copyright{} 1994, 1995 Board of Trustees, University of Illinois. @sp 2 -Version 1.2 @* -October 1998.@* +Version 1.3 @* +August 1999.@* Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are @@ -127,7 +128,8 @@ This Info file contains v1.0 of the XEmacs Internals Manual. * Consoles; Devices; Frames; Windows:: * The Redisplay Mechanism:: * Extents:: -* Faces and Glyphs:: +* Faces:: +* Glyphs:: * Specifiers:: * Menus:: * Subprocesses:: @@ -174,6 +176,7 @@ Allocation of Objects in XEmacs Lisp * Introduction to Allocation:: * Garbage Collection:: * GCPROing:: +* Garbage Collection - Step by Step:: * Integers and Characters:: * Allocation from Frob Blocks:: * lrecords:: @@ -260,7 +263,9 @@ Extents * Mathematics of Extent Ordering:: A rigorous foundation. * Extent Fragments:: Cached information useful for redisplay. -Faces and Glyphs +Faces + +Glyphs Specifiers @@ -4370,6 +4375,7 @@ Asian-language support, and is not currently used. * Introduction to Allocation:: * Garbage Collection:: * GCPROing:: +* Garbage Collection - Step by Step:: * Integers and Characters:: * Allocation from Frob Blocks:: * lrecords:: @@ -4714,6 +4720,502 @@ will result in a few objects not getting collected when they should, but it obviates the need for @code{GCPRO}ing, and allows garbage collection to happen at any point at all, such as during object allocation. +@node Garbage Collection - Step by Step +@section Garbage Collection - Step by Step +@cindex garbage collection step by step + +@menu +* Invocation:: +* garbage_collect_1:: +* mark_object:: +* gc_sweep:: +* sweep_lcrecords_1:: +* compact_string_chars:: +* sweep_strings:: +* sweep_bit_vectors_1:: +@end menu + +@node Invocation +@subsection Invocation +@cindex garbage collection, invocation + +The first thing that anyone should know about garbage collection is: +when and how the garbage collector is invoked. One might think that this +could happen every time new memory is allocated, e.g. new objects are +created, but this is @emph{not} the case. Instead, we have the following +situation: + +The entry point of any process of garbage collection is an invocation +of the function @code{garbage_collect_1} in file @code{alloc.c}. The +invocation can occur @emph{explicitly} by calling the function +@code{Fgarbage_collect} (in addition this function provides information +about the freed memory), or can occur @emph{implicitly} in four different +situations: +@enumerate +@item +In function @code{main_1} in file @code{emacs.c}. This function is called +at each startup of xemacs. The garbage collection is invoked after all +initial creations are completed, but only if a special internal error +checking-constant @code{ERROR_CHECK_GC} is defined. +@item +In function @code{disksave_object_finalization} in file +@code{alloc.c}. The only purpose of this function is to clear the +objects from memory which need not be stored with xemacs when we dump out +an executable. This is only done by @code{Fdump_emacs} or by +@code{Fdump_emacs_data} respectively (both in @code{emacs.c}). The +actual clearing is accomplished by making these objects unreachable and +starting a garbage collection. The function is only used while building +xemacs. +@item +In function @code{Feval / eval} in file @code{eval.c}. Each time the +well known and often used function eval is called to evaluate a form, +one of the first things that could happen, is a potential call of +@code{garbage_collect_1}. There exist three global variables, +@code{consing_since_gc} (counts the created cons-cells since the last +garbage collection), @code{gc_cons_threshold} (a specified threshold +after which a garbage collection occurs) and @code{always_gc}. If +@code{always_gc} is set or if the threshold is exceeded, the garbage +collection will start. +@item +In function @code{Ffuncall / funcall} in file @code{eval.c}. This +function evaluates calls of elisp functions and works according to +@code{Feval}. +@end enumerate + +The upshot is that garbage collection can basically occur everywhere +@code{Feval}, respectively @code{Ffuncall}, is used - either directly or +through another function. Since calls to these two functions are +hidden in various other functions, many calls to +@code{garabge_collect_1} are not obviously foreseeable, and therefore +unexpected. Instances where they are used that are worth remembering are +various elisp commands, as for example @code{or}, +@code{and}, @code{if}, @code{cond}, @code{while}, @code{setq}, etc., +miscellaneous @code{gui_item_...} functions, everything related to +@code{eval} (@code{Feval_buffer}, @code{call0}, ...) and inside +@code{Fsignal}. The latter is used to handle signals, as for example the +ones raised by every @code{QUITE}-macro triggered after pressing Ctrl-g. + +@node garbage_collect_1 +@subsection @code{garbage_collect_1} +@cindex @code{garbage_collect_1} + +We can now describe exactly what happens after the invocation takes +place. +@enumerate +@item +There are several cases in which the garbage collector is left immediately: +when we are already garbage collecting (@code{gc_in_progress}), when +the garbage collection is somehow forbidden +(@code{gc_currently_forbidden}), when we are currently displaying something +(@code{in_display}) or when we are preparing for the armageddon of the +whole system (@code{preparing_for_armageddon}). +@item +Next the correct frame in which to put +all the output occurring during garbage collecting is determined. In +order to be able to restore the old display's state after displaying the +message, some data about the current cursor position has to be +saved. The variables @code{pre_gc_curser} and @code{cursor_changed} take +care of that. +@item +The state of @code{gc_currently_forbidden} must be restored after +the garbage collection, no matter what happens during the process. We +accomplish this by @code{record_unwind_protect}ing the suitable function +@code{restore_gc_inhibit} together with the current value of +@code{gc_currently_forbidden}. +@item +If we are concurrently running an interactive xemacs session, the next step +is simply to show the garbage collector's cursor/message. +@item +The following steps are the intrinsic steps of the garbage collector, +therefore @code{gc_in_progress} is set. +@item +For debugging purposes, it is possible to copy the current C stack +frame. However, this seems to be a currently unused feature. +@item +Before actually starting to go over all live objects, references to +objects that are no longer used are pruned. We only have to do this for events +(@code{clear_event_resource}) and for specifiers +(@code{cleanup_specifiers}). +@item +Now the mark phase begins and marks all accessible elements. In order to +start from +all slots that serve as roots of accessibility, the function +@code{mark_object} is called for each root individually to go out from +there to mark all reachable objects. All roots that are traversed are +shown in their processed order: +@itemize @bullet +@item +all constant symbols and static variables that are registered via +@code{staticpro}@ in the array @code{staticvec}. +@xref{Adding Global Lisp Variables}. +@item +all Lisp objects that are created in C functions and that must be +protected from freeing them. They are registered in the global +list @code{gcprolist}. +@xref{GCPROing}. +@item +all local variables (i.e. their name fields @code{symbol} and old +values @code{old_values}) that are bound during the evaluation by the Lisp +engine. They are stored in @code{specbinding} structs pushed on a stack +called @code{specpdl}. +@xref{Dynamic Binding; The specbinding Stack; Unwind-Protects}. +@item +all catch blocks that the Lisp engine encounters during the evaluation +cause the creation of structs @code{catchtag} inserted in the list +@code{catchlist}. Their tag (@code{tag}) and value (@code{val} fields +are freshly created objects and therefore have to be marked. +@xref{Catch and Throw}. +@item +every function application pushes new structs @code{backtrace} +on the call stack of the Lisp engine (@code{backtrace_list}). The unique +parts that have to be marked are the fields for each function +(@code{function}) and all their arguments (@code{args}). +@xref{Evaluation}. +@item +all objects that are used by the redisplay engine that must not be freed +are marked by a special function called @code{mark_redisplay} (in +@code{redisplay.c}). +@item +all objects created for profiling purposes are allocated by C functions +instead of using the lisp allocation mechanisms. In order to receive the +right ones during the sweep phase, they also have to be marked +manually. That is done by the function @code{mark_profiling_info} +@end itemize +@item +Hash tables in Xemacs belong to a kind of special objects that +make use of a concept often called 'weak pointers'. +To make a long story short, these kind of pointers are not followed +during the estimation of the live objects during garbage collection. +Any object referenced only by weak pointers is collected +anyway, and the reference to it is cleared. In hash tables there are +different usage patterns of them, manifesting in different types of hash +tables, namely 'non-weak', 'weak', 'key-weak' and 'value-weak' +(internally also 'key-car-weak' and 'value-car-weak') hash tables, each +clearing entries depending on different conditions. More information can +be found in the documentation to the function @code{make-hash-table}. + +Because there are complicated dependency rules about when and what to +mark while processing weak hash tables, the standard @code{marker} +method is only active if it is marking non-weak hash tables. As soon as +a weak component is in the table, the hash table entries are ignored +while marking. Instead their marking is done each separately by the +function @code{finish_marking_weak_hash_tables}. This function iterates +over each hash table entry @code{hentries} for each weak hash table in +@code{Vall_weak_hash_tables}. Depending on the type of a table, the +appropriate action is performed. +If a table is acting as @code{HASH_TABLE_KEY_WEAK}, and a key already marked, +everything reachable from the @code{value} component is marked. If it is +acting as a @code{HASH_TABLE_VALUE_WEAK} and the value component is +already marked, the marking starts beginning only from the +@code{key} component. +If it is a @code{HASH_TABLE_KEY_CAR_WEAK} and the car +of the key entry is already marked, we mark both the @code{key} and +@code{value} components. +Finally, if the table is of the type @code{HASH_TABLE_VALUE_CAR_WEAK} +and the car of the value components is already marked, again both the +@code{key} and the @code{value} components get marked. + +Again, there are lists with comparable properties called weak +lists. There exist different peculiarities of their types called +@code{simple}, @code{assoc}, @code{key-assoc} and +@code{value-assoc}. You can find further details about them in the +description to the function @code{make-weak-list}. The scheme of their +marking is similar: all weak lists are listed in @code{Qall_weak_lists}, +therefore we iterate over them. The marking is advanced until we hit an +already marked pair. Then we know that during a former run all +the rest has been marked completely. Again, depending on the special +type of the weak list, our jobs differ. If it is a @code{WEAK_LIST_SIMPLE} +and the elem is marked, we mark the @code{cons} part. If it is a +@code{WEAK_LIST_ASSOC} and not a pair or a pair with both marked car and +cdr, we mark the @code{cons} and the @code{elem}. If it is a +@code{WEAK_LIST_KEY_ASSOC} and not a pair or a pair with a marked car of +the elem, we mark the @code{cons} and the @code{elem}. Finally, if it is +a @code{WEAK_LIST_VALUE_ASSOC} and not a pair or a pair with a marked +cdr of the elem, we mark both the @code{cons} and the @code{elem}. + +Since, by marking objects in reach from weak hash tables and weak lists, +other objects could get marked, this perhaps implies further marking of +other weak objects, both finishing functions are redone as long as +yet unmarked objects get freshly marked. + +@item +After completing the special marking for the weak hash tables and for the weak +lists, all entries that point to objects that are going to be swept in +the further process are useless, and therefore have to be removed from +the table or the list. + +The function @code{prune_weak_hash_tables} does the job for weak hash +tables. Totally unmarked hash tables are removed from the list +@code{Vall_weak_hash_tables}. The other ones are treated more carefully +by scanning over all entries and removing one as soon as one of +the components @code{key} and @code{value} is unmarked. + +The same idea applies to the weak lists. It is accomplished by +@code{prune_weak_lists}: An unmarked list is pruned from +@code{Vall_weak_lists} immediately. A marked list is treated more +carefully by going over it and removing just the unmarked pairs. + +@item +The function @code{prune_specifiers} checks all listed specifiers held +in @code{Vall_speficiers} and removes the ones from the lists that are +unmarked. + +@item +All syntax tables are stored in a list called +@code{Vall_syntax_tables}. The function @code{prune_syntax_tables} walks +through it and unlinks the tables that are unmarked. + +@item +Next, we will attack the complete sweeping - the function +@code{gc_sweep} which holds the predominance. +@item +First, all the variables with respect to garbage collection are +reset. @code{consing_since_gc} - the counter of the created cells since +the last garbage collection - is set back to 0, and +@code{gc_in_progress} is not @code{true} anymore. +@item +In case the session is interactive, the displayed cursor and message are +removed again. +@item +The state of @code{gc_inhibit} is restored to the former value by +unwinding the stack. +@item +A small memory reserve is always held back that can be reached by +@code{breathing_space}. If nothing more is left, we create a new reserve +and exit. +@end enumerate + +@node mark_object +@subsection @code{mark_object} +@cindex @code{mark_object} + +The first thing that is checked while marking an object is whether the +object is a real Lisp object @code{Lisp_Type_Record} or just an integer +or a character. Integers and characters are the only two types that are +stored directly - without another level of indirection, and therefore they +don´t have to be marked and collected. +@xref{How Lisp Objects Are Represented in C}. + +The second case is the one we have to handle. It is the one when we are +dealing with a pointer to a Lisp object. But, there exist also three +possibilities, that prevent us from doing anything while marking: The +object is read only which prevents it from being garbage collected, +i.e. marked (@code{C_READONLY_RECORD_HEADER}). The object in question is +already marked, and need not be marked for the second time (checked by +@code{MARKED_RECORD_HEADER_P}). If it is a special, unmarkable object +(@code{UNMARKABLE_RECORD_HEADER_P}, apparently, these are objects that +sit in some CONST space, and can therefore not be marked, see +@code{this_one_is_unmarkable} in @code{alloc.c}). + +Now, the actual marking is feasible. We do so by once using the macro +@code{MARK_RECORD_HEADER} to mark the object itself (actually the +special flag in the lrecord header), and calling its special marker +"method" @code{marker} if available. The marker method marks every +other object that is in reach from our current object. Note, that these +marker methods should not call @code{mark_object} recursively, but +instead should return the next object from where further marking has to +be performed. + +In case another object was returned, as mentioned before, we reiterate +the whole @code{mark_object} process beginning with this next object. + +@node gc_sweep +@subsection @code{gc_sweep} +@cindex @code{gc_sweep} + +The job of this function is to free all unmarked records from memory. As +we know, there are different types of objects implemented and managed, and +consequently different ways to free them from memory. +@xref{Introduction to Allocation}. + +We start with all objects stored through @code{lcrecords}. All +bulkier objects are allocated and handled using that scheme of +@code{lcrecords}. Each object is @code{malloc}ed separately +instead of placing it in one of the contiguous frob blocks. All types +that are currently stored +using @code{lcrecords}´s @code{alloc_lcrecord} and +@code{make_lcrecord_list} are the types: vectors, buffers, +char-table, char-table-entry, console, weak-list, database, device, +ldap, hash-table, command-builder, extent-auxiliary, extent-info, face, +coding-system, frame, image-instance, glyph, popup-data, gui-item, +keymap, charset, color_instance, font_instance, opaque, opaque-list, +process, range-table, specifier, symbol-value-buffer-local, +symbol-value-lisp-magic, symbol-value-varalias, toolbar-button, +tooltalk-message, tooltalk-pattern, window, and window-configuration. We +take care of them in the fist place +in order to be able to handle and to finalize items stored in them more +easily. The function @code{sweep_lcrecords_1} as described below is +doing the whole job for us. +For a description about the internals: @xref{lrecords}. + +Our next candidates are the other objects that behave quite differently +than everything else: the strings. They consists of two parts, a +fixed-size portion (@code{struct Lisp_string}) holding the string's +length, its property list and a pointer to the second part, and the +actual string data, which is stored in string-chars blocks comparable to +frob blocks. In this block, the data is not only freed, but also a +compression of holes is made, i.e. all strings are relocated together. +@xref{String}. This compacting phase is performed by the function +@code{compact_string_chars}, the actual sweeping by the function +@code{sweep_strings} is described below. + +After that, the other types are swept step by step using functions +@code{sweep_conses}, @code{sweep_bit_vectors_1}, +@code{sweep_compiled_functions}, @code{sweep_floats}, +@code{sweep_symbols}, @code{sweep_extents}, @code{sweep_markers} and +@code{sweep_extents}. They are the fixed-size types cons, floats, +compiled-functions, symbol, marker, extent, and event stored in +so-called "frob blocks", and therefore we can basically do the same on +every type objects, using the same macros, especially defined only to +handle everything with respect to fixed-size blocks. The only fixed-size +type that is not handled here are the fixed-size portion of strings, +because we took special care of them earlier. + +The only big exceptions are bit vectors stored differently and +therefore treated differently by the function @code{sweep_bit_vectors_1} +described later. + +At first, we need some brief information about how +these fixed-size types are managed in general, in order to understand +how the sweeping is done. They have all a fixed size, and are therefore +stored in big blocks of memory - allocated at once - that can hold a +certain amount of objects of one type. The macro +@code{DECLARE_FIXED_TYPE_ALLOC} creates the suitable structures for +every type. More precisely, we have the block struct +(holding a pointer to the previous block @code{prev} and the +objects in @code{block[]}), a pointer to current block +(@code{current_..._block)}) and its last index +(@code{current_..._block_index}), and a pointer to the free list that +will be created. Also a macro @code{FIXED_TYPE_FROM_BLOCK} plus some +related macros exists that are used to obtain a new object, either from +the free list @code{ALLOCATE_FIXED_TYPE_1} if there is an unused object +of that type stored or by allocating a completely new block using +@code{ALLOCATE_FIXED_TYPE_FROM_BLOCK}. + +The rest works as follows: all of them define a +macro @code{UNMARK_...} that is used to unmark the object. They define a +macro @code{ADDITIONAL_FREE_...} that defines additional work that has +to be done when converting an object from in use to not in use (so far, +only markers use it in order to unchain them). Then, they all call +the macro @code{SWEEP_FIXED_TYPE_BLOCK} instantiated with their type name +and their struct name. + +This call in particular does the following: we go over all blocks +starting with the current moving towards the oldest. +For each block, we look at every object in it. If the object already +freed (checked with @code{FREE_STRUCT_P} using the first pointer of the +object), or if it is +set to read only (@code{C_READONLY_RECORD_HEADER_P}, nothing must be +done. If it is unmarked (checked with @code{MARKED_RECORD_HEADER_P}), it +is put in the free list and set free (using the macro +@code{FREE_FIXED_TYPE}, otherwise it stays in the block, but is unmarked +(by @code{UNMARK_...}). While going through one block, we note if the +whole block is empty. If so, the whole block is freed (using +@code{xfree}) and the free list state is set to the state it had before +handling this block. + +@node sweep_lcrecords_1 +@subsection @code{sweep_lcrecords_1} +@cindex @code{sweep_lcrecords_1} + +After nullifying the complete lcrecord statistics, we go over all +lcrecords two separate times. They are all chained together in a list with +a head called @code{all_lcrecords}. + +The first loop calls for each object its @code{finalizer} method, but only +in the case that it is not read only +(@code{C_READONLY_RECORD_HEADER_P)}, it is not already marked +(@code{MARKED_RECORD_HEADER_P}), it is not already in a free list (list of +freed objects, field @code{free}) and finally it owns a finalizer +method. + +The second loop actually frees the appropriate objects again by iterating +through the whole list. In case an object is read only or marked, it +has to persist, otherwise it is manually freed by calling +@code{xfree}. During this loop, the lcrecord statistics are kept up to +date by calling @code{tick_lcrecord_stats} with the right arguments, + +@node compact_string_chars +@subsection @code{compact_string_chars} +@cindex @code{compact_string_chars} + +The purpose of this function is to compact all the data parts of the +strings that are held in so-called @code{string_chars_block}, i.e. the +strings that do not exceed a certain maximal length. + +The procedure with which this is done is as follows. We are keeping two +positions in the @code{string_chars_block}s using two pointer/integer +pairs, namely @code{from_sb}/@code{from_pos} and +@code{to_sb}/@code{to_pos}. They stand for the actual positions, from +where to where, to copy the actually handled string. + +While going over all chained @code{string_char_block}s and their held +strings, staring at @code{first_string_chars_block}, both pointers +are advanced and eventually a string is copied from @code{from_sb} to +@code{to_sb}, depending on the status of the pointed at strings. + +More precisely, we can distinguish between the following actions. +@itemize @bullet +@item +The string at @code{from_sb}'s position could be marked as free, which +is indicated by an invalid pointer to the pointer that should point back +to the fixed size string object, and which is checked by +@code{FREE_STRUCT_P}. In this case, the @code{from_sb}/@code{from_pos} +is advanced to the next string, and nothing has to be copied. +@item +Also, if a string object itself is unmarked, nothing has to be +copied. We likewise advance the @code{from_sb}/@code{from_pos} +pair as described above. +@item +In all other cases, we have a marked string at hand. The string data +must be moved from the from-position to the to-position. In case +there is not enough space in the actual @code{to_sb}-block, we advance +this pointer to the beginning of the next block before copying. In case the +from and to positions are different, we perform the +actual copying using the library function @code{memmove}. +@end itemize + +After compacting, the pointer to the current +@code{string_chars_block}, sitting in @code{current_string_chars_block}, +is reset on the last block to which we moved a string, +i.e. @code{to_block}, and all remaining blocks (we know that they just +carry garbage) are explicitly @code{xfree}d. + +@node sweep_strings +@subsection @code{sweep_strings} +@cindex @code{sweep_strings} + +The sweeping for the fixed sized string objects is essentially exactly +the same as it is for all other fixed size types. As before, the freeing +into the suitable free list is done by using the macro +@code{SWEEP_FIXED_SIZE_BLOCK} after defining the right macros +@code{UNMARK_string} and @code{ADDITIONAL_FREE_string}. These two +definitions are a little bit special compared to the ones used +for the other fixed size types. + +@code{UNMARK_string} is defined the same way except some additional code +used for updating the bookkeeping information. + +For strings, @code{ADDITIONAL_FREE_string} has to do something in +addition: in case, the string was not allocated in a +@code{string_chars_block} because it exceeded the maximal length, and +therefore it was @code{malloc}ed separately, we know also @code{xfree} +it explicitly. + +@node sweep_bit_vectors_1 +@subsection @code{sweep_bit_vectors_1} +@cindex @code{sweep_bit_vectors_1} + +Bit vectors are also one of the rare types that are @code{malloc}ed +individually. Consequently, while sweeping, all further needless +bit vectors must be freed by hand. This is done, as one might imagine, +the expected way: since they are all registered in a list called +@code{all_bit_vectors}, all elements of that list are traversed, +all unmarked bit vectors are unlinked by calling @code{xfree} and all of +them become unmarked. +In addition, the bookkeeping information used for garbage +collector's output purposes is updated. + @node Integers and Characters @section Integers and Characters @@ -7402,6 +7904,7 @@ It Is Better To Be Fast Than Not To Be. @menu * Critical Redisplay Sections:: * Line Start Cache:: +* Redisplay Piece by Piece:: @end menu @node Critical Redisplay Sections @@ -7497,7 +8000,58 @@ the part of the cache starting at where the modification occurs. In case you're wondering, the Second Golden Rule of Redisplay is not applicable. -@node Extents, Faces and Glyphs, The Redisplay Mechanism, Top +@node Redisplay Piece by Piece +@section Redisplay Piece by Piece +@cindex Redisplay Piece by Piece + +As you can begin to see redisplay is complex and also not well +documented. Chuck no longer works on XEmacs so this section is my take +on the workings of redisplay. + +Redisplay happens in three phases: + +@enumerate +@item +Determine desired display in area that needs redisplay. +Implemented by @code{redisplay.c} +@item +Compare desired display with current display +Implemented by @code{redisplay-output.c} +@item +Output changes Implemented by @code{redisplay-output.c}, +@code{redisplay-x.c}, @code{redisplay-msw.c} and @code{redisplay-tty.c} +@end enumerate + +Steps 1 and 2 are device-independant and relatively complex. Step 3 is +mostly device-dependent. + +Determining the desired display + +Display attributes are stored in @code{display_line} structures. Each +@code{display_line} consists of a set of @code{display_block}'s and each +@code{display_block} contains a number of @code{rune}'s. Generally +dynarr's of @code{display_line}'s are held by each window representing +the current display and the desired display. + +The @code{display_line} structures are tighly tied to buffers which +presents a problem for redisplay as this connection is bogus for the +modeline. Hence the @code{display_line} generation routines are +duplicated for generating the modeline. This means that the modeline +display code has many bugs that the standard redisplay code does not. + +The guts of @code{display_line} generation are in +@code{create_text_block}, which creates a single display line for the +desired locale. This incrementally parses the characters on the current +line and generates redisplay structures for each. + +Gutter redisplay is different. Because the data to display is stored in +a string we cannot use @code{create_text_block}. Instead we use +@code{create_text_string_block} which performs the same function as +@code{create_text_block} but for strings. Many of the complexities of +@code{create_text_block} to do with cursor handling and selective +display have been removed. + +@node Extents, Faces, The Redisplay Mechanism, Top @chapter Extents @menu @@ -7785,12 +8339,74 @@ position when moving linearly through the buffer. They rely on the stack-of-extents code, which does the heavy-duty algorithmic work of determining which extents overly a particular position. -@node Faces and Glyphs, Specifiers, Extents, Top -@chapter Faces and Glyphs +@node Faces, Glyphs, Extents, Top +@chapter Faces Not yet documented. -@node Specifiers, Menus, Faces and Glyphs, Top +@node Glyphs, Specifiers, Faces, Top +@chapter Glyphs + +Glyphs are graphical elements that can be displayed in XEmacs buffers or +gutters. We use the term graphical element here in the broadest possible +sense since glyphs can be as mundane as text to as arcane as a native +tab widget. + +In XEmacs, glyphs represent the uninstantiated state of graphical +elements, i.e. they hold all the information necessary to produce an +image on-screen but the image does not exist at this stage. + +Glyphs are lazily instantiated by calling one of the glyph +functions. This usually occurs within redisplay when +@code{Fglyph_height} is called. Instantiation causes an image-instance +to be created and cached. This cache is on a device basis for all glyphs +except glyph-widgets, and on a window basis for glyph widgets. The +caching is done by @code{image_instantiate} and is necessary because it +is generally possible to display an image-instance in multiple +domains. For instance if we create a Pixmap, we can actually display +this on multiple windows - even though we only need a single Pixmap +instance to do this. If caching wasn't done then it would be necessary +to create image-instances for every displayable occurrance of a glyph - +and every usage - and this would be extremely memory and cpu intensive. + +Widget-glyphs (a.k.a native widgets) are not cached in this way. This is +because widget-glyph image-instances on screen are toolkit windows, and +thus cannot be reused in multiple XEmacs domains. Thus widget-glyphs are +cached on a window basis. + +Any action on a glyph first consults the cache before actually +instantiating a widget. + +@section Widget-Glyphs in the MS-WIndows Environment + +To Do + +@section Widget-Glyphs in the X Environment + +Widget-glyphs under X make heavy use of lwlib for manipulating the +native toolkit objects. This is primarily so that different toolkits can +be supported for widget-glyphs, just as they are supported for features +such as menubars etc. + +Lwlib is extremely poorly documented and quite hairy so here is my +understanding of what goes on. + +Lwlib maintains a set of widget_instances which mirror the hierarchical +state of Xt widgets. I think this is so that widgets can be updated and +manipulated generically by the lwlib library. For instance +update_one_widget_instance can cope with multiple types of widget and +multiple types of toolkit. Each element in the widget hierarchy is updated +from its corresponding widget_instance by walking the widget_instance +tree recursively. + +This has desirable properties such as lw_modify_all_widgets which is +called from glyphs-x.c and updates all the properties of a widget +without having to know what the widget is or what toolkit it is from. +Unfortunately this also has hairy properrties such as making the lwlib +code quite complex. And of course lwlib has to know at some level what +the widget is and how to set its properties. + +@node Specifiers, Menus, Glyphs, Top @chapter Specifiers Not yet documented. diff --git a/man/lispref/hash-tables.texi b/man/lispref/hash-tables.texi index ddf239b..6d0b646 100644 --- a/man/lispref/hash-tables.texi +++ b/man/lispref/hash-tables.texi @@ -72,19 +72,25 @@ The structure syntax accepts the same keywords as @code{make-hash-table} (without the @code{:} character), as well as the additional keyword @code{data}, which specifies the initial hash table contents. -@defun make-hash-table &key @code{:size} @code{:test} @code{:type} @code{:rehash-size} @code{:rehash-threshold} +@defun make-hash-table &key @code{test} @code{size} @code{rehash-size} @code{rehash-threshold} @code{weakness} This function returns a new empty hash table object. -Keyword @code{:size} specifies the number of keys likely to be inserted. -This number of entries can be inserted without enlarging the hash table. - Keyword @code{:test} can be @code{eq}, @code{eql} (default) or @code{equal}. Comparison between keys is done using this function. If speed is important, consider using @code{eq}. When storing strings in the hash table, you will likely need to use @code{equal}. -Keyword @code{:type} can be @code{non-weak} (default), @code{weak}, -@code{key-weak} or @code{value-weak}. +Keyword @code{:size} specifies the number of keys likely to be inserted. +This number of entries can be inserted without enlarging the hash table. + +Keyword @code{:rehash-size} must be a float greater than 1.0, and specifies +the factor by which to increase the size of the hash table when enlarging. + +Keyword @code{:rehash-threshold} must be a float between 0.0 and 1.0, +and specifies the load factor of the hash table which triggers enlarging. + +Keyword @code{:weakness} can be @code{nil} (default), @code{t}, +@code{key} or @code{value}. A weak hash table is one whose pointers do not count as GC referents: for any key-value pair in the hash table, if the only remaining pointer @@ -104,12 +110,6 @@ that a key-value pair will be removed only if the value remains unmarked outside of weak hash tables. The pair will remain in the hash table if the value is pointed to by something other than a weak hash table, even if the key is not. - -Keyword @code{:rehash-size} must be a float greater than 1.0, and specifies -the factor by which to increase the size of the hash table when enlarging. - -Keyword @code{:rehash-threshold} must be a float between 0.0 and 1.0, -and specifies the load factor of the hash table which triggers enlarging. @end defun @defun copy-hash-table hash-table @@ -122,22 +122,16 @@ copied. This function returns the number of entries in @var{hash-table}. @end defun -@defun hash-table-size hash-table -This function returns the current number of slots in @var{hash-table}, -whether occupied or not. -@end defun - -@defun hash-table-type hash-table -This function returns the type of @var{hash-table}. -This can be one of @code{non-weak}, @code{weak}, @code{key-weak} or -@code{value-weak}. -@end defun - @defun hash-table-test hash-table This function returns the test function of @var{hash-table}. This can be one of @code{eq}, @code{eql} or @code{equal}. @end defun +@defun hash-table-size hash-table +This function returns the current number of slots in @var{hash-table}, +whether occupied or not. +@end defun + @defun hash-table-rehash-size hash-table This function returns the current rehash size of @var{hash-table}. This is a float greater than 1.0; the factor by which @var{hash-table} @@ -150,6 +144,11 @@ This is a float between 0.0 and 1.0; the maximum @dfn{load factor} of @var{hash-table}, beyond which the @var{hash-table} is enlarged by rehashing. @end defun +@defun hash-table-weakness hash-table +This function returns the weakness of @var{hash-table}. +This can be one of @code{nil}, @code{t}, @code{key} or @code{value}. +@end defun + @node Working With Hash Tables @section Working With Hash Tables @@ -181,6 +180,7 @@ that @var{function} may remhash or puthash the entry currently being processed by @var{function}. @end defun + @node Weak Hash Tables @section Weak Hash Tables @cindex hash table, weak @@ -220,5 +220,5 @@ of the table, regardless of how the key is referenced. Also see @ref{Weak Lists}. -Weak hash tables are created by specifying the @code{:type} keyword to +Weak hash tables are created by specifying the @code{:weakness} keyword to @code{make-hash-table}. diff --git a/man/xemacs-faq.texi b/man/xemacs-faq.texi index 76641d8..0c2eaa7 100644 --- a/man/xemacs-faq.texi +++ b/man/xemacs-faq.texi @@ -7,7 +7,7 @@ @finalout @titlepage @title XEmacs FAQ -@subtitle Frequently asked questions about XEmacs @* Last Modified: $Date: 1999/03/04 15:48:25 $ +@subtitle Frequently asked questions about XEmacs @* Last Modified: $Date: 1999/09/26 19:46:47 $ @sp 1 @author Tony Rossini @author Ben Wing @@ -580,7 +580,7 @@ that often result. Mail your questions to @email{xemacs-beta@@xemacs.org} and @unnumberedsubsec Q1.0.6: Where can I get help? Probably the easiest way, if everything is installed, is to use info, by -pressing @kbd{C-h i}, or selecting @code{Emacs Info} from the Help Menu. +pressing @kbd{C-h i}, or selecting @code{Manuals->Info} from the Help Menu. Also, @kbd{M-x apropos} will look for commands for you. @@ -1148,9 +1148,9 @@ directory called @file{sample.emacs}. Copy this file from there to your home directory and rename it @file{.emacs}. Then edit it to suit. Starting with 19.14, you may bring the @file{sample.emacs} into an -XEmacs buffer by selecting @samp{Help->Sample .emacs} from the menubar. -To determine the location of the @file{etc} directory type the command -@kbd{C-h v data-directory @key{RET}}. +XEmacs buffer by selecting @samp{Help->Samples->Sample .emacs} from the +menubar. To determine the location of the @file{etc} directory type the +command @kbd{C-h v data-directory @key{RET}}. @node Q1.4.2, Q1.4.3, Q1.4.1, Introduction @unnumberedsubsec Q1.4.2: Can I use the same @file{.emacs} with the other Emacs? @@ -1161,10 +1161,10 @@ show you how to handle different versions and flavors of Emacs. @node Q1.4.3, Q1.4.4, Q1.4.2, Introduction @unnumberedsubsec Q1.4.3: Any good tutorials around? -There's the XEmacs tutorial available from the Help Menu, or by typing -@kbd{C-h t}. To check whether it's available in a non-english language, -type @kbd{C-u C-h t TAB}, type the first letters of your preferred -language, then type @key{RET}. +There's the XEmacs tutorial available from the Help Menu under +@samp{Basics->Tutorials}, or by typing @kbd{C-h t}. To check whether +it's available in a non-english language, type @kbd{C-u C-h t TAB}, type +the first letters of your preferred language, then type @key{RET}. There's an Emacs Lisp tutorial at @@ -1580,7 +1580,7 @@ bad pointer, perhaps to a CD-ROM that is not inserted. No. The name @dfn{XEmacs} is unfortunate in the sense that it is @strong{not} an X Window System-only version of Emacs. Starting with -19.14 XEmacs has full color support on a color capable character +19.14 XEmacs has full color support on a color-capable character terminal. @node Q2.0.6, Q2.0.7, Q2.0.5, Installation @@ -5112,6 +5112,10 @@ This will then start a second shell. The key is that no buffer named rename-uniquely} to rename the @code{*shell*} buffer instead of @kbd{M-x rename-buffer}. +Alternately, you can set the variable @code{shell-multiple-shells}. +If the value of this variable is non-nil, each time shell mode is invoked, +a new shell is made + @node Q5.0.7, Q5.0.8, Q5.0.6, Miscellaneous @unnumberedsubsec Q5.0.7: Telnet from shell filters too much diff --git a/man/xemacs/cmdargs.texi b/man/xemacs/cmdargs.texi index c81812c..fe78398 100644 --- a/man/xemacs/cmdargs.texi +++ b/man/xemacs/cmdargs.texi @@ -155,10 +155,17 @@ concerning the package system, @xref{Startup Paths}.) @item -vanilla This is equivalent to @samp{-q -no-site-file -no-early-packages}. +@item -user-init-file @var{file} +Load @var{file} as your Emacs init file instead of @file{~/.emacs}. + +@item -user-init-directory @var{directory} +Use @var{directory} as the location of your early package hierarchies +and the various user-specific initialization files. + @item -user @var{user} @itemx -u @var{user} -Load @var{user}'s Emacs init file @file{~@var{user}/.emacs} instead of -your own. +Equivalent to +@samp{-user-init-file ~@var{user}/.emacs -user-init-directory ~@var{user}/.xemacs}. @end table diff --git a/man/xemacs/custom.texi b/man/xemacs/custom.texi index 28abc84..3b7ccdc 100644 --- a/man/xemacs/custom.texi +++ b/man/xemacs/custom.texi @@ -1539,18 +1539,13 @@ and some English to explain that string if necessary. When you start Emacs, it normally loads the file @file{.emacs} in your home directory. This file, if it exists, should contain Lisp code. It is called your initialization file or @dfn{init file}. Use the command -line switches @samp{-q} and @samp{-u} to tell Emacs whether to load an -init file (@pxref{Entering Emacs}). - -@vindex init-file-user -When the @file{.emacs} file is read, the variable @code{init-file-user} -says which user's init file it is. The value may be the null string or a -string containing a user's name. If the value is a null string, it means -that the init file was taken from the user that originally logged in. - -In all cases, @code{(concat "~" init-file-user "/")} evaluates to the -directory name of the directory where the @file{.emacs} file was looked -for. +line switch @samp{-q} to tell Emacs whether to load an +init file (@pxref{Entering Emacs}). Use the command line switch +@samp{-user-init-file} (@pxref{Command Switches}) to tell Emacs to load +a different file instead of @file{~/.emacs}. + +When the @file{.emacs} file is read, the variable @code{user-init-file} +says which init file was loaded. At some sites there is a @dfn{default init file}, which is the library named @file{default.el}, found via the standard search path for diff --git a/man/xemacs/packages.texi b/man/xemacs/packages.texi index fd4ac70..b147f9a 100644 --- a/man/xemacs/packages.texi +++ b/man/xemacs/packages.texi @@ -116,6 +116,17 @@ Hint to system administrators of multi-user systems: it might be a good idea to install all packages and not interfere with the wishes of your users. +If you can't find which package provides the feature you require, try +using the @code{package-get-package-provider} function. Eg., if you know +that you need @code{thingatpt}, type: + +@example +M-x package-get-package-provider RET thingatpt +@end example + +which will return something like (fsf-compat "1.06"). You can the use +one of the methods above for installing the package you want. + @subsection XEmacs and Installing Packages Normally, packages are installed over the network, using EFS diff --git a/man/xemacs/programs.texi b/man/xemacs/programs.texi index ff2b41e..dd9bf07 100644 --- a/man/xemacs/programs.texi +++ b/man/xemacs/programs.texi @@ -884,7 +884,7 @@ Move past next close parenthesis and re-indent @findex insert-parentheses @findex move-over-close-and-reindent The commands @kbd{M-(} (@code{insert-parentheses}) and @kbd{M-)} -(@code{move-over-close-@*and-reindent}) are designed to facilitate a style of +(@code{move-over-close-and-reindent}) are designed to facilitate a style of editing which keeps parentheses balanced at all times. @kbd{M-(} inserts a pair of parentheses, either together as in @samp{()}, or, if given an argument, around the next several sexps, and leaves point after the open diff --git a/modules/base64/Makefile b/modules/base64/Makefile index 43a70e3..4063805 100644 --- a/modules/base64/Makefile +++ b/modules/base64/Makefile @@ -25,6 +25,8 @@ MODTITLE="Encode objects in Base 64" all: $(MODNAME).ell +distclean: clean + clean: rm -f $(MODNAME).ell $(OBJS) base64_i.o base64_i.c diff --git a/modules/ldap/Makefile b/modules/ldap/Makefile index e0f1976..6e775ec 100644 --- a/modules/ldap/Makefile +++ b/modules/ldap/Makefile @@ -25,6 +25,8 @@ MODTITLE="LDAP Client Interface for XEmacs" all: $(MODNAME).ell +distclean: clean + clean: rm -f $(MODNAME).ell $(OBJS) eldap_i.o eldap_i.c diff --git a/modules/sample/Makefile b/modules/sample/Makefile index 09390d1..1e0849c 100644 --- a/modules/sample/Makefile +++ b/modules/sample/Makefile @@ -25,6 +25,8 @@ MODTITLE="Sample loadable module" all: $(MODNAME).ell +distclean: clean + clean: rm -f $(MODNAME).ell $(OBJS) sample_i.o sample_i.c diff --git a/modules/zlib/Makefile b/modules/zlib/Makefile index cb7aecd..45076e3 100644 --- a/modules/zlib/Makefile +++ b/modules/zlib/Makefile @@ -25,6 +25,8 @@ MODTITLE="ZLIB compression library interface" all: $(MODNAME).ell +distclean: clean + clean: rm -f $(MODNAME).ell $(OBJS) zlib_i.o zlib_i.c diff --git a/nt/ChangeLog b/nt/ChangeLog index 9d66963..f1d7e42 100644 --- a/nt/ChangeLog +++ b/nt/ChangeLog @@ -1,3 +1,29 @@ +1999-11-10 XEmacs Build Bot + + * XEmacs 21.2.20 is released + +1999-10-07 Norbert Koch + + * xemacs.mak: Ignore return code of 'del' calls. Use a make + variable for 'del'. + +1999-09-26 Adrian Aichner + + * xemacs.mak (all): Update $(LISP)/auto-autoloads.elc? and + $(LISP)/custom-load.el using XEmacs itself, like xemacs-packages + do. + ($(LISP)\auto-autoloads.el): Add new rule. + ($(LISP)\custom-load.el): Ditto. + +1999-08-04 Andy Piper + + * xemacs.mak (HAVE_WIDGETS): add define to appropriate places. + +1999-07-26 Adrian Aichner + + * xemacs.mak ($(MANDIR)\lispref\lispref.texi): Replace bad + dependency. + 1999-07-30 XEmacs Build Bot * XEmacs 21.2.19 is released diff --git a/nt/xemacs.mak b/nt/xemacs.mak index 31733b5..7331255 100644 --- a/nt/xemacs.mak +++ b/nt/xemacs.mak @@ -30,6 +30,9 @@ MODULES=$(XEMACS)\modules NT=$(XEMACS)\nt OUTDIR=$(NT)\obj +# Define a variable for the 'del' command to use +DEL=-del + # Program name and version !include "..\version.sh" @@ -117,6 +120,9 @@ HAVE_MSW_C_DIRED=1 !if !defined(HAVE_NATIVE_SOUND) HAVE_NATIVE_SOUND=1 !endif +!if !defined(HAVE_WIDGETS) +HAVE_WIDGETS=1 +!endif !if !defined(DEBUG_XEMACS) DEBUG_XEMACS=0 !endif @@ -311,6 +317,9 @@ MSW_DEFINES=$(MSW_DEFINES) -DHAVE_DIALOGS MSW_DIALOG_SRC=$(XEMACS)\src\dialog.c $(XEMACS)\src\dialog-msw.c MSW_DIALOG_OBJ=$(OUTDIR)\dialog.obj $(OUTDIR)\dialog-msw.obj !endif +!if $(HAVE_WIDGETS) +MSW_DEFINES=$(MSW_DEFINES) -DHAVE_WIDGETS +!endif !if $(HAVE_NATIVE_SOUND) MSW_DEFINES=$(MSW_DEFINES) -DHAVE_NATIVE_SOUND !endif @@ -881,7 +890,7 @@ $(TEMACS): $(TEMACS_INCLUDES) $(TEMACS_OBJS) !if $(DEBUG_XEMACS) @dir /b/s $(OUTDIR)\*.sbr > bscmake.tmp bscmake -nologo -o$(TEMACS_BROWSE) @bscmake.tmp - @del bscmake.tmp + @$(DEL) bscmake.tmp !endif link.exe @<< $(TEMACS_LFLAGS) $(TEMACS_OBJS) $(TEMACS_LIBS) @@ -981,7 +990,7 @@ $(MANDIR)\xemacs\xemacs.texi: \ $(MANDIR)\xemacs\text.texi \ $(MANDIR)\xemacs\trouble.texi \ $(MANDIR)\xemacs\undo.texi \ - $(MANDIR)\xemacs\windows.texi \ + $(MANDIR)\xemacs\windows.texi $(INFODIR)\lispref.info: $(MANDIR)\lispref\lispref.texi @@ -1016,7 +1025,8 @@ $(MANDIR)\lispref\lispref.texi: \ $(MANDIR)\lispref\hash-tables.texi \ $(MANDIR)\lispref\help.texi \ $(MANDIR)\lispref\hooks.texi \ - $(MANDIR)\lispref\index.texi \ + $(MANDIR)\lispref\index.perm \ + $(MANDIR)\lispref\index.unperm \ $(MANDIR)\lispref\internationalization.texi \ $(MANDIR)\lispref\intro.texi \ $(MANDIR)\lispref\keymaps.texi \ @@ -1054,7 +1064,7 @@ $(MANDIR)\lispref\lispref.texi: \ $(MANDIR)\lispref\windows.texi \ $(MANDIR)\lispref\x-windows.texi \ $(MANDIR)\lispref\index.unperm \ - $(MANDIR)\lispref\index.perm \ + $(MANDIR)\lispref\index.perm $(INFODIR)\new-users-guide.info: $(MANDIR)\new-users-guide\new-users-guide.texi @@ -1070,7 +1080,7 @@ $(MANDIR)\new-users-guide\new-users-guide.texi: \ $(MANDIR)\new-users-guide\edit.texi \ $(MANDIR)\new-users-guide\modes.texi \ $(MANDIR)\new-users-guide\xmenu.texi \ - $(MANDIR)\new-users-guide\enter.texi \ + $(MANDIR)\new-users-guide\enter.texi $(INFODIR)\internals.info: $(MANDIR)\internals\internals.texi @@ -1079,7 +1089,7 @@ $(INFODIR)\internals.info: $(MANDIR)\internals\internals.texi $(MANDIR)\internals\internals.texi: \ $(MANDIR)\internals\index.unperm \ - $(MANDIR)\internals\index.perm \ + $(MANDIR)\internals\index.perm info: $(INFO_FILES) @@ -1093,7 +1103,7 @@ info: $(INFO_FILES) LOADPATH=$(LISP) $(DOC): $(LIB_SRC)\make-docfile.exe - -del $(DOC) + $(DEL) $(DOC) $(TEMACS) -batch -l $(TEMACS_DIR)\..\lisp\make-docfile.el -- -o $(DOC) -i $(XEMACS)\site-packages $(LIB_SRC)\make-docfile.exe -a $(DOC) -d $(TEMACS_SRC) $(DOC_SRC1) $(LIB_SRC)\make-docfile.exe -a $(DOC) -d $(TEMACS_SRC) $(DOC_SRC2) @@ -1123,8 +1133,9 @@ dump-xemacs: $(TEMACS) #------------------------------------------------------------------------------ # use this rule to build the complete system -all: $(XEMACS)\Installation $(OUTDIR)\nul $(LASTFILE) $(LWLIB) $(LIB_SRC_TOOLS) $(RUNEMACS) \ - $(TEMACS) update-elc $(DOC) dump-xemacs info +all: $(XEMACS)\Installation $(OUTDIR)\nul $(LASTFILE) $(LWLIB) \ + $(LIB_SRC_TOOLS) $(RUNEMACS) $(TEMACS) update-elc $(DOC) dump-xemacs \ + $(LISP)/auto-autoloads.el $(LISP)/custom-load.el info temacs: $(TEMACS) @@ -1134,7 +1145,7 @@ install: all @echo PlaceHolder > PlaceHolder @xcopy /q PROBLEMS "$(INSTALL_DIR)\" @xcopy /q PlaceHolder "$(INSTALL_DIR)\lock\" - @del "$(INSTALL_DIR)\lock\PlaceHolder" + @$(DEL) "$(INSTALL_DIR)\lock\PlaceHolder" @xcopy /q $(LIB_SRC)\*.exe "$(INSTALL_DIR)\$(EMACS_CONFIGURATION)\" @copy $(LIB_SRC)\DOC "$(INSTALL_DIR)\$(EMACS_CONFIGURATION)" @copy $(CONFIG_VALUES) "$(INSTALL_DIR)\$(EMACS_CONFIGURATION)" @@ -1145,50 +1156,50 @@ install: all @xcopy /e /q $(XEMACS)\lisp "$(INSTALL_DIR)\lisp\" @echo Making skeleton package tree in $(PACKAGE_PREFIX) ... @xcopy /q PlaceHolder "$(PACKAGE_PREFIX)\site-packages\" - @del "$(PACKAGE_PREFIX)\site-packages\PlaceHolder" + @$(DEL) "$(PACKAGE_PREFIX)\site-packages\PlaceHolder" @xcopy /q PlaceHolder "$(PACKAGE_PREFIX)\mule-packages\" - @del "$(PACKAGE_PREFIX)\mule-packages\PlaceHolder" + @$(DEL) "$(PACKAGE_PREFIX)\mule-packages\PlaceHolder" @xcopy /q PlaceHolder "$(PACKAGE_PREFIX)\xemacs-packages\" - @del "$(PACKAGE_PREFIX)\xemacs-packages\PlaceHolder" - @del PlaceHolder + @$(DEL) "$(PACKAGE_PREFIX)\xemacs-packages\PlaceHolder" + @$(DEL) PlaceHolder distclean: - del *.bak - del *.orig - del *.rej - del *.tmp - del $(XEMACS)\Installation + $(DEL) *.bak + $(DEL) *.orig + $(DEL) *.rej + $(DEL) *.tmp + $(DEL) $(XEMACS)\Installation cd $(OUTDIR) - del *.lib - del *.obj - del *.pdb - del *.res - del *.sbr + $(DEL) *.lib + $(DEL) *.obj + $(DEL) *.pdb + $(DEL) *.res + $(DEL) *.sbr cd $(XEMACS)\$(TEMACS_DIR) - del config.h - del paths.h - del Emacs.ad.h - del *.bak - del *.orig - del *.rej - del *.exe - del *.map - del *.bsc - del *.pdb + $(DEL) config.h + $(DEL) paths.h + $(DEL) Emacs.ad.h + $(DEL) *.bak + $(DEL) *.orig + $(DEL) *.rej + $(DEL) *.exe + $(DEL) *.map + $(DEL) *.bsc + $(DEL) *.pdb cd $(LIB_SRC) - del DOC - del *.bak - del *.orig - del *.rej - del *.exe - del *.obj - del *.pdb - del *.res - del $(CONFIG_VALUES) + $(DEL) DOC + $(DEL) *.bak + $(DEL) *.orig + $(DEL) *.rej + $(DEL) *.exe + $(DEL) *.obj + $(DEL) *.pdb + $(DEL) *.res + $(DEL) $(CONFIG_VALUES) cd $(LISP) - -del /s /q *.bak *.elc *.orig *.rej + $(DEL) /s /q *.bak *.elc *.orig *.rej cd $(INFODIR) - del *.info* $(MANDIR)\internals\index.texi $(MANDIR)\lispref\index.texi + $(DEL) *.info* $(MANDIR)\internals\index.texi $(MANDIR)\lispref\index.texi depend: mkdepend -f xemacs.mak -p$(OUTDIR)\ -o.obj -w9999 -- $(TEMACS_CPP_FLAGS) -- $(DOC_SRC1) $(DOC_SRC2) $(DOC_SRC3) $(DOC_SRC4) $(DOC_SRC5) $(DOC_SRC6) $(DOC_SRC7) $(DOC_SRC8) $(DOC_SRC9) $(LASTFILE_SRC)\lastfile.c $(LIB_SRC)\make-docfile.c $(LIB_SRC)\run.c @@ -1257,6 +1268,9 @@ XEmacs $(XEMACS_VERSION_STRING) $(xemacs_codename:"=\") configured for `$(EMACS_ !if $(HAVE_DIALOGS) Compiling in support for dialogs. !endif +!if $(HAVE_WIDGETS) + Compiling in support for widgets. +!endif !if $(HAVE_NATIVE_SOUND) Compiling in support for native sounds. !endif @@ -1286,5 +1300,20 @@ XEmacs $(XEMACS_VERSION_STRING) $(xemacs_codename:"=\") configured for `$(EMACS_ @type $(XEMACS)\Installation @echo -------------------------------------------------------------------- +# Update auto-autoloads.el and custom-load.el similar to what +# XEmacs.rules does for xemacs-packages. +VANILLA=-vanilla +FORCE: +$(LISP)\auto-autoloads.el: FORCE + $(PROGNAME) $(VANILLA) -batch \ + -l autoload -f batch-update-directory $(LISP) + $(PROGNAME) $(VANILLA) -batch \ + -f batch-byte-compile $@ + @$(DEL) $(LISP)\auto-autoloads.el~ + +$(LISP)\custom-load.el: FORCE + $(PROGNAME) $(VANILLA) -batch -l cus-dep \ + -f Custom-make-dependencies $(LISP) + # DO NOT DELETE THIS LINE -- make depend depends on it. diff --git a/src/.cvsignore b/src/.cvsignore index 17d59ef..afa30ff 100644 --- a/src/.cvsignore +++ b/src/.cvsignore @@ -10,3 +10,4 @@ temacs xemacs SATISFIED update-elc.stamp +*.so.* \ No newline at end of file diff --git a/src/ChangeLog b/src/ChangeLog index c00a101..91f2864 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -27,6 +27,1314 @@ * faces.h (FACE_CACHEL_FONT): Use `MIN_LEADING_BYTE' instead of 128. +1999-11-10 XEmacs Build Bot + + * XEmacs 21.2.20 is released + +1999-11-04 Martin Buchholz + + * mule-ccl.c (ccl_driver): Warning suppression + +1999-11-01 SL Baur + + * emacs.c (main_1): Guard call to reinit_vars_of_debug when not + building a debugged XEmacs. + +1999-10-28 Andreas Jaeger + + * src/emacs.c (main_1): Don't set the malloc hooks if using + DOUG_LEA_MALLOC. + +1999-10-30 Olivier Galibert + + * alloc.c (pdump_dump_rtables): Don't forget to dump the last + registered type. + (pdump): Ditto. + +1999-10-25 Olivier Galibert + + * emacs.c (main_1): Call reinit_vars_of_scrollbar_x. + + * symsinit.h: Declare reinit_vars_of_scrollbar_x. + +1999-10-25 Martin Buchholz + + * redisplay.h (CLASS_RESET_CHANGED_FLAGS): + (GLOBAL_RESET_CHANGED_FLAGS): + (CLASS_REDISPLAY_FLAGS_CHANGEDP): + (RESET_CHANGED_SET_FLAGS): + Fix C++ compile errors/warnings. + These macros were just a tad too clever. + + * process-unix.c (unix_open_network_stream): + * objects-x.c (allocate_nearest_color): + * mule-charset.c (vars_of_mule_charset): + * fileio.c (Ffile_truename): + * file-coding.c (vars_of_file_coding): + Fix compile errors/warnings. + + * alloc.c (xstrdup): Use fact that memcpy returns its first arg. + (allocate_lisp_storage): Simplify. + +1999-10-24 Olivier Galibert + + * conslots.h: Add defines with first and last slot names. + * bufslots.h: Add defines with first and last slot names. + + * buffer.c (common_init_complex_vars_of_buffer): Renamed from + reinit_complex_vars_of_buffer + (reinit_complex_vars_of_buffer): Reset the slots to the dumped + value. + (complex_vars_of_buffer): Dump the slots values. + + * console.c (common_init_complex_vars_of_console): Renamed from + reinit_complex_vars_of_console + (reinit_complex_vars_of_console): Reset the slots to the dumped + value. + (complex_vars_of_console): Dump the slots values. + + * alloc.c: Rename reloc_table to pdump_reloc_table, rt_list to + pdump_rt_list and move them at the beginning of the file. + (gc_sweep): Unmark pdumped objects after the sweep phase. + (pdump_dump_rtables): Change a bare 256 to + last_lrecord_type_index_assigned. Add a separator between the + adresses or lrecords and the ones of C structs in the dump file. + (pdump_load): Cope with the new separator and the renamings. Stop + looking for the hash tables list after it has been found (duh!). + +1999-10-24 Robert Bihlmeyer + + * sound.c: support HAVE_ESD_SOUND + + * miscplay.c: + * miscplay.h: + * linuxplay.c: Move large part of linuxplay to generalized file + miscplay. Make it platform independent. + + * esd.c: New file + +1999-10-24 Adrian Aichner + + * lisp.h (Dynarr_declare): Fix boo-boo. + +1999-10-24 Olivier Galibert + + * process-unix.c (allocate_pty): Fix HAVE_GETPT. + * process.h: Ditto. + +1999-10-24 Jan Vroonhof + + * redisplay.c (start_with_line_at_pixpos): Remove assert(cur_elt + >=0). Handle the cur_elt == 0 case. + +1999-10-24 Jan Vroonhof + + * unexelf.c: Merge Martin's c++ fixes back in + +1999-10-20 Jan Vroonhof + + * unexelf.c (unexec): Only copy the global offset + table from memory on sgi machines. + +1999-08-13 Alexandre Oliva , Vin Shelton + + * unexelf.c: Enable GNU/Linux/alpha to build with gcc 2.95 by + adding support for an sbss section. Get IRIX 5.2 to build using + unexelf.c. + + * m/iris4d.h: Use unexelf.o for unexec. + + * m/iris5d.h: Use unexelf.o for unexec. + +1999-10-24 Jan Vroonhof + + * unexelf.c: Revert to 21.1 version + +1999-08-28 Jan Vroonhof + + * window.c (Fwindow_truncated_p): New function. + +1999-08-25 Jonathan Marten + + * window.c (window_truncation_on): Always return 0 for minibuffer + windows, to enable auto scrolling. + +1999-10-24 Neal Becker + * process.h: Unix98 PTY support + +1999-10-17 Jan Vroonhof + + * fileio.c (Ffile_truename): Do proper mule decoding on + the argument to xrealpath() + +1999-08-19 Stephen Tse + + * process-unix.c (unix_open_network_stream): Add udp network + support; rename variable Qtcpip to Qtcp, parameter family to + protocol for consistency with Qudp. + + * process-nt.c (nt_open_network_stream): Rename variable Qtcpip to + Qtcp, parameter family to protocol for consistency with Qudp. + + * process.c (global_variables): Add a new variable Qudp for udp + network support; rename variable Qtcpip to Qtcp for consistency + with Qudp. + (Fopen_network_stream_internal): Rename parameter FAMILY to + PROTOCOL for consistency; fix a minor typo and add an explanation + in docstring for udp programming. + (Fopen_multicast_group_internal): Fix a minor typo in docstring. + (syms_of_process): Add a new variable Qudp for udp network + support; rename variable Qtcpip to Qtcp for consistency with Qudp. + + * process.h (extern_variables): Add a new variable Qudp for udp + network support; rename variable Qtcpip to Qtcp for consistency + with Qudp. + + * procimpl.h: Add a new variable Qudp for udp network support; + rename variable Qtcpip to Qtcp for consistency with Qudp. + (struct process_methods): Rename parameter family to protocol. + + +1999-10-24 Olivier Galibert + + * alloc.c (pdump_make_hash): Divide pointers by 8 for a better hash. + +1999-10-23 Olivier Galibert + + * lrecord.h (struct lrecord_header): Removed dumped flags. + + * dynarr.c: Use DUMPEDP instead of dumped flag. + + * lisp.h (DUMPEDP): Added. Removed dumped flag from dynarr. + + * alloc.c: Removed hash_next linked list pointer. + + * *.c *.h: Removed markobj and mark_object parameters, removed GC_ + and XGC macros. + +1999-10-14 Andy Piper + + * redisplay-x.c (x_output_shadows): fix dodgy maths for border + calculations. + + * gutter.c (output_gutter): be more accurate about the area to be + cleared since X seems to manage to do the clear after drawing the + border. + + * redisplay.h (RESET_CHANGED_FLAGS): new macro for setting + redisplay flags as a group. + (RESET_CHANGED_SET_FLAGS): ditto. + (CLASS_RESET_CHANGED_FLAGS): ditto. + (GLOBAL_RESET_CHANGED_FLAGS): ditto. + (REDISPLAY_FLAGS_CHANGEDP): new macro for testing redisplay flags + as a group. + (CLASS_REDISPLAY_FLAGS_CHANGEDP): ditto. + (GLOBAL_REDISPLAY_FLAGS_CHANGEDP): ditto. + + * redisplay.c (redisplay_frame): use CLASS_RESET_CHANGED_FLAGS + instead of setting flags individually. + (redisplay_device): ditto CLASS_REDISPLAY_FLAGS_CHANGEDP. + (redisplay_device): ditto. + (redisplay_device): ditto CLASS_RESET_CHANGED_FLAGS. + (redisplay_without_hooks): ditto GLOBAL_REDISPLAY_FLAGS_CHANGEDP. + (redisplay_without_hooks): ditto CLASS_REDISPLAY_FLAGS_CHANGEDP. + (redisplay_without_hooks): ditto. + (redisplay_without_hooks): ditto GLOBAL_RESET_CHANGED_FLAGS. + + * redisplay-x.c (x_output_string): unmap subwindows in the area. + (x_output_blank): ditto. + + * redisplay-output.c (redisplay_output_display_block): don't unmap + subwindows in case layout optimization can avoid it. + (redisplay_output_subwindow): unmap subwindows in the area. + (redisplay_output_layout): optimize the output of layouts - only + output glyphs that have changed if nothing else of redisplay + significance has occurred. + (redisplay_output_pixmap): change args to + redisplay_clear_clipped_region. + (redisplay_clear_clipped_region): allow the clipped region to be + cleared of all subwindows except the one passed in. + + * redisplay-msw.c (mswindows_output_blank): unmap subwindows in + the area. + (mswindows_output_cursor): ditto. + (mswindows_output_string): ditto. + + * gutter.c (calculate_gutter_size): if the window buffer is nil + then don't continue. + (update_frame_gutters): be more lenient about when we actually + update the gutter. Layout optimization makes this + non-costly. Cache redisplay flags that we want to temporarily + ignore. + + * glyphs.c (Fglyph_animated_timeout_handler): handle image + specific timeouts rather than iterating over the instance cache. + (glyph_animated_timeout_mapper): deleted. + (add_glyph_animated_timeout): use a weak list to hold onto the + image so that it can be GC'ed. + (disable_glyph_animated_timeout): disable a specific timeout. + (vars_of_glyphs): disable-animated-pixmaps is a new boolean for + controlling whether pixmaps are animated or not. + + * glyphs-msw.c (mswindows_finalize_image_instance): make sure the + image timeout gets disabled when the image gets freed. + + * glyphs-eimage.c (gif_instantiate): remove meaningless + comment. Cope with timeouts specified in the gif extension block. + + * event-msw.c (vars_of_event_mswindows): new variable + mswindows-meta-activates-menu. + (mswindows_wnd_proc): only goto defproc with VK_MENU if the user + wants it. + + * glyphs-x.c (x_finalize_image_instance): delete mask first so + that we can compare with image. + +1999-10-14 Jonathan Harris + + * event-msw.c (mswindows_key_to_emacs_keysym): + Recognise keypad keys as different from normal keys. + +1999-10-14 Didier Verna + + * glyphs-x.c (x_finalize_image_instance): avoid freeing null pixmaps. + +1999-10-10 Olivier Galibert + + * symbols.c (init_symbols_once_early): dump Vquit_flag. + + * symsinit.h: Updated. + + * ntproc.c (vars_of_ntproc): Use defsymbol. + + * emacs.c (main_1): Updated reinit calls. + + * lisp.h: Removed Fpurecopy and pure_put declarations. + * fns.c: Removed pure_put. + + * eval.c (Fdefvar): pure_put -> Fput + (Fdefconst): Ditto. + * frame-x.c (init_x_prop_symbols): Ditto. + * symbols.c (deferror): Ditto. + + * alloc.c (Fmake_byte_code): Remove Fpurecopy call. + * buffer.c (vars_of_buffer): Ditto. + * bytecode.c (Ffetch_bytecode): Ditto. + (optimize_compiled_function): Ditto. + * emacs.c (vars_of_emacs): Ditto. + * emodules.c (vars_of_module): Ditto. + * eval.c (define_function): Ditto. + (Fautoload): Ditto. + * frame.c (vars_of_frame): Ditto. + * intl.c (Fset_domain): Ditto. + * lread.c (load_force_doc_string_unwind): Ditto. + * menubar.c (vars_of_menubar): Ditto. + * minibuf.c (reinit_complex_vars_of_minibuf): Ditto. + + * debug.c (reinit_vars_of_debug): Extracted. + * device-x.c (reinit_vars_of_device_x): Ditto. + * emodules.c (reinit_vars_of_module): Ditto. + * font-lock.c (reinit_vars_of_font_lock): Ditto. + * glyphs-widget.c (reinit_vars_of_glyphs_widget): Ditto. + * glyphs.c (reinit_vars_of_glyphs): Ditto. + * gui-x.c (reinit_vars_of_gui_x): Ditto. + * insdel.c (reinit_vars_of_insdel): Ditto. + * menubar-x.c (reinit_vars_of_menubar_x): Ditto. + * minibuf.c (reinit_complex_vars_of_minibuf): Ditto. + * mule-wnnfns.c (reinit_vars_of_mule_wnn): Ditto. + * print.c (reinit_vars_of_print): Ditto. + * redisplay.c (reinit_vars_of_redisplay): Ditto. + * select-x.c (reinit_vars_of_xselect): Ditto. + * undo.c (reinit_vars_of_undo): Ditto. + +1999-10-10 Olivier Galibert + + * symsinit.h: Updated declarations, see other ChangeLog entries. + + * redisplay.c (init_redisplay): Ensure proper reinitialisation. + + * lrecord.h (XD_DYNARR_DESC): Introduce XD_INT_RESET and use it. + + * glyphs.c: Add the ii_keyword_entry and related descriptions. + Fix the image_instantiator_methods one. + + * file-coding.c: Plonk all data that needs to be dumped in a + dynamically allocated structure. + + * extents.c (reinit_vars_of_extents): Extracted from + vars_of_extents. + + * event-stream.c (vars_of_event_stream): Don't staticpro when + pdump_wire is enough. + + * event-msw.c (reinit_vars_of_event_mswindows): Extracted from + vars_of_event_mswindows. + + * event-Xt.c (reinit_vars_of_event_Xt): Extracted from + vars_of_event_Xt. + + * eval.c (vars_of_eval): Don't staticpro when pdump_wire is enough. + + * emacs.c (main_1): Added some reinit calls. + + * device-x.c (reinit_console_type_create_device_x): Extracted from + console_type_create_device_x. + + * console.h: Declare the console_type_entry_dynarr description. + + * console.c: Unstatic the console_type_entry_dynarr description. + + * alloc.c: Removed some dubious comments. Handle XD_INT_RESET. + +1999-10-07 Olivier Galibert + + * symsinit.h: Updated declarations, see other ChangeLog entries. + + * minibuf.c (reinit_complex_vars_of_minibuf): Extracted from + complex_vars_of_minibuf. + + * lrecord.h: Removed XD_PARENT_INDIRECT (unused and + unimplemented), added XD_LO_LINK. + + * lisp.h (pdump_wire_list): Add declaration. + + * glyphs.h (INITIALIZE_DEVICE_IIFORMAT): Fix bug found by Andy. + (INITIALIZE_IMAGE_INSTANTIATOR_FORMAT): Fix stupid bug. + (REINITIALIZE_IMAGE_INSTANTIATOR_FORMAT): Remove, useless once the + stupid bug fixed. + + * glyphs.c (reinit_image_instantiator_format_create): Remove. + + * glyphs-x.c (reinit_image_instantiator_format_create_glyphs_x): + Remove. + + * glyphs-widget.c + (reinit_image_instantiator_format_create_glyphs_widget): Remove. + + * glyphs-msw.c + (reinit_image_instantiator_format_create_glyphs_mswindows): + Remove. + + * glyphs-eimage.c + (reinit_image_instantiator_format_create_glyphs_eimage): Remove. + + * frame.c (Fmake_frame): Don't reset the face cache when using the + stream device. + + * file-coding.c: Dumped the_codesys_prop_dynarr and added all + relevant descriptions. + + * events.c (reinit_vars_of_events): Extracted from vars_of_events. + + * eval.c: The subr is _not_ a lcrecord. + + * emacs.c (main_1): Call vars_of_specifier early before any + specifier creation (e.g in vars_of_glyphs, at least). Remove the + useless reinit_image_instantiator_format*. Add + reinit_vars_of_events and reinit_complex_vars_of_minibuf. Add + calls to lstream_type_create* and process_type_create*. + + * elhash.c: Dump Vall_weak_hash_tables correctly. + + * data.c: Dump Vall_weak_lists correctly. + + * console.c: Fix description. + + * console-stream.c (init_console_stream): Do initializations + correctly in the pdump case. + + * chartab.c: Fix description. Dump Vall_syntax_tables correctly. + (Fcopy_char_table): Link into Vall_syntax_tables. + + * alloc.c (pdump_wire_list): Added. + (Fgarbage_collect): Fix loop in stats couting missing the last + lrecord type. + (pdump_register_sub): Added XD_LO_LINK. + (pdump_dump_data): Ditto. Fixed XD_LO_RESET_NIL forgttting the + counter. + (pdump_reloc_one): Ditto. + (pdump_scan_by_alignement): Use last_lrecord_type_index_assigned + instead of 256. + (pdump_dump_wired): Added lists. + (pdump): Use last_lrecord_type_index_assigned instead of 256. + Dump last_lrecord_type_index_assigned value. Fix minor bugs. + +1999-10-07 Andy Piper + + * glyphs-msw.c (mswindows_finalize_image_instance): zero out + bitmap slices. + + * glyphs-x.c (x_finalize_image_instance): fix FMW problem. + +1999-10-06 Andy Piper + + * elhash.c (resize_hash_table): Correct reference to lrecord_header. + +1999-10-06 Damon Lipparelli + + * elhash.h: forward declare Lisp_Hash_Table. + +1999-10-06 Andy Piper + + * glyphs.c (Fset_image_instance_property): mark glyphs as dirty + after setting an image instance property. + +1999-10-05 Andy Piper + + * gutter.c (update_frame_gutters): output gutters if + windows_changed is set. This is the only way of catching changes + in selected window which obviously can affect the specifiers. + + * redisplay.c: new state flags, subwindows_state_changed and + subwindows_state_changed set. + (redisplay_window): use them. + (redisplay_device): ditto. + (redisplay_without_hooks): ditto. + (redisplay_frame): ditto. Reset subwindow cachels if + subwindows_changed is set. + (redisplay_window): call mark_glyph_cachels_as_clean after + redisplaying. + + * redisplay-x.c (x_output_x_pixmap): select correct + pixmap image for display depending on the currently selected + slice. + + * redisplay-output.c (compare_runes): check dirtiness when + checking RUNE_DGLYPH runes. + (compare_display_blocks): relax invalidation of display blocks + since we can now detect whether individual glyphs have changed or + not. + + * redisplay-msw.c (mswindows_output_dibitmap): select correct + bitmap image for display depending on the currently selected + slice. + + * glyphs.h (struct Lisp_Image_Instance): add a dirty flag. + (IMAGE_INSTANCE_DIRTYP): new macro. + (XIMAGE_INSTANCE_DIRTYP): ditto. + (MARK_IMAGE_INSTANCE_CHANGED): ditto. + (GLYPH_DIRTYP): ditto. + (XGLYPH_DIRTYP): ditto. + (MARK_GLYPH_CHANGED): ditto. + (GLYPH_CACHEL_DIRTYP): ditto. + (struct glyph_cachel): add a dirty flag. + + * glyphs.c (update_frame_subwindows): Don't update on + glyphs_changed. + (glyph_animated_timeout_mapper): new function. Map over the + instance cache lookinng for animated images to update. + (Fglyph_animated_timeout_handler): new function. Lisp callback for + handling animated image timeout events. + (disable_glyph_animated_timeout): new function. Add the animated + image timeout. + (disable_glyph_animated_timeout): new function. Remove the + animated image timeout. + (syms_of_glyphs): initialize Qglyph_animated_timeout_handler and + friends. + (vars_of_glyphs): initialize Vglyph_animated_ticker. + (image_instance_equal): add the currently displayed slice. + (image_instance_hash): ditto. + (allocate_glyph): initialize dirty flag. + (glyph_width): rename glyph -> glyph_or_image. + (glyph_height_internal): ditto. + (glyph_dirty_p): new function. Determine whether the image + instance in the domain and/or glyph is dirty. + (set_glyph_dirty_p): set the dirtiness. + (update_glyph_cachel_data): take dirtiness into account. Pass the + image instance we are interested in to glyph_width and friends. + (get_glyph_cachel_index): make non-static. Always call + update_glyph_cachel_data. + (mark_glyph_cachels_as_not_updated): meaningless formatting + change. + (mark_glyph_cachels_as_clean): new function. Clean dirtiness from + glyph cachels. + + * glyphs-x.h (struct x_image_instance_data): change + pixmap to a list of pixmaps. + (IMAGE_INSTANCE_X_PIXMAP_SLICE): new macro. + (IMAGE_INSTANCE_X_PIXMAP_SLICES): ditto. + (XIMAGE_INSTANCE_X_PIXMAP_SLICE): ditto. + (XIMAGE_INSTANCE_X_PIXMAP_SLICES): ditto. + + * glyphs-x.c (x_finalize_image_instance): make sure multi pixmap + images get deleted properly. + (init_image_instance_from_x_image): add slices paramater and use + it to initialize x_image_instance_data correctly. + (image_instance_add_x_image): new function. Add new pixmaps to our + set of instantiated pixmaps for an image. Used by animated images. + (x_init_image_instance_from_eimage): add a slices + parameter. Instantiate all images from the eimage. + (x_xpm_instantiate): update use of + init_image_instance_from_x_image. + (init_image_instance_from_xbm_inline): ditto. + (x_initialize_pixmap_image_instance): add slices paramater and use + it to allocate x_image_instance_data correctly. + + * glyphs-msw.h (struct mswindows_image_instance_data): change + bitmap to a list of bitmaps. + (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE): new macro. + (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES): ditto. + (XIMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE): ditto. + (XIMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES): ditto. + + * glyphs-msw.c (init_image_instance_from_dibitmap): add slices + paramater and use it to initialize mswindows_image_instance_data + correctly. + (image_instance_add_dibitmap): new function. Add new bitmaps to + our set of instantiated bitmaps for an image. Used by animated + images. + (mswindows_init_image_instance_from_eimage): add a slices + parameter. Instantiate all images from the eimage. + (mswindows_xpm_instantiate): update use of + init_image_instance_from_dibitmap. + (bmp_instantiate): ditto. + (init_image_instance_from_xbm_inline): ditto. + (mswindows_finalize_image_instance): make sure all the bitmap + slices get deleted. + (mswindows_initialize_dibitmap_image_instance): add slices + paramater and use it to allocate mswindows_image_instance_data + correctly. + + * glyphs-eimage.c (jpeg_instantiate): give extra paramter to + init_image_instance_from_eimage. + (png_instantiate): ditto. + (tiff_instantiate): ditto. + (gif_instantiate): allocate bitmaps for all gif slices not just + the first one. + + * device.h (struct device): add subwindows_state_changed flag. + (MARK_DEVICE_SUBWINDOWS_STATE_CHANGED): new macro. + (MARK_DEVICE_FRAMES_GLYPHS_CHANGED): ditto. + + * console.h (struct console_methods): add a slice parameter to + init_image_instance_from_eimage_method. + + * redisplay.c (create_string_text_block): Allow buffer to be nil + without crashing. + +1999-09-24 Andy Piper + + * glyphs-x.c: only include gui-x.h if we are building with + widgets. + + * gui-x.c (vars_of_gui_x): only set popup_up_p if we have popups. + +1999-09-28 Lee Kindness + + * objects-x.c (allocate_nearest_color): will return 0 (failure) + when the colormap is full and the color it has computed to be the + 'nearest' has been allocated read/write. + +1999-10-02 Olivier Galibert + + * search.c (reinit_vars_of_search): Reinit the search cache + correctly. + + * elhash.h: Make the description visible. Declare + resize_hash_table. + + * elhash.c (resize_hash_table): Extracted from enlarge_hash_table + to generalize the hash table reorganization. + (reorganize_hash_table): Added. + (enlarge_hash_table): Uses resize_has_table. + + * casetab.c (complex_vars_of_casetab): staticpro the mule mirror + tables. + + * alloc.c: Add correct management of blocks of structures. + Reorganize hash tables at reload since the hash values can change + with the pointers. + +1999-10-01 Olivier Galibert + + * lisp.h: Add pdump_wire declaration + + * elhash.c (vars_of_elhash): Wire Vall_weak_hash_tables. + * symbols.c (init_symbols_once_early): Wire Qnil and Qunbound. + + * alloc.c (pdump_wire): Added.. + (pdump_load): Support it. + (pdump): Support it + + * glyphs-msw.c + (reinit_image_instantiator_format_create_glyphs_mswindows): Fix + macro calls. + +1999-09-28 Olivier Galibert + + * symsinit.h: Added lots of prototypes. + + * symeval.h: Added defsymbol_nodump declaration. + + * symbols.c (find_symbol_value): Lame attempt at making the + startup go further. + (defsymbol_nodump): Added. + + * mule-charset.c: Collapsed global lisp objects arrays in one + dumpable structure. + + * lrecord.h: Added some flags. + + * lisp.h: Added dumped flag to dynarrs. Added dumpstruct + declaration. + + * glyphs.h (INITIALIZE_IMAGE_INSTANTIATOR_FORMAT_NO_SYM): Don't + staticpro dynamic variables. + + * glyphs.c (reinit_specifier_type_create_image): Added. + (image_instantiator_format_create): Dump image instantiator format + dynarr. + (reinit_image_instantiator_format_create): Added. + + * emacs.c (main_1): Added reinits calls. + + * dynarr.c: Protect dumped dynarrays from going berzek in free or + realloc. + + * specifier.h (INITIALIZE_SPECIFIER_TYPE): Don't staticpro dynamic + variables. + * specifier.c (specifier_type_create): Dump the specifier type + dynarr. + (reinit_specifier_type_create): Added. + * console.h (INITIALIZE_CONSOLE_TYPE): Don't staticpro dynamic + variables. + * console.c (console_type_create): Dump the console type dynarr. + (reinit_vars_of_console): Extracted from vars_of_console. + (reinit_complex_vars_of_console): Extracted from + complex_vars_of_console + * window.c (reinit_vars_of_window): Extracted from vars_of_window. + * toolbar.c (reinit_specifier_type_create_toolbar): Added. + * search.c (reinit_vars_of_search): Extracted from vars_of_search. + * objects.c (reinit_specifier_type_create_objects): Added. + (reinit_vars_of_objects): Extracted from vars_of_objects. + * lstream.c (reinit_vars_of_lstream): Extracted from + vars_of_lstream. + * lread.c (reinit_vars_of_lread): Extracted from vars_of_lread. + * gutter.c (reinit_specifier_type_create_gutter): Added. + * glyphs-x.c (reinit_image_instantiator_format_create_glyphs_x): + Added. + * glyphs-widget.c + (reinit_image_instantiator_format_create_glyphs_widget): Added + * glyphs-msw.c + (reinit_image_instantiator_format_create_glyphs_mswindows): Added. + * glyphs-eimage.c + (reinit_image_instantiator_format_create_glyphs_eimage): Added. + * event-stream.c (reinit_vars_of_event_stream): Extracted from + vars_of_event_stream + * eval.c (reinit_vars_of_eval): Extracted from vars_of_eval. + * device.c (reinit_vars_of_device): Extracted from vars_of_device. + * console-x.c (reinit_console_type_create_x): Added. + * console-tty.c (reinit_console_type_create_tty): Added + * console-stream.c (reinit_console_type_create_stream): Added. + (init_console_stream): If PDUMP, always reinitialise basic + devices. + * console-msw.c (reinit_console_type_create_mswindows): Added. + * buffer.c (reinit_vars_of_buffer): Extracted from + init_vars_of_buffer. + (reinit_complex_vars_of_buffer): Extracted from + complex_vars_of_buffer + + * alloc.c: Further with the portable dumping, the revenge. + (dumpstruct): Added. + (reinit_alloc_once_early): Extracted from init_alloc_once_early. + + * specifier.c (sizeof_specifier): Correct size computation. + (make_specifier_internal): Ditto. + +1999-09-27 Olivier Galibert + + * alloc.c: Further with the portable dumping. + +1999-09-27 Martin Buchholz + + * glyphs-x.c (update_widget_face): Remove bogus cast + + * data.c (sign_extent_lisp): + * data.c (check_int_range): + * data.c (Faref): + * data.c (Faset): + * data.c (number_char_or_marker_to_int): + * data.c (number_char_or_marker_to_double): + * data.c (Frem): + * data.c (Fmod): + * extents.c (print_extent_1): + * fns.c (print_bit_vector): + * fns.c (Flength): + * fns.c (Fsafe_length): + * fns.c (copy_list): + * fns.c (Fsubseq): + * fns.c (Felt): + * fns.c (Flast): + * fns.c (Fnbutlast): + * insdel.h: + * marker.c (print_marker): + * syntax.h: + * bytecode.c (bytecode_arithcompare): + * bytecode.c (bytecode_arithop): + * lisp.h: + * lisp.h (EXTERNAL_LIST_LOOP_DELETE_IF): + * lisp.h (TRUE_LIST_P): + * lisp.h (CHECK_TRUE_LIST): + * lisp.h (bit_vector_length): + * lisp.h (GCPRO4): Make consistent. + * lisp.h (NGCPRO4): Make consistent. + * lisp.h (NNGCPRO4): Make consistent. + * alloc.c (Fmake_list): + * alloc.c (Fmake_string): + Use proper 64-bit types, e.g. EMACS_INT or size_t instead of int. + This should make all arithmetic 64-bit clean. + + Use %ld with (long) casts in print statements of types with sizes + possibly larger than int. + + Following functions had mismatched prototypes!!: + do_marker_adjustment(), fixup_internal_substring(), scan_lists(), + char_quoted(), make_string_from_buffer(), + make_string_from_buffer_no_extents() + + The types of Bufpos, Bytind, Memind, Bytecount, Charcount, + Extcount are all now EMACS_INT. I hope to see the day when I can + create a buffer with more than INT_MAX characters, without having + XEmacs slow down to a crawl. I also hope to be able to create a + list with more than INT_MAX cons cells. + + * redisplay.c (decode_mode_spec): + The %p and %P specs in the mode line were not correct for buffers + larger than MAX_INT/100! The %p spec was off by .5% even for + small buffers! + +1999-09-27 Martin Buchholz + + * cmdloop.c (num_input_keys): + * print.c (debug_temp): + * emacs.c (Vinfo_directory): + Delete unused variables + + * console-x.h (x_interline_space): Mark as unimplemented. + * redisplay-x.c (x_interline_space): Mark as unimplemented. + + * event-Xt.c (pending_timeouts): + * linuxplay.c (linuxplay_sndbuf): + * profile.c (QS*): + * search.c (searchbufs): + * specifier.c (specifier_type_entry_dynarr): + * undo.c (pending_boundary): + * event-stream.c (the_low_level_timeout_blocktype): + * extents.c (gap_array_marker_freelist): + * extents.c (extent_list_marker_freelist): + * print.c (being_printed): + * print.c (alternate_do_pointer): + * alloc.c (first_string_chars_block): + * alloc.c (current_string_chars_block): + * emacs.c (initial_argv): + * emacs.c (initial_argc): + * eval.c (lisp_eval_depth): + * free-hook.c (pointer_table): + * free-hook.c (free_queue): + * free-hook.c (current_free): + * free-hook.c (strict_free_check): + * redisplay.c (formatted_string_emchar_dynarr): + * redisplay.c (formatted_string_display_line): + * redisplay.c (formatted_string_extent_dynarr): + * redisplay.c (formatted_string_extent_start_dynarr): + * redisplay.c (formatted_string_extent_end_dynarr): + * redisplay.c (updating_line_start_cache): + * redisplay.c (last_display_warning_tick): + * redisplay.c (display_warning_tick): + * redisplay.c (internal_cache): + * window.c (Vwindow_configuration_free_list): + Make static. + + * redisplay.c (Vinitial_window_system): Make CONST. + +1999-09-24 Martin Buchholz + + * redisplay-tty.c (term_get_fkeys_1): Minor aesthetic improvements. + + * doprnt.c (get_doprnt_args): Use int, not short, with va_arg. + +1999-09-24 Andy Piper + + * redisplay-output.c (output_display_line): only clear the borders + if we are not displaying the gutter. + +1999-09-24 Jan Vroonhof + + * frame-x.c (x_any_window_to_frame): Let Xt find the widget and + then use x_any_widget_or_parent_to_frame(). + (x_find_frame_for_window): remove special cases. + +1999-09-24 Andy Piper + + * scrollbar-x.c (x_window_is_scrollbar): deleted. + * scrollbar-x.h: ditto. + +1999-09-23 Martin Buchholz + + * alloc.c (this_marks_a_marked_record): Remove. + + * buffer.c (mark_buffer): + * buffer.c (nuke_all_buffer_slots): + * console.c (mark_console): + * console.c (nuke_all_console_slots): + * frame.c (mark_frame): + * frame.c (nuke_all_frame_slots): + Treat MARKED_SLOT() macros consistently. + + * device.h (error_check_device_type): + * faces.c (face_getprop): + * fileio.c (DRIVE_LETTER): + * filelock.c (lock_file_1): + * frame-x.c (x_create_widgets): + * frame.h (error_check_frame_type): + * keymap.c (print_keymap): + * keymap.c (Fkey_description): + * keymap.c (where_is_recursive_mapper): + * mule-charset.h (CHARSET_LEADING_BYTE): + * objects-msw.c (mswindows_color_instance_hash): + * objects.c (color_instance_equal): + * objects.h (struct color_specifier): + * objects.h (struct font_specifier): + * objects.h (struct face_boolean_specifier): + * opaque.h (get_opaque_ptr): + * opaque.h (set_opaque_ptr): + * process-unix.c (set_socket_nonblocking_maybe): + * specifier.h (SPECIFIER_TYPE_P): + * symbols.c (store_symval_forwarding): + * syssignal.h (EMACS_KILLPG): + * terminfo.c (emacs_tparam): + * glyphs.c (glyph_putprop): + * glyphs.c (glyph_remprop): + * glyphs.c (Fimage_instance_subwindow_id): + * window.c (mark_window): + * window.c (mark_window_config): + * window.c (Fset_window_configuration): + * window.c (save_window_save): + * eval.c (Fuser_variable_p): + * eval.c (Fcommand_execute): + * eval.c (Feval): + * eval.c (Ffuncall): + * lisp.h (XPNTR): + * lisp.h (INT_OR_FLOATP): + * lisp.h (GC_INT_OR_FLOATP): + * lisp.h (XFLOATINT): + * lisp.h (IS_ANY_SEP): + * mule-ccl.c (Fccl_execute): + * mule-ccl.c (Fccl_execute_on_string): + * redisplay-x.c (x_output_string): + Remove redundant extra parentheses. + +1999-09-22 Martin Buchholz + + * chartab.c (word_boundary_p): Add prototype for warning avoidance. + * eval.c (PRIMITIVE_FUNCALL): ANSIfy + * free-hook.c (fun_ptr): ANSIfy + * getloadavg.c: Remove declaration for errno. + * gui.c (allocate_gui_item): ANSIfy + * gui.h (allocate_gui_item): ANSIfy + * mule-ccl.c (resolve_symbol_ccl_program): Make static + * realpath.c: Remove K&R support. + * redisplay-x.c (x_output_display_block): Don't shadow previous local + * glyphs-widget.c (layout_instantiate): Don't shadow previous local + * gutter.c (get_gutter_coords): Make static. + * lread.c (locate_file_map_suffixes): Make static. + * ralloc.c (relinquish): ANSIfy + * redisplay.c: + * lisp.h: + Move prototypes from redisplay.c to lisp.h + +1999-09-22 Martin Buchholz + + * glyphs-x.c (x_widget_set_property): + - Remove unnecessary initialization. + - Use char*, not Bufbyte *, with GET_C_STRING_OS_DATA_ALLOCA + * glyphs-x.c (x_widget_instantiate): + - Use char*, not Bufbyte *, with GET_C_STRING_OS_DATA_ALLOCA + * unexelf.c (unexec): + Add cast for C++ compilability. + * redisplay.h: + Fix a typo. + * ralloc.c (r_alloc_reinit): + SET_FUN_PTR was broken wrt ANSI aliasing! + To compensate, use __typeof__ when using gcc, else live with + possible (but rare) warnings. + * ralloc.c (init_ralloc): + Ditto + * ralloc.c: Use the real dlmalloc prototype for __morecore. + * lread.c (locate_file_map_suffixes): + * input-method-xlib.c (XIM_init_frame): + - Xlib functions should use XPointer, not XtPointer. + * input-method-xlib.c (XIM_delete_frame): + - Xlib functions should use XPointer, not XtPointer. + * input-method-xlib.c (IMDestroyCallback): + - Simplify. + - XFRAME (obj) can never be NULL, so don't test for it. + * gutter.h: + Add GUTTER_POS_LOOP for iterating over all gutter_pos'es + * gutter.c (SET_GUTTER_WAS_VISIBLE_FLAG): + Run c-backslash-region on macro body. + * gutter.c (gutter_was_visible): + Remove redundant parens - this is not a macro. + * gutter.c (redraw_exposed_gutters): + Use GUTTER_POS_LOOP. + * gutter.c (gutter_specs_changed): + Use GUTTER_POS_LOOP. + * gutter.c (gutter_geometry_changed_in_window): + Use GUTTER_POS_LOOP. + * gutter.c (update_frame_gutters): + Use GUTTER_POS_LOOP. + * gutter.c (init_frame_gutters): + Use GUTTER_POS_LOOP. + * file-coding.c (determine_real_coding_system): + Fix C++ compile error. + * emodules.c (find_make_module): + Cast return value from xrealloc + * emacs.c (Fkill_emacs): + Use __typeof__, when available. + * emacs.c (voodoo_free_hook): + Use __typeof__, when available. + (Unfortunately, the type of __free_hook is glibc-version-dependent) + * dired.c (user_cache): Use Bufbyte *, not char * + * dired.c (Fuser_name_all_completions): Ditto. + +1999-09-22 Andy Piper + + * redisplay.c (redisplay_frame): reset the gutter display lines + when we reset the subwindows. + + * gutter.c (reset_gutter_display_lines): new function. + + * window.c (Flast_nonminibuf_window): new function equivalent to + FRAME_LAST_NONMINIBUF_WINDOW (). + (syms_of_window): declare it. + + * redisplay.c (create_string_text_block): don't add bogus eol + markers to gutter display lines. + + * glyphs.c (reset_subwindow_cachels): make sure we unmap + subwindows using unmap_subwindow so that expose events get + registered correctly. + + * window.c (window_scroll): use Vwindow_pixel_scroll_increment to + determine how much to scroll the window. + (vars_of_window): Vwindow_pixel_scroll_increment is a new + variable. + +1999-09-20 Robert Pluim + + * glyphs-x.c (update_widget_face): Guard fontList declaration for + non-motif uses. + +1999-09-20 Andy Piper + + * glyphs-msw.c (mswindows_update_subwindow): update faces. + +1999-09-19 Andy Piper + + * glyphs.c (update_frame_subwindows): update if faces have + changed. + + * glyphs-x.c (x_widget_instantiate): create the clip widget using + lwlib rather than directly. + (x_finalize_image_instance): delete the clip widget using lwlib. + (x_update_subwindow): update widget faces. + (update_widget_face): new function for updating the face + properties of a widget. + (x_widget_set_property): update widget faces. + + * lwlib-Xlw.c (xlw_create_clip_window): new function. We need to + manage the clip widgets using lwlib so that we can delete them in + a safe manner. + +1999-09-16 Martin Buchholz + + * lisp-union.h: + * lisp-disunion.h: + Define new, potentially faster INT arithmetic macros + INT_PLUS, INT_MINUS, INT_PLUS1, INT_MINUS1 + * bytecode.c (execute_optimized_function): + Use new macros. + Fix metering code + * bytecode.c (bytecode_negate): + Optimize for integer case. + +1999-08-29 Andreas Jaeger + + * m/mips.h: Support for mips-linux: Add !linux around places + that are not valid for linux, define TEXT_START, DATA_START, + DATA_SEG_BITS. + +1999-09-16 Andy Piper + + * redisplay-output.c (redisplay_output_subwindow): clip subwindows + that don't completely fit on-screen rather than just unmapping + them. + + * glyphs.h: change signature of map_subwindow. + + * glyphs.c (map_subwindow): add display_glyph_area to the + signature. make sure the mapped area saved in the subwindow_cachel + reflects this. + (Fforce_subwindow_map): make a no-op. I don't think this does + anything useful. + + * glyphs-x.h (struct x_subwindow_data): save the Display rather + than the Screen. Add a clipwindow and clipwidget handle. + (IMAGE_INSTANCE_X_CLIPWINDOW): new accessor. + (IMAGE_INSTANCE_X_CLIPWIDGET): ditto. + (XIMAGE_INSTANCE_X_CLIPWIDGET): ditto. + (XIMAGE_INSTANCE_X_CLIPWINDOW): ditto. + + * glyphs-x.c (x_finalize_image_instance): destroy the clipwidget + as well as the widget itself. + (x_unmap_subwindow): unmap the clipwindow and clipwidget rather + than the widgets and subwindows themselves. move the widget inside + the clipwidget. + (x_subwindow_instantiate): hold onto the Display rather than the + Screen. allocate a clipwindow to put the subwindow inside. + (x_resize_subwindow): use saved Display directly. + (x_widget_instantiate): allocate a clipwidget of type EmacsManager + to put widgets inside. + + * glyphs-widget.c: remove group stuff. + + * glyphs-msw.h (struct mswindows_subwindow_data): new structure to + hold the clipwindow. + (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW): new accessor. + (XIMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW): ditto. + + * glyphs-msw.c: remove group stuff. + (mswindows_finalize_image_instance): destroy clipwindow as well as + the widget itself. + (mswindows_unmap_subwindow): unmap the clipwindow rather than the + widget. + (mswindows_map_subwindow): ditto. move the widget within the + clipwindow. + (mswindows_subwindow_instantiate): allocate and initialize + mswindows_subwindow_data. allocate a clipwindow with the subwindow + as a child. + (mswindows_widget_instantiate): ditto. + (mswindows_control_wnd_proc): new function that allows us to + propagate events from the widget to the main windows control loop. + + * device-msw.c (mswindows_init_device): register new widget clip window + class. + + * console.h (struct console_methods): add display_glyph_area to + map_window. + + * console-msw.h: declare new window class and wnd proc for + widgets. + +1999-09-14 Martin Buchholz + + * general.c: + * eldap.c: + Move symbols used only by eldap.c into eldap.c as statics. + +1999-09-09 Martin Buchholz + + * window.c (syms_of_window): + * symbols.c (syms_of_symbols): + * redisplay.c (syms_of_redisplay): + * print.c (syms_of_print): + * lisp.h: + * intl.c (syms_of_intl): + * general.c (syms_of_general): + * frame.c (syms_of_frame): + * fileio.c (syms_of_fileio): + * file-coding.h: + * file-coding.c (syms_of_file_coding): + * extents.c (syms_of_extents): + * event-stream.c (syms_of_event_stream): + * event-stream.c (Fnext_event): + * device.c (syms_of_device): + * data.c (syms_of_data): + * casetab.c (syms_of_casetab): + * casetab.c (check_case_table): + * callint.c (syms_of_callint): + * buffer.c (syms_of_buffer): + Delete unused C symbols: + Qbuffer_file_name, Qbuffer_undo_list, Quser_variable_p, + Qcurrent_prefix_arg, Qtranslate_table, Qkeywordp, + Qnumber_or_marker_p, Qcons, Qkeyword, Qignore, Qdelete_device, + Qcommand_execute, Qglyph_invisible, + Qbuffer_file_coding_system, Qfile_name_handler_alist, + Qframe_x_p, Qframe_tty_p, Qblack, Qkeyboard, Qmenubar, Qpath, + Qvector, Qwhite, Qcase, Qdomain, Qalternate_debugging_output, + Qprint_escape_newlines, Qprint_readably, Qfloat_output_format, + Qwindow_scroll_functions, Qfboundp, Qscroll_up, Qscroll_down + + Rename symbols as required by the CHECK_RECORD macro: + - Qcase_table_p to Qcase_tablep + - Qcoding_system_p to Qcoding_systemp + + * debug.h: + * debug.c (syms_of_debug): + Make debug.c's internal Lisp_Objects static. + + * events.c (vars_of_events): + * events.c (syms_of_events): + Use regular old defsymbol instead of KEYSYM + staticpro(). + + * select-x.c (CHECK_CUTBUFFER): + Rewrite in accordance with coding standards. + + * keymap.c (syms_of_keymap): + Use SPC in the same way as RET, TAB, etc. + +1999-08-27 Jan Vroonhof + + * xemacs-20/src/menubar-x.c (make_dummy_xbutton_event): Don't add + offset twice if HAVE_WMCOMMAND is defined. + +1999-09-13 Mike McEwan + + * redisplay-x.c (x_output_vertical_divider): make sure + shadow_thickness is positive. + +1999-09-10 Julian Back + + * process-nt.c (nt_create_process): fixup to cope with + Vprocess_environment. + +1999-09-02 Andy Piper + + * redisplay-output.c (redisplay_output_layout): call output + routines with clear_clip false. output layout borders with text + correctly. + + * redisplay-msw.c (mswindows_output_blank): call output routines + with clear_clip true. + (mswindows_output_string): ditto. + (mswindows_output_display_block): ditto. + + * redisplay-x.c (x_output_display_block): call output routines + with clear_clip true. + + * redisplay.h: fix output routines for clear_clip parameter. + + * redisplay-output.c (redisplay_output_layout): cope with glyphs + in the border. + + * glyphs-widget.c (layout_instantiate): deal with border glyphs. + (check_valid_glyph_or_instantiator): renamed from + check_valid_glyph_or_image. + (check_valid_border): allow glyphs or their instantiators. + (check_valid_glyph_or_instantiator_list): renamed from + check_valid_glyph_or_image_list, + (glyph_instantiator_to_glyph): new function. make sure a glyph is + a glyph and not an instantiator. + (substitute_keyword_value): new function. replace a keyword value + with a new one. + +1999-09-01 Andy Piper + + * glyphs.c (string_set_property): new function to set the data of + a string. + (image_instantiator_format_create): use it. + +1999-09-07 Hrvoje Niksic + + * fns.c (Fmapc): Rename back to Fmapc_internal. + +1999-07-30 Gleb Arshinov + + * ntheap.h: CONST (semantically constant) name field of file_data + struct + + * unexnt.c (open_output_file): match function definition with + function declaration + + * editfns.c: #include "sysfile.h" for getcwd() prototype + + * gif_io.c: #include "sysfile.h" for close() prototype + +1999-09-02 Martin Buchholz + + * elhash.c: + * elhash.h: + Change the :type keyword to :weakness, for compatibility with the + GNU Emacs 20.5 hash table implementation. + Keep (but don't document) the :type keyword for compatibility. + Obsolete function hash-table-type + General cleanup. + Define function sxhash for compatibility with Common Lisp and GNU Emacs. + +1999-09-01 Martin Buchholz + + * floatfns.c (arith_error): + * floatfns.c (range_error): + * floatfns.c (range_error2): + * floatfns.c (domain_error): + * floatfns.c (domain_error2): + * lrecord.h (LRECORDP): + * console-x.h (X_ERROR_OCCURRED): + * console-x.h (HANDLING_X_ERROR): + * chartab.c (CATEGORYP): + * buffer.h (XCHAR_OR_CHAR_INT): + Remove redundant and confusing parentheses. + + * redisplay-output.c (redisplay_clear_to_window_end): + Remove redundant initialization. + + * redisplay.h: + * redisplay-msw.c: + * redisplay-x.c: + Move declarations of bevel_modeline() into redisplay.h. + +1999-08-30 Olivier Galibert + + * lisp.h: Add staticpro_nodump for undumped staticpro-ing. + * alloc.c: Add staticpro_nodump for undumped staticpro-ing. Add + alignment information for dumped data. Enhance + descriptions. Phase out Vterminal_* variables while + dumping. + * lrecord.h: Add chained descriptions and automagically-reset + lisp_objects to the description system. + + * console-stream.h: Declare the Vterminal_* variables. + + * buffer.c: Don't dump Vbuffer_alist, Vbuffer_defaults and + Vbuffer_local_symbols. + * console.c: Don't dump Vconsole_list, Vconsole_defaults and + Vconsole_local_symbols. + * eval.c: Don't dump Qunbound_suspended_errors_tag. + * lread.c: Don't dump Vread_buffer_stream. + * lstream.c: Don't dump Vlstream_free_list[]. + * search.c: Don't dump last_thing_searched. + * window.c: Don't dump minibuf_window and + Vwindow_configuration_free_list[]. + + * faces.c: Add face description. + * fns.c: Add bit_vector description. + * glyphs.c: Add image specifier description. + * objects.c: Add color, face and face boolean specifiers descriptions. + * opaque.c: Add opaque description. Don't dump Vopaque_ptr_free_list. + * rangetab.c: Add range table description. + * specifier.c: Add specifier and specifier methods description. + * specifier.h: Add specifier extra description support. + + * symbols.c: Fix symbol_value_buffer_local_description. + + * gdbinit (Lisp): Add opaque_ptr, remove opaque_list. + +1999-09-02 Hrvoje Niksic + + * extents.c (extent_remprop): Get extent's plist address + correctly. + +1999-08-31 Andy Piper + + * xmu.h: define Xmu/Converters.h things. + +1999-08-31 Andy Piper + + * opaque.c (equal_opaque_ptr): define. + (hash_opaque_ptr): define. + + * xmu.h: define Xmu/Misc.h things. + 1999-08-17 MORIOKA Tomohiko * file-coding.c (determine_real_coding_system): Treat `coding:' @@ -39,13 +1347,556 @@ (decode_coding_ucs4): Use `counter'. (decode_coding_utf8): Likewise. +1999-08-31 Andy Piper + + * redisplay-output.c (redisplay_normalize_glyph_area): make sure + the clip offset doesn't exceed the height we have available to + show. + + * window.h (struct window): add top_yoffset and left_xoffset for + pixel scrolling. + (WINDOW_TEXT_TOP_CLIP): new macro. + + * window.c (window_scroll): add behaviour for pixel-scrolling of + tall lines. + + * redisplay.h (struct display_line): add top_clip. + (DISPLAY_LINE_HEIGHT): adjust for top_clip. + (DISPLAY_LINE_YPOS): ditto. + + * redisplay.c (position_redisplay_data_type): add + start_col_xoffset to prepare for pixel-based h-scrolling. + (WINDOW_SCROLLED): new macro. + (next_tab_position): use it. + (add_glyph_rune): use new hscoll vars. + (create_text_block): ditto. + (generate_displayable_area): adjust off-by-one error. + (regenerate_window): take top_clip into account. + (regenerate_window_extents_only_changed): ditto. + (regenerate_window_incrementally): ditto. + + * redisplay-x.c (x_output_display_block): use DISPLAY_LINE_YPOS, + DISPLAY_LINE_HEIGHT and DISPLAY_LINE_YEND macros. + (x_output_string): ditto. + (x_output_blank): ditto. + (x_output_hline): ditto. + (x_output_eol_cursor): ditto. + + * redisplay-output.c (output_display_line): allow for + top_clip. use DISPLAY_LINE_YPOS, DISPLAY_LINE_HEIGHT and + DISPLAY_LINE_YEND macros. + (redisplay_output_layout): output strings in layouts correctly. + (redisplay_clear_clipped_region): allow for top_clip. + (redisplay_calculate_display_boxes): ditto. + + * redisplay-msw.c (mswindows_output_blank): use DISPLAY_LINE_YPOS, + DISPLAY_LINE_HEIGHT and DISPLAY_LINE_YEND macros. + (mswindows_output_cursor): ditto. + (mswindows_output_string): ditto. + (mswindows_redraw_exposed_window): ditto. + (mswindows_output_display_block): ditto. + + * gutter.c: new specifier type gutter-size. + (gutter_size_validate): validate gutter-size specifier. + (Fgutter_size_specifier_p): predicate for gutter-size. + (Fredisplay_gutter_area): allow the gutter area to be redisplayed + under user contol, like Fredisplay_echo_area. + (syms_of_gutter): add new functions. + (specifier_type_create_gutter): add new specifier. + (specifier_vars_of_gutter): change specifier types of *-height to + gutter-size. + + * glyphs.c (glyph_width): make work with image instances. + + * console.h (struct console_methods): change api of output_string. + + * glyphs-x.c (x_map_subwindow): move before mapping as reported by + Stephen J. Turnbull + +1999-08-30 Andy Piper + + * glyphs-x.c (x_finalize_image_instance): X_MASK -> PIXMAP_MASK + for assignment. + (init_image_instance_from_x_image): ditto. + (x_xpm_instantiate): ditto. + (x_colorize_image_instance): ditto. Reported by Richard Cognot + + +1999-08-29 Andy Piper + + * glyphs-x.c (x_widget_instantiate): move font initialisation so + that it doesn't get saved in the user defined args. + (x_tab_control_instantiate): Set the fg color of the tab's + children. + (x_tab_control_set_property): ditto. + +1999-08-27 Damon Lipparelli + + * events.h (XTIMEOUT): must preface Lisp_Timeout with ``struct'' + (XSETTIMEOUT): fixup typo + +1999-08-11 Jan Vroonhof + + * syntax.c (scan_words): Unified Mule and Non-mule scanning. + Word boundary search looks back instead of forward so that it + doesn't peek over the limit. + +1999-08-20 Olivier Galibert + + * config.h.in: Add PDUMP define. + * emacs.c (Fdump_emacs): Hackish, call pdump() if configured in. + + * lrecord.h: Enhance description system. + * alloc.c: Fix vector and string description. Add portable + dumper enumeration fonctions. + + * symbols.c: Fix symbols description. Add symbol_value_forward + description. + * eval.c: Add subr description. + * elhash.c (CLEAR_HENTRY): Clean value pointer too. Fix hash + table description. + (remhash_1): CLEAR_HENTRY evaluates the parameter two times now. + +1999-08-20 Olivier Galibert + + * opaque.c: Kill opaque lists, make Lisp_Opaque_Ptr a lrecord of + its own. + * opaque.h: Ditto. + + * eval.c (eval_in_buffer_trapping_errors): + (run_hook_trapping_errors): + (safe_run_hook_trapping_errors): + (call0_trapping_errors): + (call1_trapping_errors): + (call2_trapping_errors): OPAQUEP -> OPAQUE_PTRP. make_opaque_ptr + now takes a non-const void *. + +1999-08-20 Olivier Galibert + + * opaque.c: Remove make_opaque_long. + + * opaque.h: Remove everything opaque_long related. + + * eval.c (vars_of_eval): Make Qunbound_suspended_errors_tag an + opaque_ptr. + + * emacs.c (main_1): Remove make_opaque_long from comment. + +1999-08-20 Olivier Galibert + + * event-stream.c (mark_timeout): + (print_timeout): + (event_stream_generate_wakeup): + (event_stream_resignal_wakeup): + (event_stream_disable_wakeup): + (event_stream_wakeup_pending_p): + (vars_of_event_stream): Lisp_Timeout is now a lrecord. + + * events.h (struct Lisp_Timeout): Added. + +1999-08-24 Andy Piper + + * console-x.h: declare new pixmap signatures. + +1999-08-23 Andy Piper + + * glyphs-x.c (x_update_subwindow): make sure the widget size is + maintained after an update. + + * event-Xt.c (emacs_Xt_handle_magic_event): use + find_matching_subwindow to check whether the exposure is totally + inside a subwindow, if it is then ignore it. + + * glyphs.c (find_matching_subwindow): new function. + + * toolbar-x.c (x_draw_blank_toolbar_button): use new + x_output_shadows signature. + (x_output_toolbar_button): use new x_output_x_pixmap signature. + + * redisplay.h (struct display_box): new structure. + (struct display_glyph_area): ditto. + declare new display_box functions. + + * redisplay-x.c (x_output_pixmap): update for new display + box stuff. + (x_bevel_area): update to allow multiple edge styles and border + segments. + (x_output_display_block): update for new display_box stuff and + signatures. + (x_clear_region): ditto. + (x_output_x_pixmap): ditto. adjust offsets rather than clip. + (console_type_create_redisplay_x): declare new console methods. + (x_output_vertical_divider): update for new bevel_area signature. + (x_output_shadows): update to allow selective drawing of edges. + + * redisplay-tty.c (tty_output_display_block): do nothing for + layouts. + + * redisplay-output.c (redisplay_output_subwindow): convert to use + display_box structure, this allows us to put subwindows anywhere + with any offset, useful for layout glyphs. + (redisplay_output_layout): new function. output a layout and its + sub-glyphs. + (redisplay_output_pixmap): new modular function combining generic + parts of the X and mswindows versions. convert to use display_box + structures. + (redisplay_clear_clipped_region): new function. clear the area a + glyph is going into. + (redisplay_normalize_glyph_area): new function. calculate the + bounds of a display_glyph_area given a display_box. + (redisplay_normalize_display_box): new function. shrink a + display_box to enclose a display_glyph_area. + (redisplay_display_boxes_in_window_p): check whether the input + display_box and display_glyph_area are actually in a window. + (redisplay_calculate_display_boxes): calculate display boxes based + on conventional display_line metrics. + (bevel_modeline): update for new bevel_area signature. + + * redisplay-msw.c (mswindows_output_blank): update for new + display_box stuff. + (mswindows_output_string): ditto. + (mswindows_output_dibitmap): ditto. + (mswindows_output_dibitmap_region): ditto. + (mswindows_output_pixmap): ditto. + (mswindows_bevel_area): update to allow multiple edge styles and + border segments. + (mswindows_output_display_block): update for new display_box stuff + and signatures. + (mswindows_clear_region): ditto. + (console_type_create_redisplay_mswindows): declare new console methods. + + * lisp.h (edge_style): new enum. + declare display_box and display_glyph_area. + + * gutter.c (output_gutter): update for new bevel_area signature. + + * glyphs.h (image_instance_type): add layout. + (IMAGE_LAYOUT_MASK): ditto. + (LAYOUT_IMAGE_INSTANCEP): new macro. + (CHECK_LAYOUT_IMAGE_INSTANCE): ditto. + (struct Lisp_Image_Instance): add offsets for layout and the + layout type itself. move mask here also. + (IMAGE_INSTANCE_LAYOUT_CHILDREN): new macro. + (IMAGE_INSTANCE_LAYOUT_BORDER): ditto. + (XIMAGE_INSTANCE_LAYOUT_CHILDREN): ditto. + (XIMAGE_INSTANCE_LAYOUT_BORDER): ditto. + + * glyphs.c (mark_image_instance): update for layouts. + (print_image_instance): ditto. + (image_instance_equal): ditto. + (image_instance_hash): ditto. + (allocate_image_instance): initialise offsets for layout. + (decode_image_instance_type): update for layouts. + (encode_image_instance_type): ditto. + (Fimage_instance_height): ditto. + (Fimage_instance_width): ditto. + (allocate_glyph): ditto. + (glyph_width): allow image instances as an argument. update for layouts. + (glyph_height_internal): ditto. + (syms_of_glyphs): add layout symbols. + + * glyphs-x.h (struct x_image_instance_data): remove mask entry. + (IMAGE_INSTANCE_X_MASK): update. + + * glyphs-x.c (x_label_instantiate): new function. instantiate a + label. + (image_instantiator_format_create_glyphs_x): initialise new layout + glyph type. + + * glyphs-widget.c: new layout type. + (check_valid_orientation): new keyword checker for layouts. + (check_valid_justification): ditto. + (check_valid_border): ditto. + (check_valid_glyph_or_image_list): ditto. + (layout_possible_dest_types): new function for layout glyph type. + (layout_normalize): ditto. + (layout_instantiate): ditto. + (syms_of_glyphs_widget): new keywords for layout. + (image_instantiator_format_create_glyphs_widget): initialise the + layout glyph type. + + * glyphs-msw.h (struct mswindows_image_instance_data): remove mask + argument. + (IMAGE_INSTANCE_MSWINDOWS_MASK): update. + + * glyphs-msw.c: declare layout format. + (image_instantiator_format_create_glyphs_mswindows): initialise it. + + * general.c: new symbols for layouts. + + * console.h (struct console_methods): new console methods for + outputting pixmaps and strings. + +1999-08-23 Didier Verna + + * sound.c: revert the renaming of `bell_volume' to `Vbell_volume' + and `bell_inhibit_time' to `Vbell_inhibit_time'. + +1999-08-18 Andy Piper + + * redisplay-output.c (redisplay_output_subwindow): disable + clipping attempt. + +1999-08-17 Andy Piper + + * gutter.c (redraw_exposed_gutter): handle degenerate case of no + area to expose or no gutter to display. + +1999-08-16 Charles G Waldman + + * sound.c: rename `bell_volume' to `Vbell_volume' and + `bell_inhibit_time' to `Vbell_inhibit_time'. + +1999-08-13 Charles G Waldman + + * sound.c: (bell-inhibit-time): New variable. + (ding): Use it. + (sound-alist): Fix docstring. + +1999-08-17 Andy Piper + + * gui-x.c (button_item_to_widget_value): xstrdup name so that + deleting it is ok. + +1999-08-16 Jeff Miller + + * syntax.c (scan_words): make compile. + +1999-08-16 Andy Piper + + * redisplay-output.c (redisplay_output_subwindow): try and be more + relaxed about clipping possibilities. + + * glyphs-x.c (x_tab_control_set_property): free_widget_value_tree + rather than just the widget_value. + (x_update_subwindow): ditto. + (x_widget_instantiate): ditto. + + * gutter.c (output_gutter): shrink current display lines if + required. + +1999-08-15 Andy Piper + + * redisplay.h: declare free_display_lines. + + * redisplay.c (free_display_lines): make non-static. + + * gutter.c (free_frame_gutters): use free_display_lines instead of + Dynarr_free. + (calculate_gutter_size): ditto. + +1999-08-12 Jan Vroonhof + + * eval.c (run_hook_with_args_in_buffer): GCPRO globals. + +1999-08-14 Andy Piper + + * glyphs.c (update_subwindow_cachel): make it less brittle. + +1999-08-04 Mike Woolley + + * scrollbar-msw.c (mswindows_handle_mousewheel_event): Fixed + problem in wheelmouse code occurring when the horizontal scrollbar + is enabled but not visible. + +1999-08-08 Andy Piper + + * toolbar-msw.c (mswindows_redraw_frame_toolbars): new function. + (console_type_create_toolbar_mswindows): use it. + + * glyphs.c (Fset_image_instance_property): fiddly reorganisation. + + * redisplay-output.c (redisplay_output_display_block): unmap + subwindows in the block area before outputting the block. + + * event-msw.c (mswindows_wnd_proc): check the update rect before + painting and disable expose registration while painting. + + * glyphs.c (register_ignored_expose): check + hold_ignored_expose_registration before registering expose events. + + * redisplay.c (redisplay_frame): reset the subwindow cache before + displaying the gutter. + + * glyphs-msw.c (mswindows_map_subwindow): move the window before + mapping. + + * gutter.c (update_frame_gutters): check for glyphs_changed as if + it is the subwindow cache will have been reset. + +1999-08-06 Andy Piper + + * gui-x.c (button_item_to_widget_value): cope with strings. + + * glyphs.h: declare global widget functions. + (IIFORMAT_HAS_SHARED_DEVMETHOD): new macro. + + * glyphs-x.c (x_combo_box_instantiate): do generic initialization + here. remove dead code. + (image_instantiator_format_create_glyphs_x): enable combo boxes + for Motif 2.0. + + * glyphs-widget.c (widget_instantiate_1): make non-static. + (tree_view_instantiate): renamed from combo_box_instantiate. + (image_instantiator_format_create_glyphs_widget): use new/changed methods. + + * glyphs-msw.c (mswindows_combo_box_instantiate): do generic + initialization here. + + * lwlib-Xm.c (xm_update_combo_box): new function. + (xm_update_one_widget): call it. + (xm_update_one_value): deal with combo boxes as well as lists. + (xm_create_combo_box): create a drop-down combo box. + + * toolbar-msw.c (mswindows_output_toolbar): call + mswindows_move_toolbar. + +1999-08-05 Andy Piper + + * window.c (Fcurrent_pixel_column): new function. use display + lines to calculate pixel position of point. + * window.c (syms_of_window): declare it. + +1999-08-05 Andy Piper + + * glyphs.c (check_for_ignored_expose): ignore exposures wholly + contained in our ignore list. + + * buffer.c (Frecord_buffer): add call to record-buffer-hook. + (syms_of_buffer): declare record-buffer-hook. + + * s/mingw32.h: define mousewheel things. + +1999-08-04 Mike Woolley + + * windowsnt.h (_WIN32_WINNT): enable for win95 + + * s/cygwin32.h: define mousewheel things. + + * scrollbar-msw.h: declare mousewheel handler. + + * scrollbar-msw.c (mswindows_handle_mousewheel_event): new function. + +1999-08-04 Andy Piper + + * gui-x.c (gui_items_to_widget_values): remove unused variable. + (gui_items_to_widget_values_1): ditto. + + * gui-x.h: unconditionally define since it is used everywhere. + +1999-08-04 Andy Piper + + * glyphs-x.c (x_finalize_image_instance): only free pixels if we + have that type of image. + +1999-07-30 Andy Piper + + * redisplay-output.c (redisplay_unmap_subwindows): add comparison + subwindow to not unmap if required. + (redisplay_unmap_subwindows_maybe): comparison is Qnil. + (redisplay_unmap_subwindows_except_us): new function. + (redisplay_output_subwindow): use it to unmap windows in the area + we are displaying into. + + * glyphs.c (update_subwindow_cachel_data): always update as we + only ever get called when an update is required. + (update_subwindow_cachel): new function. sync a subwindow with its + cachel. + (Fresize_subwindow): use it. + (register_ignored_expose): make sure we set the tail correctly. + +1999-07-28 Andy Piper + + * redisplay-output.c (redisplay_clear_bottom_of_window): remove + unneeded device. + + * gutter.c (redraw_exposed_gutter): unmap subwindows from the + whole gutter. + + * gui.h: declare parse_gui_item_tree_list and + parse_gui_item_tree_children. + + * gui.c (parse_gui_item_tree_item): new function for parsing item + lists into gui-item trees. + (parse_gui_item_tree_children): ditto. + (parse_gui_item_tree_list): ditto. + + * gui-x.h: declare gui_items_to_widget_values. + + * gui-x.c (gui_items_to_widget_values_1): new function for + recursively parsing gui-items into widget_values. + (gui_item_children_to_widget_values): ditto. + (gui_items_to_widget_values): ditto. + (sanity_check_lwlib): add widgets macrolets. + + * glyphs.h (IMAGE_INSTANCE_WIDGET_ITEMS): rename from *ITEM. + (XIMAGE_INSTANCE_WIDGET_ITEMS): ditto. + (IMAGE_INSTANCE_WIDGET_ITEM): rename from *SINGLE_ITEM. + (XIMAGE_INSTANCE_WIDGET_ITEM): ditto. + (struct expose_ignore): new structure for storing ignorable expose + events. + + * glyphs.c (valid_image_instantiator_format_p): fix so that using + a console-type as a locale works. + (mark_image_instance): ITEM->ITEMS. + (image_instance_equal): ditto. + (image_instance_hash): ditto. + (struct expose_ignore_blocktype): new blocktype. + (check_for_ignored_expose): new function. checks frame exposure + list for events to ignore. + (register_ignored_expose): new function. registers an expose event + as ignorable. + (unmap_subwindow): register the expose event as ignorable. + (vars_of_glyphs): initialise the exposure blocktype. + + * glyphs-x.c (x_finalize_image_instance): use lw_destroy_widget. + (x_update_subwindow): modify all widgets using widget_value tree + rather than just a single widget value. + (x_widget_instantiate): LWLIB_USES_MOTIF -> LWLIB_WIDGETS_MOTIF. + make sure widgets don't resize themselves. + (x_tab_control_instantiate): new function. use lwlib tab functions. + (x_tab_control_set_property): new function. + (image_instantiator_format_create_glyphs_x): add tab_control. + + * glyphs-widget.c (widget_text_to_pixel_conversion): calculate + slightly more sensibly. + (initialize_widget_image_instance): ITEM->ITEMS. + (widget_instantiate_1): parse gui items generically into the ITEMS + entry. + + * glyphs-msw.c (mswindows_update_subwindow): replace + SINGLE_ITEM->ITEM. + (mswindows_register_widget_instance): ditto. + (add_tree_item): modify to use new pre-initialised gui-item + structure. + (add_tab_item): ditto. + (mswindows_tab_control_instantiate): ditto. + (mswindows_tab_control_set_property): ditto. + (image_instantiator_format_create_glyphs_mswindows): predicate + existance of widgets on HAVE_WIDGETS. + + * frame.h (struct frame): add subwindow_exposures variables. + + * frame.c (allocate_frame_core): reset subwindow_exposures links. + + * event-msw.c (mswindows_wnd_proc): check for ignored + expose events before redrawing. + + * event-Xt.c (emacs_Xt_handle_magic_event): check for ignored + expose events before redrawing. + +1999-07-30 SL Baur + + * scrollbar-x.c: should include EmacsFrame.h. + From Jeff Miller + 1999-07-30 XEmacs Build Bot * XEmacs 21.2.19 is released 1999-07-27 Jeff Miller - * add a "#ifdef HAVE_MENUBARS" wrapper to gui.c around + * add a "#ifdef HAVE_MENUBARS" wrapper to gui.c around menubar_show_keybindings. 1999-07-23 SL Baur @@ -141,10 +1992,10 @@ * event-Xt.c (handle_focus_event_1): Re-enable Motif/XIM to get focus the event (XIM_focus_event). - (emacs_Xt_handle_magic_event): No side effect on Motif/XIM because + (emacs_Xt_handle_magic_event): No side effect on Motif/XIM because XIM_SetGeometry does nothing in input_method_motif.c, but re-unify the interface for future use (XIM_SetGeometry). - * redisplay-x.c (x_output_string): Re-enable Motif/XIM to set spot + * redisplay-x.c (x_output_string): Re-enable Motif/XIM to set spot location (XIM_SetSpotLocation). (x_output_eol_cursor): Ditto. @@ -252,7 +2103,7 @@ * redisplay-x.c (redisplay_clear_to_window_end): moved to redisplay.c - + * redisplay-msw.c (redisplay_clear_to_window_end): deleted. * gutter.c: new file - implements gutters. All new functions are @@ -391,9 +2242,9 @@ 1999-07-03 Gunnar Evermann - * tooltalk.c (init_tooltalk): save signal actions for SIGQUIT, - SIGINT and SIGCHLD before calling tt_open and restore the - afterwards. This fixes e.g. the zombie subprocesses on Solaris + * tooltalk.c (init_tooltalk): save signal actions for SIGQUIT, + SIGINT and SIGCHLD before calling tt_open and restore the + afterwards. This fixes e.g. the zombie subprocesses on Solaris 1999-07-06 SL Baur @@ -2318,8 +4169,8 @@ 1998-12-11 Martin Buchholz - * event-msw.c (mswindows_cancel_dispatch_event): - Gratuitous code prettification + * event-msw.c (mswindows_cancel_dispatch_event): + Gratuitous code prettification 1998-12-07 Hrvoje Niksic @@ -4144,7 +5995,7 @@ 1998-08-07 Matt Stupple - * ntproc.c: don't wait on char_consumed at thread entry. + * ntproc.c: don't wait on char_consumed at thread entry. Additionally, to get the 'process' marked as finished, ensure that the CHILD_ACTIVE macro returns false, so before exiting close char_avail and set it to NULL, and close other handles @@ -5437,7 +7288,7 @@ Wed May 27, 1998 Darryl Okahata 1998-05-14 Damon Lipparelli - * winslots.h: close comment + * winslots.h: close comment 1998-05-16 Kirill M. Katsnelson diff --git a/src/alloc.c b/src/alloc.c index 610efa4..8bd4b99 100644 --- a/src/alloc.c +++ b/src/alloc.c @@ -36,7 +36,7 @@ Boston, MA 02111-1307, USA. */ Added lcrecord lists for 19.14. slb: Lots of work on the purification and dump time code. Synched Doug Lea malloc support from Emacs 20.2. - og: Killed the purespace. + og: Killed the purespace. Portable dumper. */ #include @@ -57,11 +57,27 @@ Boston, MA 02111-1307, USA. */ #include "specifier.h" #include "sysfile.h" #include "window.h" +#include "console-stream.h" #ifdef DOUG_LEA_MALLOC #include #endif +#ifdef HAVE_MMAP +#include +#include +#endif + +#ifdef PDUMP +typedef struct +{ + const struct lrecord_description *desc; + int count; +} pdump_reloc_table; + +static char *pdump_rt_list = 0; +#endif + EXFUN (Fgarbage_collect, 0); /* Return the true size of a struct with a variable-length array field. */ @@ -183,13 +199,13 @@ Error_behavior ERROR_ME, ERROR_ME_NOT, ERROR_ME_WARN; int c_readonly (Lisp_Object obj) { - return POINTER_TYPE_P (XGCTYPE (obj)) && C_READONLY (obj); + return POINTER_TYPE_P (XTYPE (obj)) && C_READONLY (obj); } int lisp_readonly (Lisp_Object obj) { - return POINTER_TYPE_P (XGCTYPE (obj)) && LISP_READONLY (obj); + return POINTER_TYPE_P (XTYPE (obj)) && LISP_READONLY (obj); } @@ -359,8 +375,7 @@ xstrdup (CONST char *str) void *val = xmalloc (len); if (val == 0) return 0; - memcpy (val, str, len); - return (char *) val; + return (char *) memcpy (val, str, len); } #ifdef NEED_STRDUP @@ -375,8 +390,7 @@ strdup (CONST char *s) static void * allocate_lisp_storage (size_t size) { - void *p = xmalloc (size); - return p; + return xmalloc (size); } @@ -465,42 +479,17 @@ disksave_object_finalization_1 (void) } } - -/* This must not be called -- it just serves as for EQ test - * If lheader->implementation->finalizer is this_marks_a_marked_record, - * then lrecord has been marked by the GC sweeper - * header->implementation is put back to its correct value by - * sweep_records */ -void -this_marks_a_marked_record (void *dummy0, int dummy1) -{ - abort (); -} - /* Semi-kludge -- lrecord_symbol_value_forward objects get stuck in CONST space and you get SEGV's if you attempt to mark them. This sits in lheader->implementation->marker. */ Lisp_Object -this_one_is_unmarkable (Lisp_Object obj, void (*markobj) (Lisp_Object)) +this_one_is_unmarkable (Lisp_Object obj) { abort (); return Qnil; } -/* XGCTYPE for records */ -int -gc_record_type_p (Lisp_Object frob, CONST struct lrecord_implementation *type) -{ - CONST struct lrecord_implementation *imp; - - if (XGCTYPE (frob) != Lisp_Type_Record) - return 0; - - imp = XRECORD_LHEADER_IMPLEMENTATION (frob); - return imp == type; -} - /************************************************************************/ /* Debugger support */ @@ -943,12 +932,12 @@ DECLARE_FIXED_TYPE_ALLOC (cons, struct Lisp_Cons); #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_cons 2000 static Lisp_Object -mark_cons (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_cons (Lisp_Object obj) { - if (GC_NILP (XCDR (obj))) + if (NILP (XCDR (obj))) return XCAR (obj); - markobj (XCAR (obj)); + mark_object (XCAR (obj)); return XCDR (obj); } @@ -1096,9 +1085,9 @@ Return a new list of length LENGTH, with each element being INIT. { Lisp_Object val = Qnil; - int size = XINT (length); + size_t size = XINT (length); - while (size-- > 0) + while (size--) val = Fcons (init, val); return val; } @@ -1135,14 +1124,14 @@ make_float (double float_value) /************************************************************************/ static Lisp_Object -mark_vector (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_vector (Lisp_Object obj) { Lisp_Vector *ptr = XVECTOR (obj); int len = vector_length (ptr); int i; for (i = 0; i < len - 1; i++) - markobj (ptr->contents[i]); + mark_object (ptr->contents[i]); return (len > 0) ? ptr->contents[len - 1] : Qnil; } @@ -1172,7 +1161,8 @@ vector_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) static const struct lrecord_description vector_description[] = { { XD_LONG, offsetof(struct Lisp_Vector, size) }, - { XD_LISP_OBJECT, offsetof(struct Lisp_Vector, contents), XD_INDIRECT(0) } + { XD_LISP_OBJECT, offsetof(struct Lisp_Vector, contents), XD_INDIRECT(0, 0) }, + { XD_END } }; DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION("vector", vector, @@ -1545,7 +1535,7 @@ This is terrible behavior which is retained for compatibility with old f->constants = constants; CHECK_NATNUM (stack_depth); - f->stack_depth = XINT (stack_depth); + f->stack_depth = XINT (stack_depth); #ifdef COMPILED_FUNCTION_ANNOTATION_HACK if (!NILP (Vcurrent_compiled_function_annotation)) @@ -1557,7 +1547,7 @@ This is terrible behavior which is retained for compatibility with old struct gcpro gcpro1; GCPRO1 (fun); /* don't let fun get reaped */ Vload_file_name_internal_the_purecopy = - Fpurecopy (Ffile_name_nondirectory (Vload_file_name_internal)); + Ffile_name_nondirectory (Vload_file_name_internal); f->annotated = Vload_file_name_internal_the_purecopy; UNGCPRO; } @@ -1736,11 +1726,11 @@ DECLARE_FIXED_TYPE_ALLOC (string, struct Lisp_String); #define MINIMUM_ALLOWED_FIXED_TYPE_CELLS_string 1000 static Lisp_Object -mark_string (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_string (Lisp_Object obj) { struct Lisp_String *ptr = XSTRING (obj); - if (GC_CONSP (ptr->plist) && GC_EXTENT_INFOP (XCAR (ptr->plist))) + if (CONSP (ptr->plist) && EXTENT_INFOP (XCAR (ptr->plist))) flush_cached_extent_info (XCAR (ptr->plist)); return ptr->plist; } @@ -1754,8 +1744,9 @@ string_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) } static const struct lrecord_description string_description[] = { - { XD_STRING_DATA, offsetof(Lisp_String, data) }, - { XD_LISP_OBJECT, offsetof(Lisp_String, plist), 1 }, + { XD_BYTECOUNT, offsetof(Lisp_String, size) }, + { XD_OPAQUE_DATA_PTR, offsetof(Lisp_String, data), XD_INDIRECT(0, 1) }, + { XD_LISP_OBJECT, offsetof(Lisp_String, plist), 1 }, { XD_END } }; @@ -1791,8 +1782,8 @@ struct string_chars_block unsigned char string_chars[STRING_CHARS_BLOCK_SIZE]; }; -struct string_chars_block *first_string_chars_block; -struct string_chars_block *current_string_chars_block; +static struct string_chars_block *first_string_chars_block; +static struct string_chars_block *current_string_chars_block; /* If SIZE is the length of a string, this returns how many bytes * the string occupies in string_chars_block->string_chars @@ -2079,7 +2070,7 @@ LENGTH must be an integer and INIT must be a character. memset (XSTRING_DATA (val), XCHAR (init), XSTRING_LENGTH (val)); else { - int i; + size_t i; Bufbyte *ptr = XSTRING_DATA (val); for (i = XINT (length); i; i--) @@ -2202,7 +2193,7 @@ make_string_nocopy (CONST Bufbyte *contents, Bytecount length) It works like this: 1) Create an lcrecord-list object using make_lcrecord_list(). - This is often done at initialization. Remember to staticpro + This is often done at initialization. Remember to staticpro_nodump this object! The arguments to make_lcrecord_list() are the same as would be passed to alloc_lcrecord(). 2) Instead of calling alloc_lcrecord(), call allocate_managed_lcrecord() @@ -2223,7 +2214,7 @@ make_string_nocopy (CONST Bufbyte *contents, Bytecount length) */ static Lisp_Object -mark_lcrecord_list (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_lcrecord_list (Lisp_Object obj) { struct lcrecord_list *list = XLCRECORD_LIST (obj); Lisp_Object chain = list->free; @@ -2376,6 +2367,7 @@ struct gcpro *gcprolist; /* 415 used Mly 29-Jun-93 */ /* 1327 used slb 28-Feb-98 */ +/* 1328 used og 03-Oct-99 (moving slowly, heh?) */ #ifdef HAVE_SHLIB #define NSTATICS 4000 #else @@ -2399,24 +2391,89 @@ staticpro (Lisp_Object *varaddress) staticvec[staticidx++] = varaddress; } +/* Not "static" because of linker lossage on some systems */ +Lisp_Object *staticvec_nodump[200] + /* Force it into data space! */ + = {0}; +static int staticidx_nodump; + +/* Put an entry in staticvec_nodump, pointing at the variable whose address is given + */ +void +staticpro_nodump (Lisp_Object *varaddress) +{ + if (staticidx_nodump >= countof (staticvec_nodump)) + /* #### This is now a dubious abort() since this routine may be called */ + /* by Lisp attempting to load a DLL. */ + abort (); + staticvec_nodump[staticidx_nodump++] = varaddress; +} + +/* Not "static" because of linker lossage on some systems */ +struct { + void *data; + const struct struct_description *desc; +} dumpstructvec[200]; + +static int dumpstructidx; + +/* Put an entry in dumpstructvec, pointing at the variable whose address is given + */ +void +dumpstruct (void *varaddress, const struct struct_description *desc) +{ + if (dumpstructidx >= countof (dumpstructvec)) + abort (); + dumpstructvec[dumpstructidx].data = varaddress; + dumpstructvec[dumpstructidx].desc = desc; + dumpstructidx++; +} + +Lisp_Object *pdump_wirevec[50]; +static int pdump_wireidx; + +/* Put an entry in pdump_wirevec, pointing at the variable whose address is given + */ +void +pdump_wire (Lisp_Object *varaddress) +{ + if (pdump_wireidx >= countof (pdump_wirevec)) + abort (); + pdump_wirevec[pdump_wireidx++] = varaddress; +} + + +Lisp_Object *pdump_wirevec_list[50]; +static int pdump_wireidx_list; + +/* Put an entry in pdump_wirevec_list, pointing at the variable whose address is given + */ +void +pdump_wire_list (Lisp_Object *varaddress) +{ + if (pdump_wireidx_list >= countof (pdump_wirevec_list)) + abort (); + pdump_wirevec_list[pdump_wireidx_list++] = varaddress; +} + /* Mark reference to a Lisp_Object. If the object referred to has not been seen yet, recursively mark all the references contained in it. */ -static void +void mark_object (Lisp_Object obj) { tail_recurse: #ifdef ERROR_CHECK_GC - assert (! (GC_EQ (obj, Qnull_pointer))); + assert (! (EQ (obj, Qnull_pointer))); #endif /* Checks we used to perform */ /* if (EQ (obj, Qnull_pointer)) return; */ /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return; */ /* if (PURIFIED (XPNTR (obj))) return; */ - if (XGCTYPE (obj) == Lisp_Type_Record) + if (XTYPE (obj) == Lisp_Type_Record) { struct lrecord_header *lheader = XRECORD_LHEADER (obj); #if defined (ERROR_CHECK_GC) @@ -2437,8 +2494,8 @@ mark_object (Lisp_Object obj) #endif if (implementation->marker) { - obj = implementation->marker (obj, mark_object); - if (!GC_NILP (obj)) goto tail_recurse; + obj = implementation->marker (obj); + if (!NILP (obj)) goto tail_recurse; } } } @@ -2911,7 +2968,7 @@ free_marker (struct Lisp_Marker *ptr) /* Perhaps this will catch freeing an already-freed marker. */ Lisp_Object temmy; XSETMARKER (temmy, ptr); - assert (GC_MARKERP (temmy)); + assert (MARKERP (temmy)); #endif /* ERROR_CHECK_GC */ #ifndef ALLOC_NO_POOLS @@ -3124,18 +3181,18 @@ sweep_strings (void) /* I hate duplicating all this crap! */ -static int +int marked_p (Lisp_Object obj) { #ifdef ERROR_CHECK_GC - assert (! (GC_EQ (obj, Qnull_pointer))); + assert (! (EQ (obj, Qnull_pointer))); #endif /* Checks we used to perform. */ /* if (EQ (obj, Qnull_pointer)) return 1; */ /* if (!POINTER_TYPE_P (XGCTYPE (obj))) return 1; */ /* if (PURIFIED (XPNTR (obj))) return 1; */ - if (XGCTYPE (obj) == Lisp_Type_Record) + if (XTYPE (obj) == Lisp_Type_Record) { struct lrecord_header *lheader = XRECORD_LHEADER (obj); #if defined (ERROR_CHECK_GC) @@ -3205,6 +3262,27 @@ gc_sweep (void) sweep_events (); +#ifdef PDUMP + /* Unmark all dumped objects */ + { + int i; + char *p = pdump_rt_list; + if(p) + for(;;) + { + pdump_reloc_table *rt = (pdump_reloc_table *)p; + p += sizeof (pdump_reloc_table); + if (rt->desc) { + for (i=0; icount; i++) + { + UNMARK_RECORD_HEADER ((struct lrecord_header *)(*(EMACS_INT *)p)); + p += sizeof (EMACS_INT); + } + } else + break; + } + } +#endif } /* Clearing for disksave. */ @@ -3406,6 +3484,8 @@ garbage_collect_1 (void) int i; for (i = 0; i < staticidx; i++) mark_object (*(staticvec[i])); + for (i = 0; i < staticidx_nodump; i++) + mark_object (*(staticvec_nodump[i])); } { /* GCPRO() */ @@ -3450,8 +3530,8 @@ garbage_collect_1 (void) } } - mark_redisplay (mark_object); - mark_profiling_info (mark_object); + mark_redisplay (); + mark_profiling_info (); /* OK, now do the after-mark stuff. This is for things that are only marked when something else is marked (e.g. weak hash tables). @@ -3460,18 +3540,18 @@ garbage_collect_1 (void) weak hash table, the former one might get marked. So we have to iterate until nothing more gets marked. */ - while (finish_marking_weak_hash_tables (marked_p, mark_object) > 0 || - finish_marking_weak_lists (marked_p, mark_object) > 0) + while (finish_marking_weak_hash_tables () > 0 || + finish_marking_weak_lists () > 0) ; /* And prune (this needs to be called after everything else has been marked and before we do any sweeping). */ /* #### this is somewhat ad-hoc and should probably be an object method */ - prune_weak_hash_tables (marked_p); - prune_weak_lists (marked_p); - prune_specifiers (marked_p); - prune_syntax_tables (marked_p); + prune_weak_hash_tables (); + prune_weak_lists (); + prune_specifiers (); + prune_syntax_tables (); gc_sweep (); @@ -3565,7 +3645,7 @@ Garbage collection happens automatically if you cons more than garbage_collect_1 (); - for (i = 0; i < last_lrecord_type_index_assigned; i++) + for (i = 0; i <= last_lrecord_type_index_assigned; i++) { if (lcrecord_stats[i].bytes_in_use != 0 || lcrecord_stats[i].bytes_freed != 0 @@ -3839,32 +3919,8 @@ fixed_type_block_overhead (size_t size) /* Initialization */ void -init_alloc_once_early (void) +reinit_alloc_once_early (void) { - int iii; - - last_lrecord_type_index_assigned = -1; - for (iii = 0; iii < countof (lrecord_implementations_table); iii++) - { - lrecord_implementations_table[iii] = 0; - } - - /* - * All the staticly - * defined subr lrecords were initialized with lheader->type == 0. - * See subr_lheader_initializer in lisp.h. Force type index 0 to be - * assigned to lrecord_subr so that those predefined indexes match - * reality. - */ - lrecord_type_index (&lrecord_subr); - assert (*(lrecord_subr.lrecord_type_index) == 0); - /* - * The same is true for symbol_value_forward objects, except the - * type is 1. - */ - lrecord_type_index (&lrecord_symbol_value_forward); - assert (*(lrecord_symbol_value_forward.lrecord_type_index) == 1); - gc_generation_number[0] = 0; /* purify_flag 1 is correct even if CANNOT_DUMP. * loadup.el will set to nil at end. */ @@ -3894,7 +3950,11 @@ init_alloc_once_early (void) init_event_alloc (); ignore_malloc_warnings = 0; - staticidx = 0; + + staticidx_nodump = 0; + dumpstructidx = 0; + pdump_wireidx = 0; + consing_since_gc = 0; #if 1 gc_cons_threshold = 500000; /* XEmacs change */ @@ -3923,6 +3983,38 @@ init_alloc_once_early (void) #endif /* ERROR_CHECK_TYPECHECK */ } +void +init_alloc_once_early (void) +{ + int iii; + + reinit_alloc_once_early (); + + last_lrecord_type_index_assigned = -1; + for (iii = 0; iii < countof (lrecord_implementations_table); iii++) + { + lrecord_implementations_table[iii] = 0; + } + + /* + * All the staticly + * defined subr lrecords were initialized with lheader->type == 0. + * See subr_lheader_initializer in lisp.h. Force type index 0 to be + * assigned to lrecord_subr so that those predefined indexes match + * reality. + */ + lrecord_type_index (&lrecord_subr); + assert (*(lrecord_subr.lrecord_type_index) == 0); + /* + * The same is true for symbol_value_forward objects, except the + * type is 1. + */ + lrecord_type_index (&lrecord_symbol_value_forward); + assert (*(lrecord_symbol_value_forward.lrecord_type_index) == 1); + + staticidx = 0; +} + int pure_bytes_used = 0; void @@ -4030,8 +4122,7 @@ window system and `gc-pointer-glyph' specifies a value (i.e. a pointer image instance) in the domain of the selected frame, the mouse pointer will change instead of this message being printed. */ ); - Vgc_message = make_string_nocopy ((CONST Bufbyte *) gc_default_message, - countof (gc_default_message) - 1); + Vgc_message = build_string (gc_default_message); DEFVAR_LISP ("gc-pointer-glyph", &Vgc_pointer_glyph /* Pointer glyph used to indicate that a garbage collection is in progress. @@ -4048,3 +4139,982 @@ complex_vars_of_alloc (void) { Vgc_pointer_glyph = Fmake_glyph_internal (Qpointer); } + + +#ifdef PDUMP + +/* The structure of the file + * + * 0 - header + * 256 - dumped objects + * stab_offset - nb_staticpro*(Lisp_Object *) from staticvec + * - nb_staticpro*(relocated Lisp_Object) pointed to by staticpro + * - nb_structdmp*pair(void *, adr) for pointers to structures + * - lrecord_implementations_table[] + * - relocation table + * - wired variable address/value couples with the count preceding the list + */ +typedef struct +{ + char signature[8]; + EMACS_UINT stab_offset; + EMACS_UINT reloc_address; + int nb_staticpro; + int nb_structdmp; + int last_type; +} dump_header; + +char *pdump_start, *pdump_end; + +static const unsigned char align_table[256] = +{ + 8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 7, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 6, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 5, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, + 4, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0 +}; + +typedef struct pdump_entry_list_elmt +{ + struct pdump_entry_list_elmt *next; + const void *obj; + size_t size; + int count; + int is_lrecord; + EMACS_INT save_offset; +} pdump_entry_list_elmt; + +typedef struct +{ + pdump_entry_list_elmt *first; + int align; + int count; +} pdump_entry_list; + +typedef struct pdump_struct_list_elmt +{ + pdump_entry_list list; + const struct struct_description *sdesc; +} pdump_struct_list_elmt; + +typedef struct +{ + pdump_struct_list_elmt *list; + int count; + int size; +} pdump_struct_list; + +static pdump_entry_list pdump_object_table[256]; +static pdump_entry_list pdump_opaque_data_list; +static pdump_struct_list pdump_struct_table; +static pdump_entry_list_elmt *pdump_qnil; + +static int pdump_alert_undump_object[256]; + +static unsigned long cur_offset; +static size_t max_size; +static int pdump_fd; +static void *pdump_buf; + +#define PDUMP_HASHSIZE 200001 + +static pdump_entry_list_elmt **pdump_hash; + +/* Since most pointers are eight bytes aligned, the >>3 allows for a better hash */ +static int +pdump_make_hash (const void *obj) +{ + return ((unsigned long)(obj)>>3) % PDUMP_HASHSIZE; +} + +static pdump_entry_list_elmt * +pdump_get_entry (const void *obj) +{ + int pos = pdump_make_hash(obj); + pdump_entry_list_elmt *e; + while ((e = pdump_hash[pos]) != 0) + { + if (e->obj == obj) + return e; + + pos++; + if (pos == PDUMP_HASHSIZE) + pos = 0; + } + return 0; +} + +static void +pdump_add_entry (pdump_entry_list *list, const void *obj, size_t size, int count, int is_lrecord) +{ + pdump_entry_list_elmt *e; + int align; + int pos = pdump_make_hash (obj); + + while ((e = pdump_hash[pos]) != 0) + { + if (e->obj == obj) + return; + + pos++; + if (pos == PDUMP_HASHSIZE) + pos = 0; + } + + e = malloc (sizeof (pdump_entry_list_elmt)); + + e->next = list->first; + e->obj = obj; + e->size = size; + e->count = count; + e->is_lrecord = is_lrecord; + list->first = e; + + list->count += count; + pdump_hash[pos] = e; + + align = align_table[size & 255]; + if (align<2 && is_lrecord) + align = 2; + + if(align < list->align) + list->align = align; +} + +static pdump_entry_list * +pdump_get_entry_list(const struct struct_description *sdesc) +{ + int i; + for(i=0; iname, + backtrace[i].position, + backtrace[i].offset); + } + } +} + +static void pdump_register_object (Lisp_Object obj); +static void pdump_register_struct (const void *data, const struct struct_description *sdesc, int count); + +static EMACS_INT +pdump_get_indirect_count (EMACS_INT code, const struct lrecord_description *idesc, const void *idata) +{ + EMACS_INT count; + const void *irdata; + + int line = XD_INDIRECT_VAL (code); + int delta = XD_INDIRECT_DELTA (code); + + irdata = ((char *)idata) + idesc[line].offset; + switch (idesc[line].type) { + case XD_SIZE_T: + count = *(size_t *)irdata; + break; + case XD_INT: + count = *(int *)irdata; + break; + case XD_LONG: + count = *(long *)irdata; + break; + case XD_BYTECOUNT: + count = *(Bytecount *)irdata; + break; + default: + fprintf (stderr, "Unsupported count type : %d (line = %d, code=%ld)\n", idesc[line].type, line, (long)code); + pdump_backtrace (); + abort (); + } + count += delta; + return count; +} + +static void +pdump_register_sub (const void *data, const struct lrecord_description *desc, int me) +{ + int pos; + const void *rdata; + + restart: + for (pos = 0; desc[pos].type != XD_END; pos++) + { + backtrace[me].position = pos; + backtrace[me].offset = desc[pos].offset; + + rdata = ((const char *)data) + desc[pos].offset; + switch(desc[pos].type) + { + case XD_SPECIFIER_END: + pos = 0; + desc = ((const struct Lisp_Specifier *)data)->methods->extra_description; + goto restart; + case XD_SIZE_T: + case XD_INT: + case XD_LONG: + case XD_BYTECOUNT: + case XD_LO_RESET_NIL: + case XD_INT_RESET: + case XD_LO_LINK: + break; + case XD_OPAQUE_DATA_PTR: + { + EMACS_INT count = desc[pos].data1; + if (XD_IS_INDIRECT(count)) + count = pdump_get_indirect_count (count, desc, data); + + pdump_add_entry (&pdump_opaque_data_list, + *(void **)rdata, + count, + 1, + 0); + break; + } + case XD_C_STRING: + { + const char *str = *(const char **)rdata; + if (str) + pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1, 0); + break; + } + case XD_DOC_STRING: + { + const char *str = *(const char **)rdata; + if ((EMACS_INT)str > 0) + pdump_add_entry (&pdump_opaque_data_list, str, strlen (str)+1, 1, 0); + break; + } + case XD_LISP_OBJECT: + { + EMACS_INT count = desc[pos].data1; + int i; + if (XD_IS_INDIRECT (count)) + count = pdump_get_indirect_count (count, desc, data); + + for(i=0;idescription) + { + int me = depth++; + if (me>65536) + { + fprintf (stderr, "Backtrace overflow, loop ?\n"); + abort (); + } + backtrace[me].obj = obj; + backtrace[me].position = 0; + backtrace[me].offset = 0; + + pdump_add_entry (pdump_object_table + XRECORD_LHEADER (obj)->type, + XRECORD_LHEADER (obj), + XRECORD_LHEADER_IMPLEMENTATION (obj)->static_size ? + XRECORD_LHEADER_IMPLEMENTATION (obj)->static_size : + XRECORD_LHEADER_IMPLEMENTATION (obj)->size_in_bytes_method (XRECORD_LHEADER (obj)), + 1, + 1); + pdump_register_sub (XRECORD_LHEADER (obj), + XRECORD_LHEADER_IMPLEMENTATION (obj)->description, + me); + --depth; + } + else + { + pdump_alert_undump_object[XRECORD_LHEADER (obj)->type]++; + fprintf (stderr, "Undumpable object type : %s\n", XRECORD_LHEADER_IMPLEMENTATION (obj)->name); + pdump_backtrace (); + } +} + +static void +pdump_register_struct (const void *data, const struct struct_description *sdesc, int count) +{ + if (data && !pdump_get_entry (data)) + { + int me = depth++; + int i; + if (me>65536) + { + fprintf (stderr, "Backtrace overflow, loop ?\n"); + abort (); + } + backtrace[me].obj = 0; + backtrace[me].position = 0; + backtrace[me].offset = 0; + + pdump_add_entry (pdump_get_entry_list (sdesc), + data, + sdesc->size, + count, + 0); + for (i=0; isize*i, + sdesc->description, + me); + } + --depth; + } +} + +static void +pdump_dump_data (pdump_entry_list_elmt *elmt, const struct lrecord_description *desc) +{ + size_t size = elmt->size; + int count = elmt->count; + if (desc) + { + int pos, i; + void *rdata; + memcpy (pdump_buf, elmt->obj, size*count); + + for (i=0; iobj))->methods->extra_description; + goto restart; + case XD_SIZE_T: + case XD_INT: + case XD_LONG: + case XD_BYTECOUNT: + break; + case XD_LO_RESET_NIL: + { + EMACS_INT count = desc[pos].data1; + int i; + if (XD_IS_INDIRECT (count)) + count = pdump_get_indirect_count (count, desc, elmt->obj); + for (i=0; isave_offset; + break; + } + case XD_INT_RESET: + { + EMACS_INT val = desc[pos].data1; + if (XD_IS_INDIRECT (val)) + val = pdump_get_indirect_count (val, desc, elmt->obj); + *(int *)rdata = val; + break; + } + case XD_OPAQUE_DATA_PTR: + case XD_C_STRING: + case XD_STRUCT_PTR: + { + void *ptr = *(void **)rdata; + if (ptr) + *(EMACS_INT *)rdata = pdump_get_entry (ptr)->save_offset; + break; + } + case XD_LO_LINK: + { + Lisp_Object obj = *(Lisp_Object *)rdata; + pdump_entry_list_elmt *elmt1; + for(;;) + { + elmt1 = pdump_get_entry (XRECORD_LHEADER(obj)); + if (elmt1) + break; + obj = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj))); + } + *(EMACS_INT *)rdata = elmt1->save_offset; + break; + } + case XD_LISP_OBJECT: + { + EMACS_INT count = desc[pos].data1; + int i; + if (XD_IS_INDIRECT (count)) + count = pdump_get_indirect_count (count, desc, elmt->obj); + + for(i=0; isave_offset; + } + break; + } + case XD_DOC_STRING: + { + EMACS_INT str = *(EMACS_INT *)rdata; + if (str > 0) + *(EMACS_INT *)rdata = pdump_get_entry ((void *)str)->save_offset; + break; + } + default: + fprintf (stderr, "Unsupported dump type : %d\n", desc[pos].type); + abort (); + }; + } + } + } + write (pdump_fd, desc ? pdump_buf : elmt->obj, size*count); + if (elmt->is_lrecord && ((size*count) & 3)) + write (pdump_fd, "\0\0\0", 4-((size*count) & 3)); +} + +static void +pdump_reloc_one (void *data, EMACS_INT delta, const struct lrecord_description *desc) +{ + int pos; + void *rdata; + + restart: + for (pos = 0; desc[pos].type != XD_END; pos++) + { + rdata = ((char *)data) + desc[pos].offset; + switch (desc[pos].type) { + case XD_SPECIFIER_END: + pos = 0; + desc = ((const struct Lisp_Specifier *)data)->methods->extra_description; + goto restart; + case XD_SIZE_T: + case XD_INT: + case XD_LONG: + case XD_BYTECOUNT: + case XD_INT_RESET: + break; + case XD_OPAQUE_DATA_PTR: + case XD_C_STRING: + case XD_STRUCT_PTR: + case XD_LO_LINK: + { + EMACS_INT ptr = *(EMACS_INT *)rdata; + if (ptr) + *(EMACS_INT *)rdata = ptr+delta; + break; + } + case XD_LISP_OBJECT: + case XD_LO_RESET_NIL: + { + EMACS_INT count = desc[pos].data1; + int i; + if (XD_IS_INDIRECT (count)) + count = pdump_get_indirect_count (count, desc, data); + + for (i=0; i 0) + *(EMACS_INT *)rdata = str + delta; + break; + } + default: + fprintf (stderr, "Unsupported dump type : %d\n", desc[pos].type); + abort (); + }; + } +} + +static void +pdump_allocate_offset (pdump_entry_list_elmt *elmt, const struct lrecord_description *desc) +{ + size_t size = (elmt->is_lrecord ? (elmt->size + 3) & ~3 : elmt->size)*elmt->count; + elmt->save_offset = cur_offset; + if (size>max_size) + max_size = size; + cur_offset += size; +} + +static void +pdump_scan_by_alignement (void (*f)(pdump_entry_list_elmt *, const struct lrecord_description *)) +{ + int align, i; + const struct lrecord_description *idesc; + pdump_entry_list_elmt *elmt; + for (align=8; align>=0; align--) + { + for (i=0; i<=last_lrecord_type_index_assigned; i++) + if (pdump_object_table[i].align == align) + { + elmt = pdump_object_table[i].first; + if (!elmt) + continue; + idesc = lrecord_implementations_table[i]->description; + while (elmt) + { + f (elmt, idesc); + elmt = elmt->next; + } + } + + for (i=0; idescription; + while (elmt) + { + f (elmt, idesc); + elmt = elmt->next; + } + } + + elmt = pdump_opaque_data_list.first; + while (elmt) + { + if (align_table[elmt->size & 255] == align) + f (elmt, 0); + elmt = elmt->next; + } + } +} + +static void +pdump_dump_staticvec (void) +{ + Lisp_Object *reloc = malloc (staticidx*sizeof (Lisp_Object)); + int i; + write (pdump_fd, staticvec, staticidx*sizeof (Lisp_Object *)); + + for(i=0; isave_offset; + else + reloc[i] = obj; + } + write (pdump_fd, reloc, staticidx*sizeof (Lisp_Object)); + free (reloc); +} + +static void +pdump_dump_structvec (void) +{ + int i; + for (i=0; isave_offset; + write (pdump_fd, &adr, sizeof (adr)); + } +} + +static void +pdump_dump_itable (void) +{ + write (pdump_fd, lrecord_implementations_table, sizeof (lrecord_implementations_table)); +} + +static void +pdump_dump_rtables (void) +{ + int i, j; + pdump_entry_list_elmt *elmt; + pdump_reloc_table rt; + + for (i=0; i<=last_lrecord_type_index_assigned; i++) + { + elmt = pdump_object_table[i].first; + if(!elmt) + continue; + rt.desc = lrecord_implementations_table[i]->description; + rt.count = pdump_object_table[i].count; + write (pdump_fd, &rt, sizeof (rt)); + while (elmt) + { + EMACS_INT rdata = pdump_get_entry (XRECORD_LHEADER (elmt->obj))->save_offset; + write (pdump_fd, &rdata, sizeof (rdata)); + elmt = elmt->next; + } + } + + rt.desc = 0; + rt.count = 0; + write (pdump_fd, &rt, sizeof (rt)); + + for (i=0; idescription; + rt.count = pdump_struct_table.list[i].list.count; + write (pdump_fd, &rt, sizeof (rt)); + while (elmt) + { + EMACS_INT rdata = pdump_get_entry (XRECORD_LHEADER (elmt->obj))->save_offset; + for (j=0; jcount; j++) { + write (pdump_fd, &rdata, sizeof (rdata)); + rdata += elmt->size; + } + elmt = elmt->next; + } + } + rt.desc = 0; + rt.count = 0; + write (pdump_fd, &rt, sizeof (rt)); +} + +static void +pdump_dump_wired (void) +{ + EMACS_INT count = pdump_wireidx + pdump_wireidx_list; + int i; + + write (pdump_fd, &count, sizeof (count)); + + for (i=0; isave_offset; + write (pdump_fd, &pdump_wirevec[i], sizeof (pdump_wirevec[i])); + write (pdump_fd, &obj, sizeof (obj)); + } + + for (i=0; idescription; + for (pos = 0; desc[pos].type != XD_LO_LINK; pos++) + if (desc[pos].type == XD_END) + abort (); + + obj = *(Lisp_Object *)(desc[pos].offset + (char *)(XRECORD_LHEADER (obj))); + } + res = elmt->save_offset; + + write (pdump_fd, &pdump_wirevec_list[i], sizeof (pdump_wirevec_list[i])); + write (pdump_fd, &res, sizeof (res)); + } +} + +void +pdump (void) +{ + int i; + Lisp_Object t_console, t_device, t_frame; + int none; + dump_header hd; + + /* These appear in a DEFVAR_LISP, which does a staticpro() */ + t_console = Vterminal_console; + t_frame = Vterminal_frame; + t_device = Vterminal_device; + + Vterminal_console = Qnil; + Vterminal_frame = Qnil; + Vterminal_device = Qnil; + + pdump_hash = malloc (PDUMP_HASHSIZE*sizeof (pdump_entry_list_elmt *)); + memset (pdump_hash, 0, PDUMP_HASHSIZE*sizeof (pdump_entry_list_elmt *)); + + for (i=0; i<=last_lrecord_type_index_assigned; i++) + { + pdump_object_table[i].first = 0; + pdump_object_table[i].align = 8; + pdump_object_table[i].count = 0; + pdump_alert_undump_object[i] = 0; + } + pdump_struct_table.count = 0; + pdump_struct_table.size = -1; + + pdump_opaque_data_list.first = 0; + pdump_opaque_data_list.align = 8; + pdump_opaque_data_list.count = 0; + depth = 0; + + for (i=0; iname, pdump_alert_undump_object[i]); + } + if (!none) + return; + + for (i=0; inb_staticpro; + last_lrecord_type_index_assigned = ((dump_header *)(pdump_start))->last_type; + delta = ((EMACS_INT)pdump_start) - ((dump_header *)pdump_start)->reloc_address; + p = pdump_start + ((dump_header *)pdump_start)->stab_offset; + + /* Put back the staticvec in place */ + memcpy (staticvec, p, staticidx*sizeof (Lisp_Object *)); + p += staticidx*sizeof (Lisp_Object *); + for (i=0; inb_structdmp; i++) + { + void **adr = *(void **)p; + p += sizeof (void *); + *adr = (void *)((*(EMACS_INT *)p) + delta); + p += sizeof (EMACS_INT); + } + + /* Put back the lrecord_implementations_table */ + memcpy (lrecord_implementations_table, p, sizeof (lrecord_implementations_table)); + p += sizeof (lrecord_implementations_table); + + /* Give back their numbers to the lrecord implementations */ + for (i=0; ilrecord_type_index) = i; + last_lrecord_type_index_assigned = i; + } + + /* Do the relocations */ + pdump_rt_list = p; + count = 2; + for(;;) + { + pdump_reloc_table *rt = (pdump_reloc_table *)p; + p += sizeof (pdump_reloc_table); + if (rt->desc) { + for (i=0; icount; i++) + { + EMACS_INT adr = delta + *(EMACS_INT *)p; + *(EMACS_INT *)p = adr; + pdump_reloc_one ((void *)adr, delta, rt->desc); + p += sizeof (EMACS_INT); + } + } else + if(!(--count)) + break; + } + + /* Put the pdump_wire variables in place */ + count = *(EMACS_INT *)p; + p += sizeof(EMACS_INT); + + for (i=0; idesc) + break; + if (rt->desc == hash_table_description) + { + for (i=0; icount; i++) + { + struct Lisp_Hash_Table *ht = XHASH_TABLE (*(EMACS_INT *)p); + reorganize_hash_table (ht); + p += sizeof (EMACS_INT); + } + break; + } else + p += sizeof (EMACS_INT)*rt->count; + } + return 1; +} + +#endif diff --git a/src/buffer.c b/src/buffer.c index 0c59b8e..ec6afef 100644 --- a/src/buffer.c +++ b/src/buffer.c @@ -96,6 +96,7 @@ struct buffer *current_buffer; /* the current buffer */ Setting the default value also goes through the alist of buffers and stores into each buffer that does not say it has a local value. */ Lisp_Object Vbuffer_defaults; +static void *buffer_defaults_saved_slots; /* This structure marks which slots in a buffer have corresponding default values in Vbuffer_defaults. @@ -133,6 +134,7 @@ char initial_directory[MAXPATHLEN+1]; /* This structure holds the names of symbols whose values may be buffer-local. It is indexed and accessed in the same way as the above. */ static Lisp_Object Vbuffer_local_symbols; +static void *buffer_local_symbols_saved_slots; /* Alist of all buffer names vs the buffers. */ /* This used to be a variable, but is no longer, @@ -189,7 +191,7 @@ Lisp_Object QSscratch; /* "*scratch*" */ Lisp_Object Qdefault_directory; Lisp_Object Qkill_buffer_hook; -Lisp_Object Qbuffer_file_name, Qbuffer_undo_list; +Lisp_Object Qrecord_buffer_hook; Lisp_Object Qrename_auto_save_file; @@ -220,7 +222,7 @@ make_buffer (struct buffer *buf) } static Lisp_Object -mark_buffer (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_buffer (Lisp_Object obj) { struct buffer *buf = XBUFFER (obj); @@ -229,13 +231,13 @@ mark_buffer (Lisp_Object obj, void (*markobj) (Lisp_Object)) undo_threshold, undo_high_threshold); -#define MARKED_SLOT(x) ((void) (markobj (buf->x))); +#define MARKED_SLOT(x) mark_object (buf->x) #include "bufslots.h" #undef MARKED_SLOT - markobj (buf->extent_info); + mark_object (buf->extent_info); if (buf->text) - markobj (buf->text->line_number_cache); + mark_object (buf->text->line_number_cache); /* Don't mark normally through the children slot. (Actually, in this case, it doesn't matter.) */ @@ -1406,6 +1408,9 @@ buffer. See `other-buffer' for more information. XCDR (prev) = XCDR (XCDR (prev)); XCDR (lynk) = f->buffer_alist; f->buffer_alist = lynk; + + va_run_hook_with_args (Qrecord_buffer_hook, 1, buffer); + return Qnil; } @@ -1806,6 +1811,7 @@ syms_of_buffer (void) defsymbol (&Qmode_class, "mode-class"); defsymbol (&Qrename_auto_save_file, "rename-auto-save-file"); defsymbol (&Qkill_buffer_hook, "kill-buffer-hook"); + defsymbol (&Qrecord_buffer_hook, "record-buffer-hook"); defsymbol (&Qpermanent_local, "permanent-local"); defsymbol (&Qfirst_change_hook, "first-change-hook"); @@ -1816,8 +1822,6 @@ syms_of_buffer (void) defsymbol (&Qbefore_change_function, "before-change-function"); defsymbol (&Qafter_change_function, "after-change-function"); - defsymbol (&Qbuffer_file_name, "buffer-file-name"); - defsymbol (&Qbuffer_undo_list, "buffer-undo-list"); defsymbol (&Qdefault_directory, "default-directory"); defsymbol (&Qget_file_buffer, "get-file-buffer"); @@ -1870,20 +1874,26 @@ syms_of_buffer (void) "Attempt to modify a protected field", Qerror); } +void +reinit_vars_of_buffer (void) +{ + staticpro_nodump (&Vbuffer_alist); + Vbuffer_alist = Qnil; + current_buffer = 0; +} + /* initialize the buffer routines */ void vars_of_buffer (void) { /* This function can GC */ + reinit_vars_of_buffer (); + staticpro (&QSFundamental); staticpro (&QSscratch); - staticpro (&Vbuffer_alist); - QSFundamental = Fpurecopy (build_string ("Fundamental")); - QSscratch = Fpurecopy (build_string (DEFER_GETTEXT ("*scratch*"))); - - Vbuffer_alist = Qnil; - current_buffer = 0; + QSFundamental = build_string ("Fundamental"); + QSscratch = build_string (DEFER_GETTEXT ("*scratch*")); DEFVAR_LISP ("change-major-mode-hook", &Vchange_major_mode_hook /* List of hooks to be run before killing local variables in a buffer. @@ -2063,21 +2073,21 @@ nuke_all_buffer_slots (struct buffer *b, Lisp_Object zap) b->indirect_children = Qnil; b->own_text.line_number_cache = Qnil; -#define MARKED_SLOT(x) b->x = (zap); +#define MARKED_SLOT(x) b->x = zap #include "bufslots.h" #undef MARKED_SLOT } -void -complex_vars_of_buffer (void) +static void +common_init_complex_vars_of_buffer (void) { /* Make sure all markable slots in buffer_defaults are initialized reasonably, so mark_buffer won't choke. */ struct buffer *defs = alloc_lcrecord_type (struct buffer, &lrecord_buffer); struct buffer *syms = alloc_lcrecord_type (struct buffer, &lrecord_buffer); - staticpro (&Vbuffer_defaults); - staticpro (&Vbuffer_local_symbols); + staticpro_nodump (&Vbuffer_defaults); + staticpro_nodump (&Vbuffer_local_symbols); XSETBUFFER (Vbuffer_defaults, defs); XSETBUFFER (Vbuffer_local_symbols, syms); @@ -2193,11 +2203,57 @@ complex_vars_of_buffer (void) buffer_local_flags.buffer_file_coding_system = make_int (1<<14); #endif - /* #### Warning: 1<<28 is the largest number currently allowable + /* #### Warning: 1<<31 is the largest number currently allowable due to the XINT() handling of this value. With some rearrangement you can get 3 more bits. */ } +} + +#define BUFFER_SLOTS_SIZE (offsetof (struct buffer, BUFFER_SLOTS_LAST_NAME) - offsetof (struct buffer, BUFFER_SLOTS_FIRST_NAME) + sizeof (Lisp_Object)) +#define BUFFER_SLOTS_COUNT (BUFFER_SLOTS_SIZE / sizeof (Lisp_Object)) + +void +reinit_complex_vars_of_buffer (void) +{ + struct buffer *defs, *syms; + + common_init_complex_vars_of_buffer (); + + defs = XBUFFER (Vbuffer_defaults); + syms = XBUFFER (Vbuffer_local_symbols); + memcpy (&defs->BUFFER_SLOTS_FIRST_NAME, + buffer_defaults_saved_slots, + BUFFER_SLOTS_SIZE); + memcpy (&syms->BUFFER_SLOTS_FIRST_NAME, + buffer_local_symbols_saved_slots, + BUFFER_SLOTS_SIZE); +} + + +static const struct lrecord_description buffer_slots_description_1[] = { + { XD_LISP_OBJECT, 0, BUFFER_SLOTS_COUNT }, + { XD_END } +}; + +static const struct struct_description buffer_slots_description = { + BUFFER_SLOTS_SIZE, + buffer_slots_description_1 +}; + +void +complex_vars_of_buffer (void) +{ + struct buffer *defs, *syms; + + common_init_complex_vars_of_buffer (); + defs = XBUFFER (Vbuffer_defaults); + syms = XBUFFER (Vbuffer_local_symbols); + buffer_defaults_saved_slots = &defs->BUFFER_SLOTS_FIRST_NAME; + buffer_local_symbols_saved_slots = &syms->BUFFER_SLOTS_FIRST_NAME; + dumpstruct (&buffer_defaults_saved_slots, &buffer_slots_description); + dumpstruct (&buffer_local_symbols_saved_slots, &buffer_slots_description); + DEFVAR_BUFFER_DEFAULTS ("default-modeline-format", modeline_format /* Default value of `modeline-format' for buffers that don't override it. This is the same as (default-value 'modeline-format). diff --git a/src/buffer.h b/src/buffer.h index 11c037e..2c5498d 100644 --- a/src/buffer.h +++ b/src/buffer.h @@ -219,7 +219,6 @@ DECLARE_LRECORD (buffer, struct buffer); #define XBUFFER(x) XRECORD (x, buffer, struct buffer) #define XSETBUFFER(x, p) XSETRECORD (x, p, buffer) #define BUFFERP(x) RECORDP (x, buffer) -#define GC_BUFFERP(x) GC_RECORDP (x, buffer) #define CHECK_BUFFER(x) CHECK_RECORD (x, buffer) #define CONCHECK_BUFFER(x) CONCHECK_RECORD (x, buffer) @@ -568,7 +567,7 @@ XCHAR_OR_CHAR_INT (Lisp_Object obj) #else -#define XCHAR_OR_CHAR_INT(obj) (CHARP ((obj)) ? XCHAR ((obj)) : XINT ((obj))) +#define XCHAR_OR_CHAR_INT(obj) (CHARP (obj) ? XCHAR (obj) : XINT (obj)) #endif diff --git a/src/bufslots.h b/src/bufslots.h index 88f5daf..a5430e0 100644 --- a/src/bufslots.h +++ b/src/bufslots.h @@ -32,6 +32,10 @@ Boston, MA 02111-1307, USA. */ definition. In the garbage collector this file is included after defining MARKED_SLOT(x) to be mark_object(buffer->x). */ +#ifndef BUFFER_SLOTS_FIRST_NAME +#define BUFFER_SLOTS_FIRST_NAME name +#endif + /* The name of this buffer. */ MARKED_SLOT (name); @@ -235,6 +239,11 @@ Boston, MA 02111-1307, USA. */ /* A hash table that maps from a "generic extent" (an extent in `modeline-format') into a buffer-specific extent. */ MARKED_SLOT (modeline_extent_table); + +#ifndef BUFFER_SLOTS_LAST_NAME +#define BUFFER_SLOTS_LAST_NAME modeline_extent_table +#endif + #if 0 /* FSFmacs */ /* This is silly and stupid */ /* These are so we don't have to recompile everything diff --git a/src/bytecode.c b/src/bytecode.c index af9d3f4..8a685ab 100644 --- a/src/bytecode.c +++ b/src/bytecode.c @@ -235,21 +235,17 @@ extern Lisp_Object Qand_rest, Qand_optional; Lisp_Object Vbyte_code_meter, Qbyte_code_meter; int byte_metering_on; -#define METER_2(code1, code2) \ - XINT (XVECTOR_DATA (XVECTOR_DATA (Vbyte_code_meter)[(code1)])[(code2)]) - -#define METER_1(code) METER_2 (0, (code)) - -#define METER_CODE(last_code, this_code) do { \ - if (byte_metering_on) \ - { \ - if (METER_1 (this_code) != ((1<specpdl_depth = XINT (Flength (f->arglist)) + varbind_count; f->instructions = - Fpurecopy (make_opaque (program_length * sizeof (Opbyte), - (CONST void *) program)); + make_opaque (program_length * sizeof (Opbyte), + (CONST void *) program); } assert (OPAQUEP (f->instructions)); @@ -1981,15 +1977,15 @@ print_compiled_function (Lisp_Object obj, Lisp_Object printcharfun, static Lisp_Object -mark_compiled_function (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_compiled_function (Lisp_Object obj) { Lisp_Compiled_Function *f = XCOMPILED_FUNCTION (obj); - markobj (f->instructions); - markobj (f->arglist); - markobj (f->doc_and_interactive); + mark_object (f->instructions); + mark_object (f->arglist); + mark_object (f->doc_and_interactive); #ifdef COMPILED_FUNCTION_ANNOTATION_HACK - markobj (f->annotated); + mark_object (f->annotated); #endif /* tail-recurse on constants */ return f->constants; @@ -2350,10 +2346,8 @@ If the byte code for compiled function FUNCTION is lazy-loaded, fetch it now. /* v18 or v19 bytecode file. Need to Ebolify. */ if (f->flags.ebolified && VECTORP (XCDR (tem))) ebolify_bytecode_constants (XCDR (tem)); - /* VERY IMPORTANT to purecopy here!!!!! - See load_force_doc_string_unwind. */ - f->instructions = Fpurecopy (XCAR (tem)); - f->constants = Fpurecopy (XCDR (tem)); + f->instructions = XCAR (tem); + f->constants = XCDR (tem); return function; } abort (); diff --git a/src/bytecode.h b/src/bytecode.h index 3387b93..71674ec 100644 --- a/src/bytecode.h +++ b/src/bytecode.h @@ -93,7 +93,6 @@ DECLARE_LRECORD (compiled_function, Lisp_Compiled_Function); Lisp_Compiled_Function) #define XSETCOMPILED_FUNCTION(x, p) XSETRECORD (x, p, compiled_function) #define COMPILED_FUNCTIONP(x) RECORDP (x, compiled_function) -#define GC_COMPILED_FUNCTIONP(x) GC_RECORDP (x, compiled_function) #define CHECK_COMPILED_FUNCTION(x) CHECK_RECORD (x, compiled_function) #define CONCHECK_COMPILED_FUNCTION(x) CONCHECK_RECORD (x, compiled_function) diff --git a/src/callint.c b/src/callint.c index 14d9e23..2e6832a 100644 --- a/src/callint.c +++ b/src/callint.c @@ -58,9 +58,6 @@ Lisp_Object Vmouse_leave_buffer_hook, Qmouse_leave_buffer_hook; Lisp_Object Qlet, QletX, Qsave_excursion; -Lisp_Object Qcurrent_prefix_arg; - -Lisp_Object Quser_variable_p; Lisp_Object Qread_from_minibuffer; Lisp_Object Qread_file_name; Lisp_Object Qread_directory_name; @@ -995,8 +992,6 @@ syms_of_callint (void) defsymbol (&Qevents_to_keys, "events-to-keys"); defsymbol (&Qcommand_debug_status, "command-debug-status"); defsymbol (&Qenable_recursive_minibuffers, "enable-recursive-minibuffers"); - defsymbol (&Quser_variable_p, "user-variable-p"); - defsymbol (&Qcurrent_prefix_arg, "current-prefix-arg"); defsymbol (&Qlet, "let"); defsymbol (&QletX, "let*"); diff --git a/src/casetab.c b/src/casetab.c index ff9443c..af2d31c 100644 --- a/src/casetab.c +++ b/src/casetab.c @@ -42,14 +42,13 @@ Boston, MA 02111-1307, USA. */ #include "buffer.h" #include "opaque.h" -Lisp_Object Qcase_table_p; +Lisp_Object Qcase_tablep; Lisp_Object Vascii_downcase_table, Vascii_upcase_table; Lisp_Object Vascii_canon_table, Vascii_eqv_table; #ifdef MULE Lisp_Object Vmirror_ascii_downcase_table, Vmirror_ascii_upcase_table; Lisp_Object Vmirror_ascii_canon_table, Vmirror_ascii_eqv_table; #endif -Lisp_Object Qtranslate_table; static void compute_trt_inverse (Lisp_Object trt, Lisp_Object inverse); @@ -81,7 +80,7 @@ check_case_table (Lisp_Object obj) REGISTER Lisp_Object tem; while (tem = Fcase_table_p (obj), NILP (tem)) - obj = wrong_type_argument (Qcase_table_p, obj); + obj = wrong_type_argument (Qcase_tablep, obj); return (obj); } @@ -289,8 +288,7 @@ compute_trt_inverse (Lisp_Object trt, Lisp_Object inverse) void syms_of_casetab (void) { - defsymbol (&Qcase_table_p, "case-table-p"); - defsymbol (&Qtranslate_table, "translate-table"); + defsymbol (&Qcase_tablep, "case-table-p"); DEFSUBR (Fcase_table_p); DEFSUBR (Fcurrent_case_table); @@ -310,6 +308,13 @@ complex_vars_of_casetab (void) staticpro (&Vascii_canon_table); staticpro (&Vascii_eqv_table); +#ifdef MULE + staticpro (&Vmirror_ascii_downcase_table); + staticpro (&Vmirror_ascii_upcase_table); + staticpro (&Vmirror_ascii_canon_table); + staticpro (&Vmirror_ascii_eqv_table); +#endif + tem = MAKE_TRT_TABLE (); Vascii_downcase_table = tem; Vascii_canon_table = tem; diff --git a/src/chartab.c b/src/chartab.c index 4e7480d..475c87f 100644 --- a/src/chartab.c +++ b/src/chartab.c @@ -95,14 +95,14 @@ Lisp_Object Vword_combining_categories, Vword_separating_categories; #ifdef MULE static Lisp_Object -mark_char_table_entry (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_char_table_entry (Lisp_Object obj) { struct Lisp_Char_Table_Entry *cte = XCHAR_TABLE_ENTRY (obj); int i; for (i = 0; i < 96; i++) { - markobj (cte->level2[i]); + mark_object (cte->level2[i]); } return Qnil; } @@ -143,16 +143,16 @@ DEFINE_LRECORD_IMPLEMENTATION ("char-table-entry", char_table_entry, #endif /* MULE */ static Lisp_Object -mark_char_table (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_char_table (Lisp_Object obj) { struct Lisp_Char_Table *ct = XCHAR_TABLE (obj); int i; for (i = 0; i < NUM_ASCII_CHARS; i++) - markobj (ct->ascii[i]); + mark_object (ct->ascii[i]); #ifdef MULE for (i = 0; i < NUM_LEADING_BYTES; i++) - markobj (ct->level1[i]); + mark_object (ct->level1[i]); #endif return ct->mirror_table; } @@ -162,18 +162,18 @@ mark_char_table (Lisp_Object obj, void (*markobj) (Lisp_Object)) and prune_weak_hash_tables(). */ void -prune_syntax_tables (int (*obj_marked_p) (Lisp_Object)) +prune_syntax_tables (void) { Lisp_Object rest, prev = Qnil; for (rest = Vall_syntax_tables; - !GC_NILP (rest); + !NILP (rest); rest = XCHAR_TABLE (rest)->next_table) { - if (! obj_marked_p (rest)) + if (! marked_p (rest)) { /* This table is garbage. Remove it from the list. */ - if (GC_NILP (prev)) + if (NILP (prev)) Vall_syntax_tables = XCHAR_TABLE (rest)->next_table; else XCHAR_TABLE (prev)->next_table = @@ -431,6 +431,8 @@ static const struct lrecord_description char_table_description[] = { #ifdef MULE { XD_LISP_OBJECT, offsetof(struct Lisp_Char_Table, level1), NUM_LEADING_BYTES }, #endif + { XD_LISP_OBJECT, offsetof(struct Lisp_Char_Table, mirror_table), 1 }, + { XD_LO_LINK, offsetof(struct Lisp_Char_Table, next_table) }, { XD_END } }; @@ -707,7 +709,13 @@ as OLD-TABLE. The values will not themselves be copied. ctnew->mirror_table = Fcopy_char_table (ct->mirror_table); else ctnew->mirror_table = ct->mirror_table; + ctnew->next_table = Qnil; XSETCHAR_TABLE (obj, ctnew); + if (ctnew->type == CHAR_TABLE_TYPE_SYNTAX) + { + ctnew->next_table = Vall_syntax_tables; + Vall_syntax_tables = obj; + } return obj; } @@ -1731,7 +1739,7 @@ Valid values are nil or a bit vector of size 95. #define CATEGORYP(x) \ - (CHARP ((x)) && XCHAR ((x)) >= 0x20 && XCHAR ((x)) <= 0x7E) + (CHARP (x) && XCHAR (x) >= 0x20 && XCHAR (x) <= 0x7E) #define CATEGORY_SET(c) \ (get_char_table(c, XCHAR_TABLE(current_buffer->category_table))) @@ -1746,6 +1754,7 @@ Valid values are nil or a bit vector of size 95. Use the macro WORD_BOUNDARY_P instead of calling this function directly. */ +int word_boundary_p (Emchar c1, Emchar c2); int word_boundary_p (Emchar c1, Emchar c2) { @@ -1839,6 +1848,7 @@ vars_of_chartab (void) { /* DO NOT staticpro this. It works just like Vweak_hash_tables. */ Vall_syntax_tables = Qnil; + pdump_wire_list (&Vall_syntax_tables); } void diff --git a/src/chartab.h b/src/chartab.h index f720dad..7ae8051 100644 --- a/src/chartab.h +++ b/src/chartab.h @@ -42,7 +42,6 @@ DECLARE_LRECORD (char_table_entry, struct Lisp_Char_Table_Entry); XRECORD (x, char_table_entry, struct Lisp_Char_Table_Entry) #define XSETCHAR_TABLE_ENTRY(x, p) XSETRECORD (x, p, char_table_entry) #define CHAR_TABLE_ENTRYP(x) RECORDP (x, char_table_entry) -#define GC_CHAR_TABLE_ENTRYP(x) GC_RECORDP (x, char_table_entry) /* #define CHECK_CHAR_TABLE_ENTRY(x) CHECK_RECORD (x, char_table_entry) char table entries should never escape to Lisp */ @@ -63,7 +62,6 @@ DECLARE_LRECORD (char_table, struct Lisp_Char_Table); XRECORD (x, char_table, struct Lisp_Char_Table) #define XSETCHAR_TABLE(x, p) XSETRECORD (x, p, char_table) #define CHAR_TABLEP(x) RECORDP (x, char_table) -#define GC_CHAR_TABLEP(x) GC_RECORDP (x, char_table) #define CHECK_CHAR_TABLE(x) CHECK_RECORD (x, char_table) #define CONCHECK_CHAR_TABLE(x) CONCHECK_RECORD (x, char_table) @@ -186,7 +184,7 @@ int map_char_table (struct Lisp_Char_Table *ct, int (*fn) (struct chartab_range *range, Lisp_Object val, void *arg), void *arg); -void prune_syntax_tables (int (*obj_marked_p) (Lisp_Object)); +void prune_syntax_tables (void); EXFUN (Fcopy_char_table, 1); EXFUN (Fmake_char_table, 1); diff --git a/src/cmdloop.c b/src/cmdloop.c index 5c3d8a6..4d0cab8 100644 --- a/src/cmdloop.c +++ b/src/cmdloop.c @@ -40,9 +40,6 @@ Boston, MA 02111-1307, USA. */ /* Current depth in recursive edits. */ int command_loop_level; -/* Total number of times command_loop has read a key sequence. */ -int num_input_keys; - #ifndef LISP_COMMAND_LOOP /* Form to evaluate (if non-nil) when Emacs is started. */ Lisp_Object Vtop_level; diff --git a/src/config.h.in b/src/config.h.in index 9b3f285..45bd85f 100644 --- a/src/config.h.in +++ b/src/config.h.in @@ -272,6 +272,7 @@ char *alloca(); #undef HAVE_GETTIMEOFDAY #undef HAVE_GETWD #undef HAVE_GETCWD +#undef HAVE_GETPT #undef HAVE_LOGB #undef HAVE_LRAND48 #undef HAVE_MATHERR @@ -294,6 +295,7 @@ char *alloca(); #undef HAVE_SIGPROCMASK #undef HAVE_SIGSETJMP #undef HAVE_SNPRINTF +#undef HAVE_STPCPY #undef HAVE_STRCASECMP #undef HAVE_STRERROR #undef HAVE_TZSET @@ -597,12 +599,16 @@ extern "C" { #undef LWLIB_DIALOGS_MOTIF #undef LWLIB_DIALOGS_ATHENA #undef LWLIB_DIALOGS_ATHENA3D +#undef LWLIB_TABS_LUCID +#undef LWLIB_WIDGETS_MOTIF +#undef LWLIB_WIDGETS_ATHENA /* Other things that can be disabled by configure. */ #undef HAVE_MENUBARS #undef HAVE_SCROLLBARS #undef HAVE_DIALOGS #undef HAVE_TOOLBARS +#undef HAVE_WIDGETS #if defined (HAVE_MENUBARS) || defined (HAVE_DIALOGS) @@ -812,4 +818,6 @@ on various systems. */ #undef INFODIR_USER_DEFINED #undef INFOPATH_USER_DEFINED +#undef PDUMP + #endif /* _SRC_CONFIG_H_ */ diff --git a/src/conslots.h b/src/conslots.h index dfa9752..3c39a94 100644 --- a/src/conslots.h +++ b/src/conslots.h @@ -25,6 +25,10 @@ Boston, MA 02111-1307, USA. */ definition. In the garbage collector this file is included after defining MARKED_SLOT(x) to be mark_object(console->x). */ +#ifndef CONSOLE_SLOTS_FIRST_NAME +#define CONSOLE_SLOTS_FIRST_NAME name +#endif + /* Name of this console, for resourcing and printing purposes. If not explicitly given, it's initialized in a console-specific manner. */ @@ -93,4 +97,7 @@ Boston, MA 02111-1307, USA. */ Initialized by the terminal-specific lisp files. */ MARKED_SLOT (function_key_map); +#ifndef CONSOLE_SLOTS_LAST_NAME +#define CONSOLE_SLOTS_LAST_NAME function_key_map +#endif diff --git a/src/console-msw.c b/src/console-msw.c index ddda9f6..3370b56 100644 --- a/src/console-msw.c +++ b/src/console-msw.c @@ -70,6 +70,12 @@ console_type_create_mswindows (void) } void +reinit_console_type_create_mswindows (void) +{ + REINITIALIZE_CONSOLE_TYPE (mswindows); +} + +void vars_of_console_mswindows (void) { Fprovide (Qmswindows); diff --git a/src/console-msw.h b/src/console-msw.h index 0bb2fc5..19d01d0 100644 --- a/src/console-msw.h +++ b/src/console-msw.h @@ -38,7 +38,7 @@ Boston, MA 02111-1307, USA. */ #endif #include #include /* DDE management library */ -#if !defined (__CYGWIN32__) && !defined(__MINGW32__) +#if !defined(__CYGWIN32__) && !defined(__MINGW32__) #include /* FileManager/Explorer drag and drop */ #include #endif @@ -66,6 +66,7 @@ Boston, MA 02111-1307, USA. */ /* The name of the main window class */ #define XEMACS_CLASS "XEmacs" +#define XEMACS_CONTROL_CLASS "XEmacsControl" /* * Console @@ -224,6 +225,9 @@ struct mswindows_frame /* win32 "Windows" procedure */ LRESULT WINAPI mswindows_wnd_proc (HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); +LRESULT WINAPI mswindows_control_wnd_proc (HWND hwnd, + UINT msg, WPARAM wParam, + LPARAM lParam); void mswindows_redraw_exposed_area (struct frame *f, int x, int y, int width, int height); diff --git a/src/console-stream.c b/src/console-stream.c index 3953850..7899bc6 100644 --- a/src/console-stream.c +++ b/src/console-stream.c @@ -298,6 +298,12 @@ console_type_create_stream (void) } void +reinit_console_type_create_stream (void) +{ + REINITIALIZE_CONSOLE_TYPE (stream); +} + +void vars_of_console_stream (void) { DEFVAR_LISP ("terminal-console", &Vterminal_console /* @@ -320,6 +326,7 @@ The initial frame-object, which represents XEmacs' stdout. staticpro (&Vstdio_str); } +#ifndef PDUMP void init_console_stream (void) { @@ -339,3 +346,22 @@ init_console_stream (void) event_stream_select_console (XCONSOLE (Vterminal_console)); } } + +#else + +void +init_console_stream (void) +{ + /* This function can GC */ + Vterminal_device = Fmake_device (Qstream, Qnil, Qnil); + Vterminal_console = Fdevice_console (Vterminal_device); + Vterminal_frame = Fmake_frame (Qnil, Vterminal_device); + minibuf_window = XFRAME (Vterminal_frame)->minibuffer_window; + if (initialized) + { + stream_init_console (XCONSOLE (Vterminal_console), Qnil); + if (noninteractive) + event_stream_select_console (XCONSOLE (Vterminal_console)); + } +} +#endif diff --git a/src/console-stream.h b/src/console-stream.h index a097e13..e70165c 100644 --- a/src/console-stream.h +++ b/src/console-stream.h @@ -40,6 +40,8 @@ struct stream_console #define CONSOLE_STREAM_DATA(con) CONSOLE_TYPE_DATA (con, stream) +extern Lisp_Object Vterminal_console, Vterminal_frame, Vterminal_device; + Lisp_Object stream_semi_canonicalize_console_connection(Lisp_Object, Error_behavior); Lisp_Object stream_canonicalize_console_connection(Lisp_Object, diff --git a/src/console-tty.c b/src/console-tty.c index c57c0f7..05089bc 100644 --- a/src/console-tty.c +++ b/src/console-tty.c @@ -166,12 +166,12 @@ tty_init_console (struct console *con, Lisp_Object props) } static void -tty_mark_console (struct console *con, void (*markobj) (Lisp_Object)) +tty_mark_console (struct console *con) { struct tty_console *tty_con = CONSOLE_TTY_DATA (con); - markobj (tty_con->terminal_type); - markobj (tty_con->instream); - markobj (tty_con->outstream); + mark_object (tty_con->terminal_type); + mark_object (tty_con->instream); + mark_object (tty_con->outstream); } static int @@ -372,6 +372,12 @@ console_type_create_tty (void) } void +reinit_console_type_create_tty (void) +{ + REINITIALIZE_CONSOLE_TYPE (tty); +} + +void image_instantiator_format_create_glyphs_tty (void) { IIFORMAT_VALID_CONSOLE (tty, nothing); diff --git a/src/console-x.c b/src/console-x.c index 4a4ab21..2470521 100644 --- a/src/console-x.c +++ b/src/console-x.c @@ -280,3 +280,9 @@ console_type_create_x (void) CONSOLE_HAS_METHOD (x, initially_selected_for_input); } + +void +reinit_console_type_create_x (void) +{ + REINITIALIZE_CONSOLE_TYPE (x); +} diff --git a/src/console-x.h b/src/console-x.h index e285226..cbf0161 100644 --- a/src/console-x.h +++ b/src/console-x.h @@ -381,7 +381,7 @@ extern struct console_type *x_console_type; extern Lisp_Object Vdefault_x_device; /* Number of pixels below each line. */ -extern int x_interline_space; +extern int x_interline_space; /* #### implement me */ extern int x_selection_timeout; @@ -420,15 +420,14 @@ void x_output_string (struct window *w, struct display_line *dl, int cursor, int cursor_start, int cursor_width, int cursor_height); void x_output_x_pixmap (struct frame *f, struct Lisp_Image_Instance *p, - int x, int y, int clip_x, int clip_y, - int clip_width, int clip_height, int width, - int height, int pixmap_offset, + int x, int y, int xoffset, int yoffset, + int width, int height, unsigned long fg, unsigned long bg, GC override_gc); void x_output_shadows (struct frame *f, int x, int y, int width, int height, GC top_shadow_gc, GC bottom_shadow_gc, GC background_gc, - int shadow_thickness); + int shadow_thickness, int edges); void x_generate_shadow_pixels (struct frame *f, unsigned long *top_shadow, unsigned long *bottom_shadow, @@ -439,10 +438,10 @@ int x_initialize_frame_menubar (struct frame *f); void x_init_modifier_mapping (struct device *d); #define X_ERROR_OCCURRED(dpy, body) \ - (expect_x_error ((dpy)), (body), x_error_occurred_p (dpy)) + (expect_x_error (dpy), body, x_error_occurred_p (dpy)) #define HANDLING_X_ERROR(dpy, body) \ - ( expect_x_error ((dpy)), (body), signal_if_x_error ((dpy), 0)) + (expect_x_error (dpy), body, signal_if_x_error (dpy, 0)) void Initialize_Locale (void); diff --git a/src/console.c b/src/console.c index 7e27f86..00c1f13 100644 --- a/src/console.c +++ b/src/console.c @@ -53,6 +53,7 @@ Lisp_Object Qsuspend_resume_hook; list of consoles and stores into each console that does not say it has a local value. */ Lisp_Object Vconsole_defaults; +static void *console_defaults_saved_slots; /* This structure marks which slots in a console have corresponding default values in console_defaults. @@ -69,7 +70,7 @@ Lisp_Object Vconsole_defaults; consoles. If a slot is -1, then there is a DEFVAR_CONSOLE_LOCAL for it - as well as a default value which is used to initialize newly-created + as well as a default value which is used to initialize newly-created consoles and as a reset-value when local-vars are killed. If a slot is -2, there is no DEFVAR_CONSOLE_LOCAL for it. @@ -87,6 +88,7 @@ struct console console_local_flags; /* This structure holds the names of symbols whose values may be console-local. It is indexed and accessed in the same way as the above. */ static Lisp_Object Vconsole_local_symbols; +static void *console_local_symbols_saved_slots; DEFINE_CONSOLE_TYPE (dead); @@ -96,19 +98,19 @@ console_type_entry_dynarr *the_console_type_entry_dynarr; static Lisp_Object -mark_console (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_console (Lisp_Object obj) { struct console *con = XCONSOLE (obj); -#define MARKED_SLOT(x) ((void) (markobj (con->x))); +#define MARKED_SLOT(x) mark_object (con->x) #include "conslots.h" #undef MARKED_SLOT /* Can be zero for Vconsole_defaults, Vconsole_local_symbols */ if (con->conmeths) { - markobj (con->conmeths->symbol); - MAYBE_CONMETH (con, mark_console, (con, markobj)); + mark_object (con->conmeths->symbol); + MAYBE_CONMETH (con, mark_console, (con)); } return Qnil; @@ -1096,10 +1098,44 @@ syms_of_console (void) defsymbol (&Qsuspend_resume_hook, "suspend-resume-hook"); } +static const struct lrecord_description cte_description_1[] = { + { XD_LISP_OBJECT, offsetof(console_type_entry, symbol), 1 }, + { XD_STRUCT_PTR, offsetof(console_type_entry, meths), 1, &console_methods_description }, + { XD_END } +}; + +static const struct struct_description cte_description = { + sizeof(console_type_entry), + cte_description_1 +}; + +static const struct lrecord_description cted_description_1[] = { + XD_DYNARR_DESC(console_type_entry_dynarr, &cte_description), + { XD_END } +}; + +const struct struct_description cted_description = { + sizeof(console_type_entry_dynarr), + cted_description_1 +}; + +static const struct lrecord_description console_methods_description_1[] = { + { XD_LISP_OBJECT, offsetof(struct console_methods, symbol), 2 }, + { XD_LISP_OBJECT, offsetof(struct console_methods, image_conversion_list), 1 }, + { XD_END } +}; + +const struct struct_description console_methods_description = { + sizeof(struct console_methods), + console_methods_description_1 +}; + + void console_type_create (void) { the_console_type_entry_dynarr = Dynarr_new (console_type_entry); + dumpstruct(&the_console_type_entry_dynarr, &cted_description); Vconsole_type_list = Qnil; staticpro (&Vconsole_type_list); @@ -1114,8 +1150,19 @@ console_type_create (void) } void +reinit_vars_of_console (void) +{ + staticpro_nodump (&Vconsole_list); + Vconsole_list = Qnil; + staticpro_nodump (&Vselected_console); + Vselected_console = Qnil; +} + +void vars_of_console (void) { + reinit_vars_of_console (); + DEFVAR_LISP ("create-console-hook", &Vcreate_console_hook /* Function or functions to call when a console is created. One argument, the newly-created console. @@ -1131,11 +1178,6 @@ One argument, the to-be-deleted console. */ ); Vdelete_console_hook = Qnil; - staticpro (&Vconsole_list); - Vconsole_list = Qnil; - staticpro (&Vselected_console); - Vselected_console = Qnil; - #ifdef HAVE_WINDOW_SYSTEM Fprovide (intern ("window-system")); #endif @@ -1184,13 +1226,13 @@ nuke_all_console_slots (struct console *con, Lisp_Object zap) { zero_lcrecord (con); -#define MARKED_SLOT(x) con->x = (zap); +#define MARKED_SLOT(x) con->x = zap #include "conslots.h" #undef MARKED_SLOT } -void -complex_vars_of_console (void) +static void +common_init_complex_vars_of_console (void) { /* Make sure all markable slots in console_defaults are initialized reasonably, so mark_console won't choke. @@ -1198,8 +1240,8 @@ complex_vars_of_console (void) struct console *defs = alloc_lcrecord_type (struct console, &lrecord_console); struct console *syms = alloc_lcrecord_type (struct console, &lrecord_console); - staticpro (&Vconsole_defaults); - staticpro (&Vconsole_local_symbols); + staticpro_nodump (&Vconsole_defaults); + staticpro_nodump (&Vconsole_local_symbols); XSETCONSOLE (Vconsole_defaults, defs); XSETCONSOLE (Vconsole_local_symbols, syms); @@ -1254,6 +1296,53 @@ complex_vars_of_console (void) currently allowable due to the XINT() handling of this value. With some rearrangement you can get 4 more bits. */ } +} + + +#define CONSOLE_SLOTS_SIZE (offsetof (struct console, CONSOLE_SLOTS_LAST_NAME) - offsetof (struct console, CONSOLE_SLOTS_FIRST_NAME) + sizeof (Lisp_Object)) +#define CONSOLE_SLOTS_COUNT (CONSOLE_SLOTS_SIZE / sizeof (Lisp_Object)) + +void +reinit_complex_vars_of_console (void) +{ + struct console *defs, *syms; + + common_init_complex_vars_of_console (); + + defs = XCONSOLE (Vconsole_defaults); + syms = XCONSOLE (Vconsole_local_symbols); + memcpy (&defs->CONSOLE_SLOTS_FIRST_NAME, + console_defaults_saved_slots, + CONSOLE_SLOTS_SIZE); + memcpy (&syms->CONSOLE_SLOTS_FIRST_NAME, + console_local_symbols_saved_slots, + CONSOLE_SLOTS_SIZE); +} + + +static const struct lrecord_description console_slots_description_1[] = { + { XD_LISP_OBJECT, 0, CONSOLE_SLOTS_COUNT }, + { XD_END } +}; + +static const struct struct_description console_slots_description = { + CONSOLE_SLOTS_SIZE, + console_slots_description_1 +}; + +void +complex_vars_of_console (void) +{ + struct console *defs, *syms; + + common_init_complex_vars_of_console (); + + defs = XCONSOLE (Vconsole_defaults); + syms = XCONSOLE (Vconsole_local_symbols); + console_defaults_saved_slots = &defs->CONSOLE_SLOTS_FIRST_NAME; + console_local_symbols_saved_slots = &syms->CONSOLE_SLOTS_FIRST_NAME; + dumpstruct (&console_defaults_saved_slots, &console_slots_description); + dumpstruct (&console_local_symbols_saved_slots, &console_slots_description); DEFVAR_CONSOLE_DEFAULTS ("default-function-key-map", function_key_map /* Default value of `function-key-map' for consoles that don't override it. diff --git a/src/console.h b/src/console.h index e19c15a..ffee406 100644 --- a/src/console.h +++ b/src/console.h @@ -60,6 +60,9 @@ enum device_metrics DM_slow_device, DM_security }; +extern const struct struct_description cted_description; +extern const struct struct_description console_methods_description; + struct console_methods { CONST char *name; /* Used by print_console, print_device, print_frame */ @@ -68,7 +71,7 @@ struct console_methods /* console methods */ void (*init_console_method) (struct console *, Lisp_Object props); - void (*mark_console_method) (struct console *, void (*)(Lisp_Object)); + void (*mark_console_method) (struct console *); int (*initially_selected_for_input_method) (struct console *); void (*delete_console_method) (struct console *); Lisp_Object (*semi_canonicalize_console_connection_method) @@ -86,7 +89,7 @@ struct console_methods void (*init_device_method) (struct device *, Lisp_Object props); void (*finish_init_device_method) (struct device *, Lisp_Object props); void (*delete_device_method) (struct device *); - void (*mark_device_method) (struct device *, void (*)(Lisp_Object)); + void (*mark_device_method) (struct device *); void (*asynch_device_change_method) (void); Lisp_Object (*device_system_metrics_method) (struct device *, enum device_metrics); unsigned int (*device_implementation_flags_method) (void); @@ -103,7 +106,7 @@ struct console_methods void (*init_frame_3_method) (struct frame *); void (*after_init_frame_method) (struct frame *, int first_on_device, int first_on_console); - void (*mark_frame_method) (struct frame *, void (*)(Lisp_Object)); + void (*mark_frame_method) (struct frame *); void (*delete_frame_method) (struct frame *); void (*focus_on_frame_method) (struct frame *); void (*raise_frame_method) (struct frame *); @@ -155,15 +158,23 @@ struct console_methods int duration); void (*frame_redraw_cursor_method) (struct frame *f); void (*set_final_cursor_coords_method) (struct frame *, int, int); - void (*bevel_area_method) (struct window *, face_index, int, int, int, int, int); - + void (*bevel_area_method) (struct window *, face_index, int, int, int, int, int, + int, enum edge_style); + void (*output_pixmap_method) (struct window *w, Lisp_Object image_instance, + struct display_box *db, struct display_glyph_area *dga, + face_index findex, int cursor_start, int cursor_width, + int cursor_height, int offset_bitmap); + void (*output_string_method) (struct window *w, struct display_line *dl, + Emchar_dynarr *buf, int xpos, int xoffset, + int start_pixpos, int width, face_index findex, + int cursor, int cursor_start, int cursor_width, + int cursor_height); /* color methods */ int (*initialize_color_instance_method) (struct Lisp_Color_Instance *, Lisp_Object name, Lisp_Object device, Error_behavior errb); - void (*mark_color_instance_method) (struct Lisp_Color_Instance *, - void (*)(Lisp_Object)); + void (*mark_color_instance_method) (struct Lisp_Color_Instance *); void (*print_color_instance_method) (struct Lisp_Color_Instance *, Lisp_Object printcharfun, int escapeflag); @@ -182,8 +193,7 @@ struct console_methods Lisp_Object name, Lisp_Object device, Error_behavior errb); - void (*mark_font_instance_method) (struct Lisp_Font_Instance *, - void (*)(Lisp_Object)); + void (*mark_font_instance_method) (struct Lisp_Font_Instance *); void (*print_font_instance_method) (struct Lisp_Font_Instance *, Lisp_Object printcharfun, int escapeflag); @@ -204,14 +214,14 @@ struct console_methods Bytecount length); /* image methods */ - void (*mark_image_instance_method) (struct Lisp_Image_Instance *, - void (*)(Lisp_Object)); + void (*mark_image_instance_method) (struct Lisp_Image_Instance *); void (*print_image_instance_method) (struct Lisp_Image_Instance *, Lisp_Object printcharfun, int escapeflag); void (*finalize_image_instance_method) (struct Lisp_Image_Instance *); void (*unmap_subwindow_method) (struct Lisp_Image_Instance *); - void (*map_subwindow_method) (struct Lisp_Image_Instance *, int x, int y); + void (*map_subwindow_method) (struct Lisp_Image_Instance *, int x, int y, + struct display_glyph_area* dga); void (*resize_subwindow_method) (struct Lisp_Image_Instance *, int w, int h); void (*update_subwindow_method) (struct Lisp_Image_Instance *); int (*image_instance_equal_method) (struct Lisp_Image_Instance *, @@ -221,6 +231,7 @@ struct console_methods int depth); void (*init_image_instance_from_eimage_method) (struct Lisp_Image_Instance *ii, int width, int height, + int slices, unsigned char *eimage, int dest_mask, Lisp_Object instantiator, @@ -346,12 +357,19 @@ struct console_methods * type##_console_methods type##_console_methods = xnew_and_zero (struct console_methods); \ type##_console_methods->name = obj_name; \ type##_console_methods->symbol = Q##type; \ - defsymbol (&type##_console_methods->predicate_symbol, pred_sym); \ + defsymbol_nodump (&type##_console_methods->predicate_symbol, pred_sym); \ add_entry_to_console_type_list (Q##type, type##_console_methods); \ type##_console_methods->image_conversion_list = Qnil; \ - staticpro (&type##_console_methods->image_conversion_list); \ + staticpro_nodump (&type##_console_methods->image_conversion_list); \ + dumpstruct (&type##_console_methods, &console_methods_description); \ } while (0) +#define REINITIALIZE_CONSOLE_TYPE(type) do { \ + staticpro_nodump (&type##_console_methods->predicate_symbol); \ + staticpro_nodump (&type##_console_methods->image_conversion_list); \ +} while (0) + + /* Declare that console-type TYPE has method M; used in initialization routines */ #define CONSOLE_HAS_METHOD(type, m) \ @@ -402,7 +420,6 @@ DECLARE_LRECORD (console, struct console); #define XCONSOLE(x) XRECORD (x, console, struct console) #define XSETCONSOLE(x, p) XSETRECORD (x, p, console) #define CONSOLEP(x) RECORDP (x, console) -#define GC_CONSOLEP(x) GC_RECORDP (x, console) #define CHECK_CONSOLE(x) CHECK_RECORD (x, console) #define CONCHECK_CONSOLE(x) CONCHECK_RECORD (x, console) diff --git a/src/data.c b/src/data.c index 20100db..9cf8ff4 100644 --- a/src/data.c +++ b/src/data.c @@ -50,14 +50,14 @@ Lisp_Object Qio_error, Qend_of_file; Lisp_Object Qarith_error, Qrange_error, Qdomain_error; Lisp_Object Qsingularity_error, Qoverflow_error, Qunderflow_error; Lisp_Object Qbeginning_of_buffer, Qend_of_buffer, Qbuffer_read_only; -Lisp_Object Qintegerp, Qnatnump, Qsymbolp, Qkeywordp; +Lisp_Object Qintegerp, Qnatnump, Qsymbolp; Lisp_Object Qlistp, Qtrue_list_p, Qweak_listp; Lisp_Object Qconsp, Qsubrp; Lisp_Object Qcharacterp, Qstringp, Qarrayp, Qsequencep, Qvectorp; Lisp_Object Qchar_or_string_p, Qmarkerp, Qinteger_or_marker_p, Qbufferp; Lisp_Object Qinteger_or_char_p, Qinteger_char_or_marker_p; -Lisp_Object Qnumberp, Qnumber_or_marker_p, Qnumber_char_or_marker_p; -Lisp_Object Qbit_vectorp, Qbitp, Qcons, Qkeyword, Qcdr, Qignore; +Lisp_Object Qnumberp, Qnumber_char_or_marker_p; +Lisp_Object Qbit_vectorp, Qbitp, Qcdr; Lisp_Object Qfloatp; @@ -147,7 +147,7 @@ args_out_of_range_3 (Lisp_Object a1, Lisp_Object a2, Lisp_Object a3) } void -check_int_range (int val, int min, int max) +check_int_range (EMACS_INT val, EMACS_INT min, EMACS_INT max) { if (val < min || val > max) args_out_of_range_3 (make_int (val), make_int (min), make_int (max)); @@ -160,8 +160,8 @@ EMACS_INT sign_extend_temp; /* On a few machines, XINT can only be done by calling this. */ /* XEmacs: only used by m/convex.h */ -int sign_extend_lisp_int (EMACS_INT num); -int +EMACS_INT sign_extend_lisp_int (EMACS_INT num); +EMACS_INT sign_extend_lisp_int (EMACS_INT num) { if (num & (1L << (VALBITS - 1))) @@ -615,7 +615,6 @@ Set the car of CONSCELL to be NEWCAR. Return NEWCAR. if (!CONSP (conscell)) conscell = wrong_type_argument (Qconsp, conscell); - CHECK_LISP_WRITEABLE (conscell); XCAR (conscell) = newcar; return newcar; } @@ -628,7 +627,6 @@ Set the cdr of CONSCELL to be NEWCDR. Return NEWCDR. if (!CONSP (conscell)) conscell = wrong_type_argument (Qconsp, conscell); - CHECK_LISP_WRITEABLE (conscell); XCDR (conscell) = newcdr; return newcdr; } @@ -689,7 +687,7 @@ ARRAY may be a vector, bit vector, or string. INDEX starts at 0. */ (array, index_)) { - int idx; + EMACS_INT idx; retry: @@ -743,7 +741,7 @@ ARRAY may be a vector, bit vector, or string. INDEX starts at 0. */ (array, index_, newval)) { - int idx; + EMACS_INT idx; retry: @@ -757,8 +755,6 @@ ARRAY may be a vector, bit vector, or string. INDEX starts at 0. if (idx < 0) goto range_error; - CHECK_LISP_WRITEABLE (array); - if (VECTORP (array)) { if (idx >= XVECTOR_LENGTH (array)) goto range_error; @@ -839,7 +835,7 @@ number_char_or_marker_to_double (Lisp_Object obj) } } -static int +static EMACS_INT integer_char_or_marker_to_int (Lisp_Object obj) { retry: @@ -1416,8 +1412,8 @@ Both must be integers, characters or markers. */ (num1, num2)) { - int ival1 = integer_char_or_marker_to_int (num1); - int ival2 = integer_char_or_marker_to_int (num2); + EMACS_INT ival1 = integer_char_or_marker_to_int (num1); + EMACS_INT ival2 = integer_char_or_marker_to_int (num2); if (ival2 == 0) Fsignal (Qarith_error, Qnil); @@ -1468,7 +1464,7 @@ If either argument is a float, a float will be returned. } #endif /* LISP_FLOAT_TYPE */ { - int ival; + EMACS_INT ival; if (iod2.c.ival == 0) goto divide_by_zero; ival = iod1.c.ival % iod2.c.ival; @@ -1570,7 +1566,7 @@ static Lisp_Object Vall_weak_lists; /* Gemarke es nicht!!! */ static Lisp_Object encode_weak_list_type (enum weak_list_type type); static Lisp_Object -mark_weak_list (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_weak_list (Lisp_Object obj) { return Qnil; /* nichts ist gemarkt */ } @@ -1625,7 +1621,7 @@ make_weak_list (enum weak_list_type type) static const struct lrecord_description weak_list_description[] = { { XD_LISP_OBJECT, offsetof(struct weak_list, list), 1 }, - { XD_LISP_OBJECT, offsetof(struct weak_list, next_weak), 1 }, + { XD_LO_LINK, offsetof(struct weak_list, next_weak) }, { XD_END } }; @@ -1652,20 +1648,19 @@ DEFINE_LRECORD_IMPLEMENTATION ("weak-list", weak_list, */ int -finish_marking_weak_lists (int (*obj_marked_p) (Lisp_Object), - void (*markobj) (Lisp_Object)) +finish_marking_weak_lists (void) { Lisp_Object rest; int did_mark = 0; for (rest = Vall_weak_lists; - !GC_NILP (rest); + !NILP (rest); rest = XWEAK_LIST (rest)->next_weak) { Lisp_Object rest2; enum weak_list_type type = XWEAK_LIST (rest)->type; - if (! obj_marked_p (rest)) + if (! marked_p (rest)) /* The weak list is probably garbage. Ignore it. */ continue; @@ -1673,7 +1668,7 @@ finish_marking_weak_lists (int (*obj_marked_p) (Lisp_Object), /* We need to be trickier since we're inside of GC; use CONSP instead of !NILP in case of user-visible imperfect lists */ - GC_CONSP (rest2); + CONSP (rest2); rest2 = XCDR (rest2)) { Lisp_Object elem; @@ -1688,7 +1683,7 @@ finish_marking_weak_lists (int (*obj_marked_p) (Lisp_Object), (either because of an external pointer or because of a previous call to this function), and likewise for all the rest of the elements in the list, so we can stop now. */ - if (obj_marked_p (rest2)) + if (marked_p (rest2)) break; elem = XCAR (rest2); @@ -1696,19 +1691,19 @@ finish_marking_weak_lists (int (*obj_marked_p) (Lisp_Object), switch (type) { case WEAK_LIST_SIMPLE: - if (obj_marked_p (elem)) + if (marked_p (elem)) need_to_mark_cons = 1; break; case WEAK_LIST_ASSOC: - if (!GC_CONSP (elem)) + if (!CONSP (elem)) { /* just leave bogus elements there */ need_to_mark_cons = 1; need_to_mark_elem = 1; } - else if (obj_marked_p (XCAR (elem)) && - obj_marked_p (XCDR (elem))) + else if (marked_p (XCAR (elem)) && + marked_p (XCDR (elem))) { need_to_mark_cons = 1; /* We still need to mark elem, because it's @@ -1718,13 +1713,13 @@ finish_marking_weak_lists (int (*obj_marked_p) (Lisp_Object), break; case WEAK_LIST_KEY_ASSOC: - if (!GC_CONSP (elem)) + if (!CONSP (elem)) { /* just leave bogus elements there */ need_to_mark_cons = 1; need_to_mark_elem = 1; } - else if (obj_marked_p (XCAR (elem))) + else if (marked_p (XCAR (elem))) { need_to_mark_cons = 1; /* We still need to mark elem and XCDR (elem); @@ -1734,13 +1729,13 @@ finish_marking_weak_lists (int (*obj_marked_p) (Lisp_Object), break; case WEAK_LIST_VALUE_ASSOC: - if (!GC_CONSP (elem)) + if (!CONSP (elem)) { /* just leave bogus elements there */ need_to_mark_cons = 1; need_to_mark_elem = 1; } - else if (obj_marked_p (XCDR (elem))) + else if (marked_p (XCDR (elem))) { need_to_mark_cons = 1; /* We still need to mark elem and XCAR (elem); @@ -1753,23 +1748,23 @@ finish_marking_weak_lists (int (*obj_marked_p) (Lisp_Object), abort (); } - if (need_to_mark_elem && ! obj_marked_p (elem)) + if (need_to_mark_elem && ! marked_p (elem)) { - markobj (elem); + mark_object (elem); did_mark = 1; } /* We also need to mark the cons that holds the elem or - assoc-pair. We do *not* want to call (markobj) here + assoc-pair. We do *not* want to call (mark_object) here because that will mark the entire list; we just want to mark the cons itself. */ if (need_to_mark_cons) { - struct Lisp_Cons *ptr = XCONS (rest2); - if (!CONS_MARKED_P (ptr)) + Lisp_Cons *c = XCONS (rest2); + if (!CONS_MARKED_P (c)) { - MARK_CONS (ptr); + MARK_CONS (c); did_mark = 1; } } @@ -1777,9 +1772,9 @@ finish_marking_weak_lists (int (*obj_marked_p) (Lisp_Object), /* In case of imperfect list, need to mark the final cons because we're not removing it */ - if (!GC_NILP (rest2) && ! obj_marked_p (rest2)) + if (!NILP (rest2) && ! marked_p (rest2)) { - markobj (rest2); + mark_object (rest2); did_mark = 1; } } @@ -1788,18 +1783,18 @@ finish_marking_weak_lists (int (*obj_marked_p) (Lisp_Object), } void -prune_weak_lists (int (*obj_marked_p) (Lisp_Object)) +prune_weak_lists (void) { Lisp_Object rest, prev = Qnil; for (rest = Vall_weak_lists; - !GC_NILP (rest); + !NILP (rest); rest = XWEAK_LIST (rest)->next_weak) { - if (! (obj_marked_p (rest))) + if (! (marked_p (rest))) { /* This weak list itself is garbage. Remove it from the list. */ - if (GC_NILP (prev)) + if (NILP (prev)) Vall_weak_lists = XWEAK_LIST (rest)->next_weak; else XWEAK_LIST (prev)->next_weak = @@ -1815,7 +1810,7 @@ prune_weak_lists (int (*obj_marked_p) (Lisp_Object)) /* We need to be trickier since we're inside of GC; use CONSP instead of !NILP in case of user-visible imperfect lists */ - GC_CONSP (rest2);) + CONSP (rest2);) { /* It suffices to check the cons for marking, regardless of the type of weak list: @@ -1826,10 +1821,10 @@ prune_weak_lists (int (*obj_marked_p) (Lisp_Object)) have been marked in finish_marking_weak_lists(). -- otherwise, it's not marked and should disappear. */ - if (! obj_marked_p (rest2)) + if (! marked_p (rest2)) { /* bye bye :-( */ - if (GC_NILP (prev2)) + if (NILP (prev2)) XWEAK_LIST (rest)->list = XCDR (rest2); else XCDR (prev2) = XCDR (rest2); @@ -1870,7 +1865,7 @@ prune_weak_lists (int (*obj_marked_p) (Lisp_Object)) if (go_tortoise) tortoise = XCDR (tortoise); go_tortoise = !go_tortoise; - if (GC_EQ (rest2, tortoise)) + if (EQ (rest2, tortoise)) break; } } @@ -2081,17 +2076,13 @@ init_errors_once_early (void) void syms_of_data (void) { - defsymbol (&Qcons, "cons"); - defsymbol (&Qkeyword, "keyword"); defsymbol (&Qquote, "quote"); defsymbol (&Qlambda, "lambda"); - defsymbol (&Qignore, "ignore"); defsymbol (&Qlistp, "listp"); defsymbol (&Qtrue_list_p, "true-list-p"); defsymbol (&Qconsp, "consp"); defsymbol (&Qsubrp, "subrp"); defsymbol (&Qsymbolp, "symbolp"); - defsymbol (&Qkeywordp, "keywordp"); defsymbol (&Qintegerp, "integerp"); defsymbol (&Qcharacterp, "characterp"); defsymbol (&Qnatnump, "natnump"); @@ -2108,7 +2099,6 @@ syms_of_data (void) defsymbol (&Qinteger_or_char_p, "integer-or-char-p"); defsymbol (&Qinteger_char_or_marker_p, "integer-char-or-marker-p"); defsymbol (&Qnumberp, "numberp"); - defsymbol (&Qnumber_or_marker_p, "number-or-marker-p"); defsymbol (&Qnumber_char_or_marker_p, "number-char-or-marker-p"); defsymbol (&Qcdr, "cdr"); defsymbol (&Qweak_listp, "weak-list-p"); @@ -2207,6 +2197,7 @@ vars_of_data (void) { /* This must not be staticpro'd */ Vall_weak_lists = Qnil; + pdump_wire_list (&Vall_weak_lists); #ifdef DEBUG_XEMACS DEFVAR_BOOL ("debug-issue-ebola-notices", &debug_issue_ebola_notices /* diff --git a/src/database.c b/src/database.c index c17c827..31739ab 100644 --- a/src/database.c +++ b/src/database.c @@ -148,12 +148,10 @@ allocate_database (void) } static Lisp_Object -mark_database (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_database (Lisp_Object obj) { Lisp_Database *db = XDATABASE (obj); - - markobj (db->fname); - return Qnil; + return db->fname; } static void diff --git a/src/debug.c b/src/debug.c index d3eb58d..3e50d0a 100644 --- a/src/debug.c +++ b/src/debug.c @@ -39,8 +39,7 @@ Boston, MA 02111-1307, USA. */ * 4. Add a FROB line for it in xemacs_debug_loop. */ -Lisp_Object Qredisplay, Qbuffers, Qfaces; -Lisp_Object Qwindows, Qframes, Qdevices; +static Lisp_Object Qredisplay, Qbuffers, Qfaces, Qwindows, Qframes, Qdevices; struct debug_classes active_debug_classes; @@ -194,7 +193,6 @@ syms_of_debug (void) defsymbol (&Qwindows, "windows"); defsymbol (&Qframes, "frames"); defsymbol (&Qdevices, "devices"); - /* defsymbol (&Qbyte_code, "byte-code"); in bytecode.c */ DEFSUBR (Fadd_debug_class_to_check); DEFSUBR (Fdelete_debug_class_to_check); @@ -206,7 +204,7 @@ syms_of_debug (void) } void -vars_of_debug (void) +reinit_vars_of_debug (void) { /* If you need to have any classes active early on in startup, then the flags should be set here. @@ -214,3 +212,9 @@ vars_of_debug (void) to emacs.c. */ xemacs_debug_loop (INIT, Qnil, Qnil); } + +void +vars_of_debug (void) +{ + reinit_vars_of_debug (); +} diff --git a/src/debug.h b/src/debug.h index 06efdd3..6bee237 100644 --- a/src/debug.h +++ b/src/debug.h @@ -53,8 +53,6 @@ struct debug_classes unsigned int types_of_byte_code; }; -extern Lisp_Object Qbuffers, Qdevices, Qfaces, Qframes, Qredisplay, Qwindows; - extern struct debug_classes active_debug_classes; #define DASSERT(class, desired_type, action, assertion) do \ diff --git a/src/depend b/src/depend index 4d9d637..c4b0017 100644 --- a/src/depend +++ b/src/depend @@ -35,7 +35,7 @@ input-method-xlib.o: $(LISP_H) EmacsFrame.h buffer.h bufslots.h conslots.h conso menubar-x.o: $(LISP_H) $(LWLIB_SRCDIR)/lwlib.h EmacsFrame.h buffer.h bufslots.h commands.h conslots.h console-x.h console.h device.h events.h frame.h frameslots.h glyphs.h gui-x.h gui.h lisp-disunion.h lisp-union.h lrecord.h mule-charset.h opaque.h redisplay.h scrollbar.h specifier.h symeval.h symsinit.h systime.h toolbar.h window.h winslots.h xintrinsic.h objects-x.o: $(LISP_H) buffer.h bufslots.h conslots.h console-x.h console.h device.h insdel.h lisp-disunion.h lisp-union.h lrecord.h mule-charset.h objects-x.h objects.h specifier.h symeval.h symsinit.h xintrinsic.h redisplay-x.o: $(LISP_H) $(LWLIB_SRCDIR)/lwlib.h EmacsFrame.h EmacsFrameP.h buffer.h bufslots.h conslots.h console-x.h console.h debug.h device.h faces.h file-coding.h frame.h frameslots.h glyphs-x.h glyphs.h gui.h gutter.h lisp-disunion.h lisp-union.h lrecord.h mule-ccl.h mule-charset.h objects-x.h objects.h redisplay.h scrollbar.h specifier.h symeval.h symsinit.h sysdep.h sysproc.h systime.h toolbar.h window.h winslots.h xgccache.h xintrinsic.h xintrinsicp.h xmprimitivep.h -scrollbar-x.o: $(LISP_H) $(LWLIB_SRCDIR)/lwlib.h conslots.h console-x.h console.h device.h frame.h frameslots.h glyphs-x.h glyphs.h gui-x.h gui.h lisp-disunion.h lisp-union.h lrecord.h redisplay.h scrollbar-x.h scrollbar.h specifier.h symeval.h symsinit.h toolbar.h window.h winslots.h xintrinsic.h +scrollbar-x.o: $(LISP_H) $(LWLIB_SRCDIR)/lwlib.h EmacsFrame.h conslots.h console-x.h console.h device.h frame.h frameslots.h glyphs-x.h glyphs.h gui-x.h gui.h lisp-disunion.h lisp-union.h lrecord.h redisplay.h scrollbar-x.h scrollbar.h specifier.h symeval.h symsinit.h toolbar.h window.h winslots.h xintrinsic.h select-x.o: $(LISP_H) buffer.h bufslots.h conslots.h console-x.h console.h device.h frame.h frameslots.h glyphs.h gui.h lisp-disunion.h lisp-union.h lrecord.h mule-charset.h objects-x.h objects.h opaque.h redisplay.h scrollbar.h select.h specifier.h symeval.h symsinit.h systime.h toolbar.h xintrinsic.h toolbar-x.o: $(LISP_H) $(LWLIB_SRCDIR)/lwlib.h EmacsFrame.h EmacsFrameP.h buffer.h bufslots.h conslots.h console-x.h console.h device.h faces.h frame.h frameslots.h glyphs-x.h glyphs.h gui.h lisp-disunion.h lisp-union.h lrecord.h mule-charset.h objects-x.h objects.h redisplay.h scrollbar.h specifier.h symeval.h symsinit.h toolbar.h window.h winslots.h xintrinsic.h xintrinsicp.h xmprimitivep.h #endif @@ -45,7 +45,7 @@ database.o: $(LISP_H) buffer.h bufslots.h database.h lisp-disunion.h lisp-union. #ifdef MULE mule-canna.o: $(LISP_H) buffer.h bufslots.h file-coding.h lisp-disunion.h lisp-union.h lrecord.h mule-charset.h symeval.h symsinit.h mule-ccl.o: $(LISP_H) buffer.h bufslots.h file-coding.h lisp-disunion.h lisp-union.h lrecord.h mule-ccl.h mule-charset.h symeval.h symsinit.h -mule-charset.o: $(LISP_H) buffer.h bufslots.h chartab.h conslots.h console.h device.h elhash.h faces.h lisp-disunion.h lisp-union.h lrecord.h lstream.h mule-charset.h symeval.h symsinit.h +mule-charset.o: $(LISP_H) buffer.h bufslots.h chartab.h conslots.h console.h device.h elhash.h faces.h lisp-disunion.h lisp-union.h lrecord.h lstream.h mule-ccl.h mule-charset.h symeval.h symsinit.h mule-mcpath.o: $(LISP_H) buffer.h bufslots.h lisp-disunion.h lisp-union.h lrecord.h mule-charset.h symeval.h symsinit.h sysfile.h mule-wnnfns.o: $(LISP_H) buffer.h bufslots.h lisp-disunion.h lisp-union.h lrecord.h mule-charset.h redisplay.h scrollbar.h symeval.h symsinit.h sysdep.h window.h winslots.h mule.o: $(LISP_H) lisp-disunion.h lisp-union.h lrecord.h regex.h symeval.h symsinit.h @@ -119,7 +119,7 @@ getloadavg.o: $(LISP_H) lisp-disunion.h lisp-union.h lrecord.h symeval.h symsini gif_io.o: gifrlib.h glyphs-eimage.o: $(LISP_H) buffer.h bufslots.h conslots.h console.h device.h faces.h file-coding.h frame.h frameslots.h gifrlib.h glyphs.h gui.h lisp-disunion.h lisp-union.h lrecord.h lstream.h mule-charset.h objects.h opaque.h redisplay.h scrollbar.h specifier.h symeval.h symsinit.h sysfile.h toolbar.h glyphs-widget.o: $(LISP_H) buffer.h bufslots.h bytecode.h conslots.h console.h device.h faces.h frame.h frameslots.h glyphs.h gui.h insdel.h lisp-disunion.h lisp-union.h lrecord.h lstream.h mule-charset.h objects.h opaque.h redisplay.h scrollbar.h specifier.h symeval.h symsinit.h toolbar.h window.h winslots.h -glyphs.o: $(LISP_H) buffer.h bufslots.h chartab.h conslots.h console.h device.h elhash.h faces.h frame.h frameslots.h glyphs.h gui.h insdel.h lisp-disunion.h lisp-union.h lrecord.h mule-charset.h objects.h opaque.h rangetab.h redisplay.h scrollbar.h specifier.h symeval.h symsinit.h toolbar.h window.h winslots.h +glyphs.o: $(LISP_H) blocktype.h buffer.h bufslots.h chartab.h conslots.h console.h device.h elhash.h faces.h frame.h frameslots.h glyphs.h gui.h insdel.h lisp-disunion.h lisp-union.h lrecord.h mule-charset.h objects.h opaque.h rangetab.h redisplay.h scrollbar.h specifier.h symeval.h symsinit.h toolbar.h window.h winslots.h gmalloc.o: config.h getpagesize.h gpmevent.o: $(LISP_H) conslots.h console-tty.h console.h device.h events-mod.h events.h gpmevent.h lisp-disunion.h lisp-union.h lrecord.h symeval.h symsinit.h sysdep.h syssignal.h systime.h systty.h gui.o: $(LISP_H) bytecode.h elhash.h gui.h lisp-disunion.h lisp-union.h lrecord.h symeval.h symsinit.h @@ -166,7 +166,7 @@ redisplay-output.o: $(LISP_H) buffer.h bufslots.h conslots.h console.h device.h redisplay-tty.o: $(LISP_H) buffer.h bufslots.h conslots.h console-tty.h console.h device.h events.h faces.h frame.h frameslots.h glyphs.h gui.h lisp-disunion.h lisp-union.h lrecord.h lstream.h mule-charset.h objects-tty.h objects.h redisplay.h scrollbar.h specifier.h symeval.h symsinit.h sysdep.h syssignal.h systime.h systty.h toolbar.h window.h winslots.h redisplay.o: $(LISP_H) buffer.h bufslots.h commands.h conslots.h console-tty.h console.h debug.h device.h elhash.h extents.h faces.h file-coding.h frame.h frameslots.h glyphs.h gui.h gutter.h insdel.h line-number.h lisp-disunion.h lisp-union.h lrecord.h menubar.h mule-charset.h objects.h process.h redisplay.h scrollbar.h specifier.h symeval.h symsinit.h syssignal.h systty.h toolbar.h window.h winslots.h regex.o: $(LISP_H) buffer.h bufslots.h chartab.h lisp-disunion.h lisp-union.h lrecord.h mule-charset.h regex.h symeval.h symsinit.h syntax.h -scrollbar.o: $(LISP_H) buffer.h bufslots.h commands.h conslots.h console.h device.h frame.h frameslots.h glyphs.h gui.h lisp-disunion.h lisp-union.h lrecord.h mule-charset.h redisplay.h scrollbar.h specifier.h symeval.h symsinit.h toolbar.h window.h winslots.h +scrollbar.o: $(LISP_H) buffer.h bufslots.h commands.h conslots.h console.h device.h frame.h frameslots.h glyphs.h gui.h gutter.h lisp-disunion.h lisp-union.h lrecord.h mule-charset.h redisplay.h scrollbar.h specifier.h symeval.h symsinit.h toolbar.h window.h winslots.h search.o: $(LISP_H) buffer.h bufslots.h chartab.h insdel.h lisp-disunion.h lisp-union.h lrecord.h mule-charset.h opaque.h regex.h symeval.h symsinit.h syntax.h select.o: $(LISP_H) buffer.h bufslots.h conslots.h console.h device.h frame.h frameslots.h glyphs.h gui.h lisp-disunion.h lisp-union.h lrecord.h mule-charset.h objects.h opaque.h redisplay.h scrollbar.h select.h specifier.h symeval.h symsinit.h toolbar.h sgiplay.o: $(LISP_H) libst.h lisp-disunion.h lisp-union.h lrecord.h symeval.h symsinit.h diff --git a/src/device-msw.c b/src/device-msw.c index 49231f7..18231ba 100644 --- a/src/device-msw.c +++ b/src/device-msw.c @@ -139,7 +139,9 @@ mswindows_init_device (struct device *d, Lisp_Object props) wc.lpfnWndProc = (WNDPROC) mswindows_wnd_proc; wc.cbClsExtra = 0; wc.cbWndExtra = MSWINDOWS_WINDOW_EXTRA_BYTES; - wc.hInstance = NULL; /* ? */ + /* This must match whatever is passed to CreateWIndowEx, NULL is ok + for this. */ + wc.hInstance = NULL; wc.hIcon = LoadIcon (GetModuleHandle(NULL), XEMACS_CLASS); wc.hCursor = LoadCursor (NULL, IDC_ARROW); /* Background brush is only used during sizing, when XEmacs cannot @@ -151,6 +153,17 @@ mswindows_init_device (struct device *d, Lisp_Object props) wc.hIconSm = LoadImage (GetModuleHandle (NULL), XEMACS_CLASS, IMAGE_ICON, 16, 16, 0); RegisterClassEx (&wc); + +#ifdef HAVE_WIDGETS + xzero (wc); + /* Register the main window class */ + wc.cbSize = sizeof (WNDCLASSEX); + wc.lpfnWndProc = (WNDPROC) mswindows_control_wnd_proc; + wc.lpszClassName = XEMACS_CONTROL_CLASS; + wc.hInstance = NULL; + RegisterClassEx (&wc); +#endif + #ifdef HAVE_TOOLBARS InitCommonControls (); #endif diff --git a/src/device-x.c b/src/device-x.c index 9ea7f0b..80b0f45 100644 --- a/src/device-x.c +++ b/src/device-x.c @@ -743,10 +743,10 @@ x_finish_init_device (struct device *d, Lisp_Object props) } static void -x_mark_device (struct device *d, void (*markobj) (Lisp_Object)) +x_mark_device (struct device *d) { - markobj (DEVICE_X_WM_COMMAND_FRAME (d)); - markobj (DEVICE_X_DATA (d)->x_keysym_map_hash_table); + mark_object (DEVICE_X_WM_COMMAND_FRAME (d)); + mark_object (DEVICE_X_DATA (d)->x_keysym_map_hash_table); } @@ -1893,29 +1893,43 @@ syms_of_device_x (void) } void +reinit_console_type_create_device_x (void) +{ + /* Initialize variables to speed up X resource interactions */ + CONST char *valid_resource_chars = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; + while (*valid_resource_chars) + valid_resource_char_p[(unsigned int) (*valid_resource_chars++)] = 1; + + name_char_dynarr = Dynarr_new (char); + class_char_dynarr = Dynarr_new (char); +} + +void console_type_create_device_x (void) { + reinit_console_type_create_device_x (); CONSOLE_HAS_METHOD (x, init_device); CONSOLE_HAS_METHOD (x, finish_init_device); CONSOLE_HAS_METHOD (x, mark_device); CONSOLE_HAS_METHOD (x, delete_device); CONSOLE_HAS_METHOD (x, device_system_metrics); +} - { - /* Initialize variables to speed up X resource interactions */ - CONST char *valid_resource_chars = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_"; - while (*valid_resource_chars) - valid_resource_char_p[(unsigned int) (*valid_resource_chars++)] = 1; - - name_char_dynarr = Dynarr_new (char); - class_char_dynarr = Dynarr_new (char); - } +void +reinit_vars_of_device_x (void) +{ + error_expected = 0; + error_occurred = 0; + + in_resource_setting = 0; } void vars_of_device_x (void) { + reinit_vars_of_device_x (); + DEFVAR_LISP ("x-emacs-application-class", &Vx_emacs_application_class /* The X application class of the XEmacs process. This controls, among other things, the name of the `app-defaults' file @@ -1958,9 +1972,4 @@ where the localized init files are. staticpro (&Vdefault_x_device); Vdefault_x_device = Qnil; - - error_expected = 0; - error_occurred = 0; - - in_resource_setting = 0; } diff --git a/src/device.c b/src/device.c index dd98407..a080d09 100644 --- a/src/device.c +++ b/src/device.c @@ -73,41 +73,40 @@ Lisp_Object Qslow_device, Qsecurity; Lisp_Object Qdevicep, Qdevice_live_p; -Lisp_Object Qdelete_device; Lisp_Object Qcreate_device_hook; Lisp_Object Qdelete_device_hook; Lisp_Object Vdevice_class_list; static Lisp_Object -mark_device (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_device (Lisp_Object obj) { struct device *d = XDEVICE (obj); - markobj (d->name); - markobj (d->connection); - markobj (d->canon_connection); - markobj (d->console); - markobj (d->selected_frame); - markobj (d->frame_with_focus_real); - markobj (d->frame_with_focus_for_hooks); - markobj (d->frame_that_ought_to_have_focus); - markobj (d->device_class); - markobj (d->user_defined_tags); - markobj (d->pixel_to_glyph_cache.obj1); - markobj (d->pixel_to_glyph_cache.obj2); - - markobj (d->color_instance_cache); - markobj (d->font_instance_cache); + mark_object (d->name); + mark_object (d->connection); + mark_object (d->canon_connection); + mark_object (d->console); + mark_object (d->selected_frame); + mark_object (d->frame_with_focus_real); + mark_object (d->frame_with_focus_for_hooks); + mark_object (d->frame_that_ought_to_have_focus); + mark_object (d->device_class); + mark_object (d->user_defined_tags); + mark_object (d->pixel_to_glyph_cache.obj1); + mark_object (d->pixel_to_glyph_cache.obj2); + + mark_object (d->color_instance_cache); + mark_object (d->font_instance_cache); #ifdef MULE - markobj (d->charset_font_cache); + mark_object (d->charset_font_cache); #endif - markobj (d->image_instance_cache); + mark_object (d->image_instance_cache); if (d->devmeths) { - markobj (d->devmeths->symbol); - MAYBE_DEVMETH (d, mark_device, (d, markobj)); + mark_object (d->devmeths->symbol); + MAYBE_DEVMETH (d, mark_device, (d)); } return (d->frame_list); @@ -1250,7 +1249,6 @@ syms_of_device (void) defsymbol (&Qdevicep, "devicep"); defsymbol (&Qdevice_live_p, "device-live-p"); - defsymbol (&Qdelete_device, "delete-device"); defsymbol (&Qcreate_device_hook, "create-device-hook"); defsymbol (&Qdelete_device_hook, "delete-device-hook"); @@ -1299,8 +1297,18 @@ syms_of_device (void) } void +reinit_vars_of_device (void) +{ + staticpro_nodump (&Vdefault_device); + Vdefault_device = Qnil; + asynch_device_change_pending = 0; +} + +void vars_of_device (void) { + reinit_vars_of_device (); + DEFVAR_LISP ("create-device-hook", &Vcreate_device_hook /* Function or functions to call when a device is created. One argument, the newly-created device. @@ -1316,11 +1324,6 @@ One argument, the to-be-deleted device. */ ); Vdelete_device_hook = Qnil; - staticpro (&Vdefault_device); - Vdefault_device = Qnil; - - asynch_device_change_pending = 0; - Vdevice_class_list = list3 (Qcolor, Qgrayscale, Qmono); staticpro (&Vdevice_class_list); diff --git a/src/device.h b/src/device.h index 1e8f0b5..b144afa 100644 --- a/src/device.h +++ b/src/device.h @@ -168,6 +168,7 @@ struct device unsigned int frame_changed :1; unsigned int glyphs_changed :1; unsigned int subwindows_changed :1; + unsigned int subwindows_state_changed :1; unsigned int icon_changed :1; unsigned int menubar_changed :1; unsigned int modeline_changed :1; @@ -220,7 +221,6 @@ DECLARE_LRECORD (device, struct device); #define XDEVICE(x) XRECORD (x, device, struct device) #define XSETDEVICE(x, p) XSETRECORD (x, p, device) #define DEVICEP(x) RECORDP (x, device) -#define GC_DEVICEP(x) GC_RECORDP (x, device) #define CHECK_DEVICE(x) CHECK_RECORD (x, device) #define CONCHECK_DEVICE(x) CONCHECK_RECORD (x, device) @@ -247,7 +247,7 @@ error_check_device_type (struct device *d, Lisp_Object sym) return d; } # define DEVICE_TYPE_DATA(d, type) \ - ((struct type##_device *) (error_check_device_type (d, Q##type))->device_data) + ((struct type##_device *) error_check_device_type (d, Q##type)->device_data) #else # define DEVICE_TYPE_DATA(d, type) \ ((struct type##_device *) (d)->device_data) @@ -348,6 +348,9 @@ int valid_device_class_p (Lisp_Object class); #define MARK_DEVICE_SUBWINDOWS_CHANGED(d) \ ((void) (subwindows_changed = (d)->subwindows_changed = 1)) +#define MARK_DEVICE_SUBWINDOWS_STATE_CHANGED(d) \ + ((void) (subwindows_state_changed = (d)->subwindows_state_changed = 1)) + #define MARK_DEVICE_TOOLBARS_CHANGED(d) \ ((void) (toolbar_changed = (d)->toolbar_changed = 1)) @@ -365,6 +368,14 @@ int valid_device_class_p (Lisp_Object class); MARK_DEVICE_FACES_CHANGED (mdffc_d); \ } while (0) +#define MARK_DEVICE_FRAMES_GLYPHS_CHANGED(d) do { \ + struct device *mdffc_d = (d); \ + Lisp_Object frmcons; \ + DEVICE_FRAME_LOOP (frmcons, mdffc_d) \ + XFRAME (XCAR (frmcons))->glyphs_changed = 1; \ + MARK_DEVICE_GLYPHS_CHANGED (mdffc_d); \ +} while (0) + #define MARK_DEVICE_FRAME_CHANGED(d) \ ((void) (frame_changed = (d)->frame_changed = 1)) diff --git a/src/dired.c b/src/dired.c index 472133e..e247ac5 100644 --- a/src/dired.c +++ b/src/dired.c @@ -558,7 +558,7 @@ These are all user names which begin with USER. } struct user_cache { - char **data; + Bufbyte **data; int length; int size; EMACS_TIME last_rebuild_time; @@ -634,9 +634,10 @@ user_name_completion (Lisp_Object user, int all_flag, int *uniq) Bufbyte *pwuser; QUIT; DO_REALLOC (user_cache.data, user_cache.size, - user_cache.length + 1, char *); + user_cache.length + 1, Bufbyte *); GET_C_CHARPTR_INT_DATA_ALLOCA (pwd->pw_name, FORMAT_OS, pwuser); - user_cache.data[user_cache.length++] = xstrdup (pwuser); + user_cache.data[user_cache.length++] = + (Bufbyte *) xstrdup ((char *) pwuser); } endpwent (); speed_up_interrupts (); diff --git a/src/doprnt.c b/src/doprnt.c index 8259c5a..b0ed31c 100644 --- a/src/doprnt.c +++ b/src/doprnt.c @@ -386,7 +386,7 @@ get_doprnt_args (printf_spec_dynarr *specs, va_list vargs) if (strchr (int_converters, ch)) { if (spec->h_flag) - arg.i = va_arg (vargs, short); + arg.i = va_arg (vargs, int /* short */); else if (spec->l_flag) arg.l = va_arg (vargs, long); else @@ -395,7 +395,7 @@ get_doprnt_args (printf_spec_dynarr *specs, va_list vargs) else if (strchr (unsigned_int_converters, ch)) { if (spec->h_flag) - arg.ui = va_arg (vargs, unsigned short); + arg.ui = va_arg (vargs, unsigned int /* unsigned short */); else if (spec->l_flag) arg.ul = va_arg (vargs, unsigned long); else diff --git a/src/dynarr.c b/src/dynarr.c index 4167b5b..02f4343 100644 --- a/src/dynarr.c +++ b/src/dynarr.c @@ -111,6 +111,19 @@ Use the following global variable: int Dynarr_min_size = 1; +static void +Dynarr_realloc (Dynarr *dy, int new_size) +{ + if (DUMPEDP (dy->base)) + { + void *new_base = malloc (new_size); + memcpy (new_base, dy->base, dy->max > new_size ? new_size : dy->max); + dy->base = new_base; + } + else + dy->base = xrealloc (dy->base, new_size); +} + void * Dynarr_newf (int elsize) { @@ -138,7 +151,7 @@ Dynarr_resize (void *d, int size) /* Don't do anything if the array is already big enough. */ if (newsize > dy->max) { - dy->base = xrealloc (dy->base, newsize*dy->elsize); + Dynarr_realloc (dy, newsize*dy->elsize); dy->max = newsize; } } @@ -186,9 +199,10 @@ Dynarr_free (void *d) { Dynarr *dy = (Dynarr *) d; - if (dy->base) + if (dy->base && !DUMPEDP (dy->base)) xfree (dy->base); - xfree (dy); + if(!DUMPEDP (dy)) + xfree (dy); } #ifdef MEMORY_USAGE_STATS diff --git a/src/editfns.c b/src/editfns.c index b914b4a..e3dd769 100644 --- a/src/editfns.c +++ b/src/editfns.c @@ -45,6 +45,7 @@ Boston, MA 02111-1307, USA. */ #include "systime.h" #include "sysdep.h" #include "syspwd.h" +#include "sysfile.h" /* for getcwd */ /* Some static data, and a function to initialize it for each run */ diff --git a/src/eldap.c b/src/eldap.c index 8dd06bd..a0dd5f7 100644 --- a/src/eldap.c +++ b/src/eldap.c @@ -47,14 +47,13 @@ static Lisp_Object Vldap_default_base; Lisp_Object Qldapp; /* ldap-open plist keywords */ -extern Lisp_Object Qport, Qauth, Qbinddn, Qpasswd, Qderef, Qtimelimit, - Qsizelimit; +static Lisp_Object Qport, Qauth, Qbinddn, Qpasswd, Qderef, Qtimelimit, Qsizelimit; /* Search scope limits */ -extern Lisp_Object Qbase, Qonelevel, Qsubtree; +static Lisp_Object Qbase, Qonelevel, Qsubtree; /* Authentication methods */ -extern Lisp_Object Qkrbv41, Qkrbv42; +static Lisp_Object Qkrbv41, Qkrbv42; /* Deref policy */ -extern Lisp_Object Qnever, Qalways, Qfind; +static Lisp_Object Qnever, Qalways, Qfind; /************************************************************************/ /* Utility Functions */ @@ -98,7 +97,7 @@ make_ldap (struct Lisp_LDAP *ldap) } static Lisp_Object -mark_ldap (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_ldap (Lisp_Object obj) { return XLDAP (obj)->host; } @@ -579,6 +578,22 @@ void syms_of_eldap (void) { defsymbol (&Qldapp, "ldapp"); + defsymbol (&Qport, "port"); + defsymbol (&Qauth, "auth"); + defsymbol (&Qbinddn, "binddn"); + defsymbol (&Qpasswd, "passwd"); + defsymbol (&Qderef, "deref"); + defsymbol (&Qtimelimit, "timelimit"); + defsymbol (&Qsizelimit, "sizelimit"); + defsymbol (&Qbase, "base"); + defsymbol (&Qonelevel, "onelevel"); + defsymbol (&Qsubtree, "subtree"); + defsymbol (&Qkrbv41, "krbv41"); + defsymbol (&Qkrbv42, "krbv42"); + defsymbol (&Qnever, "never"); + defsymbol (&Qalways, "always"); + defsymbol (&Qfind, "find"); + DEFSUBR (Fldapp); DEFSUBR (Fldap_host); DEFSUBR (Fldap_status); diff --git a/src/eldap.h b/src/eldap.h index 29f9aa9..788f88e 100644 --- a/src/eldap.h +++ b/src/eldap.h @@ -44,7 +44,6 @@ DECLARE_LRECORD (ldap, struct Lisp_LDAP); #define XLDAP(x) XRECORD (x, ldap, struct Lisp_LDAP) #define XSETLDAP(x, p) XSETRECORD (x, p, ldap) #define LDAPP(x) RECORDP (x, ldap) -#define GC_LDAPP(x) GC_RECORDP (x, ldap) #define CHECK_LDAP(x) CHECK_RECORD (x, ldap) #define CONCHECK_LDAP(x) CONCHECK_RECORD (x, ldap) diff --git a/src/elhash.c b/src/elhash.c index b53f7a0..f3b79f5 100644 --- a/src/elhash.c +++ b/src/elhash.c @@ -27,11 +27,15 @@ Boston, MA 02111-1307, USA. */ #include "bytecode.h" #include "elhash.h" -Lisp_Object Qhash_tablep, Qhashtable, Qhash_table; -Lisp_Object Qweak, Qkey_weak, Qvalue_weak, Qnon_weak; +Lisp_Object Qhash_tablep; +static Lisp_Object Qhashtable, Qhash_table; +static Lisp_Object Qweakness, Qvalue; static Lisp_Object Vall_weak_hash_tables; static Lisp_Object Qrehash_size, Qrehash_threshold; -static Lisp_Object Q_size, Q_test, Q_type, Q_rehash_size, Q_rehash_threshold; +static Lisp_Object Q_size, Q_test, Q_weakness, Q_rehash_size, Q_rehash_threshold; + +/* obsolete as of 19990901 in xemacs-21.2 */ +static Lisp_Object Qweak, Qkey_weak, Qvalue_weak, Qnon_weak, Q_type; typedef struct hentry { @@ -51,14 +55,16 @@ struct Lisp_Hash_Table hash_table_hash_function_t hash_function; hash_table_test_function_t test_function; hentry *hentries; - enum hash_table_type type; /* whether and how this hash table is weak */ + enum hash_table_weakness weakness; Lisp_Object next_weak; /* Used to chain together all of the weak hash tables. Don't mark through this. */ }; typedef struct Lisp_Hash_Table Lisp_Hash_Table; #define HENTRY_CLEAR_P(hentry) ((*(EMACS_UINT*)(&((hentry)->key))) == 0) -#define CLEAR_HENTRY(hentry) ((*(EMACS_UINT*)(&((hentry)->key))) = 0) +#define CLEAR_HENTRY(hentry) \ + ((*(EMACS_UINT*)(&((hentry)->key))) = 0, \ + (*(EMACS_UINT*)(&((hentry)->value))) = 0) #define HASH_TABLE_DEFAULT_SIZE 16 #define HASH_TABLE_DEFAULT_REHASH_SIZE 1.3 @@ -190,29 +196,29 @@ lisp_object_equal_hash (Lisp_Object obj) static Lisp_Object -mark_hash_table (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_hash_table (Lisp_Object obj) { Lisp_Hash_Table *ht = XHASH_TABLE (obj); /* If the hash table is weak, we don't want to mark the keys and values (we scan over them after everything else has been marked, and mark or remove them as necessary). */ - if (ht->type == HASH_TABLE_NON_WEAK) + if (ht->weakness == HASH_TABLE_NON_WEAK) { hentry *e, *sentinel; for (e = ht->hentries, sentinel = e + ht->size; e < sentinel; e++) if (!HENTRY_CLEAR_P (e)) { - markobj (e->key); - markobj (e->value); + mark_object (e->key); + mark_object (e->value); } } return Qnil; } /* Equality of hash tables. Two hash tables are equal when they are of - the same type and test function, they have the same number of + the same weakness and test function, they have the same number of elements, and for each key in the hash table, the values are `equal'. This is similar to Common Lisp `equalp' of hash tables, with the @@ -229,7 +235,7 @@ hash_table_equal (Lisp_Object hash_table1, Lisp_Object hash_table2, int depth) hentry *e, *sentinel; if ((ht1->test_function != ht2->test_function) || - (ht1->type != ht2->type) || + (ht1->weakness != ht2->weakness) || (ht1->count != ht2->count)) return 0; @@ -256,9 +262,13 @@ hash_table_equal (Lisp_Object hash_table1, Lisp_Object hash_table2, int depth) #s(hash-table size 2 data (key1 value1 key2 value2)) - The supported keywords are `type' (non-weak (or nil), weak, - key-weak and value-weak), `test' (eql (or nil), eq or equal), - `size' (a natnum or nil) and `data' (a list). + The supported hash table structure keywords and their values are: + `test' (eql (or nil), eq or equal) + `size' (a natnum or nil) + `rehash-size' (a float) + `rehash-threshold' (a float) + `weakness' (nil, t, key or value) + `data' (a list) If `print-readably' is non-nil, then a simpler syntax is used; for instance: @@ -307,16 +317,6 @@ print_hash_table (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) write_c_string (print_readably ? "#s(hash-table" : "#type != HASH_TABLE_NON_WEAK) - { - sprintf (buf, " type %s", - (ht->type == HASH_TABLE_WEAK ? "weak" : - ht->type == HASH_TABLE_KEY_WEAK ? "key-weak" : - ht->type == HASH_TABLE_VALUE_WEAK ? "value-weak" : - "you-d-better-not-see-this")); - write_c_string (buf, printcharfun); - } - /* These checks have a kludgy look to them, but they are safe. Due to nature of hashing, you cannot use arbitrary test functions anyway. */ @@ -340,6 +340,16 @@ print_hash_table (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) write_c_string (buf, printcharfun); } + if (ht->weakness != HASH_TABLE_NON_WEAK) + { + sprintf (buf, " weakness %s", + (ht->weakness == HASH_TABLE_WEAK ? "t" : + ht->weakness == HASH_TABLE_KEY_WEAK ? "key" : + ht->weakness == HASH_TABLE_VALUE_WEAK ? "value" : + "you-d-better-not-see-this")); + write_c_string (buf, printcharfun); + } + if (ht->count) print_hash_table_data (ht, printcharfun); @@ -374,9 +384,10 @@ static const struct struct_description hentry_description = { hentry_description_1 }; -static const struct lrecord_description hash_table_description[] = { +const struct lrecord_description hash_table_description[] = { { XD_SIZE_T, offsetof(Lisp_Hash_Table, size) }, - { XD_STRUCT_PTR, offsetof(Lisp_Hash_Table, hentries), XD_INDIRECT(0), &hentry_description }, + { XD_STRUCT_PTR, offsetof(Lisp_Hash_Table, hentries), XD_INDIRECT(0, 1), &hentry_description }, + { XD_LO_LINK, offsetof(Lisp_Hash_Table, next_weak) }, { XD_END } }; @@ -421,18 +432,18 @@ compute_hash_table_derived_values (Lisp_Hash_Table *ht) } Lisp_Object -make_general_lisp_hash_table (size_t size, - enum hash_table_type type, - enum hash_table_test test, - double rehash_size, - double rehash_threshold) +make_general_lisp_hash_table (enum hash_table_test test, + size_t size, + double rehash_size, + double rehash_threshold, + enum hash_table_weakness weakness) { Lisp_Object hash_table; Lisp_Hash_Table *ht = alloc_lcrecord_type (Lisp_Hash_Table, &lrecord_hash_table); - ht->type = type; ht->rehash_size = rehash_size; ht->rehash_threshold = rehash_threshold; + ht->weakness = weakness; switch (test) { @@ -477,7 +488,7 @@ make_general_lisp_hash_table (size_t size, XSETHASH_TABLE (hash_table, ht); - if (type == HASH_TABLE_NON_WEAK) + if (weakness == HASH_TABLE_NON_WEAK) ht->next_weak = Qunbound; else ht->next_weak = Vall_weak_hash_tables, Vall_weak_hash_tables = hash_table; @@ -487,11 +498,11 @@ make_general_lisp_hash_table (size_t size, Lisp_Object make_lisp_hash_table (size_t size, - enum hash_table_type type, + enum hash_table_weakness weakness, enum hash_table_test test) { - return make_general_lisp_hash_table (size, type, test, - HASH_TABLE_DEFAULT_REHASH_SIZE, -1.0); + return make_general_lisp_hash_table + (test, size, HASH_TABLE_DEFAULT_REHASH_SIZE, -1.0, weakness); } /* Pretty reading of hash tables. @@ -524,30 +535,40 @@ decode_hash_table_size (Lisp_Object obj) } static int -hash_table_type_validate (Lisp_Object keyword, Lisp_Object value, - Error_behavior errb) +hash_table_weakness_validate (Lisp_Object keyword, Lisp_Object value, + Error_behavior errb) { if (EQ (value, Qnil)) return 1; + if (EQ (value, Qt)) return 1; + if (EQ (value, Qkey)) return 1; + if (EQ (value, Qvalue)) return 1; + + /* Following values are obsolete as of 19990901 in xemacs-21.2 */ if (EQ (value, Qnon_weak)) return 1; if (EQ (value, Qweak)) return 1; if (EQ (value, Qkey_weak)) return 1; if (EQ (value, Qvalue_weak)) return 1; - maybe_signal_simple_error ("Invalid hash table type", + maybe_signal_simple_error ("Invalid hash table weakness", value, Qhash_table, errb); return 0; } -static enum hash_table_type -decode_hash_table_type (Lisp_Object obj) +static enum hash_table_weakness +decode_hash_table_weakness (Lisp_Object obj) { if (EQ (obj, Qnil)) return HASH_TABLE_NON_WEAK; + if (EQ (obj, Qt)) return HASH_TABLE_WEAK; + if (EQ (obj, Qkey)) return HASH_TABLE_KEY_WEAK; + if (EQ (obj, Qvalue)) return HASH_TABLE_VALUE_WEAK; + + /* Following values are obsolete as of 19990901 in xemacs-21.2 */ if (EQ (obj, Qnon_weak)) return HASH_TABLE_NON_WEAK; if (EQ (obj, Qweak)) return HASH_TABLE_WEAK; if (EQ (obj, Qkey_weak)) return HASH_TABLE_KEY_WEAK; if (EQ (obj, Qvalue_weak)) return HASH_TABLE_VALUE_WEAK; - signal_simple_error ("Invalid hash table type", obj); + signal_simple_error ("Invalid hash table weakness", obj); return HASH_TABLE_NON_WEAK; /* not reached */ } @@ -579,7 +600,7 @@ decode_hash_table_test (Lisp_Object obj) static int hash_table_rehash_size_validate (Lisp_Object keyword, Lisp_Object value, - Error_behavior errb) + Error_behavior errb) { if (!FLOATP (value)) { @@ -668,11 +689,11 @@ hash_table_instantiate (Lisp_Object plist) { Lisp_Object hash_table; Lisp_Object test = Qnil; - Lisp_Object type = Qnil; Lisp_Object size = Qnil; - Lisp_Object data = Qnil; Lisp_Object rehash_size = Qnil; Lisp_Object rehash_threshold = Qnil; + Lisp_Object weakness = Qnil; + Lisp_Object data = Qnil; while (!NILP (plist)) { @@ -681,22 +702,23 @@ hash_table_instantiate (Lisp_Object plist) value = XCAR (plist); plist = XCDR (plist); if (EQ (key, Qtest)) test = value; - else if (EQ (key, Qtype)) type = value; else if (EQ (key, Qsize)) size = value; - else if (EQ (key, Qdata)) data = value; else if (EQ (key, Qrehash_size)) rehash_size = value; else if (EQ (key, Qrehash_threshold)) rehash_threshold = value; + else if (EQ (key, Qweakness)) weakness = value; + else if (EQ (key, Qdata)) data = value; + else if (EQ (key, Qtype))/*obsolete*/ weakness = value; else abort (); } /* Create the hash table. */ hash_table = make_general_lisp_hash_table - (decode_hash_table_size (size), - decode_hash_table_type (type), - decode_hash_table_test (test), + (decode_hash_table_test (test), + decode_hash_table_size (size), decode_hash_table_rehash_size (rehash_size), - decode_hash_table_rehash_threshold (rehash_threshold)); + decode_hash_table_rehash_threshold (rehash_threshold), + decode_hash_table_weakness (weakness)); /* I'm not sure whether this can GC, but better safe than sorry. */ { @@ -723,17 +745,20 @@ structure_type_create_hash_table_structure_name (Lisp_Object structure_name) struct structure_type *st; st = define_structure_type (structure_name, 0, hash_table_instantiate); - define_structure_type_keyword (st, Qsize, hash_table_size_validate); define_structure_type_keyword (st, Qtest, hash_table_test_validate); - define_structure_type_keyword (st, Qtype, hash_table_type_validate); - define_structure_type_keyword (st, Qdata, hash_table_data_validate); + define_structure_type_keyword (st, Qsize, hash_table_size_validate); define_structure_type_keyword (st, Qrehash_size, hash_table_rehash_size_validate); define_structure_type_keyword (st, Qrehash_threshold, hash_table_rehash_threshold_validate); + define_structure_type_keyword (st, Qweakness, hash_table_weakness_validate); + define_structure_type_keyword (st, Qdata, hash_table_data_validate); + + /* obsolete as of 19990901 in xemacs-21.2 */ + define_structure_type_keyword (st, Qtype, hash_table_weakness_validate); } /* Create a built-in Lisp structure type named `hash-table'. We make #s(hashtable ...) equivalent to #s(hash-table ...), - for backward comptabibility. + for backward compatibility. This is called from emacs.c. */ void structure_type_create_hash_table (void) @@ -758,17 +783,23 @@ Return t if OBJECT is a hash table, else nil. DEFUN ("make-hash-table", Fmake_hash_table, 0, MANY, 0, /* Return a new empty hash table object. Use Common Lisp style keywords to specify hash table properties. - (make-hash-table &key :size :test :type :rehash-size :rehash-threshold) - -Keyword :size specifies the number of keys likely to be inserted. -This number of entries can be inserted without enlarging the hash table. + (make-hash-table &key test size rehash-size rehash-threshold weakness) Keyword :test can be `eq', `eql' (default) or `equal'. Comparison between keys is done using this function. If speed is important, consider using `eq'. When storing strings in the hash table, you will likely need to use `equal'. -Keyword :type can be `non-weak' (default), `weak', `key-weak' or `value-weak'. +Keyword :size specifies the number of keys likely to be inserted. +This number of entries can be inserted without enlarging the hash table. + +Keyword :rehash-size must be a float greater than 1.0, and specifies +the factor by which to increase the size of the hash table when enlarging. + +Keyword :rehash-threshold must be a float between 0.0 and 1.0, +and specifies the load factor of the hash table which triggers enlarging. + +Non-standard keyword :weakness can be `nil' (default), `t', `key' or `value'. A weak hash table is one whose pointers do not count as GC referents: for any key-value pair in the hash table, if the only remaining pointer @@ -788,58 +819,48 @@ that a key-value pair will be removed only if the value remains unmarked outside of weak hash tables. The pair will remain in the hash table if the value is pointed to by something other than a weak hash table, even if the key is not. - -Keyword :rehash-size must be a float greater than 1.0, and specifies -the factor by which to increase the size of the hash table when enlarging. - -Keyword :rehash-threshold must be a float between 0.0 and 1.0, -and specifies the load factor of the hash table which triggers enlarging. - */ (int nargs, Lisp_Object *args)) { - int j = 0; - Lisp_Object size = Qnil; - Lisp_Object type = Qnil; + int i = 0; Lisp_Object test = Qnil; + Lisp_Object size = Qnil; Lisp_Object rehash_size = Qnil; Lisp_Object rehash_threshold = Qnil; + Lisp_Object weakness = Qnil; - while (j < nargs) + while (i + 1 < nargs) { - Lisp_Object keyword, value; - - keyword = args[j++]; - if (!KEYWORDP (keyword)) - signal_simple_error ("Invalid hash table property keyword", keyword); - if (j == nargs) - signal_simple_error ("Hash table property requires a value", keyword); - - value = args[j++]; + Lisp_Object keyword = args[i++]; + Lisp_Object value = args[i++]; - if (EQ (keyword, Q_size)) size = value; - else if (EQ (keyword, Q_type)) type = value; - else if (EQ (keyword, Q_test)) test = value; + if (EQ (keyword, Q_test)) test = value; + else if (EQ (keyword, Q_size)) size = value; else if (EQ (keyword, Q_rehash_size)) rehash_size = value; else if (EQ (keyword, Q_rehash_threshold)) rehash_threshold = value; + else if (EQ (keyword, Q_weakness)) weakness = value; + else if (EQ (keyword, Q_type))/*obsolete*/ weakness = value; else signal_simple_error ("Invalid hash table property keyword", keyword); } + if (i < nargs) + signal_simple_error ("Hash table property requires a value", args[i]); + #define VALIDATE_VAR(var) \ if (!NILP (var)) hash_table_##var##_validate (Q##var, var, ERROR_ME); - VALIDATE_VAR (size); - VALIDATE_VAR (type); VALIDATE_VAR (test); + VALIDATE_VAR (size); VALIDATE_VAR (rehash_size); VALIDATE_VAR (rehash_threshold); + VALIDATE_VAR (weakness); return make_general_lisp_hash_table - (decode_hash_table_size (size), - decode_hash_table_type (type), - decode_hash_table_test (test), + (decode_hash_table_test (test), + decode_hash_table_size (size), decode_hash_table_rehash_size (rehash_size), - decode_hash_table_rehash_threshold (rehash_threshold)); + decode_hash_table_rehash_threshold (rehash_threshold), + decode_hash_table_weakness (weakness)); } DEFUN ("copy-hash-table", Fcopy_hash_table, 1, 1, 0, /* @@ -868,14 +889,13 @@ The keys and values will not themselves be copied. } static void -enlarge_hash_table (Lisp_Hash_Table *ht) +resize_hash_table (Lisp_Hash_Table *ht, size_t new_size) { hentry *old_entries, *new_entries, *old_sentinel, *new_sentinel, *e; - size_t old_size, new_size; + size_t old_size; old_size = ht->size; - new_size = ht->size = - hash_table_size ((size_t) ((double) old_size * ht->rehash_size)); + ht->size = new_size; old_entries = ht->hentries; @@ -899,7 +919,22 @@ enlarge_hash_table (Lisp_Hash_Table *ht) *probe = *e; } - xfree (old_entries); + if (!DUMPEDP (old_entries)) + xfree (old_entries); +} + +void +reorganize_hash_table (Lisp_Hash_Table *ht) +{ + resize_hash_table (ht, ht->size); +} + +static void +enlarge_hash_table (Lisp_Hash_Table *ht) +{ + size_t new_size = + hash_table_size ((size_t) ((double) ht->size * ht->rehash_size)); + resize_hash_table (ht, new_size); } static hentry * @@ -955,7 +990,8 @@ static void remhash_1 (Lisp_Hash_Table *ht, hentry *entries, hentry *probe) { size_t size = ht->size; - CLEAR_HENTRY (probe++); + CLEAR_HENTRY (probe); + probe++; ht->count--; LINEAR_PROBING_LOOP (probe, entries, size) @@ -1016,30 +1052,6 @@ Return the number of entries in HASH-TABLE. return make_int (xhash_table (hash_table)->count); } -DEFUN ("hash-table-size", Fhash_table_size, 1, 1, 0, /* -Return the size of HASH-TABLE. -This is the current number of slots in HASH-TABLE, whether occupied or not. -*/ - (hash_table)) -{ - return make_int (xhash_table (hash_table)->size); -} - -DEFUN ("hash-table-type", Fhash_table_type, 1, 1, 0, /* -Return the type of HASH-TABLE. -This can be one of `non-weak', `weak', `key-weak' or `value-weak'. -*/ - (hash_table)) -{ - switch (xhash_table (hash_table)->type) - { - case HASH_TABLE_WEAK: return Qweak; - case HASH_TABLE_KEY_WEAK: return Qkey_weak; - case HASH_TABLE_VALUE_WEAK: return Qvalue_weak; - default: return Qnon_weak; - } -} - DEFUN ("hash-table-test", Fhash_table_test, 1, 1, 0, /* Return the test function of HASH-TABLE. This can be one of `eq', `eql' or `equal'. @@ -1053,6 +1065,15 @@ This can be one of `eq', `eql' or `equal'. Qeq); } +DEFUN ("hash-table-size", Fhash_table_size, 1, 1, 0, /* +Return the size of HASH-TABLE. +This is the current number of slots in HASH-TABLE, whether occupied or not. +*/ + (hash_table)) +{ + return make_int (xhash_table (hash_table)->size); +} + DEFUN ("hash-table-rehash-size", Fhash_table_rehash_size, 1, 1, 0, /* Return the current rehash size of HASH-TABLE. This is a float greater than 1.0; the factor by which HASH-TABLE @@ -1073,6 +1094,37 @@ beyond which the HASH-TABLE is enlarged by rehashing. return make_float (hash_table_rehash_threshold (xhash_table (hash_table))); } +DEFUN ("hash-table-weakness", Fhash_table_weakness, 1, 1, 0, /* +Return the weakness of HASH-TABLE. +This can be one of `nil', `t', `key' or `value'. +*/ + (hash_table)) +{ + switch (xhash_table (hash_table)->weakness) + { + case HASH_TABLE_WEAK: return Qt; + case HASH_TABLE_KEY_WEAK: return Qkey; + case HASH_TABLE_VALUE_WEAK: return Qvalue; + default: return Qnil; + } +} + +/* obsolete as of 19990901 in xemacs-21.2 */ +DEFUN ("hash-table-type", Fhash_table_type, 1, 1, 0, /* +Return the type of HASH-TABLE. +This can be one of `non-weak', `weak', `key-weak' or `value-weak'. +*/ + (hash_table)) +{ + switch (xhash_table (hash_table)->weakness) + { + case HASH_TABLE_WEAK: return Qweak; + case HASH_TABLE_KEY_WEAK: return Qkey_weak; + case HASH_TABLE_VALUE_WEAK: return Qvalue_weak; + default: return Qnon_weak; + } +} + /************************************************************************/ /* Mapping Functions */ /************************************************************************/ @@ -1156,21 +1208,20 @@ elisp_map_remhash (maphash_function_t predicate, /* Complete the marking for semi-weak hash tables. */ int -finish_marking_weak_hash_tables (int (*obj_marked_p) (Lisp_Object), - void (*markobj) (Lisp_Object)) +finish_marking_weak_hash_tables (void) { Lisp_Object hash_table; int did_mark = 0; for (hash_table = Vall_weak_hash_tables; - !GC_NILP (hash_table); + !NILP (hash_table); hash_table = XHASH_TABLE (hash_table)->next_weak) { CONST Lisp_Hash_Table *ht = XHASH_TABLE (hash_table); CONST hentry *e = ht->hentries; CONST hentry *sentinel = e + ht->size; - if (! obj_marked_p (hash_table)) + if (! marked_p (hash_table)) /* The hash table is probably garbage. Ignore it. */ continue; @@ -1178,28 +1229,28 @@ finish_marking_weak_hash_tables (int (*obj_marked_p) (Lisp_Object), half-marked, we may need to mark the other half if we're keeping this pair. */ #define MARK_OBJ(obj) \ -do { if (!obj_marked_p (obj)) markobj (obj), did_mark = 1; } while (0) +do { if (!marked_p (obj)) mark_object (obj), did_mark = 1; } while (0) - switch (ht->type) + switch (ht->weakness) { case HASH_TABLE_KEY_WEAK: for (; e < sentinel; e++) if (!HENTRY_CLEAR_P (e)) - if (obj_marked_p (e->key)) + if (marked_p (e->key)) MARK_OBJ (e->value); break; case HASH_TABLE_VALUE_WEAK: for (; e < sentinel; e++) if (!HENTRY_CLEAR_P (e)) - if (obj_marked_p (e->value)) + if (marked_p (e->value)) MARK_OBJ (e->key); break; case HASH_TABLE_KEY_CAR_WEAK: for (; e < sentinel; e++) if (!HENTRY_CLEAR_P (e)) - if (!CONSP (e->key) || obj_marked_p (XCAR (e->key))) + if (!CONSP (e->key) || marked_p (XCAR (e->key))) { MARK_OBJ (e->key); MARK_OBJ (e->value); @@ -1209,7 +1260,7 @@ do { if (!obj_marked_p (obj)) markobj (obj), did_mark = 1; } while (0) case HASH_TABLE_VALUE_CAR_WEAK: for (; e < sentinel; e++) if (!HENTRY_CLEAR_P (e)) - if (!CONSP (e->value) || obj_marked_p (XCAR (e->value))) + if (!CONSP (e->value) || marked_p (XCAR (e->value))) { MARK_OBJ (e->key); MARK_OBJ (e->value); @@ -1225,17 +1276,17 @@ do { if (!obj_marked_p (obj)) markobj (obj), did_mark = 1; } while (0) } void -prune_weak_hash_tables (int (*obj_marked_p) (Lisp_Object)) +prune_weak_hash_tables (void) { Lisp_Object hash_table, prev = Qnil; for (hash_table = Vall_weak_hash_tables; - !GC_NILP (hash_table); + !NILP (hash_table); hash_table = XHASH_TABLE (hash_table)->next_weak) { - if (! obj_marked_p (hash_table)) + if (! marked_p (hash_table)) { /* This hash table itself is garbage. Remove it from the list. */ - if (GC_NILP (prev)) + if (NILP (prev)) Vall_weak_hash_tables = XHASH_TABLE (hash_table)->next_weak; else XHASH_TABLE (prev)->next_weak = XHASH_TABLE (hash_table)->next_weak; @@ -1244,7 +1295,7 @@ prune_weak_hash_tables (int (*obj_marked_p) (Lisp_Object)) { /* Now, scan over all the pairs. Remove all of the pairs in which the key or value, or both, is unmarked - (depending on the type of weak hash table). */ + (depending on the weakness of the hash table). */ Lisp_Hash_Table *ht = XHASH_TABLE (hash_table); hentry *entries = ht->hentries; hentry *sentinel = entries + ht->size; @@ -1254,7 +1305,7 @@ prune_weak_hash_tables (int (*obj_marked_p) (Lisp_Object)) if (!HENTRY_CLEAR_P (e)) { again: - if (!obj_marked_p (e->key) || !obj_marked_p (e->value)) + if (!marked_p (e->key) || !marked_p (e->value)) { remhash_1 (ht, entries, e); if (!HENTRY_CLEAR_P (e)) @@ -1337,6 +1388,15 @@ internal_hash (Lisp_Object obj, int depth) return LISP_HASH (obj); } +DEFUN ("sxhash", Fsxhash, 1, 1, 0, /* +Return a hash value for OBJECT. +(equal obj1 obj2) implies (= (sxhash obj1) (sxhash obj2)). +*/ + (object)) +{ + return make_int (internal_hash (object, 0)); +} + #if 0 xxDEFUN ("internal-hash-value", Finternal_hash_value, 1, 1, 0, /* Hash value of OBJECT. For debugging. @@ -1367,11 +1427,13 @@ syms_of_elhash (void) DEFSUBR (Fclrhash); DEFSUBR (Fmaphash); DEFSUBR (Fhash_table_count); + DEFSUBR (Fhash_table_test); DEFSUBR (Fhash_table_size); DEFSUBR (Fhash_table_rehash_size); DEFSUBR (Fhash_table_rehash_threshold); - DEFSUBR (Fhash_table_type); - DEFSUBR (Fhash_table_test); + DEFSUBR (Fhash_table_weakness); + DEFSUBR (Fhash_table_type); /* obsolete */ + DEFSUBR (Fsxhash); #if 0 DEFSUBR (Finternal_hash_value); #endif @@ -1379,18 +1441,22 @@ syms_of_elhash (void) defsymbol (&Qhash_tablep, "hash-table-p"); defsymbol (&Qhash_table, "hash-table"); defsymbol (&Qhashtable, "hashtable"); - defsymbol (&Qweak, "weak"); - defsymbol (&Qkey_weak, "key-weak"); - defsymbol (&Qvalue_weak, "value-weak"); - defsymbol (&Qnon_weak, "non-weak"); + defsymbol (&Qweakness, "weakness"); + defsymbol (&Qvalue, "value"); defsymbol (&Qrehash_size, "rehash-size"); defsymbol (&Qrehash_threshold, "rehash-threshold"); - defkeyword (&Q_size, ":size"); + defsymbol (&Qweak, "weak"); /* obsolete */ + defsymbol (&Qkey_weak, "key-weak"); /* obsolete */ + defsymbol (&Qvalue_weak, "value-weak"); /* obsolete */ + defsymbol (&Qnon_weak, "non-weak"); /* obsolete */ + defkeyword (&Q_test, ":test"); - defkeyword (&Q_type, ":type"); + defkeyword (&Q_size, ":size"); defkeyword (&Q_rehash_size, ":rehash-size"); defkeyword (&Q_rehash_threshold, ":rehash-threshold"); + defkeyword (&Q_weakness, ":weakness"); + defkeyword (&Q_type, ":type"); /* obsolete */ } void @@ -1398,4 +1464,5 @@ vars_of_elhash (void) { /* This must NOT be staticpro'd */ Vall_weak_hash_tables = Qnil; + pdump_wire_list (&Vall_weak_hash_tables); } diff --git a/src/elhash.h b/src/elhash.h index 982a729..e780626 100644 --- a/src/elhash.h +++ b/src/elhash.h @@ -28,11 +28,10 @@ DECLARE_LRECORD (hash_table, struct Lisp_Hash_Table); #define XHASH_TABLE(x) XRECORD (x, hash_table, struct Lisp_Hash_Table) #define XSETHASH_TABLE(x, p) XSETRECORD (x, p, hash_table) #define HASH_TABLEP(x) RECORDP (x, hash_table) -#define GC_HASH_TABLEP(x) GC_RECORDP (x, hash_table) #define CHECK_HASH_TABLE(x) CHECK_RECORD (x, hash_table) #define CONCHECK_HASH_TABLE(x) CONCHECK_RECORD (x, hash_table) -enum hash_table_type +enum hash_table_weakness { HASH_TABLE_NON_WEAK, HASH_TABLE_KEY_WEAK, @@ -49,6 +48,8 @@ enum hash_table_test HASH_TABLE_EQUAL }; +extern const struct lrecord_description hash_table_description[]; + EXFUN (Fcopy_hash_table, 1); EXFUN (Fhash_table_count, 1); EXFUN (Fgethash, 3); @@ -62,15 +63,16 @@ typedef unsigned long (*hash_table_hash_function_t) (Lisp_Object obj); typedef int (*maphash_function_t) (Lisp_Object key, Lisp_Object value, void* extra_arg); +struct Lisp_Hash_Table; -Lisp_Object make_general_lisp_hash_table (size_t size, - enum hash_table_type type, - enum hash_table_test test, +Lisp_Object make_general_lisp_hash_table (enum hash_table_test test, + size_t size, + double rehash_size, double rehash_threshold, - double rehash_size); + enum hash_table_weakness weakness); Lisp_Object make_lisp_hash_table (size_t size, - enum hash_table_type type, + enum hash_table_weakness weakness, enum hash_table_test test); void elisp_maphash (maphash_function_t function, @@ -79,8 +81,9 @@ void elisp_maphash (maphash_function_t function, void elisp_map_remhash (maphash_function_t predicate, Lisp_Object hash_table, void *extra_arg); -int finish_marking_weak_hash_tables (int (*obj_marked_p) (Lisp_Object), - void (*markobj) (Lisp_Object)); -void prune_weak_hash_tables (int (*obj_marked_p) (Lisp_Object)); +int finish_marking_weak_hash_tables (void); +void prune_weak_hash_tables (void); + +void reorganize_hash_table (struct Lisp_Hash_Table *ht); #endif /* _XEMACS_ELHASH_H_ */ diff --git a/src/emacs.c b/src/emacs.c index a60922f..08bfa7e 100644 --- a/src/emacs.c +++ b/src/emacs.c @@ -151,7 +151,7 @@ Lisp_Object Vdata_directory, Vconfigure_data_directory; Lisp_Object Vdoc_directory, Vconfigure_doc_directory; Lisp_Object Vconfigure_lock_directory; Lisp_Object Vdata_directory_list; -Lisp_Object Vinfo_directory, Vconfigure_info_directory; +Lisp_Object Vconfigure_info_directory; Lisp_Object Vsite_directory, Vconfigure_site_directory; Lisp_Object Vconfigure_info_path; Lisp_Object Vinternal_error_checking; @@ -221,8 +221,8 @@ int inhibit_autoloads; int debug_paths; /* Save argv and argc. */ -char **initial_argv; -int initial_argc; +static char **initial_argv; +static int initial_argc; static void sort_args (int argc, char **argv); @@ -547,7 +547,8 @@ main_1 (int argc, char **argv, char **envp, int restart) extern int malloc_cookie; #endif -#if !defined(SYSTEM_MALLOC) && !defined(HAVE_LIBMCHECK) +#if (!defined (SYSTEM_MALLOC) && !defined (HAVE_LIBMCHECK) \ + && !defined (DOUG_LEA_MALLOC)) /* Make sure that any libraries we link against haven't installed a hook for a gmalloc of a potentially incompatible version. */ /* If we're using libmcheck, the hooks have already been initialized, */ @@ -555,7 +556,7 @@ main_1 (int argc, char **argv, char **envp, int restart) __malloc_hook = NULL; __realloc_hook = NULL; __free_hook = NULL; -#endif /* not SYSTEM_MALLOC */ +#endif /* not SYSTEM_MALLOC or HAVE_LIBMCHECK or DOUG_LEA_MALLOC */ noninteractive = 0; @@ -855,6 +856,10 @@ main_1 (int argc, char **argv, char **envp, int restart) We try to do things in an order that minimizes the non-obvious dependencies between functions. */ +#ifdef PDUMP + initialized = restart || pdump_load (); +#endif + if (!initialized) { /* Initialize things so that new Lisp objects @@ -1253,7 +1258,7 @@ main_1 (int argc, char **argv, char **envp, int restart) staticpro() Fprovide(symbol) intern() - pure_put() + Fput() xmalloc() defsymbol(), if it's absolutely necessary and you're sure that the symbol isn't referenced anywhere else in the initialization @@ -1266,7 +1271,6 @@ main_1 (int argc, char **argv, char **envp, int restart) Any of the object-creating functions on alloc.c: e.g. make_pure_*() - Fpurecopy() make_string() build_string() make_vector() @@ -1276,7 +1280,6 @@ main_1 (int argc, char **argv, char **envp, int restart) Fcons() listN() make_opaque_ptr() - make_opaque_long() perhaps a few others. */ @@ -1284,6 +1287,9 @@ main_1 (int argc, char **argv, char **envp, int restart) /* Now allow Fprovide() statements to be made. */ init_provide_once (); + /* Do that before any specifier creation (esp. vars_of_glyphs()) */ + vars_of_specifier (); + vars_of_abbrev (); vars_of_alloc (); #ifdef HAVE_X_WINDOWS @@ -1393,7 +1399,6 @@ main_1 (int argc, char **argv, char **envp, int restart) vars_of_search (); vars_of_select (); vars_of_sound (); - vars_of_specifier (); vars_of_symbols (); vars_of_syntax (); #ifdef HAVE_TOOLBARS @@ -1609,8 +1614,113 @@ main_1 (int argc, char **argv, char **envp, int restart) garbage_collect_1 (); } #endif +#ifdef PDUMP + } else if (!restart) { + reinit_alloc_once_early (); + reinit_opaque_once_early (); + + reinit_console_type_create_stream (); +#ifdef HAVE_TTY + reinit_console_type_create_tty (); +#endif +#ifdef HAVE_X_WINDOWS + reinit_console_type_create_x (); + reinit_console_type_create_device_x (); +#endif +#ifdef HAVE_MS_WINDOWS + reinit_console_type_create_mswindows (); +#endif + + reinit_specifier_type_create (); + reinit_specifier_type_create_image (); + reinit_specifier_type_create_gutter (); + reinit_specifier_type_create_objects (); +#ifdef HAVE_TOOLBARS + reinit_specifier_type_create_toolbar (); +#endif + + structure_type_create (); + + structure_type_create_chartab (); + structure_type_create_faces (); + structure_type_create_rangetab (); + structure_type_create_hash_table (); + + lstream_type_create (); +#ifdef FILE_CODING + lstream_type_create_file_coding (); +#endif +#if defined (HAVE_MS_WINDOWS) && !defined(HAVE_MSG_SELECT) + lstream_type_create_mswindows_selectable (); +#endif +#ifdef HAVE_UNIX_PROCESSES + process_type_create_unix (); +#endif +#ifdef HAVE_WIN32_PROCESSES + process_type_create_nt (); +#endif + + reinit_vars_of_buffer (); + reinit_vars_of_console (); +#ifdef DEBUG_XEMACS + reinit_vars_of_debug (); +#endif + reinit_vars_of_device (); + reinit_vars_of_eval (); +#ifdef HAVE_X_WINDOWS + reinit_vars_of_event_Xt (); +#endif +#if defined(HAVE_TTY) && (defined (DEBUG_TTY_EVENT_STREAM) || !defined (HAVE_X_WINDOWS)) + reinit_vars_of_event_tty (); +#endif +#ifdef HAVE_MS_WINDOWS + reinit_vars_of_event_mswindows (); +#endif + reinit_vars_of_event_stream (); + reinit_vars_of_events (); + reinit_vars_of_extents (); + reinit_vars_of_font_lock (); + reinit_vars_of_glyphs (); + reinit_vars_of_glyphs_widget (); + reinit_vars_of_insdel (); + reinit_vars_of_lread (); + reinit_vars_of_lstream (); + reinit_vars_of_minibuf (); + reinit_vars_of_module (); + reinit_vars_of_objects (); + reinit_vars_of_print (); + reinit_vars_of_redisplay (); + reinit_vars_of_search (); + reinit_vars_of_scrollbar_x (); + reinit_vars_of_undo (); + reinit_vars_of_window (); + +#ifdef HAVE_MS_WINDOWS + reinit_vars_of_frame_mswindows (); +#endif + +#ifdef HAVE_X_WINDOWS + reinit_vars_of_device_x (); +#ifdef HAVE_MENUBARS + reinit_vars_of_menubar_x (); +#endif + reinit_vars_of_xselect (); +#if defined (HAVE_MENUBARS) || defined (HAVE_SCROLLBARS) || defined (HAVE_DIALOGS) || defined (HAVE_TOOLBARS) + reinit_vars_of_gui_x (); +#endif +#endif + +#if defined(MULE) && defined(HAVE_WNN) + reinit_vars_of_mule_wnn (); +#endif + + reinit_complex_vars_of_buffer (); + reinit_complex_vars_of_console (); + reinit_complex_vars_of_minibuf (); +#endif } + /* CONGRATULATIONS!!! We have successfully initialized the Lisp engine. */ @@ -2200,9 +2310,13 @@ voodoo_free_hook (void *mem) { /* Disable all calls to free() when XEmacs is exiting and it doesn't */ /* matter. */ - __free_hook = voodoo_free_hook; -} + __free_hook = +#ifdef __GNUC__ /* prototype of __free_hook varies with glibc version */ + (__typeof__ (__free_hook)) #endif + voodoo_free_hook; +} +#endif /* GNU_MALLOC */ DEFUN ("kill-emacs", Fkill_emacs, 0, 1, "P", /* Exit the XEmacs job and kill it. Ask for confirmation, without argument. @@ -2256,13 +2370,17 @@ all of which are called before XEmacs is actually killed. UNGCPRO; - shut_down_emacs (0, ((STRINGP (arg)) ? arg : Qnil)); + shut_down_emacs (0, STRINGP (arg) ? arg : Qnil); #if defined(GNU_MALLOC) - __free_hook = voodoo_free_hook; + __free_hook = +#ifdef __GNUC__ /* prototype of __free_hook varies with glibc version */ + (__typeof__ (__free_hook)) +#endif + voodoo_free_hook; #endif - exit ((INTP (arg)) ? XINT (arg) : 0); + exit (INTP (arg) ? XINT (arg) : 0); /* NOTREACHED */ return Qnil; /* I'm sick of the compiler warning */ } @@ -2344,11 +2462,11 @@ shut_down_emacs (int sig, Lisp_Object stuff) /* Now try to determine the actual path to the executable, to try to make the backtrace-determination process as foolproof as possible. */ - if (GC_STRINGP (Vinvocation_name)) + if (STRINGP (Vinvocation_name)) name = (char *) XSTRING_DATA (Vinvocation_name); else name = "xemacs"; - if (GC_STRINGP (Vinvocation_directory)) + if (STRINGP (Vinvocation_directory)) dir = (char *) XSTRING_DATA (Vinvocation_directory); if (!dir || dir[0] != '/') stderr_out ("`which %s`", name); @@ -2512,6 +2630,11 @@ and announce itself normally when it is run. symname_ext = 0; garbage_collect_1 (); + +#ifdef PDUMP + pdump (); +#else + #ifdef DOUG_LEA_MALLOC malloc_state_ptr = malloc_get_state (); #endif @@ -2525,6 +2648,7 @@ and announce itself normally when it is run. #ifdef DOUG_LEA_MALLOC free (malloc_state_ptr); #endif +#endif /* not PDUMP */ } #endif /* not MSDOS and EMX */ @@ -2784,7 +2908,7 @@ Symbol indicating type of operating system you are using. DEFVAR_LISP ("system-configuration", &Vsystem_configuration /* String naming the configuration XEmacs was built for. */ ); - Vsystem_configuration = Fpurecopy (build_string (EMACS_CONFIGURATION)); + Vsystem_configuration = build_string (EMACS_CONFIGURATION); #ifndef EMACS_CONFIG_OPTIONS # define EMACS_CONFIG_OPTIONS "UNKNOWN" @@ -2792,8 +2916,7 @@ String naming the configuration XEmacs was built for. DEFVAR_LISP ("system-configuration-options", &Vsystem_configuration_options /* String containing the configuration options XEmacs was built with. */ ); - Vsystem_configuration_options = Fpurecopy (build_string - (EMACS_CONFIG_OPTIONS)); + Vsystem_configuration_options = build_string (EMACS_CONFIG_OPTIONS); DEFVAR_LISP ("emacs-major-version", &Vemacs_major_version /* Major version number of this version of Emacs, as an integer. @@ -2859,7 +2982,7 @@ Codename of this version of Emacs (a string). #ifndef XEMACS_CODENAME #define XEMACS_CODENAME "Noname" #endif - Vxemacs_codename = Fpurecopy (build_string (XEMACS_CODENAME)); + Vxemacs_codename = build_string (XEMACS_CODENAME); DEFVAR_BOOL ("noninteractive", &noninteractive1 /* Non-nil means XEmacs is running without interactive terminal. @@ -2933,7 +3056,6 @@ bufpos - check buffer positions. Vinternal_error_checking = Fcons (intern ("bufpos"), Vinternal_error_checking); #endif - Vinternal_error_checking = Fpurecopy (Vinternal_error_checking); DEFVAR_LISP ("path-separator", &Vpath_separator /* The directory separator in search paths, as a string. @@ -3160,7 +3282,7 @@ The configured initial path for info documentation. #endif } -#ifdef __sgi +#if defined(__sgi) && !defined(PDUMP) /* This is so tremendously ugly I'd puke. But then, it works. * The target is to override the static constructor from the * libiflPNG.so library which is maskerading as libz, and diff --git a/src/emodules.c b/src/emodules.c index b8f2e6e..3f33e0a 100644 --- a/src/emodules.c +++ b/src/emodules.c @@ -215,7 +215,7 @@ find_make_module (CONST char *mod, CONST char *name, CONST char *ver, int mof) if (modules == (emodules_list *)0) modules = (emodules_list *)xmalloc (sizeof(emodules_list)); modnum++; - modules = xrealloc (modules, modnum * sizeof(emodules_list)); + modules = (emodules_list *) xrealloc (modules, modnum * sizeof(emodules_list)); fs = modnum - 1; memset (&modules[fs], 0, sizeof(emodules_list)); @@ -526,8 +526,18 @@ syms_of_module (void) } void +reinit_vars_of_module (void) +{ + emodules_depth = 0; + modules = (emodules_list *)0; + modnum = 0; +} + +void vars_of_module (void) { + reinit_vars_of_module (); + DEFVAR_LISP ("module-version", &Vmodule_version /* Emacs dynamic loading mechanism version, as a string. @@ -537,7 +547,7 @@ This variable can be used to distinquish between different versions of the dynamic loading technology used in Emacs, if required. It is not a given that this value will be the same as the Emacs version number. */ ); - Vmodule_version = Fpurecopy (build_string (EMODULES_VERSION)); + Vmodule_version = build_string (EMODULES_VERSION); DEFVAR_BOOL ("load-modules-quietly", &load_modules_quietly /* *Set to t if module loading is to be silent. @@ -575,9 +585,6 @@ when a dynamic module is loaded. staticpro (&Vmodule_extensions); load_modules_quietly = 0; - emodules_depth = 0; - modules = (emodules_list *)0; - modnum = 0; Vmodule_load_path = Qnil; Fprovide (intern ("modules")); } diff --git a/src/eval.c b/src/eval.c index 22310ec..6ace437 100644 --- a/src/eval.c +++ b/src/eval.c @@ -73,7 +73,7 @@ struct backtrace *backtrace_list; a SUBR with more than 8 arguments, use max_args == MANY. See the DEFUN macro in lisp.h) */ #define PRIMITIVE_FUNCALL(rv, fn, av, ac) do { \ - void (*PF_fn)() = (void (*)()) (fn); \ + void (*PF_fn)(void) = (void (*)(void)) fn; \ Lisp_Object *PF_av = (av); \ switch (ac) \ { \ @@ -170,7 +170,7 @@ int specpdl_depth_counter; int max_specpdl_size; /* Depth in Lisp evaluations and function calls. */ -int lisp_eval_depth; +static int lisp_eval_depth; /* Maximum allowed depth in Lisp evaluations and function calls. */ int max_lisp_eval_depth; @@ -295,9 +295,15 @@ print_subr (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) write_c_string (trailer, printcharfun); } -DEFINE_LRECORD_IMPLEMENTATION ("subr", subr, - this_one_is_unmarkable, print_subr, 0, 0, 0, 0, - Lisp_Subr); +static const struct lrecord_description subr_description[] = { + { XD_DOC_STRING, offsetof(Lisp_Subr, doc) }, + { XD_END } +}; + +DEFINE_BASIC_LRECORD_IMPLEMENTATION ("subr", subr, + this_one_is_unmarkable, print_subr, 0, 0, 0, + subr_description, + Lisp_Subr); /************************************************************************/ /* Entering the debugger */ @@ -1004,8 +1010,6 @@ In byte compilation, `function' causes its argument to be compiled. static Lisp_Object define_function (Lisp_Object name, Lisp_Object defn) { - if (purify_flag) - defn = Fpurecopy (defn); Ffset (name, defn); LOADHIST_ATTACH (name); return name; @@ -1078,14 +1082,7 @@ In lisp-interaction-mode defvar is treated as defconst. if (!NILP (args = XCDR (args))) { Lisp_Object doc = XCAR (args); -#if 0 /* FSFmacs */ - /* #### We should probably do this but it might be dangerous */ - if (purify_flag) - doc = Fpurecopy (doc); Fput (sym, Qvariable_documentation, doc); -#else - pure_put (sym, Qvariable_documentation, doc); -#endif if (!NILP (args = XCDR (args))) error ("too many arguments"); } @@ -1093,7 +1090,7 @@ In lisp-interaction-mode defvar is treated as defconst. #ifdef I18N3 if (!NILP (Vfile_domain)) - pure_put (sym, Qvariable_domain, Vfile_domain); + Fput (sym, Qvariable_domain, Vfile_domain); #endif LOADHIST_ATTACH (sym); @@ -1133,21 +1130,14 @@ Since `defconst' unconditionally assigns the variable, if (!NILP (args = XCDR (args))) { Lisp_Object doc = XCAR (args); -#if 0 /* FSFmacs */ - /* #### We should probably do this but it might be dangerous */ - if (purify_flag) - doc = Fpurecopy (doc); Fput (sym, Qvariable_documentation, doc); -#else - pure_put (sym, Qvariable_documentation, doc); -#endif if (!NILP (args = XCDR (args))) error ("too many arguments"); } #ifdef I18N3 if (!NILP (Vfile_domain)) - pure_put (sym, Qvariable_domain, Vfile_domain); + Fput (sym, Qvariable_domain, Vfile_domain); #endif LOADHIST_ATTACH (sym); @@ -1167,7 +1157,7 @@ for the variable is `*'. return ((INTP (documentation) && XINT (documentation) < 0) || - ((STRINGP (documentation)) && + (STRINGP (documentation) && (string_byte (XSTRING (documentation), 0) == '*')) || /* If (STRING . INTEGER), a negative integer means a user variable. */ @@ -2633,7 +2623,7 @@ when reading the arguments. { Fsignal (Qwrong_type_argument, Fcons (Qcommandp, - ((EQ (cmd, final)) + (EQ (cmd, final) ? list1 (cmd) : list2 (cmd, final)))); return Qnil; @@ -2750,12 +2740,11 @@ this does nothing and returns nil. /* Attempt to avoid consing identical (string=) pure strings. */ file = Fsymbol_name (Fintern (file, Qnil)); } - - return Ffset (function, - Fpurecopy (Fcons (Qautoload, list4 (file, - docstring, - interactive, - type)))); + + return Ffset (function, Fcons (Qautoload, list4 (file, + docstring, + interactive, + type))); } Lisp_Object @@ -2955,7 +2944,7 @@ Evaluate FORM and return its value. if (max_args == UNEVALLED) /* Optimize for the common case */ { backtrace.evalargs = 0; - val = (((Lisp_Object (*) (Lisp_Object)) (subr_function (subr))) + val = (((Lisp_Object (*) (Lisp_Object)) subr_function (subr)) (original_args)); } else if (nargs <= max_args) @@ -3009,7 +2998,7 @@ Evaluate FORM and return its value. backtrace.args = args; backtrace.nargs = nargs; - val = (((Lisp_Object (*) (int, Lisp_Object *)) (subr_function (subr))) + val = (((Lisp_Object (*) (int, Lisp_Object *)) subr_function (subr)) (nargs, args)); UNGCPRO; @@ -3203,7 +3192,7 @@ Thus, (funcall 'cons 'x 'y) returns (x . y). } else if (max_args == MANY) { - val = ((Lisp_Object (*) (int, Lisp_Object *)) (subr_function (subr))) + val = ((Lisp_Object (*) (int, Lisp_Object *)) subr_function (subr)) (fun_nargs, fun_args); } else if (max_args == UNEVALLED) /* Can't funcall a special form */ @@ -3627,8 +3616,9 @@ run_hook_with_args_in_buffer (struct buffer *buf, int nargs, Lisp_Object *args, } else { - struct gcpro gcpro1, gcpro2; - GCPRO2 (sym, val); + struct gcpro gcpro1, gcpro2, gcpro3; + Lisp_Object globals = Qnil; + GCPRO3 (sym, val, globals); for (; CONSP (val) && ((cond == RUN_HOOKS_TO_COMPLETION) @@ -3640,7 +3630,7 @@ run_hook_with_args_in_buffer (struct buffer *buf, int nargs, Lisp_Object *args, { /* t indicates this hook has a local binding; it means to run the global binding too. */ - Lisp_Object globals = Fdefault_value (sym); + globals = Fdefault_value (sym); if ((! CONSP (globals) || EQ (XCAR (globals), Qlambda)) && ! NILP (globals)) @@ -4207,14 +4197,14 @@ eval_in_buffer_trapping_errors (CONST char *warning_string, /* gc_currently_forbidden = 1; Currently no reason to do this; */ cons = noseeum_cons (buffer, form); - opaque = (warning_string ? make_opaque_ptr (warning_string) : Qnil); + opaque = (warning_string ? make_opaque_ptr ((void *)warning_string) : Qnil); GCPRO2 (cons, opaque); /* Qerror not Qt, so you can get a backtrace */ tem = condition_case_1 (Qerror, catch_them_squirmers_eval_in_buffer, cons, caught_a_squirmer, opaque); free_cons (XCONS (cons)); - if (OPAQUEP (opaque)) + if (OPAQUE_PTRP (opaque)) free_opaque_ptr (opaque); UNGCPRO; @@ -4247,13 +4237,13 @@ run_hook_trapping_errors (CONST char *warning_string, Lisp_Object hook_symbol) speccount = specpdl_depth(); specbind (Qinhibit_quit, Qt); - opaque = (warning_string ? make_opaque_ptr (warning_string) : Qnil); + opaque = (warning_string ? make_opaque_ptr ((void *)warning_string) : Qnil); GCPRO1 (opaque); /* Qerror not Qt, so you can get a backtrace */ tem = condition_case_1 (Qerror, catch_them_squirmers_run_hook, hook_symbol, caught_a_squirmer, opaque); - if (OPAQUEP (opaque)) + if (OPAQUE_PTRP (opaque)) free_opaque_ptr (opaque); UNGCPRO; @@ -4283,7 +4273,7 @@ safe_run_hook_trapping_errors (CONST char *warning_string, specbind (Qinhibit_quit, Qt); cons = noseeum_cons (hook_symbol, - warning_string ? make_opaque_ptr (warning_string) + warning_string ? make_opaque_ptr ((void *)warning_string) : Qnil); GCPRO1 (cons); /* Qerror not Qt, so you can get a backtrace */ @@ -4294,7 +4284,7 @@ safe_run_hook_trapping_errors (CONST char *warning_string, allow_quit_safe_run_hook_caught_a_squirmer : safe_run_hook_caught_a_squirmer, cons); - if (OPAQUEP (XCDR (cons))) + if (OPAQUE_PTRP (XCDR (cons))) free_opaque_ptr (XCDR (cons)); free_cons (XCONS (cons)); UNGCPRO; @@ -4329,12 +4319,12 @@ call0_trapping_errors (CONST char *warning_string, Lisp_Object function) specbind (Qinhibit_quit, Qt); /* gc_currently_forbidden = 1; Currently no reason to do this; */ - opaque = (warning_string ? make_opaque_ptr (warning_string) : Qnil); + opaque = (warning_string ? make_opaque_ptr ((void *)warning_string) : Qnil); /* Qerror not Qt, so you can get a backtrace */ tem = condition_case_1 (Qerror, catch_them_squirmers_call0, function, caught_a_squirmer, opaque); - if (OPAQUEP (opaque)) + if (OPAQUE_PTRP (opaque)) free_opaque_ptr (opaque); UNGCPRO; @@ -4379,12 +4369,12 @@ call1_trapping_errors (CONST char *warning_string, Lisp_Object function, /* gc_currently_forbidden = 1; Currently no reason to do this; */ cons = noseeum_cons (function, object); - opaque = (warning_string ? make_opaque_ptr (warning_string) : Qnil); + opaque = (warning_string ? make_opaque_ptr ((void *)warning_string) : Qnil); /* Qerror not Qt, so you can get a backtrace */ tem = condition_case_1 (Qerror, catch_them_squirmers_call1, cons, caught_a_squirmer, opaque); - if (OPAQUEP (opaque)) + if (OPAQUE_PTRP (opaque)) free_opaque_ptr (opaque); free_cons (XCONS (cons)); UNGCPRO; @@ -4415,12 +4405,12 @@ call2_trapping_errors (CONST char *warning_string, Lisp_Object function, /* gc_currently_forbidden = 1; Currently no reason to do this; */ cons = list3 (function, object1, object2); - opaque = (warning_string ? make_opaque_ptr (warning_string) : Qnil); + opaque = (warning_string ? make_opaque_ptr ((void *)warning_string) : Qnil); /* Qerror not Qt, so you can get a backtrace */ tem = condition_case_1 (Qerror, catch_them_squirmers_call2, cons, caught_a_squirmer, opaque); - if (OPAQUEP (opaque)) + if (OPAQUE_PTRP (opaque)) free_opaque_ptr (opaque); free_list (cons); UNGCPRO; @@ -5053,8 +5043,28 @@ reinit_eval (void) } void +reinit_vars_of_eval (void) +{ + preparing_for_armageddon = 0; + in_warnings = 0; + Qunbound_suspended_errors_tag = make_opaque_ptr (&Qunbound_suspended_errors_tag); + staticpro_nodump (&Qunbound_suspended_errors_tag); + + specpdl_size = 50; + specpdl = xnew_array (struct specbinding, specpdl_size); + /* XEmacs change: increase these values. */ + max_specpdl_size = 3000; + max_lisp_eval_depth = 500; +#if 0 /* no longer used */ + throw_level = 0; +#endif +} + +void vars_of_eval (void) { + reinit_vars_of_eval (); + DEFVAR_INT ("max-specpdl-size", &max_specpdl_size /* Limit on number of Lisp variable bindings & unwind-protects before error. */ ); @@ -5156,13 +5166,10 @@ If due to `eval' entry, one arg, t. */ ); Vdebugger = Qnil; - preparing_for_armageddon = 0; - staticpro (&Vpending_warnings); Vpending_warnings = Qnil; - Vpending_warnings_tail = Qnil; /* no need to protect this */ - - in_warnings = 0; + pdump_wire (&Vpending_warnings_tail); + Vpending_warnings_tail = Qnil; staticpro (&Vautoload_queue); Vautoload_queue = Qnil; @@ -5175,18 +5182,5 @@ If due to `eval' entry, one arg, t. staticpro (&Vcurrent_error_state); Vcurrent_error_state = Qnil; /* errors as normal */ - Qunbound_suspended_errors_tag = make_opaque_long (0); - staticpro (&Qunbound_suspended_errors_tag); - - specpdl_size = 50; - specpdl_depth_counter = 0; - specpdl = xnew_array (struct specbinding, specpdl_size); - /* XEmacs change: increase these values. */ - max_specpdl_size = 3000; - max_lisp_eval_depth = 500; -#if 0 /* no longer used */ - throw_level = 0; -#endif - reinit_eval (); } diff --git a/src/event-Xt.c b/src/event-Xt.c index 38b1781..3417197 100644 --- a/src/event-Xt.c +++ b/src/event-Xt.c @@ -1569,8 +1569,13 @@ emacs_Xt_handle_magic_event (struct Lisp_Event *emacs_event) break; case Expose: - x_redraw_exposed_area (f, event->xexpose.x, event->xexpose.y, - event->xexpose.width, event->xexpose.height); + if (!check_for_ignored_expose (f, event->xexpose.x, event->xexpose.y, + event->xexpose.width, event->xexpose.height) + && + !find_matching_subwindow (f, event->xexpose.x, event->xexpose.y, + event->xexpose.width, event->xexpose.height)) + x_redraw_exposed_area (f, event->xexpose.x, event->xexpose.y, + event->xexpose.width, event->xexpose.height); break; case GraphicsExpose: /* This occurs when an XCopyArea's source area was @@ -1663,14 +1668,14 @@ static int timeout_id_tick; /* Xt interval id's might not fit into an int (they're pointers, as it happens), so we need to provide a conversion list. */ -struct Xt_timeout +static struct Xt_timeout { int id; XtIntervalId interval_id; struct Xt_timeout *next; } *pending_timeouts, *completed_timeouts; -struct Xt_timeout_blocktype +static struct Xt_timeout_blocktype { Blocktype_declare (struct Xt_timeout); } *the_Xt_timeout_blocktype; @@ -2918,15 +2923,8 @@ syms_of_event_Xt (void) } void -vars_of_event_Xt (void) +reinit_vars_of_event_Xt (void) { - dispatch_event_queue = Qnil; - staticpro (&dispatch_event_queue); - dispatch_event_queue_tail = Qnil; - - /* this function only makes safe calls */ - init_what_input_once (); - Xt_event_stream = xnew (struct event_stream); Xt_event_stream->event_pending_p = emacs_Xt_event_pending_p; Xt_event_stream->next_event_cb = emacs_Xt_next_event; @@ -2941,6 +2939,24 @@ vars_of_event_Xt (void) Xt_event_stream->create_stream_pair_cb = emacs_Xt_create_stream_pair; Xt_event_stream->delete_stream_pair_cb = emacs_Xt_delete_stream_pair; + the_Xt_timeout_blocktype = Blocktype_new (struct Xt_timeout_blocktype); + + last_quit_check_signal_tick_count = 0; + + /* this function only makes safe calls */ + init_what_input_once (); +} + +void +vars_of_event_Xt (void) +{ + reinit_vars_of_event_Xt (); + + dispatch_event_queue = Qnil; + staticpro (&dispatch_event_queue); + dispatch_event_queue_tail = Qnil; + pdump_wire (&dispatch_event_queue_tail); + DEFVAR_BOOL ("modifier-keys-are-sticky", &modifier_keys_are_sticky /* *Non-nil makes modifier keys sticky. This means that you can release the modifier key before pressing down @@ -2966,10 +2982,6 @@ Information is displayed on stderr. Currently defined values are: */ ); x_debug_events = 0; #endif - - the_Xt_timeout_blocktype = Blocktype_new (struct Xt_timeout_blocktype); - - last_quit_check_signal_tick_count = 0; } /* This mess is a hack that patches the shell widget to treat visual inheritance diff --git a/src/event-msw.c b/src/event-msw.c index 45e77ee..0dee130 100644 --- a/src/event-msw.c +++ b/src/event-msw.c @@ -98,7 +98,8 @@ mswindows_handle_gui_wm_command (struct frame* f, HWND ctrl, WORD id); static Lisp_Object mswindows_find_frame (HWND hwnd); static Lisp_Object mswindows_find_console (HWND hwnd); -static Lisp_Object mswindows_key_to_emacs_keysym(int mswindows_key, int mods); +static Lisp_Object mswindows_key_to_emacs_keysym (int mswindows_key, int mods, + int extendedp); static int mswindows_modifier_state (BYTE* keymap, int has_AltGr); static void mswindows_set_chord_timer (HWND hwnd); static int mswindows_button2_near_enough (POINTS p1, POINTS p2); @@ -144,6 +145,7 @@ int mswindows_quit_chars_count = 0; /* These are Lisp integers; see DEFVARS in this file for description. */ int mswindows_dynamic_frame_resize; +int mswindows_meta_activates_menu; int mswindows_num_mouse_buttons; int mswindows_mouse_button_max_skew_x; int mswindows_mouse_button_max_skew_y; @@ -1659,15 +1661,17 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) BYTE keymap[256]; int has_AltGr = mswindows_current_layout_has_AltGr (); int mods; + int extendedp = lParam & 0x1000000; Lisp_Object keysym; GetKeyboardState (keymap); mods = mswindows_modifier_state (keymap, has_AltGr); - /* Handle those keys for which TranslateMessage won't generate a WM_CHAR */ - if (!NILP (keysym = mswindows_key_to_emacs_keysym(wParam, mods))) + /* Handle non-printables */ + if (!NILP (keysym = mswindows_key_to_emacs_keysym (wParam, mods, + extendedp))) mswindows_enqueue_keypress_event (hwnd, keysym, mods); - else + else /* Normal keys & modifiers */ { int quit_ch = CONSOLE_QUIT_CHAR (XCONSOLE (mswindows_find_console (hwnd))); BYTE keymap_orig[256]; @@ -1685,9 +1689,9 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) * to loosely track Left and Right modifiers on behalf of the OS, * without screwing up Windows NT which tracks them properly. */ if (wParam == VK_CONTROL) - keymap [(lParam & 0x1000000) ? VK_RCONTROL : VK_LCONTROL] |= 0x80; + keymap [extendedp ? VK_RCONTROL : VK_LCONTROL] |= 0x80; else if (wParam == VK_MENU) - keymap [(lParam & 0x1000000) ? VK_RMENU : VK_LMENU] |= 0x80; + keymap [extendedp ? VK_RMENU : VK_LMENU] |= 0x80; memcpy (keymap_orig, keymap, 256); @@ -1734,7 +1738,7 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) } /* else */ } /* F10 causes menu activation by default. We do not want this */ - if (wParam != VK_F10) + if (wParam != VK_F10 && (mswindows_meta_activates_menu || wParam != VK_MENU)) goto defproc; break; @@ -1982,15 +1986,35 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) case WM_PAINT: { - PAINTSTRUCT paintStruct; - - frame = XFRAME (mswindows_find_frame (hwnd)); + /* According to the docs we need to check GetUpdateRect() before + actually doing a WM_PAINT */ + if (GetUpdateRect (hwnd, NULL, FALSE)) + { + PAINTSTRUCT paintStruct; + int x, y, width, height; + + frame = XFRAME (mswindows_find_frame (hwnd)); + + BeginPaint (hwnd, &paintStruct); + x = paintStruct.rcPaint.left; + y = paintStruct.rcPaint.top; + width = paintStruct.rcPaint.right - paintStruct.rcPaint.left; + height = paintStruct.rcPaint.bottom - paintStruct.rcPaint.top; + /* Normally we want to ignore expose events when child + windows are unmapped, however once we are in the guts of + WM_PAINT we need to make sure that we don't register + unmaps then because they will not actually occur. */ + if (!check_for_ignored_expose (frame, x, y, width, height)) + { + hold_ignored_expose_registration = 1; + mswindows_redraw_exposed_area (frame, x, y, width, height); + hold_ignored_expose_registration = 0; + } - BeginPaint (hwnd, &paintStruct); - mswindows_redraw_exposed_area (frame, - paintStruct.rcPaint.left, paintStruct.rcPaint.top, - paintStruct.rcPaint.right, paintStruct.rcPaint.bottom); - EndPaint (hwnd, &paintStruct); + EndPaint (hwnd, &paintStruct); + } + else + goto defproc; } break; @@ -2142,6 +2166,23 @@ mswindows_wnd_proc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam) UNGCPRO; break; } + + case WM_MOUSEWHEEL: + { + int keys = LOWORD (wParam); /* Modifier key flags */ + int delta = (short) HIWORD (wParam); /* Wheel rotation amount */ + struct gcpro gcpro1, gcpro2; + + if (mswindows_handle_mousewheel_event (mswindows_find_frame (hwnd), keys, delta)) + { + GCPRO2 (emacs_event, fobj); + mswindows_pump_outstanding_events (); /* Can GC */ + UNGCPRO; + } + else + goto defproc; + break; + } #endif #ifdef HAVE_MENUBARS @@ -2417,67 +2458,100 @@ int mswindows_modifier_state (BYTE* keymap, int has_AltGr) * Only returns non-Qnil for keys that don't generate WM_CHAR messages * or whose ASCII codes (like space) xemacs doesn't like. * Virtual key values are defined in winresrc.h - * XXX I'm not sure that KEYSYM("name") is the best thing to use here. */ -Lisp_Object mswindows_key_to_emacs_keysym(int mswindows_key, int mods) +Lisp_Object mswindows_key_to_emacs_keysym (int mswindows_key, int mods, + int extendedp) { - switch (mswindows_key) - { - /* First the predefined ones */ - case VK_BACK: return QKbackspace; - case VK_TAB: return QKtab; - case '\n': return QKlinefeed; /* No VK_LINEFEED in winresrc.h */ - case VK_RETURN: return QKreturn; - case VK_ESCAPE: return QKescape; - case VK_SPACE: return QKspace; - case VK_DELETE: return QKdelete; - - /* The rest */ - case VK_CLEAR: return KEYSYM ("clear"); /* Should do ^L ? */ - case VK_PRIOR: return KEYSYM ("prior"); - case VK_NEXT: return KEYSYM ("next"); - case VK_END: return KEYSYM ("end"); - case VK_HOME: return KEYSYM ("home"); - case VK_LEFT: return KEYSYM ("left"); - case VK_UP: return KEYSYM ("up"); - case VK_RIGHT: return KEYSYM ("right"); - case VK_DOWN: return KEYSYM ("down"); - case VK_SELECT: return KEYSYM ("select"); - case VK_PRINT: return KEYSYM ("print"); - case VK_EXECUTE: return KEYSYM ("execute"); - case VK_SNAPSHOT: return KEYSYM ("print"); - case VK_INSERT: return KEYSYM ("insert"); - case VK_HELP: return KEYSYM ("help"); -#if 0 /* XXX What are these supposed to do? */ - case VK_LWIN return KEYSYM (""); - case VK_RWIN return KEYSYM (""); + if (extendedp) /* Keys not present on a 82 key keyboard */ + { + switch (mswindows_key) + { + case VK_RETURN: return KEYSYM ("kp-enter"); + case VK_PRIOR: return KEYSYM ("prior"); + case VK_NEXT: return KEYSYM ("next"); + case VK_END: return KEYSYM ("end"); + case VK_HOME: return KEYSYM ("home"); + case VK_LEFT: return KEYSYM ("left"); + case VK_UP: return KEYSYM ("up"); + case VK_RIGHT: return KEYSYM ("right"); + case VK_DOWN: return KEYSYM ("down"); + case VK_INSERT: return KEYSYM ("insert"); + case VK_DELETE: return QKdelete; + } + } + else + { + switch (mswindows_key) + { + case VK_BACK: return QKbackspace; + case VK_TAB: return QKtab; + case '\n': return QKlinefeed; + case VK_CLEAR: return KEYSYM ("clear"); + case VK_RETURN: return QKreturn; + case VK_ESCAPE: return QKescape; + case VK_SPACE: return QKspace; + case VK_PRIOR: return KEYSYM ("kp-prior"); + case VK_NEXT: return KEYSYM ("kp-next"); + case VK_END: return KEYSYM ("kp-end"); + case VK_HOME: return KEYSYM ("kp-home"); + case VK_LEFT: return KEYSYM ("kp-left"); + case VK_UP: return KEYSYM ("kp-up"); + case VK_RIGHT: return KEYSYM ("kp-right"); + case VK_DOWN: return KEYSYM ("kp-down"); + case VK_SELECT: return KEYSYM ("select"); + case VK_PRINT: return KEYSYM ("print"); + case VK_EXECUTE: return KEYSYM ("execute"); + case VK_SNAPSHOT: return KEYSYM ("print"); + case VK_INSERT: return KEYSYM ("kp-insert"); + case VK_DELETE: return KEYSYM ("kp-delete"); + case VK_HELP: return KEYSYM ("help"); +#if 0 /* FSF Emacs allows these to return configurable syms/mods */ + case VK_LWIN return KEYSYM (""); + case VK_RWIN return KEYSYM (""); #endif - case VK_APPS: return KEYSYM ("menu"); - case VK_F1: return KEYSYM ("f1"); - case VK_F2: return KEYSYM ("f2"); - case VK_F3: return KEYSYM ("f3"); - case VK_F4: return KEYSYM ("f4"); - case VK_F5: return KEYSYM ("f5"); - case VK_F6: return KEYSYM ("f6"); - case VK_F7: return KEYSYM ("f7"); - case VK_F8: return KEYSYM ("f8"); - case VK_F9: return KEYSYM ("f9"); - case VK_F10: return KEYSYM ("f10"); - case VK_F11: return KEYSYM ("f11"); - case VK_F12: return KEYSYM ("f12"); - case VK_F13: return KEYSYM ("f13"); - case VK_F14: return KEYSYM ("f14"); - case VK_F15: return KEYSYM ("f15"); - case VK_F16: return KEYSYM ("f16"); - case VK_F17: return KEYSYM ("f17"); - case VK_F18: return KEYSYM ("f18"); - case VK_F19: return KEYSYM ("f19"); - case VK_F20: return KEYSYM ("f20"); - case VK_F21: return KEYSYM ("f21"); - case VK_F22: return KEYSYM ("f22"); - case VK_F23: return KEYSYM ("f23"); - case VK_F24: return KEYSYM ("f24"); - } + case VK_APPS: return KEYSYM ("menu"); + case VK_NUMPAD0: return KEYSYM ("kp-0"); + case VK_NUMPAD1: return KEYSYM ("kp-1"); + case VK_NUMPAD2: return KEYSYM ("kp-2"); + case VK_NUMPAD3: return KEYSYM ("kp-3"); + case VK_NUMPAD4: return KEYSYM ("kp-4"); + case VK_NUMPAD5: return KEYSYM ("kp-5"); + case VK_NUMPAD6: return KEYSYM ("kp-6"); + case VK_NUMPAD7: return KEYSYM ("kp-7"); + case VK_NUMPAD8: return KEYSYM ("kp-8"); + case VK_NUMPAD9: return KEYSYM ("kp-9"); + case VK_MULTIPLY: return KEYSYM ("kp-multiply"); + case VK_ADD: return KEYSYM ("kp-add"); + case VK_SEPARATOR: return KEYSYM ("kp-separator"); + case VK_SUBTRACT: return KEYSYM ("kp-subtract"); + case VK_DECIMAL: return KEYSYM ("kp-decimal"); + case VK_DIVIDE: return KEYSYM ("kp-divide"); + case VK_F1: return KEYSYM ("f1"); + case VK_F2: return KEYSYM ("f2"); + case VK_F3: return KEYSYM ("f3"); + case VK_F4: return KEYSYM ("f4"); + case VK_F5: return KEYSYM ("f5"); + case VK_F6: return KEYSYM ("f6"); + case VK_F7: return KEYSYM ("f7"); + case VK_F8: return KEYSYM ("f8"); + case VK_F9: return KEYSYM ("f9"); + case VK_F10: return KEYSYM ("f10"); + case VK_F11: return KEYSYM ("f11"); + case VK_F12: return KEYSYM ("f12"); + case VK_F13: return KEYSYM ("f13"); + case VK_F14: return KEYSYM ("f14"); + case VK_F15: return KEYSYM ("f15"); + case VK_F16: return KEYSYM ("f16"); + case VK_F17: return KEYSYM ("f17"); + case VK_F18: return KEYSYM ("f18"); + case VK_F19: return KEYSYM ("f19"); + case VK_F20: return KEYSYM ("f20"); + case VK_F21: return KEYSYM ("f21"); + case VK_F22: return KEYSYM ("f22"); + case VK_F23: return KEYSYM ("f23"); + case VK_F24: return KEYSYM ("f24"); + } + } return Qnil; } @@ -2877,20 +2951,10 @@ debug_process_finalization (struct Lisp_Process *p) /************************************************************************/ /* initialization */ /************************************************************************/ - + void -vars_of_event_mswindows (void) +reinit_vars_of_event_mswindows (void) { - mswindows_u_dispatch_event_queue = Qnil; - staticpro (&mswindows_u_dispatch_event_queue); - mswindows_u_dispatch_event_queue_tail = Qnil; - - mswindows_s_dispatch_event_queue = Qnil; - staticpro (&mswindows_s_dispatch_event_queue); - mswindows_s_dispatch_event_queue_tail = Qnil; - - mswindows_error_caught_in_modal_loop = Qnil; - staticpro (&mswindows_error_caught_in_modal_loop); mswindows_in_modal_loop = 0; mswindows_pending_timers_count = 0; @@ -2917,6 +2981,31 @@ vars_of_event_mswindows (void) mswindows_event_stream->create_stream_pair_cb = emacs_mswindows_create_stream_pair; mswindows_event_stream->delete_stream_pair_cb = emacs_mswindows_delete_stream_pair; #endif +} + +void +vars_of_event_mswindows (void) +{ + reinit_vars_of_event_mswindows (); + + mswindows_u_dispatch_event_queue = Qnil; + staticpro (&mswindows_u_dispatch_event_queue); + mswindows_u_dispatch_event_queue_tail = Qnil; + pdump_wire (&mswindows_u_dispatch_event_queue_tail); + + mswindows_s_dispatch_event_queue = Qnil; + staticpro (&mswindows_s_dispatch_event_queue); + mswindows_s_dispatch_event_queue_tail = Qnil; + pdump_wire (&mswindows_u_dispatch_event_queue_tail); + + mswindows_error_caught_in_modal_loop = Qnil; + staticpro (&mswindows_error_caught_in_modal_loop); + + DEFVAR_BOOL ("mswindows-meta-activates-menu", &mswindows_meta_activates_menu /* +*Controls whether pressing and releasing the Meta (Alt) key should +activate the menubar. +Default is t. +*/ ); DEFVAR_BOOL ("mswindows-dynamic-frame-resize", &mswindows_dynamic_frame_resize /* *Controls redrawing frame contents during mouse-drag or keyboard resize @@ -2962,6 +3051,7 @@ If negative or zero, currently set system default is used instead. mswindows_mouse_button_max_skew_x = 0; mswindows_mouse_button_max_skew_y = 0; mswindows_mouse_button_tolerance = 0; + mswindows_meta_activates_menu = 1; } void diff --git a/src/event-stream.c b/src/event-stream.c index f008935..b9fefe2 100644 --- a/src/event-stream.c +++ b/src/event-stream.c @@ -81,7 +81,6 @@ Boston, MA 02111-1307, USA. */ #include "keymap.h" #include "lstream.h" #include "macros.h" /* for defining_keyboard_macro */ -#include "opaque.h" #include "process.h" #include "window.h" @@ -102,8 +101,6 @@ static int auto_save_interval; Lisp_Object Qundefined_keystroke_sequence; -Lisp_Object Qcommand_execute; - Lisp_Object Qcommand_event_p; /* Hooks to run before and after each command. */ @@ -389,15 +386,15 @@ static Lisp_Object recursive_sit_for; #define CHECK_COMMAND_BUILDER(x) CHECK_RECORD (x, command_builder) static Lisp_Object -mark_command_builder (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_command_builder (Lisp_Object obj) { struct command_builder *builder = XCOMMAND_BUILDER (obj); - markobj (builder->prefix_events); - markobj (builder->current_events); - markobj (builder->most_current_event); - markobj (builder->last_non_munged_event); - markobj (builder->munge_me[0].first_mungeable_event); - markobj (builder->munge_me[1].first_mungeable_event); + mark_object (builder->prefix_events); + mark_object (builder->current_events); + mark_object (builder->most_current_event); + mark_object (builder->last_non_munged_event); + mark_object (builder->munge_me[0].first_mungeable_event); + mark_object (builder->munge_me[1].first_mungeable_event); return builder->console; } @@ -985,7 +982,7 @@ Actually, the value is nil only if we can be sure that no input is available. used to indicate an absence of a timer. */ static int low_level_timeout_id_tick; -struct low_level_timeout_blocktype +static struct low_level_timeout_blocktype { Blocktype_declare (struct low_level_timeout); } *the_low_level_timeout_blocktype; @@ -1101,38 +1098,39 @@ pop_low_level_timeout (struct low_level_timeout **timeout_list, static int timeout_id_tick; -/* Since timeout structures contain Lisp_Objects, they need to be GC'd - properly. The opaque data type provides a convenient way of doing - this without having to create a new Lisp object, since we can - provide our own mark function. */ - -struct timeout -{ - int id; /* Id we use to identify the timeout over its lifetime */ - int interval_id; /* Id for this particular interval; this may - be different each time the timeout is - signalled.*/ - Lisp_Object function, object; /* Function and object associated - with timeout. */ - EMACS_TIME next_signal_time; /* Absolute time when the timeout - is next going to be signalled. */ - unsigned int resignal_msecs; /* How far after the next timeout - should the one after that - occur? */ -}; - static Lisp_Object pending_timeout_list, pending_async_timeout_list; static Lisp_Object Vtimeout_free_list; static Lisp_Object -mark_timeout (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_timeout (Lisp_Object obj) { - struct timeout *tm = (struct timeout *) XOPAQUE_DATA (obj); - markobj (tm->function); + struct Lisp_Timeout *tm = XTIMEOUT (obj); + mark_object (tm->function); return tm->object; } +/* Should never, ever be called. (except by an external debugger) */ +static void +print_timeout (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) +{ + CONST struct Lisp_Timeout *t = XTIMEOUT (obj); + char buf[64]; + + sprintf (buf, "#", + (unsigned long) t); + write_c_string (buf, printcharfun); +} + +static const struct lrecord_description timeout_description[] = { + { XD_LISP_OBJECT, offsetof(struct Lisp_Timeout, function), 2 }, + { XD_END } +}; + +DEFINE_LRECORD_IMPLEMENTATION ("timeout", timeout, + mark_timeout, print_timeout, + 0, 0, 0, timeout_description, struct Lisp_Timeout); + /* Generate a timeout and return its ID. */ int @@ -1141,8 +1139,8 @@ event_stream_generate_wakeup (unsigned int milliseconds, Lisp_Object function, Lisp_Object object, int async_p) { - Lisp_Object op = allocate_managed_opaque (Vtimeout_free_list, 0); - struct timeout *timeout = (struct timeout *) XOPAQUE_DATA (op); + Lisp_Object op = allocate_managed_lcrecord (Vtimeout_free_list); + struct Lisp_Timeout *timeout = XTIMEOUT (op); EMACS_TIME current_time; EMACS_TIME interval; @@ -1191,7 +1189,7 @@ event_stream_resignal_wakeup (int interval_id, int async_p, Lisp_Object *function, Lisp_Object *object) { Lisp_Object op = Qnil, rest; - struct timeout *timeout; + struct Lisp_Timeout *timeout; Lisp_Object *timeout_list; struct gcpro gcpro1; int id; @@ -1204,16 +1202,16 @@ event_stream_resignal_wakeup (int interval_id, int async_p, /* Find the timeout on the list of pending ones. */ LIST_LOOP (rest, *timeout_list) { - timeout = (struct timeout *) XOPAQUE_DATA (XCAR (rest)); + timeout = XTIMEOUT (XCAR (rest)); if (timeout->interval_id == interval_id) break; } assert (!NILP (rest)); op = XCAR (rest); - timeout = (struct timeout *) XOPAQUE_DATA (op); + timeout = XTIMEOUT (op); /* We make sure to snarf the data out of the timeout object before - we free it with free_managed_opaque(). */ + we free it with free_managed_lcrecord(). */ id = timeout->id; *function = timeout->function; *object = timeout->object; @@ -1255,7 +1253,7 @@ event_stream_resignal_wakeup (int interval_id, int async_p, *timeout_list = noseeum_cons (op, *timeout_list); } else - free_managed_opaque (Vtimeout_free_list, op); + free_managed_lcrecord (Vtimeout_free_list, op); UNGCPRO; return id; @@ -1264,7 +1262,7 @@ event_stream_resignal_wakeup (int interval_id, int async_p, void event_stream_disable_wakeup (int id, int async_p) { - struct timeout *timeout = 0; + struct Lisp_Timeout *timeout = 0; Lisp_Object rest; Lisp_Object *timeout_list; @@ -1276,7 +1274,7 @@ event_stream_disable_wakeup (int id, int async_p) /* Find the timeout on the list of pending ones, if it's still there. */ LIST_LOOP (rest, *timeout_list) { - timeout = (struct timeout *) XOPAQUE_DATA (XCAR (rest)); + timeout = XTIMEOUT (XCAR (rest)); if (timeout->id == id) break; } @@ -1292,14 +1290,14 @@ event_stream_disable_wakeup (int id, int async_p) event_stream_remove_async_timeout (timeout->interval_id); else event_stream_remove_timeout (timeout->interval_id); - free_managed_opaque (Vtimeout_free_list, op); + free_managed_lcrecord (Vtimeout_free_list, op); } } static int event_stream_wakeup_pending_p (int id, int async_p) { - struct timeout *timeout; + struct Lisp_Timeout *timeout; Lisp_Object rest; Lisp_Object timeout_list; int found = 0; @@ -1313,7 +1311,7 @@ event_stream_wakeup_pending_p (int id, int async_p) /* Find the element on the list of pending ones, if it's still there. */ LIST_LOOP (rest, timeout_list) { - timeout = (struct timeout *) XOPAQUE_DATA (XCAR (rest)); + timeout = XTIMEOUT (XCAR (rest)); if (timeout->id == id) { found = 1; @@ -4909,7 +4907,6 @@ syms_of_event_stream (void) deferror (&Qundefined_keystroke_sequence, "undefined-keystroke-sequence", "Undefined keystroke sequence", Qerror); - defsymbol (&Qcommand_execute, "command-execute"); DEFSUBR (Frecent_keys); DEFSUBR (Frecent_keys_ring_size); @@ -4966,22 +4963,36 @@ syms_of_event_stream (void) } void -vars_of_event_stream (void) +reinit_vars_of_event_stream (void) { recent_keys_ring_index = 0; recent_keys_ring_size = 100; + num_input_chars = 0; + Vtimeout_free_list = make_lcrecord_list (sizeof (struct Lisp_Timeout), + &lrecord_timeout); + staticpro_nodump (&Vtimeout_free_list); + the_low_level_timeout_blocktype = + Blocktype_new (struct low_level_timeout_blocktype); + something_happened = 0; + recursive_sit_for = Qnil; +} + +void +vars_of_event_stream (void) +{ + reinit_vars_of_event_stream (); Vrecent_keys_ring = Qnil; staticpro (&Vrecent_keys_ring); Vthis_command_keys = Qnil; staticpro (&Vthis_command_keys); Vthis_command_keys_tail = Qnil; - - num_input_chars = 0; + pdump_wire (&Vthis_command_keys_tail); command_event_queue = Qnil; staticpro (&command_event_queue); command_event_queue_tail = Qnil; + pdump_wire (&command_event_queue_tail); Vlast_selected_frame = Qnil; staticpro (&Vlast_selected_frame); @@ -4992,20 +5003,9 @@ vars_of_event_stream (void) pending_async_timeout_list = Qnil; staticpro (&pending_async_timeout_list); - Vtimeout_free_list = make_opaque_list (sizeof (struct timeout), - mark_timeout); - staticpro (&Vtimeout_free_list); - - the_low_level_timeout_blocktype = - Blocktype_new (struct low_level_timeout_blocktype); - - something_happened = 0; - last_point_position_buffer = Qnil; staticpro (&last_point_position_buffer); - recursive_sit_for = Qnil; - DEFVAR_LISP ("echo-keystrokes", &Vecho_keystrokes /* *Nonzero means echo unfinished commands after this many seconds of pause. */ ); diff --git a/src/event-tty.c b/src/event-tty.c index 0e44cf4..0437604 100644 --- a/src/event-tty.c +++ b/src/event-tty.c @@ -245,7 +245,7 @@ emacs_tty_delete_stream_pair (Lisp_Object instream, Lisp_Object outstream) /************************************************************************/ void -vars_of_event_tty (void) +reinit_vars_of_event_tty (void) { tty_event_stream = xnew (struct event_stream); @@ -264,6 +264,12 @@ vars_of_event_tty (void) } void +vars_of_event_tty (void) +{ + reinit_vars_of_event_tty (); +} + +void init_event_tty_late (void) { event_stream = tty_event_stream; diff --git a/src/events.c b/src/events.c index 1a2db77..8f465d3 100644 --- a/src/events.c +++ b/src/events.c @@ -103,29 +103,29 @@ zero_event (struct Lisp_Event *e) } static Lisp_Object -mark_event (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_event (Lisp_Object obj) { struct Lisp_Event *event = XEVENT (obj); switch (event->event_type) { case key_press_event: - markobj (event->event.key.keysym); + mark_object (event->event.key.keysym); break; case process_event: - markobj (event->event.process.process); + mark_object (event->event.process.process); break; case timeout_event: - markobj (event->event.timeout.function); - markobj (event->event.timeout.object); + mark_object (event->event.timeout.function); + mark_object (event->event.timeout.object); break; case eval_event: case misc_user_event: - markobj (event->event.eval.function); - markobj (event->event.eval.object); + mark_object (event->event.eval.function); + mark_object (event->event.eval.object); break; case magic_eval_event: - markobj (event->event.magic_eval.object); + mark_object (event->event.magic_eval.object); break; case button_press_event: case button_release_event: @@ -137,7 +137,7 @@ mark_event (Lisp_Object obj, void (*markobj) (Lisp_Object)) default: abort (); } - markobj (event->channel); + mark_object (event->channel); return event->next; } @@ -2229,11 +2229,28 @@ syms_of_events (void) defsymbol (&Qbutton_release, "button-release"); defsymbol (&Qmisc_user, "misc-user"); defsymbol (&Qascii_character, "ascii-character"); + + defsymbol (&QKbackspace, "backspace"); + defsymbol (&QKtab, "tab"); + defsymbol (&QKlinefeed, "linefeed"); + defsymbol (&QKreturn, "return"); + defsymbol (&QKescape, "escape"); + defsymbol (&QKspace, "space"); + defsymbol (&QKdelete, "delete"); +} + + +void +reinit_vars_of_events (void) +{ + Vevent_resource = Qnil; } void vars_of_events (void) { + reinit_vars_of_events (); + DEFVAR_LISP ("character-set-property", &Vcharacter_set_property /* A symbol used to look up the 8-bit character of a keysym. To convert a keysym symbol to an 8-bit code, as when that key is @@ -2243,22 +2260,4 @@ system-specific code will set up appropriate properties and set this variable. */ ); Vcharacter_set_property = Qnil; - - Vevent_resource = Qnil; - - QKbackspace = KEYSYM ("backspace"); - QKtab = KEYSYM ("tab"); - QKlinefeed = KEYSYM ("linefeed"); - QKreturn = KEYSYM ("return"); - QKescape = KEYSYM ("escape"); - QKspace = KEYSYM ("space"); - QKdelete = KEYSYM ("delete"); - - staticpro (&QKbackspace); - staticpro (&QKtab); - staticpro (&QKlinefeed); - staticpro (&QKreturn); - staticpro (&QKescape); - staticpro (&QKspace); - staticpro (&QKdelete); } diff --git a/src/events.h b/src/events.h index 04e7cd4..adc0b0c 100644 --- a/src/events.h +++ b/src/events.h @@ -435,6 +435,29 @@ union magic_data #endif }; +struct Lisp_Timeout +{ + struct lcrecord_header header; + int id; /* Id we use to identify the timeout over its lifetime */ + int interval_id; /* Id for this particular interval; this may + be different each time the timeout is + signalled.*/ + Lisp_Object function, object; /* Function and object associated + with timeout. */ + EMACS_TIME next_signal_time; /* Absolute time when the timeout + is next going to be signalled. */ + unsigned int resignal_msecs; /* How far after the next timeout + should the one after that + occur? */ +}; + +DECLARE_LRECORD (timeout, struct Lisp_Timeout); +#define XTIMEOUT(x) XRECORD (x, timeout, struct Lisp_Timeout) +#define XSETTIMEOUT(x, p) XSETRECORD (x, p, timeout) +#define TIMEOUTP(x) RECORDP (x, timeout) +#define CHECK_TIMEOUT(x) CHECK_RECORD (x, timeout) +#define CONCHECK_TIMEOUT(x) CONCHECK_RECORD (x, timeout) + struct Lisp_Event { /* header->next (aka XEVENT_NEXT ()) is used as follows: @@ -466,7 +489,6 @@ DECLARE_LRECORD (event, struct Lisp_Event); #define XEVENT(x) XRECORD (x, event, struct Lisp_Event) #define XSETEVENT(x, p) XSETRECORD (x, p, event) #define EVENTP(x) RECORDP (x, event) -#define GC_EVENTP(x) GC_RECORDP (x, event) #define CHECK_EVENT(x) CHECK_RECORD (x, event) #define CONCHECK_EVENT(x) CONCHECK_RECORD (x, event) diff --git a/src/extents.c b/src/extents.c index e11eded..d0ef995 100644 --- a/src/extents.c +++ b/src/extents.c @@ -260,7 +260,7 @@ typedef struct gap_array Gap_Array_Marker *markers; } Gap_Array; -Gap_Array_Marker *gap_array_marker_freelist; +static Gap_Array_Marker *gap_array_marker_freelist; /* Convert a "memory position" (i.e. taking the gap into account) into the address of the element at (i.e. after) that position. "Memory @@ -301,7 +301,7 @@ typedef struct extent_list Extent_List_Marker *markers; } Extent_List; -Extent_List_Marker *extent_list_marker_freelist; +static Extent_List_Marker *extent_list_marker_freelist; #define EXTENT_LESS_VALS(e,st,nd) ((extent_start (e) < (st)) || \ ((extent_start (e) == (st)) && \ @@ -444,9 +444,6 @@ Lisp_Object Qinside_margin; Lisp_Object Qwhitespace; /* Qtext defined in general.c */ -/* partially used in redisplay */ -Lisp_Object Qglyph_invisible; - Lisp_Object Qcopy_function; Lisp_Object Qpaste_function; @@ -910,18 +907,18 @@ free_extent_list (Extent_List *el) /************************************************************************/ static Lisp_Object -mark_extent_auxiliary (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_extent_auxiliary (Lisp_Object obj) { struct extent_auxiliary *data = XEXTENT_AUXILIARY (obj); - markobj (data->begin_glyph); - markobj (data->end_glyph); - markobj (data->invisible); - markobj (data->children); - markobj (data->read_only); - markobj (data->mouse_face); - markobj (data->initial_redisplay_function); - markobj (data->before_change_functions); - markobj (data->after_change_functions); + mark_object (data->begin_glyph); + mark_object (data->end_glyph); + mark_object (data->invisible); + mark_object (data->children); + mark_object (data->read_only); + mark_object (data->mouse_face); + mark_object (data->initial_redisplay_function); + mark_object (data->before_change_functions); + mark_object (data->after_change_functions); return data->parent; } @@ -973,7 +970,7 @@ static void free_soe (struct stack_of_extents *soe); static void soe_invalidate (Lisp_Object obj); static Lisp_Object -mark_extent_info (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_extent_info (Lisp_Object obj) { struct extent_info *data = (struct extent_info *) XEXTENT_INFO (obj); int i; @@ -996,7 +993,7 @@ mark_extent_info (Lisp_Object obj, void (*markobj) (Lisp_Object)) Lisp_Object exobj; XSETEXTENT (exobj, extent); - markobj (exobj); + mark_object (exobj); } } @@ -2913,7 +2910,7 @@ extent_fragment_update (struct window *w, struct extent_fragment *ef, extent objects. They are similar to the functions for other lrecord objects. allocate_extent() is in alloc.c, not here. */ -static Lisp_Object mark_extent (Lisp_Object, void (*) (Lisp_Object)); +static Lisp_Object mark_extent (Lisp_Object); static int extent_equal (Lisp_Object, Lisp_Object, int depth); static unsigned long extent_hash (Lisp_Object obj, int depth); static void print_extent (Lisp_Object obj, Lisp_Object printcharfun, @@ -2945,12 +2942,12 @@ DEFINE_BASIC_LRECORD_IMPLEMENTATION_WITH_PROPS ("extent", extent, struct extent); static Lisp_Object -mark_extent (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_extent (Lisp_Object obj) { struct extent *extent = XEXTENT (obj); - markobj (extent_object (extent)); - markobj (extent_no_chase_normal_field (extent, face)); + mark_object (extent_object (extent)); + mark_object (extent_no_chase_normal_field (extent, face)); return extent->plist; } @@ -2969,11 +2966,9 @@ print_extent_1 (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) if (extent_detached_p (ext)) strcpy (bp, "detached"); else - { - Bufpos from = XINT (Fextent_start_position (obj)); - Bufpos to = XINT (Fextent_end_position (obj)); - sprintf (bp, "%d, %d", from, to); - } + sprintf (bp, "%ld, %ld", + (long) XINT (Fextent_start_position (obj)), + (long) XINT (Fextent_end_position (obj))); bp += strlen (bp); *bp++ = (extent_end_open_p (anc) ? ')': ']'); if (!NILP (extent_end_glyph (anc))) *bp++ = '*'; @@ -3184,7 +3179,7 @@ extent_remprop (Lisp_Object obj, Lisp_Object prop) return -1; } - return external_remprop (&ext->plist, prop, 0, ERROR_ME); + return external_remprop (extent_plist_addr (ext), prop, 0, ERROR_ME); } static Lisp_Object @@ -6722,8 +6717,6 @@ syms_of_extents (void) defsymbol (&Qwhitespace, "whitespace"); /* Qtext defined in general.c */ - defsymbol (&Qglyph_invisible, "glyph-invisible"); - defsymbol (&Qpaste_function, "paste-function"); defsymbol (&Qcopy_function, "copy-function"); @@ -6800,8 +6793,26 @@ syms_of_extents (void) } void +reinit_vars_of_extents (void) +{ + extent_auxiliary_defaults.begin_glyph = Qnil; + extent_auxiliary_defaults.end_glyph = Qnil; + extent_auxiliary_defaults.parent = Qnil; + extent_auxiliary_defaults.children = Qnil; + extent_auxiliary_defaults.priority = 0; + extent_auxiliary_defaults.invisible = Qnil; + extent_auxiliary_defaults.read_only = Qnil; + extent_auxiliary_defaults.mouse_face = Qnil; + extent_auxiliary_defaults.initial_redisplay_function = Qnil; + extent_auxiliary_defaults.before_change_functions = Qnil; + extent_auxiliary_defaults.after_change_functions = Qnil; +} + +void vars_of_extents (void) { + reinit_vars_of_extents (); + DEFVAR_INT ("mouse-highlight-priority", &mouse_highlight_priority /* The priority to use for the mouse-highlighting pseudo-extent that is used to highlight extents with the `mouse-face' attribute set. @@ -6828,18 +6839,6 @@ functions `get-text-property' or `get-char-property' are called. Vextent_face_reusable_list = Fcons (Qnil, Qnil); staticpro (&Vextent_face_reusable_list); - - extent_auxiliary_defaults.begin_glyph = Qnil; - extent_auxiliary_defaults.end_glyph = Qnil; - extent_auxiliary_defaults.parent = Qnil; - extent_auxiliary_defaults.children = Qnil; - extent_auxiliary_defaults.priority = 0; - extent_auxiliary_defaults.invisible = Qnil; - extent_auxiliary_defaults.read_only = Qnil; - extent_auxiliary_defaults.mouse_face = Qnil; - extent_auxiliary_defaults.initial_redisplay_function = Qnil; - extent_auxiliary_defaults.before_change_functions = Qnil; - extent_auxiliary_defaults.after_change_functions = Qnil; } void diff --git a/src/extents.h b/src/extents.h index 457031e..390c3e0 100644 --- a/src/extents.h +++ b/src/extents.h @@ -27,7 +27,6 @@ DECLARE_LRECORD (extent, struct extent); #define XEXTENT(x) XRECORD (x, extent, struct extent) #define XSETEXTENT(x, p) XSETRECORD (x, p, extent) #define EXTENTP(x) RECORDP (x, extent) -#define GC_EXTENTP(x) GC_RECORDP (x, extent) #define CHECK_EXTENT(x) CHECK_RECORD (x, extent) #define CONCHECK_EXTENT(x) CONCHECK_RECORD (x, extent) @@ -147,7 +146,6 @@ DECLARE_LRECORD (extent_auxiliary, struct extent_auxiliary); XRECORD (x, extent_auxiliary, struct extent_auxiliary) #define XSETEXTENT_AUXILIARY(x, p) XSETRECORD (x, p, extent_auxiliary) #define EXTENT_AUXILIARYP(x) RECORDP (x, extent_auxiliary) -#define GC_EXTENT_AUXILIARYP(x) GC_RECORDP (x, extent_auxiliary) #define CHECK_EXTENT_AUXILIARY(x) CHECK_RECORD (x, extent_auxiliary) #define CONCHECK_EXTENT_AUXILIARY(x) CONCHECK_RECORD (x, extent_auxiliary) @@ -163,7 +161,6 @@ DECLARE_LRECORD (extent_info, struct extent_info); #define XEXTENT_INFO(x) XRECORD (x, extent_info, struct extent_info) #define XSETEXTENT_INFO(x, p) XSETRECORD (x, p, extent_info) #define EXTENT_INFOP(x) RECORDP (x, extent_info) -#define GC_EXTENT_INFOP(x) GC_RECORDP (x, extent_info) #define CHECK_EXTENT_INFO(x) CHECK_RECORD (x, extent_info) #define CONCHECK_EXTENT_INFO(x) CONCHECK_RECORD (x, extent_info) diff --git a/src/faces.c b/src/faces.c index 732c018..0c678f2 100644 --- a/src/faces.c +++ b/src/faces.c @@ -73,26 +73,26 @@ Lisp_Object Vbuilt_in_face_specifiers; static Lisp_Object -mark_face (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_face (Lisp_Object obj) { struct Lisp_Face *face = XFACE (obj); - markobj (face->name); - markobj (face->doc_string); + mark_object (face->name); + mark_object (face->doc_string); - markobj (face->foreground); - markobj (face->background); - markobj (face->font); - markobj (face->display_table); - markobj (face->background_pixmap); - markobj (face->underline); - markobj (face->strikethru); - markobj (face->highlight); - markobj (face->dim); - markobj (face->blinking); - markobj (face->reverse); + mark_object (face->foreground); + mark_object (face->background); + mark_object (face->font); + mark_object (face->display_table); + mark_object (face->background_pixmap); + mark_object (face->underline); + mark_object (face->strikethru); + mark_object (face->highlight); + mark_object (face->dim); + mark_object (face->blinking); + mark_object (face->reverse); - markobj (face->charsets_warned_about); + mark_object (face->charsets_warned_about); return face->plist; } @@ -171,18 +171,18 @@ face_getprop (Lisp_Object obj, Lisp_Object prop) struct Lisp_Face *f = XFACE (obj); return - ((EQ (prop, Qforeground)) ? f->foreground : - (EQ (prop, Qbackground)) ? f->background : - (EQ (prop, Qfont)) ? f->font : - (EQ (prop, Qdisplay_table)) ? f->display_table : - (EQ (prop, Qbackground_pixmap)) ? f->background_pixmap : - (EQ (prop, Qunderline)) ? f->underline : - (EQ (prop, Qstrikethru)) ? f->strikethru : - (EQ (prop, Qhighlight)) ? f->highlight : - (EQ (prop, Qdim)) ? f->dim : - (EQ (prop, Qblinking)) ? f->blinking : - (EQ (prop, Qreverse)) ? f->reverse : - (EQ (prop, Qdoc_string)) ? f->doc_string : + (EQ (prop, Qforeground) ? f->foreground : + EQ (prop, Qbackground) ? f->background : + EQ (prop, Qfont) ? f->font : + EQ (prop, Qdisplay_table) ? f->display_table : + EQ (prop, Qbackground_pixmap) ? f->background_pixmap : + EQ (prop, Qunderline) ? f->underline : + EQ (prop, Qstrikethru) ? f->strikethru : + EQ (prop, Qhighlight) ? f->highlight : + EQ (prop, Qdim) ? f->dim : + EQ (prop, Qblinking) ? f->blinking : + EQ (prop, Qreverse) ? f->reverse : + EQ (prop, Qdoc_string) ? f->doc_string : external_plist_get (&f->plist, prop, 0, ERROR_ME)); } @@ -264,9 +264,15 @@ face_plist (Lisp_Object obj) return result; } +static const struct lrecord_description face_description[] = { + { XD_LISP_OBJECT, offsetof(struct Lisp_Face, name), 2 }, + { XD_LISP_OBJECT, offsetof(struct Lisp_Face, foreground), 13 }, + { XD_END } +}; + DEFINE_LRECORD_IMPLEMENTATION_WITH_PROPS ("face", face, mark_face, print_face, 0, face_equal, - face_hash, 0, face_getprop, + face_hash, face_description, face_getprop, face_putprop, face_remprop, face_plist, struct Lisp_Face); @@ -981,8 +987,7 @@ Here's an approach that should keep things clean and unconfused: /* mark for GC a dynarr of face cachels. */ void -mark_face_cachels (face_cachel_dynarr *elements, - void (*markobj) (Lisp_Object)) +mark_face_cachels (face_cachel_dynarr *elements) { int elt; @@ -998,13 +1003,13 @@ mark_face_cachels (face_cachel_dynarr *elements, for (i = 0; i < NUM_LEADING_BYTES; i++) if (!NILP (cachel->font[i]) && !UNBOUNDP (cachel->font[i])) - markobj (cachel->font[i]); + mark_object (cachel->font[i]); } - markobj (cachel->face); - markobj (cachel->foreground); - markobj (cachel->background); - markobj (cachel->display_table); - markobj (cachel->background_pixmap); + mark_object (cachel->face); + mark_object (cachel->foreground); + mark_object (cachel->background); + mark_object (cachel->display_table); + mark_object (cachel->background_pixmap); } } diff --git a/src/faces.h b/src/faces.h index 697b2f8..d452731 100644 --- a/src/faces.h +++ b/src/faces.h @@ -226,7 +226,6 @@ DECLARE_LRECORD (face, struct Lisp_Face); #define XFACE(x) XRECORD (x, face, struct Lisp_Face) #define XSETFACE(x, p) XSETRECORD (x, p, face) #define FACEP(x) RECORDP (x, face) -#define GC_FACEP(x) GC_RECORDP (x, face) #define CHECK_FACE(x) CHECK_RECORD (x, face) Lisp_Object ensure_face_cachel_contains_charset (struct face_cachel *cachel, @@ -241,8 +240,7 @@ void update_face_cachel_data (struct face_cachel *cachel, void face_cachel_charset_font_metric_info (struct face_cachel *cachel, unsigned char *charsets, struct font_metric_info *fm); -void mark_face_cachels (face_cachel_dynarr *elements, - void (*markobj) (Lisp_Object)); +void mark_face_cachels (face_cachel_dynarr *elements); void mark_face_cachels_as_clean (struct window *w); void mark_face_cachels_as_not_updated (struct window *w); void reset_face_cachel (struct face_cachel *inst); diff --git a/src/file-coding.c b/src/file-coding.c index 9d3afe7..c6e9ae0 100644 --- a/src/file-coding.c +++ b/src/file-coding.c @@ -36,7 +36,7 @@ Boston, MA 02111-1307, USA. */ #endif #include "file-coding.h" -Lisp_Object Qbuffer_file_coding_system, Qcoding_system_error; +Lisp_Object Qcoding_system_error; Lisp_Object Vkeyboard_coding_system; Lisp_Object Vterminal_coding_system; @@ -47,14 +47,33 @@ Lisp_Object Vfile_name_coding_system; /* Table of symbols identifying each coding category. */ Lisp_Object coding_category_symbol[CODING_CATEGORY_LAST + 1]; -/* Coding system currently associated with each coding category. */ -Lisp_Object coding_category_system[CODING_CATEGORY_LAST + 1]; -/* Table of all coding categories in decreasing order of priority. - This describes a permutation of the possible coding categories. */ -int coding_category_by_priority[CODING_CATEGORY_LAST + 1]; -Lisp_Object Qcoding_system_p; +struct file_coding_dump { + /* Coding system currently associated with each coding category. */ + Lisp_Object coding_category_system[CODING_CATEGORY_LAST + 1]; + + /* Table of all coding categories in decreasing order of priority. + This describes a permutation of the possible coding categories. */ + int coding_category_by_priority[CODING_CATEGORY_LAST + 1]; + + Lisp_Object ucs_to_mule_table[65536]; +} *fcd; + +static const struct lrecord_description fcd_description_1[] = { + { XD_LISP_OBJECT, offsetof(struct file_coding_dump, coding_category_system), CODING_CATEGORY_LAST + 1 }, + { XD_LISP_OBJECT, offsetof(struct file_coding_dump, ucs_to_mule_table), 65536 }, + { XD_END } +}; + +static const struct struct_description fcd_description = { + sizeof(struct file_coding_dump), + fcd_description_1 +}; + +Lisp_Object mule_to_ucs_table; + +Lisp_Object Qcoding_systemp; Lisp_Object Qraw_text, Qno_conversion, Qccl, Qiso2022; /* Qinternal in general.c */ @@ -227,6 +246,26 @@ typedef struct Dynarr_declare (codesys_prop); } codesys_prop_dynarr; +static const struct lrecord_description codesys_prop_description_1[] = { + { XD_LISP_OBJECT, offsetof(codesys_prop, sym), 1 }, + { XD_END } +}; + +static const struct struct_description codesys_prop_description = { + sizeof(codesys_prop), + codesys_prop_description_1 +}; + +static const struct lrecord_description codesys_prop_dynarr_description_1[] = { + XD_DYNARR_DESC(codesys_prop_dynarr, &codesys_prop_description), + { XD_END } +}; + +static const struct struct_description codesys_prop_dynarr_description = { + sizeof(codesys_prop_dynarr), + codesys_prop_dynarr_description_1 +}; + codesys_prop_dynarr *the_codesys_prop_dynarr; enum codesys_prop_enum @@ -241,7 +280,7 @@ enum codesys_prop_enum /* Coding system functions */ /************************************************************************/ -static Lisp_Object mark_coding_system (Lisp_Object, void (*) (Lisp_Object)); +static Lisp_Object mark_coding_system (Lisp_Object); static void print_coding_system (Lisp_Object, Lisp_Object, int); static void finalize_coding_system (void *header, int for_disksave); @@ -287,16 +326,16 @@ DEFINE_LRECORD_IMPLEMENTATION ("coding-system", coding_system, struct Lisp_Coding_System); static Lisp_Object -mark_coding_system (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_coding_system (Lisp_Object obj) { Lisp_Coding_System *codesys = XCODING_SYSTEM (obj); - markobj (CODING_SYSTEM_NAME (codesys)); - markobj (CODING_SYSTEM_DOC_STRING (codesys)); - markobj (CODING_SYSTEM_MNEMONIC (codesys)); - markobj (CODING_SYSTEM_EOL_LF (codesys)); - markobj (CODING_SYSTEM_EOL_CRLF (codesys)); - markobj (CODING_SYSTEM_EOL_CR (codesys)); + mark_object (CODING_SYSTEM_NAME (codesys)); + mark_object (CODING_SYSTEM_DOC_STRING (codesys)); + mark_object (CODING_SYSTEM_MNEMONIC (codesys)); + mark_object (CODING_SYSTEM_EOL_LF (codesys)); + mark_object (CODING_SYSTEM_EOL_CRLF (codesys)); + mark_object (CODING_SYSTEM_EOL_CR (codesys)); switch (CODING_SYSTEM_TYPE (codesys)) { @@ -304,15 +343,15 @@ mark_coding_system (Lisp_Object obj, void (*markobj) (Lisp_Object)) int i; case CODESYS_ISO2022: for (i = 0; i < 4; i++) - markobj (CODING_SYSTEM_ISO2022_INITIAL_CHARSET (codesys, i)); + mark_object (CODING_SYSTEM_ISO2022_INITIAL_CHARSET (codesys, i)); if (codesys->iso2022.input_conv) { for (i = 0; i < Dynarr_length (codesys->iso2022.input_conv); i++) { struct charset_conversion_spec *ccs = Dynarr_atp (codesys->iso2022.input_conv, i); - markobj (ccs->from_charset); - markobj (ccs->to_charset); + mark_object (ccs->from_charset); + mark_object (ccs->to_charset); } } if (codesys->iso2022.output_conv) @@ -321,22 +360,22 @@ mark_coding_system (Lisp_Object obj, void (*markobj) (Lisp_Object)) { struct charset_conversion_spec *ccs = Dynarr_atp (codesys->iso2022.output_conv, i); - markobj (ccs->from_charset); - markobj (ccs->to_charset); + mark_object (ccs->from_charset); + mark_object (ccs->to_charset); } } break; case CODESYS_CCL: - markobj (CODING_SYSTEM_CCL_DECODE (codesys)); - markobj (CODING_SYSTEM_CCL_ENCODE (codesys)); + mark_object (CODING_SYSTEM_CCL_DECODE (codesys)); + mark_object (CODING_SYSTEM_CCL_ENCODE (codesys)); break; #endif /* MULE */ default: break; } - markobj (CODING_SYSTEM_PRE_WRITE_CONVERSION (codesys)); + mark_object (CODING_SYSTEM_PRE_WRITE_CONVERSION (codesys)); return CODING_SYSTEM_POST_READ_CONVERSION (codesys); } @@ -1301,7 +1340,7 @@ previously. order. */ for (j = 0; j <= CODING_CATEGORY_LAST; j++) { - int cat = coding_category_by_priority[j]; + int cat = fcd->coding_category_by_priority[j]; if (category_to_priority[cat] < 0) category_to_priority[cat] = i++; } @@ -1310,7 +1349,7 @@ previously. constructed. */ for (i = 0; i <= CODING_CATEGORY_LAST; i++) - coding_category_by_priority[category_to_priority[i]] = i; + fcd->coding_category_by_priority[category_to_priority[i]] = i; /* Phew! That was confusing. */ return Qnil; @@ -1325,7 +1364,7 @@ Return a list of coding categories in descending order of priority. Lisp_Object list = Qnil; for (i = CODING_CATEGORY_LAST; i >= 0; i--) - list = Fcons (coding_category_symbol[coding_category_by_priority[i]], + list = Fcons (coding_category_symbol[fcd->coding_category_by_priority[i]], list); return list; } @@ -1338,7 +1377,7 @@ Change the coding system associated with a coding category. int cat = decode_coding_category (coding_category); coding_system = Fget_coding_system (coding_system); - coding_category_system[cat] = coding_system; + fcd->coding_category_system[cat] = coding_system; return Qnil; } @@ -1348,7 +1387,7 @@ Return the coding system associated with a coding category. (coding_category)) { int cat = decode_coding_category (coding_category); - Lisp_Object sys = coding_category_system[cat]; + Lisp_Object sys = fcd->coding_category_system[cat]; if (!NILP (sys)) return XCODING_SYSTEM_NAME (sys); @@ -1582,13 +1621,13 @@ coding_system_from_mask (int mask) the first one that is allowed. */ for (i = 0; i <= CODING_CATEGORY_LAST; i++) { - cat = coding_category_by_priority[i]; + cat = fcd->coding_category_by_priority[i]; if ((mask & (1 << cat)) && - !NILP (coding_category_system[cat])) + !NILP (fcd->coding_category_system[cat])) break; } if (cat >= 0) - return coding_category_system[cat]; + return fcd->coding_category_system[cat]; else return Fget_coding_system (Qraw_text); } @@ -1654,7 +1693,7 @@ determine_real_coding_system (Lstream *stream, Lisp_Object *codesys_in_out, } *np = 0; coding_system - = Ffind_coding_system (intern (coding_system_name)); + = Ffind_coding_system (intern ((char *) coding_system_name)); break; } } @@ -1736,10 +1775,10 @@ type. Optional arg BUFFER defaults to the current buffer. #endif for (i = CODING_CATEGORY_LAST; i >= 0; i--) { - int sys = coding_category_by_priority[i]; + int sys = fcd->coding_category_by_priority[i]; if (decst.mask & (1 << sys)) { - Lisp_Object codesys = coding_category_system[sys]; + Lisp_Object codesys = fcd->coding_category_system[sys]; if (!NILP (codesys)) codesys = subsidiary_coding_system (codesys, decst.eol_type); val = Fcons (codesys, val); @@ -1889,14 +1928,13 @@ static int decoding_seekable_p (Lstream *stream); static int decoding_flusher (Lstream *stream); static int decoding_closer (Lstream *stream); -static Lisp_Object decoding_marker (Lisp_Object stream, - void (*markobj) (Lisp_Object)); +static Lisp_Object decoding_marker (Lisp_Object stream); DEFINE_LSTREAM_IMPLEMENTATION ("decoding", lstream_decoding, sizeof (struct decoding_stream)); static Lisp_Object -decoding_marker (Lisp_Object stream, void (*markobj) (Lisp_Object)) +decoding_marker (Lisp_Object stream) { Lstream *str = DECODING_STREAM_DATA (XLSTREAM (stream))->other_end; Lisp_Object str_obj; @@ -1906,9 +1944,9 @@ decoding_marker (Lisp_Object stream, void (*markobj) (Lisp_Object)) and automatically marked. */ XSETLSTREAM (str_obj, str); - markobj (str_obj); + mark_object (str_obj); if (str->imp->marker) - return (str->imp->marker) (str_obj, markobj); + return (str->imp->marker) (str_obj); else return Qnil; } @@ -2345,14 +2383,13 @@ static int encoding_seekable_p (Lstream *stream); static int encoding_flusher (Lstream *stream); static int encoding_closer (Lstream *stream); -static Lisp_Object encoding_marker (Lisp_Object stream, - void (*markobj) (Lisp_Object)); +static Lisp_Object encoding_marker (Lisp_Object stream); DEFINE_LSTREAM_IMPLEMENTATION ("encoding", lstream_encoding, sizeof (struct encoding_stream)); static Lisp_Object -encoding_marker (Lisp_Object stream, void (*markobj) (Lisp_Object)) +encoding_marker (Lisp_Object stream) { Lstream *str = ENCODING_STREAM_DATA (XLSTREAM (stream))->other_end; Lisp_Object str_obj; @@ -2362,9 +2399,9 @@ encoding_marker (Lisp_Object stream, void (*markobj) (Lisp_Object)) and automatically marked. */ XSETLSTREAM (str_obj, str); - markobj (str_obj); + mark_object (str_obj); if (str->imp->marker) - return (str->imp->marker) (str_obj, markobj); + return (str->imp->marker) (str_obj); else return Qnil; } @@ -3203,8 +3240,6 @@ Return the corresponding character code in Big5. /* */ /************************************************************************/ -Lisp_Object ucs_to_mule_table[65536]; -Lisp_Object mule_to_ucs_table; DEFUN ("set-ucs-char", Fset_ucs_char, 2, 2, 0, /* Map UCS-4 code CODE to Mule character CHARACTER. @@ -3219,9 +3254,9 @@ Return T on success, NIL on failure. CHECK_INT (code); c = XINT (code); - if (c < sizeof (ucs_to_mule_table)) + if (c < sizeof (fcd->ucs_to_mule_table)) { - ucs_to_mule_table[c] = character; + fcd->ucs_to_mule_table[c] = character; return Qt; } else @@ -3231,9 +3266,9 @@ Return T on success, NIL on failure. static Lisp_Object ucs_to_char (unsigned long code) { - if (code < sizeof (ucs_to_mule_table)) + if (code < sizeof (fcd->ucs_to_mule_table)) { - return ucs_to_mule_table[code]; + return fcd->ucs_to_mule_table[code]; } else if ((0xe00000 <= code) && (code <= 0xe00000 + 94 * 94 * 14)) { @@ -5491,7 +5526,6 @@ convert_from_external_format (CONST Extbyte *ptr, void syms_of_file_coding (void) { - defsymbol (&Qbuffer_file_coding_system, "buffer-file-coding-system"); deferror (&Qcoding_system_error, "coding-system-error", "Coding-system error", Qio_error); @@ -5531,7 +5565,7 @@ syms_of_file_coding (void) DEFSUBR (Fset_char_ucs); DEFSUBR (Fchar_ucs); #endif /* MULE */ - defsymbol (&Qcoding_system_p, "coding-system-p"); + defsymbol (&Qcoding_systemp, "coding-system-p"); defsymbol (&Qno_conversion, "no-conversion"); defsymbol (&Qraw_text, "raw-text"); #ifdef MULE @@ -5626,11 +5660,14 @@ vars_of_file_coding (void) { int i; + fcd = xnew (struct file_coding_dump); + dumpstruct (&fcd, &fcd_description); + /* Initialize to something reasonable ... */ for (i = 0; i <= CODING_CATEGORY_LAST; i++) { - coding_category_system[i] = Qnil; - coding_category_by_priority[i] = i; + fcd->coding_category_system[i] = Qnil; + fcd->coding_category_by_priority[i] = i; } Fprovide (intern ("file-coding")); @@ -5691,6 +5728,7 @@ complex_vars_of_file_coding (void) make_lisp_hash_table (50, HASH_TABLE_NON_WEAK, HASH_TABLE_EQ); the_codesys_prop_dynarr = Dynarr_new (codesys_prop); + dumpstruct (&the_codesys_prop_dynarr, &codesys_prop_dynarr_description); #define DEFINE_CODESYS_PROP(Prop_Type, Sym) do \ { \ @@ -5744,7 +5782,7 @@ complex_vars_of_file_coding (void) Fdefine_coding_system_alias (Qno_conversion, Qraw_text); /* Need this for bootstrapping */ - coding_category_system[CODING_CATEGORY_NO_CONVERSION] = + fcd->coding_category_system[CODING_CATEGORY_NO_CONVERSION] = Fget_coding_system (Qraw_text); #ifdef MULE @@ -5752,7 +5790,7 @@ complex_vars_of_file_coding (void) unsigned int i; for (i = 0; i < 65536; i++) - ucs_to_mule_table[i] = Qnil; + fcd->ucs_to_mule_table[i] = Qnil; } staticpro (&mule_to_ucs_table); mule_to_ucs_table = Fmake_char_table(Qgeneric); diff --git a/src/file-coding.h b/src/file-coding.h index 19fc60e..023bf57 100644 --- a/src/file-coding.h +++ b/src/file-coding.h @@ -140,7 +140,6 @@ DECLARE_LRECORD (coding_system, struct Lisp_Coding_System); #define XCODING_SYSTEM(x) XRECORD (x, coding_system, struct Lisp_Coding_System) #define XSETCODING_SYSTEM(x, p) XSETRECORD (x, p, coding_system) #define CODING_SYSTEMP(x) RECORDP (x, coding_system) -#define GC_CODING_SYSTEMP(x) GC_RECORDP (x, coding_system) #define CHECK_CODING_SYSTEM(x) CHECK_RECORD (x, coding_system) #define CONCHECK_CODING_SYSTEM(x) CONCHECK_RECORD (x, coding_system) @@ -250,9 +249,9 @@ EXFUN (Fset_coding_priority_list, 1); EXFUN (Fsubsidiary_coding_system, 2); extern Lisp_Object Qucs4, Qutf8; -extern Lisp_Object Qbig5, Qbuffer_file_coding_system, Qccl, Qcharset_g0; +extern Lisp_Object Qbig5, Qccl, Qcharset_g0; extern Lisp_Object Qcharset_g1, Qcharset_g2, Qcharset_g3, Qcoding_system_error; -extern Lisp_Object Qcoding_system_p, Qcr, Qcrlf, Qctext, Qdecode, Qencode; +extern Lisp_Object Qcoding_systemp, Qcr, Qcrlf, Qctext, Qdecode, Qencode; extern Lisp_Object Qeol_cr, Qeol_crlf, Qeol_lf, Qeol_type, Qescape_quoted; extern Lisp_Object Qforce_g0_on_output, Qforce_g1_on_output; extern Lisp_Object Qforce_g2_on_output, Qforce_g3_on_output; diff --git a/src/fileio.c b/src/fileio.c index 6844d96..a44dd4c 100644 --- a/src/fileio.c +++ b/src/fileio.c @@ -71,7 +71,7 @@ Boston, MA 02111-1307, USA. */ /* Need to lower-case the drive letter, or else expanded filenames will sometimes compare inequal, because `expand-file-name' doesn't always down-case the drive letter. */ -#define DRIVE_LETTER(x) (tolower (x)) +#define DRIVE_LETTER(x) tolower (x) #endif /* WINDOWSNT */ int lisp_to_time (Lisp_Object, time_t *); @@ -109,8 +109,6 @@ Lisp_Object Vauto_save_list_file_name; int disable_auto_save_when_buffer_shrinks; -Lisp_Object Qfile_name_handler_alist; - Lisp_Object Vdirectory_sep_char; /* These variables describe handlers that have "already" had a chance @@ -1303,19 +1301,19 @@ No component of the resulting pathname will be a symbolic link, as { char resolved_path[MAXPATHLEN]; - char path[MAXPATHLEN]; - char *p = path; - int elen = XSTRING_LENGTH (expanded_name); + Extbyte *path; + Extbyte *p; + Extcount elen = XSTRING_LENGTH (expanded_name); - if (elen >= countof (path)) + GET_STRING_FILENAME_DATA_ALLOCA (expanded_name,path,elen); + p = path; + if (elen > MAXPATHLEN) goto toolong; - - memcpy (path, XSTRING_DATA (expanded_name), elen + 1); - /* memset (resolved_path, 0, sizeof (resolved_path)); */ - + /* Try doing it all at once. */ - /* !!#### Does realpath() Mule-encapsulate? */ - if (!xrealpath (path, resolved_path)) + /* !! Does realpath() Mule-encapsulate? + Answer: Nope! So we do it above */ + if (!xrealpath ((char *) path, resolved_path)) { /* Didn't resolve it -- have to do it one component at a time. */ /* "realpath" is a typically useless, stupid un*x piece of crap. @@ -1325,12 +1323,12 @@ No component of the resulting pathname will be a symbolic link, as partial result returned. What a piece of junk. */ for (;;) { - p = (char *) memchr (p + 1, '/', elen - (p + 1 - path)); + p = (Extbyte *) memchr (p + 1, '/', elen - (p + 1 - path)); if (p) *p = 0; /* memset (resolved_path, 0, sizeof (resolved_path)); */ - if (xrealpath (path, resolved_path)) + if (xrealpath ((char *) path, resolved_path)) { if (p) *p = '/'; @@ -1998,7 +1996,7 @@ This is what happens in interactive use with M-x. Fcopy_file (filename, newname, /* We have already prompted if it was an integer, so don't have copy-file prompt again. */ - ((NILP (ok_if_already_exists)) ? Qnil : Qt), + (NILP (ok_if_already_exists) ? Qnil : Qt), Qt); Fdelete_file (filename); } @@ -3909,7 +3907,7 @@ Non-nil second argument means save only current buffer. run_hook (Qauto_save_hook); - if (GC_STRINGP (Vauto_save_list_file_name)) + if (STRINGP (Vauto_save_list_file_name)) listfile = condition_case_1 (Qt, auto_save_expand_name, Vauto_save_list_file_name, @@ -3928,13 +3926,13 @@ Non-nil second argument means save only current buffer. for (do_handled_files = 0; do_handled_files < 2; do_handled_files++) { for (tail = Vbuffer_alist; - GC_CONSP (tail); + CONSP (tail); tail = XCDR (tail)) { buf = XCDR (XCAR (tail)); b = XBUFFER (buf); - if (!GC_NILP (current_only) + if (!NILP (current_only) && b != current_buffer) continue; @@ -3946,7 +3944,7 @@ Non-nil second argument means save only current buffer. /* Check for auto save enabled and file changed since last auto save and file changed since last real save. */ - if (GC_STRINGP (b->auto_save_file_name) + if (STRINGP (b->auto_save_file_name) && BUF_SAVE_MODIFF (b) < BUF_MODIFF (b) && b->auto_save_modified < BUF_MODIFF (b) /* -1 means we've turned off autosaving for a while--see below. */ @@ -3991,7 +3989,7 @@ Non-nil second argument means save only current buffer. continue; } set_buffer_internal (b); - if (!auto_saved && GC_NILP (no_message)) + if (!auto_saved && NILP (no_message)) { static CONST unsigned char *msg = (CONST unsigned char *) "Auto-saving..."; @@ -4003,7 +4001,7 @@ Non-nil second argument means save only current buffer. /* Open the auto-save list file, if necessary. We only do this now so that the file only exists if we actually auto-saved any files. */ - if (!auto_saved && GC_STRINGP (listfile) && listdesc < 0) + if (!auto_saved && STRINGP (listfile) && listdesc < 0) { listdesc = open ((char *) XSTRING_DATA (listfile), O_WRONLY | O_TRUNC | O_CREAT | OPEN_BINARY, @@ -4092,7 +4090,7 @@ Non-nil second argument means save only current buffer. one because nothing needed to be auto-saved. Do this afterwards rather than before in case we get a crash attempting to autosave (in that case we'd still want the old one around). */ - if (listdesc < 0 && !auto_saved && GC_STRINGP (listfile)) + if (listdesc < 0 && !auto_saved && STRINGP (listfile)) unlink ((char *) XSTRING_DATA (listfile)); /* Show "...done" only if the echo area would otherwise be empty. */ @@ -4180,7 +4178,6 @@ syms_of_fileio (void) defsymbol (&Qset_visited_file_modtime, "set-visited-file-modtime"); defsymbol (&Qcar_less_than_car, "car-less-than-car"); /* Vomitous! */ - defsymbol (&Qfile_name_handler_alist, "file-name-handler-alist"); defsymbol (&Qauto_save_hook, "auto-save-hook"); defsymbol (&Qauto_save_error, "auto-save-error"); defsymbol (&Qauto_saving, "auto-saving"); diff --git a/src/filelock.c b/src/filelock.c index 44a4f43..49bda9a 100644 --- a/src/filelock.c +++ b/src/filelock.c @@ -126,11 +126,11 @@ lock_file_1 (char *lfname,int force) char *lock_info_str; if (STRINGP (Fuser_login_name (Qnil))) - user_name = (char *)XSTRING_DATA((Fuser_login_name (Qnil))); + user_name = (char *) XSTRING_DATA (Fuser_login_name (Qnil)); else user_name = ""; if (STRINGP (Fsystem_name ())) - host_name = (char *)XSTRING_DATA((Fsystem_name ())); + host_name = (char *) XSTRING_DATA (Fsystem_name ()); else host_name = ""; lock_info_str = (char *)alloca (strlen (user_name) + strlen (host_name) diff --git a/src/floatfns.c b/src/floatfns.c index a0fd427..5e86a98 100644 --- a/src/floatfns.c +++ b/src/floatfns.c @@ -108,15 +108,15 @@ static CONST char *float_error_fn_name; #define arith_error(op,arg) \ - Fsignal (Qarith_error, list2 (build_string ((op)), (arg))) + Fsignal (Qarith_error, list2 (build_string (op), arg)) #define range_error(op,arg) \ - Fsignal (Qrange_error, list2 (build_string ((op)), (arg))) + Fsignal (Qrange_error, list2 (build_string (op), arg)) #define range_error2(op,a1,a2) \ - Fsignal (Qrange_error, list3 (build_string ((op)), (a1), (a2))) + Fsignal (Qrange_error, list3 (build_string (op), a1, a2)) #define domain_error(op,arg) \ - Fsignal (Qdomain_error, list2 (build_string ((op)), (arg))) + Fsignal (Qdomain_error, list2 (build_string (op), arg)) #define domain_error2(op,a1,a2) \ - Fsignal (Qdomain_error, list3 (build_string ((op)), (a1), (a2))) + Fsignal (Qdomain_error, list3 (build_string (op), a1, a2)) /* Convert float to Lisp Integer if it fits, else signal a range @@ -160,7 +160,7 @@ in_float_error (void) static Lisp_Object -mark_float (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_float (Lisp_Object obj) { return Qnil; } diff --git a/src/fns.c b/src/fns.c index 55d5e2f..0b110e8 100644 --- a/src/fns.c +++ b/src/fns.c @@ -61,7 +61,7 @@ Lisp_Object Qidentity; static int internal_old_equal (Lisp_Object, Lisp_Object, int); static Lisp_Object -mark_bit_vector (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_bit_vector (Lisp_Object obj) { return Qnil; } @@ -69,10 +69,10 @@ mark_bit_vector (Lisp_Object obj, void (*markobj) (Lisp_Object)) static void print_bit_vector (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) { - int i; + size_t i; struct Lisp_Bit_Vector *v = XBIT_VECTOR (obj); - int len = bit_vector_length (v); - int last = len; + size_t len = bit_vector_length (v); + size_t last = len; if (INTP (Vprint_length)) last = min (len, XINT (Vprint_length)); @@ -111,9 +111,16 @@ bit_vector_hash (Lisp_Object obj, int depth) sizeof (long))); } +static const struct lrecord_description bit_vector_description[] = { + { XD_LISP_OBJECT, offsetof(Lisp_Bit_Vector, next), 1 }, + { XD_END } +}; + + DEFINE_BASIC_LRECORD_IMPLEMENTATION ("bit-vector", bit_vector, mark_bit_vector, print_bit_vector, 0, - bit_vector_equal, bit_vector_hash, 0, + bit_vector_equal, bit_vector_hash, + bit_vector_description, struct Lisp_Bit_Vector); DEFUN ("identity", Fidentity, 1, 1, 0, /* @@ -208,7 +215,7 @@ Return the length of vector, bit vector, list or string SEQUENCE. return make_int (XSTRING_CHAR_LENGTH (sequence)); else if (CONSP (sequence)) { - int len; + size_t len; GET_EXTERNAL_LIST_LENGTH (sequence, len); return make_int (len); } @@ -235,7 +242,7 @@ which is at least the number of distinct elements. (list)) { Lisp_Object hare, tortoise; - int len; + size_t len; for (hare = tortoise = list, len = 0; CONSP (hare) && (! EQ (hare, tortoise) || len == 0); @@ -515,7 +522,7 @@ copy_list (Lisp_Object list) Lisp_Object list_copy = Fcons (XCAR (list), XCDR (list)); Lisp_Object last = list_copy; Lisp_Object hare, tortoise; - int len; + size_t len; for (tortoise = hare = XCDR (list), len = 1; CONSP (hare); @@ -916,7 +923,7 @@ If SEQ is a string, relevant parts of the string-extent-data are copied */ (seq, from, to)) { - int len, f, t; + EMACS_INT len, f, t; if (STRINGP (seq)) return Fsubstring (seq, from, to); @@ -950,7 +957,7 @@ If SEQ is a string, relevant parts of the string-extent-data are copied if (VECTORP (seq)) { Lisp_Object result = make_vector (t - f, Qnil); - int i; + EMACS_INT i; Lisp_Object *in_elts = XVECTOR_DATA (seq); Lisp_Object *out_elts = XVECTOR_DATA (result); @@ -962,7 +969,7 @@ If SEQ is a string, relevant parts of the string-extent-data are copied if (LISTP (seq)) { Lisp_Object result = Qnil; - int i; + EMACS_INT i; seq = Fnthcdr (make_int (f), seq); @@ -978,7 +985,7 @@ If SEQ is a string, relevant parts of the string-extent-data are copied /* bit vector */ { Lisp_Object result = make_bit_vector (t - f, Qzero); - int i; + EMACS_INT i; for (i = f; i < t; i++) set_bit_vector_bit (XBIT_VECTOR (result), i - f, @@ -993,7 +1000,7 @@ Take cdr N times on LIST, and return the result. */ (n, list)) { - REGISTER int i; + REGISTER size_t i; REGISTER Lisp_Object tail = list; CHECK_NATNUM (n); for (i = XINT (n); i; i--) @@ -1052,7 +1059,7 @@ Return element of SEQUENCE at index N. #ifdef LOSING_BYTECODE else if (COMPILED_FUNCTIONP (sequence)) { - int idx = XINT (n); + EMACS_INT idx = XINT (n); if (idx < 0) { lose: @@ -1104,7 +1111,7 @@ If N is greater than the length of LIST, then LIST itself is returned. */ (list, n)) { - int int_n, count; + EMACS_INT int_n, count; Lisp_Object retval, tortoise, hare; CHECK_LIST (list); @@ -1140,7 +1147,7 @@ If LIST has N or fewer elements, nil is returned and LIST is unmodified. */ (list, n)) { - int int_n; + EMACS_INT int_n; CHECK_LIST (list); @@ -2714,12 +2721,6 @@ See also `get', `remprop', and `object-plist'. return value; } -void -pure_put (Lisp_Object sym, Lisp_Object prop, Lisp_Object val) -{ - Fput (sym, prop, Fpurecopy (val)); -} - DEFUN ("remprop", Fremprop, 2, 2, 0, /* Remove from OBJECT's property list the property PROPNAME and its value. OBJECT can be a symbol, face, extent, or string. Returns @@ -3176,11 +3177,14 @@ SEQUENCE may be a list, a vector or a string. return result; } -DEFUN ("mapc", Fmapc, 2, 2, 0, /* +DEFUN ("mapc-internal", Fmapc_internal, 2, 2, 0, /* Apply FUNCTION to each element of SEQUENCE. SEQUENCE may be a list, a vector, a bit vector, or a string. This function is like `mapcar' but does not accumulate the results, which is more efficient if you do not use the results. + +The difference between this and `mapc' is that `mapc' supports all +the spiffy Common Lisp arguments. You should normally use `mapc'. */ (fn, seq)) { @@ -3871,7 +3875,7 @@ syms_of_fns (void) DEFSUBR (Fnconc); DEFSUBR (Fmapcar); DEFSUBR (Fmapvector); - DEFSUBR (Fmapc); + DEFSUBR (Fmapc_internal); DEFSUBR (Fmapconcat); DEFSUBR (Fload_average); DEFSUBR (Ffeaturep); diff --git a/src/font-lock.c b/src/font-lock.c index cefa0d5..0debfda 100644 --- a/src/font-lock.c +++ b/src/font-lock.c @@ -769,8 +769,14 @@ syms_of_font_lock (void) } void -vars_of_font_lock (void) +reinit_vars_of_font_lock (void) { xzero (context_cache); xzero (bol_context_cache); } + +void +vars_of_font_lock (void) +{ + reinit_vars_of_font_lock (); +} diff --git a/src/frame-msw.c b/src/frame-msw.c index f48b7af..6eaac63 100644 --- a/src/frame-msw.c +++ b/src/frame-msw.c @@ -248,13 +248,13 @@ mswindows_after_init_frame (struct frame *f, int first_on_device, } static void -mswindows_mark_frame (struct frame *f, void (*markobj) (Lisp_Object)) +mswindows_mark_frame (struct frame *f) { - markobj (FRAME_MSWINDOWS_MENU_HASH_TABLE (f)); + mark_object (FRAME_MSWINDOWS_MENU_HASH_TABLE (f)); #ifdef HAVE_TOOLBARS - markobj (FRAME_MSWINDOWS_TOOLBAR_HASH_TABLE (f)); + mark_object (FRAME_MSWINDOWS_TOOLBAR_HASH_TABLE (f)); #endif - markobj (FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f)); + mark_object (FRAME_MSWINDOWS_WIDGET_HASH_TABLE (f)); } static void @@ -741,10 +741,16 @@ syms_of_frame_mswindows (void) } void -vars_of_frame_mswindows (void) +reinit_vars_of_frame_mswindows (void) { /* Needn't staticpro -- see comment above. */ Vmswindows_frame_being_created = Qnil; +} + +void +vars_of_frame_mswindows (void) +{ + reinit_vars_of_frame_mswindows (); DEFVAR_LISP ("mswindows-use-system-frame-size-defaults", &Vmswindows_use_system_frame_size_defaults /* Controls whether to use system or XEmacs defaults for frame size. diff --git a/src/frame-x.c b/src/frame-x.c index 2aa7d59..906a6b1 100644 --- a/src/frame-x.c +++ b/src/frame-x.c @@ -103,19 +103,34 @@ x_window_to_frame (struct device *d, Window wdesc) struct frame * x_any_window_to_frame (struct device *d, Window wdesc) { - Lisp_Object tail, frame; - struct frame *f; - + Widget w; assert (DEVICE_X_P (d)); + w = XtWindowToWidget (DEVICE_X_DISPLAY (d), wdesc); + + if (!w) + return 0; + + /* We used to map over all frames here and then map over all widgets + belonging to that frame. However it turns out that this was very fragile + as it requires our display stuctures to be in sync _and_ that the + loop is told about every new widget somebody adds. Therefore we + now let Xt find it for us (which does a bottom-up search which + could even be faster) */ + return x_any_widget_or_parent_to_frame (d, w); +} + +static struct frame * +x_find_frame_for_window (struct device *d, Window wdesc) +{ + Lisp_Object tail, frame; + struct frame *f; /* This function was previously written to accept only a window argument (and to loop over all devices looking for a matching window), but that is incorrect because window ID's are not unique across displays. */ for (tail = DEVICE_FRAME_LIST (d); CONSP (tail); tail = XCDR (tail)) { - int i; - frame = XCAR (tail); f = XFRAME (frame); /* This frame matches if the window is any of its widgets. */ @@ -138,18 +153,18 @@ x_any_window_to_frame (struct device *d, Window wdesc) would incorrectly get sucked away by Emacs if this function matched on psheet widgets. */ - for (i = 0; i < FRAME_X_NUM_TOP_WIDGETS (f); i++) - { - Widget wid = FRAME_X_TOP_WIDGETS (f)[i]; - if (wid && XtIsManaged (wid) && wdesc == XtWindow (wid)) - return f; - } - -#ifdef HAVE_SCROLLBARS - /* Match if the window is one of this frame's scrollbars. */ - if (x_window_is_scrollbar (f, wdesc)) - return f; -#endif + /* Note: that this called only from + x_any_widget_or_parent_to_frame it is unnecessary to iterate + over the top level widgets. */ + + /* Note: we use to special case scrollbars but this turns out to be a bad idea + because + 1. We sometimes get events for _unmapped_ scrollbars and our + callers don't want us to fail. + 2. Starting with the 21.2 widget stuff there are now loads of + widgets to check and it is easy to forget adding them in a loop here. + See x_any_window_to_frame + 3. We pick up all widgets now anyway. */ } return 0; @@ -160,7 +175,7 @@ x_any_widget_or_parent_to_frame (struct device *d, Widget widget) { while (widget) { - struct frame *f = x_any_window_to_frame (d, XtWindow (widget)); + struct frame *f = x_find_frame_for_window (d, XtWindow (widget)); if (f) return f; widget = XtParent (widget); @@ -421,9 +436,9 @@ static void init_x_prop_symbols (void) { #define def(sym, rsrc) \ - pure_put (sym, Qx_resource_name, build_string (rsrc)) + Fput (sym, Qx_resource_name, build_string (rsrc)) #define defi(sym,rsrc) \ - def (sym, rsrc); pure_put (sym, Qintegerp, Qt) + def (sym, rsrc); Fput (sym, Qintegerp, Qt) #if 0 /* this interferes with things. #### fix this right */ def (Qminibuffer, XtNminibuffer); @@ -1880,7 +1895,7 @@ x_create_widgets (struct frame *f, Lisp_Object lisp_window_id, char *string; CHECK_STRING (lisp_window_id); - string = (char *) (XSTRING_DATA (lisp_window_id)); + string = (char *) XSTRING_DATA (lisp_window_id); if (string[0] == '0' && (string[1] == 'x' || string[1] == 'X')) sscanf (string+2, "%lxu", &window_id); #if 0 @@ -2190,10 +2205,10 @@ x_init_frame_3 (struct frame *f) } static void -x_mark_frame (struct frame *f, void (*markobj) (Lisp_Object)) +x_mark_frame (struct frame *f) { - markobj (FRAME_X_ICON_PIXMAP (f)); - markobj (FRAME_X_ICON_PIXMAP_MASK (f)); + mark_object (FRAME_X_ICON_PIXMAP (f)); + mark_object (FRAME_X_ICON_PIXMAP_MASK (f)); } static void diff --git a/src/frame.c b/src/frame.c index 5caeece..0264e90 100644 --- a/src/frame.c +++ b/src/frame.c @@ -86,7 +86,6 @@ Lisp_Object Qborder_color; Lisp_Object Qborder_width; Lisp_Object Qframep, Qframe_live_p; -Lisp_Object Qframe_x_p, Qframe_tty_p; Lisp_Object Qdelete_frame; Lisp_Object Qframe_title_format, Vframe_title_format; @@ -122,17 +121,17 @@ EXFUN (Fset_frame_properties, 2); static Lisp_Object -mark_frame (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_frame (Lisp_Object obj) { struct frame *f = XFRAME (obj); -#define MARKED_SLOT(x) ((void) (markobj (f->x))); +#define MARKED_SLOT(x) mark_object (f->x) #include "frameslots.h" - mark_subwindow_cachels (f->subwindow_cachels, markobj); + mark_subwindow_cachels (f->subwindow_cachels); if (FRAME_LIVE_P (f)) /* device is nil for a dead frame */ - MAYBE_FRAMEMETH (f, mark_frame, (f, markobj)); + MAYBE_FRAMEMETH (f, mark_frame, (f)); return Qnil; } @@ -162,7 +161,7 @@ DEFINE_LRECORD_IMPLEMENTATION ("frame", frame, static void nuke_all_frame_slots (struct frame *f) { -#define MARKED_SLOT(x) f->x = Qnil; +#define MARKED_SLOT(x) f->x = Qnil #include "frameslots.h" } @@ -209,6 +208,10 @@ allocate_frame_core (Lisp_Object device) /* cache of subwindows visible on frame */ f->subwindow_cachels = Dynarr_new (subwindow_cachel); + /* associated exposure ignore list */ + f->subwindow_exposures = 0; + f->subwindow_exposures_tail = 0; + /* Choose a buffer for the frame's root window. */ XWINDOW (root_window)->buffer = Qt; { @@ -410,7 +413,7 @@ See `set-frame-properties', `default-x-frame-plist', and update_frame_window_mirror (f); - if (initialized) + if (initialized && !DEVICE_STREAM_P (d)) { if (!NILP (f->minibuffer_window)) reset_face_cachels (XWINDOW (f->minibuffer_window)); @@ -3074,8 +3077,6 @@ syms_of_frame (void) defsymbol (&Qframep, "framep"); defsymbol (&Qframe_live_p, "frame-live-p"); - defsymbol (&Qframe_x_p, "frame-x-p"); - defsymbol (&Qframe_tty_p, "frame-tty-p"); defsymbol (&Qdelete_frame, "delete-frame"); defsymbol (&Qsynchronize_minibuffers, "synchronize-minibuffers"); defsymbol (&Qbuffer_predicate, "buffer-predicate"); @@ -3291,13 +3292,13 @@ Controls the title of the X window corresponding to the selected frame. This is the same format as `modeline-format' with the exception that %- is ignored. */ ); - Vframe_title_format = Fpurecopy (build_string ("%S: %b")); + Vframe_title_format = build_string ("%S: %b"); DEFVAR_LISP ("frame-icon-title-format", &Vframe_icon_title_format /* Controls the title of the icon corresponding to the selected frame. See also the variable `frame-title-format'. */ ); - Vframe_icon_title_format = Fpurecopy (build_string ("%b")); + Vframe_icon_title_format = build_string ("%b"); DEFVAR_LISP ("default-frame-name", &Vdefault_frame_name /* The default name to assign to newly-created frames. @@ -3305,9 +3306,9 @@ This can be overridden by arguments to `make-frame'. This must be a string. */ ); #ifndef INFODOCK - Vdefault_frame_name = Fpurecopy (build_string ("emacs")); + Vdefault_frame_name = build_string ("emacs"); #else - Vdefault_frame_name = Fpurecopy (build_string ("InfoDock")); + Vdefault_frame_name = build_string ("InfoDock"); #endif DEFVAR_LISP ("default-frame-plist", &Vdefault_frame_plist /* diff --git a/src/frame.h b/src/frame.h index be75ff9..bba3195 100644 --- a/src/frame.h +++ b/src/frame.h @@ -94,6 +94,9 @@ struct frame /* subwindow cache elements for this frame */ subwindow_cachel_dynarr *subwindow_cachels; + struct expose_ignore* subwindow_exposures; + struct expose_ignore* subwindow_exposures_tail; + #ifdef HAVE_SCROLLBARS /* frame-local scrollbar information. See scrollbar.c. */ int scrollbar_y_offset; @@ -178,6 +181,7 @@ Value : Emacs meaning :f-v-p : X meaning unsigned int faces_changed :1; unsigned int frame_changed :1; unsigned int subwindows_changed :1; + unsigned int subwindows_state_changed :1; unsigned int glyphs_changed :1; unsigned int icon_changed :1; unsigned int menubar_changed :1; @@ -233,7 +237,6 @@ DECLARE_LRECORD (frame, struct frame); #define XFRAME(x) XRECORD (x, frame, struct frame) #define XSETFRAME(x, p) XSETRECORD (x, p, frame) #define FRAMEP(x) RECORDP (x, frame) -#define GC_FRAMEP(x) GC_RECORDP (x, frame) #define CHECK_FRAME(x) CHECK_RECORD (x, frame) #define CONCHECK_FRAME(x) CONCHECK_RECORD (x, frame) @@ -260,7 +263,7 @@ error_check_frame_type (struct frame * f, Lisp_Object sym) return f; } # define FRAME_TYPE_DATA(f, type) \ - ((struct type##_frame *) (error_check_frame_type (f, Q##type))->frame_data) + ((struct type##_frame *) error_check_frame_type (f, Q##type)->frame_data) #else # define FRAME_TYPE_DATA(f, type) \ ((struct type##_frame *) (f)->frame_data) @@ -340,6 +343,19 @@ extern int frame_changed; subwindows_changed = 1; \ } while (0) +#define MARK_FRAME_SUBWINDOWS_STATE_CHANGED(f) do { \ + struct frame *mfgc_f = (f); \ + mfgc_f->subwindows_state_changed = 1; \ + mfgc_f->modiff++; \ + if (!NILP (mfgc_f->device)) \ + { \ + struct device *mfgc_d = XDEVICE (mfgc_f->device); \ + MARK_DEVICE_SUBWINDOWS_STATE_CHANGED (mfgc_d); \ + } \ + else \ + subwindows_state_changed = 1; \ +} while (0) + #define MARK_FRAME_TOOLBARS_CHANGED(f) do { \ struct frame *mftc_f = (f); \ mftc_f->toolbar_changed = 1; \ diff --git a/src/free-hook.c b/src/free-hook.c index cac4a86..d243aeb 100644 --- a/src/free-hook.c +++ b/src/free-hook.c @@ -85,14 +85,14 @@ void *malloc (size_t); /* System function prototypes don't belong in C source files */ /* extern void free (void *); */ -struct hash_table *pointer_table; +static struct hash_table *pointer_table; extern void (*__free_hook) (void *); extern void *(*__malloc_hook) (size_t); static void *check_malloc (size_t); -typedef void (*fun_ptr) (); +typedef void (*fun_ptr) (void); /* free_queue is not too useful without backtrace logging */ #define FREE_QUEUE_LIMIT 1 @@ -110,11 +110,11 @@ typedef struct { unsigned long length; } free_queue_entry; -free_queue_entry free_queue[FREE_QUEUE_LIMIT]; +static free_queue_entry free_queue[FREE_QUEUE_LIMIT]; -int current_free; +static int current_free; -int strict_free_check; +static int strict_free_check; static void check_free (void *ptr) diff --git a/src/gdbinit b/src/gdbinit index b7d238d..a50968a 100644 --- a/src/gdbinit +++ b/src/gdbinit @@ -327,8 +327,8 @@ define pobj if $imp == &lrecord_opaque pstruct Lisp_Opaque else - if $imp == &lrecord_opaque_list - pstruct Lisp_Opaque_List + if $imp == &lrecord_opaque_ptr + pstruct Lisp_Opaque_Ptr else if $imp == &lrecord_popup_data pstruct popup_data diff --git a/src/general.c b/src/general.c index 06c4db1..9676b6d 100644 --- a/src/general.c +++ b/src/general.c @@ -34,24 +34,19 @@ Boston, MA 02111-1307, USA. */ Lisp_Object Qactually_requested; Lisp_Object Qafter; Lisp_Object Qall; -Lisp_Object Qalways; Lisp_Object Qand; Lisp_Object Qassoc; Lisp_Object Qat; -Lisp_Object Qauth; Lisp_Object Qautodetect; Lisp_Object Qbad_variable; -Lisp_Object Qbase; Lisp_Object Qbefore; Lisp_Object Qbinary; -Lisp_Object Qbinddn; Lisp_Object Qbitmap; -Lisp_Object Qblack; Lisp_Object Qboolean; Lisp_Object Qbottom; Lisp_Object Qbuffer; Lisp_Object Qbutton; -Lisp_Object Qcase; +Lisp_Object Qcenter; Lisp_Object Qcategory; Lisp_Object Qchannel; Lisp_Object Qchar; @@ -68,7 +63,6 @@ Lisp_Object Qdead; Lisp_Object Qdefault; Lisp_Object Qdelete; Lisp_Object Qdelq; -Lisp_Object Qderef; Lisp_Object Qdevice; Lisp_Object Qdimension; Lisp_Object Qdisplay; @@ -81,7 +75,6 @@ Lisp_Object Qequal; Lisp_Object Qeval; Lisp_Object Qextents; Lisp_Object Qface; -Lisp_Object Qfind; Lisp_Object Qfont; Lisp_Object Qframe; Lisp_Object Qfunction; @@ -92,6 +85,7 @@ Lisp_Object Qglobal; Lisp_Object Qgutter; Lisp_Object Qheight; Lisp_Object Qhighlight; +Lisp_Object Qhorizontal; Lisp_Object Qicon; Lisp_Object Qid; Lisp_Object Qimage; @@ -101,10 +95,7 @@ Lisp_Object Qinteger; Lisp_Object Qinternal; Lisp_Object Qkey; Lisp_Object Qkey_assoc; -Lisp_Object Qkeyboard; Lisp_Object Qkeymap; -Lisp_Object Qkrbv41; -Lisp_Object Qkrbv42; Lisp_Object Qleft; Lisp_Object Qlist; Lisp_Object Qmagic; @@ -112,14 +103,12 @@ Lisp_Object Qmalloc_overhead; Lisp_Object Qmarkers; Lisp_Object Qmax; Lisp_Object Qmemory; -Lisp_Object Qmenubar; Lisp_Object Qmessage; Lisp_Object Qminus; Lisp_Object Qmodifiers; Lisp_Object Qmotion; Lisp_Object Qmswindows; Lisp_Object Qname; -Lisp_Object Qnever; Lisp_Object Qnone; Lisp_Object Qnot; Lisp_Object Qnothing; @@ -130,15 +119,11 @@ Lisp_Object Qold_delete; Lisp_Object Qold_delq; Lisp_Object Qold_rassoc; Lisp_Object Qold_rassq; -Lisp_Object Qonelevel; Lisp_Object Qonly; Lisp_Object Qor; Lisp_Object Qother; -Lisp_Object Qpasswd; -Lisp_Object Qpath; Lisp_Object Qpointer; Lisp_Object Qpopup; -Lisp_Object Qport; Lisp_Object Qprint; Lisp_Object Qprocess; Lisp_Object Qprovide; @@ -154,17 +139,14 @@ Lisp_Object Qselected; Lisp_Object Qsignal; Lisp_Object Qsimple; Lisp_Object Qsize; -Lisp_Object Qsizelimit; Lisp_Object Qspace; Lisp_Object Qspecifier; Lisp_Object Qstream; Lisp_Object Qstring; -Lisp_Object Qsubtree; Lisp_Object Qsymbol; Lisp_Object Qsyntax; Lisp_Object Qtest; Lisp_Object Qtext; -Lisp_Object Qtimelimit; Lisp_Object Qtimeout; Lisp_Object Qtimestamp; Lisp_Object Qtoolbar; @@ -175,9 +157,8 @@ Lisp_Object Qundecided; Lisp_Object Qundefined; Lisp_Object Qunimplemented; Lisp_Object Qvalue_assoc; -Lisp_Object Qvector; +Lisp_Object Qvertical; Lisp_Object Qwarning; -Lisp_Object Qwhite; Lisp_Object Qwidth; Lisp_Object Qwidget; Lisp_Object Qwindow; @@ -191,25 +172,20 @@ syms_of_general (void) defsymbol (&Qactually_requested, "actually-requested"); defsymbol (&Qafter, "after"); defsymbol (&Qall, "all"); - defsymbol (&Qalways, "always"); defsymbol (&Qand, "and"); defsymbol (&Qassoc, "assoc"); defsymbol (&Qat, "at"); - defsymbol (&Qauth, "auth"); defsymbol (&Qautodetect, "autodetect"); defsymbol (&Qbad_variable, "bad-variable"); - defsymbol (&Qbase, "base"); defsymbol (&Qbefore, "before"); defsymbol (&Qbinary, "binary"); - defsymbol (&Qbinddn, "binddn"); defsymbol (&Qbitmap, "bitmap"); - defsymbol (&Qblack, "black"); defsymbol (&Qboolean, "boolean"); defsymbol (&Qbottom, "bottom"); defsymbol (&Qbuffer, "buffer"); defsymbol (&Qbutton, "button"); - defsymbol (&Qcase, "case"); defsymbol (&Qcategory, "category"); + defsymbol (&Qcenter, "center"); defsymbol (&Qchannel, "channel"); defsymbol (&Qchar, "char"); defsymbol (&Qcharacter, "character"); @@ -225,7 +201,6 @@ syms_of_general (void) defsymbol (&Qdefault, "default"); defsymbol (&Qdelete, "delete"); defsymbol (&Qdelq, "delq"); - defsymbol (&Qderef, "deref"); defsymbol (&Qdevice, "device"); defsymbol (&Qdimension, "dimension"); defsymbol (&Qdisplay, "display"); @@ -238,7 +213,6 @@ syms_of_general (void) defsymbol (&Qeval, "eval"); defsymbol (&Qextents, "extents"); defsymbol (&Qface, "face"); - defsymbol (&Qfind, "find"); defsymbol (&Qfont, "font"); defsymbol (&Qframe, "frame"); defsymbol (&Qfunction, "function"); @@ -249,6 +223,7 @@ syms_of_general (void) defsymbol (&Qgutter, "gutter"); defsymbol (&Qheight, "height"); defsymbol (&Qhighlight, "highlight"); + defsymbol (&Qhorizontal, "horizontal"); defsymbol (&Qicon, "icon"); defsymbol (&Qid, "id"); defsymbol (&Qimage, "image"); @@ -258,10 +233,7 @@ syms_of_general (void) defsymbol (&Qinternal, "internal"); defsymbol (&Qkey, "key"); defsymbol (&Qkey_assoc, "key-assoc"); - defsymbol (&Qkeyboard, "keyboard"); defsymbol (&Qkeymap, "keymap"); - defsymbol (&Qkrbv41, "krbv41"); - defsymbol (&Qkrbv42, "krbv42"); defsymbol (&Qleft, "left"); defsymbol (&Qlist, "list"); defsymbol (&Qmagic, "magic"); @@ -269,14 +241,12 @@ syms_of_general (void) defsymbol (&Qmarkers, "markers"); defsymbol (&Qmax, "max"); defsymbol (&Qmemory, "memory"); - defsymbol (&Qmenubar, "menubar"); defsymbol (&Qmessage, "message"); defsymbol (&Qminus, "-"); defsymbol (&Qmodifiers, "modifiers"); defsymbol (&Qmotion, "motion"); defsymbol (&Qmswindows, "mswindows"); defsymbol (&Qname, "name"); - defsymbol (&Qnever, "never"); defsymbol (&Qnone, "none"); defsymbol (&Qnot, "not"); defsymbol (&Qnothing, "nothing"); @@ -287,15 +257,11 @@ syms_of_general (void) defsymbol (&Qold_delq, "old-delq"); defsymbol (&Qold_rassoc, "old-rassoc"); defsymbol (&Qold_rassq, "old-rassq"); - defsymbol (&Qonelevel, "onelevel"); defsymbol (&Qonly, "only"); defsymbol (&Qor, "or"); defsymbol (&Qother, "other"); - defsymbol (&Qpasswd, "passwd"); - defsymbol (&Qpath, "path"); defsymbol (&Qpointer, "pointer"); defsymbol (&Qpopup, "popup"); - defsymbol (&Qport, "port"); defsymbol (&Qprint, "print"); defsymbol (&Qprocess, "process"); defsymbol (&Qprovide, "provide"); @@ -311,17 +277,14 @@ syms_of_general (void) defsymbol (&Qsignal, "signal"); defsymbol (&Qsimple, "simple"); defsymbol (&Qsize, "size"); - defsymbol (&Qsizelimit, "sizelimit"); defsymbol (&Qspace, "space"); defsymbol (&Qspecifier, "specifier"); defsymbol (&Qstream, "stream"); defsymbol (&Qstring, "string"); - defsymbol (&Qsubtree, "subtree"); defsymbol (&Qsymbol, "symbol"); defsymbol (&Qsyntax, "syntax"); defsymbol (&Qtest, "test"); defsymbol (&Qtext, "text"); - defsymbol (&Qtimelimit, "timelimit"); defsymbol (&Qtimeout, "timeout"); defsymbol (&Qtimestamp, "timestamp"); defsymbol (&Qtoolbar, "toolbar"); @@ -332,9 +295,8 @@ syms_of_general (void) defsymbol (&Qundefined, "undefined"); defsymbol (&Qunimplemented, "unimplemented"); defsymbol (&Qvalue_assoc, "value-assoc"); - defsymbol (&Qvector, "vector"); + defsymbol (&Qvertical, "vertical"); defsymbol (&Qwarning, "warning"); - defsymbol (&Qwhite, "white"); defsymbol (&Qwidth, "width"); defsymbol (&Qwidget, "widget"); defsymbol (&Qwindow, "window"); diff --git a/src/getloadavg.c b/src/getloadavg.c index b8161e4..2bf2c3f 100644 --- a/src/getloadavg.c +++ b/src/getloadavg.c @@ -94,10 +94,6 @@ Boston, MA 02111-1307, USA. */ #include -#ifndef errno -extern int errno; -#endif - #ifndef HAVE_GETLOADAVG /* The existing Emacs configuration files define a macro called diff --git a/src/gif_io.c b/src/gif_io.c index ddbfb16..0421b4b 100644 --- a/src/gif_io.c +++ b/src/gif_io.c @@ -3,6 +3,7 @@ #include #include #include "gifrlib.h" +#include "sysfile.h" /****************************************************************************** * Set up the GifFileType structure for use. This must be called first in any * diff --git a/src/glyphs-eimage.c b/src/glyphs-eimage.c index 6b80c82..4005413 100644 --- a/src/glyphs-eimage.c +++ b/src/glyphs-eimage.c @@ -482,7 +482,7 @@ jpeg_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, /* now instantiate */ MAYBE_DEVMETH (XDEVICE (ii->device), init_image_instance_from_eimage, - (ii, cinfo.output_width, cinfo.output_height, + (ii, cinfo.output_width, cinfo.output_height, 1, unwind.eimage, dest_mask, instantiator, domain)); @@ -651,10 +651,10 @@ gif_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, DGifSlurp (unwind.giffile); } - /* 3. Now create the EImage */ + /* 3. Now create the EImage(s) */ { ColorMapObject *cmo = unwind.giffile->SColorMap; - int i, j, row, pass, interlace; + int i, j, row, pass, interlace, slice; unsigned char *eip; /* interlaced gifs have rows in this order: 0, 8, 16, ..., 4, 12, 20, ..., 2, 6, 10, ..., 1, 3, 5, ... */ @@ -663,52 +663,81 @@ gif_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, height = unwind.giffile->SHeight; width = unwind.giffile->SWidth; - unwind.eimage = (unsigned char*) xmalloc (width * height * 3); + unwind.eimage = (unsigned char*) + xmalloc (width * height * 3 * unwind.giffile->ImageCount); if (!unwind.eimage) signal_image_error("Unable to allocate enough memory for image", instantiator); /* write the data in EImage format (8bit RGB triples) */ - /* Note: We just use the first image in the file and ignore the rest. - We check here that that image covers the full "screen" size. - I don't know whether that's always the case. - -dkindred@cs.cmu.edu */ - if (unwind.giffile->SavedImages[0].ImageDesc.Height != height - || unwind.giffile->SavedImages[0].ImageDesc.Width != width - || unwind.giffile->SavedImages[0].ImageDesc.Left != 0 - || unwind.giffile->SavedImages[0].ImageDesc.Top != 0) - signal_image_error ("First image in GIF file is not full size", - instantiator); - - interlace = unwind.giffile->SavedImages[0].ImageDesc.Interlace; - pass = 0; - row = interlace ? InterlacedOffset[pass] : 0; - eip = unwind.eimage; - for (i = 0; i < height; i++) + for (slice = 0; slice < unwind.giffile->ImageCount; slice++) { - if (interlace) - if (row >= height) { - row = InterlacedOffset[++pass]; - while (row >= height) - row = InterlacedOffset[++pass]; - } - eip = unwind.eimage + (row * width * 3); - for (j = 0; j < width; j++) + /* We check here that that the current image covers the full "screen" size. */ + if (unwind.giffile->SavedImages[slice].ImageDesc.Height != height + || unwind.giffile->SavedImages[slice].ImageDesc.Width != width + || unwind.giffile->SavedImages[slice].ImageDesc.Left != 0 + || unwind.giffile->SavedImages[slice].ImageDesc.Top != 0) + signal_image_error ("Image in GIF file is not full size", + instantiator); + + interlace = unwind.giffile->SavedImages[slice].ImageDesc.Interlace; + pass = 0; + row = interlace ? InterlacedOffset[pass] : 0; + eip = unwind.eimage + (width * height * 3 * slice); + for (i = 0; i < height; i++) { - unsigned char pixel = unwind.giffile->SavedImages[0].RasterBits[(i * width) + j]; - *eip++ = cmo->Colors[pixel].Red; - *eip++ = cmo->Colors[pixel].Green; - *eip++ = cmo->Colors[pixel].Blue; + if (interlace) + if (row >= height) { + row = InterlacedOffset[++pass]; + while (row >= height) + row = InterlacedOffset[++pass]; + } + eip = unwind.eimage + (width * height * 3 * slice) + (row * width * 3); + for (j = 0; j < width; j++) + { + unsigned char pixel = + unwind.giffile->SavedImages[slice].RasterBits[(i * width) + j]; + *eip++ = cmo->Colors[pixel].Red; + *eip++ = cmo->Colors[pixel].Green; + *eip++ = cmo->Colors[pixel].Blue; + } + row += interlace ? InterlacedJumps[pass] : 1; } - row += interlace ? InterlacedJumps[pass] : 1; } + + /* now instantiate */ + MAYBE_DEVMETH (XDEVICE (ii->device), + init_image_instance_from_eimage, + (ii, width, height, unwind.giffile->ImageCount, unwind.eimage, dest_mask, + instantiator, domain)); } - /* now instantiate */ - MAYBE_DEVMETH (XDEVICE (ii->device), - init_image_instance_from_eimage, - (ii, width, height, unwind.eimage, dest_mask, - instantiator, domain)); + /* We read the gif successfully. If we have more than one slice then + animate the gif. */ + if (unwind.giffile->ImageCount > 1) + { + /* See if there is a timeout value. In theory there could be one + for every image - but that makes the implementation way to + complicated for now so we just take the first. */ + unsigned short timeout = 0; + Lisp_Object tid; + + if (unwind.giffile->SavedImages[0].Function == GRAPHICS_EXT_FUNC_CODE + && + unwind.giffile->SavedImages[0].ExtensionBlockCount) + { + timeout = (unsigned short) + ((unwind.giffile->SavedImages[0].ExtensionBlocks[0].Bytes[2] << 8) + + unwind.giffile-> SavedImages[0].ExtensionBlocks[0].Bytes[1]) * 10; + } + + /* Too short a timeout will crucify us performance-wise. */ + tid = add_glyph_animated_timeout (timeout > 10 ? timeout : 10, image_instance); + + if (!NILP (tid)) + IMAGE_INSTANCE_PIXMAP_TIMEOUT (ii) = XINT (tid); + } + unbind_to (speccount, Qnil); } @@ -990,7 +1019,7 @@ png_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, /* now instantiate */ MAYBE_DEVMETH (XDEVICE (ii->device), init_image_instance_from_eimage, - (ii, width, height, unwind.eimage, dest_mask, + (ii, width, height, 1, unwind.eimage, dest_mask, instantiator, domain)); /* This will clean up everything else. */ @@ -1270,7 +1299,7 @@ tiff_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, /* now instantiate */ MAYBE_DEVMETH (XDEVICE (ii->device), init_image_instance_from_eimage, - (ii, width, height, unwind.eimage, dest_mask, + (ii, width, height, 1, unwind.eimage, dest_mask, instantiator, domain)); unbind_to (speccount, Qnil); diff --git a/src/glyphs-msw.c b/src/glyphs-msw.c index 7a9f8d3..d3c11b6 100644 --- a/src/glyphs-msw.c +++ b/src/glyphs-msw.c @@ -1,5 +1,5 @@ /* mswindows-specific glyph objects. - Copyright (C) 1998, 99 Andy Piper. + Copyright (C) 1998, 1999 Andy Piper. This file is part of XEmacs. @@ -57,6 +57,7 @@ DECLARE_IMAGE_INSTANTIATOR_FORMAT (nothing); DECLARE_IMAGE_INSTANTIATOR_FORMAT (string); DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string); DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit); +DECLARE_IMAGE_INSTANTIATOR_FORMAT (layout); #ifdef HAVE_JPEG DECLARE_IMAGE_INSTANTIATOR_FORMAT (jpeg); #endif @@ -78,9 +79,6 @@ DEFINE_DEVICE_IIFORMAT (mswindows, xface); #endif DEFINE_DEVICE_IIFORMAT (mswindows, button); DEFINE_DEVICE_IIFORMAT (mswindows, edit_field); -#if 0 -DEFINE_DEVICE_IIFORMAT (mswindows, group); -#endif DEFINE_DEVICE_IIFORMAT (mswindows, subwindow); DEFINE_DEVICE_IIFORMAT (mswindows, widget); DEFINE_DEVICE_IIFORMAT (mswindows, label); @@ -101,13 +99,13 @@ Lisp_Object Qmswindows_resource; static void mswindows_initialize_dibitmap_image_instance (struct Lisp_Image_Instance *ii, - enum image_instance_type type); + int slices, + enum image_instance_type type); static void mswindows_initialize_image_instance_mask (struct Lisp_Image_Instance* image, struct frame* f); COLORREF mswindows_string_to_color (CONST char *name); -void check_valid_item_list_1 (Lisp_Object items); #define BPLINE(width) ((int)(~3UL & (unsigned long)((width) +3))) @@ -293,6 +291,7 @@ init_image_instance_from_dibitmap (struct Lisp_Image_Instance *ii, int dest_mask, void *bmp_data, int bmp_bits, + int slices, Lisp_Object instantiator, int x_hot, int y_hot, int create_mask) @@ -334,12 +333,14 @@ init_image_instance_from_dibitmap (struct Lisp_Image_Instance *ii, /* copy in the actual bitmap */ memcpy (bmp_buf, bmp_data, bmp_bits); - mswindows_initialize_dibitmap_image_instance (ii, type); + mswindows_initialize_dibitmap_image_instance (ii, slices, type); IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = find_keyword_in_vector (instantiator, Q_file); + /* Fixup a set of bitmaps. */ IMAGE_INSTANCE_MSWINDOWS_BITMAP (ii) = bitmap; + IMAGE_INSTANCE_MSWINDOWS_MASK (ii) = NULL; IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = bmp_info->bmiHeader.biWidth; IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = bmp_info->bmiHeader.biHeight; @@ -359,8 +360,36 @@ init_image_instance_from_dibitmap (struct Lisp_Image_Instance *ii, } static void +image_instance_add_dibitmap (struct Lisp_Image_Instance *ii, + BITMAPINFO *bmp_info, + void *bmp_data, + int bmp_bits, + int slice, + Lisp_Object instantiator) +{ + Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); + struct device *d = XDEVICE (device); + struct frame *f = XFRAME (DEVICE_SELECTED_FRAME (d)); + void* bmp_buf=0; + HDC hdc = FRAME_MSWINDOWS_CDC (f); + HBITMAP bitmap = CreateDIBSection (hdc, + bmp_info, + DIB_RGB_COLORS, + &bmp_buf, + 0,0); + + if (!bitmap || !bmp_buf) + signal_simple_error ("Unable to create bitmap", instantiator); + + /* copy in the actual bitmap */ + memcpy (bmp_buf, bmp_data, bmp_bits); + IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (ii, slice) = bitmap; +} + +static void mswindows_init_image_instance_from_eimage (struct Lisp_Image_Instance *ii, int width, int height, + int slices, unsigned char *eimage, int dest_mask, Lisp_Object instantiator, @@ -371,6 +400,7 @@ mswindows_init_image_instance_from_eimage (struct Lisp_Image_Instance *ii, unsigned char* bmp_data; int bmp_bits; COLORREF bkcolor; + int slice; if (!DEVICE_MSWINDOWS_P (XDEVICE (device))) signal_simple_error ("Not an mswindows device", device); @@ -380,21 +410,29 @@ mswindows_init_image_instance_from_eimage (struct Lisp_Image_Instance *ii, bkcolor = COLOR_INSTANCE_MSWINDOWS_COLOR (XCOLOR_INSTANCE (FACE_BACKGROUND (Vdefault_face, domain))); - /* build a bitmap from the eimage */ - if (!(bmp_info=convert_EImage_to_DIBitmap (device, width, height, eimage, - &bmp_bits, &bmp_data))) + for (slice = 0; slice < slices; slice++) { - signal_simple_error ("EImage to DIBitmap conversion failed", - instantiator); - } - - /* Now create the pixmap and set up the image instance */ - init_image_instance_from_dibitmap (ii, bmp_info, dest_mask, - bmp_data, bmp_bits, instantiator, - 0, 0, 0); + /* build a bitmap from the eimage */ + if (!(bmp_info=convert_EImage_to_DIBitmap (device, width, height, + eimage + (width * height * 3 * slice), + &bmp_bits, &bmp_data))) + { + signal_simple_error ("EImage to DIBitmap conversion failed", + instantiator); + } - xfree (bmp_info); - xfree (bmp_data); + /* Now create the pixmap and set up the image instance */ + if (slice == 0) + init_image_instance_from_dibitmap (ii, bmp_info, dest_mask, + bmp_data, bmp_bits, slices, instantiator, + 0, 0, 0); + else + image_instance_add_dibitmap (ii, bmp_info, bmp_data, bmp_bits, slice, + instantiator); + + xfree (bmp_info); + xfree (bmp_data); + } } static void set_mono_pixel ( unsigned char* bits, @@ -923,7 +961,7 @@ mswindows_xpm_instantiate (Lisp_Object image_instance, /* Now create the pixmap and set up the image instance */ init_image_instance_from_dibitmap (ii, bmp_info, dest_mask, - bmp_data, bmp_bits, instantiator, + bmp_data, bmp_bits, 1, instantiator, x_hot, y_hot, transp); xfree (bmp_info); @@ -986,7 +1024,7 @@ bmp_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, /* Now create the pixmap and set up the image instance */ init_image_instance_from_dibitmap (ii, bmp_info, dest_mask, - bmp_data, bmp_bits, instantiator, + bmp_data, bmp_bits, 1, instantiator, 0, 0, 0); } @@ -1241,7 +1279,7 @@ mswindows_resource_instantiate (Lisp_Object image_instance, Lisp_Object instanti if (hinst) FreeLibrary (hinst); - mswindows_initialize_dibitmap_image_instance (ii, iitype); + mswindows_initialize_dibitmap_image_instance (ii, 1, iitype); IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = file; IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = @@ -1723,7 +1761,7 @@ init_image_instance_from_xbm_inline (struct Lisp_Image_Instance *ii, IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK | IMAGE_POINTER_MASK); - mswindows_initialize_dibitmap_image_instance (ii, type); + mswindows_initialize_dibitmap_image_instance (ii, 1, type); IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = find_keyword_in_vector (instantiator, Q_file); @@ -1984,6 +2022,10 @@ mswindows_print_image_instance (struct Lisp_Image_Instance *p, } } +#ifdef DEBUG_WIDGETS +extern int debug_widget_instances; +#endif + static void mswindows_finalize_image_instance (struct Lisp_Image_Instance *p) { @@ -1993,15 +2035,34 @@ mswindows_finalize_image_instance (struct Lisp_Image_Instance *p) || IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW) { +#ifdef DEBUG_WIDGETS + debug_widget_instances--; + stderr_out ("widget destroyed, %d left\n", debug_widget_instances); +#endif if (IMAGE_INSTANCE_SUBWINDOW_ID (p)) - DestroyWindow (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p)); - IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0; + { + DestroyWindow (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p)); + DestroyWindow (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p)); + IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0; + } } else if (p->data) { - if (IMAGE_INSTANCE_MSWINDOWS_BITMAP (p)) - DeleteObject (IMAGE_INSTANCE_MSWINDOWS_BITMAP (p)); - IMAGE_INSTANCE_MSWINDOWS_BITMAP (p) = 0; + int i; + if (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p)) + disable_glyph_animated_timeout (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p)); + + if (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (p)) + { + for (i = 0; i < IMAGE_INSTANCE_PIXMAP_MAXSLICE (p); i++) + { + if (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (p, i)) + DeleteObject (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (p, i)); + IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (p, i) = 0; + } + xfree (IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (p)); + IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (p) = 0; + } if (IMAGE_INSTANCE_MSWINDOWS_MASK (p)) DeleteObject (IMAGE_INSTANCE_MSWINDOWS_MASK (p)); IMAGE_INSTANCE_MSWINDOWS_MASK (p) = 0; @@ -2029,31 +2090,46 @@ mswindows_unmap_subwindow (struct Lisp_Image_Instance *p) { if (IMAGE_INSTANCE_SUBWINDOW_ID (p)) { - SetWindowPos (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), + SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p), NULL, 0, 0, 0, 0, - SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE - | SWP_NOCOPYBITS | SWP_NOSENDCHANGING); + SWP_HIDEWINDOW | SWP_NOMOVE | SWP_NOSIZE + | SWP_NOSENDCHANGING); } } /* map the subwindow. This is used by redisplay via redisplay_output_subwindow */ static void -mswindows_map_subwindow (struct Lisp_Image_Instance *p, int x, int y) +mswindows_map_subwindow (struct Lisp_Image_Instance *p, int x, int y, + struct display_glyph_area* dga) { - /* ShowWindow (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), SW_SHOW);*/ - SetWindowPos (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), + /* move the window before mapping it ... */ + SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p), NULL, - x, y, 0, 0, - SWP_NOZORDER | SWP_SHOWWINDOW | SWP_NOSIZE + x, y, dga->width, dga->height, + SWP_NOZORDER | SWP_NOCOPYBITS | SWP_NOSENDCHANGING); + /* ... adjust the child ... */ + SetWindowPos (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), + NULL, + -dga->xoffset, -dga->yoffset, 0, 0, + SWP_NOZORDER | SWP_NOSIZE + | SWP_NOCOPYBITS | SWP_NOSENDCHANGING); + /* ... now map it - we are not allowed to move it at the same time. */ + SetWindowPos (IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (p), + NULL, + 0, 0, 0, 0, + SWP_NOZORDER | SWP_NOSIZE | SWP_NOMOVE + | SWP_SHOWWINDOW | SWP_NOCOPYBITS + | SWP_NOSENDCHANGING); } /* resize the subwindow instance */ static void mswindows_resize_subwindow (struct Lisp_Image_Instance* ii, int w, int h) { + /* Set the size of the control .... */ SetWindowPos (WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii), NULL, 0, 0, w, h, @@ -2071,13 +2147,23 @@ mswindows_update_subwindow (struct Lisp_Image_Instance *p) /* buttons checked or otherwise */ if ( EQ (IMAGE_INSTANCE_WIDGET_TYPE (p), Qbutton)) { - if (gui_item_selected_p (IMAGE_INSTANCE_WIDGET_SINGLE_ITEM (p))) + if (gui_item_selected_p (IMAGE_INSTANCE_WIDGET_ITEM (p))) SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), BM_SETCHECK, (WPARAM)BST_CHECKED, 0); else SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), BM_SETCHECK, (WPARAM)BST_UNCHECKED, 0); } + + /* set the widget font from the widget face */ + SendMessage (WIDGET_INSTANCE_MSWINDOWS_HANDLE (p), + WM_SETFONT, + (WPARAM)FONT_INSTANCE_MSWINDOWS_HFONT + (XFONT_INSTANCE (widget_face_font_info + (IMAGE_INSTANCE_SUBWINDOW_FRAME (p), + IMAGE_INSTANCE_WIDGET_FACE (p), + 0, 0))), + MAKELPARAM (TRUE, 0)); } } @@ -2101,7 +2187,7 @@ mswindows_register_gui_item (Lisp_Object gui, Lisp_Object domain) static int mswindows_register_widget_instance (Lisp_Object instance, Lisp_Object domain) { - return mswindows_register_gui_item (XIMAGE_INSTANCE_WIDGET_SINGLE_ITEM (instance), + return mswindows_register_gui_item (XIMAGE_INSTANCE_WIDGET_ITEM (instance), domain); } @@ -2122,6 +2208,26 @@ mswindows_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instant /* have to set the type this late in case there is no device instantiation for a widget */ IMAGE_INSTANCE_TYPE (ii) = IMAGE_SUBWINDOW; + /* Allocate space for the clip window */ + ii->data = xnew_and_zero (struct mswindows_subwindow_data); + + if ((IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii) + = CreateWindowEx( + 0, /* EX flags */ + XEMACS_CONTROL_CLASS, + 0, /* text */ + WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_CHILD, + 0, /* starting x position */ + 0, /* starting y position */ + IMAGE_INSTANCE_WIDGET_WIDTH (ii), + IMAGE_INSTANCE_WIDGET_HEIGHT (ii), + /* parent window */ + FRAME_MSWINDOWS_HANDLE (XFRAME (frame)), + NULL, /* No menu */ + NULL, /* must be null for this class */ + NULL)) == NULL) + signal_simple_error ("window creation failed with code", + make_int (GetLastError())); wnd = CreateWindow( "STATIC", "", @@ -2130,7 +2236,7 @@ mswindows_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instant 0, /* starting y position */ IMAGE_INSTANCE_WIDGET_WIDTH (ii), IMAGE_INSTANCE_WIDGET_HEIGHT (ii), - FRAME_MSWINDOWS_HANDLE (XFRAME (frame)), /* parent window */ + IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii), 0, (HINSTANCE) GetWindowLong (FRAME_MSWINDOWS_HANDLE (XFRAME (frame)), @@ -2185,6 +2291,7 @@ mswindows_image_instance_hash (struct Lisp_Image_Instance *p, int depth) static void mswindows_initialize_dibitmap_image_instance (struct Lisp_Image_Instance *ii, + int slices, enum image_instance_type type) { ii->data = xnew_and_zero (struct mswindows_image_instance_data); @@ -2195,9 +2302,14 @@ mswindows_initialize_dibitmap_image_instance (struct Lisp_Image_Instance *ii, IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (ii) = Qnil; IMAGE_INSTANCE_PIXMAP_FG (ii) = Qnil; IMAGE_INSTANCE_PIXMAP_BG (ii) = Qnil; + IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) = slices; + IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (ii) = + xnew_array_and_zero (HBITMAP, slices); } +#ifdef HAVE_WIDGETS + /************************************************************************/ /* widgets */ /************************************************************************/ @@ -2207,11 +2319,8 @@ mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiat int dest_mask, Lisp_Object domain, CONST char* class, int flags, int exflags) { + /* this function can call lisp */ struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); -#if 0 - struct Lisp_Image_Instance *groupii = 0; - Lisp_Object group = find_keyword_in_vector (instantiator, Q_group); -#endif Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii), style; struct device* d = XDEVICE (device); Lisp_Object frame = FW_FRAME (domain); @@ -2223,17 +2332,7 @@ mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiat if (!DEVICE_MSWINDOWS_P (d)) signal_simple_error ("Not an mswindows device", device); -#if 0 - /* if the user specified another glyph as a group pick up the - instance in our domain. */ - if (!NILP (group)) - { - if (SYMBOLP (group)) - group = XSYMBOL (group)->value; - group = glyph_image_instance (group, domain, ERROR_ME, 1); - groupii = XIMAGE_INSTANCE (group); - } -#endif + if (!gui_item_active_p (gui)) flags |= WS_DISABLED; @@ -2249,22 +2348,46 @@ mswindows_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiat if (!NILP (IMAGE_INSTANCE_WIDGET_TEXT (ii))) GET_C_STRING_OS_DATA_ALLOCA (IMAGE_INSTANCE_WIDGET_TEXT (ii), nm); - wnd = CreateWindowEx( - exflags /* | WS_EX_NOPARENTNOTIFY*/, - class, - nm, - flags | WS_CHILD, - 0, /* starting x position */ - 0, /* starting y position */ - IMAGE_INSTANCE_WIDGET_WIDTH (ii), - IMAGE_INSTANCE_WIDGET_HEIGHT (ii), - /* parent window */ - FRAME_MSWINDOWS_HANDLE (XFRAME (frame)), - (HMENU)id, /* No menu */ - (HINSTANCE) - GetWindowLong (FRAME_MSWINDOWS_HANDLE (XFRAME (frame)), - GWL_HINSTANCE), - NULL); + /* allocate space for the clip window and then allocate the clip window */ + ii->data = xnew_and_zero (struct mswindows_subwindow_data); + + if ((IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii) + = CreateWindowEx( + 0, /* EX flags */ + XEMACS_CONTROL_CLASS, + 0, /* text */ + WS_CLIPCHILDREN | WS_CLIPSIBLINGS | WS_CHILD, + 0, /* starting x position */ + 0, /* starting y position */ + IMAGE_INSTANCE_WIDGET_WIDTH (ii), + IMAGE_INSTANCE_WIDGET_HEIGHT (ii), + /* parent window */ + FRAME_MSWINDOWS_HANDLE (XFRAME (frame)), + (HMENU)id, /* No menu */ + NULL, /* must be null for this class */ + NULL)) == NULL) + signal_simple_error ("window creation failed with code", + make_int (GetLastError())); + + if ((wnd = CreateWindowEx( + exflags /* | WS_EX_NOPARENTNOTIFY*/, + class, + nm, + flags | WS_CHILD | WS_VISIBLE, + 0, /* starting x position */ + 0, /* starting y position */ + IMAGE_INSTANCE_WIDGET_WIDTH (ii), + IMAGE_INSTANCE_WIDGET_HEIGHT (ii), + /* parent window */ + IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (ii), + (HMENU)id, /* No menu */ + (HINSTANCE) + GetWindowLong + (FRAME_MSWINDOWS_HANDLE (XFRAME (frame)), + GWL_HINSTANCE), + NULL)) == NULL) + signal_simple_error ("window creation failed with code", + make_int (GetLastError())); IMAGE_INSTANCE_SUBWINDOW_ID (ii) = wnd; SetWindowLong (wnd, GWL_USERDATA, (LONG)LISP_TO_VOID(image_instance)); @@ -2289,6 +2412,7 @@ mswindows_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiat Lisp_Object pointer_fg, Lisp_Object pointer_bg, int dest_mask, Lisp_Object domain) { + /* this function can call lisp */ struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); HWND wnd; int flags = BS_NOTIFY; @@ -2392,7 +2516,7 @@ mswindows_progress_gauge_instantiate (Lisp_Object image_instance, Lisp_Object in /* instantiate a tree view widget */ static HTREEITEM add_tree_item (Lisp_Object image_instance, - HWND wnd, HTREEITEM parent, Lisp_Object entry, + HWND wnd, HTREEITEM parent, Lisp_Object item, int children, Lisp_Object domain) { TV_INSERTSTRUCT tvitem; @@ -2403,39 +2527,21 @@ static HTREEITEM add_tree_item (Lisp_Object image_instance, tvitem.item.mask = TVIF_TEXT | TVIF_CHILDREN; tvitem.item.cChildren = children; - if (VECTORP (entry)) - { - /* we always maintain the real gui item at the head of the - list. We have to put them in the list in the first place - because the whole model assumes that the glyph instances have - references to all the associated data. If we didn't do this - GC would bite us badly. */ - Lisp_Object gui = gui_parse_item_keywords_no_errors (entry); - if (CONSP (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance))) - { - Lisp_Object rest = - Fcons (gui, XCDR (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance))); - Fsetcdr (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance), rest); - } - else - { - XIMAGE_INSTANCE_WIDGET_ITEM (image_instance) = - Fcons (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance), gui); - } - - tvitem.item.lParam = mswindows_register_gui_item (gui, domain); + if (GUI_ITEMP (item)) + { + tvitem.item.lParam = mswindows_register_gui_item (item, domain); tvitem.item.mask |= TVIF_PARAM; - GET_C_STRING_OS_DATA_ALLOCA (XGUI_ITEM (gui)->name, + GET_C_STRING_OS_DATA_ALLOCA (XGUI_ITEM (item)->name, tvitem.item.pszText); } else - GET_C_STRING_OS_DATA_ALLOCA (entry, tvitem.item.pszText); + GET_C_STRING_OS_DATA_ALLOCA (item, tvitem.item.pszText); tvitem.item.cchTextMax = strlen (tvitem.item.pszText); if ((ret = (HTREEITEM)SendMessage (wnd, TVM_INSERTITEM, 0, (LPARAM)&tvitem)) == 0) - signal_simple_error ("error adding tree view entry", entry); + signal_simple_error ("error adding tree view entry", item); return ret; } @@ -2476,12 +2582,13 @@ mswindows_tree_view_instantiate (Lisp_Object image_instance, Lisp_Object instant wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii); /* define a root */ - parent = add_tree_item (image_instance, - wnd, NULL, IMAGE_INSTANCE_WIDGET_TEXT (ii), TRUE, - domain); + parent = add_tree_item (image_instance, wnd, NULL, + XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)), + TRUE, domain); /* recursively add items to the tree view */ - LIST_LOOP (rest, Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), Q_items, Qnil)) + /* add items to the tab */ + LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))) { if (LISTP (XCAR (rest))) add_tree_item_list (image_instance, wnd, parent, XCAR (rest), domain); @@ -2492,46 +2599,31 @@ mswindows_tree_view_instantiate (Lisp_Object image_instance, Lisp_Object instant /* instantiate a tab control */ static TC_ITEM* add_tab_item (Lisp_Object image_instance, - HWND wnd, Lisp_Object entry, + HWND wnd, Lisp_Object item, Lisp_Object domain, int index) { TC_ITEM tvitem, *ret; tvitem.mask = TCIF_TEXT; - if (VECTORP (entry)) - { - /* we always maintain the real gui item at the head of the - list. We have to put them in the list in the first place - because the whole model assumes that the glyph instances have - references to all the associated data. If we didn't do this - GC would bite us badly. */ - Lisp_Object gui = gui_parse_item_keywords_no_errors (entry); - if (CONSP (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance))) - { - Lisp_Object rest = - Fcons (gui, XCDR (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance))); - Fsetcdr (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance), rest); - } - else - { - XIMAGE_INSTANCE_WIDGET_ITEM (image_instance) = - Fcons (XIMAGE_INSTANCE_WIDGET_ITEM (image_instance), gui); - } - - tvitem.lParam = mswindows_register_gui_item (gui, domain); + if (GUI_ITEMP (item)) + { + tvitem.lParam = mswindows_register_gui_item (item, domain); tvitem.mask |= TCIF_PARAM; - GET_C_STRING_OS_DATA_ALLOCA (XGUI_ITEM (gui)->name, + GET_C_STRING_OS_DATA_ALLOCA (XGUI_ITEM (item)->name, tvitem.pszText); } else - GET_C_STRING_OS_DATA_ALLOCA (entry, tvitem.pszText); + { + CHECK_STRING (item); + GET_C_STRING_OS_DATA_ALLOCA (item, tvitem.pszText); + } tvitem.cchTextMax = strlen (tvitem.pszText); if ((ret = (TC_ITEM*)SendMessage (wnd, TCM_INSERTITEM, index, (LPARAM)&tvitem)) < 0) - signal_simple_error ("error adding tab entry", entry); + signal_simple_error ("error adding tab entry", item); return ret; } @@ -2553,7 +2645,7 @@ mswindows_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object insta wnd = WIDGET_INSTANCE_MSWINDOWS_HANDLE (ii); /* add items to the tab */ - LIST_LOOP (rest, Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), Q_items, Qnil)) + LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))) { add_tab_item (image_instance, wnd, XCAR (rest), domain, index); index++; @@ -2577,8 +2669,12 @@ mswindows_tab_control_set_property (Lisp_Object image_instance, Lisp_Object prop /* delete the pre-existing items */ SendMessage (wnd, TCM_DELETEALLITEMS, 0, 0); + IMAGE_INSTANCE_WIDGET_ITEMS (ii) = + Fcons (XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)), + parse_gui_item_tree_children (val)); + /* add items to the tab */ - LIST_LOOP (rest, val) + LIST_LOOP (rest, XCDR (IMAGE_INSTANCE_WIDGET_ITEMS (ii))) { add_tab_item (image_instance, wnd, XCAR (rest), IMAGE_INSTANCE_SUBWINDOW_FRAME (ii), index); @@ -2601,20 +2697,6 @@ mswindows_label_instantiate (Lisp_Object image_instance, Lisp_Object instantiato 0, WS_EX_STATICEDGE); } -#if 0 -/* instantiate a static control possible for putting other things in */ -static void -mswindows_group_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, - Lisp_Object pointer_fg, Lisp_Object pointer_bg, - int dest_mask, Lisp_Object domain) -{ - mswindows_widget_instantiate (image_instance, instantiator, pointer_fg, - pointer_bg, dest_mask, domain, "BUTTON", - WS_GROUP | BS_GROUPBOX | WS_BORDER, - WS_EX_CLIENTEDGE ); -} -#endif - /* instantiate a scrollbar control */ static void mswindows_scrollbar_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, @@ -2636,6 +2718,10 @@ mswindows_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instant struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); HANDLE wnd; Lisp_Object rest; + Lisp_Object data = Fplist_get (find_keyword_in_vector (instantiator, Q_properties), + Q_items, Qnil); + int len; + GET_LIST_LENGTH (data, len); /* Maybe ought to generalise this more but it may be very windows specific. In windows the window height of a combo box is the @@ -2643,6 +2729,9 @@ mswindows_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instant before creating the window and then reset it to a single line after the window is created so that redisplay does the right thing. */ + widget_instantiate_1 (image_instance, instantiator, pointer_fg, + pointer_bg, dest_mask, domain, len + 1, 0, 0); + mswindows_widget_instantiate (image_instance, instantiator, pointer_fg, pointer_bg, dest_mask, domain, "COMBOBOX", WS_BORDER | WS_TABSTOP | CBS_DROPDOWN @@ -2754,6 +2843,28 @@ mswindows_progress_gauge_set_property (Lisp_Object image_instance, Lisp_Object p return Qunbound; } +LRESULT WINAPI +mswindows_control_wnd_proc (HWND hwnd, UINT message, + WPARAM wParam, LPARAM lParam) +{ + switch (message) + { + case WM_NOTIFY: + case WM_COMMAND: + case WM_CTLCOLORBTN: + case WM_CTLCOLORLISTBOX: + case WM_CTLCOLOREDIT: + case WM_CTLCOLORSTATIC: + case WM_CTLCOLORSCROLLBAR: + + return mswindows_wnd_proc (GetParent (hwnd), message, wParam, lParam); + default: + return DefWindowProc (hwnd, message, wParam, lParam); + } +} + +#endif /* HAVE_WIDGETS */ + /************************************************************************/ /* initialization */ @@ -2788,6 +2899,7 @@ image_instantiator_format_create_glyphs_mswindows (void) { IIFORMAT_VALID_CONSOLE (mswindows, nothing); IIFORMAT_VALID_CONSOLE (mswindows, string); + IIFORMAT_VALID_CONSOLE (mswindows, layout); IIFORMAT_VALID_CONSOLE (mswindows, formatted_string); IIFORMAT_VALID_CONSOLE (mswindows, inherit); /* image-instantiator types */ @@ -2813,6 +2925,7 @@ image_instantiator_format_create_glyphs_mswindows (void) #ifdef HAVE_GIF IIFORMAT_VALID_CONSOLE (mswindows, gif); #endif +#ifdef HAVE_WIDGETS /* button widget */ INITIALIZE_DEVICE_IIFORMAT (mswindows, button); IIFORMAT_HAS_DEVMETHOD (mswindows, button, property); @@ -2827,10 +2940,7 @@ image_instantiator_format_create_glyphs_mswindows (void) INITIALIZE_DEVICE_IIFORMAT (mswindows, widget); IIFORMAT_HAS_DEVMETHOD (mswindows, widget, property); IIFORMAT_HAS_DEVMETHOD (mswindows, widget, set_property); -#if 0 - INITIALIZE_DEVICE_IIFORMAT (mswindows, group); - IIFORMAT_HAS_DEVMETHOD (mswindows, group, instantiate); -#endif + /* label */ INITIALIZE_DEVICE_IIFORMAT (mswindows, label); IIFORMAT_HAS_DEVMETHOD (mswindows, label, instantiate); @@ -2858,7 +2968,7 @@ image_instantiator_format_create_glyphs_mswindows (void) INITIALIZE_DEVICE_IIFORMAT (mswindows, tab_control); IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, instantiate); IIFORMAT_HAS_DEVMETHOD (mswindows, tab_control, set_property); - +#endif /* windows bitmap format */ INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (bmp, "bmp"); IIFORMAT_HAS_METHOD (bmp, validate); diff --git a/src/glyphs-msw.h b/src/glyphs-msw.h index 8371d0a..3783c90 100644 --- a/src/glyphs-msw.h +++ b/src/glyphs-msw.h @@ -34,8 +34,7 @@ Boston, MA 02111-1307, USA. */ struct mswindows_image_instance_data { - HBITMAP bitmap; - HBITMAP mask; + HBITMAP* bitmaps; HICON icon; }; @@ -43,14 +42,22 @@ struct mswindows_image_instance_data ((struct mswindows_image_instance_data *) (i)->data) #define IMAGE_INSTANCE_MSWINDOWS_BITMAP(i) \ - (MSWINDOWS_IMAGE_INSTANCE_DATA (i)->bitmap) + (MSWINDOWS_IMAGE_INSTANCE_DATA (i)->bitmaps[0]) +#define IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE(i,slice) \ + (MSWINDOWS_IMAGE_INSTANCE_DATA (i)->bitmaps[slice]) +#define IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES(i) \ + (MSWINDOWS_IMAGE_INSTANCE_DATA (i)->bitmaps) #define IMAGE_INSTANCE_MSWINDOWS_MASK(i) \ - (MSWINDOWS_IMAGE_INSTANCE_DATA (i)->mask) + (HBITMAP)(IMAGE_INSTANCE_PIXMAP_MASK (i)) #define IMAGE_INSTANCE_MSWINDOWS_ICON(i) \ (MSWINDOWS_IMAGE_INSTANCE_DATA (i)->icon) #define XIMAGE_INSTANCE_MSWINDOWS_BITMAP(i) \ IMAGE_INSTANCE_MSWINDOWS_BITMAP (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE(i,slice) \ + IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE (XIMAGE_INSTANCE (i,slice)) +#define XIMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES(i) \ + IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICES (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_MSWINDOWS_MASK(i) \ IMAGE_INSTANCE_MSWINDOWS_MASK (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_MSWINDOWS_ICON(i) \ @@ -78,5 +85,19 @@ mswindows_initialize_image_instance_icon (struct Lisp_Image_Instance* image, #define XWIDGET_INSTANCE_MSWINDOWS_HANDLE(i) \ WIDGET_INSTANCE_MSWINDOWS_HANDLE (XIMAGE_INSTANCE (i)) +struct mswindows_subwindow_data +{ + HWND clip_window; +}; + +#define MSWINDOWS_SUBWINDOW_DATA(i) \ +((struct mswindows_subwindow_data *) (i)->data) + +#define IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW(i) \ + (MSWINDOWS_SUBWINDOW_DATA (i)->clip_window) + +#define XIMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW(i) \ + IMAGE_INSTANCE_MSWINDOWS_CLIPWINDOW (XIMAGE_INSTANCE (i)) + #endif /* HAVE_MS_WINDOWS */ #endif /* _XEMACS_GLYPHS_MSW_H_ */ diff --git a/src/glyphs-widget.c b/src/glyphs-widget.c index 917739d..69c3efe 100644 --- a/src/glyphs-widget.c +++ b/src/glyphs-widget.c @@ -1,5 +1,5 @@ /* Widget-specific glyph objects. - Copyright (C) 1998 Andy Piper + Copyright (C) 1998, 1999 Andy Piper. This file is part of XEmacs. @@ -45,10 +45,6 @@ Lisp_Object Qedit_field; DEFINE_IMAGE_INSTANTIATOR_FORMAT (scrollbar); Lisp_Object Qscrollbar; DEFINE_IMAGE_INSTANTIATOR_FORMAT (widget); -#if 0 -DEFINE_IMAGE_INSTANTIATOR_FORMAT (group); -Lisp_Object Qgroup; -#endif DEFINE_IMAGE_INSTANTIATOR_FORMAT (label); Lisp_Object Qlabel; DEFINE_IMAGE_INSTANTIATOR_FORMAT (progress_gauge); @@ -57,13 +53,20 @@ DEFINE_IMAGE_INSTANTIATOR_FORMAT (tree_view); Lisp_Object Qtree_view; DEFINE_IMAGE_INSTANTIATOR_FORMAT (tab_control); Lisp_Object Qtab_control; +DEFINE_IMAGE_INSTANTIATOR_FORMAT (layout); +Lisp_Object Qlayout; Lisp_Object Q_descriptor, Q_height, Q_width, Q_properties, Q_items; -Lisp_Object Q_image, Q_text, Q_percent; +Lisp_Object Q_image, Q_text, Q_percent, Q_orientation, Q_justify, Q_border; +Lisp_Object Qetched_in, Qetched_out, Qbevel_in, Qbevel_out; -#define WIDGET_BORDER_HEIGHT 2 +#define WIDGET_BORDER_HEIGHT 4 #define WIDGET_BORDER_WIDTH 4 +#ifdef DEBUG_WIDGETS +int debug_widget_instances; +#endif + /* TODO: - more complex controls. - tooltips for controls. @@ -96,7 +99,7 @@ widget_text_to_pixel_conversion (Lisp_Object domain, Lisp_Object face, int ch=0, cw=0; widget_face_font_info (domain, face, &ch, &cw); if (height) - *height = th * (ch + 2 * WIDGET_BORDER_HEIGHT); + *height = th * ch + 2 * WIDGET_BORDER_HEIGHT; if (width) *width = tw * cw + 2 * WIDGET_BORDER_WIDTH; } @@ -108,7 +111,7 @@ widget_possible_dest_types (void) } static void -check_valid_glyph_or_image (Lisp_Object data) +check_valid_glyph_or_instantiator (Lisp_Object data) { Lisp_Object glyph = data; if (SYMBOLP (data)) @@ -116,11 +119,36 @@ check_valid_glyph_or_image (Lisp_Object data) if (IMAGE_INSTANCEP (glyph)) CHECK_IMAGE_INSTANCE (glyph); - else if (!CONSP (glyph)) + else if (!CONSP (glyph) && !VECTORP (glyph)) CHECK_BUFFER_GLYPH (glyph); } static void +check_valid_orientation (Lisp_Object data) +{ + if (!EQ (data, Qhorizontal) + && + !EQ (data, Qvertical)) + signal_simple_error ("unknown orientation for layout", data); +} + +static void +check_valid_justification (Lisp_Object data) +{ + if (!EQ (data, Qleft) && !EQ (data, Qright) && !EQ (data, Qcenter)) + signal_simple_error ("unknown justification for layout", data); +} + +static void +check_valid_border (Lisp_Object data) +{ + if (!EQ (data, Qt) && !EQ (data, Qetched_in) && !EQ (data, Qetched_out) + && !EQ (data, Qbevel_in) && !EQ (data, Qbevel_out) + && !GLYPHP (data) && !VECTORP (data)) + signal_simple_error ("unknown border style for layout", data); +} + +static void check_valid_anything (Lisp_Object data) { } @@ -179,6 +207,58 @@ check_valid_item_list (Lisp_Object data) check_valid_item_list_1 (items); } +static void +check_valid_glyph_or_instantiator_list (Lisp_Object data) +{ + Lisp_Object rest; + + CHECK_LIST (data); + EXTERNAL_LIST_LOOP (rest, data) + { + check_valid_glyph_or_instantiator (XCAR (rest)); + } +} + +static Lisp_Object +glyph_instantiator_to_glyph (Lisp_Object sym) +{ + /* This function calls lisp. */ + Lisp_Object glyph = sym; + struct gcpro gcpro1; + + GCPRO1 (glyph); + /* if we have a symbol get at the actual data */ + if (SYMBOLP (glyph)) + glyph = XSYMBOL (glyph)->value; + + if (CONSP (glyph)) + glyph = Feval (glyph); + + /* Be really helpful to the user. */ + if (VECTORP (glyph)) + { + glyph = call1 (intern ("make-glyph"), glyph); + } + + /* substitute the new glyph */ + RETURN_UNGCPRO (glyph); +} + +static void +substitute_keyword_value (Lisp_Object inst, Lisp_Object key, Lisp_Object val) +{ + int i; + /* substitute the new glyph */ + for (i = 0; i < XVECTOR_LENGTH (inst); i++) + { + if (EQ (key, XVECTOR_DATA (inst)[i])) + { + XVECTOR_DATA (inst)[i+1] = val; + break; + } + } +} + /* wire widget property invocations to specific widgets ... The problem we are solving here is that when instantiators get converted to instances they lose some type information (they just become @@ -289,25 +369,9 @@ widget_normalize (Lisp_Object inst, Lisp_Object console_type) same reasons we normalize file to data. */ if (!NILP (glyph)) { - int i; - struct gcpro gcpro1; - if (SYMBOLP (glyph)) - glyph = XSYMBOL (glyph)->value; - GCPRO1 (glyph); - - if (CONSP (glyph)) - glyph = Feval (glyph); - /* substitute the new glyph */ - for (i = 0; i < XVECTOR_LENGTH (inst); i++) - { - if (EQ (Q_image, XVECTOR_DATA (inst)[i])) - { - XVECTOR_DATA (inst)[i+1] = glyph; - break; - } - } - UNGCPRO; + substitute_keyword_value (inst, Q_image, glyph_instantiator_to_glyph (glyph)); } + return inst; } @@ -318,7 +382,7 @@ initialize_widget_image_instance (struct Lisp_Image_Instance *ii, Lisp_Object ty IMAGE_INSTANCE_WIDGET_TYPE (ii) = type; IMAGE_INSTANCE_WIDGET_PROPS (ii) = Qnil; IMAGE_INSTANCE_WIDGET_FACE (ii) = Vwidget_face; - IMAGE_INSTANCE_WIDGET_ITEM (ii) = allocate_gui_item (); + IMAGE_INSTANCE_WIDGET_ITEMS (ii) = allocate_gui_item (); } /* Instantiate a button widget. Unfortunately instantiated widgets are @@ -327,7 +391,7 @@ initialize_widget_image_instance (struct Lisp_Image_Instance *ii, Lisp_Object ty want to display it in and BitBlt it. So image instances can have a many-to-one relationship with things you see, whereas widgets can only be one-to-one (i.e. per frame) */ -static void +void widget_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator, Lisp_Object pointer_fg, Lisp_Object pointer_bg, int dest_mask, Lisp_Object domain, int default_textheight, @@ -341,6 +405,7 @@ widget_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator, Lisp_Object pixheight = find_keyword_in_vector (instantiator, Q_pixel_height); Lisp_Object desc = find_keyword_in_vector (instantiator, Q_descriptor); Lisp_Object glyph = find_keyword_in_vector (instantiator, Q_image); + Lisp_Object props = find_keyword_in_vector (instantiator, Q_properties); int pw=0, ph=0, tw=0, th=0; /* this just does pixel type sizing */ @@ -357,8 +422,7 @@ widget_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator, IMAGE_INSTANCE_WIDGET_FACE (ii) = Fget_face (face); /* data items for some widgets */ - IMAGE_INSTANCE_WIDGET_PROPS (ii) = - find_keyword_in_vector (instantiator, Q_properties); + IMAGE_INSTANCE_WIDGET_PROPS (ii) = props; /* retrieve the gui item information. This is easy if we have been provided with a vector, more difficult if we have just been given @@ -366,14 +430,24 @@ widget_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator, if (STRINGP (desc) || NILP (desc)) { /* big cheat - we rely on the fact that a gui item looks like an instantiator */ - IMAGE_INSTANCE_WIDGET_ITEM (ii) = + IMAGE_INSTANCE_WIDGET_ITEMS (ii) = gui_parse_item_keywords_no_errors (instantiator); IMAGE_INSTANCE_WIDGET_TEXT (ii) = desc; } else - IMAGE_INSTANCE_WIDGET_ITEM (ii) = + IMAGE_INSTANCE_WIDGET_ITEMS (ii) = gui_parse_item_keywords_no_errors (desc); + /* parse more gui items out of the properties */ + if (!NILP (props)) + { + Lisp_Object items = Fplist_get (props, Q_items, Qnil); + if (!NILP (items)) + IMAGE_INSTANCE_WIDGET_ITEMS (ii) = + Fcons (IMAGE_INSTANCE_WIDGET_ITEMS (ii), + parse_gui_item_tree_children (items)); + } + /* normalize size information */ if (!NILP (width)) tw = XINT (width); @@ -421,6 +495,12 @@ widget_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator, IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = pw; IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii) = ph; +#ifdef DEBUG_WIDGETS + debug_widget_instances++; + stderr_out ("instantiated "); + debug_print (instantiator); + stderr_out ("%d widgets instantiated\n", debug_widget_instances); +#endif } static void @@ -432,11 +512,11 @@ widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, pointer_bg, dest_mask, domain, 1, 0, 0); } -/* combo-box generic instantiation - get he heigh right */ +/* tree-view generic instantiation - get the height right */ static void -combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, - Lisp_Object pointer_fg, Lisp_Object pointer_bg, - int dest_mask, Lisp_Object domain) +tree_view_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) { Lisp_Object data = Fplist_get (find_keyword_in_vector (instantiator, Q_properties), Q_items, Qnil); @@ -483,6 +563,209 @@ static_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, } +/***************************************************************************** + * widget layout * + *****************************************************************************/ +static int +layout_possible_dest_types (void) +{ + return IMAGE_LAYOUT_MASK; +} + +/* we need to convert things like glyphs to images, eval expressions + etc.*/ +static Lisp_Object +layout_normalize (Lisp_Object inst, Lisp_Object console_type) +{ + /* This function can call lisp */ + Lisp_Object items = find_keyword_in_vector (inst, Q_items); + Lisp_Object border = find_keyword_in_vector (inst, Q_border); + /* we need to eval glyph if its an expression, we do this for the + same reasons we normalize file to data. */ + if (!NILP (items)) + { + Lisp_Object rest; + LIST_LOOP (rest, items) + { + /* substitute the new glyph */ + Fsetcar (rest, glyph_instantiator_to_glyph (XCAR (rest))); + } + } + /* normalize the border spec. */ + if (VECTORP (border) || CONSP (border)) + { + substitute_keyword_value (inst, Q_border, glyph_instantiator_to_glyph (border)); + } + return inst; +} + +/* Instantiate a layout widget. */ +static void +layout_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) +{ + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + Lisp_Object rest, device = IMAGE_INSTANCE_DEVICE (ii); + Lisp_Object frame = FW_FRAME (domain); + Lisp_Object items = find_keyword_in_vector (instantiator, Q_items); + Lisp_Object width = find_keyword_in_vector (instantiator, Q_pixel_width); + Lisp_Object height = find_keyword_in_vector (instantiator, Q_pixel_height); + Lisp_Object orient = find_keyword_in_vector (instantiator, Q_orientation); + Lisp_Object justify = find_keyword_in_vector (instantiator, Q_justify); + Lisp_Object border = find_keyword_in_vector (instantiator, Q_border); + Lisp_Object children = Qnil; + int pw = 0, ph = 0, x, y, maxph = 0, maxpw = 0, nitems = 0, + horiz_spacing, vert_spacing, ph_adjust = 0; + + if (NILP (frame)) + signal_simple_error ("No selected frame", device); + + if (!(dest_mask & IMAGE_LAYOUT_MASK)) + incompatible_image_types (instantiator, dest_mask, IMAGE_LAYOUT_MASK); + + if (NILP (orient)) + orient = Qvertical; + + if (EQ (border, Qt)) + border = Qetched_in; + + ii->data = 0; + IMAGE_INSTANCE_TYPE (ii) = IMAGE_LAYOUT; + IMAGE_INSTANCE_SUBWINDOW_ID (ii) = 0; + IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0; + IMAGE_INSTANCE_SUBWINDOW_FRAME (ii) = frame; + IMAGE_INSTANCE_LAYOUT_BORDER (ii) = border; + + /* normalize size information */ + if (!NILP (width)) + pw = XINT (width); + if (!NILP (height)) + ph = XINT (height); + + /* flip through the items to work out how much stuff we have to display */ + LIST_LOOP (rest, items) + { + Lisp_Object glyph = XCAR (rest); + int gheight = glyph_height (glyph, Qnil, DEFAULT_INDEX, domain); + int gwidth = glyph_width (glyph, Qnil, DEFAULT_INDEX, domain); + nitems ++; + if (EQ (orient, Qhorizontal)) + { + maxph = max (maxph, gheight); + maxpw += gwidth; + } + else if (EQ (orient, Qvertical)) + { + maxpw = max (maxpw, gwidth); + maxph += gheight; + } + } + + /* work out spacing between items and bounds of the layout */ + if (!pw) + { + /* No user provided width so we just do default spacing. */ + horiz_spacing = WIDGET_BORDER_WIDTH * 2; + if (EQ (orient, Qhorizontal)) + pw = maxpw + (nitems + 1) * horiz_spacing; + else + pw = maxpw + 2 * horiz_spacing; + } + else if (pw < maxpw) + /* The user wants a smaller space than the largest item, so we + just provide default spacing and will let the output routines + clip.. */ + horiz_spacing = WIDGET_BORDER_WIDTH * 2; + else if (EQ (orient, Qhorizontal)) + /* We have a larger area to display in so distribute the space + evenly. */ + horiz_spacing = (pw - maxpw) / (nitems + 1); + else + horiz_spacing = (pw - maxpw) / 2; + + /* Do the border now so that we can adjust the layout. */ + if (GLYPHP (border)) + { + /* We are going to be sneaky here and add the border text as + just another child, the layout and output routines don't know + this and will just display at the offsets we prescribe. */ + Lisp_Object bglyph = glyph_image_instance (border, domain, ERROR_ME, 1); + + children = Fcons (bglyph, children); + XIMAGE_INSTANCE_XOFFSET (bglyph) = 10; /* Really, what should this be? */ + XIMAGE_INSTANCE_YOFFSET (bglyph) = 0; + + ph_adjust = (glyph_height (border, Qnil, DEFAULT_INDEX, domain) / 2); + IMAGE_INSTANCE_LAYOUT_BORDER (ii) = make_int (ph_adjust); + } + + /* Work out vertical spacings. */ + if (!ph) + { + vert_spacing = WIDGET_BORDER_HEIGHT * 2; + if (EQ (orient, Qvertical)) + ph = maxph + (nitems + 1) * vert_spacing + ph_adjust; + else + ph = maxph + 2 * vert_spacing + ph_adjust; + } + else if (ph < maxph) + vert_spacing = WIDGET_BORDER_HEIGHT * 2; + else if (EQ (orient, Qvertical)) + vert_spacing = (ph - (maxph + ph_adjust)) / (nitems + 1); + else + vert_spacing = (ph - (maxph + ph_adjust)) / 2; + + y = vert_spacing + ph_adjust; + x = horiz_spacing; + + /* Now flip through putting items where we want them, paying + attention to justification. */ + LIST_LOOP (rest, items) + { + /* make sure the image is instantiated */ + Lisp_Object glyph = XCAR (rest); + Lisp_Object gii = glyph_image_instance (glyph, domain, ERROR_ME, 1); + int gwidth = glyph_width (glyph, Qnil, DEFAULT_INDEX, domain); + int gheight = glyph_height (glyph, Qnil, DEFAULT_INDEX, domain); + + children = Fcons (gii, children); + + if (EQ (orient, Qhorizontal)) + { + if (EQ (justify, Qright)) + y = ph - (gheight + vert_spacing); + else if (EQ (justify, Qcenter)) + y = (ph - gheight) / 2; + } + else if (EQ (orient, Qvertical)) + { + if (EQ (justify, Qright)) + x = pw - (gwidth + horiz_spacing); + else if (EQ (justify, Qcenter)) + x = (pw - gwidth) / 2; + } + + XIMAGE_INSTANCE_XOFFSET (gii) = x; + XIMAGE_INSTANCE_YOFFSET (gii) = y; + + if (EQ (orient, Qhorizontal)) + { + x += (gwidth + horiz_spacing); + } + else if (EQ (orient, Qvertical)) + { + y += (gheight + vert_spacing); + } + } + + IMAGE_INSTANCE_LAYOUT_CHILDREN (ii) = children; + assert (pw && ph); + IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii) = pw; + IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii) = ph; +} + + /************************************************************************/ /* initialization */ /************************************************************************/ @@ -498,6 +781,14 @@ syms_of_glyphs_widget (void) defkeyword (&Q_image, ":image"); defkeyword (&Q_percent, ":percent"); defkeyword (&Q_text, ":text"); + defkeyword (&Q_orientation, ":orientation"); + defkeyword (&Q_justify, ":justify"); + defkeyword (&Q_border, ":border"); + + defsymbol (&Qetched_in, "etched-in"); + defsymbol (&Qetched_out, "etched-out"); + defsymbol (&Qbevel_in, "bevel-in"); + defsymbol (&Qbevel_out, "bevel-out"); } void @@ -536,7 +827,8 @@ image_instantiator_format_create_glyphs_widget (void) IIFORMAT_HAS_SHARED_METHOD (button, possible_dest_types, widget); IIFORMAT_HAS_SHARED_METHOD (button, instantiate, widget); IIFORMAT_HAS_SHARED_METHOD (button, normalize, widget); - IIFORMAT_VALID_KEYWORD (button, Q_image, check_valid_glyph_or_image); + IIFORMAT_VALID_KEYWORD (button, + Q_image, check_valid_glyph_or_instantiator); VALID_WIDGET_KEYWORDS (button); VALID_GUI_KEYWORDS (button); @@ -552,7 +844,6 @@ image_instantiator_format_create_glyphs_widget (void) INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (combo_box, "combo-box"); IIFORMAT_HAS_METHOD (combo_box, validate); IIFORMAT_HAS_SHARED_METHOD (combo_box, possible_dest_types, widget); - IIFORMAT_HAS_METHOD (combo_box, instantiate); VALID_GUI_KEYWORDS (combo_box); IIFORMAT_VALID_KEYWORD (combo_box, Q_width, check_valid_int); @@ -576,7 +867,7 @@ image_instantiator_format_create_glyphs_widget (void) INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (progress_gauge, "progress-gauge"); IIFORMAT_HAS_SHARED_METHOD (progress_gauge, validate, widget); IIFORMAT_HAS_SHARED_METHOD (progress_gauge, possible_dest_types, widget); - IIFORMAT_HAS_SHARED_METHOD (progress_gauge, instantiate, combo_box); + IIFORMAT_HAS_SHARED_METHOD (progress_gauge, instantiate, widget); VALID_WIDGET_KEYWORDS (progress_gauge); VALID_GUI_KEYWORDS (progress_gauge); @@ -584,7 +875,7 @@ image_instantiator_format_create_glyphs_widget (void) INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (tree_view, "tree-view"); IIFORMAT_HAS_SHARED_METHOD (tree_view, validate, combo_box); IIFORMAT_HAS_SHARED_METHOD (tree_view, possible_dest_types, widget); - IIFORMAT_HAS_SHARED_METHOD (tree_view, instantiate, combo_box); + IIFORMAT_HAS_METHOD (tree_view, instantiate); VALID_WIDGET_KEYWORDS (tree_view); VALID_GUI_KEYWORDS (tree_view); IIFORMAT_VALID_KEYWORD (tree_view, Q_properties, check_valid_item_list); @@ -605,23 +896,30 @@ image_instantiator_format_create_glyphs_widget (void) VALID_WIDGET_KEYWORDS (label); IIFORMAT_VALID_KEYWORD (label, Q_descriptor, check_valid_string); -#if 0 - /* group */ - INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (group, "group"); - IIFORMAT_HAS_SHARED_METHOD (group, possible_dest_types, widget); - IIFORMAT_HAS_METHOD (group, instantiate); - - IIFORMAT_VALID_KEYWORD (group, Q_width, check_valid_int); - IIFORMAT_VALID_KEYWORD (group, Q_height, check_valid_int); - IIFORMAT_VALID_KEYWORD (group, Q_pixel_width, check_valid_int); - IIFORMAT_VALID_KEYWORD (group, Q_pixel_height, check_valid_int); - IIFORMAT_VALID_KEYWORD (group, Q_face, check_valid_face); - IIFORMAT_VALID_KEYWORD (group, Q_background, check_valid_string); - IIFORMAT_VALID_KEYWORD (group, Q_descriptor, check_valid_string); + /* layout */ + INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (layout, "layout"); + IIFORMAT_HAS_METHOD (layout, possible_dest_types); + IIFORMAT_HAS_METHOD (layout, instantiate); + IIFORMAT_HAS_METHOD (layout, normalize); + IIFORMAT_VALID_KEYWORD (layout, Q_pixel_width, check_valid_int); + IIFORMAT_VALID_KEYWORD (layout, Q_pixel_height, check_valid_int); + IIFORMAT_VALID_KEYWORD (layout, Q_orientation, check_valid_orientation); + IIFORMAT_VALID_KEYWORD (layout, Q_justify, check_valid_justification); + IIFORMAT_VALID_KEYWORD (layout, Q_border, check_valid_border); + IIFORMAT_VALID_KEYWORD (layout, Q_items, + check_valid_glyph_or_instantiator_list); +} + +void +reinit_vars_of_glyphs_widget (void) +{ +#ifdef DEBUG_WIDGETS + debug_widget_instances = 0; #endif } void vars_of_glyphs_widget (void) { + reinit_vars_of_glyphs_widget (); } diff --git a/src/glyphs-x.c b/src/glyphs-x.c index a1f0051..c326e75 100644 --- a/src/glyphs-x.c +++ b/src/glyphs-x.c @@ -40,7 +40,8 @@ Boston, MA 02111-1307, USA. */ Many changes for color work and optimizations by Jareth Hein for 21.0 Switch of GIF/JPEG/PNG to new EImage intermediate code by Jareth Hein for 21.0 TIFF code by Jareth Hein for 21.0 - GIF/JPEG/PNG/TIFF code moved to new glyph-eimage.c for 21.0 + GIF/JPEG/PNG/TIFF code moved to new glyph-eimage.c by Andy Piper for 21.0 + Subwindow and Widget support by Andy Piper for 21.2 TODO: Convert images.el to C and stick it in here? @@ -52,7 +53,9 @@ Boston, MA 02111-1307, USA. */ #include "console-x.h" #include "glyphs-x.h" #include "objects-x.h" +#ifdef HAVE_WIDGETS #include "gui-x.h" +#endif #include "xmu.h" #include "buffer.h" @@ -73,7 +76,7 @@ Boston, MA 02111-1307, USA. */ #include "file-coding.h" #endif -#ifdef LWLIB_USES_MOTIF +#ifdef LWLIB_WIDGETS_MOTIF #include #endif #include @@ -94,6 +97,7 @@ DECLARE_IMAGE_INSTANTIATOR_FORMAT (nothing); DECLARE_IMAGE_INSTANTIATOR_FORMAT (string); DECLARE_IMAGE_INSTANTIATOR_FORMAT (formatted_string); DECLARE_IMAGE_INSTANTIATOR_FORMAT (inherit); +DECLARE_IMAGE_INSTANTIATOR_FORMAT (layout); #ifdef HAVE_JPEG DECLARE_IMAGE_INSTANTIATOR_FORMAT (jpeg); #endif @@ -122,11 +126,17 @@ DEFINE_IMAGE_INSTANTIATOR_FORMAT (font); DEFINE_IMAGE_INSTANTIATOR_FORMAT (autodetect); +#ifdef HAVE_WIDGETS DEFINE_DEVICE_IIFORMAT (x, widget); DEFINE_DEVICE_IIFORMAT (x, button); DEFINE_DEVICE_IIFORMAT (x, progress_gauge); DEFINE_DEVICE_IIFORMAT (x, edit_field); +#if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1 DEFINE_DEVICE_IIFORMAT (x, combo_box); +#endif +DEFINE_DEVICE_IIFORMAT (x, tab_control); +DEFINE_DEVICE_IIFORMAT (x, label); +#endif static void cursor_font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, @@ -135,6 +145,11 @@ static void cursor_font_instantiate (Lisp_Object image_instance, int dest_mask, Lisp_Object domain); +#ifdef HAVE_WIDGETS +static void +update_widget_face (struct Lisp_Image_Instance* ii, Lisp_Object domain); +#endif + #include "bitmaps.h" @@ -357,6 +372,10 @@ x_print_image_instance (struct Lisp_Image_Instance *p, } } +#ifdef DEBUG_WIDGETS +extern int debug_widget_instances; +#endif + static void x_finalize_image_instance (struct Lisp_Image_Instance *p) { @@ -371,8 +390,12 @@ x_finalize_image_instance (struct Lisp_Image_Instance *p) { if (IMAGE_INSTANCE_SUBWINDOW_ID (p)) { - XtUnmanageChild (IMAGE_INSTANCE_X_WIDGET_ID (p)); - XtDestroyWidget (IMAGE_INSTANCE_X_WIDGET_ID (p)); +#ifdef DEBUG_WIDGETS + debug_widget_instances--; + stderr_out ("widget destroyed, %d left\n", debug_widget_instances); +#endif + lw_destroy_widget (IMAGE_INSTANCE_X_WIDGET_ID (p)); + lw_destroy_widget (IMAGE_INSTANCE_X_CLIPWIDGET (p)); IMAGE_INSTANCE_SUBWINDOW_ID (p) = 0; } } @@ -384,14 +407,27 @@ x_finalize_image_instance (struct Lisp_Image_Instance *p) } else { - if (IMAGE_INSTANCE_X_PIXMAP (p)) - XFreePixmap (dpy, IMAGE_INSTANCE_X_PIXMAP (p)); + int i; + if (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p)) + disable_glyph_animated_timeout (IMAGE_INSTANCE_PIXMAP_TIMEOUT (p)); + if (IMAGE_INSTANCE_X_MASK (p) && IMAGE_INSTANCE_X_MASK (p) != IMAGE_INSTANCE_X_PIXMAP (p)) XFreePixmap (dpy, IMAGE_INSTANCE_X_MASK (p)); - IMAGE_INSTANCE_X_PIXMAP (p) = 0; - IMAGE_INSTANCE_X_MASK (p) = 0; + IMAGE_INSTANCE_PIXMAP_MASK (p) = 0; + if (IMAGE_INSTANCE_X_PIXMAP_SLICES (p)) + { + for (i = 0; i < IMAGE_INSTANCE_PIXMAP_MAXSLICE (p); i++) + if (IMAGE_INSTANCE_X_PIXMAP_SLICE (p,i)) + { + XFreePixmap (dpy, IMAGE_INSTANCE_X_PIXMAP_SLICE (p,i)); + IMAGE_INSTANCE_X_PIXMAP_SLICE (p, i) = 0; + } + xfree (IMAGE_INSTANCE_X_PIXMAP_SLICES (p)); + IMAGE_INSTANCE_X_PIXMAP_SLICES (p) = 0; + } + if (IMAGE_INSTANCE_X_CURSOR (p)) { XFreeCursor (dpy, IMAGE_INSTANCE_X_CURSOR (p)); @@ -408,7 +444,13 @@ x_finalize_image_instance (struct Lisp_Image_Instance *p) } } } - if (IMAGE_INSTANCE_X_PIXELS (p)) + /* You can sometimes have pixels without a live device. I forget + why, but that's why we free them here if we have a pixmap type + image instance. It probably means that we might also get a memory + leak with widgets. */ + if (IMAGE_INSTANCE_TYPE (p) != IMAGE_WIDGET + && IMAGE_INSTANCE_TYPE (p) != IMAGE_SUBWINDOW + && IMAGE_INSTANCE_X_PIXELS (p)) { xfree (IMAGE_INSTANCE_X_PIXELS (p)); IMAGE_INSTANCE_X_PIXELS (p) = 0; @@ -460,9 +502,13 @@ x_image_instance_hash (struct Lisp_Image_Instance *p, int depth) static void x_initialize_pixmap_image_instance (struct Lisp_Image_Instance *ii, + int slices, enum image_instance_type type) { ii->data = xnew_and_zero (struct x_image_instance_data); + IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) = slices; + IMAGE_INSTANCE_X_PIXMAP_SLICES (ii) = + xnew_array_and_zero (Pixmap, slices); IMAGE_INSTANCE_TYPE (ii) = type; IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = Qnil; IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (ii) = Qnil; @@ -781,6 +827,7 @@ init_image_instance_from_x_image (struct Lisp_Image_Instance *ii, Colormap cmap, unsigned long *pixels, int npixels, + int slices, Lisp_Object instantiator) { Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); @@ -816,13 +863,15 @@ init_image_instance_from_x_image (struct Lisp_Image_Instance *ii, XFreeGC (dpy, gc); - x_initialize_pixmap_image_instance (ii, IMAGE_COLOR_PIXMAP); + x_initialize_pixmap_image_instance (ii, slices, IMAGE_COLOR_PIXMAP); IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = find_keyword_in_vector (instantiator, Q_file); + /* Fixup a set of pixmaps. */ IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap; - IMAGE_INSTANCE_X_MASK (ii) = 0; + + IMAGE_INSTANCE_PIXMAP_MASK (ii) = 0; IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = ximage->width; IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = ximage->height; IMAGE_INSTANCE_PIXMAP_DEPTH (ii) = ximage->depth; @@ -832,8 +881,44 @@ init_image_instance_from_x_image (struct Lisp_Image_Instance *ii, } static void +image_instance_add_x_image (struct Lisp_Image_Instance *ii, + XImage *ximage, + int slice, + Lisp_Object instantiator) +{ + Lisp_Object device = IMAGE_INSTANCE_DEVICE (ii); + Display *dpy; + GC gc; + Drawable d; + Pixmap pixmap; + + dpy = DEVICE_X_DISPLAY (XDEVICE (device)); + d = XtWindow(DEVICE_XT_APP_SHELL (XDEVICE (device))); + + pixmap = XCreatePixmap (dpy, d, ximage->width, + ximage->height, ximage->depth); + if (!pixmap) + signal_simple_error ("Unable to create pixmap", instantiator); + + gc = XCreateGC (dpy, pixmap, 0, NULL); + if (!gc) + { + XFreePixmap (dpy, pixmap); + signal_simple_error ("Unable to create GC", instantiator); + } + + XPutImage (dpy, pixmap, gc, ximage, 0, 0, 0, 0, + ximage->width, ximage->height); + + XFreeGC (dpy, gc); + + IMAGE_INSTANCE_X_PIXMAP_SLICE (ii, slice) = pixmap; +} + +static void x_init_image_instance_from_eimage (struct Lisp_Image_Instance *ii, int width, int height, + int slices, unsigned char *eimage, int dest_mask, Lisp_Object instantiator, @@ -843,29 +928,38 @@ x_init_image_instance_from_eimage (struct Lisp_Image_Instance *ii, Colormap cmap = DEVICE_X_COLORMAP (XDEVICE(device)); unsigned long *pixtbl = NULL; int npixels = 0; + int slice; XImage* ximage; - ximage = convert_EImage_to_XImage (device, width, height, eimage, - &pixtbl, &npixels); - if (!ximage) + for (slice = 0; slice < slices; slice++) { - if (pixtbl) xfree (pixtbl); - signal_image_error("EImage to XImage conversion failed", instantiator); - } + ximage = convert_EImage_to_XImage (device, width, height, + eimage + (width * height * 3 * slice), + &pixtbl, &npixels); + if (!ximage) + { + if (pixtbl) xfree (pixtbl); + signal_image_error("EImage to XImage conversion failed", instantiator); + } - /* Now create the pixmap and set up the image instance */ - init_image_instance_from_x_image (ii, ximage, dest_mask, - cmap, pixtbl, npixels, - instantiator); + /* Now create the pixmap and set up the image instance */ + if (slice == 0) + init_image_instance_from_x_image (ii, ximage, dest_mask, + cmap, pixtbl, npixels, slices, + instantiator); + else + image_instance_add_x_image (ii, ximage, slice, instantiator); - if (ximage) - { - if (ximage->data) - { - xfree (ximage->data); - ximage->data = 0; - } - XDestroyImage (ximage); + if (ximage) + { + if (ximage->data) + { + xfree (ximage->data); + ximage->data = 0; + } + XDestroyImage (ximage); + ximage = 0; + } } } @@ -940,7 +1034,7 @@ init_image_instance_from_xbm_inline (struct Lisp_Image_Instance *ii, IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK | IMAGE_POINTER_MASK); - x_initialize_pixmap_image_instance (ii, type); + x_initialize_pixmap_image_instance (ii, 1, type); IMAGE_INSTANCE_PIXMAP_WIDTH (ii) = width; IMAGE_INSTANCE_PIXMAP_HEIGHT (ii) = height; IMAGE_INSTANCE_PIXMAP_FILENAME (ii) = @@ -1244,7 +1338,7 @@ x_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, visual = DEVICE_X_VISUAL (XDEVICE(device)); #endif - x_initialize_pixmap_image_instance (ii, type); + x_initialize_pixmap_image_instance (ii, 1, type); assert (!NILP (data)); @@ -1354,7 +1448,7 @@ x_xpm_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, pixels = NULL; IMAGE_INSTANCE_X_PIXMAP (ii) = pixmap; - IMAGE_INSTANCE_X_MASK (ii) = mask; + IMAGE_INSTANCE_PIXMAP_MASK (ii) = (void*)mask; IMAGE_INSTANCE_X_COLORMAP (ii) = cmap; IMAGE_INSTANCE_X_PIXELS (ii) = pixels; IMAGE_INSTANCE_X_NPIXELS (ii) = npixels; @@ -1882,7 +1976,7 @@ font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, /* #### call XQueryTextExtents() and check_pointer_sizes() here. */ - x_initialize_pixmap_image_instance (ii, IMAGE_POINTER); + x_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER); IMAGE_INSTANCE_X_CURSOR (ii) = XCreateGlyphCursor (dpy, source, mask, source_char, mask_char, &fg, &bg); @@ -1935,7 +2029,7 @@ cursor_font_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, if ((i = XmuCursorNameToIndex (name_ext)) == -1) signal_simple_error ("Unrecognized cursor-font name", data); - x_initialize_pixmap_image_instance (ii, IMAGE_POINTER); + x_initialize_pixmap_image_instance (ii, 1, IMAGE_POINTER); IMAGE_INSTANCE_X_CURSOR (ii) = XCreateFontCursor (dpy, i); foreground = find_keyword_in_vector (instantiator, Q_foreground); if (NILP (foreground)) @@ -1960,7 +2054,7 @@ x_colorize_image_instance (Lisp_Object image_instance, IMAGE_INSTANCE_TYPE (p) = IMAGE_COLOR_PIXMAP; /* Make sure there aren't two pointers to the same mask, causing it to get freed twice. */ - IMAGE_INSTANCE_X_MASK (p) = 0; + IMAGE_INSTANCE_PIXMAP_MASK (p) = 0; break; default: @@ -2008,33 +2102,41 @@ x_unmap_subwindow (struct Lisp_Image_Instance *p) if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW) { XUnmapWindow - (DisplayOfScreen (IMAGE_INSTANCE_X_SUBWINDOW_SCREEN (p)), - IMAGE_INSTANCE_X_SUBWINDOW_ID (p)); + (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p), + IMAGE_INSTANCE_X_CLIPWINDOW (p)); } else /* must be a widget */ { - XtUnmapWidget (IMAGE_INSTANCE_X_WIDGET_ID (p)); + XtUnmapWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p)); } } /* map the subwindow. This is used by redisplay via redisplay_output_subwindow */ static void -x_map_subwindow (struct Lisp_Image_Instance *p, int x, int y) +x_map_subwindow (struct Lisp_Image_Instance *p, int x, int y, + struct display_glyph_area* dga) { if (IMAGE_INSTANCE_TYPE (p) == IMAGE_SUBWINDOW) { Window subwindow = IMAGE_INSTANCE_X_SUBWINDOW_ID (p); - Screen* screen = IMAGE_INSTANCE_X_SUBWINDOW_SCREEN (p); - XMapWindow (DisplayOfScreen (screen), subwindow); - XMoveWindow (DisplayOfScreen (screen), subwindow, x, y); + XMoveResizeWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p), + IMAGE_INSTANCE_X_CLIPWINDOW (p), + x, y, dga->width, dga->height); + XMoveWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p), + subwindow, -dga->xoffset, -dga->yoffset); + XMapWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (p), + IMAGE_INSTANCE_X_CLIPWINDOW (p)); } else /* must be a widget */ { - XtMoveWidget (IMAGE_INSTANCE_X_WIDGET_ID (p), - x + IMAGE_INSTANCE_X_WIDGET_XOFFSET (p), - y + IMAGE_INSTANCE_X_WIDGET_YOFFSET (p)); - XtMapWidget (IMAGE_INSTANCE_X_WIDGET_ID (p)); + XtConfigureWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p), + x + IMAGE_INSTANCE_X_WIDGET_XOFFSET (p), + y + IMAGE_INSTANCE_X_WIDGET_YOFFSET (p), + dga->width, dga->height, 0); + XtMoveWidget (IMAGE_INSTANCE_X_WIDGET_ID (p), + -dga->xoffset, -dga->yoffset); + XtMapWidget (IMAGE_INSTANCE_X_CLIPWIDGET (p)); } } @@ -2043,14 +2145,47 @@ x_map_subwindow (struct Lisp_Image_Instance *p, int x, int y) static void x_update_subwindow (struct Lisp_Image_Instance *p) { +#ifdef HAVE_WIDGETS if (IMAGE_INSTANCE_TYPE (p) == IMAGE_WIDGET) { - widget_value* wv = xmalloc_widget_value (); - button_item_to_widget_value (IMAGE_INSTANCE_WIDGET_SINGLE_ITEM (p), - wv, 1, 1); + Arg al[5]; + widget_value* wv = gui_items_to_widget_values + (IMAGE_INSTANCE_WIDGET_ITEMS (p)); + + /* This seems ugly, but I'm not sure what else to do. */ + if (EQ (IMAGE_INSTANCE_WIDGET_TYPE (p), Qtab_control)) + { + widget_value* cur = 0; + /* Give each child label the correct foreground color. */ + Lisp_Object pixel = FACE_FOREGROUND + (IMAGE_INSTANCE_WIDGET_FACE (p), + IMAGE_INSTANCE_SUBWINDOW_FRAME (p)); + XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel)); + XtSetArg (al [0], XtNtabForeground, fcolor.pixel); + + for (cur = wv->contents; cur; cur = cur->next) + { + if (cur->value) + { + cur->nargs = 1; + cur->args = al; + } + } + } + + /* now modify the widget */ lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (p), - wv, 1); + wv, True); + free_widget_value_tree (wv); + /* update the colors and font */ + update_widget_face (p, IMAGE_INSTANCE_SUBWINDOW_FRAME (p)); + /* We have to do this otherwise Motif will unceremoniously + resize us when the label gets set. */ + XtSetArg (al [0], XtNwidth, IMAGE_INSTANCE_WIDGET_WIDTH (p)); + XtSetArg (al [1], XtNheight, IMAGE_INSTANCE_WIDGET_HEIGHT (p)); + XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (p), al, 2); } +#endif } /* instantiate and x type subwindow */ @@ -2085,14 +2220,22 @@ x_subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, ii->data = xnew_and_zero (struct x_subwindow_data); IMAGE_INSTANCE_X_SUBWINDOW_PARENT (ii) = pw; - IMAGE_INSTANCE_X_SUBWINDOW_SCREEN (ii) = xs; + IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (ii) = DisplayOfScreen (xs); xswa.backing_store = Always; valueMask |= CWBackingStore; xswa.colormap = DefaultColormapOfScreen (xs); valueMask |= CWColormap; - win = XCreateWindow (dpy, pw, 0, 0, w, h, 0, CopyFromParent, + /* Create a window for clipping */ + IMAGE_INSTANCE_X_CLIPWINDOW (ii) = + XCreateWindow (dpy, pw, 0, 0, w, h, 0, CopyFromParent, + InputOutput, CopyFromParent, valueMask, + &xswa); + + /* Now put the subwindow inside the clip window. */ + win = XCreateWindow (dpy, IMAGE_INSTANCE_X_CLIPWINDOW (ii), + 0, 0, w, h, 0, CopyFromParent, InputOutput, CopyFromParent, valueMask, &xswa); @@ -2134,24 +2277,77 @@ x_resize_subwindow (struct Lisp_Image_Instance* ii, int w, int h) { if (IMAGE_INSTANCE_TYPE (ii) == IMAGE_SUBWINDOW) { - XResizeWindow (DisplayOfScreen (IMAGE_INSTANCE_X_SUBWINDOW_SCREEN (ii)), + XResizeWindow (IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (ii), IMAGE_INSTANCE_X_SUBWINDOW_ID (ii), w, h); } else /* must be a widget */ { Arg al[2]; + + if (!XtIsRealized (IMAGE_INSTANCE_X_WIDGET_ID (ii))) + { + Lisp_Object sw; + XSETIMAGE_INSTANCE (sw, ii); + signal_simple_error ("XEmacs bug: subwindow is not realized", sw); + } + XtSetArg (al [0], XtNwidth, (Dimension)w); XtSetArg (al [1], XtNheight, (Dimension)h); XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 2); } } + +#ifdef HAVE_WIDGETS + /************************************************************************/ /* widgets */ /************************************************************************/ static void +update_widget_face (struct Lisp_Image_Instance* ii, Lisp_Object domain) +{ + Arg al[3]; +#ifdef LWLIB_WIDGETS_MOTIF + XmFontList fontList; +#endif + + Lisp_Object pixel = FACE_FOREGROUND + (IMAGE_INSTANCE_WIDGET_FACE (ii), + IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)); + XColor fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel)); + XColor bcolor; + + pixel = FACE_BACKGROUND + (IMAGE_INSTANCE_WIDGET_FACE (ii), + IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)); + bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel)); + + XtSetArg (al [0], XtNbackground, bcolor.pixel); + XtSetArg (al [1], XtNforeground, fcolor.pixel); + +#ifdef LWLIB_WIDGETS_MOTIF + fontList = XmFontListCreate + (FONT_INSTANCE_X_FONT + (XFONT_INSTANCE (widget_face_font_info + (domain, IMAGE_INSTANCE_WIDGET_FACE (ii), + 0, 0))), XmSTRING_DEFAULT_CHARSET); + XtSetArg (al [2], XmNfontList, fontList ); +#else + XtSetArg (al [2], XtNfont, (void*)FONT_INSTANCE_X_FONT + (XFONT_INSTANCE (widget_face_font_info + (domain, + IMAGE_INSTANCE_WIDGET_FACE (ii), + 0, 0)))); +#endif + XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, 3); +#ifdef LWLIB_WIDGETS_MOTIF + XmFontListFree (fontList); +#endif +} + +static void x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, Lisp_Object pointer_fg, Lisp_Object pointer_bg, int dest_mask, Lisp_Object domain, @@ -2162,18 +2358,16 @@ x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, struct device* d = XDEVICE (device); Lisp_Object frame = FW_FRAME (domain); struct frame* f = XFRAME (frame); - XColor fcolor, bcolor; - Extbyte* nm=0; + char* nm=0; Widget wid; Arg al [32]; int ac = 0; int id = new_lwlib_id (); -#ifdef LWLIB_USES_MOTIF - XmFontList fontList; -#endif + widget_value* clip_wv; + XColor fcolor, bcolor; if (!DEVICE_X_P (d)) - signal_simple_error ("Not an mswindows device", device); + signal_simple_error ("Not an X device", device); /* have to set the type this late in case there is no device instantiation for a widget. But we can go ahead and do it without @@ -2185,15 +2379,46 @@ x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, ii->data = xnew_and_zero (struct x_subwindow_data); + /* Create a clip window to contain the subwidget. Incredibly the + XEmacs manager seems to be the most appropriate widget for + this. Nothing else is simple enough and yet does what is + required. */ + clip_wv = xmalloc_widget_value (); + + XtSetArg (al [ac], XtNresize, False); ac++; + XtSetArg (al [ac], XtNwidth, + (Dimension)IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii)); ac++; + XtSetArg (al [ac], XtNheight, + (Dimension)IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii)); ac++; + + clip_wv->enabled = True; + clip_wv->nargs = ac; + clip_wv->args = al; + clip_wv->name = xstrdup ("clip-window"); + clip_wv->value = xstrdup ("clip-window"); + + IMAGE_INSTANCE_X_CLIPWIDGET (ii) + = lw_create_widget ("clip-window", "clip-window", new_lwlib_id (), + clip_wv, FRAME_X_CONTAINER_WIDGET (f), + False, 0, 0, 0); + + free_widget_value_tree (clip_wv); + /* copy any args we were given */ + ac = 0; + if (wv->nargs) lw_add_value_args_to_args (wv, al, &ac); - /* add our own arguments */ + /* Fixup the colors. We have to do this *before* the widget gets + created so that Motif will fix up the shadow colors + correctly. Once the widget is created Motif won't do this + anymore...*/ pixel = FACE_FOREGROUND (IMAGE_INSTANCE_WIDGET_FACE (ii), IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)); fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel)); + pixel = FACE_BACKGROUND (IMAGE_INSTANCE_WIDGET_FACE (ii), IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)); @@ -2201,49 +2426,44 @@ x_widget_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, XtSetArg (al [ac], XtNbackground, bcolor.pixel); ac++; XtSetArg (al [ac], XtNforeground, fcolor.pixel); ac++; -#ifdef LWLIB_USES_MOTIF - fontList = XmFontListCreate - ((void*)FONT_INSTANCE_X_FONT - (XFONT_INSTANCE (widget_face_font_info - (domain, IMAGE_INSTANCE_WIDGET_FACE (ii), - 0, 0))), XmSTRING_DEFAULT_CHARSET); - XtSetArg (al [ac], XmNfontList, fontList ); ac++; -#else - XtSetArg (al [ac], XtNfont, (void*)FONT_INSTANCE_X_FONT - (XFONT_INSTANCE (widget_face_font_info - (domain, - IMAGE_INSTANCE_WIDGET_FACE (ii), - 0, 0)))); ac++; -#endif + /* we cannot allow widgets to resize themselves */ + XtSetArg (al [ac], XtNresize, False); ac++; + XtSetArg (al [ac], XtNwidth, + (Dimension)IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii)); ac++; + XtSetArg (al [ac], XtNheight, + (Dimension)IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii)); ac++; wv->nargs = ac; wv->args = al; - - wid = lw_create_widget (type, wv->name, id, wv, FRAME_X_CONTAINER_WIDGET (f), + + wid = lw_create_widget (type, wv->name, id, wv, IMAGE_INSTANCE_X_CLIPWIDGET (ii), False, 0, popup_selection_callback, 0); + IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)wid; IMAGE_INSTANCE_X_WIDGET_LWID (ii) = id; -#ifdef LWLIB_USES_MOTIF - XmFontListFree (fontList); -#endif - /* because the EmacsManager is the widgets parent we have to - offset the redisplay of the widget by the amount the text - widget is inside the manager. */ + + /* update the font. */ + update_widget_face (ii, domain); + + /* Resize the widget here so that the values do not get copied by + lwlib. */ ac = 0; XtSetArg (al [ac], XtNwidth, (Dimension)IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii)); ac++; XtSetArg (al [ac], XtNheight, (Dimension)IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii)); ac++; - XtSetValues (wid, al, ac); - /* finally get offsets in the frame */ + XtSetValues (IMAGE_INSTANCE_X_WIDGET_ID (ii), al, ac); + /* because the EmacsManager is the widgets parent we have to + offset the redisplay of the widget by the amount the text + widget is inside the manager. */ ac = 0; XtSetArg (al [ac], XtNx, &IMAGE_INSTANCE_X_WIDGET_XOFFSET (ii)); ac++; XtSetArg (al [ac], XtNy, &IMAGE_INSTANCE_X_WIDGET_YOFFSET (ii)); ac++; XtGetValues (FRAME_X_TEXT_WIDGET (f), al, ac); - IMAGE_INSTANCE_SUBWINDOW_ID (ii) = (void*)wid; + XtMapWidget (wid); - free_widget_value (wv); + free_widget_value_tree (wv); } static Lisp_Object @@ -2254,7 +2474,7 @@ x_widget_set_property (Lisp_Object image_instance, Lisp_Object prop, if (EQ (prop, Q_text)) { - Extbyte* str=0; + char* str; widget_value* wv = lw_get_all_values (IMAGE_INSTANCE_X_WIDGET_LWID (ii)); CHECK_STRING (val); GET_C_STRING_OS_DATA_ALLOCA (val, str); @@ -2262,6 +2482,12 @@ x_widget_set_property (Lisp_Object image_instance, Lisp_Object prop, lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (ii), wv, False); return Qt; } + /* Modify the face properties of the widget */ + if (EQ (prop, Q_face)) + { + update_widget_face (ii, IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)); + return Qt; + } return Qunbound; } @@ -2311,7 +2537,7 @@ x_button_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, { Arg al [2]; int ac =0; -#ifdef LWLIB_USES_MOTIF +#ifdef LWLIB_WIDGETS_MOTIF XtSetArg (al [ac], XmNlabelType, XmPIXMAP); ac++; XtSetArg (al [ac], XmNlabelPixmap, XIMAGE_INSTANCE_X_PIXMAP (glyph));ac++; #else @@ -2389,6 +2615,7 @@ x_edit_field_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, pointer_bg, dest_mask, domain, "text-field", wv); } +#if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1 /* instantiate a combo control */ static void x_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, @@ -2396,27 +2623,116 @@ x_combo_box_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, int dest_mask, Lisp_Object domain) { struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); - Lisp_Object rest; - Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii); - widget_value* wv = xmalloc_widget_value (); + widget_value * wv = 0; + /* This is not done generically because of sizing problems under + mswindows. */ + widget_instantiate_1 (image_instance, instantiator, pointer_fg, + pointer_bg, dest_mask, domain, 1, 0, 0); - button_item_to_widget_value (gui, wv, 1, 1); + wv = gui_items_to_widget_values (IMAGE_INSTANCE_WIDGET_ITEMS (ii)); x_widget_instantiate (image_instance, instantiator, pointer_fg, pointer_bg, dest_mask, domain, "combo-box", wv); - /* add items to the combo box */ - LIST_LOOP (rest, Fplist_get (IMAGE_INSTANCE_WIDGET_PROPS (ii), Q_items, Qnil)) - { -#if 0 - Extbyte* str; - XmString xmstr; - GET_C_STRING_OS_DATA_ALLOCA (XCAR (rest), str); - xmstr = XmStringCreate (str, XmSTRING_DEFAULT_CHARSET); - XmListAddItem (IMAGE_INSTANCE_X_WIDGET_ID (ii), xmstr, 0); - XmStringFree (xmstr); +} #endif + +static void +x_tab_control_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) +{ + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + Arg al [1]; + XColor fcolor; + Lisp_Object pixel; + widget_value* cur; + + widget_value * wv = + gui_items_to_widget_values (IMAGE_INSTANCE_WIDGET_ITEMS (ii)); + + /* Give each child label the correct foreground color. */ + pixel = FACE_FOREGROUND + (IMAGE_INSTANCE_WIDGET_FACE (ii), + IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)); + fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel)); + XtSetArg (al [0], XtNtabForeground, fcolor.pixel); + + for (cur = wv->contents; cur; cur = cur->next) + { + if (cur->value) + { + cur->nargs = 1; + cur->args = al; + } } + + x_widget_instantiate (image_instance, instantiator, pointer_fg, + pointer_bg, dest_mask, domain, "tab-control", wv); +} + +/* set the properties of a tab control */ +static Lisp_Object +x_tab_control_set_property (Lisp_Object image_instance, Lisp_Object prop, + Lisp_Object val) +{ + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + + if (EQ (prop, Q_items)) + { + widget_value * wv = 0, *cur; + Arg al [1]; + XColor fcolor; + Lisp_Object pixel; + + check_valid_item_list_1 (val); + + IMAGE_INSTANCE_WIDGET_ITEMS (ii) = + Fcons (XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (ii)), + parse_gui_item_tree_children (val)); + + wv = gui_items_to_widget_values (IMAGE_INSTANCE_WIDGET_ITEMS (ii)); + + /* Give each child label the correct foreground color. */ + pixel = FACE_FOREGROUND + (IMAGE_INSTANCE_WIDGET_FACE (ii), + IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)); + fcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (pixel)); + XtSetArg (al [0], XtNtabForeground, fcolor.pixel); + + for (cur = wv->contents; cur; cur = cur->next) + { + if (cur->value) + { + cur->nargs = 1; + cur->args = al; + } + } + + lw_modify_all_widgets (IMAGE_INSTANCE_X_WIDGET_LWID (ii), wv, True); + + free_widget_value_tree (wv); + return Qt; + } + + return Qunbound; +} + +/* instantiate a static control possible for putting other things in */ +static void +x_label_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain) +{ + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + Lisp_Object gui = IMAGE_INSTANCE_WIDGET_ITEM (ii); + widget_value* wv = xmalloc_widget_value (); + + button_item_to_widget_value (gui, wv, 1, 1); + + x_widget_instantiate (image_instance, instantiator, pointer_fg, + pointer_bg, dest_mask, domain, "button", wv); } +#endif /* HAVE_WIDGETS */ /************************************************************************/ @@ -2454,6 +2770,7 @@ image_instantiator_format_create_glyphs_x (void) { IIFORMAT_VALID_CONSOLE (x, nothing); IIFORMAT_VALID_CONSOLE (x, string); + IIFORMAT_VALID_CONSOLE (x, layout); IIFORMAT_VALID_CONSOLE (x, formatted_string); IIFORMAT_VALID_CONSOLE (x, inherit); #ifdef HAVE_XPM @@ -2477,7 +2794,7 @@ image_instantiator_format_create_glyphs_x (void) INITIALIZE_DEVICE_IIFORMAT (x, subwindow); IIFORMAT_HAS_DEVMETHOD (x, subwindow, instantiate); -#ifdef LWLIB_USES_MOTIF +#ifdef HAVE_WIDGETS /* button widget */ INITIALIZE_DEVICE_IIFORMAT (x, button); IIFORMAT_HAS_DEVMETHOD (x, button, property); @@ -2493,11 +2810,19 @@ image_instantiator_format_create_glyphs_x (void) /* text field */ INITIALIZE_DEVICE_IIFORMAT (x, edit_field); IIFORMAT_HAS_DEVMETHOD (x, edit_field, instantiate); -#if 0 /* XmVERSION > 1*/ +#if defined (LWLIB_WIDGETS_MOTIF) && XmVERSION > 1 /* combo box */ INITIALIZE_DEVICE_IIFORMAT (x, combo_box); IIFORMAT_HAS_DEVMETHOD (x, combo_box, instantiate); + IIFORMAT_HAS_SHARED_DEVMETHOD (x, combo_box, set_property, tab_control); #endif + /* tab control widget */ + INITIALIZE_DEVICE_IIFORMAT (x, tab_control); + IIFORMAT_HAS_DEVMETHOD (x, tab_control, instantiate); + IIFORMAT_HAS_DEVMETHOD (x, tab_control, set_property); + /* label */ + INITIALIZE_DEVICE_IIFORMAT (x, label); + IIFORMAT_HAS_DEVMETHOD (x, label, instantiate); #endif INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (cursor_font, "cursor-font"); IIFORMAT_VALID_CONSOLE (x, cursor_font); diff --git a/src/glyphs-x.h b/src/glyphs-x.h index a2bc03f..d49ba53 100644 --- a/src/glyphs-x.h +++ b/src/glyphs-x.h @@ -39,8 +39,7 @@ Boston, MA 02111-1307, USA. */ struct x_image_instance_data { - Pixmap pixmap; - Pixmap mask; + Pixmap* pixmaps; Cursor cursor; /* If depth>0, then that means that other colors were allocated when @@ -56,8 +55,13 @@ struct x_image_instance_data #define X_IMAGE_INSTANCE_DATA(i) ((struct x_image_instance_data *) (i)->data) -#define IMAGE_INSTANCE_X_PIXMAP(i) (X_IMAGE_INSTANCE_DATA (i)->pixmap) -#define IMAGE_INSTANCE_X_MASK(i) (X_IMAGE_INSTANCE_DATA (i)->mask) +#define IMAGE_INSTANCE_X_PIXMAP(i) (X_IMAGE_INSTANCE_DATA (i)->pixmaps[0]) +#define IMAGE_INSTANCE_X_PIXMAP_SLICE(i,slice) \ + (X_IMAGE_INSTANCE_DATA (i)->pixmaps[slice]) +#define IMAGE_INSTANCE_X_PIXMAP_SLICES(i) \ + (X_IMAGE_INSTANCE_DATA (i)->pixmaps) +#define IMAGE_INSTANCE_X_MASK(i) \ + (Pixmap)(IMAGE_INSTANCE_PIXMAP_MASK (i)) #define IMAGE_INSTANCE_X_CURSOR(i) (X_IMAGE_INSTANCE_DATA (i)->cursor) #define IMAGE_INSTANCE_X_COLORMAP(i) (X_IMAGE_INSTANCE_DATA (i)->colormap) #define IMAGE_INSTANCE_X_PIXELS(i) (X_IMAGE_INSTANCE_DATA (i)->pixels) @@ -65,6 +69,10 @@ struct x_image_instance_data #define XIMAGE_INSTANCE_X_PIXMAP(i) \ IMAGE_INSTANCE_X_PIXMAP (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_X_PIXMAP_SLICES(i) \ + IMAGE_INSTANCE_X_PIXMAP_SLICES (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_X_PIXMAP_SLICE(i) \ + IMAGE_INSTANCE_X_PIXMAP_SLICE (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_X_MASK(i) \ IMAGE_INSTANCE_X_MASK (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_X_CURSOR(i) \ @@ -84,11 +92,13 @@ struct x_subwindow_data { struct { - Screen *xscreen; + Display *display; Window parent_window; + Window clip_window; } sub; struct { + Widget clip_window; Position x_offset; Position y_offset; LWLIB_ID id; @@ -98,26 +108,34 @@ struct x_subwindow_data #define X_SUBWINDOW_INSTANCE_DATA(i) ((struct x_subwindow_data *) (i)->data) -#define IMAGE_INSTANCE_X_SUBWINDOW_SCREEN(i) \ - (X_SUBWINDOW_INSTANCE_DATA (i)->data.sub.xscreen) +#define IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY(i) \ + (X_SUBWINDOW_INSTANCE_DATA (i)->data.sub.display) #define IMAGE_INSTANCE_X_SUBWINDOW_PARENT(i) \ (X_SUBWINDOW_INSTANCE_DATA (i)->data.sub.parent_window) +#define IMAGE_INSTANCE_X_CLIPWINDOW(i) \ + (X_SUBWINDOW_INSTANCE_DATA (i)->data.sub.clip_window) #define IMAGE_INSTANCE_X_WIDGET_XOFFSET(i) \ (X_SUBWINDOW_INSTANCE_DATA (i)->data.wid.x_offset) #define IMAGE_INSTANCE_X_WIDGET_YOFFSET(i) \ (X_SUBWINDOW_INSTANCE_DATA (i)->data.wid.y_offset) #define IMAGE_INSTANCE_X_WIDGET_LWID(i) \ (X_SUBWINDOW_INSTANCE_DATA (i)->data.wid.id) +#define IMAGE_INSTANCE_X_CLIPWIDGET(i) \ + (X_SUBWINDOW_INSTANCE_DATA (i)->data.wid.clip_window) #define XIMAGE_INSTANCE_X_SUBWINDOW_PARENT(i) \ IMAGE_INSTANCE_X_SUBWINDOW_PARENT (XIMAGE_INSTANCE (i)) -#define XIMAGE_INSTANCE_X_SUBWINDOW_SCREEN(i) \ - IMAGE_INSTANCE_X_SUBWINDOW_SCREEN (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_X_SUBWINDOW_DISPLAY(i) \ + IMAGE_INSTANCE_X_SUBWINDOW_DISPLAY (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_X_WIDGET_XOFFSET(i) \ IMAGE_INSTANCE_X_WIDGET_XOFFSET (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_X_WIDGET_YOFFSET(i) \ IMAGE_INSTANCE_X_WIDGET_YOFFSET (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_X_WIDGET_LWID(i) \ IMAGE_INSTANCE_X_WIDGET_LWID (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_X_CLIPWIDGET(i) \ + IMAGE_INSTANCE_X_CLIPWIDGET (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_X_CLIPWINDOW(i) \ + IMAGE_INSTANCE_X_CLIPWINDOW (XIMAGE_INSTANCE (i)) #define IMAGE_INSTANCE_X_SUBWINDOW_ID(i) \ ((Window) IMAGE_INSTANCE_SUBWINDOW_ID (i)) #define IMAGE_INSTANCE_X_WIDGET_ID(i) \ diff --git a/src/glyphs.c b/src/glyphs.c index 0db3c08..7deab6c 100644 --- a/src/glyphs.c +++ b/src/glyphs.c @@ -3,7 +3,7 @@ Copyright (C) 1995 Tinker Systems Copyright (C) 1995, 1996 Ben Wing Copyright (C) 1995 Sun Microsystems - Copyright (C) 1998 Andy Piper + Copyright (C) 1998, 1999 Andy Piper This file is part of XEmacs. @@ -24,7 +24,7 @@ Boston, MA 02111-1307, USA. */ /* Synched up with: Not in FSF. */ -/* Written by Ben Wing and Chuck Thompson */ +/* Written by Ben Wing and Chuck Thompson. */ #include #include "lisp.h" @@ -42,6 +42,7 @@ Boston, MA 02111-1307, USA. */ #include "frame.h" #include "chartab.h" #include "rangetab.h" +#include "blocktype.h" #ifdef HAVE_XPM #include @@ -56,6 +57,7 @@ Lisp_Object Qmono_pixmap_image_instance_p; Lisp_Object Qcolor_pixmap_image_instance_p; Lisp_Object Qpointer_image_instance_p; Lisp_Object Qsubwindow_image_instance_p; +Lisp_Object Qlayout_image_instance_p; Lisp_Object Qwidget_image_instance_p; Lisp_Object Qconst_glyph_variable; Lisp_Object Qmono_pixmap, Qcolor_pixmap, Qsubwindow; @@ -70,11 +72,14 @@ Lisp_Object Vimage_instantiator_format_list; Lisp_Object Vimage_instance_type_list; Lisp_Object Vglyph_type_list; +int disable_animated_pixmaps; + DEFINE_IMAGE_INSTANTIATOR_FORMAT (nothing); DEFINE_IMAGE_INSTANTIATOR_FORMAT (inherit); DEFINE_IMAGE_INSTANTIATOR_FORMAT (string); DEFINE_IMAGE_INSTANTIATOR_FORMAT (formatted_string); DEFINE_IMAGE_INSTANTIATOR_FORMAT (subwindow); +DEFINE_IMAGE_INSTANTIATOR_FORMAT (text); #ifdef HAVE_WINDOW_SYSTEM DEFINE_IMAGE_INSTANTIATOR_FORMAT (xbm); @@ -122,6 +127,13 @@ static void image_validate (Lisp_Object instantiator); static void glyph_property_was_changed (Lisp_Object glyph, Lisp_Object property, Lisp_Object locale); +static void register_ignored_expose (struct frame* f, int x, int y, int width, int height); +/* Unfortunately windows and X are different. In windows BeginPaint() + will prevent WM_PAINT messages being generated so it is unnecessary + to register exposures as they will not occur. Under X they will + always occur. */ +int hold_ignored_expose_registration; + EXFUN (Fimage_instance_type, 1); EXFUN (Fglyph_type, 1); @@ -179,13 +191,20 @@ valid_image_instantiator_format_p (Lisp_Object format, Lisp_Object locale) int i; struct image_instantiator_methods* meths = decode_image_instantiator_format (format, ERROR_ME_NOT); - struct console* console = decode_console (locale); - Lisp_Object contype = console ? CONSOLE_TYPE (console) : locale; + Lisp_Object contype = Qnil; + /* mess with the locale */ + if (!NILP (locale) && SYMBOLP (locale)) + contype = locale; + else + { + struct console* console = decode_console (locale); + contype = console ? CONSOLE_TYPE (console) : locale; + } /* nothing is valid in all locales */ if (EQ (format, Qnothing)) return 1; /* reject unknown formats */ - else if (!console || !meths) + else if (NILP (contype) || !meths) return 0; for (i = 0; i < Dynarr_length (meths->consoles); i++) @@ -598,40 +617,46 @@ instantiate_image_instantiator (Lisp_Object device, Lisp_Object domain, Lisp_Object Qimage_instancep; static Lisp_Object -mark_image_instance (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_image_instance (Lisp_Object obj) { struct Lisp_Image_Instance *i = XIMAGE_INSTANCE (obj); - markobj (i->name); + mark_object (i->name); switch (IMAGE_INSTANCE_TYPE (i)) { case IMAGE_TEXT: - markobj (IMAGE_INSTANCE_TEXT_STRING (i)); + mark_object (IMAGE_INSTANCE_TEXT_STRING (i)); break; case IMAGE_MONO_PIXMAP: case IMAGE_COLOR_PIXMAP: - markobj (IMAGE_INSTANCE_PIXMAP_FILENAME (i)); - markobj (IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (i)); - markobj (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i)); - markobj (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i)); - markobj (IMAGE_INSTANCE_PIXMAP_FG (i)); - markobj (IMAGE_INSTANCE_PIXMAP_BG (i)); + mark_object (IMAGE_INSTANCE_PIXMAP_FILENAME (i)); + mark_object (IMAGE_INSTANCE_PIXMAP_MASK_FILENAME (i)); + mark_object (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i)); + mark_object (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i)); + mark_object (IMAGE_INSTANCE_PIXMAP_FG (i)); + mark_object (IMAGE_INSTANCE_PIXMAP_BG (i)); break; case IMAGE_WIDGET: - markobj (IMAGE_INSTANCE_WIDGET_TYPE (i)); - markobj (IMAGE_INSTANCE_WIDGET_PROPS (i)); - markobj (IMAGE_INSTANCE_WIDGET_FACE (i)); - markobj (IMAGE_INSTANCE_WIDGET_ITEM (i)); + mark_object (IMAGE_INSTANCE_WIDGET_TYPE (i)); + mark_object (IMAGE_INSTANCE_WIDGET_PROPS (i)); + mark_object (IMAGE_INSTANCE_WIDGET_FACE (i)); + mark_object (IMAGE_INSTANCE_WIDGET_ITEMS (i)); case IMAGE_SUBWINDOW: - markobj (IMAGE_INSTANCE_SUBWINDOW_FRAME (i)); + mark_object (IMAGE_INSTANCE_SUBWINDOW_FRAME (i)); + break; + + case IMAGE_LAYOUT: + mark_object (IMAGE_INSTANCE_LAYOUT_CHILDREN (i)); + mark_object (IMAGE_INSTANCE_LAYOUT_BORDER (i)); + mark_object (IMAGE_INSTANCE_SUBWINDOW_FRAME (i)); break; default: break; } - MAYBE_DEVMETH (XDEVICE (i->device), mark_image_instance, (i, markobj)); + MAYBE_DEVMETH (XDEVICE (i->device), mark_image_instance, (i)); return i->device; } @@ -748,6 +773,7 @@ print_image_instance (Lisp_Object obj, Lisp_Object printcharfun, print_internal (IMAGE_INSTANCE_WIDGET_TEXT (ii), printcharfun, 0); case IMAGE_SUBWINDOW: + case IMAGE_LAYOUT: sprintf (buf, " %dx%d", IMAGE_INSTANCE_SUBWINDOW_WIDTH (ii), IMAGE_INSTANCE_SUBWINDOW_HEIGHT (ii)); write_c_string (buf, printcharfun); @@ -799,7 +825,7 @@ finalize_image_instance (void *header, int for_disksave) || IMAGE_INSTANCE_TYPE (i) == IMAGE_SUBWINDOW) { - MARK_FRAME_GLYPHS_CHANGED + MARK_FRAME_SUBWINDOWS_CHANGED (XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (i))); } @@ -843,6 +869,8 @@ image_instance_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) IMAGE_INSTANCE_PIXMAP_HEIGHT (i2) && IMAGE_INSTANCE_PIXMAP_DEPTH (i1) == IMAGE_INSTANCE_PIXMAP_DEPTH (i2) && + IMAGE_INSTANCE_PIXMAP_SLICE (i1) == + IMAGE_INSTANCE_PIXMAP_SLICE (i2) && EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i1), IMAGE_INSTANCE_PIXMAP_HOTSPOT_X (i2)) && EQ (IMAGE_INSTANCE_PIXMAP_HOTSPOT_Y (i1), @@ -859,14 +887,24 @@ image_instance_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) case IMAGE_WIDGET: if (!(EQ (IMAGE_INSTANCE_WIDGET_TYPE (i1), IMAGE_INSTANCE_WIDGET_TYPE (i2)) - && internal_equal (IMAGE_INSTANCE_WIDGET_ITEM (i1), - IMAGE_INSTANCE_WIDGET_ITEM (i2), + && internal_equal (IMAGE_INSTANCE_WIDGET_ITEMS (i1), + IMAGE_INSTANCE_WIDGET_ITEMS (i2), depth + 1) && internal_equal (IMAGE_INSTANCE_WIDGET_PROPS (i1), IMAGE_INSTANCE_WIDGET_PROPS (i2), depth + 1) )) return 0; + case IMAGE_LAYOUT: + if (IMAGE_INSTANCE_TYPE (i1) == IMAGE_LAYOUT + && + !(EQ (IMAGE_INSTANCE_LAYOUT_BORDER (i1), + IMAGE_INSTANCE_LAYOUT_BORDER (i2)) + && + internal_equal (IMAGE_INSTANCE_LAYOUT_CHILDREN (i1), + IMAGE_INSTANCE_LAYOUT_CHILDREN (i2), + depth + 1))) + return 0; case IMAGE_SUBWINDOW: if (!(IMAGE_INSTANCE_SUBWINDOW_WIDTH (i1) == IMAGE_INSTANCE_SUBWINDOW_WIDTH (i2) && @@ -904,9 +942,10 @@ image_instance_hash (Lisp_Object obj, int depth) case IMAGE_MONO_PIXMAP: case IMAGE_COLOR_PIXMAP: case IMAGE_POINTER: - hash = HASH5 (hash, IMAGE_INSTANCE_PIXMAP_WIDTH (i), + hash = HASH6 (hash, IMAGE_INSTANCE_PIXMAP_WIDTH (i), IMAGE_INSTANCE_PIXMAP_HEIGHT (i), IMAGE_INSTANCE_PIXMAP_DEPTH (i), + IMAGE_INSTANCE_PIXMAP_SLICE (i), internal_hash (IMAGE_INSTANCE_PIXMAP_FILENAME (i), depth + 1)); break; @@ -915,7 +954,13 @@ image_instance_hash (Lisp_Object obj, int depth) hash = HASH4 (hash, internal_hash (IMAGE_INSTANCE_WIDGET_TYPE (i), depth + 1), internal_hash (IMAGE_INSTANCE_WIDGET_PROPS (i), depth + 1), - internal_hash (IMAGE_INSTANCE_WIDGET_ITEM (i), depth + 1)); + internal_hash (IMAGE_INSTANCE_WIDGET_ITEMS (i), depth + 1)); + case IMAGE_LAYOUT: + if (IMAGE_INSTANCE_TYPE (i) == IMAGE_LAYOUT) + hash = HASH3 (hash, + internal_hash (IMAGE_INSTANCE_LAYOUT_BORDER (i), depth + 1), + internal_hash (IMAGE_INSTANCE_LAYOUT_CHILDREN (i), + depth + 1)); case IMAGE_SUBWINDOW: hash = HASH4 (hash, IMAGE_INSTANCE_SUBWINDOW_WIDTH (i), IMAGE_INSTANCE_SUBWINDOW_HEIGHT (i), @@ -947,6 +992,8 @@ allocate_image_instance (Lisp_Object device) lp->device = device; lp->type = IMAGE_NOTHING; lp->name = Qnil; + lp->x_offset = 0; + lp->y_offset = 0; XSETIMAGE_INSTANCE (val, lp); return val; } @@ -964,6 +1011,7 @@ decode_image_instance_type (Lisp_Object type, Error_behavior errb) if (EQ (type, Qpointer)) return IMAGE_POINTER; if (EQ (type, Qsubwindow)) return IMAGE_SUBWINDOW; if (EQ (type, Qwidget)) return IMAGE_WIDGET; + if (EQ (type, Qlayout)) return IMAGE_LAYOUT; maybe_signal_simple_error ("Invalid image-instance type", type, Qimage, errb); @@ -983,6 +1031,7 @@ encode_image_instance_type (enum image_instance_type type) case IMAGE_POINTER: return Qpointer; case IMAGE_SUBWINDOW: return Qsubwindow; case IMAGE_WIDGET: return Qwidget; + case IMAGE_LAYOUT: return Qlayout; default: abort (); } @@ -995,7 +1044,7 @@ image_instance_type_to_mask (enum image_instance_type type) { /* This depends on the fact that enums are assigned consecutive integers starting at 0. (Remember that IMAGE_UNKNOWN is the - first enum.) I'm fairly sure this behavior in ANSI-mandated, + first enum.) I'm fairly sure this behavior is ANSI-mandated, so there should be no portability problems here. */ return (1 << ((int) (type) - 1)); } @@ -1166,7 +1215,9 @@ be generated. The recognized image instance types are 'subwindow A child window that is treated as an image. This allows (e.g.) another program to be responsible for drawing into the window. - Not currently implemented. +'widget + A child window that contains a window-system widget, e.g. a push + button. The DEST-TYPES list is unordered. If multiple destination types are possible for a given instantiator, the "most natural" type @@ -1188,7 +1239,7 @@ If DEST-TYPES is omitted, all possible types are allowed. NO-ERROR controls what happens when the image cannot be generated. If nil, an error message is generated. If t, no messages are generated and this function returns nil. If anything else, a warning -message is generated and this function returns nil. +message is generated and this function returns nil. */ (data, device, dest_types, no_error)) { @@ -1302,18 +1353,30 @@ the image instance in the domain. !UNBOUNDP (ret = IIFORMAT_METH (meths, set_property, (image_instance, prop, val)))) { - return ret; + val = ret; } - /* ... then format specific methods ... */ - meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT); - if (meths && HAS_IIFORMAT_METH_P (meths, set_property) - && - !UNBOUNDP (ret = - IIFORMAT_METH (meths, set_property, (image_instance, prop, val)))) + else { - return ret; + /* ... then format specific methods ... */ + meths = decode_device_ii_format (Qnil, type, ERROR_ME_NOT); + if (meths && HAS_IIFORMAT_METH_P (meths, set_property) + && + !UNBOUNDP (ret = + IIFORMAT_METH (meths, set_property, (image_instance, prop, val)))) + { + val = ret; + } + else + { + val = Qnil; + } } + /* Make sure the image instance gets redisplayed. */ + MARK_IMAGE_INSTANCE_CHANGED (ii); + MARK_SUBWINDOWS_STATE_CHANGED; + MARK_GLYPHS_CHANGED; + return val; } @@ -1391,6 +1454,7 @@ Return the height of the image instance, in pixels. case IMAGE_SUBWINDOW: case IMAGE_WIDGET: + case IMAGE_LAYOUT: return make_int (XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (image_instance)); default: @@ -1414,6 +1478,7 @@ Return the width of the image instance, in pixels. case IMAGE_SUBWINDOW: case IMAGE_WIDGET: + case IMAGE_LAYOUT: return make_int (XIMAGE_INSTANCE_SUBWINDOW_WIDTH (image_instance)); default: @@ -1670,6 +1735,23 @@ string_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, incompatible_image_types (instantiator, dest_mask, IMAGE_TEXT_MASK); } +/* set the properties of a string */ +static Lisp_Object +text_set_property (Lisp_Object image_instance, Lisp_Object prop, + Lisp_Object val) +{ + struct Lisp_Image_Instance *ii = XIMAGE_INSTANCE (image_instance); + + if (EQ (prop, Q_data)) + { + CHECK_STRING (val); + IMAGE_INSTANCE_TEXT_STRING (ii) = val; + + return Qt; + } + return Qunbound; +} + /**************************************************************************** * formatted-string * @@ -2334,12 +2416,12 @@ image_create (Lisp_Object obj) } static void -image_mark (Lisp_Object obj, void (*markobj) (Lisp_Object)) +image_mark (Lisp_Object obj) { struct Lisp_Specifier *image = XIMAGE_SPECIFIER (obj); - markobj (IMAGE_SPECIFIER_ATTACHEE (image)); - markobj (IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image)); + mark_object (IMAGE_SPECIFIER_ATTACHEE (image)); + mark_object (IMAGE_SPECIFIER_ATTACHEE_PROPERTY (image)); } static Lisp_Object @@ -2733,9 +2815,21 @@ pairs. FORMAT should be one of Currently can only be instanced as `pointer', although this should probably be fixed.) 'subwindow - (An embedded X window; not currently implemented.) -'widget - (A widget control, for instance text field or radio button.) + (An embedded windowing system window.) +'edit-field + (A text editing widget glyph.) +'button + (A button widget glyph; either a push button, radio button or toggle button.) +'tab-control + (A tab widget glyph; a series of user selectable tabs.) +'progress-gauge + (A sliding widget glyph, for showing progress.) +'combo-box + (A drop list of selectable items in a widget glyph, for editing text.) +'label + (A static, text-only, widget glyph; for displaying text.) +'tree-view + (A folding widget glyph.) 'autodetect (XEmacs tries to guess what format the data is in. If X support exists, the data string will be checked to see if it names a filename. @@ -2797,7 +2891,14 @@ The valid keywords are: object). If this is not specified, the contents of `xpm-color-symbols' are used to generate the alist.) :face - (Only for `inherit'. This specifies the face to inherit from.) + (Only for `inherit'. This specifies the face to inherit from. + For widget glyphs this also specifies the face to use for + display. It defaults to gui-element-face.) + +Keywords accepted as menu item specs are also accepted by widget +glyphs. These are `:selected', `:active', `:suffix', `:keys', +`:style', `:filter', `:config', `:included', `:key-sequence', +`:accelerator', `:label' and `:callback'. If instead of a vector, the instantiator is a string, it will be converted into a vector by looking it up according to the specs in the @@ -2825,14 +2926,14 @@ file). ****************************************************************************/ static Lisp_Object -mark_glyph (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_glyph (Lisp_Object obj) { struct Lisp_Glyph *glyph = XGLYPH (obj); - markobj (glyph->image); - markobj (glyph->contrib_p); - markobj (glyph->baseline); - markobj (glyph->face); + mark_object (glyph->image); + mark_object (glyph->contrib_p); + mark_object (glyph->baseline); + mark_object (glyph->face); return glyph->plist; } @@ -2902,9 +3003,9 @@ glyph_getprop (Lisp_Object obj, Lisp_Object prop) static int glyph_putprop (Lisp_Object obj, Lisp_Object prop, Lisp_Object value) { - if ((EQ (prop, Qimage)) || - (EQ (prop, Qcontrib_p)) || - (EQ (prop, Qbaseline))) + if (EQ (prop, Qimage) || + EQ (prop, Qcontrib_p) || + EQ (prop, Qbaseline)) return 0; if (EQ (prop, Qface)) @@ -2920,9 +3021,9 @@ glyph_putprop (Lisp_Object obj, Lisp_Object prop, Lisp_Object value) static int glyph_remprop (Lisp_Object obj, Lisp_Object prop) { - if ((EQ (prop, Qimage)) || - (EQ (prop, Qcontrib_p)) || - (EQ (prop, Qbaseline))) + if (EQ (prop, Qimage) || + EQ (prop, Qcontrib_p) || + EQ (prop, Qbaseline)) return -1; if (EQ (prop, Qface)) @@ -2972,13 +3073,15 @@ allocate_glyph (enum glyph_type type, g->type = type; g->image = Fmake_specifier (Qimage); /* This function can GC */ + g->dirty = 0; switch (g->type) { case GLYPH_BUFFER: XIMAGE_SPECIFIER_ALLOWED (g->image) = IMAGE_NOTHING_MASK | IMAGE_TEXT_MASK | IMAGE_MONO_PIXMAP_MASK | IMAGE_COLOR_PIXMAP_MASK - | IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK; + | IMAGE_SUBWINDOW_MASK | IMAGE_WIDGET_MASK + | IMAGE_LAYOUT_MASK; break; case GLYPH_POINTER: XIMAGE_SPECIFIER_ALLOWED (g->image) = @@ -3127,18 +3230,16 @@ The return value will be one of 'buffer, 'pointer, or 'icon. the given FACE, unless a face is defined by the glyph itself. ****************************************************************************/ unsigned short -glyph_width (Lisp_Object glyph, Lisp_Object frame_face, +glyph_width (Lisp_Object glyph_or_image, Lisp_Object frame_face, face_index window_findex, Lisp_Object window) { - Lisp_Object instance; + Lisp_Object instance = glyph_or_image; Lisp_Object frame = XWINDOW (window)->frame; /* #### We somehow need to distinguish between the user causing this error condition and a bug causing it. */ - if (!GLYPHP (glyph)) - return 0; - else - instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1); + if (GLYPHP (glyph_or_image)) + instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1); if (!IMAGE_INSTANCEP (instance)) return 0; @@ -3148,7 +3249,10 @@ glyph_width (Lisp_Object glyph, Lisp_Object frame_face, case IMAGE_TEXT: { Lisp_Object str = XIMAGE_INSTANCE_TEXT_STRING (instance); - Lisp_Object private_face = XGLYPH_FACE(glyph); + Lisp_Object private_face = Qnil; + + if (GLYPHP (glyph_or_image)) + private_face = XGLYPH_FACE(glyph_or_image); if (!NILP (private_face)) return redisplay_frame_text_width_string (XFRAME (frame), @@ -3175,6 +3279,7 @@ glyph_width (Lisp_Object glyph, Lisp_Object frame_face, case IMAGE_SUBWINDOW: case IMAGE_WIDGET: + case IMAGE_LAYOUT: return XIMAGE_INSTANCE_SUBWINDOW_WIDTH (instance); default: @@ -3213,17 +3318,15 @@ glyph_image_instance (Lisp_Object glyph, Lisp_Object domain, } static unsigned short -glyph_height_internal (Lisp_Object glyph, Lisp_Object frame_face, +glyph_height_internal (Lisp_Object glyph_or_image, Lisp_Object frame_face, face_index window_findex, Lisp_Object window, int function) { - Lisp_Object instance; + Lisp_Object instance = glyph_or_image; Lisp_Object frame = XWINDOW (window)->frame; - if (!GLYPHP (glyph)) - return 0; - else - instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1); + if (GLYPHP (glyph_or_image)) + instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1); if (!IMAGE_INSTANCEP (instance)) return 0; @@ -3279,6 +3382,7 @@ glyph_height_internal (Lisp_Object glyph, Lisp_Object frame_face, case IMAGE_SUBWINDOW: case IMAGE_WIDGET: + case IMAGE_LAYOUT: /* #### Ugh ugh ugh -- temporary crap */ if (function == RETURN_ASCENT || function == RETURN_HEIGHT) return XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (instance); @@ -3360,6 +3464,35 @@ that redisplay will. #undef RETURN_DESCENT #undef RETURN_HEIGHT +static unsigned int +glyph_dirty_p (Lisp_Object glyph_or_image, Lisp_Object window) +{ + Lisp_Object instance = glyph_or_image; + + if (GLYPHP (glyph_or_image)) + instance = glyph_image_instance (glyph_or_image, window, ERROR_ME_NOT, 1); + + return XIMAGE_INSTANCE_DIRTYP (instance); +} + +static void +set_glyph_dirty_p (Lisp_Object glyph_or_image, Lisp_Object window, int dirty) +{ + Lisp_Object instance = glyph_or_image; + + if (!NILP (glyph_or_image)) + { + if (GLYPHP (glyph_or_image)) + { + instance = glyph_image_instance (glyph_or_image, window, + ERROR_ME_NOT, 1); + XGLYPH_DIRTYP (glyph_or_image) = dirty; + } + + XIMAGE_INSTANCE_DIRTYP (instance) = dirty; + } +} + /* #### do we need to cache this info to speed things up? */ Lisp_Object @@ -3422,12 +3555,10 @@ glyph_property_was_changed (Lisp_Object glyph, Lisp_Object property, /* #### All of this is 95% copied from face cachels. Consider consolidating. - #### We need to add a dirty flag to the glyphs. */ void -mark_glyph_cachels (glyph_cachel_dynarr *elements, - void (*markobj) (Lisp_Object)) +mark_glyph_cachels (glyph_cachel_dynarr *elements) { int elt; @@ -3437,7 +3568,7 @@ mark_glyph_cachels (glyph_cachel_dynarr *elements, for (elt = 0; elt < Dynarr_length (elements); elt++) { struct glyph_cachel *cachel = Dynarr_atp (elements, elt); - markobj (cachel->glyph); + mark_object (cachel->glyph); } } @@ -3445,19 +3576,21 @@ static void update_glyph_cachel_data (struct window *w, Lisp_Object glyph, struct glyph_cachel *cachel) { - /* #### This should be || !cachel->updated */ - if (NILP (cachel->glyph) || !EQ (cachel->glyph, glyph)) + if (!cachel->updated || NILP (cachel->glyph) || !EQ (cachel->glyph, glyph) + || XGLYPH_DIRTYP (cachel->glyph)) { - Lisp_Object window; + Lisp_Object window, instance; XSETWINDOW (window, w); - /* #### This could be sped up if we redid things to grab the glyph - instantiation and passed it to the size functions. */ cachel->glyph = glyph; - cachel->width = glyph_width (glyph, Qnil, DEFAULT_INDEX, window); - cachel->ascent = glyph_ascent (glyph, Qnil, DEFAULT_INDEX, window); - cachel->descent = glyph_descent (glyph, Qnil, DEFAULT_INDEX, window); + /* Speed things up slightly by grabbing the glyph instantiation + and passing it to the size functions. */ + instance = glyph_image_instance (glyph, window, ERROR_ME_NOT, 1); + cachel->dirty = XGLYPH_DIRTYP (glyph) = glyph_dirty_p (glyph, window); + cachel->width = glyph_width (instance, Qnil, DEFAULT_INDEX, window); + cachel->ascent = glyph_ascent (instance, Qnil, DEFAULT_INDEX, window); + cachel->descent = glyph_descent (instance, Qnil, DEFAULT_INDEX, window); } cachel->updated = 1; @@ -3475,7 +3608,7 @@ add_glyph_cachel (struct window *w, Lisp_Object glyph) Dynarr_add (w->glyph_cachels, new_cachel); } -static glyph_index +glyph_index get_glyph_cachel_index (struct window *w, Lisp_Object glyph) { int elt; @@ -3490,8 +3623,7 @@ get_glyph_cachel_index (struct window *w, Lisp_Object glyph) if (EQ (cachel->glyph, glyph) && !NILP (glyph)) { - if (!cachel->updated) - update_glyph_cachel_data (w, glyph, cachel); + update_glyph_cachel_data (w, glyph, cachel); return elt; } } @@ -3534,7 +3666,24 @@ mark_glyph_cachels_as_not_updated (struct window *w) #undef FROB for (elt = 0; elt < Dynarr_length (w->glyph_cachels); elt++) - Dynarr_atp (w->glyph_cachels, elt)->updated = 0; + { + Dynarr_atp (w->glyph_cachels, elt)->updated = 0; + } +} + +/* Unset the dirty bit on all the glyph cachels that have it. */ +void +mark_glyph_cachels_as_clean (struct window* w) +{ + int elt; + Lisp_Object window; + XSETWINDOW (window, w); + for (elt = 0; elt < Dynarr_length (w->glyph_cachels); elt++) + { + struct glyph_cachel *cachel = Dynarr_atp (w->glyph_cachels, elt); + cachel->dirty = 0; + set_glyph_dirty_p (cachel->glyph, window, 0); + } } #ifdef MEMORY_USAGE_STATS @@ -3568,7 +3717,7 @@ compute_glyph_cachel_usage (glyph_cachel_dynarr *glyph_cachels, obscuring an area that we want to clear. We need to be able to flip through this quickly so a hashtable is not suitable hence the subwindow_cachels. The question is should we just not mark - instances in the subwindow_cachelsnor should we try and invalidate + instances in the subwindow_cachels or should we try and invalidate the cache at suitable points in redisplay? If we don't invalidate the cache it will fill up with crud that will only get removed when the frame is deleted. So invalidation is good, the question is when @@ -3576,8 +3725,7 @@ compute_glyph_cachel_usage (glyph_cachel_dynarr *glyph_cachels, MARK_SUBWINDOWS_CHANGED when a subwindow gets deleted. */ void -mark_subwindow_cachels (subwindow_cachel_dynarr *elements, - void (*markobj) (Lisp_Object)) +mark_subwindow_cachels (subwindow_cachel_dynarr *elements) { int elt; @@ -3587,7 +3735,7 @@ mark_subwindow_cachels (subwindow_cachel_dynarr *elements, for (elt = 0; elt < Dynarr_length (elements); elt++) { struct subwindow_cachel *cachel = Dynarr_atp (elements, elt); - markobj (cachel->subwindow); + mark_object (cachel->subwindow); } } @@ -3595,13 +3743,9 @@ static void update_subwindow_cachel_data (struct frame *f, Lisp_Object subwindow, struct subwindow_cachel *cachel) { - if (NILP (cachel->subwindow) || !EQ (cachel->subwindow, subwindow)) - { - cachel->subwindow = subwindow; - cachel->width = XIMAGE_INSTANCE_SUBWINDOW_WIDTH (subwindow); - cachel->height = XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (subwindow); - } - + cachel->subwindow = subwindow; + cachel->width = XIMAGE_INSTANCE_SUBWINDOW_WIDTH (subwindow); + cachel->height = XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (subwindow); cachel->updated = 1; } @@ -3646,6 +3790,29 @@ get_subwindow_cachel_index (struct frame *f, Lisp_Object subwindow) return elt; } +static void +update_subwindow_cachel (Lisp_Object subwindow) +{ + struct frame* f; + int elt; + + if (NILP (subwindow)) + return; + + f = XFRAME ( XIMAGE_INSTANCE_SUBWINDOW_FRAME (subwindow)); + + for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++) + { + struct subwindow_cachel *cachel = + Dynarr_atp (f->subwindow_cachels, elt); + + if (EQ (cachel->subwindow, subwindow) && !NILP (subwindow)) + { + update_subwindow_cachel_data (f, subwindow, cachel); + } + } +} + /* redisplay in general assumes that drawing something will erase what was there before. unfortunately this does not apply to subwindows that need to be specifically unmapped in order to @@ -3662,8 +3829,10 @@ reset_subwindow_cachels (struct frame *f) if (!NILP (cachel->subwindow) && cachel->being_displayed) { - struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (cachel->subwindow); - MAYBE_DEVMETH (XDEVICE (f->device), unmap_subwindow, (ii)); + cachel->updated = 1; + /* #### This is not optimal as update_subwindow will search + the cachels for ourselves as well. We could easily optimize. */ + unmap_subwindow (cachel->subwindow); } } Dynarr_reset (f->subwindow_cachels); @@ -3678,6 +3847,119 @@ mark_subwindow_cachels_as_not_updated (struct frame *f) Dynarr_atp (f->subwindow_cachels, elt)->updated = 0; } + + +/***************************************************************************** + * subwindow exposure ignorance * + *****************************************************************************/ +/* when we unmap subwindows the associated window system will generate + expose events. This we do not want as redisplay already copes with + the repainting necessary. Worse, we can get in an endless cycle of + redisplay if we are not careful. Thus we keep a per-frame list of + expose events that are going to come and ignore them as + required. */ + +struct expose_ignore_blocktype +{ + Blocktype_declare (struct expose_ignore); +} *the_expose_ignore_blocktype; + +int +check_for_ignored_expose (struct frame* f, int x, int y, int width, int height) +{ + struct expose_ignore *ei, *prev; + /* the ignore list is FIFO so we should generally get a match with + the first element in the list */ + for (ei = f->subwindow_exposures, prev = 0; ei; ei = ei->next) + { + /* Checking for exact matches just isn't good enough as we + mighte get exposures for partially obscure subwindows, thus + we have to check for overlaps. Being conservative we will + check for exposures wholly contained by the subwindow, this + might give us what we want.*/ + if (ei->x <= x && ei->y <= y + && ei->x + ei->width >= x + width + && ei->y + ei->height >= y + height) + { +#ifdef DEBUG_WIDGETS + stderr_out ("ignored %d+%d, %dx%d for exposure %d+%d, %dx%d\n", + x, y, width, height, ei->x, ei->y, ei->width, ei->height); +#endif + if (!prev) + f->subwindow_exposures = ei->next; + else + prev->next = ei->next; + + if (ei == f->subwindow_exposures_tail) + f->subwindow_exposures_tail = prev; + + Blocktype_free (the_expose_ignore_blocktype, ei); + return 1; + } + prev = ei; + } + return 0; +} + +static void +register_ignored_expose (struct frame* f, int x, int y, int width, int height) +{ + if (!hold_ignored_expose_registration) + { + struct expose_ignore *ei; + + ei = Blocktype_alloc (the_expose_ignore_blocktype); + + ei->next = NULL; + ei->x = x; + ei->y = y; + ei->width = width; + ei->height = height; + + /* we have to add the exposure to the end of the list, since we + want to check the oldest events first. for speed we keep a record + of the end so that we can add right to it. */ + if (f->subwindow_exposures_tail) + { + f->subwindow_exposures_tail->next = ei; + } + if (!f->subwindow_exposures) + { + f->subwindow_exposures = ei; + } + f->subwindow_exposures_tail = ei; + } +} + +/**************************************************************************** + find_matching_subwindow + + See if there is a subwindow that completely encloses the requested + area. + ****************************************************************************/ +int find_matching_subwindow (struct frame* f, int x, int y, int width, int height) +{ + int elt; + + for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++) + { + struct subwindow_cachel *cachel = + Dynarr_atp (f->subwindow_cachels, elt); + + if (cachel->being_displayed + && + cachel->x <= x && cachel->y <= y + && + cachel->x + cachel->width >= x + width + && + cachel->y + cachel->height >= y + height) + { + return 1; + } + } + return 0; +} + /***************************************************************************** * subwindow functions * @@ -3702,7 +3984,7 @@ update_frame_subwindows (struct frame *f) { int elt; - if (f->subwindows_changed || f->glyphs_changed) + if (f->subwindows_changed || f->subwindows_state_changed || f->faces_changed) for (elt = 0; elt < Dynarr_length (f->subwindow_cachels); elt++) { struct subwindow_cachel *cachel = @@ -3729,11 +4011,15 @@ void unmap_subwindow (Lisp_Object subwindow) || NILP (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii))) return; - +#ifdef DEBUG_WIDGETS + stderr_out ("unmapping subwindow %d\n", IMAGE_INSTANCE_SUBWINDOW_ID (ii)); +#endif f = XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)); elt = get_subwindow_cachel_index (f, subwindow); cachel = Dynarr_atp (f->subwindow_cachels, elt); + /* make sure we don't get expose events */ + register_ignored_expose (f, cachel->x, cachel->y, cachel->width, cachel->height); cachel->x = -1; cachel->y = -1; cachel->being_displayed = 0; @@ -3743,7 +4029,8 @@ void unmap_subwindow (Lisp_Object subwindow) } /* show a subwindow in its frame */ -void map_subwindow (Lisp_Object subwindow, int x, int y) +void map_subwindow (Lisp_Object subwindow, int x, int y, + struct display_glyph_area *dga) { struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (subwindow); int elt; @@ -3757,15 +4044,22 @@ void map_subwindow (Lisp_Object subwindow, int x, int y) NILP (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii))) return; +#ifdef DEBUG_WIDGETS + stderr_out ("mapping subwindow %d, %dx%d@%d+%d\n", + IMAGE_INSTANCE_SUBWINDOW_ID (ii), + dga->width, dga->height, x, y); +#endif f = XFRAME (IMAGE_INSTANCE_SUBWINDOW_FRAME (ii)); IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 1; elt = get_subwindow_cachel_index (f, subwindow); cachel = Dynarr_atp (f->subwindow_cachels, elt); cachel->x = x; cachel->y = y; + cachel->width = dga->width; + cachel->height = dga->height; cachel->being_displayed = 1; - MAYBE_DEVMETH (XDEVICE (ii->device), map_subwindow, (ii, x, y)); + MAYBE_DEVMETH (XDEVICE (ii->device), map_subwindow, (ii, x, y, dga)); } static int @@ -3794,7 +4088,6 @@ subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, ii->data = 0; IMAGE_INSTANCE_SUBWINDOW_ID (ii) = 0; - IMAGE_INSTANCE_SUBWINDOW_FRAME (ii) = Qnil; IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (ii) = 0; IMAGE_INSTANCE_SUBWINDOW_FRAME (ii) = frame; @@ -3836,7 +4129,7 @@ Return the window id of SUBWINDOW as a number. (subwindow)) { CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow); - return make_int ((int) (XIMAGE_INSTANCE_SUBWINDOW_ID (subwindow))); + return make_int ((int) XIMAGE_INSTANCE_SUBWINDOW_ID (subwindow)); } DEFUN ("resize-subwindow", Fresize_subwindow, 1, 3, 0, /* @@ -3866,6 +4159,9 @@ If a value is nil that parameter is not changed. XIMAGE_INSTANCE_SUBWINDOW_HEIGHT (subwindow) = newh; XIMAGE_INSTANCE_SUBWINDOW_WIDTH (subwindow) = neww; + /* need to update the cachels as redisplay will not do this */ + update_subwindow_cachel (subwindow); + return subwindow; } @@ -3875,9 +4171,9 @@ Generate a Map event for SUBWINDOW. (subwindow)) { CHECK_SUBWINDOW_IMAGE_INSTANCE (subwindow); - +#if 0 map_subwindow (subwindow, 0, 0); - +#endif return subwindow; } @@ -3963,6 +4259,80 @@ display_table_entry (Emchar ch, Lisp_Object face_table, abort (); } } + +/***************************************************************************** + * timeouts for animated glyphs * + *****************************************************************************/ +static Lisp_Object Qglyph_animated_timeout_handler; + +DEFUN ("glyph-animated-timeout-handler", Fglyph_animated_timeout_handler, 1, 1, 0, /* +Callback function for updating animated images. +Don't use this. +*/ + (arg)) +{ + CHECK_WEAK_LIST (arg); + + if (!NILP (XWEAK_LIST_LIST (arg)) && !NILP (XCAR (XWEAK_LIST_LIST (arg)))) + { + Lisp_Object value = XCAR (XWEAK_LIST_LIST (arg)); + + if (IMAGE_INSTANCEP (value)) + { + struct Lisp_Image_Instance* ii = XIMAGE_INSTANCE (value); + + if (COLOR_PIXMAP_IMAGE_INSTANCEP (value) + && + IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii) > 1 + && + !disable_animated_pixmaps) + { + /* Increment the index of the image slice we are currently + viewing. */ + IMAGE_INSTANCE_PIXMAP_SLICE (ii) = + (IMAGE_INSTANCE_PIXMAP_SLICE (ii) + 1) + % IMAGE_INSTANCE_PIXMAP_MAXSLICE (ii); + /* We might need to kick redisplay at this point - but we + also might not. */ + MARK_DEVICE_FRAMES_GLYPHS_CHANGED + (XDEVICE (IMAGE_INSTANCE_DEVICE (ii))); + IMAGE_INSTANCE_DIRTYP (ii) = 1; + } + } + } + return Qnil; +} + +Lisp_Object add_glyph_animated_timeout (EMACS_INT tickms, Lisp_Object image) +{ + Lisp_Object ret = Qnil; + + if (tickms > 0 && IMAGE_INSTANCEP (image)) + { + double ms = ((double)tickms) / 1000.0; + struct gcpro gcpro1; + Lisp_Object holder = make_weak_list (WEAK_LIST_SIMPLE); + + GCPRO1 (holder); + XWEAK_LIST_LIST (holder) = Fcons (image, Qnil); + + ret = Fadd_timeout (make_float (ms), + Qglyph_animated_timeout_handler, + holder, make_float (ms)); + + UNGCPRO; + } + return ret; +} + +void disable_glyph_animated_timeout (int i) +{ + Lisp_Object id; + XSETINT (id, i); + + Fdisable_timeout (id); +} + /***************************************************************************** * initialization * @@ -4011,6 +4381,7 @@ syms_of_glyphs (void) defsymbol (&Qpointer_image_instance_p, "pointer-image-instance-p"); defsymbol (&Qwidget_image_instance_p, "widget-image-instance-p"); defsymbol (&Qsubwindow_image_instance_p, "subwindow-image-instance-p"); + defsymbol (&Qlayout_image_instance_p, "layout-image-instance-p"); DEFSUBR (Fmake_image_instance); DEFSUBR (Fimage_instance_p); @@ -4069,6 +4440,12 @@ syms_of_glyphs (void) /* Qbuffer defined in general.c. */ /* Qpointer defined above */ + /* Unfortunately, timeout handlers must be lisp functions. This is + for animated glyphs. */ + defsymbol (&Qglyph_animated_timeout_handler, + "glyph-animated-timeout-handler"); + DEFSUBR (Fglyph_animated_timeout_handler); + /* Errors */ deferror (&Qimage_conversion_error, "image-conversion-error", @@ -4076,6 +4453,11 @@ syms_of_glyphs (void) } +static const struct lrecord_description image_specifier_description[] = { + { XD_LISP_OBJECT, specifier_data_offset + offsetof(struct image_specifier, attachee), 2 }, + { XD_END } +}; + void specifier_type_create_image (void) { @@ -4092,6 +4474,66 @@ specifier_type_create_image (void) } void +reinit_specifier_type_create_image (void) +{ + REINITIALIZE_SPECIFIER_TYPE (image); +} + + +static const struct lrecord_description iike_description_1[] = { + { XD_LISP_OBJECT, offsetof(ii_keyword_entry, keyword), 1 }, + { XD_END } +}; + +static const struct struct_description iike_description = { + sizeof(ii_keyword_entry), + iike_description_1 +}; + +static const struct lrecord_description iiked_description_1[] = { + XD_DYNARR_DESC(ii_keyword_entry_dynarr, &iike_description), + { XD_END } +}; + +static const struct struct_description iiked_description = { + sizeof(ii_keyword_entry_dynarr), + iiked_description_1 +}; + +static const struct lrecord_description iife_description_1[] = { + { XD_LISP_OBJECT, offsetof(image_instantiator_format_entry, symbol), 2 }, + { XD_STRUCT_PTR, offsetof(image_instantiator_format_entry, meths), 1, &iim_description }, + { XD_END } +}; + +static const struct struct_description iife_description = { + sizeof(image_instantiator_format_entry), + iife_description_1 +}; + +static const struct lrecord_description iifed_description_1[] = { + XD_DYNARR_DESC(image_instantiator_format_entry_dynarr, &iife_description), + { XD_END } +}; + +static const struct struct_description iifed_description = { + sizeof(image_instantiator_format_entry_dynarr), + iifed_description_1 +}; + +static const struct lrecord_description iim_description_1[] = { + { XD_LISP_OBJECT, offsetof(struct image_instantiator_methods, symbol), 2 }, + { XD_STRUCT_PTR, offsetof(struct image_instantiator_methods, keywords), 1, &iiked_description }, + { XD_STRUCT_PTR, offsetof(struct image_instantiator_methods, consoles), 1, &cted_description }, + { XD_END } +}; + +const struct struct_description iim_description = { + sizeof(struct image_instantiator_methods), + iim_description_1 +}; + +void image_instantiator_format_create (void) { /* image instantiators */ @@ -4102,6 +4544,8 @@ image_instantiator_format_create (void) Vimage_instantiator_format_list = Qnil; staticpro (&Vimage_instantiator_format_list); + dumpstruct (&the_image_instantiator_format_entry_dynarr, &iifed_description); + INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (nothing, "nothing"); IIFORMAT_HAS_METHOD (nothing, possible_dest_types); @@ -4123,6 +4567,9 @@ image_instantiator_format_create (void) IIFORMAT_HAS_METHOD (string, instantiate); IIFORMAT_VALID_KEYWORD (string, Q_data, check_valid_string); + /* Do this so we can set strings. */ + INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (text, "text"); + IIFORMAT_HAS_METHOD (text, set_property); INITIALIZE_IMAGE_INSTANTIATOR_FORMAT (formatted_string, "formatted-string"); @@ -4184,8 +4631,20 @@ image_instantiator_format_create (void) } void +reinit_vars_of_glyphs (void) +{ + the_expose_ignore_blocktype = + Blocktype_new (struct expose_ignore_blocktype); + + hold_ignored_expose_registration = 0; +} + + +void vars_of_glyphs (void) { + reinit_vars_of_glyphs (); + Vthe_nothing_vector = vector1 (Qnothing); staticpro (&Vthe_nothing_vector); @@ -4251,6 +4710,12 @@ The default value of this variable defines the logical color names #ifdef HAVE_XFACE Fprovide (Qxface); #endif + + DEFVAR_BOOL ("disable-animated-pixmaps", &disable_animated_pixmaps /* +Whether animated pixmaps should be animated. +Default is t. +*/); + disable_animated_pixmaps = 0; } void diff --git a/src/glyphs.h b/src/glyphs.h index 2780192..b0e65f1 100644 --- a/src/glyphs.h +++ b/src/glyphs.h @@ -56,8 +56,11 @@ struct image_instantiator_methods; inherit mono-pixmap autodetect mono-pixmap, color-pixmap, pointer, text button widget - edit widget - combo widget + edit-field widget + combo -box widget + progress-gauge widget + tab-control widget + tree-view widget scrollbar widget static widget */ @@ -78,6 +81,8 @@ typedef struct Dynarr_declare (ii_keyword_entry); } ii_keyword_entry_dynarr; +extern const struct struct_description iim_description; + struct image_instantiator_methods { Lisp_Object symbol; @@ -176,12 +181,14 @@ do { \ Dynarr_new (console_type_entry); \ add_entry_to_image_instantiator_format_list \ (Q##format, format##_image_instantiator_methods); \ + dumpstruct (&format##_image_instantiator_methods, \ + &iim_description); \ } while (0) #define INITIALIZE_IMAGE_INSTANTIATOR_FORMAT(format, obj_name) \ do { \ defsymbol (&Q##format, obj_name); \ - INITIALIZE_IMAGE_INSTANTIATOR_FORMAT_NO_SYM(format, obj_name); \ + INITIALIZE_IMAGE_INSTANTIATOR_FORMAT_NO_SYM(format, obj_name);\ } while (0) /* Declare that image-instantiator format FORMAT has method M; used in @@ -235,23 +242,27 @@ do { \ DECLARE_IMAGE_INSTANTIATOR_FORMAT(format); \ struct image_instantiator_methods *type##_##format##_image_instantiator_methods -#define INITIALIZE_DEVICE_IIFORMAT(type, format) \ -do { \ - type##_##format##_image_instantiator_methods = \ - xnew_and_zero (struct image_instantiator_methods); \ +#define INITIALIZE_DEVICE_IIFORMAT(type, format) \ +do { \ + type##_##format##_image_instantiator_methods = \ + xnew_and_zero (struct image_instantiator_methods); \ type##_##format##_image_instantiator_methods->symbol = Q##format; \ type##_##format##_image_instantiator_methods->device = Q##type; \ type##_##format##_image_instantiator_methods->keywords = \ - Dynarr_new (ii_keyword_entry); \ - add_entry_to_device_ii_format_list \ + Dynarr_new (ii_keyword_entry); \ + add_entry_to_device_ii_format_list \ (Q##type, Q##format, type##_##format##_image_instantiator_methods); \ - IIFORMAT_VALID_CONSOLE(type,format); \ + IIFORMAT_VALID_CONSOLE(type,format); \ + dumpstruct (&type##_##format##_image_instantiator_methods, \ + &iim_description); \ } while (0) /* Declare that image-instantiator format FORMAT has method M; used in initialization routines */ #define IIFORMAT_HAS_DEVMETHOD(type, format, m) \ (type##_##format##_image_instantiator_methods->m##_method = type##_##format##_##m) +#define IIFORMAT_HAS_SHARED_DEVMETHOD(type, format, m, fromformat) \ + (type##_##format##_image_instantiator_methods->m##_method = type##_##fromformat##_##m) struct image_instantiator_methods * decode_device_ii_format (Lisp_Object device, Lisp_Object format, @@ -279,11 +290,16 @@ void check_valid_string (Lisp_Object data); void check_valid_int (Lisp_Object data); void check_valid_face (Lisp_Object data); void check_valid_vector (Lisp_Object data); +void check_valid_item_list_1 (Lisp_Object items); void initialize_subwindow_image_instance (struct Lisp_Image_Instance*); void subwindow_instantiate (Lisp_Object image_instance, Lisp_Object instantiator, Lisp_Object pointer_fg, Lisp_Object pointer_bg, int dest_mask, Lisp_Object domain); +void widget_instantiate_1 (Lisp_Object image_instance, Lisp_Object instantiator, + Lisp_Object pointer_fg, Lisp_Object pointer_bg, + int dest_mask, Lisp_Object domain, int default_textheight, + int default_pixheight, int default_textwidth); DECLARE_DOESNT_RETURN (incompatible_image_types (Lisp_Object instantiator, int given_dest_mask, @@ -330,7 +346,6 @@ DECLARE_LRECORD (image_instance, struct Lisp_Image_Instance); XRECORD (x, image_instance, struct Lisp_Image_Instance) #define XSETIMAGE_INSTANCE(x, p) XSETRECORD (x, p, image_instance) #define IMAGE_INSTANCEP(x) RECORDP (x, image_instance) -#define GC_IMAGE_INSTANCEP(x) GC_RECORDP (x, image_instance) #define CHECK_IMAGE_INSTANCE(x) CHECK_RECORD (x, image_instance) #define CONCHECK_IMAGE_INSTANCE(x) CONCHECK_RECORD (x, image_instance) @@ -343,7 +358,8 @@ enum image_instance_type IMAGE_COLOR_PIXMAP, IMAGE_POINTER, IMAGE_SUBWINDOW, - IMAGE_WIDGET + IMAGE_WIDGET, + IMAGE_LAYOUT }; #define IMAGE_NOTHING_MASK (1 << 0) @@ -353,6 +369,7 @@ enum image_instance_type #define IMAGE_POINTER_MASK (1 << 4) #define IMAGE_SUBWINDOW_MASK (1 << 5) #define IMAGE_WIDGET_MASK (1 << 6) +#define IMAGE_LAYOUT_MASK (1 << 7) #define IMAGE_INSTANCE_TYPE_P(ii, type) \ (IMAGE_INSTANCEP (ii) && XIMAGE_INSTANCE_TYPE (ii) == type) @@ -371,15 +388,17 @@ enum image_instance_type IMAGE_INSTANCE_TYPE_P (ii, IMAGE_SUBWINDOW) #define WIDGET_IMAGE_INSTANCEP(ii) \ IMAGE_INSTANCE_TYPE_P (ii, IMAGE_WIDGET) +#define LAYOUT_IMAGE_INSTANCEP(ii) \ + IMAGE_INSTANCE_TYPE_P (ii, IMAGE_LAYOUT) -#define CHECK_NOTHING_IMAGE_INSTANCE(x) do { \ - CHECK_IMAGE_INSTANCE (x); \ +#define CHECK_NOTHING_IMAGE_INSTANCE(x) do { \ + CHECK_IMAGE_INSTANCE (x); \ if (!NOTHING_IMAGE_INSTANCEP (x)) \ x = wrong_type_argument (Qnothing_image_instance_p, (x)); \ } while (0) -#define CHECK_TEXT_IMAGE_INSTANCE(x) do { \ - CHECK_IMAGE_INSTANCE (x); \ +#define CHECK_TEXT_IMAGE_INSTANCE(x) do { \ + CHECK_IMAGE_INSTANCE (x); \ if (!TEXT_IMAGE_INSTANCEP (x)) \ x = wrong_type_argument (Qtext_image_instance_p, (x)); \ } while (0) @@ -390,37 +409,45 @@ enum image_instance_type x = wrong_type_argument (Qmono_pixmap_image_instance_p, (x)); \ } while (0) -#define CHECK_COLOR_PIXMAP_IMAGE_INSTANCE(x) do { \ - CHECK_IMAGE_INSTANCE (x); \ +#define CHECK_COLOR_PIXMAP_IMAGE_INSTANCE(x) do { \ + CHECK_IMAGE_INSTANCE (x); \ if (!COLOR_PIXMAP_IMAGE_INSTANCEP (x)) \ x = wrong_type_argument (Qcolor_pixmap_image_instance_p, (x)); \ } while (0) -#define CHECK_POINTER_IMAGE_INSTANCE(x) do { \ - CHECK_IMAGE_INSTANCE (x); \ +#define CHECK_POINTER_IMAGE_INSTANCE(x) do { \ + CHECK_IMAGE_INSTANCE (x); \ if (!POINTER_IMAGE_INSTANCEP (x)) \ x = wrong_type_argument (Qpointer_image_instance_p, (x)); \ } while (0) -#define CHECK_SUBWINDOW_IMAGE_INSTANCE(x) do { \ +#define CHECK_SUBWINDOW_IMAGE_INSTANCE(x) do { \ CHECK_IMAGE_INSTANCE (x); \ if (!SUBWINDOW_IMAGE_INSTANCEP (x) \ && !WIDGET_IMAGE_INSTANCEP (x)) \ x = wrong_type_argument (Qsubwindow_image_instance_p, (x)); \ } while (0) -#define CHECK_WIDGET_IMAGE_INSTANCE(x) do { \ - CHECK_IMAGE_INSTANCE (x); \ +#define CHECK_WIDGET_IMAGE_INSTANCE(x) do { \ + CHECK_IMAGE_INSTANCE (x); \ if (!WIDGET_IMAGE_INSTANCEP (x)) \ x = wrong_type_argument (Qwidget_image_instance_p, (x)); \ } while (0) +#define CHECK_LAYOUT_IMAGE_INSTANCE(x) do { \ + CHECK_IMAGE_INSTANCE (x); \ + if (!LAYOUT_IMAGE_INSTANCEP (x)) \ + x = wrong_type_argument (Qlayout_image_instance_p, (x)); \ +} while (0) + struct Lisp_Image_Instance { struct lcrecord_header header; Lisp_Object device; Lisp_Object name; enum image_instance_type type; + int x_offset, y_offset; /* for layout purposes */ + unsigned int dirty : 1; union { struct @@ -430,6 +457,7 @@ struct Lisp_Image_Instance struct { int width, height, depth; + int slice, maxslice, timeout; Lisp_Object hotspot_x, hotspot_y; /* integer or Qnil */ Lisp_Object filename; /* string or Qnil */ Lisp_Object mask_filename; /* string or Qnil */ @@ -438,20 +466,29 @@ struct Lisp_Image_Instance or a pointer */ Lisp_Object auxdata; /* list or Qnil: any additional data to be seen from lisp */ + void* mask; /* mask that can be seen from all windowing systems */ } pixmap; /* used for pointers as well */ struct { Lisp_Object frame; unsigned int width, height; void* subwindow; /* specific devices can use this as necessary */ - int being_displayed; /* used to detect when needs to be unmapped */ - struct + unsigned int being_displayed : 1; /* used to detect when needs to be unmapped */ + union { - Lisp_Object face; /* foreground and background colors */ - Lisp_Object type; - Lisp_Object props; /* properties */ - Lisp_Object gui_item; /* a list of gui_items */ - } widget; /* widgets are subwindows */ + struct + { + Lisp_Object face; /* foreground and background colors */ + Lisp_Object type; + Lisp_Object props; /* properties */ + Lisp_Object gui_item; /* a list of gui_items */ + } widget; /* widgets are subwindows */ + struct + { + Lisp_Object children; /* managed children */ + Lisp_Object border; /* Style of enclosing border or text. */ + } layout; + } s; } subwindow; } u; @@ -462,9 +499,12 @@ struct Lisp_Image_Instance #define IMAGE_INSTANCE_DEVICE(i) ((i)->device) #define IMAGE_INSTANCE_NAME(i) ((i)->name) #define IMAGE_INSTANCE_TYPE(i) ((i)->type) +#define IMAGE_INSTANCE_XOFFSET(i) ((i)->x_offset) +#define IMAGE_INSTANCE_YOFFSET(i) ((i)->y_offset) #define IMAGE_INSTANCE_PIXMAP_TYPE_P(i) \ ((IMAGE_INSTANCE_TYPE (i) == IMAGE_MONO_PIXMAP) \ || (IMAGE_INSTANCE_TYPE (i) == IMAGE_COLOR_PIXMAP)) +#define IMAGE_INSTANCE_DIRTYP(i) ((i)->dirty) #define IMAGE_INSTANCE_TEXT_STRING(i) ((i)->u.text.string) @@ -478,6 +518,10 @@ struct Lisp_Image_Instance #define IMAGE_INSTANCE_PIXMAP_FG(i) ((i)->u.pixmap.fg) #define IMAGE_INSTANCE_PIXMAP_BG(i) ((i)->u.pixmap.bg) #define IMAGE_INSTANCE_PIXMAP_AUXDATA(i) ((i)->u.pixmap.auxdata) +#define IMAGE_INSTANCE_PIXMAP_MASK(i) ((i)->u.pixmap.mask) +#define IMAGE_INSTANCE_PIXMAP_SLICE(i) ((i)->u.pixmap.slice) +#define IMAGE_INSTANCE_PIXMAP_MAXSLICE(i) ((i)->u.pixmap.maxslice) +#define IMAGE_INSTANCE_PIXMAP_TIMEOUT(i) ((i)->u.pixmap.timeout) #define IMAGE_INSTANCE_SUBWINDOW_WIDTH(i) ((i)->u.subwindow.width) #define IMAGE_INSTANCE_SUBWINDOW_HEIGHT(i) ((i)->u.subwindow.height) @@ -490,22 +534,31 @@ struct Lisp_Image_Instance IMAGE_INSTANCE_SUBWINDOW_WIDTH(i) #define IMAGE_INSTANCE_WIDGET_HEIGHT(i) \ IMAGE_INSTANCE_SUBWINDOW_HEIGHT(i) -#define IMAGE_INSTANCE_WIDGET_TYPE(i) ((i)->u.subwindow.widget.type) -#define IMAGE_INSTANCE_WIDGET_PROPS(i) ((i)->u.subwindow.widget.props) -#define IMAGE_INSTANCE_WIDGET_FACE(i) ((i)->u.subwindow.widget.face) -#define IMAGE_INSTANCE_WIDGET_ITEM(i) ((i)->u.subwindow.widget.gui_item) -#define IMAGE_INSTANCE_WIDGET_SINGLE_ITEM(i) \ -(CONSP (IMAGE_INSTANCE_WIDGET_ITEM (i)) ? \ -XCAR (IMAGE_INSTANCE_WIDGET_ITEM (i)) : \ - IMAGE_INSTANCE_WIDGET_ITEM (i)) +#define IMAGE_INSTANCE_WIDGET_TYPE(i) ((i)->u.subwindow.s.widget.type) +#define IMAGE_INSTANCE_WIDGET_PROPS(i) ((i)->u.subwindow.s.widget.props) +#define IMAGE_INSTANCE_WIDGET_FACE(i) ((i)->u.subwindow.s.widget.face) +#define IMAGE_INSTANCE_WIDGET_ITEMS(i) ((i)->u.subwindow.s.widget.gui_item) +#define IMAGE_INSTANCE_WIDGET_ITEM(i) \ +(CONSP (IMAGE_INSTANCE_WIDGET_ITEMS (i)) ? \ +XCAR (IMAGE_INSTANCE_WIDGET_ITEMS (i)) : \ + IMAGE_INSTANCE_WIDGET_ITEMS (i)) #define IMAGE_INSTANCE_WIDGET_TEXT(i) XGUI_ITEM (IMAGE_INSTANCE_WIDGET_ITEM (i))->name +#define IMAGE_INSTANCE_LAYOUT_CHILDREN(i) ((i)->u.subwindow.s.layout.children) +#define IMAGE_INSTANCE_LAYOUT_BORDER(i) ((i)->u.subwindow.s.layout.border) + #define XIMAGE_INSTANCE_DEVICE(i) \ IMAGE_INSTANCE_DEVICE (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_NAME(i) \ IMAGE_INSTANCE_NAME (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_TYPE(i) \ IMAGE_INSTANCE_TYPE (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_XOFFSET(i) \ + IMAGE_INSTANCE_XOFFSET (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_YOFFSET(i) \ + IMAGE_INSTANCE_YOFFSET (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_DIRTYP(i) \ + IMAGE_INSTANCE_DIRTYP (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_TEXT_STRING(i) \ IMAGE_INSTANCE_TEXT_STRING (XIMAGE_INSTANCE (i)) @@ -528,6 +581,14 @@ XCAR (IMAGE_INSTANCE_WIDGET_ITEM (i)) : \ IMAGE_INSTANCE_PIXMAP_FG (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_PIXMAP_BG(i) \ IMAGE_INSTANCE_PIXMAP_BG (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_PIXMAP_MASK(i) \ + IMAGE_INSTANCE_PIXMAP_MASK (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_PIXMAP_SLICE(i) \ + IMAGE_INSTANCE_PIXMAP_SLICE (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_PIXMAP_MAXSLICE(i) \ + IMAGE_INSTANCE_PIXMAP_MAXSLICE (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_PIXMAP_TIMEOUT(i) \ + IMAGE_INSTANCE_PIXMAP_TIMEOUT (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_WIDGET_WIDTH(i) \ IMAGE_INSTANCE_WIDGET_WIDTH (XIMAGE_INSTANCE (i)) @@ -541,11 +602,16 @@ XCAR (IMAGE_INSTANCE_WIDGET_ITEM (i)) : \ IMAGE_INSTANCE_WIDGET_FACE (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_WIDGET_ITEM(i) \ IMAGE_INSTANCE_WIDGET_ITEM (XIMAGE_INSTANCE (i)) -#define XIMAGE_INSTANCE_WIDGET_SINGLE_ITEM(i) \ - IMAGE_INSTANCE_WIDGET_SINGLE_ITEM (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_WIDGET_ITEMS(i) \ + IMAGE_INSTANCE_WIDGET_ITEMS (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_WIDGET_TEXT(i) \ IMAGE_INSTANCE_WIDGET_TEXT (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_LAYOUT_CHILDREN(i) \ + IMAGE_INSTANCE_LAYOUT_CHILDREN (XIMAGE_INSTANCE (i)) +#define XIMAGE_INSTANCE_LAYOUT_BORDER(i) \ + IMAGE_INSTANCE_LAYOUT_BORDER (XIMAGE_INSTANCE (i)) + #define XIMAGE_INSTANCE_SUBWINDOW_WIDTH(i) \ IMAGE_INSTANCE_SUBWINDOW_WIDTH (XIMAGE_INSTANCE (i)) #define XIMAGE_INSTANCE_SUBWINDOW_HEIGHT(i) \ @@ -557,6 +623,9 @@ XCAR (IMAGE_INSTANCE_WIDGET_ITEM (i)) : \ #define XIMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP(i) \ IMAGE_INSTANCE_SUBWINDOW_DISPLAYEDP (XIMAGE_INSTANCE (i)) +#define MARK_IMAGE_INSTANCE_CHANGED(i) \ + (IMAGE_INSTANCE_DIRTYP (i) = 1); + #ifdef HAVE_XPM Lisp_Object evaluate_xpm_color_symbols (void); Lisp_Object pixmap_to_lisp_data (Lisp_Object name, int ok_if_data_invalid); @@ -596,17 +665,19 @@ struct Lisp_Glyph Lisp_Object baseline; /* percent above baseline */ Lisp_Object face; /* if non-nil, face to use when displaying */ - + Lisp_Object plist; void (*after_change) (Lisp_Object glyph, Lisp_Object property, Lisp_Object locale); + + unsigned int dirty : 1; /* So that we can selectively + redisplay changed glyphs. */ }; DECLARE_LRECORD (glyph, struct Lisp_Glyph); #define XGLYPH(x) XRECORD (x, glyph, struct Lisp_Glyph) #define XSETGLYPH(x, p) XSETRECORD (x, p, glyph) #define GLYPHP(x) RECORDP (x, glyph) -#define GC_GLYPHP(x) GC_RECORDP (x, glyph) #define CHECK_GLYPH(x) CHECK_RECORD (x, glyph) #define CONCHECK_GLYPH(x) CONCHECK_RECORD (x, glyph) @@ -633,21 +704,26 @@ DECLARE_LRECORD (glyph, struct Lisp_Glyph); #define GLYPH_CONTRIB_P(g) ((g)->contrib_p) #define GLYPH_BASELINE(g) ((g)->baseline) #define GLYPH_FACE(g) ((g)->face) +#define GLYPH_DIRTYP(g) ((g)->dirty) #define XGLYPH_TYPE(g) GLYPH_TYPE (XGLYPH (g)) #define XGLYPH_IMAGE(g) GLYPH_IMAGE (XGLYPH (g)) #define XGLYPH_CONTRIB_P(g) GLYPH_CONTRIB_P (XGLYPH (g)) #define XGLYPH_BASELINE(g) GLYPH_BASELINE (XGLYPH (g)) #define XGLYPH_FACE(g) GLYPH_FACE (XGLYPH (g)) +#define XGLYPH_DIRTYP(g) GLYPH_DIRTYP (XGLYPH (g)) + +#define MARK_GLYPH_CHANGED(g) (GLYPH_DIRTYP (g) = 1); -extern Lisp_Object Qxpm, Qxface; +extern Lisp_Object Qxpm, Qxface, Qetched_in, Qetched_out, Qbevel_in, Qbevel_out; extern Lisp_Object Q_data, Q_file, Q_color_symbols, Qconst_glyph_variable; extern Lisp_Object Qxbm, Qedit_field, Qgroup, Qlabel, Qcombo_box, Qscrollbar; -extern Lisp_Object Qtree_view, Qtab_control, Qprogress_gauge; +extern Lisp_Object Qtree_view, Qtab_control, Qprogress_gauge, Q_border; extern Lisp_Object Q_mask_file, Q_mask_data, Q_hotspot_x, Q_hotspot_y; extern Lisp_Object Q_foreground, Q_background, Q_face, Q_descriptor, Q_group; extern Lisp_Object Q_width, Q_height, Q_pixel_width, Q_pixel_height, Q_text; extern Lisp_Object Q_items, Q_properties, Q_image, Q_percent, Qimage_conversion_error; +extern Lisp_Object Q_orientation; extern Lisp_Object Vcontinuation_glyph, Vcontrol_arrow_glyph, Vhscroll_glyph; extern Lisp_Object Vinvisible_text_glyph, Voctal_escape_glyph, Vtruncation_glyph; extern Lisp_Object Vxemacs_logo; @@ -688,6 +764,8 @@ Lisp_Object widget_face_font_info (Lisp_Object domain, Lisp_Object face, void widget_text_to_pixel_conversion (Lisp_Object domain, Lisp_Object face, int th, int tw, int* height, int* width); +Lisp_Object add_glyph_animated_timeout (EMACS_INT tickms, Lisp_Object device); +void disable_glyph_animated_timeout (int i); /************************************************************************/ /* Glyph Cachels */ @@ -698,7 +776,14 @@ struct glyph_cachel { Lisp_Object glyph; + unsigned int dirty :1; /* I'm copying faces here. I'm not + sure why we need two dirty + flags. Maybe because an image + instance can be dirty and so we + need to frob this in the same way + as other image instance properties. */ unsigned int updated :1; + unsigned short width; unsigned short ascent; unsigned short descent; @@ -721,11 +806,14 @@ struct glyph_cachel Dynarr_atp (window->glyph_cachels, index)->ascent #define GLYPH_CACHEL_DESCENT(window, index) \ Dynarr_atp (window->glyph_cachels, index)->descent +#define GLYPH_CACHEL_DIRTYP(window, index) \ + Dynarr_atp (window->glyph_cachels, index)->dirty -void mark_glyph_cachels (glyph_cachel_dynarr *elements, - void (*markobj) (Lisp_Object)); +void mark_glyph_cachels (glyph_cachel_dynarr *elements); void mark_glyph_cachels_as_not_updated (struct window *w); +void mark_glyph_cachels_as_clean (struct window *w); void reset_glyph_cachels (struct window *w); +glyph_index get_glyph_cachel_index (struct window *w, Lisp_Object glyph); #ifdef MEMORY_USAGE_STATS int compute_glyph_cachel_usage (glyph_cachel_dynarr *glyph_cachels, @@ -752,8 +840,8 @@ struct subwindow_cachel Lisp_Object subwindow; int x, y; int width, height; - int being_displayed; - int updated; + unsigned int being_displayed : 1; + unsigned int updated : 1; }; typedef struct @@ -761,12 +849,25 @@ typedef struct Dynarr_declare (subwindow_cachel); } subwindow_cachel_dynarr; -void mark_subwindow_cachels (subwindow_cachel_dynarr *elements, - void (*markobj) (Lisp_Object)); +void mark_subwindow_cachels (subwindow_cachel_dynarr *elements); void mark_subwindow_cachels_as_not_updated (struct frame *f); void reset_subwindow_cachels (struct frame *f); void unmap_subwindow (Lisp_Object subwindow); -void map_subwindow (Lisp_Object subwindow, int x, int y); +void map_subwindow (Lisp_Object subwindow, int x, int y, + struct display_glyph_area *dga); void update_frame_subwindows (struct frame *f); +int find_matching_subwindow (struct frame* f, int x, int y, int width, int height); + +struct expose_ignore +{ + int x; + int y; + int width; + int height; + struct expose_ignore *next; +}; + +int check_for_ignored_expose (struct frame* f, int x, int y, int width, int height); +extern int hold_ignored_expose_registration; #endif /* _XEMACS_GLYPHS_H_ */ diff --git a/src/gui-msw.c b/src/gui-msw.c index e02712f..3968284 100644 --- a/src/gui-msw.c +++ b/src/gui-msw.c @@ -46,7 +46,7 @@ mswindows_handle_gui_wm_command (struct frame* f, HWND ctrl, WORD id) if (NILP (data) || UNBOUNDP (data)) return Qnil; - MARK_SUBWINDOWS_CHANGED; + MARK_SUBWINDOWS_STATE_CHANGED; /* Ok, this is our one. Enqueue it. */ get_gui_callback (data, &fn, &arg); XSETFRAME (frame, f); diff --git a/src/gui-x.c b/src/gui-x.c index e35e65e..9714d02 100644 --- a/src/gui-x.c +++ b/src/gui-x.c @@ -58,34 +58,26 @@ xmalloc_widget_value (void) } -struct mark_widget_value_closure -{ - void (*markobj) (Lisp_Object); -}; - static int mark_widget_value_mapper (widget_value *val, void *closure) { Lisp_Object markee; - - struct mark_widget_value_closure *cl = - (struct mark_widget_value_closure *) closure; if (val->call_data) { VOID_TO_LISP (markee, val->call_data); - (cl->markobj) (markee); + mark_object (markee); } if (val->accel) { VOID_TO_LISP (markee, val->accel); - (cl->markobj) (markee); + mark_object (markee); } return 0; } static Lisp_Object -mark_popup_data (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_popup_data (Lisp_Object obj) { struct popup_data *data = (struct popup_data *) XPOPUP_DATA (obj); @@ -93,12 +85,7 @@ mark_popup_data (Lisp_Object obj, void (*markobj) (Lisp_Object)) call-data */ if (data->id) - { - struct mark_widget_value_closure closure; - - closure.markobj = markobj; - lw_map_widget_values (data->id, mark_widget_value_mapper, &closure); - } + lw_map_widget_values (data->id, mark_widget_value_mapper, 0); return data->last_menubar_buffer; } @@ -257,7 +244,7 @@ popup_selection_callback (Widget widget, LWLIB_ID ignored_id, } else { - MARK_SUBWINDOWS_CHANGED; + MARK_SUBWINDOWS_STATE_CHANGED; get_gui_callback (data, &fn, &arg); } @@ -325,7 +312,20 @@ button_item_to_widget_value (Lisp_Object gui_item, widget_value *wv, /* !!#### This function has not been Mule-ized */ /* This function cannot GC because gc_currently_forbidden is set when it's called */ - struct Lisp_Gui_Item* pgui = XGUI_ITEM (gui_item); + struct Lisp_Gui_Item* pgui = 0; + + /* degenerate case */ + if (STRINGP (gui_item)) + { + wv->type = TEXT_TYPE; + wv->name = (char *) XSTRING_DATA (gui_item); + wv->name = xstrdup (wv->name); + return 1; + } + else if (!GUI_ITEMP (gui_item)) + signal_simple_error("need a string or a gui_item here", gui_item); + + pgui = XGUI_ITEM (gui_item); if (!NILP (pgui->filter)) signal_simple_error(":filter keyword not permitted on leaf nodes", gui_item); @@ -340,6 +340,7 @@ button_item_to_widget_value (Lisp_Object gui_item, widget_value *wv, CHECK_STRING (pgui->name); wv->name = (char *) XSTRING_DATA (pgui->name); + wv->name = xstrdup (wv->name); wv->accel = LISP_TO_VOID (gui_item_accelerator (gui_item)); if (!NILP (pgui->suffix)) @@ -448,6 +449,111 @@ button_item_to_widget_value (Lisp_Object gui_item, widget_value *wv, return 1; } +/* parse tree's of gui items into widget_value hierarchies */ +static void gui_item_children_to_widget_values (Lisp_Object items, widget_value* parent); + +static widget_value * +gui_items_to_widget_values_1 (Lisp_Object items, widget_value* parent, + widget_value* prev) +{ + widget_value* wv = 0; + + assert ((parent || prev) && !(parent && prev)); + /* now walk the tree creating widget_values as appropriate */ + if (!CONSP (items)) + { + wv = xmalloc_widget_value(); + if (parent) + parent->contents = wv; + else + prev->next = wv; + if (!button_item_to_widget_value (items, wv, 0, 1)) + { + free_widget_value (wv); + if (parent) + parent->contents = 0; + else + prev->next = 0; + } + else + { + wv->value = xstrdup (wv->name); /* what a mess... */ + } + } + else + { + /* first one is the parent */ + if (CONSP (XCAR (items))) + signal_simple_error ("parent item must not be a list", XCAR (items)); + + if (parent) + wv = gui_items_to_widget_values_1 (XCAR (items), parent, 0); + else + wv = gui_items_to_widget_values_1 (XCAR (items), 0, prev); + /* the rest are the children */ + gui_item_children_to_widget_values (XCDR (items), wv); + } + return wv; +} + +static void +gui_item_children_to_widget_values (Lisp_Object items, widget_value* parent) +{ + widget_value* wv = 0, *prev = 0; + Lisp_Object rest; + CHECK_CONS (items); + + /* first one is master */ + prev = gui_items_to_widget_values_1 (XCAR (items), parent, 0); + /* the rest are the children */ + LIST_LOOP (rest, XCDR (items)) + { + Lisp_Object tab = XCAR (rest); + wv = gui_items_to_widget_values_1 (tab, 0, prev); + prev = wv; + } +} + +widget_value * +gui_items_to_widget_values (Lisp_Object items) +{ + /* !!#### This function has not been Mule-ized */ + /* This function can GC */ + widget_value *control = 0, *tmp = 0; + int count = specpdl_depth (); + Lisp_Object wv_closure; + + if (NILP (items)) + signal_simple_error ("must have some items", items); + + /* Inhibit GC during this conversion. The reasons for this are + the same as in menu_item_descriptor_to_widget_value(); see + the large comment above that function. */ + record_unwind_protect (restore_gc_inhibit, + make_int (gc_currently_forbidden)); + gc_currently_forbidden = 1; + + /* Also make sure that we free the partially-created widget_value + tree on Lisp error. */ + control = xmalloc_widget_value(); + wv_closure = make_opaque_ptr (control); + record_unwind_protect (widget_value_unwind, wv_closure); + + gui_items_to_widget_values_1 (items, control, 0); + + /* mess about getting the data we really want */ + tmp = control; + control = control->contents; + tmp->next = 0; + tmp->contents = 0; + free_widget_value (tmp); + + /* No more need to free the half-filled-in structures. */ + set_opaque_ptr (wv_closure, 0); + unbind_to (count, Qnil); + + return control; +} /* This is a kludge to make sure emacs can only link against a version of lwlib that was compiled in the right way. Emacs references symbols which @@ -498,6 +604,11 @@ sanity_check_lwlib (void) #elif defined (HAVE_DIALOGS) MACROLET (lwlib_dialogs_athena); #endif +#ifdef LWLIB_WIDGETS_MOTIF + MACROLET (lwlib_widgets_motif); +#elif defined (HAVE_WIDGETS) + MACROLET (lwlib_widgets_athena); +#endif #undef MACROLET } @@ -509,11 +620,21 @@ syms_of_gui_x (void) } void -vars_of_gui_x (void) +reinit_vars_of_gui_x (void) { lwlib_id_tick = (1<<16); /* start big, to not conflict with Energize */ - +#ifdef HAVE_POPUPS popup_up_p = 0; +#endif + + /* this makes only safe calls as in emacs.c */ + sanity_check_lwlib (); +} + +void +vars_of_gui_x (void) +{ + reinit_vars_of_gui_x (); Vpopup_callbacks = Qnil; staticpro (&Vpopup_callbacks); @@ -527,7 +648,4 @@ without a selection having been made. */ ); #endif Fset (Qmenu_no_selection_hook, Qnil); - - /* this makes only safe calls as in emacs.c */ - sanity_check_lwlib (); } diff --git a/src/gui-x.h b/src/gui-x.h index ed7e4d5..bb6fa10 100644 --- a/src/gui-x.h +++ b/src/gui-x.h @@ -30,8 +30,6 @@ widget_value *xmalloc_widget_value (void); LWLIB_ID new_lwlib_id (void); -#ifdef HAVE_POPUPS - /* Each frame has one of these, and they are also contained in Vpopup_callbacks. It doesn't really need to be an lrecord (it's not lisp-accessible) @@ -62,7 +60,6 @@ DECLARE_LRECORD (popup_data, struct popup_data); #define XPOPUP_DATA(x) XRECORD (x, popup_data, struct popup_data) #define XSETPOPUP_DATA(x, p) XSETRECORD (x, p, popup_data) #define POPUP_DATAP(x) RECORDP (x, popup_data) -#define GC_POPUP_DATAP(x) GC_RECORDP (x, popup_data) #define CHECK_POPUP_DATA(x) CHECK_RECORD (x, popup_data) void gcpro_popup_callbacks (LWLIB_ID id); @@ -73,10 +70,9 @@ void popup_selection_callback (Widget widget, LWLIB_ID ignored_id, XtPointer client_data); int button_item_to_widget_value (Lisp_Object desc, widget_value *wv, int allow_text_field_p, int no_keys_p); +widget_value * gui_items_to_widget_values (Lisp_Object items); Lisp_Object menu_name_to_accelerator (char *name); char *menu_separator_style (CONST char *s); Lisp_Object widget_value_unwind (Lisp_Object closure); -#endif /* HAVE_POPUPS */ - #endif /* _XEMACS_XLWLIB_H_ */ diff --git a/src/gui.c b/src/gui.c index 4824420..e43a204 100644 --- a/src/gui.c +++ b/src/gui.c @@ -34,6 +34,8 @@ Lisp_Object Q_filter, Q_config, Q_included, Q_key_sequence; Lisp_Object Q_accelerator, Q_label, Q_callback; Lisp_Object Qtoggle, Qradio; +static Lisp_Object parse_gui_item_tree_list (Lisp_Object list); + #ifdef HAVE_POPUPS /* count of menus/dboxes currently up */ @@ -152,7 +154,7 @@ gui_item_init (Lisp_Object gui_item) } Lisp_Object -allocate_gui_item () +allocate_gui_item (void) { struct Lisp_Gui_Item *lp = alloc_lcrecord_type (struct Lisp_Gui_Item, &lrecord_gui_item); @@ -381,6 +383,7 @@ unsigned int gui_item_display_flush_left (Lisp_Object gui_item, char* buf, Bytecount buf_len) { + /* This function can call lisp */ char *p = buf; Bytecount len; struct Lisp_Gui_Item* pgui_item = XGUI_ITEM (gui_item); @@ -468,22 +471,22 @@ gui_item_display_flush_right (Lisp_Object gui_item, #endif /* HAVE_WINDOW_SYSTEM */ static Lisp_Object -mark_gui_item (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_gui_item (Lisp_Object obj) { struct Lisp_Gui_Item *p = XGUI_ITEM (obj); - markobj (p->name); - markobj (p->callback); - markobj (p->config); - markobj (p->suffix); - markobj (p->active); - markobj (p->included); - markobj (p->config); - markobj (p->filter); - markobj (p->style); - markobj (p->selected); - markobj (p->keys); - markobj (p->accelerator); + mark_object (p->name); + mark_object (p->callback); + mark_object (p->config); + mark_object (p->suffix); + mark_object (p->active); + mark_object (p->included); + mark_object (p->config); + mark_object (p->filter); + mark_object (p->style); + mark_object (p->selected); + mark_object (p->keys); + mark_object (p->accelerator); return Qnil; } @@ -563,6 +566,56 @@ print_gui_item (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) write_c_string (buf, printcharfun); } +/* parse a glyph descriptor into a tree of gui items. + + The gui_item slot of an image instance can be a single item or an + arbitrarily nested hierarchy of item lists. */ + +static Lisp_Object parse_gui_item_tree_item (Lisp_Object entry) +{ + Lisp_Object ret = entry; + if (VECTORP (entry)) + { + ret = gui_parse_item_keywords_no_errors (entry); + } + else if (STRINGP (entry)) + { + CHECK_STRING (entry); + } + else + signal_simple_error ("item must be a vector or a string", entry); + + return ret; +} + +Lisp_Object parse_gui_item_tree_children (Lisp_Object list) +{ + Lisp_Object rest, ret = Qnil; + CHECK_CONS (list); + /* recursively add items to the tree view */ + LIST_LOOP (rest, list) + { + Lisp_Object sub; + if (CONSP (XCAR (rest))) + sub = parse_gui_item_tree_list (XCAR (rest)); + else + sub = parse_gui_item_tree_item (XCAR (rest)); + + ret = Fcons (sub, ret); + } + /* make the order the same as the items we have parsed */ + return Fnreverse (ret); +} + +static Lisp_Object parse_gui_item_tree_list (Lisp_Object list) +{ + Lisp_Object ret; + CHECK_CONS (list); + /* first one can never be a list */ + ret = parse_gui_item_tree_item (XCAR (list)); + return Fcons (ret, parse_gui_item_tree_children (XCDR (list))); +} + DEFINE_LRECORD_IMPLEMENTATION ("gui-item", gui_item, mark_gui_item, print_gui_item, 0, gui_item_equal, diff --git a/src/gui.h b/src/gui.h index 904bd96..169abd5 100644 --- a/src/gui.h +++ b/src/gui.h @@ -41,7 +41,6 @@ DECLARE_LRECORD (gui_item, struct Lisp_Gui_Item); XRECORD (x, gui_item, struct Lisp_Gui_Item) #define XSETGUI_ITEM(x, p) XSETRECORD (x, p, gui_item) #define GUI_ITEMP(x) RECORDP (x, gui_item) -#define GC_GUI_ITEMP(x) GC_RECORDP (x, gui_item) #define CHECK_GUI_ITEM(x) CHECK_RECORD (x, gui_item) #define CONCHECK_GUI_ITEM(x) CONCHECK_RECORD (x, gui_item) @@ -83,8 +82,9 @@ unsigned int gui_item_display_flush_left (Lisp_Object pgui_item, unsigned int gui_item_display_flush_right (Lisp_Object gui_item, char* buf, Bytecount buf_len); -Lisp_Object allocate_gui_item (); +Lisp_Object allocate_gui_item (void); void gui_item_init (Lisp_Object gui_item); +Lisp_Object parse_gui_item_tree_children (Lisp_Object list); /* this is mswindows biased but reasonably safe I think */ #define GUI_ITEM_ID_SLOTS 8 diff --git a/src/gutter.c b/src/gutter.c index 64d0df3..d9534d0 100644 --- a/src/gutter.c +++ b/src/gutter.c @@ -20,7 +20,8 @@ Boston, MA 02111-1307, USA. */ /* Synched up with: Not in FSF. */ -/* Specifers ripped-off from toolbar.c */ +/* written by Andy Piper with specifiers partially + ripped-off from toolbar.c */ #include #include "lisp.h" @@ -45,25 +46,27 @@ Lisp_Object Vdefault_gutter_border_width; Lisp_Object Vdefault_gutter_position; -#define SET_GUTTER_WAS_VISIBLE_FLAG(frame, pos, flag) \ - do { \ - switch (pos) \ - { \ - case TOP_GUTTER: \ - (frame)->top_gutter_was_visible = flag; \ - break; \ - case BOTTOM_GUTTER: \ - (frame)->bottom_gutter_was_visible = flag; \ - break; \ - case LEFT_GUTTER: \ - (frame)->left_gutter_was_visible = flag; \ - break; \ - case RIGHT_GUTTER: \ - (frame)->right_gutter_was_visible = flag; \ - break; \ - default: \ - abort (); \ - } \ +Lisp_Object Qgutter_size; + +#define SET_GUTTER_WAS_VISIBLE_FLAG(frame, pos, flag) \ + do { \ + switch (pos) \ + { \ + case TOP_GUTTER: \ + (frame)->top_gutter_was_visible = flag; \ + break; \ + case BOTTOM_GUTTER: \ + (frame)->bottom_gutter_was_visible = flag; \ + break; \ + case LEFT_GUTTER: \ + (frame)->left_gutter_was_visible = flag; \ + break; \ + case RIGHT_GUTTER: \ + (frame)->right_gutter_was_visible = flag; \ + break; \ + default: \ + abort (); \ + } \ } while (0) static int gutter_was_visible (struct frame* frame, enum gutter_pos pos) @@ -71,13 +74,13 @@ static int gutter_was_visible (struct frame* frame, enum gutter_pos pos) switch (pos) { case TOP_GUTTER: - return (frame)->top_gutter_was_visible; + return frame->top_gutter_was_visible; case BOTTOM_GUTTER: - return (frame)->bottom_gutter_was_visible; + return frame->bottom_gutter_was_visible; case LEFT_GUTTER: - return (frame)->left_gutter_was_visible; + return frame->left_gutter_was_visible; case RIGHT_GUTTER: - return (frame)->right_gutter_was_visible; + return frame->right_gutter_was_visible; default: abort (); } @@ -159,7 +162,7 @@ frame_rightmost_window (struct frame *f) use this for calculating the gutter positions we run into trouble if it is not the window nearest the gutter. Instead we predetermine the nearest window and then use that.*/ -void +static void get_gutter_coords (struct frame *f, enum gutter_pos pos, int *x, int *y, int *width, int *height) { @@ -224,19 +227,20 @@ output_gutter (struct frame *f, enum gutter_pos pos) face_index findex = get_builtin_face_cache_index (w, Vgui_element_face); display_line_dynarr* ddla, *cdla; struct display_line *dl; + int cdla_len; if (!f->current_display_lines) f->current_display_lines = Dynarr_new (display_line); if (!f->desired_display_lines) f->desired_display_lines = Dynarr_new (display_line); - + ddla = f->desired_display_lines; cdla = f->current_display_lines; + cdla_len = Dynarr_length (cdla); XSETFRAME (frame, f); get_gutter_coords (f, pos, &x, &y, &width, &height); - /* clear out what we want to cover */ /* generate some display lines */ generate_displayable_area (w, WINDOW_GUTTER (w, pos), x + border_width, y + border_width, @@ -248,22 +252,28 @@ output_gutter (struct frame *f, enum gutter_pos pos) output_display_line (w, cdla, ddla, line, -1, -1); } + /* If the number of display lines has shrunk, adjust. */ + if (cdla_len > Dynarr_length (ddla)) + { + Dynarr_length (cdla) = Dynarr_length (ddla); + } + /* grab coordinates of last line and blank after it. */ dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1); ypos = dl->ypos + dl->descent - dl->clip; redisplay_clear_region (window, findex, x + border_width , ypos, - width - 2 * border_width, height - (ypos - y)); - + width - 2 * border_width, height - (ypos - y) - border_width); /* bevel the gutter area if so desired */ if (border_width != 0) { MAYBE_DEVMETH (d, bevel_area, - (w, findex, x, y, width, height, border_width)); + (w, findex, x, y, width, height, border_width, + EDGE_ALL, EDGE_BEVEL_OUT)); } } /* sizing gutters is a pain so we try and help the user by detemining - what height will accomodate all lines. This is useless on left and + what height will accommodate all lines. This is useless on left and right gutters as we always have a maximal number of lines. */ static Lisp_Object calculate_gutter_size (struct window *w, enum gutter_pos pos) @@ -279,7 +289,9 @@ calculate_gutter_size (struct window *w, enum gutter_pos pos) /* degenerate case */ if (NILP (WINDOW_GUTTER (w, pos)) || - !FRAME_VISIBLE_P (f)) + !FRAME_VISIBLE_P (f) + || + NILP (w->buffer)) return Qnil; ddla = Dynarr_new (display_line); @@ -296,12 +308,12 @@ calculate_gutter_size (struct window *w, enum gutter_pos pos) { dl = Dynarr_atp (ddla, Dynarr_length (ddla) - 1); ypos = dl->ypos + dl->descent - dl->clip; - Dynarr_free (ddla); + free_display_lines (ddla); return make_int (ypos); } else { - Dynarr_free (ddla); + free_display_lines (ddla); return Qnil; } } @@ -323,21 +335,39 @@ clear_gutter (struct frame *f, enum gutter_pos pos) void update_frame_gutters (struct frame *f) { - if (f->gutter_changed || f->frame_changed || f->clear) + if (f->gutter_changed || f->clear || + f->glyphs_changed || f->subwindows_changed || + f->windows_changed || f->windows_structure_changed || + f->extents_changed || f->faces_changed) { - int pos; - /* and output */ + enum gutter_pos pos; + + /* We don't actually care about these when outputting the gutter + so locally disable them. */ + int local_clip_changed = f->clip_changed; + int local_buffers_changed = f->buffers_changed; + f->clip_changed = 0; + f->buffers_changed = 0; - for (pos = 0; pos < 4; pos++) + /* and output */ + GUTTER_POS_LOOP (pos) { if (FRAME_GUTTER_VISIBLE (f, pos)) - output_gutter (f, pos); + output_gutter (f, pos); else if (gutter_was_visible (f, pos)) clear_gutter (f, pos); } - + f->clip_changed = local_clip_changed; + f->buffers_changed = local_buffers_changed; + f->gutter_changed = 0; } - f->gutter_changed = 0; +} + +void +reset_gutter_display_lines (struct frame* f) +{ + if (f->current_display_lines) + Dynarr_reset (f->current_display_lines); } static void @@ -345,11 +375,10 @@ redraw_exposed_gutter (struct frame *f, enum gutter_pos pos, int x, int y, int width, int height) { int g_x, g_y, g_width, g_height; - int newx, newy; get_gutter_coords (f, pos, &g_x, &g_y, &g_width, &g_height); - if (((y + height) < g_y) || (y > (g_y + g_height))) + if (((y + height) < g_y) || (y > (g_y + g_height)) || !height || !width || !g_height || !g_width) return; if (((x + width) < g_x) || (x > (g_x + g_width))) return; @@ -357,16 +386,7 @@ redraw_exposed_gutter (struct frame *f, enum gutter_pos pos, int x, int y, /* #### optimize this - redrawing the whole gutter for every expose is very expensive. We reset the current display lines because if they're being exposed they are no longer current. */ - if (f->current_display_lines) - Dynarr_reset (f->current_display_lines); - /* we have to do this in-case there were subwindows where we are - redrawing, unfortunately sometimes this also generates expose - events resulting in an endless cycle of redsplay. */ - newx = max (x, g_x); - newy = max (y, g_y); - width = min (x + width - newx, g_x + g_width - newx); - height = min (y + height - newy, g_y + g_height - newy); - redisplay_unmap_subwindows_maybe (f, newx, newy, width, height); + reset_gutter_display_lines (f); /* Even if none of the gutter is in the area, the blank region at the very least must be because the first thing we did is verify @@ -378,21 +398,27 @@ void redraw_exposed_gutters (struct frame *f, int x, int y, int width, int height) { - int pos; - for (pos = 0; pos < 4; pos++) - { - if (FRAME_GUTTER_VISIBLE (f, pos)) - redraw_exposed_gutter (f, pos, x, y, width, height); - } + enum gutter_pos pos; + GUTTER_POS_LOOP (pos) + { + if (FRAME_GUTTER_VISIBLE (f, pos)) + redraw_exposed_gutter (f, pos, x, y, width, height); + } } void free_frame_gutters (struct frame *f) { if (f->current_display_lines) - Dynarr_free (f->current_display_lines); + { + free_display_lines (f->current_display_lines); + f->current_display_lines = 0; + } if (f->desired_display_lines) - Dynarr_free (f->desired_display_lines); + { + free_display_lines (f->desired_display_lines); + f->desired_display_lines = 0; + } } static enum gutter_pos @@ -548,8 +574,8 @@ static void gutter_specs_changed (Lisp_Object specifier, struct window *w, Lisp_Object oldval) { - int pos; - for (pos = 0; pos< 4; pos++) + enum gutter_pos pos; + GUTTER_POS_LOOP (pos) { w->real_gutter_size[pos] = w->gutter_size[pos]; if (EQ (w->real_gutter_size[pos], Qautodetect) @@ -573,8 +599,8 @@ static void gutter_geometry_changed_in_window (Lisp_Object specifier, struct window *w, Lisp_Object oldval) { - int pos; - for (pos = 0; pos< 4; pos++) + enum gutter_pos pos; + GUTTER_POS_LOOP (pos) { w->real_gutter_size[pos] = w->gutter_size[pos]; if (EQ (w->real_gutter_size[pos], Qautodetect) @@ -611,15 +637,70 @@ default_gutter_visible_p_changed_in_window (Lisp_Object specifier, recompute_overlaying_specifier (Vgutter_visible_p); } + +DECLARE_SPECIFIER_TYPE (gutter_size); +#define GUTTER_SIZE_SPECIFIERP(x) SPECIFIER_TYPEP (x, gutter_size) +DEFINE_SPECIFIER_TYPE (gutter_size); + +static void +gutter_size_validate (Lisp_Object instantiator) +{ + if (NILP (instantiator)) + return; + + if (!INTP (instantiator) && !EQ (instantiator, Qautodetect)) + signal_simple_error ("Gutter size must be an integer or 'autodetect", instantiator); +} + +DEFUN ("gutter-size-specifier-p", Fgutter_size_specifier_p, 1, 1, 0, /* +Return non-nil if OBJECT is a gutter-size specifier. +*/ + (object)) +{ + return GUTTER_SIZE_SPECIFIERP (object) ? Qt : Qnil; +} + +DEFUN ("redisplay-gutter-area", Fredisplay_gutter_area, 0, 0, 0, /* +Ensure that all gutters are correctly showing their gutter specifier. +*/ + ()) +{ + Lisp_Object devcons, concons; + + DEVICE_LOOP_NO_BREAK (devcons, concons) + { + struct device *d = XDEVICE (XCAR (devcons)); + Lisp_Object frmcons; + + DEVICE_FRAME_LOOP (frmcons, d) + { + struct frame *f = XFRAME (XCAR (frmcons)); + + if (FRAME_REPAINT_P (f)) + { + update_frame_gutters (f); + } + } + + /* We now call the output_end routine for tty frames. We delay + doing so in order to avoid cursor flicker. So much for 100% + encapsulation. */ + if (DEVICE_TTY_P (d)) + DEVMETH (d, output_end, (d)); + } + + return Qnil; +} + void init_frame_gutters (struct frame *f) { - int pos; + enum gutter_pos pos; struct window* w = XWINDOW (FRAME_LAST_NONMINIBUF_WINDOW (f)); /* We are here as far in frame creation so cached specifiers are already recomputed, and possibly modified by resource initialization. We need to recalculate autodetected gutters. */ - for (pos = 0; pos< 4; pos++) + GUTTER_POS_LOOP (pos) { w->real_gutter_size[pos] = w->gutter_size[pos]; if (EQ (w->gutter_size[pos], Qautodetect) @@ -636,10 +717,14 @@ void syms_of_gutter (void) { DEFSUBR (Fgutter_specifier_p); + DEFSUBR (Fgutter_size_specifier_p); DEFSUBR (Fset_default_gutter_position); DEFSUBR (Fdefault_gutter_position); DEFSUBR (Fgutter_pixel_height); DEFSUBR (Fgutter_pixel_width); + DEFSUBR (Fredisplay_gutter_area); + + defsymbol (&Qgutter_size, "gutter-size"); } void @@ -658,6 +743,17 @@ specifier_type_create_gutter (void) SPECIFIER_HAS_METHOD (gutter, validate); SPECIFIER_HAS_METHOD (gutter, after_change); + + INITIALIZE_SPECIFIER_TYPE (gutter_size, "gutter-size", "gutter-size-specifier-p"); + + SPECIFIER_HAS_METHOD (gutter_size, validate); +} + +void +reinit_specifier_type_create_gutter (void) +{ + REINITIALIZE_SPECIFIER_TYPE (gutter); + REINITIALIZE_SPECIFIER_TYPE (gutter_size); } void @@ -815,7 +911,7 @@ If you set the height to 'autodetect the size of the gutter will be calculated to be large enough to hold the contents of the gutter. This is the default. */ ); - Vdefault_gutter_height = Fmake_specifier (Qgeneric); + Vdefault_gutter_height = Fmake_specifier (Qgutter_size); set_specifier_caching (Vdefault_gutter_height, slot_offset (struct window, default_gutter_height), @@ -842,7 +938,7 @@ This is a specifier; use `set-specifier' to change it. See `default-gutter-height' for more information. */ ); - Vgutter_size[TOP_GUTTER] = Fmake_specifier (Qgeneric); + Vgutter_size[TOP_GUTTER] = Fmake_specifier (Qgutter_size); set_specifier_caching (Vgutter_size[TOP_GUTTER], slot_offset (struct window, gutter_size[TOP_GUTTER]), @@ -856,7 +952,7 @@ This is a specifier; use `set-specifier' to change it. See `default-gutter-height' for more information. */ ); - Vgutter_size[BOTTOM_GUTTER] = Fmake_specifier (Qgeneric); + Vgutter_size[BOTTOM_GUTTER] = Fmake_specifier (Qgutter_size); set_specifier_caching (Vgutter_size[BOTTOM_GUTTER], slot_offset (struct window, gutter_size[BOTTOM_GUTTER]), diff --git a/src/gutter.h b/src/gutter.h index d025865..8e31dd5 100644 --- a/src/gutter.h +++ b/src/gutter.h @@ -40,12 +40,16 @@ DECLARE_SPECIFIER_TYPE (gutter); enum gutter_pos { - TOP_GUTTER, - BOTTOM_GUTTER, - LEFT_GUTTER, - RIGHT_GUTTER + TOP_GUTTER = 0, + BOTTOM_GUTTER = 1, + LEFT_GUTTER = 2, + RIGHT_GUTTER = 3 }; +/* Iterate over all possible gutter positions */ +#define GUTTER_POS_LOOP(var) \ +for (var = (enum gutter_pos) 0; var < 4; var = (enum gutter_pos) (var + 1)) + extern Lisp_Object Qgutter; extern Lisp_Object Vgutter_size[4]; @@ -57,6 +61,7 @@ void init_global_gutters (struct device *d); void free_frame_gutters (struct frame *f); void redraw_exposed_gutters (struct frame *f, int x, int y, int width, int height); +void reset_gutter_display_lines (struct frame* f); #define WINDOW_GUTTER_BORDER_WIDTH(w, pos) \ (NILP ((w)->gutter_border_width[pos]) ? 0 : XINT ((w)->gutter_border_width[pos])) diff --git a/src/input-method-xlib.c b/src/input-method-xlib.c index 08e0135..4d3ccad 100644 --- a/src/input-method-xlib.c +++ b/src/input-method-xlib.c @@ -140,21 +140,17 @@ Initialize_Locale (void) static void IMDestroyCallback (XIM im, XPointer client_data, XPointer call_data) { - struct frame *f = (struct frame *)client_data; - struct device *d = XDEVICE (FRAME_DEVICE ((struct frame *)client_data)); - Lisp_Object frame_list = DEVICE_FRAME_LIST (XDEVICE (FRAME_DEVICE (f))); + struct frame *f = (struct frame *) client_data; + struct device *d = XDEVICE (FRAME_DEVICE (f)); Lisp_Object tail; - struct frame *target_frame = NULL; - LIST_LOOP (tail, frame_list) + DEVICE_FRAME_LOOP (tail, d) { - if (target_frame = XFRAME (XCAR (tail))) + struct frame *target_frame = XFRAME (XCAR (tail)); + if (FRAME_X_XIC (target_frame)) { - if ( FRAME_X_XIC(target_frame) ) - { - XDestroyIC (FRAME_X_XIC(target_frame)); - FRAME_X_XIC (target_frame) = NULL; - } + XDestroyIC (FRAME_X_XIC (target_frame)); + FRAME_X_XIC (target_frame) = NULL; } } @@ -176,10 +172,10 @@ IMDestroyCallback (XIM im, XPointer client_data, XPointer call_data) static void IMInstantiateCallback (Display *dpy, XPointer client_data, XPointer call_data) { - struct frame *f = (struct frame *)client_data; - struct device *d = XDEVICE (FRAME_DEVICE ((struct frame *)client_data)); + struct frame *f = (struct frame *) client_data; + struct device *d = XDEVICE (FRAME_DEVICE (f)); XIM xim; - Widget w = FRAME_X_TEXT_WIDGET ((struct frame *)client_data); + Widget w = FRAME_X_TEXT_WIDGET (f); Window win = XtWindow (w); XRectangle p_area = {0,0,1,1}, s_area = {0,0,1,1}; XPoint spot = {0,0}; @@ -225,7 +221,7 @@ IMInstantiateCallback (Display *dpy, XPointer client_data, XPointer call_data) /* destroy callback for im */ ximcallback.callback = IMDestroyCallback; - ximcallback.client_data = (XPointer)f; + ximcallback.client_data = (XPointer) f; XSetIMValues (xim, XNDestroyCallback, &ximcallback, NULL); } else @@ -311,16 +307,16 @@ XIM_init_device (struct device *d) static void XIM_delete_frame (Widget w, XtPointer client_data, XtPointer call_data) { - struct frame *f = (struct frame *)client_data; - struct device *d = XDEVICE (FRAME_DEVICE ((struct frame *)client_data)); + struct frame *f = (struct frame *) client_data; + struct device *d = XDEVICE (FRAME_DEVICE (f)); Display *dpy = DEVICE_X_DISPLAY (d); XUnregisterIMInstantiateCallback (dpy, NULL, NULL, NULL, - IMInstantiateCallback, (XtPointer)f); + IMInstantiateCallback, (XPointer) f); - if ( FRAME_X_XIC (f) ) + if (FRAME_X_XIC (f)) { - XDestroyIC (FRAME_X_XIC(f)); + XDestroyIC (FRAME_X_XIC (f)); FRAME_X_XIC (f) = NULL; } return; @@ -335,7 +331,7 @@ XIM_init_frame (struct frame *f) struct device *d = XDEVICE (FRAME_DEVICE (f)); XRegisterIMInstantiateCallback (DEVICE_X_DISPLAY (d), NULL, NULL, NULL, - IMInstantiateCallback, (XtPointer)f); + IMInstantiateCallback, (XPointer) f); #if 0 if ( FRAME_X_XIC (f) ) diff --git a/src/insdel.c b/src/insdel.c index 08d191d..ae3c614 100644 --- a/src/insdel.c +++ b/src/insdel.c @@ -3234,7 +3234,7 @@ convert_emchar_string_into_malloced_string (Emchar *arr, int nels, /************************************************************************/ void -vars_of_insdel (void) +reinit_vars_of_insdel (void) { int i; @@ -3246,6 +3246,12 @@ vars_of_insdel (void) } void +vars_of_insdel (void) +{ + reinit_vars_of_insdel (); +} + +void init_buffer_text (struct buffer *b) { if (!b->base_buffer) diff --git a/src/insdel.h b/src/insdel.h index 944fed3..81d477f 100644 --- a/src/insdel.h +++ b/src/insdel.h @@ -140,11 +140,11 @@ void buffer_reset_changes (struct buffer *buf); /************************************************************************/ Memind do_marker_adjustment (Memind mpos, Memind from, - Memind to, int amount); + Memind to, Bytecount amount); void fixup_internal_substring (CONST Bufbyte *nonreloc, Lisp_Object reloc, - int offset, int *len); + Bytecount offset, Bytecount *len); /* In font-lock.c */ void font_lock_maybe_update_syntactic_caches (struct buffer *buf, diff --git a/src/intl.c b/src/intl.c index 95249d4..7c06c74 100644 --- a/src/intl.c +++ b/src/intl.c @@ -165,7 +165,6 @@ x_get_composed_input (XKeyPressedEvent *x_key_event, XIC context, #endif /* I18N4 */ -Lisp_Object Qdomain; Lisp_Object Qdefer_gettext; DEFUN ("ignore-defer-gettext", Fignore_defer_gettext, 1, 1, 0, /* @@ -274,14 +273,7 @@ Bug: it has no effect on source (.el) files, only compiled (.elc) files. { CHECK_STRING (domain_name); if (load_in_progress) - { -#ifdef I18N3 - Vfile_domain = Fpurecopy (domain_name); - return Vfile_domain; -#else - return (domain_name); -#endif - } + return (domain_name); else return Qnil; } @@ -307,8 +299,6 @@ init_intl_very_early (void) void syms_of_intl (void) { - defsymbol (&Qdomain, "domain"); - /* defer-gettext is defined as a symbol because when it is used in menu specification strings, it is not evaluated as a function by menu_item_descriptor_to_widget_value(). */ diff --git a/src/keymap.c b/src/keymap.c index 430acdc..04b6b46 100644 --- a/src/keymap.c +++ b/src/keymap.c @@ -252,15 +252,15 @@ Lisp_Object QLFD, QTAB, QRET, QESC, QDEL, QSPC, QBS; /************************************************************************/ static Lisp_Object -mark_keymap (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_keymap (Lisp_Object obj) { Lisp_Keymap *keymap = XKEYMAP (obj); - markobj (keymap->parents); - markobj (keymap->prompt); - markobj (keymap->inverse_table); - markobj (keymap->sub_maps_cache); - markobj (keymap->default_binding); - markobj (keymap->name); + mark_object (keymap->parents); + mark_object (keymap->prompt); + mark_object (keymap->inverse_table); + mark_object (keymap->sub_maps_cache); + mark_object (keymap->default_binding); + mark_object (keymap->name); return keymap->table; } @@ -278,7 +278,7 @@ print_keymap (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) print_internal (keymap->name, printcharfun, 1); /* #### Yuck! This is no way to form plural! --hniksic */ sprintf (buf, "%s%d entr%s 0x%x>", - ((NILP (keymap->name)) ? "" : " "), + (NILP (keymap->name) ? "" : " "), size, ((size == 1) ? "y" : "ies"), keymap->header.uid); @@ -1351,6 +1351,8 @@ define_key_check_and_coerce_keysym (Lisp_Object spec, *keysym = QKescape; else if (EQ (*keysym, QDEL)) *keysym = QKdelete; + else if (EQ (*keysym, QSPC)) + *keysym = QKspace; else if (EQ (*keysym, QBS)) *keysym = QKbackspace; /* Emacs compatibility */ @@ -3175,9 +3177,9 @@ spaces are put between sequence elements, etc... for (i = 0; i < size; i++) { Lisp_Object s2 = Fsingle_key_description - (((STRINGP (keys)) - ? make_char (string_char (XSTRING (keys), i)) - : XVECTOR_DATA (keys)[i])); + (STRINGP (keys) + ? make_char (string_char (XSTRING (keys), i)) + : XVECTOR_DATA (keys)[i]); if (i == 0) string = s2; @@ -3534,7 +3536,7 @@ where_is_recursive_mapper (Lisp_Object map, void *arg) for (;;) /* loop over all keys that match */ { - Lisp_Object k = ((CONSP (keys)) ? XCAR (keys) : keys); + Lisp_Object k = CONSP (keys) ? XCAR (keys) : keys; int i; so_far [keys_count].keysym = k; @@ -4274,6 +4276,7 @@ syms_of_keymap (void) defsymbol (&QRET, "RET"); defsymbol (&QESC, "ESC"); defsymbol (&QDEL, "DEL"); + defsymbol (&QSPC, "SPC"); defsymbol (&QBS, "BS"); } @@ -4327,7 +4330,7 @@ Incremented for each change to any keymap. staticpro (&Vcurrent_global_map); - Vsingle_space_string = make_string_nocopy ((CONST Bufbyte *) " ", 1); + Vsingle_space_string = make_string ((CONST Bufbyte *) " ", 1); staticpro (&Vsingle_space_string); } diff --git a/src/keymap.h b/src/keymap.h index bb0c8a0..26edb82 100644 --- a/src/keymap.h +++ b/src/keymap.h @@ -28,7 +28,6 @@ DECLARE_LRECORD (keymap, struct Lisp_Keymap); #define XKEYMAP(x) XRECORD (x, keymap, struct Lisp_Keymap) #define XSETKEYMAP(x, p) XSETRECORD (x, p, keymap) #define KEYMAPP(x) RECORDP (x, keymap) -#define GC_KEYMAPP(x) GC_RECORDP (x, keymap) #define CHECK_KEYMAP(x) CHECK_RECORD (x, keymap) #define CONCHECK_KEYMAP(x) CONCHECK_RECORD (x, keymap) diff --git a/src/linuxplay.c b/src/linuxplay.c index f5fe236..4847277 100644 --- a/src/linuxplay.c +++ b/src/linuxplay.c @@ -125,7 +125,7 @@ static union { /* Use a global buffer as scratch-pad for possible conversions of the sampling format */ -unsigned char linuxplay_sndbuf[SNDBUFSZ]; +static unsigned char linuxplay_sndbuf[SNDBUFSZ]; static int mix_fd; static int audio_vol; diff --git a/src/lisp-disunion.h b/src/lisp-disunion.h index f2c321b..8ed19df 100644 --- a/src/lisp-disunion.h +++ b/src/lisp-disunion.h @@ -70,8 +70,8 @@ Boston, MA 02111-1307, USA. */ XUINT The value bits of a Lisp_Object storing an integer, unsigned INTP Non-zero if this Lisp_Object an integer? Qzero Lisp Integer 0 - EQ Non-zero if two Lisp_Objects are identical - GC_EQ Version of EQ used during garbage collection */ + EQ Non-zero if two Lisp_Objects are identical */ + typedef EMACS_INT Lisp_Object; @@ -83,14 +83,16 @@ typedef EMACS_INT Lisp_Object; #define XTYPE(x) ((enum Lisp_Type) (((EMACS_UINT)(x)) & ~VALMASK)) #define XPNTRVAL(x) (x) /* This depends on Lisp_Type_Record == 0 */ #define XCHARVAL(x) ((x) >> GCBITS) -#define GC_EQ(x,y) EQ (x,y) #define XREALINT(x) ((x) >> INT_GCBITS) #define XUINT(x) ((EMACS_UINT)(x) >> INT_GCBITS) #define INTP(x) ((EMACS_UINT)(x) & Lisp_Type_Int_Bit) +#define INT_PLUS(x,y) ((x)+(y)-Lisp_Type_Int_Bit) +#define INT_MINUS(x,y) ((x)-(y)+Lisp_Type_Int_Bit) +#define INT_PLUS1(x) INT_PLUS (x, make_int (1)) +#define INT_MINUS1(x) INT_MINUS (x, make_int (1)) #define Qzero make_int (0) #define Qnull_pointer ((Lisp_Object) 0) -#define XGCTYPE(x) XTYPE(x) #define EQ(x,y) ((x) == (y)) #define XSETINT(var, value) ((void) ((var) = make_int (value))) #define XSETCHAR(var, value) ((void) ((var) = make_char (value))) diff --git a/src/lisp-union.h b/src/lisp-union.h index a04c689..54088cf 100644 --- a/src/lisp-union.h +++ b/src/lisp-union.h @@ -123,11 +123,13 @@ extern Lisp_Object Qnull_pointer, Qzero; #define XREALINT(x) ((x).s.val) #define XUINT(x) ((x).u.val) #define XTYPE(x) ((x).gu.type) -#define XGCTYPE(x) XTYPE (x) #define EQ(x,y) ((x).v == (y).v) #define INTP(x) ((x).s.bits) -#define GC_EQ(x,y) EQ (x, y) +#define INT_PLUS(x,y) make_int (XINT (x) + XINT (y)) +#define INT_MINUS(x,y) make_int (XINT (x) - XINT (y)) +#define INT_PLUS1(x) make_int (XINT (x) + 1) +#define INT_MINUS1(x) make_int (XINT (x) - 1) /* Convert between a (void *) and a Lisp_Object, as when the Lisp_Object is passed to a toolkit callback function */ diff --git a/src/lisp.h b/src/lisp.h index 1f6c0b2..3831e32 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -250,6 +250,33 @@ DECLARE_DOESNT_RETURN (assert_failed (CONST char *, int, CONST char *)); /*#define REGISTER register*/ /*#endif*/ + +/* EMACS_INT is the underlying integral type into which a Lisp_Object must fit. + In particular, it must be large enough to contain a pointer. + config.h can override this, e.g. to use `long long' for bigger lisp ints. */ + +#ifndef SIZEOF_EMACS_INT +# define SIZEOF_EMACS_INT SIZEOF_VOID_P +#endif + +#ifndef EMACS_INT +# if SIZEOF_EMACS_INT == SIZEOF_LONG +# define EMACS_INT long +# elif SIZEOF_EMACS_INT == SIZEOF_INT +# define EMACS_INT int +# elif SIZEOF_EMACS_INT == SIZEOF_LONG_LONG +# define EMACS_INT long long +# else +# error Unable to determine suitable type for EMACS_INT +# endif +#endif + +#ifndef EMACS_UINT +# define EMACS_UINT unsigned EMACS_INT +#endif + +#define BITS_PER_EMACS_INT (SIZEOF_EMACS_INT * BITS_PER_CHAR) + /************************************************************************/ /* typedefs */ @@ -284,17 +311,17 @@ typedef int Emchar; buffer.h (where they rightfully belong) to avoid syntax errors in function prototypes. */ -typedef int Bufpos; -typedef int Bytind; -typedef int Memind; +typedef EMACS_INT Bufpos; +typedef EMACS_INT Bytind; +typedef EMACS_INT Memind; /* Counts of bytes or chars */ -typedef int Bytecount; -typedef int Charcount; +typedef EMACS_INT Bytecount; +typedef EMACS_INT Charcount; /* Length in bytes of a string in external format */ -typedef int Extcount; +typedef EMACS_INT Extcount; typedef struct lstream Lstream; @@ -340,6 +367,8 @@ typedef struct Lisp_Image_Instance Lisp_Image_Instance; struct Lisp_Gui_Item; typedef struct Lisp_Gui_Item Lisp_Gui_Item; struct display_line; +struct display_glyph_area; +struct display_box; struct redisplay_info; struct window_mirror; struct scrollbar_instance; @@ -467,6 +496,14 @@ enum toolbar_pos }; #endif +enum edge_style +{ + EDGE_ETCHED_IN, + EDGE_ETCHED_OUT, + EDGE_BEVEL_IN, + EDGE_BEVEL_OUT +}; + #ifndef ERROR_CHECK_TYPECHECK typedef enum error_behavior @@ -523,32 +560,6 @@ enum Lisp_Type #define POINTER_TYPE_P(type) ((type) == Lisp_Type_Record) -/* EMACS_INT is the underlying integral type into which a Lisp_Object must fit. - In particular, it must be large enough to contain a pointer. - config.h can override this, e.g. to use `long long' for bigger lisp ints. */ - -#ifndef SIZEOF_EMACS_INT -# define SIZEOF_EMACS_INT SIZEOF_VOID_P -#endif - -#ifndef EMACS_INT -# if SIZEOF_EMACS_INT == SIZEOF_LONG -# define EMACS_INT long -# elif SIZEOF_EMACS_INT == SIZEOF_INT -# define EMACS_INT int -# elif SIZEOF_EMACS_INT == SIZEOF_LONG_LONG -# define EMACS_INT long long -# else -# error Unable to determine suitable type for EMACS_INT -# endif -#endif - -#ifndef EMACS_UINT -# define EMACS_UINT unsigned EMACS_INT -#endif - -#define BITS_PER_EMACS_INT (SIZEOF_EMACS_INT * BITS_PER_CHAR) - /* Overridden by m/next.h */ #ifndef ASSERT_VALID_POINTER # define ASSERT_VALID_POINTER(pnt) (assert ((((EMACS_UINT) pnt) & 3) == 0)) @@ -569,7 +580,7 @@ enum Lisp_Type # include "lisp-disunion.h" #endif /* !USE_UNION_TYPE */ -#define XPNTR(x) ((void *) (XPNTRVAL(x))) +#define XPNTR(x) ((void *) XPNTRVAL(x)) /* WARNING WARNING WARNING. You must ensure on your own that proper GC protection is provided for the elements in this array. */ @@ -581,8 +592,8 @@ typedef struct /* Close your eyes now lest you vomit or spontaneously combust ... */ #define HACKEQ_UNSAFE(obj1, obj2) \ - (EQ (obj1, obj2) || (!POINTER_TYPE_P (XGCTYPE (obj1)) \ - && !POINTER_TYPE_P (XGCTYPE (obj2)) \ + (EQ (obj1, obj2) || (!POINTER_TYPE_P (XTYPE (obj1)) \ + && !POINTER_TYPE_P (XTYPE (obj2)) \ && XCHAR_OR_INT (obj1) == XCHAR_OR_INT (obj2))) #ifdef DEBUG_XEMACS @@ -612,7 +623,6 @@ int eq_with_ebola_notice (Lisp_Object, Lisp_Object); to mean "no such value". */ #define UNBOUNDP(val) EQ (val, Qunbound) -#define GC_UNBOUNDP(val) GC_EQ (val, Qunbound) /*********** cons ***********/ @@ -641,7 +651,6 @@ DECLARE_LRECORD (cons, Lisp_Cons); #define XCONS(x) XRECORD (x, cons, Lisp_Cons) #define XSETCONS(x, p) XSETRECORD (x, p, cons) #define CONSP(x) RECORDP (x, cons) -#define GC_CONSP(x) GC_RECORDP (x, cons) #define CHECK_CONS(x) CHECK_RECORD (x, cons) #define CONCHECK_CONS(x) CONCHECK_RECORD (x, cons) @@ -651,7 +660,6 @@ DECLARE_LRECORD (cons, Lisp_Cons); extern Lisp_Object Qnil; #define NILP(x) EQ (x, Qnil) -#define GC_NILP(x) GC_EQ (x, Qnil) #define XCAR(a) (XCONS (a)->car) #define XCDR(a) (XCONS (a)->cdr) #define LISTP(x) (CONSP(x) || NILP(x)) @@ -711,7 +719,7 @@ do { \ #define EXTERNAL_LIST_LOOP_DELETE_IF(elt, list, condition) do { \ Lisp_Object prev_tail_##list = Qnil; \ Lisp_Object tail_##list; \ - int len_##list; \ + EMACS_INT len_##list; \ EXTERNAL_LIST_LOOP_4 (elt, list, tail_##list, len_##list) \ { \ if (condition) \ @@ -768,26 +776,26 @@ do { \ #define EXTERNAL_LIST_LOOP_1(list) \ Lisp_Object ELL1_elt, ELL1_hare, ELL1_tortoise; \ -int ELL1_len; \ -EXTERNAL_LIST_LOOP_6(ELL1_elt, list, ELL1_len, ELL1_hare, \ - ELL1_tortoise, CIRCULAR_LIST_SUSPICION_LENGTH) +EMACS_INT ELL1_len; \ +EXTERNAL_LIST_LOOP_6 (ELL1_elt, list, ELL1_len, ELL1_hare, \ + ELL1_tortoise, CIRCULAR_LIST_SUSPICION_LENGTH) #define EXTERNAL_LIST_LOOP_2(elt, list) \ Lisp_Object hare_##elt, tortoise_##elt; \ -int len_##elt; \ -EXTERNAL_LIST_LOOP_6(elt, list, len_##elt, hare_##elt, \ - tortoise_##elt, CIRCULAR_LIST_SUSPICION_LENGTH) +EMACS_INT len_##elt; \ +EXTERNAL_LIST_LOOP_6 (elt, list, len_##elt, hare_##elt, \ + tortoise_##elt, CIRCULAR_LIST_SUSPICION_LENGTH) #define EXTERNAL_LIST_LOOP_3(elt, list, tail) \ Lisp_Object tortoise_##elt; \ -int len_##elt; \ -EXTERNAL_LIST_LOOP_6(elt, list, len_##elt, tail, \ - tortoise_##elt, CIRCULAR_LIST_SUSPICION_LENGTH) +EMACS_INT len_##elt; \ +EXTERNAL_LIST_LOOP_6 (elt, list, len_##elt, tail, \ + tortoise_##elt, CIRCULAR_LIST_SUSPICION_LENGTH) #define EXTERNAL_LIST_LOOP_4(elt, list, tail, len) \ Lisp_Object tortoise_##elt; \ -EXTERNAL_LIST_LOOP_6(elt, list, len, tail, \ - tortoise_##elt, CIRCULAR_LIST_SUSPICION_LENGTH) +EXTERNAL_LIST_LOOP_6 (elt, list, len, tail, \ + tortoise_##elt, CIRCULAR_LIST_SUSPICION_LENGTH) #define EXTERNAL_LIST_LOOP_6(elt, list, len, hare, \ @@ -812,30 +820,30 @@ EXTERNAL_LIST_LOOP_6(elt, list, len, tail, \ /* Optimized and safe macros for looping over external alists. */ -#define EXTERNAL_ALIST_LOOP_4(elt, elt_car, elt_cdr, list) \ -Lisp_Object hare_##elt, tortoise_##elt; \ -int len_##elt; \ -EXTERNAL_ALIST_LOOP_8 (elt, elt_car, elt_cdr, list, \ - len_##elt, hare_##elt, tortoise_##elt, \ +#define EXTERNAL_ALIST_LOOP_4(elt, elt_car, elt_cdr, list) \ +Lisp_Object hare_##elt, tortoise_##elt; \ +EMACS_INT len_##elt; \ +EXTERNAL_ALIST_LOOP_8 (elt, elt_car, elt_cdr, list, \ + len_##elt, hare_##elt, tortoise_##elt, \ CIRCULAR_LIST_SUSPICION_LENGTH) #define EXTERNAL_ALIST_LOOP_5(elt, elt_car, elt_cdr, list, tail) \ Lisp_Object tortoise_##elt; \ -int len_##elt; \ -EXTERNAL_ALIST_LOOP_8(elt, elt_car, elt_cdr, list, \ - len_##elt, tail, tortoise_##elt, \ - CIRCULAR_LIST_SUSPICION_LENGTH) +EMACS_INT len_##elt; \ +EXTERNAL_ALIST_LOOP_8 (elt, elt_car, elt_cdr, list, \ + len_##elt, tail, tortoise_##elt, \ + CIRCULAR_LIST_SUSPICION_LENGTH) \ #define EXTERNAL_ALIST_LOOP_6(elt, elt_car, elt_cdr, list, tail, len) \ Lisp_Object tortoise_##elt; \ -EXTERNAL_ALIST_LOOP_8(elt, elt_car, elt_cdr, list, \ - len, tail, tortoise_##elt, \ - CIRCULAR_LIST_SUSPICION_LENGTH) +EXTERNAL_ALIST_LOOP_8 (elt, elt_car, elt_cdr, list, \ + len, tail, tortoise_##elt, \ + CIRCULAR_LIST_SUSPICION_LENGTH) #define EXTERNAL_ALIST_LOOP_8(elt, elt_car, elt_cdr, list, len, hare, \ tortoise, suspicion_length) \ -EXTERNAL_LIST_LOOP_6(elt, list, len, hare, tortoise, suspicion_length) \ +EXTERNAL_LIST_LOOP_6 (elt, list, len, hare, tortoise, suspicion_length) \ if (CONSP (elt) ? (elt_car = XCAR (elt), elt_cdr = XCDR (elt), 0) :1) \ continue; \ else @@ -844,20 +852,20 @@ EXTERNAL_LIST_LOOP_6(elt, list, len, hare, tortoise, suspicion_length) \ /* Optimized and safe macros for looping over external property lists. */ #define EXTERNAL_PROPERTY_LIST_LOOP_3(key, value, list) \ Lisp_Object key, value, hare_##key, tortoise_##key; \ -int len_##key; \ -EXTERNAL_PROPERTY_LIST_LOOP_7(key, value, list, len_##key, hare_##key,\ +EMACS_INT len_##key; \ +EXTERNAL_PROPERTY_LIST_LOOP_7 (key, value, list, len_##key, hare_##key, \ tortoise_##key, CIRCULAR_LIST_SUSPICION_LENGTH) #define EXTERNAL_PROPERTY_LIST_LOOP_4(key, value, list, tail) \ Lisp_Object key, value, tail, tortoise_##key; \ -int len_##key; \ -EXTERNAL_PROPERTY_LIST_LOOP_7(key, value, list, len_##key, tail, \ +EMACS_INT len_##key; \ +EXTERNAL_PROPERTY_LIST_LOOP_7 (key, value, list, len_##key, tail, \ tortoise_##key, CIRCULAR_LIST_SUSPICION_LENGTH) #define EXTERNAL_PROPERTY_LIST_LOOP_5(key, value, list, tail, len) \ Lisp_Object key, value, tail, tortoise_##key; \ -int len; \ -EXTERNAL_PROPERTY_LIST_LOOP_7(key, value, list, len, tail, \ +EMACS_INT len; \ +EXTERNAL_PROPERTY_LIST_LOOP_7 (key, value, list, len, tail, \ tortoise_##key, CIRCULAR_LIST_SUSPICION_LENGTH) @@ -914,7 +922,7 @@ INLINE int TRUE_LIST_P (Lisp_Object object) { Lisp_Object hare, tortoise; - int len; + EMACS_INT len; for (hare = tortoise = object, len = 0; CONSP (hare); @@ -936,7 +944,7 @@ TRUE_LIST_P (Lisp_Object object) #define CHECK_TRUE_LIST(list) do { \ Lisp_Object CTL_list = (list); \ Lisp_Object CTL_hare, CTL_tortoise; \ - int CTL_len; \ + EMACS_INT CTL_len; \ \ for (CTL_hare = CTL_tortoise = CTL_list, CTL_len = 0; \ CONSP (CTL_hare); \ @@ -970,7 +978,6 @@ DECLARE_LRECORD (string, Lisp_String); #define XSTRING(x) XRECORD (x, string, Lisp_String) #define XSETSTRING(x, p) XSETRECORD (x, p, string) #define STRINGP(x) RECORDP (x, string) -#define GC_STRINGP(x) GC_RECORDP (x, string) #define CHECK_STRING(x) CHECK_RECORD (x, string) #define CONCHECK_STRING(x) CONCHECK_RECORD (x, string) @@ -1039,7 +1046,6 @@ DECLARE_LRECORD (vector, Lisp_Vector); #define XVECTOR(x) XRECORD (x, vector, Lisp_Vector) #define XSETVECTOR(x, p) XSETRECORD (x, p, vector) #define VECTORP(x) RECORDP (x, vector) -#define GC_VECTORP(x) GC_RECORDP (x, vector) #define CHECK_VECTOR(x) CHECK_RECORD (x, vector) #define CONCHECK_VECTOR(x) CONCHECK_RECORD (x, vector) @@ -1078,12 +1084,10 @@ DECLARE_LRECORD (bit_vector, Lisp_Bit_Vector); #define XBIT_VECTOR(x) XRECORD (x, bit_vector, Lisp_Bit_Vector) #define XSETBIT_VECTOR(x, p) XSETRECORD (x, p, bit_vector) #define BIT_VECTORP(x) RECORDP (x, bit_vector) -#define GC_BIT_VECTORP(x) GC_RECORDP (x, bit_vector) #define CHECK_BIT_VECTOR(x) CHECK_RECORD (x, bit_vector) #define CONCHECK_BIT_VECTOR(x) CONCHECK_RECORD (x, bit_vector) #define BITP(x) (INTP (x) && (XINT (x) == 0 || XINT (x) == 1)) -#define GC_BITP(x) (GC_INTP (x) && (XINT (x) == 0 || XINT (x) == 1)) #define CHECK_BIT(x) do { \ if (!BITP (x)) \ @@ -1098,25 +1102,22 @@ DECLARE_LRECORD (bit_vector, Lisp_Bit_Vector); #define bit_vector_length(v) ((v)->size) #define bit_vector_next(v) ((v)->next) -INLINE int bit_vector_bit (Lisp_Bit_Vector *v, int i); +INLINE int bit_vector_bit (Lisp_Bit_Vector *v, size_t n); INLINE int -bit_vector_bit (Lisp_Bit_Vector *v, int i) +bit_vector_bit (Lisp_Bit_Vector *v, size_t n) { - unsigned int ui = (unsigned int) i; - - return (((v)->bits[ui >> LONGBITS_LOG2] >> (ui & (LONGBITS_POWER_OF_2 - 1))) + return ((v->bits[n >> LONGBITS_LOG2] >> (n & (LONGBITS_POWER_OF_2 - 1))) & 1); } -INLINE void set_bit_vector_bit (Lisp_Bit_Vector *v, int i, int value); +INLINE void set_bit_vector_bit (Lisp_Bit_Vector *v, size_t n, int value); INLINE void -set_bit_vector_bit (Lisp_Bit_Vector *v, int i, int value) +set_bit_vector_bit (Lisp_Bit_Vector *v, size_t n, int value) { - unsigned int ui = (unsigned int) i; if (value) - (v)->bits[ui >> LONGBITS_LOG2] |= (1UL << (ui & (LONGBITS_POWER_OF_2 - 1))); + v->bits[n >> LONGBITS_LOG2] |= (1UL << (n & (LONGBITS_POWER_OF_2 - 1))); else - (v)->bits[ui >> LONGBITS_LOG2] &= ~(1UL << (ui & (LONGBITS_POWER_OF_2 - 1))); + v->bits[n >> LONGBITS_LOG2] &= ~(1UL << (n & (LONGBITS_POWER_OF_2 - 1))); } /* Number of longs required to hold LEN bits */ @@ -1149,7 +1150,6 @@ DECLARE_LRECORD (symbol, Lisp_Symbol); #define XSYMBOL(x) XRECORD (x, symbol, Lisp_Symbol) #define XSETSYMBOL(x, p) XSETRECORD (x, p, symbol) #define SYMBOLP(x) RECORDP (x, symbol) -#define GC_SYMBOLP(x) GC_RECORDP (x, symbol) #define CHECK_SYMBOL(x) CHECK_RECORD (x, symbol) #define CONCHECK_SYMBOL(x) CONCHECK_RECORD (x, symbol) @@ -1178,7 +1178,6 @@ DECLARE_LRECORD (subr, Lisp_Subr); #define XSUBR(x) XRECORD (x, subr, Lisp_Subr) #define XSETSUBR(x, p) XSETRECORD (x, p, subr) #define SUBRP(x) RECORDP (x, subr) -#define GC_SUBRP(x) GC_RECORDP (x, subr) #define CHECK_SUBR(x) CHECK_RECORD (x, subr) #define CONCHECK_SUBR(x) CONCHECK_RECORD (x, subr) @@ -1201,7 +1200,6 @@ DECLARE_LRECORD (marker, Lisp_Marker); #define XMARKER(x) XRECORD (x, marker, Lisp_Marker) #define XSETMARKER(x, p) XSETRECORD (x, p, marker) #define MARKERP(x) RECORDP (x, marker) -#define GC_MARKERP(x) GC_RECORDP (x, marker) #define CHECK_MARKER(x) CHECK_RECORD (x, marker) #define CONCHECK_MARKER(x) CONCHECK_RECORD (x, marker) @@ -1214,7 +1212,6 @@ DECLARE_LRECORD (marker, Lisp_Marker); /*********** char ***********/ #define CHARP(x) (XTYPE (x) == Lisp_Type_Char) -#define GC_CHARP(x) (XGCTYPE (x) == Lisp_Type_Char) #ifdef ERROR_CHECK_TYPECHECK @@ -1256,7 +1253,6 @@ DECLARE_LRECORD (float, Lisp_Float); #define XFLOAT(x) XRECORD (x, float, Lisp_Float) #define XSETFLOAT(x, p) XSETRECORD (x, p, float) #define FLOATP(x) RECORDP (x, float) -#define GC_FLOATP(x) GC_RECORDP (x, float) #define CHECK_FLOAT(x) CHECK_RECORD (x, float) #define CONCHECK_FLOAT(x) CONCHECK_RECORD (x, float) @@ -1276,31 +1272,25 @@ DECLARE_LRECORD (float, Lisp_Float); } while (0) # define INT_OR_FLOATP(x) (INTP (x) || FLOATP (x)) -# define GC_INT_OR_FLOATP(x) (GC_INTP (x) || GC_FLOATP (x)) #else /* not LISP_FLOAT_TYPE */ #define XFLOAT(x) --- error! No float support. --- #define XSETFLOAT(x, p) --- error! No float support. --- #define FLOATP(x) 0 -#define GC_FLOATP(x) 0 #define CHECK_FLOAT(x) --- error! No float support. --- #define CONCHECK_FLOAT(x) --- error! No float support. --- #define XFLOATINT(n) XINT(n) #define CHECK_INT_OR_FLOAT CHECK_INT #define CONCHECK_INT_OR_FLOAT CONCHECK_INT -#define INT_OR_FLOATP(x) (INTP (x)) -# define GC_INT_OR_FLOATP(x) (GC_INTP (x)) +#define INT_OR_FLOATP(x) INTP (x) #endif /* not LISP_FLOAT_TYPE */ /*********** int ***********/ -#define GC_INTP(x) INTP (x) - #define ZEROP(x) EQ (x, Qzero) -#define GC_ZEROP(x) GC_EQ (x, Qzero) #ifdef ERROR_CHECK_TYPECHECK @@ -1338,7 +1328,6 @@ XCHAR_OR_INT (Lisp_Object obj) } while (0) #define NATNUMP(x) (INTP (x) && XINT (x) >= 0) -#define GC_NATNUMP(x) (GC_INTP (x) && XINT (x) >= 0) #define CHECK_NATNUM(x) do { \ if (!NATNUMP (x)) \ @@ -1460,7 +1449,6 @@ DECLARE_LRECORD (weak_list, struct weak_list); #define XWEAK_LIST(x) XRECORD (x, weak_list, struct weak_list) #define XSETWEAK_LIST(x, p) XSETRECORD (x, p, weak_list) #define WEAK_LISTP(x) RECORDP (x, weak_list) -#define GC_WEAK_LISTP(x) GC_RECORDP (x, weak_list) #define CHECK_WEAK_LIST(x) CHECK_RECORD (x, weak_list) #define CONCHECK_WEAK_LIST(x) CONCHECK_RECORD (x, weak_list) @@ -1469,9 +1457,8 @@ DECLARE_LRECORD (weak_list, struct weak_list); Lisp_Object make_weak_list (enum weak_list_type type); /* The following two are only called by the garbage collector */ -int finish_marking_weak_lists (int (*obj_marked_p) (Lisp_Object), - void (*markobj) (Lisp_Object)); -void prune_weak_lists (int (*obj_marked_p) (Lisp_Object)); +int finish_marking_weak_lists (void); +void prune_weak_lists (void); /*********** lcrecord lists ***********/ @@ -1487,7 +1474,6 @@ DECLARE_LRECORD (lcrecord_list, struct lcrecord_list); #define XLCRECORD_LIST(x) XRECORD (x, lcrecord_list, struct lcrecord_list) #define XSETLCRECORD_LIST(x, p) XSETRECORD (x, p, lcrecord_list) #define LCRECORD_LISTP(x) RECORDP (x, lcrecord_list) -#define GC_LCRECORD_LISTP(x) GC_RECORDP (x, lcrecord_list) /* #define CHECK_LCRECORD_LIST(x) CHECK_RECORD (x, lcrecord_list) Lcrecord lists should never escape to the Lisp level, so functions should not be doing this. */ @@ -1814,8 +1800,7 @@ void debug_ungcpro(char *, int, struct gcpro *); gcpro4.next = &gcpro3, gcpro4.var = &var4, gcpro4.nvars = 1, \ gcprolist = &gcpro4 )) -#define GCPRO5(var1, var2, var3, var4, var5) \ - ((void) ( \ +#define GCPRO5(var1, var2, var3, var4, var5) ((void) ( \ gcpro1.next = gcprolist, gcpro1.var = &var1, gcpro1.nvars = 1, \ gcpro2.next = &gcpro1, gcpro2.var = &var2, gcpro2.nvars = 1, \ gcpro3.next = &gcpro2, gcpro3.var = &var3, gcpro3.nvars = 1, \ @@ -1847,8 +1832,7 @@ void debug_ungcpro(char *, int, struct gcpro *); ngcpro4.next = &ngcpro3, ngcpro4.var = &var4, ngcpro4.nvars = 1, \ gcprolist = &ngcpro4 )) -#define NGCPRO5(var1, var2, var3, var4, var5) \ - ((void) ( \ +#define NGCPRO5(var1, var2, var3, var4, var5) ((void) ( \ ngcpro1.next = gcprolist, ngcpro1.var = &var1, ngcpro1.nvars = 1, \ ngcpro2.next = &ngcpro1, ngcpro2.var = &var2, ngcpro2.nvars = 1, \ ngcpro3.next = &ngcpro2, ngcpro3.var = &var3, ngcpro3.nvars = 1, \ @@ -1880,8 +1864,7 @@ void debug_ungcpro(char *, int, struct gcpro *); nngcpro4.next = &nngcpro3, nngcpro4.var = &var4, nngcpro4.nvars = 1, \ gcprolist = &nngcpro4 )) -#define NNGCPRO5(var1, var2, var3, var4, var5) \ - ((void) ( \ +#define NNGCPRO5(var1, var2, var3, var4, var5) ((void) ( \ nngcpro1.next = gcprolist, nngcpro1.var = &var1, nngcpro1.nvars = 1, \ nngcpro2.next = &nngcpro1, nngcpro2.var = &var2, nngcpro2.nvars = 1, \ nngcpro3.next = &nngcpro2, nngcpro3.var = &var3, nngcpro3.nvars = 1, \ @@ -1943,6 +1926,21 @@ void debug_ungcpro(char *, int, struct gcpro *); /* Call staticpro (&var) to protect static variable `var'. */ void staticpro (Lisp_Object *); +/* Call staticpro_nodump (&var) to protect static variable `var'. */ +/* var will not be saved at dump time */ +void staticpro_nodump (Lisp_Object *); + +/* Call dumpstruct(&var, &desc) to dump the structure pointed to by `var'. */ +void dumpstruct (void *, const struct struct_description *); + +/* Call pdump_wire(&var) to ensure that var is properly updated after pdump. */ +void pdump_wire (Lisp_Object *); + +/* Call pdump_wire(&var) to ensure that var is properly updated after + pdump. var must point to a linked list of objects out of which + some may not be dumped */ +void pdump_wire_list (Lisp_Object *); + /* Nonzero means Emacs has already been initialized. Used during startup to detect startup of dumped Emacs. */ extern int initialized; @@ -1992,7 +1990,7 @@ struct overhead_stats #endif #endif #ifndef IS_ANY_SEP -#define IS_ANY_SEP(c) (IS_DIRECTORY_SEP (c)) +#define IS_ANY_SEP(c) IS_DIRECTORY_SEP (c) #endif #ifdef HAVE_INTTYPES_H @@ -2056,11 +2054,22 @@ void free_alist (Lisp_Object); void mark_conses_in_list (Lisp_Object); void free_marker (Lisp_Marker *); int object_dead_p (Lisp_Object); +void mark_object (Lisp_Object obj); +int marked_p (Lisp_Object obj); #ifdef MEMORY_USAGE_STATS size_t malloced_storage_size (void *, size_t, struct overhead_stats *); size_t fixed_type_block_overhead (size_t); #endif +#ifdef PDUMP +void pdump (void); +int pdump_load (void); + +extern char *pdump_start, *pdump_end; +#define DUMPEDP(adr) ((((char *)(adr)) < pdump_end) && (((char *)(adr)) >= pdump_start)) +#else +#define DUMPEDP(adr) 0 +#endif /* Defined in buffer.c */ Lisp_Object make_buffer (struct buffer *); @@ -2083,7 +2092,7 @@ DECLARE_DOESNT_RETURN (args_out_of_range_3 (Lisp_Object, Lisp_Object, Lisp_Object)); Lisp_Object wrong_type_argument (Lisp_Object, Lisp_Object); DECLARE_DOESNT_RETURN (dead_wrong_type_argument (Lisp_Object, Lisp_Object)); -void check_int_range (int, int, int); +void check_int_range (EMACS_INT, EMACS_INT, EMACS_INT); enum arith_comparison { arith_equal, @@ -2130,8 +2139,8 @@ char *user_login_name (int *); Bufpos bufpos_clip_to_bounds (Bufpos, Bufpos, Bufpos); Bytind bytind_clip_to_bounds (Bytind, Bytind, Bytind); void buffer_insert1 (struct buffer *, Lisp_Object); -Lisp_Object make_string_from_buffer (struct buffer *, int, int); -Lisp_Object make_string_from_buffer_no_extents (struct buffer *, int, int); +Lisp_Object make_string_from_buffer (struct buffer *, Bufpos, Charcount); +Lisp_Object make_string_from_buffer_no_extents (struct buffer *, Bufpos, Charcount); Lisp_Object save_excursion_save (void); Lisp_Object save_restriction_save (void); Lisp_Object save_excursion_restore (Lisp_Object); @@ -2336,7 +2345,6 @@ Lisp_Object remassoc_no_quit (Lisp_Object, Lisp_Object); Lisp_Object remassq_no_quit (Lisp_Object, Lisp_Object); Lisp_Object remrassq_no_quit (Lisp_Object, Lisp_Object); -void pure_put (Lisp_Object, Lisp_Object, Lisp_Object); int plists_differ (Lisp_Object, Lisp_Object, int, int, int); Lisp_Object internal_plist_get (Lisp_Object, Lisp_Object); void internal_plist_put (Lisp_Object *, Lisp_Object, Lisp_Object); @@ -2365,6 +2373,7 @@ Lisp_Object encode_error_behavior_flag (Error_behavior); /* Defined in indent.c */ int bi_spaces_at_point (struct buffer *, Bytind); int column_at_point (struct buffer *, Bufpos, int); +int string_column_at_point (struct Lisp_String *, Bufpos, int); int current_column (struct buffer *); void invalidate_current_column (void); Bufpos vmotion (struct window *, Bufpos, int, int *); @@ -2467,7 +2476,7 @@ void float_to_string (char *, double); void internal_object_printer (Lisp_Object, Lisp_Object, int); /* Defined in profile.c */ -void mark_profiling_info (void (*) (Lisp_Object)); +void mark_profiling_info (void); void profile_increase_call_count (Lisp_Object); extern int profiling_active; extern int profiling_redisplay_flag; @@ -2489,6 +2498,7 @@ Bufpos scan_buffer (struct buffer *, Emchar, Bufpos, Bufpos, EMACS_INT, EMACS_IN Bufpos find_next_newline (struct buffer *, Bufpos, int); Bufpos find_next_newline_no_quit (struct buffer *, Bufpos, int); Bytind bi_find_next_newline_no_quit (struct buffer *, Bytind, int); +Bytind bi_find_next_emchar_in_string (struct Lisp_String*, Emchar, Bytind, EMACS_INT); Bufpos find_before_next_newline (struct buffer *, Bufpos, Bufpos, int); struct re_pattern_buffer *compile_pattern (Lisp_Object, struct re_registers *, char *, int, Error_behavior); @@ -2530,7 +2540,7 @@ void reject_constant_symbols (Lisp_Object sym, Lisp_Object newval, Lisp_Object follow_past_lisp_magic); /* Defined in syntax.c */ -int scan_words (struct buffer *, int, int); +Bufpos scan_words (struct buffer *, Bufpos, int); /* Defined in undo.c */ Lisp_Object truncate_undo_list (Lisp_Object, int, int); @@ -2740,7 +2750,6 @@ EXFUN (Fprint, 2); EXFUN (Fprocess_status, 1); EXFUN (Fprogn, UNEVALLED); EXFUN (Fprovide, 1); -EXFUN (Fpurecopy, 1); EXFUN (Fput, 3); EXFUN (Fput_range_table, 4); EXFUN (Fput_text_property, 5); @@ -2805,14 +2814,14 @@ extern Lisp_Object Qafter, Qall, Qand; extern Lisp_Object Qarith_error, Qarrayp, Qassoc, Qat, Qautodetect, Qautoload; extern Lisp_Object Qbackground, Qbackground_pixmap, Qbad_variable, Qbefore; extern Lisp_Object Qbeginning_of_buffer, Qbig5, Qbinary, Qbitmap, Qbitp, Qblinking; -extern Lisp_Object Qboolean, Qbottom, Qbuffer, Qbuffer_file_coding_system; +extern Lisp_Object Qboolean, Qbottom, Qbuffer; extern Lisp_Object Qbuffer_glyph_p, Qbuffer_live_p, Qbuffer_read_only, Qbutton; extern Lisp_Object Qbyte_code, Qcall_interactively, Qcategory; extern Lisp_Object Qcategory_designator_p, Qcategory_table_value_p, Qccl, Qcdr; extern Lisp_Object Qchannel, Qchar, Qchar_or_string_p, Qcharacter, Qcharacterp; extern Lisp_Object Qchars, Qcharset_g0, Qcharset_g1, Qcharset_g2, Qcharset_g3; -extern Lisp_Object Qcircular_list, Qcircular_property_list; -extern Lisp_Object Qcoding_system_error, Qcoding_system_p; +extern Lisp_Object Qcenter, Qcircular_list, Qcircular_property_list; +extern Lisp_Object Qcoding_system_error; extern Lisp_Object Qcolor, Qcolor_pixmap_image_instance_p; extern Lisp_Object Qcolumns, Qcommand, Qcommandp, Qcompletion_ignore_case; extern Lisp_Object Qconsole, Qconsole_live_p, Qconst_specifier, Qcr, Qcritical; @@ -2829,14 +2838,14 @@ extern Lisp_Object Qexternal_debugging_output, Qface, Qfeaturep, Qfile_error; extern Lisp_Object Qfont, Qforce_g0_on_output, Qforce_g1_on_output; extern Lisp_Object Qforce_g2_on_output, Qforce_g3_on_output, Qforeground; extern Lisp_Object Qformat, Qframe, Qframe_live_p, Qfunction, Qgap_overhead; -extern Lisp_Object Qgeneric, Qgeometry, Qglobal, Qheight, Qhighlight, Qicon; +extern Lisp_Object Qgeneric, Qgeometry, Qglobal, Qheight, Qhighlight, Qhorizontal, Qicon; extern Lisp_Object Qicon_glyph_p, Qid, Qidentity, Qimage, Qinfo, Qinherit; extern Lisp_Object Qinhibit_quit, Qinhibit_read_only; extern Lisp_Object Qinput_charset_conversion, Qinteger; extern Lisp_Object Qinteger_char_or_marker_p, Qinteger_or_char_p; extern Lisp_Object Qinteger_or_marker_p, Qintegerp, Qinteractive, Qinternal; extern Lisp_Object Qinvalid_function, Qinvalid_read_syntax, Qio_error; -extern Lisp_Object Qiso2022, Qkey, Qkey_assoc, Qkeymap, Qlambda, Qleft, Qlf; +extern Lisp_Object Qiso2022, Qkey, Qkey_assoc, Qkeymap, Qlambda, Qlayout, Qleft, Qlf; extern Lisp_Object Qlist, Qlistp, Qload, Qlock_shift, Qmacro, Qmagic; extern Lisp_Object Qmalformed_list, Qmalformed_property_list; extern Lisp_Object Qmalloc_overhead, Qmark, Qmarkers; @@ -2846,10 +2855,10 @@ extern Lisp_Object Qmouse_leave_buffer_hook, Qmswindows, Qname, Qnas, Qnatnump; extern Lisp_Object Qno_ascii_cntl, Qno_ascii_eol, Qno_catch; extern Lisp_Object Qno_conversion, Qno_iso6429, Qnone, Qnot, Qnothing; extern Lisp_Object Qnothing_image_instance_p, Qnotice; -extern Lisp_Object Qnumber_char_or_marker_p, Qnumber_or_marker_p, Qnumberp; +extern Lisp_Object Qnumber_char_or_marker_p, Qnumberp; extern Lisp_Object Qobject, Qold_assoc, Qold_delete, Qold_delq, Qold_rassoc; extern Lisp_Object Qold_rassq, Qonly, Qor, Qother, Qoutput_charset_conversion; -extern Lisp_Object Qoverflow_error, Qpath, Qpoint, Qpointer, Qpointer_glyph_p; +extern Lisp_Object Qoverflow_error, Qpoint, Qpointer, Qpointer_glyph_p; extern Lisp_Object Qpointer_image_instance_p, Qpost_read_conversion; extern Lisp_Object Qpre_write_conversion, Qprint, Qprint_length; extern Lisp_Object Qprint_string_length, Qprocess, Qprogn, Qprovide, Qquit; @@ -2868,7 +2877,7 @@ extern Lisp_Object Qtoolbar, Qtop, Qtop_level, Qtrue_list_p, Qtty, Qtype; extern Lisp_Object Qunbound, Qundecided, Qundefined, Qunderflow_error; extern Lisp_Object Qunderline, Qunimplemented, Quser_files_and_directories; extern Lisp_Object Qvalue_assoc, Qvalues; -extern Lisp_Object Qvariable_documentation, Qvariable_domain, Qvector; +extern Lisp_Object Qvariable_documentation, Qvariable_domain, Qvertical; extern Lisp_Object Qvoid_function, Qvoid_variable, Qwarning, Qwidth, Qwidget, Qwindow; extern Lisp_Object Qwindow_live_p, Qwindow_system, Qwrong_number_of_arguments; extern Lisp_Object Qwrong_type_argument, Qx, Qy, Qyes_or_no_p; diff --git a/src/lread.c b/src/lread.c index 481f664..08c6c79 100644 --- a/src/lread.c +++ b/src/lread.c @@ -443,12 +443,6 @@ load_force_doc_string_unwind (Lisp_Object oldlist) Lisp_Object list = Vload_force_doc_string_list; Lisp_Object tail; int fd = XINT (XCAR (Vload_descriptor_list)); - /* NOTE: If purify_flag is true, we're in-place modifying objects that - may be in purespace (and if not, they will be). Therefore, we have - to be VERY careful to make sure that all objects that we create - are purecopied -- objects in purespace are not marked for GC, and - if we leave any impure objects inside of pure ones, we're really - screwed. */ GCPRO1 (list); /* restore the old value first just in case an error occurs. */ @@ -479,13 +473,12 @@ load_force_doc_string_unwind (Lisp_Object oldlist) ivan = Fread (juan); if (!CONSP (ivan)) signal_simple_error ("invalid lazy-loaded byte code", ivan); - /* Remember to purecopy; see above. */ - XCOMPILED_FUNCTION (john)->instructions = Fpurecopy (XCAR (ivan)); + XCOMPILED_FUNCTION (john)->instructions = XCAR (ivan); /* v18 or v19 bytecode file. Need to Ebolify. */ if (XCOMPILED_FUNCTION (john)->flags.ebolified && VECTORP (XCDR (ivan))) ebolify_bytecode_constants (XCDR (ivan)); - XCOMPILED_FUNCTION (john)->constants = Fpurecopy (XCDR (ivan)); + XCOMPILED_FUNCTION (john)->constants = XCDR (ivan); NUNGCPRO; } doc = compiled_function_documentation (XCOMPILED_FUNCTION (john)); @@ -925,7 +918,7 @@ locate_file_find_directory_hash_table (Lisp_Object directory) /* Map FUN over SUFFIXES, as described above. FUN will be called with a char * containing the current file name, and ARG. Mapping stops when FUN returns non-zero. */ -void +static void locate_file_map_suffixes (Lisp_Object filename, Lisp_Object suffixes, int (*fun) (char *, void *), void *arg) @@ -984,7 +977,7 @@ locate_file_map_suffixes (Lisp_Object filename, Lisp_Object suffixes, else { /* Case c) */ - CONST char *nsuffix = XSTRING_DATA (suffixes); + CONST char *nsuffix = (CONST char *) XSTRING_DATA (suffixes); while (1) { @@ -1947,7 +1940,6 @@ read_atom (Lisp_Object readcharfun, sym = Fmake_symbol ( make_string ((Bufbyte *) read_ptr, len)); else { - /* intern will purecopy pname if necessary */ Lisp_Object name = make_string ((Bufbyte *) read_ptr, len); sym = Fintern (name, Qnil); } @@ -3005,12 +2997,7 @@ read_vector (Lisp_Object readcharfun, i++, p++) { struct Lisp_Cons *otem = XCONS (tem); -#if 0 /* FSFmacs defun hack */ - if (read_pure) - tem = Fpurecopy (Fcar (tem)); - else -#endif - tem = Fcar (tem); + tem = Fcar (tem); *p = tem; tem = otem->cdr; free_cons (otem); @@ -3149,8 +3136,17 @@ structure_type_create (void) } void +reinit_vars_of_lread (void) +{ + Vread_buffer_stream = Qnil; + staticpro_nodump (&Vread_buffer_stream); +} + +void vars_of_lread (void) { + reinit_vars_of_lread (); + DEFVAR_LISP ("values", &Vvalues /* List of values of all expressions which were read, evaluated and printed. Order is reverse chronological. @@ -3268,9 +3264,6 @@ character escape syntaxes or just read them incorrectly. with values saved when the image is dumped. */ staticpro (&Vload_descriptor_list); - Vread_buffer_stream = Qnil; - staticpro (&Vread_buffer_stream); - /* Initialized in init_lread. */ staticpro (&Vload_force_doc_string_list); diff --git a/src/lrecord.h b/src/lrecord.h index 1858552..968ccc4 100644 --- a/src/lrecord.h +++ b/src/lrecord.h @@ -119,8 +119,7 @@ struct free_lcrecord_header }; /* see alloc.c for an explanation */ -Lisp_Object this_one_is_unmarkable (Lisp_Object obj, - void (*markobj) (Lisp_Object)); +Lisp_Object this_one_is_unmarkable (Lisp_Object obj); struct lrecord_implementation { @@ -134,7 +133,7 @@ struct lrecord_implementation recursion, so the object returned should preferably be the one with the deepest level of Lisp_Object pointers. This function can be NULL, meaning no GC marking is necessary. */ - Lisp_Object (*marker) (Lisp_Object, void (*mark_object) (Lisp_Object)); + Lisp_Object (*marker) (Lisp_Object); /* This can be NULL if the object is an lcrecord; the default_object_printer() in print.c will be used. */ void (*printer) (Lisp_Object, Lisp_Object printcharfun, int escapeflag); @@ -208,7 +207,7 @@ extern int gc_in_progress; structure. Following values are parameters, their presence, type and number is type-dependant. - The description ends with a "XD_END" record. + The description ends with a "XD_END" or "XD_SPECIFIER_END" record. Some example descriptions : static const struct lrecord_description cons_description[] = { @@ -219,20 +218,26 @@ extern int gc_in_progress; Which means "two lisp objects starting at the 'car' element" static const struct lrecord_description string_description[] = { - { XD_STRING_DATA, offsetof(Lisp_String, data) }, - { XD_LISP_OBJECT, offsetof(Lisp_String, plist), 1 }, + { XD_BYTECOUNT, offsetof(Lisp_String, size) }, + { XD_OPAQUE_DATA_PTR, offsetof(Lisp_String, data), XD_INDIRECT(0, 1) }, + { XD_LISP_OBJECT, offsetof(Lisp_String, plist), 1 }, { XD_END } }; - "A string data pointer at 'data', one lisp object at 'plist'" + "A pointer to string data at 'data', the size of the pointed array being the value + of the size variable plus 1, and one lisp object at 'plist'" The existing types : XD_LISP_OBJECT Lisp objects. The third element is the count. This is also the type to use for pointers to other lrecords. - XD_STRING_DATA - Pointer to string data. + XD_LO_RESET_NIL + Lisp objects which will be reset to Qnil when dumping. Useful for cleaning + up caches. + XD_LO_LINK + Link in a linked list of objects of the same type. + XD_OPAQUE_PTR Pointer to undumpable data. Must be NULL when dumping. @@ -244,6 +249,16 @@ extern int gc_in_progress; Pointer to dumpable opaque data. Parameter is the size of the data. Pointed data must be relocatable without changes. + XD_C_STRING + Pointer to a C string. + + XD_DOC_STRING + Pointer to a doc string (C string if positive, opaque value if negative) + + XD_INT_RESET + An integer which will be reset to a given value in the dump file. + + XD_SIZE_T size_t value. Used for counts. @@ -253,30 +268,40 @@ extern int gc_in_progress; XD_LONG long value. Used for counts. + XD_BYTECOUNT + bytecount value. Used for counts. + XD_END Special type indicating the end of the array. + XD_SPECIFIER_END + Special type indicating the end of the array for a specifier. Extra + description is going to be fetched from the specifier methods. - Special macros: - XD_INDIRECT(line) - Usable where a "count" or "size" is requested. Gives the value of the element - which is at line number 'line' in the description (count starts at zero). - XD_PARENT_INDIRECT(line) - Same as XD_INDIRECT but the element number refers to the parent structure. - Usable only in struct descriptions. + Special macros: + XD_INDIRECT(line, delta) + Usable where a "count" or "size" is requested. Gives the value of + the element which is at line number 'line' in the description (count + starts at zero) and adds delta to it. */ enum lrecord_description_type { XD_LISP_OBJECT, - XD_STRING_DATA, + XD_LO_RESET_NIL, + XD_LO_LINK, XD_OPAQUE_PTR, XD_STRUCT_PTR, XD_OPAQUE_DATA_PTR, + XD_C_STRING, + XD_DOC_STRING, + XD_INT_RESET, XD_SIZE_T, XD_INT, XD_LONG, - XD_END + XD_BYTECOUNT, + XD_END, + XD_SPECIFIER_END }; struct lrecord_description { @@ -291,12 +316,16 @@ struct struct_description { const struct lrecord_description *description; }; -#define XD_INDIRECT(count) (-1-(count)) -#define XD_PARENT_INDIRECT(count) (-1000-(count)) +#define XD_INDIRECT(val, delta) (-1-((val)|(delta<<8))) + +#define XD_IS_INDIRECT(code) (code<0) +#define XD_INDIRECT_VAL(code) ((-1-code) & 255) +#define XD_INDIRECT_DELTA(code) (((-1-code)>>8) & 255) #define XD_DYNARR_DESC(base_type, sub_desc) \ - { XD_STRUCT_PTR, offsetof(base_type, base), XD_INDIRECT(1), sub_desc }, \ - { XD_INT, offsetof(base_type, max) } + { XD_STRUCT_PTR, offsetof(base_type, base), XD_INDIRECT(1, 0), sub_desc }, \ + { XD_INT, offsetof(base_type, cur) }, \ + { XD_INT_RESET, offsetof(base_type, max), XD_INDIRECT(1, 0) } /* Declaring the following structures as const puts them in the text (read-only) segment, which makes debugging inconvenient @@ -345,7 +374,7 @@ CONST_IF_NOT_DEBUG struct lrecord_implementation lrecord_##c_name = \ getprop, putprop, remprop, props, size, sizer, \ &(lrecord_##c_name##_lrecord_type_index), basic_p } \ -#define LRECORDP(a) (XTYPE ((a)) == Lisp_Type_Record) +#define LRECORDP(a) (XTYPE (a) == Lisp_Type_Record) #define XRECORD_LHEADER(a) ((struct lrecord_header *) XPNTR (a)) #define RECORD_TYPEP(x, ty) \ @@ -370,8 +399,7 @@ INLINE structtype *error_check_##c_name (Lisp_Object obj); \ INLINE structtype * \ error_check_##c_name (Lisp_Object obj) \ { \ - assert (RECORD_TYPEP (obj, &lrecord_##c_name) || \ - MARKED_RECORD_P (obj)); \ + assert (RECORD_TYPEP (obj, &lrecord_##c_name)); \ return (structtype *) XPNTR (obj); \ } \ extern Lisp_Object Q##c_name##p @@ -381,7 +409,7 @@ INLINE structtype *error_check_##c_name (Lisp_Object obj); \ INLINE structtype * \ error_check_##c_name (Lisp_Object obj) \ { \ - assert (XGCTYPE (obj) == type_enum); \ + assert (XTYPE (obj) == type_enum); \ return (structtype *) XPNTR (obj); \ } \ extern Lisp_Object Q##c_name##p @@ -392,8 +420,7 @@ extern Lisp_Object Q##c_name##p # define XSETRECORD(var, p, c_name) do \ { \ XSETOBJ (var, Lisp_Type_Record, p); \ - assert (RECORD_TYPEP (var, &lrecord_##c_name) || \ - MARKED_RECORD_P (var)); \ + assert (RECORD_TYPEP (var, &lrecord_##c_name)); \ } while (0) #else /* not ERROR_CHECK_TYPECHECK */ @@ -412,7 +439,6 @@ extern Lisp_Object Q##c_name##p #endif /* not ERROR_CHECK_TYPECHECK */ #define RECORDP(x, c_name) RECORD_TYPEP (x, &lrecord_##c_name) -#define GC_RECORDP(x, c_name) gc_record_type_p (x, &lrecord_##c_name) /* Note: we now have two different kinds of type-checking macros. The "old" kind has now been renamed CONCHECK_foo. The reason for @@ -459,9 +485,6 @@ void *alloc_lcrecord (size_t size, CONST struct lrecord_implementation *); #define alloc_lcrecord_type(type, lrecord_implementation) \ ((type *) alloc_lcrecord (sizeof (type), lrecord_implementation)) -int gc_record_type_p (Lisp_Object frob, - CONST struct lrecord_implementation *type); - /* Copy the data from one lcrecord structure into another, but don't overwrite the header information. */ diff --git a/src/lstream.c b/src/lstream.c index 42eb940..d7c4f70 100644 --- a/src/lstream.c +++ b/src/lstream.c @@ -134,10 +134,10 @@ void Lstream_rewind (Lstream *stream) #define MAX_READ_SIZE 512 static Lisp_Object -mark_lstream (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_lstream (Lisp_Object obj) { Lstream *lstr = XLSTREAM (obj); - return lstr->imp->marker ? (lstr->imp->marker) (obj, markobj) : Qnil; + return lstr->imp->marker ? (lstr->imp->marker) (obj) : Qnil; } static void @@ -1214,7 +1214,7 @@ lisp_string_rewinder (Lstream *stream) } static Lisp_Object -lisp_string_marker (Lisp_Object stream, void (*markobj) (Lisp_Object)) +lisp_string_marker (Lisp_Object stream) { struct lisp_string_stream *str = LISP_STRING_STREAM_DATA (XLSTREAM (stream)); return str->obj; @@ -1612,13 +1612,13 @@ lisp_buffer_rewinder (Lstream *stream) } static Lisp_Object -lisp_buffer_marker (Lisp_Object stream, void (*markobj) (Lisp_Object)) +lisp_buffer_marker (Lisp_Object stream) { struct lisp_buffer_stream *str = LISP_BUFFER_STREAM_DATA (XLSTREAM (stream)); - markobj (str->start); - markobj (str->end); + mark_object (str->start); + mark_object (str->end); return str->buffer; } @@ -1673,13 +1673,19 @@ lstream_type_create (void) } void -vars_of_lstream (void) +reinit_vars_of_lstream (void) { int i; for (i = 0; i < countof (Vlstream_free_list); i++) { Vlstream_free_list[i] = Qnil; - staticpro (&Vlstream_free_list[i]); + staticpro_nodump (&Vlstream_free_list[i]); } } + +void +vars_of_lstream (void) +{ + reinit_vars_of_lstream (); +} diff --git a/src/lstream.h b/src/lstream.h index e67bf4d..357c820 100644 --- a/src/lstream.h +++ b/src/lstream.h @@ -129,7 +129,7 @@ typedef struct lstream_implementation int (*closer) (Lstream *stream); /* Mark this object for garbage collection. Same semantics as a standard Lisp_Object marker. This function can be NULL. */ - Lisp_Object (*marker) (Lisp_Object lstream, void (*markfun) (Lisp_Object)); + Lisp_Object (*marker) (Lisp_Object lstream); } Lstream_implementation; #define DEFINE_LSTREAM_IMPLEMENTATION(name,c_name,size) \ diff --git a/src/m/iris4d.h b/src/m/iris4d.h index 639dfe4..62b56b0 100644 --- a/src/m/iris4d.h +++ b/src/m/iris4d.h @@ -99,8 +99,7 @@ Boston, MA 02111-1307, USA. */ #ifdef USG5_4 #undef UNEXEC -/* FSF renames this file to unexsgi.o */ -#define UNEXEC "unexelfsgi.o" +#define UNEXEC "unexelf.o" #else #define UNEXEC "unexmips.o" #endif diff --git a/src/m/iris5d.h b/src/m/iris5d.h index 0b67c42..05a03c0 100644 --- a/src/m/iris5d.h +++ b/src/m/iris5d.h @@ -101,8 +101,7 @@ Boston, MA 02111-1307, USA. */ #ifdef UNEXEC #undef UNEXEC #endif -/* FSF renames this file to unexsgi.o */ -#define UNEXEC "unexelfsgi.o" +#define UNEXEC "unexelf.o" #define TEXT_START 0x400000 diff --git a/src/m/mips.h b/src/m/mips.h index 03b769e..a0751cb 100644 --- a/src/m/mips.h +++ b/src/m/mips.h @@ -63,10 +63,12 @@ NOTE-END */ #define LOAD_AVE_CVT(x) (int) (((double) (x)) * 100.0 / 256.0) +#ifndef linux /* CDC EP/IX 1.4.3 uses /unix */ #undef KERNEL_FILE #define KERNEL_FILE "/unix" +#endif /* ! linux */ /* Define CANNOT_DUMP on machines where unexec does not work. Then the function dump-emacs will not be defined @@ -106,16 +108,23 @@ NOTE-END */ /* This machine requires completely different unexec code which lives in a separate file. Specify the file name. */ +#ifndef linux #define UNEXEC "unexmips.o" - +#endif /* !linux */ /* Describe layout of the address space in an executing process. */ +#ifdef linux +#define TEXT_START 0x00400000 +#define DATA_START 0x10000000 +#define DATA_SEG_BITS 0x10000000 +#else /* !linux */ #define TEXT_START 0x400000 #define DATA_START 0x800000 +#endif /* linux */ /* Alter some of the options used when linking. */ -#ifndef NEWSOS5 +#if !defined(NEWSOS5) && !defined(linux) #ifdef BSD /* DECstations don't have this library. */ @@ -138,9 +147,9 @@ NOTE-END */ #define C_DEBUG_SWITCH "-O -g3" #endif /* not BSD */ -#endif /* not NEWSOS5 */ +#endif /* !NEWSOS5 && !linux */ -#ifndef NEWSOS5 +#if !defined(NEWSOS5) && !defined(linux) #ifdef USG /* Don't try to use SIGIO even though it is defined. */ @@ -167,4 +176,4 @@ NOTE-END */ #define TERMINFO #undef MAIL_USE_FLOCK /* Someone should check this. */ #endif /* BSD */ -#endif /* not NEWSOS5 */ +#endif /* !NEWSOS5 && !linux */ diff --git a/src/marker.c b/src/marker.c index 5ed6c4d..5f9db4a 100644 --- a/src/marker.c +++ b/src/marker.c @@ -36,7 +36,7 @@ Boston, MA 02111-1307, USA. */ #include "buffer.h" static Lisp_Object -mark_marker (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_marker (Lisp_Object obj) { struct Lisp_Marker *marker = XMARKER (obj); Lisp_Object buf; @@ -66,7 +66,7 @@ print_marker (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) write_c_string (GETTEXT ("in no buffer"), printcharfun); else { - sprintf (buf, "at %d in ", marker_position (obj)); + sprintf (buf, "at %ld in ", (long) marker_position (obj)); write_c_string (buf, printcharfun); print_internal (marker->buffer->name, printcharfun, 0); } diff --git a/src/menubar-x.c b/src/menubar-x.c index 6212281..fecb4a7 100644 --- a/src/menubar-x.c +++ b/src/menubar-x.c @@ -675,7 +675,6 @@ make_dummy_xbutton_event (XEvent *dummy, if (eev) { Position shellx, shelly, framex, framey; - Widget shell = XtParent (daddy); Arg al [2]; btn->time = eev->timestamp; btn->button = eev->event.button.button; @@ -683,9 +682,16 @@ make_dummy_xbutton_event (XEvent *dummy, btn->subwindow = (Window) NULL; btn->x = eev->event.button.x; btn->y = eev->event.button.y; - XtSetArg (al [0], XtNx, &shellx); - XtSetArg (al [1], XtNy, &shelly); - XtGetValues (shell, al, 2); + shellx = shelly = 0; +#ifndef HAVE_WMCOMMAND + { + Widget shell = XtParent (daddy); + + XtSetArg (al [0], XtNx, &shellx); + XtSetArg (al [1], XtNy, &shelly); + XtGetValues (shell, al, 2); + } +#endif XtSetArg (al [0], XtNx, &framex); XtSetArg (al [1], XtNy, &framey); XtGetValues (daddy, al, 2); @@ -855,9 +861,15 @@ console_type_create_menubar_x (void) } void -vars_of_menubar_x (void) +reinit_vars_of_menubar_x (void) { last_popup_menu_selection_callback_id = (LWLIB_ID) -1; +} + +void +vars_of_menubar_x (void) +{ + reinit_vars_of_menubar_x (); #if defined (LWLIB_MENUBARS_LUCID) Fprovide (intern ("lucid-menubars")); diff --git a/src/menubar.c b/src/menubar.c index 8eab6af..7a6e2dc 100644 --- a/src/menubar.c +++ b/src/menubar.c @@ -378,7 +378,6 @@ vars_of_menubar (void) Fcons (Fvector (3, &menu_item[0]), Qnil)), Qnil); - Vblank_menubar = Fpurecopy (Vblank_menubar); staticpro (&Vblank_menubar); } diff --git a/src/minibuf.c b/src/minibuf.c index c87858d..16174c5 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -936,9 +936,15 @@ syms_of_minibuf (void) } void -vars_of_minibuf (void) +reinit_vars_of_minibuf (void) { minibuf_level = 0; +} + +void +vars_of_minibuf (void) +{ + reinit_vars_of_minibuf (); staticpro (&Vminibuf_prompt); Vminibuf_prompt = Qnil; @@ -965,7 +971,7 @@ Each completion has to match all regexps in this list. } void -complex_vars_of_minibuf (void) +reinit_complex_vars_of_minibuf (void) { /* This function can GC */ #ifdef I18N3 @@ -974,8 +980,14 @@ complex_vars_of_minibuf (void) #endif Vminibuffer_zero = Fget_buffer_create - (Fpurecopy (build_string (DEFER_GETTEXT (" *Minibuf-0*")))); + (build_string (DEFER_GETTEXT (" *Minibuf-0*"))); Vecho_area_buffer = Fget_buffer_create - (Fpurecopy (build_string (DEFER_GETTEXT (" *Echo Area*")))); + (build_string (DEFER_GETTEXT (" *Echo Area*"))); +} + +void +complex_vars_of_minibuf (void) +{ + reinit_complex_vars_of_minibuf (); } diff --git a/src/mule-ccl.c b/src/mule-ccl.c index 356c7de..e84c7e1 100644 --- a/src/mule-ccl.c +++ b/src/mule-ccl.c @@ -760,7 +760,7 @@ ccl_driver (struct ccl_program *ccl, CONST unsigned char *source, int i, j, op; int stack_idx = ccl->stack_idx; /* Instruction counter of the current CCL code. */ - int this_ic; + int this_ic = 0; if (ic >= ccl->eof_ic) ic = CCL_HEADER_MAIN; @@ -1667,7 +1667,7 @@ setup_ccl_program (struct ccl_program *ccl, Lisp_Object vec) function converts symbols of code conversion maps and character translation tables embeded in the CCL code into their ID numbers. */ -Lisp_Object +static Lisp_Object resolve_symbol_ccl_program (Lisp_Object ccl) { int i, veclen; @@ -1734,8 +1734,8 @@ As side effect, each element of REGISTER holds the value of int i; Lisp_Object ccl_id; - if ((SYMBOLP (ccl_prog)) && - (!NILP (ccl_id = Fget (ccl_prog, Qccl_program_idx, Qnil)))) + if (SYMBOLP (ccl_prog) && + !NILP (ccl_id = Fget (ccl_prog, Qccl_program_idx, Qnil))) { ccl_prog = XVECTOR_DATA (Vccl_program_table)[XUINT (ccl_id)]; CHECK_LIST (ccl_prog); @@ -1801,8 +1801,8 @@ It returns the contents of write buffer as a string, struct gcpro gcpro1, gcpro2, gcpro3; Lisp_Object ccl_id; - if ((SYMBOLP (ccl_prog)) && - (!NILP (ccl_id = Fget (ccl_prog, Qccl_program_idx, Qnil)))) + if (SYMBOLP (ccl_prog) && + !NILP (ccl_id = Fget (ccl_prog, Qccl_program_idx, Qnil))) { ccl_prog = XVECTOR (Vccl_program_table)->contents[XUINT (ccl_id)]; CHECK_LIST (ccl_prog); diff --git a/src/mule-charset.c b/src/mule-charset.c index aae29a5..6470fe4 100644 --- a/src/mule-charset.c +++ b/src/mule-charset.c @@ -74,11 +74,17 @@ static int composite_char_col_next; #endif /* ENABLE_COMPOSITE_CHARS */ -/* Table of charsets indexed by leading byte. */ -Lisp_Object charset_by_leading_byte[NUM_LEADING_BYTES]; +struct charset_lookup *chlook; -/* Table of charsets indexed by type/final-byte/direction. */ -Lisp_Object charset_by_attributes[4][128][2]; +static const struct lrecord_description charset_lookup_description_1[] = { + { XD_LISP_OBJECT, offsetof(struct charset_lookup, charset_by_leading_byte), 128+4*128*2 }, + { XD_END } +}; + +static const struct struct_description charset_lookup_description = { + sizeof(struct charset_lookup), + charset_lookup_description_1 +}; /* Table of number of bytes in the string representation of a character indexed by the first byte of that representation. @@ -397,15 +403,15 @@ Lstream_funget_emchar (Lstream *stream, Emchar ch) /************************************************************************/ static Lisp_Object -mark_charset (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_charset (Lisp_Object obj) { struct Lisp_Charset *cs = XCHARSET (obj); - markobj (cs->short_name); - markobj (cs->long_name); - markobj (cs->doc_string); - markobj (cs->registry); - markobj (cs->ccl_program); + mark_object (cs->short_name); + mark_object (cs->long_name); + mark_object (cs->doc_string); + mark_object (cs->registry); + mark_object (cs->ccl_program); return cs->name; } @@ -490,12 +496,12 @@ make_charset (int id, Lisp_Object name, unsigned char rep_bytes, /* some charsets do not have final characters. This includes ASCII, Control-1, Composite, and the two faux private charsets. */ - assert (NILP (charset_by_attributes[type][final][direction])); - charset_by_attributes[type][final][direction] = obj; + assert (NILP (chlook->charset_by_attributes[type][final][direction])); + chlook->charset_by_attributes[type][final][direction] = obj; } - assert (NILP (charset_by_leading_byte[id - MIN_LEADING_BYTE])); - charset_by_leading_byte[id - MIN_LEADING_BYTE] = obj; + assert (NILP (chlook->charset_by_leading_byte[id - 128])); + chlook->charset_by_leading_byte[id - 128] = obj; if (id < 0xA0) /* official leading byte */ rep_bytes_by_first_byte[id] = rep_bytes; @@ -1307,15 +1313,18 @@ vars_of_mule_charset (void) { int i, j, k; + chlook = xnew (struct charset_lookup); + dumpstruct (&chlook, &charset_lookup_description); + /* Table of charsets indexed by leading byte. */ - for (i = 0; i < countof (charset_by_leading_byte); i++) - charset_by_leading_byte[i] = Qnil; + for (i = 0; i < countof (chlook->charset_by_leading_byte); i++) + chlook->charset_by_leading_byte[i] = Qnil; /* Table of charsets indexed by type/final-byte/direction. */ - for (i = 0; i < countof (charset_by_attributes); i++) - for (j = 0; j < countof (charset_by_attributes[0]); j++) - for (k = 0; k < countof (charset_by_attributes[0][0]); k++) - charset_by_attributes[i][j][k] = Qnil; + for (i = 0; i < countof (chlook->charset_by_attributes); i++) + for (j = 0; j < countof (chlook->charset_by_attributes[0]); j++) + for (k = 0; k < countof (chlook->charset_by_attributes[0][0]); k++) + chlook->charset_by_attributes[i][j][k] = Qnil; next_allocated_1_byte_leading_byte = MIN_LEADING_BYTE_PRIVATE_1; next_allocated_2_byte_leading_byte = MIN_LEADING_BYTE_PRIVATE_2; @@ -1337,6 +1346,7 @@ complex_vars_of_mule_charset (void) /* Predefined character sets. We store them into variables for ease of access. */ + staticpro (&Vcharset_ascii); Vcharset_ascii = make_charset (LEADING_BYTE_ASCII, Qascii, 1, CHARSET_TYPE_94, 1, 0, 'B', @@ -1345,6 +1355,7 @@ complex_vars_of_mule_charset (void) build_string ("ASCII)"), build_string ("ASCII (ISO646 IRV)"), build_string ("\\(iso8859-[0-9]*\\|-ascii\\)")); + staticpro (&Vcharset_control_1); Vcharset_control_1 = make_charset (LEADING_BYTE_CONTROL_1, Qcontrol_1, 2, CHARSET_TYPE_94, 1, 1, 0, @@ -1353,6 +1364,7 @@ complex_vars_of_mule_charset (void) build_string ("Control characters"), build_string ("Control characters 128-191"), build_string ("")); + staticpro (&Vcharset_latin_iso8859_1); Vcharset_latin_iso8859_1 = make_charset (LEADING_BYTE_LATIN_ISO8859_1, Qlatin_iso8859_1, 2, CHARSET_TYPE_96, 1, 1, 'A', @@ -1361,6 +1373,7 @@ complex_vars_of_mule_charset (void) build_string ("ISO8859-1 (Latin-1)"), build_string ("ISO8859-1 (Latin-1)"), build_string ("iso8859-1")); + staticpro (&Vcharset_latin_iso8859_2); Vcharset_latin_iso8859_2 = make_charset (LEADING_BYTE_LATIN_ISO8859_2, Qlatin_iso8859_2, 2, CHARSET_TYPE_96, 1, 1, 'B', @@ -1369,6 +1382,7 @@ complex_vars_of_mule_charset (void) build_string ("ISO8859-2 (Latin-2)"), build_string ("ISO8859-2 (Latin-2)"), build_string ("iso8859-2")); + staticpro (&Vcharset_latin_iso8859_3); Vcharset_latin_iso8859_3 = make_charset (LEADING_BYTE_LATIN_ISO8859_3, Qlatin_iso8859_3, 2, CHARSET_TYPE_96, 1, 1, 'C', @@ -1377,6 +1391,7 @@ complex_vars_of_mule_charset (void) build_string ("ISO8859-3 (Latin-3)"), build_string ("ISO8859-3 (Latin-3)"), build_string ("iso8859-3")); + staticpro (&Vcharset_latin_iso8859_4); Vcharset_latin_iso8859_4 = make_charset (LEADING_BYTE_LATIN_ISO8859_4, Qlatin_iso8859_4, 2, CHARSET_TYPE_96, 1, 1, 'D', @@ -1385,6 +1400,7 @@ complex_vars_of_mule_charset (void) build_string ("ISO8859-4 (Latin-4)"), build_string ("ISO8859-4 (Latin-4)"), build_string ("iso8859-4")); + staticpro (&Vcharset_thai_tis620); Vcharset_thai_tis620 = make_charset (LEADING_BYTE_THAI_TIS620, Qthai_tis620, 2, CHARSET_TYPE_96, 1, 1, 'T', @@ -1393,6 +1409,7 @@ complex_vars_of_mule_charset (void) build_string ("TIS620 (Thai)"), build_string ("TIS620.2529 (Thai)"), build_string ("tis620")); + staticpro (&Vcharset_greek_iso8859_7); Vcharset_greek_iso8859_7 = make_charset (LEADING_BYTE_GREEK_ISO8859_7, Qgreek_iso8859_7, 2, CHARSET_TYPE_96, 1, 1, 'F', @@ -1401,6 +1418,7 @@ complex_vars_of_mule_charset (void) build_string ("ISO8859-7 (Greek)"), build_string ("ISO8859-7 (Greek)"), build_string ("iso8859-7")); + staticpro (&Vcharset_arabic_iso8859_6); Vcharset_arabic_iso8859_6 = make_charset (LEADING_BYTE_ARABIC_ISO8859_6, Qarabic_iso8859_6, 2, CHARSET_TYPE_96, 1, 1, 'G', @@ -1409,6 +1427,7 @@ complex_vars_of_mule_charset (void) build_string ("ISO8859-6 (Arabic)"), build_string ("ISO8859-6 (Arabic)"), build_string ("iso8859-6")); + staticpro (&Vcharset_hebrew_iso8859_8); Vcharset_hebrew_iso8859_8 = make_charset (LEADING_BYTE_HEBREW_ISO8859_8, Qhebrew_iso8859_8, 2, CHARSET_TYPE_96, 1, 1, 'H', @@ -1417,6 +1436,7 @@ complex_vars_of_mule_charset (void) build_string ("ISO8859-8 (Hebrew)"), build_string ("ISO8859-8 (Hebrew)"), build_string ("iso8859-8")); + staticpro (&Vcharset_katakana_jisx0201); Vcharset_katakana_jisx0201 = make_charset (LEADING_BYTE_KATAKANA_JISX0201, Qkatakana_jisx0201, 2, CHARSET_TYPE_94, 1, 1, 'I', @@ -1425,6 +1445,7 @@ complex_vars_of_mule_charset (void) build_string ("JISX0201.1976 (Japanese Kana)"), build_string ("JISX0201.1976 Japanese Kana"), build_string ("jisx0201.1976")); + staticpro (&Vcharset_latin_jisx0201); Vcharset_latin_jisx0201 = make_charset (LEADING_BYTE_LATIN_JISX0201, Qlatin_jisx0201, 2, CHARSET_TYPE_94, 1, 0, 'J', @@ -1433,6 +1454,7 @@ complex_vars_of_mule_charset (void) build_string ("JISX0201.1976 (Japanese Roman)"), build_string ("JISX0201.1976 Japanese Roman"), build_string ("jisx0201.1976")); + staticpro (&Vcharset_cyrillic_iso8859_5); Vcharset_cyrillic_iso8859_5 = make_charset (LEADING_BYTE_CYRILLIC_ISO8859_5, Qcyrillic_iso8859_5, 2, CHARSET_TYPE_96, 1, 1, 'L', @@ -1441,6 +1463,7 @@ complex_vars_of_mule_charset (void) build_string ("ISO8859-5 (Cyrillic)"), build_string ("ISO8859-5 (Cyrillic)"), build_string ("iso8859-5")); + staticpro (&Vcharset_latin_iso8859_9); Vcharset_latin_iso8859_9 = make_charset (LEADING_BYTE_LATIN_ISO8859_9, Qlatin_iso8859_9, 2, CHARSET_TYPE_96, 1, 1, 'M', @@ -1449,6 +1472,7 @@ complex_vars_of_mule_charset (void) build_string ("ISO8859-9 (Latin-5)"), build_string ("ISO8859-9 (Latin-5)"), build_string ("iso8859-9")); + staticpro (&Vcharset_japanese_jisx0208_1978); Vcharset_japanese_jisx0208_1978 = make_charset (LEADING_BYTE_JAPANESE_JISX0208_1978, Qjapanese_jisx0208_1978, 3, CHARSET_TYPE_94X94, 2, 0, '@', @@ -1458,6 +1482,7 @@ complex_vars_of_mule_charset (void) build_string ("JISX0208.1978 Japanese Kanji (so called \"old JIS\")"), build_string ("\\(jisx0208\\|jisc6226\\)\\.1978")); + staticpro (&Vcharset_chinese_gb2312); Vcharset_chinese_gb2312 = make_charset (LEADING_BYTE_CHINESE_GB2312, Qchinese_gb2312, 3, CHARSET_TYPE_94X94, 2, 0, 'A', @@ -1466,6 +1491,7 @@ complex_vars_of_mule_charset (void) build_string ("GB2312)"), build_string ("GB2312 Chinese simplified"), build_string ("gb2312")); + staticpro (&Vcharset_japanese_jisx0208); Vcharset_japanese_jisx0208 = make_charset (LEADING_BYTE_JAPANESE_JISX0208, Qjapanese_jisx0208, 3, CHARSET_TYPE_94X94, 2, 0, 'B', @@ -1474,6 +1500,7 @@ complex_vars_of_mule_charset (void) build_string ("JISX0208.1983/1990 (Japanese)"), build_string ("JISX0208.1983/1990 Japanese Kanji"), build_string ("jisx0208.19\\(83\\|90\\)")); + staticpro (&Vcharset_korean_ksc5601); Vcharset_korean_ksc5601 = make_charset (LEADING_BYTE_KOREAN_KSC5601, Qkorean_ksc5601, 3, CHARSET_TYPE_94X94, 2, 0, 'C', @@ -1482,6 +1509,7 @@ complex_vars_of_mule_charset (void) build_string ("KSC5601 (Korean"), build_string ("KSC5601 Korean Hangul and Hanja"), build_string ("ksc5601")); + staticpro (&Vcharset_japanese_jisx0212); Vcharset_japanese_jisx0212 = make_charset (LEADING_BYTE_JAPANESE_JISX0212, Qjapanese_jisx0212, 3, CHARSET_TYPE_94X94, 2, 0, 'D', @@ -1492,6 +1520,7 @@ complex_vars_of_mule_charset (void) build_string ("jisx0212")); #define CHINESE_CNS_PLANE_RE(n) "cns11643[.-]\\(.*[.-]\\)?" n "$" + staticpro (&Vcharset_chinese_cns11643_1); Vcharset_chinese_cns11643_1 = make_charset (LEADING_BYTE_CHINESE_CNS11643_1, Qchinese_cns11643_1, 3, CHARSET_TYPE_94X94, 2, 0, 'G', @@ -1501,6 +1530,7 @@ complex_vars_of_mule_charset (void) build_string ("CNS 11643 Plane 1 Chinese traditional"), build_string (CHINESE_CNS_PLANE_RE("1"))); + staticpro (&Vcharset_chinese_cns11643_2); Vcharset_chinese_cns11643_2 = make_charset (LEADING_BYTE_CHINESE_CNS11643_2, Qchinese_cns11643_2, 3, CHARSET_TYPE_94X94, 2, 0, 'H', @@ -1510,6 +1540,7 @@ complex_vars_of_mule_charset (void) build_string ("CNS 11643 Plane 2 Chinese traditional"), build_string (CHINESE_CNS_PLANE_RE("2"))); + staticpro (&Vcharset_chinese_big5_1); Vcharset_chinese_big5_1 = make_charset (LEADING_BYTE_CHINESE_BIG5_1, Qchinese_big5_1, 3, CHARSET_TYPE_94X94, 2, 0, '0', @@ -1519,6 +1550,7 @@ complex_vars_of_mule_charset (void) build_string ("Big5 Level-1 Chinese traditional"), build_string ("big5")); + staticpro (&Vcharset_chinese_big5_2); Vcharset_chinese_big5_2 = make_charset (LEADING_BYTE_CHINESE_BIG5_2, Qchinese_big5_2, 3, CHARSET_TYPE_94X94, 2, 0, '1', @@ -1534,6 +1566,7 @@ complex_vars_of_mule_charset (void) /* #### For simplicity, we put composite chars into a 96x96 charset. This is going to lead to problems because you can run out of room, esp. as we don't yet recycle numbers. */ + staticpro (&Vcharset_composite); Vcharset_composite = make_charset (LEADING_BYTE_COMPOSITE, Qcomposite, 3, CHARSET_TYPE_96X96, 2, 0, 0, @@ -1543,6 +1576,7 @@ complex_vars_of_mule_charset (void) build_string ("Composite characters"), build_string ("")); + /* #### not dumped properly */ composite_char_row_next = 32; composite_char_col_next = 32; diff --git a/src/mule-charset.h b/src/mule-charset.h index d149930..bcae03f 100644 --- a/src/mule-charset.h +++ b/src/mule-charset.h @@ -486,7 +486,6 @@ DECLARE_LRECORD (charset, struct Lisp_Charset); #define XCHARSET(x) XRECORD (x, charset, struct Lisp_Charset) #define XSETCHARSET(x, p) XSETRECORD (x, p, charset) #define CHARSETP(x) RECORDP (x, charset) -#define GC_CHARSETP(x) GC_RECORDP (x, charset) #define CHECK_CHARSET(x) CHECK_RECORD (x, charset) #define CONCHECK_CHARSET(x) CONCHECK_RECORD (x, charset) @@ -500,7 +499,7 @@ DECLARE_LRECORD (charset, struct Lisp_Charset); /* Leading byte and id have been regrouped. -- OG */ #define CHARSET_ID(cs) ((cs)->id) -#define CHARSET_LEADING_BYTE(cs) ((Bufbyte)(CHARSET_ID(cs))) +#define CHARSET_LEADING_BYTE(cs) ((Bufbyte) CHARSET_ID(cs)) #define CHARSET_NAME(cs) ((cs)->name) #define CHARSET_SHORT_NAME(cs) ((cs)->short_name) #define CHARSET_LONG_NAME(cs) ((cs)->long_name) @@ -540,11 +539,15 @@ DECLARE_LRECORD (charset, struct Lisp_Charset); #define XCHARSET_REVERSE_DIRECTION_CHARSET(cs) \ CHARSET_REVERSE_DIRECTION_CHARSET (XCHARSET (cs)) -/* Table of charsets indexed by (leading byte - 128). */ -extern Lisp_Object charset_by_leading_byte[NUM_LEADING_BYTES]; +struct charset_lookup { + /* Table of charsets indexed by leading byte. */ + Lisp_Object charset_by_leading_byte[128]; + + /* Table of charsets indexed by type/final-byte/direction. */ + Lisp_Object charset_by_attributes[4][128][2]; +}; -/* Table of charsets indexed by type/final-byte/direction. */ -extern Lisp_Object charset_by_attributes[4][128][2]; +extern struct charset_lookup *chlook; /* Table of number of bytes in the string representation of a character indexed by the first byte of that representation. @@ -567,18 +570,18 @@ CHARSET_BY_LEADING_BYTE (int lb) { assert (lb >= MIN_LEADING_BYTE && lb < (MIN_LEADING_BYTE + NUM_LEADING_BYTES)); - return charset_by_leading_byte[lb - MIN_LEADING_BYTE]; + return chlook->charset_by_leading_byte[lb - MIN_LEADING_BYTE]; } #else #define CHARSET_BY_LEADING_BYTE(lb) \ - (charset_by_leading_byte[(lb) - MIN_LEADING_BYTE]) + (chlook->charset_by_leading_byte[(lb) - MIN_LEADING_BYTE]) #endif #define CHARSET_BY_ATTRIBUTES(type, final, dir) \ - (charset_by_attributes[type][final][dir]) + (chlook->charset_by_attributes[type][final][dir]) #ifdef ERROR_CHECK_TYPECHECK diff --git a/src/mule-wnnfns.c b/src/mule-wnnfns.c index 1569365..6c475f3 100644 --- a/src/mule-wnnfns.c +++ b/src/mule-wnnfns.c @@ -1875,10 +1875,23 @@ syms_of_mule_wnn (void) } void -vars_of_mule_wnn (void) +reinit_vars_of_mule_wnn (void) { int i; + for (i = 0; i < NSERVER; i++) + { + wnnfns_buf[i] = (struct wnn_buf *) 0; + wnnfns_env_norm[i] = (struct wnn_env *) 0; + wnnfns_env_rev[i] = (struct wnn_env *) 0; + } +} + +void +vars_of_mule_wnn (void) +{ + reinit_vars_of_mule_wnn (); + DEFVAR_INT ("lb-sisheng", &lb_sisheng /* Leading character for Sisheng. */ ); @@ -1901,13 +1914,6 @@ Leading character for Sisheng. Vwnn_uniq_level = Qwnn_uniq; - for (i = 0; i < NSERVER; i++) - { - wnnfns_buf[i] = (struct wnn_buf *) 0; - wnnfns_env_norm[i] = (struct wnn_env *) 0; - wnnfns_env_rev[i] = (struct wnn_env *) 0; - } - Fprovide(intern("wnn")); } diff --git a/src/ntheap.h b/src/ntheap.h index 6bde266..1d193a3 100644 --- a/src/ntheap.h +++ b/src/ntheap.h @@ -87,7 +87,7 @@ extern unsigned char *round_to_next (unsigned char *address, /* Useful routines for manipulating memory-mapped files. */ typedef struct file_data { - char *name; + CONST char *name; unsigned long size; HANDLE file; HANDLE file_mapping; diff --git a/src/ntproc.c b/src/ntproc.c index 5618847..45a7db3 100644 --- a/src/ntproc.c +++ b/src/ntproc.c @@ -1456,8 +1456,8 @@ syms_of_ntproc () void vars_of_ntproc (void) { - Qhigh = intern ("high"); - Qlow = intern ("low"); + defsymbol (&Qhigh, "high"); + defsymbol (&Qlow, "low"); DEFVAR_LISP ("win32-quote-process-args", &Vwin32_quote_process_args /* Non-nil enables quoting of process arguments to ensure correct parsing. diff --git a/src/objects-msw.c b/src/objects-msw.c index 15abb2c..1b90aca 100644 --- a/src/objects-msw.c +++ b/src/objects-msw.c @@ -1066,8 +1066,7 @@ mswindows_initialize_color_instance (struct Lisp_Color_Instance *c, Lisp_Object #if 0 static void -mswindows_mark_color_instance (struct Lisp_Color_Instance *c, - void (*markobj) (Lisp_Object)) +mswindows_mark_color_instance (struct Lisp_Color_Instance *c) { } #endif @@ -1105,7 +1104,7 @@ mswindows_color_instance_equal (struct Lisp_Color_Instance *c1, static unsigned long mswindows_color_instance_hash (struct Lisp_Color_Instance *c, int depth) { - return (unsigned long)(COLOR_INSTANCE_MSWINDOWS_COLOR(c)); + return (unsigned long) COLOR_INSTANCE_MSWINDOWS_COLOR(c); } static Lisp_Object @@ -1406,8 +1405,7 @@ mswindows_initialize_font_instance (struct Lisp_Font_Instance *f, Lisp_Object na #if 0 static void -mswindows_mark_font_instance (struct Lisp_Font_Instance *f, - void (*markobj) (Lisp_Object)) +mswindows_mark_font_instance (struct Lisp_Font_Instance *f) { } #endif diff --git a/src/objects-tty.c b/src/objects-tty.c index 7e02318..0b38de4 100644 --- a/src/objects-tty.c +++ b/src/objects-tty.c @@ -168,10 +168,9 @@ tty_initialize_color_instance (struct Lisp_Color_Instance *c, Lisp_Object name, } static void -tty_mark_color_instance (struct Lisp_Color_Instance *c, - void (*markobj) (Lisp_Object)) +tty_mark_color_instance (struct Lisp_Color_Instance *c) { - markobj (COLOR_INSTANCE_TTY_SYMBOL (c)); + mark_object (COLOR_INSTANCE_TTY_SYMBOL (c)); } static void @@ -256,10 +255,9 @@ tty_initialize_font_instance (struct Lisp_Font_Instance *f, Lisp_Object name, } static void -tty_mark_font_instance (struct Lisp_Font_Instance *f, - void (*markobj) (Lisp_Object)) +tty_mark_font_instance (struct Lisp_Font_Instance *f) { - markobj (FONT_INSTANCE_TTY_CHARSET (f)); + mark_object (FONT_INSTANCE_TTY_CHARSET (f)); } static void diff --git a/src/objects-x.c b/src/objects-x.c index 29d51cf..536228c 100644 --- a/src/objects-x.c +++ b/src/objects-x.c @@ -28,6 +28,7 @@ Boston, MA 02111-1307, USA. */ #include #include "lisp.h" +#include #include "console-x.h" #include "objects-x.h" @@ -45,11 +46,13 @@ int x_handle_non_fully_specified_fonts; /* Replacement for XAllocColor() that tries to return the nearest available color if the colormap is full. Original was from FSFmacs, - but rewritten by Jareth Hein 97/11/25 */ + but rewritten by Jareth Hein 97/11/25 + Modified by Lee Kindness 31/08/99 to handle previous + total failure which was due to a read/write colorcell being the nearest + match - tries the next nearest... -/* Return value is 1 for normal success, 2 for nearest color success, - 3 for Non-deallocable sucess, and 0 for absolute failure (shouldn't - happen?) */ + Return value is 1 for normal success, 2 for nearest color success, + 3 for Non-deallocable sucess. */ int allocate_nearest_color (Display *display, Colormap colormap, Visual *visual, XColor *color_def) @@ -140,30 +143,35 @@ allocate_nearest_color (Display *display, Colormap colormap, Visual *visual, } else { + XColor *cells = NULL; + /* JH: I can't believe there's no way to go backwards from a + colormap ID and get its visual and number of entries, but X + apparently isn't built that way... */ + int no_cells = visual->map_entries; + status = 0; + if (XAllocColor (display, colormap, color_def) != 0) status = 1; - else + else while( status != 2 ) { /* If we got to this point, the colormap is full, so we're going to try and get the next closest color. The algorithm used is a least-squares matching, which is what X uses for closest color matching with StaticColor visuals. */ - XColor *cells; - /* JH: I can't believe there's no way to go backwards from a - colormap ID and get its visual and number of entries, but X - apparently isn't built that way... */ - int no_cells = visual->map_entries; int nearest; long nearest_delta, trial_delta; int x; - cells = alloca_array (XColor, no_cells); + if( cells == NULL ) + { + cells = alloca_array (XColor, no_cells); + for (x = 0; x < no_cells; x++) + cells[x].pixel = x; - for (x = 0; x < no_cells; x++) - cells[x].pixel = x; + /* read the current colormap */ + XQueryColors (display, colormap, cells, no_cells); + } - /* read the current colormap */ - XQueryColors (display, colormap, cells, no_cells); nearest = 0; /* I'm assuming CSE so I'm not going to condense this. */ nearest_delta = ((((color_def->red >> 8) - (cells[0].red >> 8)) @@ -184,7 +192,10 @@ allocate_nearest_color (Display *display, Colormap colormap, Visual *visual, + (((color_def->blue >> 8) - (cells[x].blue >> 8)) * ((color_def->blue >> 8) - (cells[x].blue >> 8)))); - if (trial_delta < nearest_delta) + + /* less? Ignore cells marked as previously failing */ + if( (trial_delta < nearest_delta) && + (cells[x].pixel != ULONG_MAX) ) { nearest = x; nearest_delta = trial_delta; @@ -193,12 +204,15 @@ allocate_nearest_color (Display *display, Colormap colormap, Visual *visual, color_def->red = cells[nearest].red; color_def->green = cells[nearest].green; color_def->blue = cells[nearest].blue; - if (XAllocColor (display, colormap, color_def) != 0) { - status = 2; - } else { - status = 0; /* JH: how does this happen??? DOES this happen??? */ - fprintf(stderr,"allocate_nearest_color returned 0!!!\n"); - } + if (XAllocColor (display, colormap, color_def) != 0) + status = 2; + else + /* LSK: Either the colour map has changed since + * we read it, or the colour is allocated + * read/write... Mark this cmap entry so it's + * ignored in the next iteration. + */ + cells[nearest].pixel = ULONG_MAX; } } return status; @@ -208,15 +222,11 @@ int x_parse_nearest_color (struct device *d, XColor *color, Bufbyte *name, Bytecount len, Error_behavior errb) { - Display *dpy; - Colormap cmap; - Visual *visual; + Display *dpy = DEVICE_X_DISPLAY (d); + Colormap cmap = DEVICE_X_COLORMAP (d); + Visual *visual = DEVICE_X_VISUAL (d); int result; - dpy = DEVICE_X_DISPLAY (d); - cmap = DEVICE_X_COLORMAP(d); - visual = DEVICE_X_VISUAL (d); - xzero (*color); { CONST Extbyte *extname; @@ -447,10 +457,9 @@ x_initialize_font_instance (struct Lisp_Font_Instance *f, Lisp_Object name, } static void -x_mark_font_instance (struct Lisp_Font_Instance *f, - void (*markobj) (Lisp_Object)) +x_mark_font_instance (struct Lisp_Font_Instance *f) { - markobj (FONT_INSTANCE_X_TRUENAME (f)); + mark_object (FONT_INSTANCE_X_TRUENAME (f)); } static void diff --git a/src/objects.c b/src/objects.c index 69fcab6..9e9e8b1 100644 --- a/src/objects.c +++ b/src/objects.c @@ -57,12 +57,12 @@ finalose (void *ptr) Lisp_Object Qcolor_instancep; static Lisp_Object -mark_color_instance (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_color_instance (Lisp_Object obj) { struct Lisp_Color_Instance *c = XCOLOR_INSTANCE (obj); - markobj (c->name); + mark_object (c->name); if (!NILP (c->device)) /* Vthe_null_color_instance */ - MAYBE_DEVMETH (XDEVICE (c->device), mark_color_instance, (c, markobj)); + MAYBE_DEVMETH (XDEVICE (c->device), mark_color_instance, (c)); return c->device; } @@ -106,7 +106,7 @@ color_instance_equal (Lisp_Object obj1, Lisp_Object obj2, int depth) struct Lisp_Color_Instance *c2 = XCOLOR_INSTANCE (obj2); return (c1 == c2) || - ((EQ (c1->device, c2->device)) && + (EQ (c1->device, c2->device) && DEVICEP (c1->device) && HAS_DEVMETH_P (XDEVICE (c1->device), color_instance_equal) && DEVMETH (XDEVICE (c1->device), color_instance_equal, (c1, c2, depth))); @@ -237,13 +237,13 @@ static Lisp_Object font_instance_truename_internal (Lisp_Object xfont, Error_behavior errb); static Lisp_Object -mark_font_instance (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_font_instance (Lisp_Object obj) { struct Lisp_Font_Instance *f = XFONT_INSTANCE (obj); - markobj (f->name); + mark_object (f->name); if (!NILP (f->device)) /* Vthe_null_font_instance */ - MAYBE_DEVMETH (XDEVICE (f->device), mark_font_instance, (f, markobj)); + MAYBE_DEVMETH (XDEVICE (f->device), mark_font_instance, (f)); return f->device; } @@ -489,12 +489,12 @@ color_create (Lisp_Object obj) } static void -color_mark (Lisp_Object obj, void (*markobj) (Lisp_Object)) +color_mark (Lisp_Object obj) { struct Lisp_Specifier *color = XCOLOR_SPECIFIER (obj); - markobj (COLOR_SPECIFIER_FACE (color)); - markobj (COLOR_SPECIFIER_FACE_PROPERTY (color)); + mark_object (COLOR_SPECIFIER_FACE (color)); + mark_object (COLOR_SPECIFIER_FACE_PROPERTY (color)); } /* No equal or hash methods; ignore the face the color is based off @@ -667,12 +667,12 @@ font_create (Lisp_Object obj) } static void -font_mark (Lisp_Object obj, void (*markobj) (Lisp_Object)) +font_mark (Lisp_Object obj) { struct Lisp_Specifier *font = XFONT_SPECIFIER (obj); - markobj (FONT_SPECIFIER_FACE (font)); - markobj (FONT_SPECIFIER_FACE_PROPERTY (font)); + mark_object (FONT_SPECIFIER_FACE (font)); + mark_object (FONT_SPECIFIER_FACE_PROPERTY (font)); } /* No equal or hash methods; ignore the face the font is based off @@ -874,12 +874,12 @@ face_boolean_create (Lisp_Object obj) } static void -face_boolean_mark (Lisp_Object obj, void (*markobj) (Lisp_Object)) +face_boolean_mark (Lisp_Object obj) { struct Lisp_Specifier *face_boolean = XFACE_BOOLEAN_SPECIFIER (obj); - markobj (FACE_BOOLEAN_SPECIFIER_FACE (face_boolean)); - markobj (FACE_BOOLEAN_SPECIFIER_FACE_PROPERTY (face_boolean)); + mark_object (FACE_BOOLEAN_SPECIFIER_FACE (face_boolean)); + mark_object (FACE_BOOLEAN_SPECIFIER_FACE_PROPERTY (face_boolean)); } /* No equal or hash methods; ignore the face the face-boolean is based off @@ -1036,6 +1036,21 @@ syms_of_objects (void) defsymbol (&Qface_boolean, "face-boolean"); } +static const struct lrecord_description color_specifier_description[] = { + { XD_LISP_OBJECT, specifier_data_offset + offsetof(struct color_specifier, face), 2 }, + { XD_END } +}; + +static const struct lrecord_description font_specifier_description[] = { + { XD_LISP_OBJECT, specifier_data_offset + offsetof(struct font_specifier, face), 2 }, + { XD_END } +}; + +static const struct lrecord_description face_boolean_specifier_description[] = { + { XD_LISP_OBJECT, specifier_data_offset + offsetof(struct face_boolean_specifier, face), 2 }, + { XD_END } +}; + void specifier_type_create_objects (void) { @@ -1070,9 +1085,17 @@ specifier_type_create_objects (void) } void -vars_of_objects (void) +reinit_specifier_type_create_objects (void) { - staticpro (&Vthe_null_color_instance); + REINITIALIZE_SPECIFIER_TYPE (color); + REINITIALIZE_SPECIFIER_TYPE (font); + REINITIALIZE_SPECIFIER_TYPE (face_boolean); +} + +void +reinit_vars_of_objects (void) +{ + staticpro_nodump (&Vthe_null_color_instance); { struct Lisp_Color_Instance *c = alloc_lcrecord_type (struct Lisp_Color_Instance, &lrecord_color_instance); @@ -1083,7 +1106,7 @@ vars_of_objects (void) XSETCOLOR_INSTANCE (Vthe_null_color_instance, c); } - staticpro (&Vthe_null_font_instance); + staticpro_nodump (&Vthe_null_font_instance); { struct Lisp_Font_Instance *f = alloc_lcrecord_type (struct Lisp_Font_Instance, &lrecord_font_instance); @@ -1099,3 +1122,9 @@ vars_of_objects (void) XSETFONT_INSTANCE (Vthe_null_font_instance, f); } } + +void +vars_of_objects (void) +{ + reinit_vars_of_objects (); +} diff --git a/src/objects.h b/src/objects.h index c5d3492..fdce3e8 100644 --- a/src/objects.h +++ b/src/objects.h @@ -38,7 +38,7 @@ struct color_specifier Lisp_Object face_property; /* property of that face */ }; -#define COLOR_SPECIFIER_DATA(g) (SPECIFIER_TYPE_DATA (g, color)) +#define COLOR_SPECIFIER_DATA(g) SPECIFIER_TYPE_DATA (g, color) #define COLOR_SPECIFIER_FACE(g) (COLOR_SPECIFIER_DATA (g)->face) #define COLOR_SPECIFIER_FACE_PROPERTY(g) \ (COLOR_SPECIFIER_DATA (g)->face_property) @@ -63,7 +63,7 @@ struct font_specifier Lisp_Object face_property; /* property of that face */ }; -#define FONT_SPECIFIER_DATA(g) (SPECIFIER_TYPE_DATA (g, font)) +#define FONT_SPECIFIER_DATA(g) SPECIFIER_TYPE_DATA (g, font) #define FONT_SPECIFIER_FACE(g) (FONT_SPECIFIER_DATA (g)->face) #define FONT_SPECIFIER_FACE_PROPERTY(g) \ (FONT_SPECIFIER_DATA (g)->face_property) @@ -88,7 +88,7 @@ struct face_boolean_specifier Lisp_Object face_property; /* property of that face */ }; -#define FACE_BOOLEAN_SPECIFIER_DATA(g) (SPECIFIER_TYPE_DATA (g, face_boolean)) +#define FACE_BOOLEAN_SPECIFIER_DATA(g) SPECIFIER_TYPE_DATA (g, face_boolean) #define FACE_BOOLEAN_SPECIFIER_FACE(g) (FACE_BOOLEAN_SPECIFIER_DATA (g)->face) #define FACE_BOOLEAN_SPECIFIER_FACE_PROPERTY(g) \ (FACE_BOOLEAN_SPECIFIER_DATA (g)->face_property) @@ -116,7 +116,6 @@ DECLARE_LRECORD (color_instance, struct Lisp_Color_Instance); XRECORD (x, color_instance, struct Lisp_Color_Instance) #define XSETCOLOR_INSTANCE(x, p) XSETRECORD (x, p, color_instance) #define COLOR_INSTANCEP(x) RECORDP (x, color_instance) -#define GC_COLOR_INSTANCEP(x) GC_RECORDP (x, color_instance) #define CHECK_COLOR_INSTANCE(x) CHECK_RECORD (x, color_instance) #define CONCHECK_COLOR_INSTANCE(x) CONCHECK_RECORD (x, color_instance) @@ -145,7 +144,6 @@ DECLARE_LRECORD (font_instance, struct Lisp_Font_Instance); #define XFONT_INSTANCE(x) XRECORD (x, font_instance, struct Lisp_Font_Instance) #define XSETFONT_INSTANCE(x, p) XSETRECORD (x, p, font_instance) #define FONT_INSTANCEP(x) RECORDP (x, font_instance) -#define GC_FONT_INSTANCEP(x) GC_RECORDP (x, font_instance) #define CHECK_FONT_INSTANCE(x) CHECK_RECORD (x, font_instance) #define CONCHECK_FONT_INSTANCE(x) CONCHECK_RECORD (x, font_instance) diff --git a/src/opaque.c b/src/opaque.c index 70d29b9..b36abf1 100644 --- a/src/opaque.c +++ b/src/opaque.c @@ -32,67 +32,23 @@ Boston, MA 02111-1307, USA. */ OPAQUE OBJECTS SHOULD NEVER ESCAPE TO THE LISP LEVEL. Some code depends on this. As such, opaque objects are a generalization of the Qunbound marker. - - "Opaque lists" are used to keep track of lots of opaque objects - of a particular size so that they can be efficiently "freed" and - re-used again without actually entering the Lisp allocation system - (and consequently doing a malloc()). */ #include #include "lisp.h" #include "opaque.h" -Lisp_Object Qopaquep; - -static int in_opaque_list_marking; - -/* Holds freed opaque objects created with make_opaque_ptr(). - We do this quite often so it's a noticeable win if we don't - create GC junk. */ Lisp_Object Vopaque_ptr_free_list; -static Lisp_Object -mark_opaque (Lisp_Object obj, void (*markobj) (Lisp_Object)) -{ - Lisp_Opaque *p = XOPAQUE (obj); - /* Egcs 1.1.1 sometimes crashes on INTP (p->size_or_chain) */ - Lisp_Object size_or_chain = p->size_or_chain; -#ifdef ERROR_CHECK_GC - if (!in_opaque_list_marking) - /* size is non-int for objects on an opaque free list. We sure - as hell better not be marking any of these objects unless - we're marking an opaque list. */ - assert (GC_INTP (size_or_chain)); - else - /* marking an opaque on the free list doesn't do any recursive - markings, so we better not have non-freed opaques on a free - list. */ - assert (!GC_INTP (size_or_chain)); -#endif - if (GC_INTP (size_or_chain) && OPAQUE_MARKFUN (p)) - return OPAQUE_MARKFUN (p) (obj, markobj); - else - return size_or_chain; -} - /* Should never, ever be called. (except by an external debugger) */ static void print_opaque (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) { CONST Lisp_Opaque *p = XOPAQUE (obj); - /* Egcs 1.1.1 sometimes crashes on INTP (p->size_or_chain) */ - Lisp_Object size_or_chain = p->size_or_chain; char buf[200]; - char size_buf[50]; - - if (INTP (size_or_chain)) - sprintf (size_buf, "size=%lu", (unsigned long) OPAQUE_SIZE (p)); - else - sprintf (size_buf, "freed"); - sprintf (buf, "#", - size_buf, (unsigned long) p); + sprintf (buf, "#", + (long)(p->size), (unsigned long) p); write_c_string (buf, printcharfun); } @@ -100,10 +56,7 @@ static size_t sizeof_opaque (CONST void *header) { CONST Lisp_Opaque *p = (CONST Lisp_Opaque *) header; - /* Egcs 1.1.1 sometimes crashes on INTP (p->size_or_chain) */ - Lisp_Object size_or_chain = p->size_or_chain; - return offsetof (Lisp_Opaque, data) - + (GC_INTP (size_or_chain) ? XINT (size_or_chain) : 0); + return offsetof (Lisp_Opaque, data) + p->size; } /* Return an opaque object of size SIZE. @@ -115,8 +68,7 @@ make_opaque (size_t size, CONST void *data) { Lisp_Opaque *p = (Lisp_Opaque *) alloc_lcrecord (offsetof (Lisp_Opaque, data) + size, &lrecord_opaque); - p->markfun = 0; - p->size_or_chain = make_int (size); + p->size = size; if (data == OPAQUE_CLEAR) memset (p->data, '\0', size); @@ -137,21 +89,9 @@ make_opaque (size_t size, CONST void *data) static int equal_opaque (Lisp_Object obj1, Lisp_Object obj2, int depth) { -#ifdef DEBUG_XEMACS - { - /* Egcs 1.1.1 sometimes crashes on INTP (p->size_or_chain) */ - Lisp_Object size_or_chain_1 = XOPAQUE (obj1)->size_or_chain; - Lisp_Object size_or_chain_2 = XOPAQUE (obj2)->size_or_chain; - assert (INTP (size_or_chain_1)); - assert (INTP (size_or_chain_2)); - assert (!XOPAQUE_MARKFUN (obj1) && !XOPAQUE_MARKFUN (obj2)); - } -#endif - { - size_t size; - return ((size = XOPAQUE_SIZE (obj1)) == XOPAQUE_SIZE (obj2) && - !memcmp (XOPAQUE_DATA (obj1), XOPAQUE_DATA (obj2), size)); - } + size_t size; + return ((size = XOPAQUE_SIZE (obj1)) == XOPAQUE_SIZE (obj2) && + !memcmp (XOPAQUE_DATA (obj1), XOPAQUE_DATA (obj2), size)); } /* This will not work correctly for opaques with subobjects! */ @@ -159,102 +99,59 @@ equal_opaque (Lisp_Object obj1, Lisp_Object obj2, int depth) static unsigned long hash_opaque (Lisp_Object obj, int depth) { -#ifdef DEBUG_XEMACS - { - /* Egcs 1.1.1 sometimes crashes on INTP (p->size_or_chain) */ - Lisp_Object size_or_chain = XOPAQUE (obj)->size_or_chain; - assert (INTP (size_or_chain)); - assert (!XOPAQUE_MARKFUN (obj)); - } -#endif if (XOPAQUE_SIZE (obj) == sizeof (unsigned long)) return *((unsigned long *) XOPAQUE_DATA (obj)); else return memory_hash (XOPAQUE_DATA (obj), XOPAQUE_SIZE (obj)); } +static const struct lrecord_description opaque_description[] = { + { XD_END } +}; + DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("opaque", opaque, - mark_opaque, print_opaque, 0, - equal_opaque, hash_opaque, 0, + 0, print_opaque, 0, + equal_opaque, hash_opaque, + opaque_description, sizeof_opaque, Lisp_Opaque); -static Lisp_Object -mark_opaque_list (Lisp_Object obj, void (*markobj) (Lisp_Object)) -{ - in_opaque_list_marking++; - markobj (XOPAQUE_LIST (obj)->free); - in_opaque_list_marking--; - return Qnil; -} +/* stuff to handle opaque pointers */ -Lisp_Object -make_opaque_list (size_t size, - Lisp_Object (*markfun) (Lisp_Object obj, - void (*markobj) (Lisp_Object))) +/* Should never, ever be called. (except by an external debugger) */ +static void +print_opaque_ptr (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) { - Lisp_Object val; - Lisp_Opaque_List *p = - alloc_lcrecord_type (Lisp_Opaque_List, &lrecord_opaque_list); + CONST Lisp_Opaque_Ptr *p = XOPAQUE_PTR (obj); + char buf[200]; - p->markfun = markfun; - p->size = size; - p->free = Qnil; - XSETOPAQUE_LIST (val, p); - return val; + sprintf (buf, "#", + (long)(p->ptr), (unsigned long) p); + write_c_string (buf, printcharfun); } -DEFINE_LRECORD_IMPLEMENTATION ("opaque-list", opaque_list, - mark_opaque_list, internal_object_printer, - 0, 0, 0, 0, Lisp_Opaque_List); - -Lisp_Object -allocate_managed_opaque (Lisp_Object opaque_list, CONST void *data) +static int +equal_opaque_ptr (Lisp_Object obj1, Lisp_Object obj2, int depth) { - Lisp_Opaque_List *li = XOPAQUE_LIST (opaque_list); - Lisp_Object val; - - if (!NILP (li->free)) - { - val = li->free; - li->free = XOPAQUE (val)->size_or_chain; -#ifdef ERROR_CHECK_GC - assert (NILP (li->free) || OPAQUEP (li->free)); -#endif - XOPAQUE (val)->size_or_chain = make_int (li->size); - if (data) - memcpy (XOPAQUE (val)->data, data, li->size); - else - memset (XOPAQUE (val)->data, 0, li->size); - } - else - val = make_opaque (li->size, data); - XOPAQUE (val)->markfun = li->markfun; - return val; + return (XOPAQUE_PTR (obj1)->ptr == XOPAQUE_PTR (obj2)->ptr); } -void -free_managed_opaque (Lisp_Object opaque_list, Lisp_Object opaque) +static unsigned long +hash_opaque_ptr (Lisp_Object obj, int depth) { - Lisp_Opaque_List *li = XOPAQUE_LIST (opaque_list); - -#ifdef ERROR_CHECK_GC - { - /* Egcs 1.1.1 sometimes crashes on INTP (p->size_or_chain) */ - Lisp_Object size_or_chain = XOPAQUE (opaque)->size_or_chain; - assert (INTP (size_or_chain)); - } -#endif - XOPAQUE (opaque)->size_or_chain = li->free; - li->free = opaque; + return (unsigned long) XOPAQUE_PTR (obj)->ptr; } -/* stuff to handle opaque pointers */ +DEFINE_LRECORD_IMPLEMENTATION ("opaque_ptr", opaque_ptr, + 0, print_opaque_ptr, 0, + equal_opaque_ptr, hash_opaque_ptr, 0, + Lisp_Opaque_Ptr); Lisp_Object -make_opaque_ptr (CONST void *val) +make_opaque_ptr (void *val) { - return allocate_managed_opaque (Vopaque_ptr_free_list, - (CONST void *) &val); + Lisp_Object res = allocate_managed_lcrecord(Vopaque_ptr_free_list); + set_opaque_ptr (res, val); + return res; } /* Be very very careful with this. Same admonitions as with @@ -263,18 +160,18 @@ make_opaque_ptr (CONST void *val) void free_opaque_ptr (Lisp_Object ptr) { - free_managed_opaque (Vopaque_ptr_free_list, ptr); + free_managed_lcrecord (Vopaque_ptr_free_list, ptr); } -Lisp_Object -make_opaque_long (long val) +void +reinit_opaque_once_early (void) { - return make_opaque (sizeof (val), (void *) &val); + Vopaque_ptr_free_list = make_lcrecord_list (sizeof (Lisp_Opaque_Ptr), &lrecord_opaque_ptr); + staticpro_nodump (&Vopaque_ptr_free_list); } void init_opaque_once_early (void) { - Vopaque_ptr_free_list = make_opaque_list (sizeof (void *), 0); - staticpro (&Vopaque_ptr_free_list); + reinit_opaque_once_early (); } diff --git a/src/opaque.h b/src/opaque.h index f12a985..4788cf0 100644 --- a/src/opaque.h +++ b/src/opaque.h @@ -35,69 +35,46 @@ typedef union { typedef struct Lisp_Opaque { struct lcrecord_header header; - Lisp_Object (*markfun) (Lisp_Object obj, void (*markobj) (Lisp_Object)); - /* An integral size for non-freed objects, an opaque or nil for - freed objects. */ - Lisp_Object size_or_chain; + size_t size; max_align_t data[1]; } Lisp_Opaque; -typedef struct Lisp_Opaque_List -{ - struct lcrecord_header header; - /* `markfun' allows you to put lisp objects inside of opaque objects - without having to create a new object type. */ - Lisp_Object (*markfun) (Lisp_Object obj, void (*markobj) (Lisp_Object)); - Lisp_Object free; - size_t size; -} Lisp_Opaque_List; - DECLARE_LRECORD (opaque, Lisp_Opaque); #define XOPAQUE(x) XRECORD (x, opaque, Lisp_Opaque) #define XSETOPAQUE(x, p) XSETRECORD (x, p, opaque) #define OPAQUEP(x) RECORDP (x, opaque) -#define GC_OPAQUEP(x) GC_RECORDP (x, opaque) /* #define CHECK_OPAQUE(x) CHECK_RECORD (x, opaque) Opaque pointers should never escape to the Lisp level, so functions should not be doing this. */ -DECLARE_LRECORD (opaque_list, Lisp_Opaque_List); -#define XOPAQUE_LIST(x) XRECORD (x, opaque_list, Lisp_Opaque_List) -#define XSETOPAQUE_LIST(x, p) XSETRECORD (x, p, opaque_list) -#define OPAQUE_LISTP(x) RECORDP (x, opaque_list) -#define GC_OPAQUE_LISTP(x) GC_RECORDP (x, opaque_list) -/* #define CHECK_OPAQUE_LIST(x) CHECK_RECORD (x, opaque_list) - Opaque lists should never escape to the Lisp level, so - functions should not be doing this. */ - /* Alternative DATA arguments to make_opaque */ #define OPAQUE_CLEAR ((CONST void *) 0) #define OPAQUE_UNINIT ((CONST void *) -1) -Lisp_Object make_opaque (size_t size, CONST void *data); -Lisp_Object make_opaque_ptr (CONST void *val); -Lisp_Object make_opaque_long (long val); -void free_opaque_ptr (Lisp_Object ptr); - -#define OPAQUE_SIZE(op) XINT ((op)->size_or_chain) +#define OPAQUE_SIZE(op) ((op)->size) #define OPAQUE_DATA(op) ((void *) ((op)->data)) #define OPAQUE_MARKFUN(op) ((op)->markfun) #define XOPAQUE_SIZE(op) OPAQUE_SIZE (XOPAQUE (op)) #define XOPAQUE_DATA(op) OPAQUE_DATA (XOPAQUE (op)) #define XOPAQUE_MARKFUN(op) OPAQUE_MARKFUN (XOPAQUE (op)) -#define get_opaque_ptr(op) (* (void **) XOPAQUE_DATA (op)) -#define set_opaque_ptr(op, ptr) (get_opaque_ptr (op) = (void *) ptr) -#define get_opaque_long(op) (* (long *) XOPAQUE_DATA (op)) -#define set_opaque_long(op, ptr) (get_opaque_long (op) = ptr) -#define set_opaque_markfun(op, fun) (XOPAQUE_MARKFUN (op) = fun) - -Lisp_Object make_opaque_list (size_t size, - Lisp_Object (*markfun) - (Lisp_Object obj, - void (*markobj) (Lisp_Object))); -Lisp_Object allocate_managed_opaque (Lisp_Object opaque_list, - CONST void *data); -void free_managed_opaque (Lisp_Object opaque_list, Lisp_Object opaque); +Lisp_Object make_opaque (size_t size, CONST void *data); + +typedef struct Lisp_Opaque_Ptr +{ + struct lcrecord_header header; + void *ptr; +} Lisp_Opaque_Ptr; + +DECLARE_LRECORD (opaque_ptr, Lisp_Opaque_Ptr); +#define XOPAQUE_PTR(x) XRECORD (x, opaque_ptr, Lisp_Opaque_Ptr) +#define XSETOPAQUE_PTR(x, p) XSETRECORD (x, p, opaque_ptr) +#define OPAQUE_PTRP(x) RECORDP (x, opaque_ptr) + +Lisp_Object make_opaque_ptr (void *val); +void free_opaque_ptr (Lisp_Object ptr); + +#define get_opaque_ptr(op) (XOPAQUE_PTR (op)->ptr) +#define set_opaque_ptr(op, ptr_) (XOPAQUE_PTR (op)->ptr = (ptr_)) #endif /* _XEMACS_OPAQUE_H_ */ diff --git a/src/print.c b/src/print.c index 8ded305..2616896 100644 --- a/src/print.c +++ b/src/print.c @@ -51,14 +51,13 @@ Lisp_Object Vstandard_output, Qstandard_output; /* The subroutine object for external-debugging-output is kept here for the convenience of the debugger. */ Lisp_Object Qexternal_debugging_output; -Lisp_Object Qalternate_debugging_output; /* Avoid actual stack overflow in print. */ static int print_depth; /* Detect most circularities to print finite output. */ #define PRINT_CIRCLE 200 -Lisp_Object being_printed[PRINT_CIRCLE]; +static Lisp_Object being_printed[PRINT_CIRCLE]; /* Maximum length of list or vector to print in full; noninteger means effectively infinity */ @@ -92,9 +91,6 @@ int print_readably; Lisp_Object Vprint_gensym; Lisp_Object Vprint_gensym_alist; -Lisp_Object Qprint_escape_newlines; -Lisp_Object Qprint_readably; - Lisp_Object Qdisplay_error; Lisp_Object Qprint_message_label; @@ -711,7 +707,6 @@ Display ERROR-OBJECT on STREAM in a user-friendly way. #ifdef LISP_FLOAT_TYPE Lisp_Object Vfloat_output_format; -Lisp_Object Qfloat_output_format; /* * This buffer should be at least as large as the max string size of the @@ -1362,8 +1357,8 @@ print_symbol (Lisp_Object obj, Lisp_Object printcharfun, int escapeflag) getting rid of this function altogether? Does anything actually *use* it? --hniksic */ -int alternate_do_pointer; -char alternate_do_string[5000]; +static int alternate_do_pointer; +static char alternate_do_string[5000]; DEFUN ("alternate-debugging-output", Falternate_debugging_output, 1, 1, 0, /* Append CHARACTER to the array `alternate_do_string'. @@ -1467,7 +1462,6 @@ FILE = nil means just close any termscript file currently open. /* Debugging kludge -- unbuffered */ static int debug_print_length = 50; static int debug_print_level = 15; -Lisp_Object debug_temp; static void debug_print_no_newline (Lisp_Object debug_print_obj) @@ -1604,15 +1598,8 @@ debug_short_backtrace (int length) void syms_of_print (void) { - defsymbol (&Qprint_escape_newlines, "print-escape-newlines"); - defsymbol (&Qprint_readably, "print-readably"); - defsymbol (&Qstandard_output, "standard-output"); -#ifdef LISP_FLOAT_TYPE - defsymbol (&Qfloat_output_format, "float-output-format"); -#endif - defsymbol (&Qprint_length, "print-length"); defsymbol (&Qprint_string_length, "print-string-length"); @@ -1629,7 +1616,6 @@ syms_of_print (void) DEFSUBR (Fterpri); DEFSUBR (Fwrite_char); DEFSUBR (Falternate_debugging_output); - defsymbol (&Qalternate_debugging_output, "alternate-debugging-output"); DEFSUBR (Fexternal_debugging_output); DEFSUBR (Fopen_termscript); defsymbol (&Qexternal_debugging_output, "external-debugging-output"); @@ -1637,9 +1623,15 @@ syms_of_print (void) } void -vars_of_print (void) +reinit_vars_of_print (void) { alternate_do_pointer = 0; +} + +void +vars_of_print (void) +{ + reinit_vars_of_print (); DEFVAR_LISP ("standard-output", &Vstandard_output /* Output stream `print' uses by default for outputting a character. diff --git a/src/process-nt.c b/src/process-nt.c index 0582761..0b92984 100644 --- a/src/process-nt.c +++ b/src/process-nt.c @@ -409,8 +409,6 @@ nt_init_process (void) * must signal an error instead. */ -/* #### This function completely ignores Vprocess_environment */ - static void signal_cannot_launch (Lisp_Object image_file, DWORD err) { @@ -426,6 +424,7 @@ nt_create_process (struct Lisp_Process *p, HANDLE hmyshove, hmyslurp, hprocin, hprocout; LPTSTR command_line; BOOL do_io, windowed; + char *proc_env; /* Find out whether the application is windowed or not */ { @@ -513,6 +512,80 @@ nt_create_process (struct Lisp_Process *p, UNGCPRO; /* args_or_ret */ } + /* Set `proc_env' to a nul-separated array of the strings in + Vprocess_environment terminated by 2 nuls. */ + + { + extern int compare_env (const char **strp1, const char **strp2); + char **env; + REGISTER Lisp_Object tem; + REGISTER char **new_env; + REGISTER int new_length = 0, i, new_space; + char *penv; + + for (tem = Vprocess_environment; + (CONSP (tem) + && STRINGP (XCAR (tem))); + tem = XCDR (tem)) + new_length++; + + /* new_length + 1 to include terminating 0. */ + env = new_env = alloca_array (char *, new_length + 1); + + /* Copy the Vprocess_environment strings into new_env. */ + for (tem = Vprocess_environment; + (CONSP (tem) + && STRINGP (XCAR (tem))); + tem = XCDR (tem)) + { + char **ep = env; + char *string = (char *) XSTRING_DATA (XCAR (tem)); + /* See if this string duplicates any string already in the env. + If so, don't put it in. + When an env var has multiple definitions, + we keep the definition that comes first in process-environment. */ + for (; ep != new_env; ep++) + { + char *p = *ep, *q = string; + while (1) + { + if (*q == 0) + /* The string is malformed; might as well drop it. */ + goto duplicate; + if (*q != *p) + break; + if (*q == '=') + goto duplicate; + p++, q++; + } + } + *new_env++ = string; + duplicate: ; + } + *new_env = 0; + + /* Sort the environment variables */ + new_length = new_env - env; + qsort (env, new_length, sizeof (char *), compare_env); + + /* Work out how much space to allocate */ + new_space = 0; + for (i = 0; i < new_length; i++) + { + new_space += strlen(env[i]) + 1; + } + new_space++; + + /* Allocate space and copy variables into it */ + penv = proc_env = alloca(new_space); + for (i = 0; i < new_length; i++) + { + strcpy(penv, env[i]); + penv += strlen(env[i]) + 1; + } + *penv = 0; + } + /* Create process */ { STARTUPINFO si; @@ -533,7 +606,7 @@ nt_create_process (struct Lisp_Process *p, err = (CreateProcess (NULL, command_line, NULL, NULL, TRUE, CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP | CREATE_SUSPENDED, - NULL, (char *) XSTRING_DATA (cur_dir), &si, &pi) + proc_env, (char *) XSTRING_DATA (cur_dir), &si, &pi) ? 0 : GetLastError ()); if (do_io) @@ -834,7 +907,7 @@ nt_canonicalize_host_name (Lisp_Object host) static void nt_open_network_stream (Lisp_Object name, Lisp_Object host, Lisp_Object service, - Lisp_Object family, void** vinfd, void** voutfd) + Lisp_Object protocol, void** vinfd, void** voutfd) { struct sockaddr_in address; SOCKET s; @@ -843,9 +916,9 @@ nt_open_network_stream (Lisp_Object name, Lisp_Object host, Lisp_Object service, CHECK_STRING (host); - if (!EQ (family, Qtcpip)) - error ("Unsupported protocol family \"%s\"", - string_data (symbol_name (XSYMBOL (family)))); + if (!EQ (protocol, Qtcp)) + error ("Unsupported protocol \"%s\"", + string_data (symbol_name (XSYMBOL (protocol)))); if (INTP (service)) port = htons ((unsigned short) XINT (service)); diff --git a/src/process-unix.c b/src/process-unix.c index 6f8e7c6..b4a612e 100644 --- a/src/process-unix.c +++ b/src/process-unix.c @@ -212,9 +212,11 @@ allocate_pty (void) end of the ptys. */ int failed_count = 0; #endif - int i; int fd; +#ifndef HAVE_GETPT + int i; int c; +#endif #ifdef PTY_ITERATION PTY_ITERATION @@ -261,7 +263,7 @@ allocate_pty (void) #else sprintf (pty_name, "/dev/tty%c%x", c, i); #endif /* no PTY_TTY_NAME_SPRINTF */ -#ifndef UNIPLUS +#if !defined(UNIPLUS) && !defined(HAVE_GETPT) if (access (pty_name, 6) != 0) { close (fd); @@ -384,7 +386,7 @@ set_socket_nonblocking_maybe (int fd, int port, CONST char* proto) else continue; } - else if ((INTP (tail_port)) && (htons ((unsigned short) XINT (tail_port)) == port)) + else if (INTP (tail_port) && (htons ((unsigned short) XINT (tail_port)) == port)) break; } @@ -663,10 +665,9 @@ unix_alloc_process_data (struct Lisp_Process *p) */ static void -unix_mark_process_data (struct Lisp_Process *proc, - void (*markobj) (Lisp_Object)) +unix_mark_process_data (struct Lisp_Process *proc) { - markobj (UNIX_DATA(proc)->tty_name); + mark_object (UNIX_DATA(proc)->tty_name); } /* @@ -1429,19 +1430,21 @@ unix_canonicalize_host_name (Lisp_Object host) static void unix_open_network_stream (Lisp_Object name, Lisp_Object host, Lisp_Object service, - Lisp_Object family, void** vinfd, void** voutfd) + Lisp_Object protocol, void** vinfd, void** voutfd) { struct sockaddr_in address; - int s, inch, outch; + int inch; + int outch; + volatile int s; volatile int port; volatile int retry = 0; int retval; CHECK_STRING (host); - if (!EQ (family, Qtcpip)) - error ("Unsupported protocol family \"%s\"", - string_data (symbol_name (XSYMBOL (family)))); + if (!EQ (protocol, Qtcp) && !EQ (protocol, Qudp)) + error ("Unsupported protocol \"%s\"", + string_data (symbol_name (XSYMBOL (protocol)))); if (INTP (service)) port = htons ((unsigned short) XINT (service)); @@ -1449,7 +1452,12 @@ unix_open_network_stream (Lisp_Object name, Lisp_Object host, Lisp_Object servic { struct servent *svc_info; CHECK_STRING (service); - svc_info = getservbyname ((char *) XSTRING_DATA (service), "tcp"); + + if (EQ (protocol, Qtcp)) + svc_info = getservbyname ((char *) XSTRING_DATA (service), "tcp"); + else /* EQ (protocol, Qudp) */ + svc_info = getservbyname ((char *) XSTRING_DATA (service), "udp"); + if (svc_info == 0) error ("Unknown service \"%s\"", XSTRING_DATA (service)); port = svc_info->s_port; @@ -1458,7 +1466,11 @@ unix_open_network_stream (Lisp_Object name, Lisp_Object host, Lisp_Object servic get_internet_address (host, &address, ERROR_ME); address.sin_port = port; - s = socket (address.sin_family, SOCK_STREAM, 0); + if (EQ (protocol, Qtcp)) + s = socket (address.sin_family, SOCK_STREAM, 0); + else /* EQ (protocol, Qudp) */ + s = socket (address.sin_family, SOCK_DGRAM, 0); + if (s < 0) report_file_error ("error creating socket", list1 (name)); diff --git a/src/process.c b/src/process.c index c3b493a..9b73e80 100644 --- a/src/process.c +++ b/src/process.c @@ -71,7 +71,7 @@ Lisp_Object Qrun, Qstop; /* Qrun => Qopen, Qexit => Qclosed for "network connection" processes */ Lisp_Object Qopen, Qclosed; /* Protocol families */ -Lisp_Object Qtcpip; +Lisp_Object Qtcp, Qudp; #ifdef HAVE_MULTICAST Lisp_Object Qmulticast; /* Will be used for occasional warnings */ @@ -111,22 +111,22 @@ extern Lisp_Object Vlisp_EXEC_SUFFIXES; static Lisp_Object -mark_process (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_process (Lisp_Object obj) { struct Lisp_Process *proc = XPROCESS (obj); - MAYBE_PROCMETH (mark_process_data, (proc, markobj)); - markobj (proc->name); - markobj (proc->command); - markobj (proc->filter); - markobj (proc->sentinel); - markobj (proc->buffer); - markobj (proc->mark); - markobj (proc->pid); - markobj (proc->pipe_instream); - markobj (proc->pipe_outstream); + MAYBE_PROCMETH (mark_process_data, (proc)); + mark_object (proc->name); + mark_object (proc->command); + mark_object (proc->filter); + mark_object (proc->sentinel); + mark_object (proc->buffer); + mark_object (proc->mark); + mark_object (proc->pid); + mark_object (proc->pipe_instream); + mark_object (proc->pipe_outstream); #ifdef FILE_CODING - markobj (proc->coding_instream); - markobj (proc->coding_outstream); + mark_object (proc->coding_instream); + mark_object (proc->coding_outstream); #endif return proc->status_symbol; } @@ -245,7 +245,7 @@ connected_via_filedesc_p (struct Lisp_Process *p) int network_connection_p (Lisp_Object process) { - return GC_CONSP (XPROCESS (process)->pid); + return CONSP (XPROCESS (process)->pid); } #endif @@ -272,7 +272,7 @@ Return the process named NAME, or nil if there is none. { Lisp_Object tail; - if (GC_PROCESSP (name)) + if (PROCESSP (name)) return name; if (!gc_in_progress) @@ -280,7 +280,7 @@ Return the process named NAME, or nil if there is none. of a signal or crash. */ CHECK_STRING (name); - for (tail = Vprocess_list; GC_CONSP (tail); tail = XCDR (tail)) + for (tail = Vprocess_list; CONSP (tail); tail = XCDR (tail)) { Lisp_Object proc = XCAR (tail); QUIT; @@ -298,18 +298,18 @@ BUFFER may be a buffer or the name of one. { Lisp_Object buf, tail, proc; - if (GC_NILP (name)) return Qnil; + if (NILP (name)) return Qnil; buf = Fget_buffer (name); - if (GC_NILP (buf)) return Qnil; + if (NILP (buf)) return Qnil; - for (tail = Vprocess_list; GC_CONSP (tail); tail = XCDR (tail)) + for (tail = Vprocess_list; CONSP (tail); tail = XCDR (tail)) { /* jwz: do not quit here - it isn't necessary, as there is no way for Vprocess_list to get circular or overwhelmingly long, and this function is called from layout_mode_element under redisplay. */ /* QUIT; */ proc = XCAR (tail); - if (GC_PROCESSP (proc) && EQ (XPROCESS (proc)->buffer, buf)) + if (PROCESSP (proc) && EQ (XPROCESS (proc)->buffer, buf)) return proc; } return Qnil; @@ -331,28 +331,28 @@ get_process (Lisp_Object name) /* This may be called during a GC from process_send_signal() from kill_buffer_processes() if emacs decides to abort(). */ - if (GC_PROCESSP (name)) + if (PROCESSP (name)) return name; - if (GC_STRINGP (name)) + if (STRINGP (name)) { obj = Fget_process (name); - if (GC_NILP (obj)) + if (NILP (obj)) obj = Fget_buffer (name); - if (GC_NILP (obj)) + if (NILP (obj)) error ("Process %s does not exist", XSTRING_DATA (name)); } - else if (GC_NILP (name)) + else if (NILP (name)) obj = Fcurrent_buffer (); else obj = name; /* Now obj should be either a buffer object or a process object. */ - if (GC_BUFFERP (obj)) + if (BUFFERP (obj)) { proc = Fget_buffer_process (obj); - if (GC_NILP (proc)) + if (NILP (proc)) error ("Buffer %s has no process", XSTRING_DATA (XBUFFER(obj)->name)); } else @@ -659,7 +659,7 @@ INCODE and OUTCODE specify the coding-system objects used in input/output DEFUN ("open-network-stream-internal", Fopen_network_stream_internal, 4, 5, 0, /* Open a TCP connection for a service to a host. -Returns a subprocess-object to represent the connection. +Return a subprocess-object to represent the connection. Input and output work as for subprocesses; `delete-process' closes it. NAME is name for process. It is modified if necessary to make it unique. @@ -671,10 +671,18 @@ BUFFER is the buffer (or buffer-name) to associate with the process. Third arg is name of the host to connect to, or its IP address. Fourth arg SERVICE is name of the service desired, or an integer specifying a port number to connect to. -Fifth argument FAMILY is a protocol family. When omitted, 'tcp/ip -\(Internet protocol family TCP/IP) is assumed. +Fifth argument PROTOCOL is a network protocol. Currently 'tcp + (Transmission Control Protocol) and 'udp (User Datagram Protocol) are + supported. When omitted, 'tcp is assumed. + +Ouput via `process-send-string' and input via buffer or filter (see +`set-process-filter') are stream-oriented. That means UDP datagrams are +not guaranteed to be sent and received in discrete packets. (But small +datagrams around 500 bytes that are not truncated by `process-send-string' +are usually fine.) Note further that UDP protocol does not guard against +lost packets. */ - (name, buffer, host, service, family)) + (name, buffer, host, service, protocol)) { /* !!#### This function has not been Mule-ized */ /* This function can GC */ @@ -682,17 +690,17 @@ Fifth argument FAMILY is a protocol family. When omitted, 'tcp/ip struct gcpro gcpro1, gcpro2, gcpro3, gcpro4, gcpro5, ngcpro1; void *inch, *outch; - GCPRO5 (name, buffer, host, service, family); + GCPRO5 (name, buffer, host, service, protocol); CHECK_STRING (name); - if (NILP(family)) - family = Qtcpip; + if (NILP(protocol)) + protocol = Qtcp; else - CHECK_SYMBOL (family); + CHECK_SYMBOL (protocol); /* Since this code is inside HAVE_SOCKETS, existence of open_network_stream is mandatory */ - PROCMETH (open_network_stream, (name, host, service, family, + PROCMETH (open_network_stream, (name, host, service, protocol, &inch, &outch)); if (!NILP (buffer)) @@ -716,7 +724,7 @@ Fifth argument FAMILY is a protocol family. When omitted, 'tcp/ip DEFUN ("open-multicast-group-internal", Fopen_multicast_group_internal, 5, 5, 0, /* Open a multicast connection on the specified dest/port/ttl. -Returns a subprocess-object to represent the connection. +Return a subprocess-object to represent the connection. Input and output work as for subprocesses; `delete-process' closes it. NAME is name for process. It is modified if necessary to make it unique. @@ -965,7 +973,7 @@ send_process (Lisp_Object proc, if (nonrelocatable) lstream = make_fixed_buffer_input_stream (nonrelocatable + start, len); - else if (GC_BUFFERP (relocatable)) + else if (BUFFERP (relocatable)) lstream = make_lisp_buffer_input_stream (XBUFFER (relocatable), start, start + len, 0); else @@ -1898,12 +1906,12 @@ kill_buffer_processes (Lisp_Object buffer) { Lisp_Object tail; - for (tail = Vprocess_list; GC_CONSP (tail); + for (tail = Vprocess_list; CONSP (tail); tail = XCDR (tail)) { Lisp_Object proc = XCAR (tail); - if (GC_PROCESSP (proc) - && (GC_NILP (buffer) || GC_EQ (XPROCESS (proc)->buffer, buffer))) + if (PROCESSP (proc) + && (NILP (buffer) || EQ (XPROCESS (proc)->buffer, buffer))) { if (network_connection_p (proc)) Fdelete_process (proc); @@ -1975,7 +1983,8 @@ syms_of_process (void) defsymbol (&Qopen, "open"); defsymbol (&Qclosed, "closed"); - defsymbol (&Qtcpip, "tcp/ip"); + defsymbol (&Qtcp, "tcp"); + defsymbol (&Qudp, "udp"); #ifdef HAVE_MULTICAST defsymbol(&Qmulticast, "multicast"); /* Used for occasional warnings */ diff --git a/src/process.h b/src/process.h index f2574d8..59adf41 100644 --- a/src/process.h +++ b/src/process.h @@ -44,7 +44,6 @@ DECLARE_LRECORD (process, struct Lisp_Process); #define XPROCESS(x) XRECORD (x, process, struct Lisp_Process) #define XSETPROCESS(x, p) XSETRECORD (x, p, process) #define PROCESSP(x) RECORDP (x, process) -#define GC_PROCESSP(x) GC_RECORDP (x, process) #define CHECK_PROCESS(x) CHECK_RECORD (x, process) #define PROCESS_LIVE_P(x) (!NILP (XPROCESS(x)->pipe_instream)) @@ -93,7 +92,7 @@ int network_connection_p (Lisp_Object process); #define network_connection_p(x) 0 #endif -extern Lisp_Object Qclosed, Qmulticast, Qopen, Qrun, Qstop, Qtcpip; +extern Lisp_Object Qclosed, Qmulticast, Qopen, Qrun, Qstop, Qtcp, Qudp; extern Lisp_Object Vprocess_connection_type, Vprocess_list; /* Report all recent events of a change in process status @@ -134,4 +133,13 @@ Lisp_Object canonicalize_host_name (Lisp_Object host); #endif /* emacs */ +#ifdef HAVE_GETPT +#define PTY_ITERATION +#define PTY_OPEN \ + if ((fd = getpt()) < 0 || grantpt (fd) < 0 || unlockpt (fd) < 0) \ + return -1; +#define PTY_NAME_SPRINTF +#define PTY_TTY_NAME_SPRINTF strcpy (pty_name, ptsname (fd)); +#endif + #endif /* _XEMACS_PROCESS_H_ */ diff --git a/src/procimpl.h b/src/procimpl.h index b16c1e0..ded0881 100644 --- a/src/procimpl.h +++ b/src/procimpl.h @@ -37,8 +37,7 @@ struct Lisp_Process; struct process_methods { - void (*mark_process_data) (struct Lisp_Process *proc, - void (*markobj) (Lisp_Object)); + void (*mark_process_data) (struct Lisp_Process *proc); void (*print_process_data) (struct Lisp_Process *proc, Lisp_Object printcharfun); void (*finalize_process_data) (struct Lisp_Process *proc, int for_disksave); @@ -51,7 +50,7 @@ struct process_methods int (*tooltalk_connection_p) (struct Lisp_Process *p); #ifdef HAVE_SOCKETS void (*open_network_stream) (Lisp_Object name, Lisp_Object host, - Lisp_Object service, Lisp_Object family, + Lisp_Object service, Lisp_Object protocol, void** vinfd, void** voutfd); #ifdef HAVE_MULTICAST void (*open_multicast_group) (Lisp_Object name, Lisp_Object dest, @@ -159,7 +158,7 @@ struct Lisp_Process /* Random externs from process.c */ extern Lisp_Object Qrun, Qstop, Qopen, Qclosed; -extern Lisp_Object Qtcpip; +extern Lisp_Object Qtcp, Qudp; extern Lisp_Object Vprocess_connection_type; extern Lisp_Object Vprocess_list; diff --git a/src/profile.c b/src/profile.c index 6fa506b..648026f 100644 --- a/src/profile.c +++ b/src/profile.c @@ -57,7 +57,7 @@ Boston, MA 02111-1307, USA. */ even be useful to provide a way to turn on only one profiling mechanism, but I haven't done so yet. --hniksic */ -struct hash_table *big_profile_table; +static struct hash_table *big_profile_table; Lisp_Object Vcall_count_profile_table; int default_profiling_interval; @@ -68,10 +68,10 @@ int profiling_active; and is not set the whole time we're in redisplay. */ int profiling_redisplay_flag; -Lisp_Object QSin_redisplay; -Lisp_Object QSin_garbage_collection; -Lisp_Object QSprocessing_events_at_top_level; -Lisp_Object QSunknown; +static Lisp_Object QSin_redisplay; +static Lisp_Object QSin_garbage_collection; +static Lisp_Object QSprocessing_events_at_top_level; +static Lisp_Object QSunknown; /* We use inside_profiling to prevent the handler from writing to the table while another routine is operating on it. We also set @@ -119,9 +119,9 @@ sigprof_handler (int signo) { fun = *backtrace_list->function; - if (!GC_SYMBOLP (fun) && - !GC_COMPILED_FUNCTIONP (fun) && - !GC_SUBRP (fun)) + if (!SYMBOLP (fun) && + !COMPILED_FUNCTIONP (fun) && + !SUBRP (fun)) fun = QSunknown; } else @@ -262,11 +262,6 @@ Return the profiling info as an alist. return closure.accum; } -struct mark_profiling_info_closure -{ - void (*markfun) (Lisp_Object); -}; - static int mark_profiling_info_maphash (CONST void *void_key, void *void_val, @@ -275,21 +270,18 @@ mark_profiling_info_maphash (CONST void *void_key, Lisp_Object key; CVOID_TO_LISP (key, void_key); - (((struct mark_profiling_info_closure *) void_closure)->markfun) (key); + mark_object (key); return 0; } void -mark_profiling_info (void (*markfun) (Lisp_Object)) +mark_profiling_info (void) { - /* This function does not GC (if markfun doesn't) */ - struct mark_profiling_info_closure closure; - - closure.markfun = markfun; + /* This function does not GC */ if (big_profile_table) { inside_profiling = 1; - maphash (mark_profiling_info_maphash, big_profile_table, &closure); + maphash (mark_profiling_info_maphash, big_profile_table, 0); inside_profiling = 0; } } diff --git a/src/ralloc.c b/src/ralloc.c index 5f336a9..9cc4416 100644 --- a/src/ralloc.c +++ b/src/ralloc.c @@ -98,7 +98,7 @@ static int r_alloc_initialized = 0; /* Declarations for working with the malloc, ralloc, and system breaks. */ /* Function to set the real break value. */ -static POINTER (*real_morecore) (long size); +static POINTER (*real_morecore) (ptrdiff_t size); /* The break value, as seen by malloc (). */ static POINTER virtual_break_value; @@ -339,7 +339,7 @@ get_more_space (SIZE size) If SIZE is more than a page, return the space to the system. */ static void -relinquish () +relinquish (void) { register heap_ptr h; int excess = 0; @@ -790,9 +790,9 @@ free_bloc (bloc_ptr bloc) __morecore hook values - in particular, __default_morecore in the GNU malloc package. */ -POINTER r_alloc_sbrk (long size); +POINTER r_alloc_sbrk (ptrdiff_t size); POINTER -r_alloc_sbrk (long size) +r_alloc_sbrk (ptrdiff_t size) { register bloc_ptr b; POINTER address; @@ -1082,7 +1082,7 @@ r_alloc_freeze (long size) void r_alloc_thaw (void); void -r_alloc_thaw () +r_alloc_thaw (void) { if (! r_alloc_initialized) @@ -1109,14 +1109,11 @@ r_alloc_thaw () /* The hook `malloc' uses for the function which gets more space from the system. */ #ifndef DOUG_LEA_MALLOC -extern POINTER (*__morecore) (long size); +extern POINTER (*__morecore) (ptrdiff_t size); #endif /* Initialize various things for memory allocation. */ -#define SET_FUN_PTR(fun_ptr, fun_val) \ - (*((void **) (&fun_ptr)) = ((void *) (fun_val))) - void init_ralloc (void) { @@ -1124,8 +1121,12 @@ init_ralloc (void) return; r_alloc_initialized = 1; - SET_FUN_PTR (real_morecore, __morecore); - SET_FUN_PTR (__morecore, r_alloc_sbrk); + real_morecore = (POINTER (*) (ptrdiff_t)) __morecore; + __morecore = +#ifdef __GNUC__ + (__typeof__ (__morecore)) +#endif + r_alloc_sbrk; first_heap = last_heap = &heap_base; first_heap->next = first_heap->prev = NIL_HEAP; @@ -1172,21 +1173,25 @@ init_ralloc (void) Emacs. This is needed when using Doug Lea's malloc from GNU libc. */ void r_alloc_reinit (void); void -r_alloc_reinit () +r_alloc_reinit (void) { /* Only do this if the hook has been reset, so that we don't get an infinite loop, in case Emacs was linked statically. */ - if ( ((void*) __morecore) != (void *) (r_alloc_sbrk)) + if ( (POINTER (*) (ptrdiff_t)) __morecore != r_alloc_sbrk) { - SET_FUN_PTR (real_morecore, __morecore); - SET_FUN_PTR (__morecore, r_alloc_sbrk); + real_morecore = (POINTER (*) (ptrdiff_t)) __morecore; + __morecore = +#ifdef __GNUC__ + (__typeof__ (__morecore)) +#endif + r_alloc_sbrk; } } #if 0 #ifdef DEBUG void -r_alloc_check () +r_alloc_check (void) { int found = 0; heap_ptr h, ph = 0; diff --git a/src/rangetab.c b/src/rangetab.c index b7d9983..8d5bdba 100644 --- a/src/rangetab.c +++ b/src/rangetab.c @@ -41,13 +41,13 @@ Lisp_Object Qrange_table; is not hard but just requires moving that stuff out of that file. */ static Lisp_Object -mark_range_table (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_range_table (Lisp_Object obj) { struct Lisp_Range_Table *rt = XRANGE_TABLE (obj); int i; for (i = 0; i < Dynarr_length (rt->entries); i++) - markobj (Dynarr_at (rt->entries, i).val); + mark_object (Dynarr_at (rt->entries, i).val); return Qnil; } @@ -132,9 +132,35 @@ range_table_hash (Lisp_Object obj, int depth) return hash; } +static const struct lrecord_description rte_description_1[] = { + { XD_LISP_OBJECT, offsetof(range_table_entry, val), 1 }, + { XD_END } +}; + +static const struct struct_description rte_description = { + sizeof(range_table_entry), + rte_description_1 +}; + +static const struct lrecord_description rted_description_1[] = { + XD_DYNARR_DESC(range_table_entry_dynarr, &rte_description), + { XD_END } +}; + +static const struct struct_description rted_description = { + sizeof(range_table_entry_dynarr), + rted_description_1 +}; + +static const struct lrecord_description range_table_description[] = { + { XD_STRUCT_PTR, offsetof(struct Lisp_Range_Table, entries), 1, &rted_description }, + { XD_END } +}; + DEFINE_LRECORD_IMPLEMENTATION ("range-table", range_table, mark_range_table, print_range_table, 0, - range_table_equal, range_table_hash, 0, + range_table_equal, range_table_hash, + range_table_description, struct Lisp_Range_Table); /************************************************************************/ diff --git a/src/rangetab.h b/src/rangetab.h index f54c433..0a3a21a 100644 --- a/src/rangetab.h +++ b/src/rangetab.h @@ -50,7 +50,6 @@ DECLARE_LRECORD (range_table, struct Lisp_Range_Table); XRECORD (x, range_table, struct Lisp_Range_Table) #define XSETRANGE_TABLE(x, p) XSETRECORD (x, p, range_table) #define RANGE_TABLEP(x) RECORDP (x, range_table) -#define GC_RANGE_TABLEP(x) GC_RECORDP (x, range_table) #define CHECK_RANGE_TABLE(x) CHECK_RECORD (x, range_table) #endif diff --git a/src/realpath.c b/src/realpath.c index 78ccc25..f81bab6 100644 --- a/src/realpath.c +++ b/src/realpath.c @@ -22,25 +22,20 @@ Boston, MA 02111-1307, USA. */ /* Synched up with: Not in FSF. */ -#ifdef HAVE_CONFIG_H #include -#endif #include -#if defined(HAVE_UNISTD_H) || defined(STDC_HEADERS) -#include -#endif #include #include +#include +#ifdef HAVE_UNISTD_H +#include +#endif #ifdef _POSIX_VERSION #include /* for PATH_MAX */ #else #include /* for MAXPATHLEN */ #endif -#include -#ifndef STDC_HEADERS -extern int errno; -#endif #ifdef WINDOWSNT #include @@ -62,13 +57,8 @@ extern int errno; #define MAX_READLINKS 32 -#ifdef __STDC__ -char *xrealpath(const char *path, char resolved_path []) -#else -char *xrealpath(path, resolved_path) -const char *path; -char resolved_path []; -#endif +char * +xrealpath (const char *path, char resolved_path []) { char copy_path[PATH_MAX]; char *new_path = resolved_path; diff --git a/src/redisplay-msw.c b/src/redisplay-msw.c index 24ff96d..b9288e7 100644 --- a/src/redisplay-msw.c +++ b/src/redisplay-msw.c @@ -64,19 +64,8 @@ static void mswindows_redraw_exposed_windows (Lisp_Object window, int x, int y, int width, int height); static void mswindows_output_dibitmap (struct frame *f, struct Lisp_Image_Instance *p, - int x, int y, - int clip_x, int clip_y, - int clip_width, int clip_height, - int width, int height, - int pixmap_offset, - int offset_bitmap); -static void mswindows_output_pixmap (struct window *w, struct display_line *dl, - Lisp_Object image_instance, int xpos, - int xoffset, int start_pixpos, int width, - face_index findex, int cursor_start, - int cursor_width, int cursor_height, - int offset_bitmap); -void bevel_modeline (struct window *w, struct display_line *dl); + struct display_box* db, + struct display_glyph_area* dga); typedef struct textual_run { @@ -304,28 +293,37 @@ mswindows_output_hline (struct window *w, struct display_line *dl, struct rune * of its face. ****************************************************************************/ static void -mswindows_output_blank (struct window *w, struct display_line *dl, struct rune *rb, int start_pixpos) +mswindows_output_blank (struct window *w, struct display_line *dl, + struct rune *rb, int start_pixpos) { struct frame *f = XFRAME (w->frame); - RECT rect = { rb->xpos, dl->ypos-dl->ascent, - rb->xpos+rb->width, dl->ypos+dl->descent-dl->clip }; + RECT rect = { rb->xpos, DISPLAY_LINE_YPOS (dl), + rb->xpos+rb->width, + DISPLAY_LINE_YEND (dl) }; struct face_cachel *cachel = WINDOW_FACE_CACHEL (w, rb->findex); Lisp_Object bg_pmap = WINDOW_FACE_CACHEL_BACKGROUND_PIXMAP (w, rb->findex); + /* Unmap all subwindows in the area we are going to blank. */ + redisplay_unmap_subwindows_maybe (f, rb->xpos, DISPLAY_LINE_YPOS (dl), + rb->width, DISPLAY_LINE_HEIGHT (dl)); + if (!IMAGE_INSTANCEP (bg_pmap) || !IMAGE_INSTANCE_PIXMAP_TYPE_P (XIMAGE_INSTANCE (bg_pmap))) bg_pmap = Qnil; if (!NILP(bg_pmap)) { + struct display_box db; + struct display_glyph_area dga; + redisplay_calculate_display_boxes (dl, rb->xpos, + /*rb->object.dglyph.xoffset*/ 0, + start_pixpos, rb->width, + &db, &dga); /* blank the background in the appropriate color */ mswindows_update_dc (FRAME_MSWINDOWS_DC (f), Qnil, cachel->foreground, cachel->background, Qnil); - - mswindows_output_pixmap (w, dl, bg_pmap, - rb->xpos, 0 /*rb->object.dglyph.xoffset*/, - start_pixpos, rb->width, rb->findex, + redisplay_output_pixmap (w, bg_pmap, &db, &dga, rb->findex, 0, 0, 0, TRUE); } else @@ -359,15 +357,19 @@ mswindows_output_cursor (struct window *w, struct display_line *dl, int xpos, char *p_char = NULL; int n_char = 0; RECT rect = { xpos, - dl->ypos - dl->ascent, + DISPLAY_LINE_YPOS (dl), xpos + width, - dl->ypos + dl->descent - dl->clip}; + DISPLAY_LINE_YEND (dl) }; Lisp_Object bar = symbol_value_in_buffer (Qbar_cursor, WINDOW_BUFFER (w)); int bar_p = image_p || !NILP (bar); int cursor_p = !NILP (w->text_cursor_visible_p); int real_char_p = ch != 0; + /* Unmap all subwindows in the area we are going to blank. */ + redisplay_unmap_subwindows_maybe (f, xpos, DISPLAY_LINE_YPOS (dl), + width, DISPLAY_LINE_HEIGHT (dl)); + if (real_char_p) { /* Use the font from the underlying character */ @@ -466,8 +468,10 @@ mswindows_output_cursor (struct window *w, struct display_line *dl, int xpos, ****************************************************************************/ void mswindows_output_string (struct window *w, struct display_line *dl, - Emchar_dynarr *buf, int xpos, int xoffset, int clip_start, - int width, face_index findex) + Emchar_dynarr *buf, int xpos, int xoffset, int clip_start, + int width, face_index findex, + int cursor, int cursor_start, int cursor_width, + int cursor_height) { struct frame *f = XFRAME (w->frame); /* struct device *d = XDEVICE (f->device);*/ @@ -506,9 +510,13 @@ mswindows_output_string (struct window *w, struct display_line *dl, /* sort out the destination rectangle */ height = DISPLAY_LINE_HEIGHT (dl); rect.left = clip_start; - rect.top = dl->ypos - dl->ascent; + rect.top = DISPLAY_LINE_YPOS (dl); rect.right = clip_end; - rect.bottom = height + dl->ypos - dl->ascent; + rect.bottom = rect.top + height; + + /* make sure the area we are about to display is subwindow free. */ + redisplay_unmap_subwindows_maybe (f, clip_start, DISPLAY_LINE_YPOS (dl), + clip_end - clip_start, DISPLAY_LINE_HEIGHT (dl)); /* output the background pixmap if there is one */ bg_pmap = cachel->background_pixmap; @@ -518,13 +526,14 @@ mswindows_output_string (struct window *w, struct display_line *dl, if (!NILP(bg_pmap)) { + struct display_box db; + struct display_glyph_area dga; + redisplay_calculate_display_boxes (dl, xpos + xoffset, 0, + clip_start, width, &db, &dga); /* blank the background in the appropriate color */ mswindows_update_dc (hdc, Qnil, cachel->foreground, cachel->background, Qnil); - - mswindows_output_pixmap (w, dl, bg_pmap, - xpos, xoffset, - clip_start, width, findex, + redisplay_output_pixmap (w, bg_pmap, &db, &dga, findex, 0, 0, 0, TRUE); /* output pixmap calls this so we have to recall to get correct references */ @@ -549,14 +558,14 @@ mswindows_output_string (struct window *w, struct display_line *dl, this_width = mswindows_text_width_single_run (hdc, cachel, runs + i); /* cope with fonts taller than lines */ - if ((int) fi->height < (int) (height + dl->clip)) + if ((int) fi->height < (int) (height + dl->clip + dl->top_clip)) { int clear_start = max (xpos, clip_start); int clear_end = min (xpos + this_width, clip_end); { redisplay_clear_region (window, findex, clear_start, - dl->ypos - dl->ascent, + DISPLAY_LINE_YPOS (dl), clear_end - clear_start, height); /* output pixmap calls this so we have to recall to get correct @@ -581,31 +590,12 @@ mswindows_output_string (struct window *w, struct display_line *dl, static void mswindows_output_dibitmap (struct frame *f, struct Lisp_Image_Instance *p, - int x, int y, - int clip_x, int clip_y, - int clip_width, int clip_height, - int width, int height, int pixmap_offset, - int offset_bitmap) + struct display_box* db, + struct display_glyph_area* dga) { HDC hdc = FRAME_MSWINDOWS_DC (f); HGDIOBJ old=NULL; COLORREF bgcolor = GetBkColor (hdc); - int need_clipping = (clip_x || clip_y); - int yoffset=0; - int xoffset=0; - - /* do we need to offset the pixmap vertically? this is necessary - for background pixmaps. */ - if (offset_bitmap) - { - yoffset = y % IMAGE_INSTANCE_PIXMAP_HEIGHT (p); - xoffset = x % IMAGE_INSTANCE_PIXMAP_WIDTH (p); - /* the width is handled by mswindows_output_pixmap_region */ - } - - if (need_clipping) - { - } /* first blt the mask */ if (IMAGE_INSTANCE_MSWINDOWS_MASK (p)) @@ -622,93 +612,94 @@ mswindows_output_dibitmap (struct frame *f, struct Lisp_Image_Instance *p, SetDIBColorTable (FRAME_MSWINDOWS_CDC (f), 1, 1, &col); BitBlt (hdc, - x,y, - width, height, + db->xpos, db->ypos, + dga->width, dga->height, FRAME_MSWINDOWS_CDC (f), - xoffset,yoffset, + dga->xoffset, dga->yoffset, SRCCOPY); SelectObject (FRAME_MSWINDOWS_CDC (f), old); } - /* now blt the bitmap itself. */ + /* Now blt the bitmap itself, or one of its slices. */ old = SelectObject (FRAME_MSWINDOWS_CDC (f), - IMAGE_INSTANCE_MSWINDOWS_BITMAP (p)); + IMAGE_INSTANCE_MSWINDOWS_BITMAP_SLICE + (p, IMAGE_INSTANCE_PIXMAP_SLICE (p))); BitBlt (hdc, - x,y, - width, height, + db->xpos, db->ypos, + dga->width, dga->height, FRAME_MSWINDOWS_CDC (f), - xoffset, yoffset, + dga->xoffset, dga->yoffset, IMAGE_INSTANCE_MSWINDOWS_MASK (p) ? SRCINVERT : SRCCOPY); SelectObject (FRAME_MSWINDOWS_CDC (f),old); - - if (need_clipping) - { - } } -/* - * X gc's have this nice property that setting the bg pixmap will +/* X gc's have this nice property that setting the bg pixmap will * output it offset relative to the window. Windows doesn't have this - * feature so we have to emulate this by outputting multiple pixmaps - */ + * feature so we have to emulate this by outputting multiple pixmaps. + * This is only used for background pixmaps. Normal pixmaps are + * outputted once and are scrollable */ static void mswindows_output_dibitmap_region (struct frame *f, struct Lisp_Image_Instance *p, - int x, int y, - int clip_x, int clip_y, - int clip_width, int clip_height, - int width, int height, int pixmap_offset, - int offset_bitmap) + struct display_box *db, + struct display_glyph_area *dga) { - int pwidth = min (width, IMAGE_INSTANCE_PIXMAP_WIDTH (p)); - int pheight = min (height, IMAGE_INSTANCE_PIXMAP_HEIGHT (p)); + struct display_box xdb = { db->xpos, db->ypos, db->width, db->height }; + struct display_glyph_area xdga + = { 0, 0, IMAGE_INSTANCE_PIXMAP_WIDTH (p), + IMAGE_INSTANCE_PIXMAP_HEIGHT (p) }; int pxoffset = 0, pyoffset = 0; + if (dga) + { + xdga.width = dga->width; + xdga.height = dga->height; + } + else if (!redisplay_normalize_glyph_area (&xdb, &xdga)) + return; + /* when doing a bg pixmap do a partial pixmap first so that we blt whole pixmaps thereafter */ + xdga.height = min (xdga.height, IMAGE_INSTANCE_PIXMAP_HEIGHT (p) - + db->ypos % IMAGE_INSTANCE_PIXMAP_HEIGHT (p)); - if (offset_bitmap) - { - pheight = min (pheight, IMAGE_INSTANCE_PIXMAP_HEIGHT (p) - - y % IMAGE_INSTANCE_PIXMAP_HEIGHT (p)); - } - - while (pheight > 0) + while (xdga.height > 0) { - if (offset_bitmap) - { - pwidth = min (min (width, IMAGE_INSTANCE_PIXMAP_WIDTH (p)), + xdga.width = min (min (db->width, IMAGE_INSTANCE_PIXMAP_WIDTH (p)), IMAGE_INSTANCE_PIXMAP_WIDTH (p) - - x % IMAGE_INSTANCE_PIXMAP_WIDTH (p)); - pxoffset = 0; - } - while (pwidth > 0) + db->xpos % IMAGE_INSTANCE_PIXMAP_WIDTH (p)); + pxoffset = 0; + while (xdga.width > 0) { - mswindows_output_dibitmap (f, p, - x + pxoffset, y + pyoffset, - clip_x, clip_y, - clip_width, clip_height, - pwidth, pheight, pixmap_offset, - offset_bitmap); - pxoffset += pwidth; - pwidth = min ((width-pxoffset), - IMAGE_INSTANCE_PIXMAP_WIDTH (p)); + xdb.xpos = db->xpos + pxoffset; + xdb.ypos = db->ypos + pyoffset; + /* do we need to offset the pixmap vertically? this is necessary + for background pixmaps. */ + xdga.yoffset = xdb.ypos % IMAGE_INSTANCE_PIXMAP_HEIGHT (p); + xdga.xoffset = xdb.xpos % IMAGE_INSTANCE_PIXMAP_WIDTH (p); + /* the width is handled by mswindows_output_pixmap_region */ + mswindows_output_dibitmap (f, p, &xdb, &xdga); + pxoffset += xdga.width; + xdga.width = min ((db->width - pxoffset), + IMAGE_INSTANCE_PIXMAP_WIDTH (p)); } - pyoffset += pheight; - pheight = min ((height-pyoffset), - IMAGE_INSTANCE_PIXMAP_HEIGHT (p)); + pyoffset += xdga.height; + xdga.height = min ((db->height - pyoffset), + IMAGE_INSTANCE_PIXMAP_HEIGHT (p)); } } +/* Output a pixmap at the desired location. + DB normalized display_box. + DGA normalized display_glyph_area. */ static void -mswindows_output_pixmap (struct window *w, struct display_line *dl, - Lisp_Object image_instance, int xpos, int xoffset, - int start_pixpos, int width, face_index findex, - int cursor_start, int cursor_width, int cursor_height, - int offset_bitmap) +mswindows_output_pixmap (struct window *w, Lisp_Object image_instance, + struct display_box *db, struct display_glyph_area *dga, + face_index findex, int cursor_start, int cursor_width, + int cursor_height, int bg_pixmap) { struct frame *f = XFRAME (w->frame); HDC hdc = FRAME_MSWINDOWS_DC (f); @@ -716,100 +707,18 @@ mswindows_output_pixmap (struct window *w, struct display_line *dl, struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); Lisp_Object window; - int lheight = DISPLAY_LINE_HEIGHT (dl); - int pheight = ((int) IMAGE_INSTANCE_PIXMAP_HEIGHT (p) > lheight ? lheight : - IMAGE_INSTANCE_PIXMAP_HEIGHT (p)); - int clip_x, clip_y, clip_width, clip_height; - - /* The pixmap_offset is used to center the pixmap on lines which are - shorter than it is. This results in odd effects when scrolling - pixmaps off of the bottom. Let's try not using it. */ -#if 0 - int pixmap_offset = (int) (IMAGE_INSTANCE_PIXMAP_HEIGHT (p) - lheight) / 2; -#else - int pixmap_offset = 0; -#endif - XSETWINDOW (window, w); - if ((start_pixpos >= 0 && start_pixpos > xpos) || xoffset) - { - if (start_pixpos > xpos && start_pixpos > xpos + width) - return; - - clip_x = xoffset; - clip_width = width; - if (start_pixpos > xpos) - { - clip_x += (start_pixpos - xpos); - clip_width -= (start_pixpos - xpos); - } - } - else - { - clip_x = 0; - clip_width = 0; - } - - /* Place markers for possible future functionality (clipping the top - half instead of the bottom half; think pixel scrolling). */ - clip_y = 0; - clip_height = pheight; - - /* Clear the area the pixmap is going into. The pixmap itself will - always take care of the full width. We don't want to clear where - it is going to go in order to avoid flicker. So, all we have to - take care of is any area above or below the pixmap. */ - /* #### We take a shortcut for now. We know that since we have - pixmap_offset hardwired to 0 that the pixmap is against the top - edge so all we have to worry about is below it. */ - /* #### Unless the pixmap has a mask in which case we have to clear - the whole damn thing since we can't yet clear just the area not - included in the mask. */ - if (((int) (dl->ypos - dl->ascent + pheight) < - (int) (dl->ypos + dl->descent - dl->clip)) - || IMAGE_INSTANCE_MSWINDOWS_MASK (p)) - { - int clear_x, clear_y, clear_width, clear_height; - - if (IMAGE_INSTANCE_MSWINDOWS_MASK (p)) - { - clear_y = dl->ypos - dl->ascent; - clear_height = lheight; - } - else - { - clear_y = dl->ypos - dl->ascent + pheight; - clear_height = lheight - pheight; - } - - if (start_pixpos >= 0 && start_pixpos > xpos) - { - clear_x = start_pixpos; - clear_width = xpos + width - start_pixpos; - } - else - { - clear_x = xpos; - clear_width = width; - } - - if (!offset_bitmap) /* i.e. not a bg pixmap */ - redisplay_clear_region (window, findex, clear_x, clear_y, - clear_width, clear_height); - } - /* Output the pixmap. Have to do this as many times as is required to fill the given area */ mswindows_update_dc (hdc, Qnil, WINDOW_FACE_CACHEL_FOREGROUND (w, findex), WINDOW_FACE_CACHEL_BACKGROUND (w, findex), Qnil); - mswindows_output_dibitmap_region (f, p, xpos - xoffset, - dl->ypos - dl->ascent, - clip_x, clip_y, clip_width, clip_height, - width + xoffset, pheight, pixmap_offset, - offset_bitmap); + if (bg_pixmap) + mswindows_output_dibitmap_region (f, p, db, dga); + else + mswindows_output_dibitmap (f, p, db, dga); } #ifdef HAVE_SCROLLBARS @@ -901,12 +810,11 @@ mswindows_redraw_exposed_window (struct window *w, int x, int y, int width, for (line = 0; line < Dynarr_length (cdla); line++) { struct display_line *cdl = Dynarr_atp (cdla, line); - int top_y = cdl->ypos - cdl->ascent; - int bottom_y = cdl->ypos + cdl->descent; - if (bottom_y >= rect_draw.top) + if (DISPLAY_LINE_YPOS (cdl) + DISPLAY_LINE_HEIGHT (cdl) + >= rect_draw.top) { - if (top_y > rect_draw.bottom) + if (DISPLAY_LINE_YPOS (cdl) > rect_draw.bottom) { if (line == 0) continue; @@ -986,29 +894,47 @@ mswindows_redraw_exposed_area (struct frame *f, int x, int y, int width, int hei ****************************************************************************/ static void mswindows_bevel_area (struct window *w, face_index findex, int x, int y, - int width, int height, int shadow_thickness) + int width, int height, int thickness, + int edges, enum edge_style style) { struct frame *f = XFRAME (w->frame); UINT edge; + UINT border = 0; - if (shadow_thickness < -1) - edge = EDGE_SUNKEN; - else if (shadow_thickness < 0) - edge = BDR_SUNKENINNER; - else if (shadow_thickness == 1) - edge = BDR_RAISEDINNER; - else - edge = EDGE_RAISED; + if (style == EDGE_ETCHED_IN) + edge = EDGE_ETCHED; + else if (style == EDGE_ETCHED_OUT) + edge = EDGE_BUMP; + else if (style == EDGE_BEVEL_IN) + { + if (thickness == 1) + edge = BDR_SUNKENINNER; + else + edge = EDGE_SUNKEN; + } + else /* EDGE_BEVEL_OUT */ + { + if (thickness == 1) + edge = BDR_RAISEDINNER; + else + edge = EDGE_RAISED; + } - if (shadow_thickness < 0) - shadow_thickness = -shadow_thickness; + if (edges & EDGE_TOP) + border |= BF_TOP; + if (edges & EDGE_LEFT) + border |= BF_LEFT; + if (edges & EDGE_BOTTOM) + border |= BF_BOTTOM; + if (edges & EDGE_RIGHT) + border |= BF_RIGHT; { RECT rect = { x, y, x + width, y + height }; Lisp_Object color = WINDOW_FACE_CACHEL_BACKGROUND (w, findex); mswindows_update_dc (FRAME_MSWINDOWS_DC (f), Qnil, Qnil, color, Qnil); - DrawEdge (FRAME_MSWINDOWS_DC (f), &rect, edge, BF_RECT); + DrawEdge (FRAME_MSWINDOWS_DC (f), &rect, edge, border); } } @@ -1141,7 +1067,7 @@ mswindows_output_display_block (struct window *w, struct display_line *dl, int b if (Dynarr_length (buf)) { mswindows_output_string (w, dl, buf, xpos, 0, start_pixpos, width, - findex); + findex, 0, 0, 0, 0); xpos = rb->xpos; width = 0; } @@ -1175,10 +1101,9 @@ mswindows_output_display_block (struct window *w, struct display_line *dl, int b else if (rb->object.chr.ch == '\n') { /* Clear in case a cursor was formerly here. */ - int height = DISPLAY_LINE_HEIGHT (dl); - - redisplay_clear_region (window, findex, xpos, dl->ypos - dl->ascent, - rb->width, height); + redisplay_clear_region (window, findex, xpos, + DISPLAY_LINE_YPOS (dl), + rb->width, DISPLAY_LINE_HEIGHT (dl)); elt++; } } @@ -1214,6 +1139,11 @@ mswindows_output_display_block (struct window *w, struct display_line *dl, int b else if (rb->type == RUNE_DGLYPH) { Lisp_Object instance; + struct display_box db; + struct display_glyph_area dga; + redisplay_calculate_display_boxes (dl, rb->xpos, rb->object.dglyph.xoffset, + start_pixpos, rb->width, + &db, &dga); XSETWINDOW (window, w); instance = glyph_image_instance (rb->object.dglyph.glyph, @@ -1238,17 +1168,17 @@ mswindows_output_display_block (struct window *w, struct display_line *dl, int b else /* #### redisplay-x passes -1 as the width: why ? */ mswindows_output_string (w, dl, buf, xpos, rb->object.dglyph.xoffset, - start_pixpos, rb->width, findex); + start_pixpos, rb->width, findex, + 0, 0, 0, 0); Dynarr_reset (buf); } break; case IMAGE_MONO_PIXMAP: case IMAGE_COLOR_PIXMAP: - mswindows_output_pixmap (w, dl, instance, xpos, - rb->object.dglyph.xoffset, start_pixpos, - rb->width, findex, cursor_start, - cursor_width, cursor_height, 0); + redisplay_output_pixmap (w, instance, &db, &dga, findex, + cursor_start, cursor_width, + cursor_height, 0); if (rb->cursor_type == CURSOR_ON) mswindows_output_cursor (w, dl, xpos, cursor_width, findex, 0, 1); @@ -1259,10 +1189,18 @@ mswindows_output_display_block (struct window *w, struct display_line *dl, int b case IMAGE_SUBWINDOW: case IMAGE_WIDGET: - redisplay_output_subwindow (w, dl, instance, xpos, - rb->object.dglyph.xoffset, start_pixpos, - rb->width, findex, cursor_start, - cursor_width, cursor_height); + redisplay_output_subwindow (w, instance, &db, &dga, findex, + cursor_start, cursor_width, + cursor_height); + if (rb->cursor_type == CURSOR_ON) + mswindows_output_cursor (w, dl, xpos, cursor_width, + findex, 0, 1); + break; + + case IMAGE_LAYOUT: + redisplay_output_layout (w, instance, &db, &dga, findex, + cursor_start, cursor_width, + cursor_height); if (rb->cursor_type == CURSOR_ON) mswindows_output_cursor (w, dl, xpos, cursor_width, findex, 0, 1); @@ -1285,7 +1223,8 @@ mswindows_output_display_block (struct window *w, struct display_line *dl, int b } if (Dynarr_length (buf)) - mswindows_output_string (w, dl, buf, xpos, 0, start_pixpos, width, findex); + mswindows_output_string (w, dl, buf, xpos, 0, start_pixpos, width, findex, + 0, 0, 0, 0); if (dl->modeline && !EQ (Qzero, w->modeline_shadow_thickness) @@ -1400,12 +1339,11 @@ mswindows_clear_region (Lisp_Object locale, struct device* d, struct frame* f, if (!NILP (background_pixmap)) { + struct display_box db = { x, y, width, height }; mswindows_update_dc (FRAME_MSWINDOWS_DC (f), Qnil, fcolor, bcolor, background_pixmap); - mswindows_output_dibitmap_region - ( f, XIMAGE_INSTANCE (background_pixmap), - x, y, 0, 0, 0, 0, width, height, 0, TRUE); + ( f, XIMAGE_INSTANCE (background_pixmap), &db, 0); } else { @@ -1449,4 +1387,6 @@ console_type_create_redisplay_mswindows (void) CONSOLE_HAS_METHOD (mswindows, flash); CONSOLE_HAS_METHOD (mswindows, ring_bell); CONSOLE_HAS_METHOD (mswindows, bevel_area); + CONSOLE_HAS_METHOD (mswindows, output_string); + CONSOLE_HAS_METHOD (mswindows, output_pixmap); } diff --git a/src/redisplay-output.c b/src/redisplay-output.c index ae041e9..06b78b3 100644 --- a/src/redisplay-output.c +++ b/src/redisplay-output.c @@ -2,6 +2,7 @@ Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. Copyright (C) 1995, 1996 Ben Wing. Copyright (C) 1996 Chuck Thompson. + Copyright (C) 1999 Andy Piper. This file is part of XEmacs. @@ -26,6 +27,9 @@ Boston, MA 02111-1307, USA. */ /* Author: Chuck Thompson */ +/* Heavily hacked for modularity, gutter and subwindow support by Andy + Piper. */ + #include #include "lisp.h" @@ -45,6 +49,15 @@ static void redisplay_output_display_block (struct window *w, struct display_lin int block, int start, int end, int start_pixpos, int cursor_start, int cursor_width, int cursor_height); +static void redisplay_normalize_display_box (struct display_box* dest, + struct display_glyph_area* src); +static int redisplay_display_boxes_in_window_p (struct window* w, + struct display_box* db, + struct display_glyph_area* dga); +static void redisplay_clear_clipped_region (Lisp_Object locale, face_index findex, + struct display_box* dest, + struct display_glyph_area* glyphsrc, + int fullheight_p, Lisp_Object); /***************************************************************************** sync_rune_structs @@ -191,15 +204,28 @@ compare_runes (struct window *w, struct rune *crb, struct rune *drb) else if (crb->type == RUNE_CHAR && (crb->object.chr.ch != drb->object.chr.ch)) return 0; - else if (crb->type == RUNE_DGLYPH && - (!EQ (crb->object.dglyph.glyph, drb->object.dglyph.glyph) || - !EQ (crb->object.dglyph.extent, drb->object.dglyph.extent) || - crb->object.dglyph.xoffset != drb->object.dglyph.xoffset)) - return 0; else if (crb->type == RUNE_HLINE && (crb->object.hline.thickness != drb->object.hline.thickness || crb->object.hline.yoffset != drb->object.hline.yoffset)) return 0; + else if (crb->type == RUNE_DGLYPH && + (!EQ (crb->object.dglyph.glyph, drb->object.dglyph.glyph) || + !EQ (crb->object.dglyph.extent, drb->object.dglyph.extent) || + crb->object.dglyph.xoffset != drb->object.dglyph.xoffset)) + return 0; + /* Only check dirtiness if we know something has changed. */ + else if (crb->type == RUNE_DGLYPH && + XFRAME (w->frame)->glyphs_changed) + { + glyph_index gindex = get_glyph_cachel_index (w, drb->object.dglyph.glyph); + /* Although doing the cachel lookup for every comparison is + very expensive.we have to do it to make sure the cache is + up-to-date. */ + if (GLYPH_CACHEL_DIRTYP (w, gindex)) + return 0; + else + return 1; + } else return 1; } @@ -351,8 +377,14 @@ compare_display_blocks (struct window *w, struct display_line *cdl, force = 1; if (f->windows_structure_changed || + /* #### Why is this so? We have face cachels so that we don't + have to recalculate all the display blocks when faces + change. I have fixed this for glyphs and am inclined to think + that faces should "Just Work", but I'm not feeling brave + today. Maybe its because the face cachels represent merged + faces rather than simply instantiations in a particular + domain. */ f->faces_changed || - f->glyphs_changed || cdl->ypos != ddl->ypos || cdl->ascent != ddl->ascent || cdl->descent != ddl->descent || @@ -589,6 +621,7 @@ output_display_line (struct window *w, display_line_dynarr *cdla, (cdl && (cdl->ypos != ddl->ypos || cdl->ascent != ddl->ascent || cdl->descent != ddl->descent || + cdl->top_clip != ddl->top_clip || cdl->clip != ddl->clip))) { int x, y, width, height; @@ -596,9 +629,9 @@ output_display_line (struct window *w, display_line_dynarr *cdla, must_sync = 1; x = start_pixpos; - y = ddl->ypos - ddl->ascent; + y = DISPLAY_LINE_YPOS (ddl); width = min (next_start_pixpos, block_end) - x; - height = ddl->ascent + ddl->descent - ddl->clip; + height = DISPLAY_LINE_HEIGHT (ddl); if (x < ddl->bounds.left_in) { @@ -658,7 +691,11 @@ output_display_line (struct window *w, display_line_dynarr *cdla, region or if it was a block of a different type, then output the entire ddb. Otherwise, compare cdb and ddb and output only the changed region. */ - if (!force && cdb && ddb->type == cdb->type && b == old_b) + if (!force && cdb && ddb->type == cdb->type + /* If there was no buffer being display before the + compare anyway as we might be outputting a gutter. */ + && + (b == old_b || !old_b)) { must_sync |= compare_display_blocks (w, cdl, ddl, old_block, block, start_pixpos, @@ -709,19 +746,23 @@ output_display_line (struct window *w, display_line_dynarr *cdla, if (f->windows_structure_changed || f->faces_changed || clear_border || f->clear) { - int y = ddl->ypos - ddl->ascent; - int height = ddl->ascent + ddl->descent - ddl->clip; + int y = DISPLAY_LINE_YPOS (ddl); + int height = DISPLAY_LINE_HEIGHT (ddl); - if (ddl->modeline) + /* If we are in the gutter then we musn't clear the borders. */ + if (y >= WINDOW_TEXT_TOP (w) && (y + height) <= WINDOW_TEXT_BOTTOM (w)) { - y -= MODELINE_SHADOW_THICKNESS (w); - height += (2 * MODELINE_SHADOW_THICKNESS (w)); + if (ddl->modeline) + { + y -= MODELINE_SHADOW_THICKNESS (w); + height += (2 * MODELINE_SHADOW_THICKNESS (w)); + } + + if (window_is_leftmost (w)) + clear_left_border (w, y, height); + if (window_is_rightmost (w)) + clear_right_border (w, y, height); } - - if (window_is_leftmost (w)) - clear_left_border (w, y, height); - if (window_is_rightmost (w)) - clear_right_border (w, y, height); } if (cdla) @@ -1005,20 +1046,38 @@ redisplay_output_display_block (struct window *w, struct display_line *dl, int b { struct frame *f = XFRAME (w->frame); struct device *d = XDEVICE (f->device); + struct display_block *db = Dynarr_atp (dl->display_blocks, block); + rune_dynarr *rba = db->runes; + struct rune *rb; + int xpos, width; + rb = Dynarr_atp (rba, start); + + if (!rb) + /* Nothing to do so don't do anything. */ + return; + + xpos = max (start_pixpos, rb->xpos); + if (end < 0) + end = Dynarr_length (rba); + + rb = Dynarr_atp (rba, end - 1); + width = rb->xpos + rb->width - xpos; + /* now actually output the block. */ DEVMETH (d, output_display_block, (w, dl, block, start, end, start_pixpos, cursor_start, cursor_width, cursor_height)); } - + /**************************************************************************** redisplay_unmap_subwindows Remove subwindows from the area in the box defined by the given parameters. ****************************************************************************/ -static void redisplay_unmap_subwindows (struct frame* f, int x, int y, int width, int height) +static void redisplay_unmap_subwindows (struct frame* f, int x, int y, int width, int height, + Lisp_Object ignored_window) { int elt; @@ -1031,7 +1090,9 @@ static void redisplay_unmap_subwindows (struct frame* f, int x, int y, int width && cachel->x + cachel->width > x && cachel->x < x + width && - cachel->y + cachel->height > y && cachel->y < y + height) + cachel->y + cachel->height > y && cachel->y < y + height + && + !EQ (cachel->subwindow, ignored_window)) { unmap_subwindow (cachel->subwindow); } @@ -1048,79 +1109,340 @@ void redisplay_unmap_subwindows_maybe (struct frame* f, int x, int y, int width, { if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f))) { - redisplay_unmap_subwindows (f, x, y, width, height); + redisplay_unmap_subwindows (f, x, y, width, height, Qnil); + } +} + +static void redisplay_unmap_subwindows_except_us (struct frame* f, int x, int y, int width, + int height, Lisp_Object subwindow) +{ + if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f))) + { + redisplay_unmap_subwindows (f, x, y, width, height, subwindow); } } /**************************************************************************** redisplay_output_subwindow - output a subwindow. This code borrows heavily from the pixmap stuff, although is much simpler not needing to account for partial pixmaps, backgrounds etc. ****************************************************************************/ void -redisplay_output_subwindow (struct window *w, struct display_line *dl, - Lisp_Object image_instance, int xpos, int xoffset, - int start_pixpos, int width, face_index findex, - int cursor_start, int cursor_width, int cursor_height) +redisplay_output_subwindow (struct window *w, + Lisp_Object image_instance, + struct display_box* db, struct display_glyph_area* dga, + face_index findex, int cursor_start, int cursor_width, + int cursor_height) { struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); Lisp_Object window; + struct display_glyph_area sdga; + + dga->height = IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p); + dga->width = IMAGE_INSTANCE_SUBWINDOW_WIDTH (p); - int lheight = dl->ascent + dl->descent - dl->clip; - int pheight = ((int) IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p) > lheight ? lheight : - IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p)); + /* This makes the glyph area fit into the display area. */ + if (!redisplay_normalize_glyph_area (db, dga)) + return; XSETWINDOW (window, w); - /* Clear the area the subwindow is going into. The subwindow itself - will always take care of the full width. We don't want to clear - where it is going to go in order to avoid flicker. So, all we - have to take care of is any area above or below the subwindow. Of - course this is rubbish if the subwindow has transparent areas - (for instance with frames). */ - /* #### We take a shortcut for now. We know that since we have - subwindow_offset hardwired to 0 that the subwindow is against the top - edge so all we have to worry about is below it. */ - if ((int) (dl->ypos - dl->ascent + pheight) < - (int) (dl->ypos + dl->descent - dl->clip)) + /* Clear the area the subwindow is going into. */ + redisplay_clear_clipped_region (window, findex, + db, dga, 0, image_instance); + + /* This shrinks the display box to exactly enclose the glyph + area. */ + redisplay_normalize_display_box (db, dga); + + /* if we can't view the whole window we can't view any of it. We + have to be careful here since we may be being asked to display + part of a subwindow, the rest of which is on-screen as well. We + need to allow this case and map the entire subwindow. We also + need to be careful since the subwindow could be outside the + window in the gutter or modeline - we also need to allow these + cases.*/ + sdga.xoffset = -dga->xoffset; + sdga.yoffset = -dga->yoffset; + sdga.height = IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p); + sdga.width = IMAGE_INSTANCE_SUBWINDOW_WIDTH (p); + + if (redisplay_display_boxes_in_window_p (w, db, &sdga) < 0) + { + map_subwindow (image_instance, db->xpos, db->ypos, dga); + } + else { - int clear_x, clear_width; + sdga.xoffset = sdga.yoffset = 0; + map_subwindow (image_instance, db->xpos - dga->xoffset, + db->ypos - dga->yoffset, &sdga); + } +} + +/**************************************************************************** + redisplay_output_layout + + Output a widget hierarchy. This can safely call itself recursively. + ****************************************************************************/ +void +redisplay_output_layout (struct window *w, + Lisp_Object image_instance, + struct display_box* db, struct display_glyph_area* dga, + face_index findex, int cursor_start, int cursor_width, + int cursor_height) +{ + struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); + Lisp_Object window, rest; + Emchar_dynarr *buf = Dynarr_new (Emchar); + struct frame *f = XFRAME (w->frame); + struct device *d = XDEVICE (f->device); + int layout_height, layout_width; + /* We bogusly don't take f->extents_changed and f->glyphs_changed + into account. This is because if we do we always redisplay the + entire layout. So far I have seen no ill effects to we'll see. */ + int frame_changed = (f->buffers_changed || + f->clip_changed || + f->faces_changed || + f->frame_changed || + f->modeline_changed || + f->subwindows_changed || + f->windows_changed || + f->windows_structure_changed); - int clear_y = dl->ypos - dl->ascent + pheight; - int clear_height = lheight - pheight; + XSETWINDOW (window, w); - if (start_pixpos >= 0 && start_pixpos > xpos) + layout_height = glyph_height (image_instance, Qnil, findex, window); + layout_width = glyph_width (image_instance, Qnil, findex, window); + + dga->height = layout_height; + dga->width = layout_width; + + /* This makes the glyph area fit into the display area. */ + if (!redisplay_normalize_glyph_area (db, dga)) + return; + + /* Highly dodgy optimization. We want to only output the whole + layout if we really have to. */ + if (frame_changed || IMAGE_INSTANCE_DIRTYP (p)) + { + /* First clear the area we are drawing into. This is the easiest + thing to do since we have many gaps that we have to make sure are + filled in. */ + redisplay_clear_clipped_region (window, findex, db, dga, 1, Qnil); + + /* Output a border if required */ + if (!NILP (IMAGE_INSTANCE_LAYOUT_BORDER (p))) { - clear_x = start_pixpos; - clear_width = xpos + width - start_pixpos; + int edges = 0; + enum edge_style style; + int ypos = db->ypos; + int height = dga->height; + + if (dga->xoffset >= 0) + edges |= EDGE_LEFT; + if (dga->width - dga->xoffset == layout_width) + edges |= EDGE_RIGHT; + if (dga->yoffset >= 0) + edges |= EDGE_TOP; + if (dga->height - dga->yoffset == layout_height) + edges |= EDGE_BOTTOM; + + if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_in)) + style = EDGE_ETCHED_IN; + else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qetched_out)) + style = EDGE_ETCHED_OUT; + else if (EQ (IMAGE_INSTANCE_LAYOUT_BORDER (p), Qbevel_in)) + style = EDGE_BEVEL_IN; + else if (INTP (IMAGE_INSTANCE_LAYOUT_BORDER (p))) + { + style = EDGE_ETCHED_IN; + if (edges & EDGE_TOP) + { + ypos += XINT (IMAGE_INSTANCE_LAYOUT_BORDER (p)); + height -= XINT (IMAGE_INSTANCE_LAYOUT_BORDER (p)); + } + } + else + style = EDGE_BEVEL_OUT; + + MAYBE_DEVMETH (d, bevel_area, + (w, findex, db->xpos, + ypos, + dga->width, height, 2, edges, style)); } - else + } + + /* This shrinks the display box to exactly enclose the glyph + area. */ + redisplay_normalize_display_box (db, dga); + + /* Flip through the widgets in the layout displaying as necessary */ + LIST_LOOP (rest, IMAGE_INSTANCE_LAYOUT_CHILDREN (p)) + { + Lisp_Object child = XCAR (rest); + + struct display_box cdb; + /* For losing HP-UX */ + cdb.xpos = db->xpos; + cdb.ypos = db->ypos; + cdb.width = db->width; + cdb.height = db->height; + + /* First determine if the image is visible at all */ + if (IMAGE_INSTANCEP (child)) { - clear_x = xpos; - clear_width = width; + struct Lisp_Image_Instance* childii = XIMAGE_INSTANCE (child); + /* The enclosing layout offsets are +ve at this point */ + struct display_glyph_area cdga; + cdga.xoffset = IMAGE_INSTANCE_XOFFSET (childii) - dga->xoffset; + cdga.yoffset = IMAGE_INSTANCE_YOFFSET (childii) - dga->yoffset; + cdga.width = glyph_width (child, Qnil, findex, window); + cdga.height = glyph_height (child, Qnil, findex, window); + + /* Although normalization is done by the output routines + we have to do it here so that they don't try and + clear all of db. This is true below also. */ + if (redisplay_normalize_glyph_area (&cdb, &cdga)) + { + redisplay_normalize_display_box (&cdb, &cdga); + /* Since the display boxes will now be totally in the + window if they are visible at all we can now check this easily. */ + if (cdb.xpos < db->xpos || cdb.ypos < db->ypos + || cdb.xpos + cdb.width > db->xpos + db->width + || cdb.ypos + cdb.height > db->ypos + db->height) + continue; + /* We have to invert the offset here as normalization + will have made them positive which the output + routines will treat as a truely +ve offset. */ + cdga.xoffset = -cdga.xoffset; + cdga.yoffset = -cdga.yoffset; + + switch (IMAGE_INSTANCE_TYPE (childii)) + { + case IMAGE_TEXT: + { + /* #### This is well hacked and could use some + generalisation.*/ + if (redisplay_normalize_glyph_area (&cdb, &cdga) + && + (frame_changed || IMAGE_INSTANCE_DIRTYP (childii))) + { + struct display_line dl; /* this is fake */ + Lisp_Object string = + IMAGE_INSTANCE_TEXT_STRING (childii); + convert_bufbyte_string_into_emchar_dynarr + (XSTRING_DATA (string), XSTRING_LENGTH (string), buf); + + redisplay_normalize_display_box (&cdb, &cdga); + /* Offsets are now +ve again so be careful + when fixing up the display line. */ + xzero (dl); + /* Munge boxes into display lines. */ + dl.ypos = (cdb.ypos - cdga.yoffset) + + glyph_ascent (child, Qnil, findex, window); + dl.ascent = glyph_ascent (child, Qnil, findex, window); + dl.descent = glyph_descent (child, Qnil, findex, window); + dl.top_clip = cdga.yoffset; + dl.clip = (dl.ypos + dl.descent) - (cdb.ypos + cdb.height); + /* output_string doesn't understand offsets in + the same way as other routines - we have to + add the offset to the width so that we + output the full string. */ + MAYBE_DEVMETH (d, output_string, (w, &dl, buf, cdb.xpos, + cdga.xoffset, cdb.xpos, + cdga.width + cdga.xoffset, + findex, 0, 0, 0, 0)); + Dynarr_reset (buf); + } + } + break; + + case IMAGE_MONO_PIXMAP: + case IMAGE_COLOR_PIXMAP: + if (frame_changed || IMAGE_INSTANCE_DIRTYP (childii)) + redisplay_output_pixmap (w, child, &cdb, &cdga, findex, + 0, 0, 0, 0); + break; + + case IMAGE_WIDGET: + case IMAGE_SUBWINDOW: + if (frame_changed || IMAGE_INSTANCE_DIRTYP (childii)) + redisplay_output_subwindow (w, child, &cdb, &cdga, findex, + 0, 0, 0); + break; + + case IMAGE_LAYOUT: + redisplay_output_layout (w, child, &cdb, &cdga, findex, + 0, 0, 0); + break; + + case IMAGE_NOTHING: + /* nothing is as nothing does */ + break; + + case IMAGE_POINTER: + default: + abort (); + } + } } - - redisplay_clear_region (window, findex, clear_x, clear_y, - clear_width, clear_height); } -#if 0 - redisplay_clear_region (window, findex, xpos - xoffset, dl->ypos - dl->ascent, - width, lheight); -#endif - /* if we can't view the whole window we can't view any of it */ - if (IMAGE_INSTANCE_SUBWINDOW_HEIGHT (p) > lheight - || - IMAGE_INSTANCE_SUBWINDOW_WIDTH (p) > width) + Dynarr_free (buf); +} + +/**************************************************************************** + redisplay_output_pixmap + + + output a pixmap. + ****************************************************************************/ +void +redisplay_output_pixmap (struct window *w, + Lisp_Object image_instance, + struct display_box* db, struct display_glyph_area* dga, + face_index findex, int cursor_start, int cursor_width, + int cursor_height, int offset_bitmap) +{ + struct frame *f = XFRAME (w->frame); + struct device *d = XDEVICE (f->device); + struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); + Lisp_Object window; + XSETWINDOW (window, w); + + dga->height = IMAGE_INSTANCE_PIXMAP_HEIGHT (p); + dga->width = IMAGE_INSTANCE_PIXMAP_WIDTH (p); + + /* This makes the glyph area fit into the display area. */ + if (!redisplay_normalize_glyph_area (db, dga)) + return; + + /* Clear the area the pixmap is going into. The pixmap itself will + always take care of the full width. We don't want to clear where + it is going to go in order to avoid flicker. So, all we have to + take care of is any area above or below the pixmap. If the pixmap + has a mask in which case we have to clear the whole damn thing + since we can't yet clear just the area not included in the + mask. */ + if (!offset_bitmap) { - redisplay_clear_region (window, findex, xpos - xoffset, dl->ypos - dl->ascent, - width, lheight); - unmap_subwindow (image_instance); + redisplay_clear_clipped_region (window, findex, + db, dga, + (int)IMAGE_INSTANCE_PIXMAP_MASK (p), + Qnil); + + /* This shrinks the display box to exactly enclose the glyph + area. */ + redisplay_normalize_display_box (db, dga); } - else - map_subwindow (image_instance, xpos - xoffset, dl->ypos - dl->ascent); + assert (db->xpos >= 0 && db->ypos >= 0); + + MAYBE_DEVMETH (d, output_pixmap, (w, image_instance, + db, dga, + findex, cursor_start, + cursor_width, cursor_height, + offset_bitmap)); } /**************************************************************************** @@ -1159,10 +1481,7 @@ redisplay_clear_region (Lisp_Object locale, face_index findex, int x, int y, d = XDEVICE (f->device); /* if we have subwindows in the region we have to unmap them */ - if (Dynarr_length (FRAME_SUBWINDOW_CACHE (f))) - { - redisplay_unmap_subwindows (f, x, y, width, height); - } + redisplay_unmap_subwindows_maybe (f, x, y, width, height); /* #### This isn't quite right for when this function is called from the toolbar code. */ @@ -1228,6 +1547,224 @@ redisplay_clear_region (Lisp_Object locale, face_index findex, int x, int y, (locale, d, f, findex, x, y, width, height, fcolor, bcolor, background_pixmap)); } +/**************************************************************************** + redisplay_clear_clipped_region + + Clear the area in the dest display_box not covered by the src + display_glyph_area using the given face. This is a common occurance + for images shorter than the display line. Clipping can be played + around with by altering these. glyphsrc should be normalized. + ****************************************************************************/ +static void +redisplay_clear_clipped_region (Lisp_Object window, face_index findex, + struct display_box* dest, struct display_glyph_area* glyphsrc, + int fullheight_p, Lisp_Object ignored_subwindow) +{ + /* assume dest->xpos >= 0 */ + int clear_x; + struct frame* f = XFRAME (XWINDOW (window)->frame); + + if (glyphsrc->xoffset > 0) + { + clear_x = dest->xpos + glyphsrc->xoffset; + } + else + { + clear_x = dest->xpos; + } + + /* If we need the whole height cleared then just do it. */ + if (fullheight_p) + { + redisplay_clear_region (window, findex, clear_x, dest->ypos, + glyphsrc->width, dest->height); + } + else + { + int yoffset = (glyphsrc->yoffset > 0 ? glyphsrc->yoffset : 0); + + /* We need to make sure that subwindows are unmapped from the + whole area. */ + redisplay_unmap_subwindows_except_us (f, clear_x, dest->ypos, + glyphsrc->width, dest->height, + ignored_subwindow); + /* first the top box */ + if (yoffset > 0) + { + redisplay_clear_region (window, findex, clear_x, dest->ypos, + glyphsrc->width, yoffset); + + } + /* Then the bottom box */ + if (yoffset + glyphsrc->height < dest->height) + { + redisplay_clear_region (window, findex, clear_x, + dest->ypos + yoffset + glyphsrc->height, + glyphsrc->width, + dest->height - (yoffset + glyphsrc->height)); + + } + } +} + +/***************************************************************************** + redisplay_normalize_glyph_area + redisplay_normalize_display_box + + Calculate the visible box for displaying src in dest. + ****************************************************************************/ +int +redisplay_normalize_glyph_area (struct display_box* dest, + struct display_glyph_area* glyphsrc) +{ + if (dest->xpos + glyphsrc->xoffset > dest->xpos + dest->width + || + dest->ypos + glyphsrc->yoffset > dest->ypos + dest->height + || + -glyphsrc->xoffset >= glyphsrc->width + || + -glyphsrc->yoffset >= glyphsrc->height) + { + /* It's all clipped out */ + return 0; + } + + /* Horizontal offsets. This works because xoffset can be -ve as well as +ve */ + if (dest->xpos + glyphsrc->xoffset + glyphsrc->width > dest->xpos + dest->width) + { + if (glyphsrc->xoffset > 0) + glyphsrc->width = dest->width - glyphsrc->xoffset; + else + glyphsrc->width = dest->width; + } + + if (glyphsrc->xoffset < 0) + glyphsrc->width += glyphsrc->xoffset; + + /* Vertical offsets. This works because yoffset can be -ve as well as +ve */ + if (dest->ypos + glyphsrc->yoffset + glyphsrc->height > dest->ypos + dest->height) + { + if (glyphsrc->yoffset > 0) + glyphsrc->height = dest->height - glyphsrc->yoffset; + else + glyphsrc->height = dest->height; + } + + if (glyphsrc->yoffset < 0) + glyphsrc->height += glyphsrc->yoffset; + + return 1; +} + +static void +redisplay_normalize_display_box (struct display_box* dest, + struct display_glyph_area* glyphsrc) +{ + /* Adjust the destination area. At the end of this the destination + area will exactly enclose the glyph area. The only remaining + adjustment will be offsets into the glyph area. */ + + /* Horizontal adjustment. */ + if (glyphsrc->xoffset > 0) + { + dest->xpos += glyphsrc->xoffset; + dest->width -= glyphsrc->xoffset; + glyphsrc->xoffset = 0; + } + else + glyphsrc->xoffset = -glyphsrc->xoffset; + + if (glyphsrc->width < dest->width) + dest->width = glyphsrc->width; + + /* Vertical adjustment. */ + if (glyphsrc->yoffset > 0) + { + dest->ypos += glyphsrc->yoffset; + dest->height -= glyphsrc->yoffset; + glyphsrc->yoffset = 0; + } + else + glyphsrc->yoffset = -glyphsrc->yoffset; + + if (glyphsrc->height < dest->height) + dest->height = glyphsrc->height; +} + +/***************************************************************************** + redisplay_display_boxes_in_window_p + + Determine whether the require display_glyph_area is completely inside + the window. 0 means the display_box is not in the window. 1 means the + display_box and the display_glyph_area are in the window. -1 means + the display_box is in the window but the display_glyph_area is not. + ****************************************************************************/ +static int +redisplay_display_boxes_in_window_p (struct window* w, + struct display_box* db, + struct display_glyph_area* dga) +{ + int left = WINDOW_TEXT_LEFT (w); + int right = WINDOW_TEXT_RIGHT (w); + int top = WINDOW_TEXT_TOP (w); + int bottom = WINDOW_TEXT_BOTTOM (w); + + if (db->xpos < left || db->ypos < top + || db->xpos + db->width > right + || db->ypos + db->height > bottom) + /* We are not displaying in a window at all */ + return 0; + + if (db->xpos + dga->xoffset >= left + && + db->ypos + dga->yoffset >= top + && + db->xpos + dga->xoffset + dga->width <= right + && + db->ypos + dga->yoffset + dga->height <= bottom) + return 1; + + return -1; +} + +/***************************************************************************** + redisplay_calculate_display_boxes + + Convert from rune/display_line co-ordinates to display_box + co-ordinates. + ****************************************************************************/ +int +redisplay_calculate_display_boxes (struct display_line *dl, int xpos, + int xoffset, int start_pixpos, int width, + struct display_box* dest, + struct display_glyph_area* src) +{ + dest->xpos = xpos; + dest->ypos = DISPLAY_LINE_YPOS (dl); + dest->width = width; + dest->height = DISPLAY_LINE_HEIGHT (dl); + + src->xoffset = -xoffset; + src->yoffset = -dl->top_clip; + src->width = 0; + src->height = 0; + + if (start_pixpos >=0 && start_pixpos > xpos) + { + /* Oops, we're asking for a start outside of the displayable + area. */ + if (start_pixpos > xpos + width) + return 0; + dest->xpos = start_pixpos; + dest->width -= (start_pixpos - xpos); + /* Offsets are -ve when we want to clip pixels off the displayed + glyph. */ + src->xoffset -= (start_pixpos - xpos); + } + + return 1; +} + /***************************************************************************** redisplay_clear_top_of_window @@ -1283,7 +1820,6 @@ redisplay_clear_to_window_end (struct window *w, int ypos1, int ypos2) if (height) { - struct frame *f = XFRAME (w->frame); Lisp_Object window; int bflag = 0 ; /* (window_needs_vertical_divider (w) ? 0 : 1);*/ layout_bounds bounds; @@ -1332,7 +1868,6 @@ redisplay_clear_bottom_of_window (struct window *w, display_line_dynarr *ddla, int min_start, int max_end) { struct frame *f = XFRAME (w->frame); - struct device *d = XDEVICE (f->device); int ypos1, ypos2; int ddla_len = Dynarr_length (ddla); @@ -1684,6 +2219,7 @@ bevel_modeline (struct window *w, struct display_line *dl) struct device *d = XDEVICE (f->device); int x, y, width, height; int shadow_thickness = MODELINE_SHADOW_THICKNESS (w); + enum edge_style style; x = WINDOW_MODELINE_LEFT (w); width = WINDOW_MODELINE_RIGHT (w) - x; @@ -1691,8 +2227,15 @@ bevel_modeline (struct window *w, struct display_line *dl) height = dl->ascent + dl->descent + 2 * shadow_thickness; if (XINT (w->modeline_shadow_thickness) < 0) - shadow_thickness = - shadow_thickness; + { + style = EDGE_BEVEL_IN; + } + else + { + style = EDGE_BEVEL_OUT; + } MAYBE_DEVMETH (d, bevel_area, - (w, MODELINE_INDEX, x, y, width, height, shadow_thickness)); + (w, MODELINE_INDEX, x, y, width, height, shadow_thickness, + EDGE_ALL, style)); } diff --git a/src/redisplay-tty.c b/src/redisplay-tty.c index 08899fa..bb4c243 100644 --- a/src/redisplay-tty.c +++ b/src/redisplay-tty.c @@ -392,6 +392,7 @@ tty_output_display_block (struct window *w, struct display_line *dl, int block, case IMAGE_COLOR_PIXMAP: case IMAGE_SUBWINDOW: case IMAGE_WIDGET: + case IMAGE_LAYOUT: /* just do nothing here */ break; @@ -464,7 +465,7 @@ tty_output_vertical_divider (struct window *w, int clear) static void tty_clear_region (Lisp_Object window, struct device* d, struct frame * f, face_index findex, int x, int y, - int width, int height, Lisp_Object fcolor, Lisp_Object bcolor, + int width, int height, Lisp_Object fcolor, Lisp_Object bcolor, Lisp_Object background_pixmap) { struct console *c = XCONSOLE (FRAME_CONSOLE (f)); @@ -949,11 +950,11 @@ tty_redisplay_shutdown (struct console *c) { Lisp_Object dev = CONSOLE_SELECTED_DEVICE (c); - if (!GC_NILP (dev)) + if (!NILP (dev)) { Lisp_Object frm = DEVICE_SELECTED_FRAME (XDEVICE (dev)); - if (!GC_NILP (frm)) + if (!NILP (frm)) { struct frame *f = XFRAME (frm); @@ -1304,7 +1305,8 @@ init_tty_for_redisplay (struct device *d, char *terminal_type) struct fkey_table { - CONST char *cap, *name; + CONST char *cap; + CONST char *name; }; /* Termcap capability names that correspond directly to X keysyms. @@ -1444,22 +1446,18 @@ term_get_fkeys_1 (Lisp_Object function_key_map) describes F10, whereas othertimes it describes F0 and "k;" describes F10. We will attempt to politely accommodate both systems by testing for "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10. - */ + */ { - char *k_semi = tgetstr ("k;", address); - char *k0 = tgetstr ("k0", address); - CONST char *k0_name = "f10"; + CONST char *k_semi = tgetstr ("k;", address); + CONST char *k0 = tgetstr ("k0", address); if (k_semi) - { - Fdefine_key (function_key_map, build_ext_string (k_semi, FORMAT_BINARY), - vector1 (intern ("f10"))); - k0_name = "f0"; - } + Fdefine_key (function_key_map, build_ext_string (k_semi, FORMAT_BINARY), + vector1 (intern ("f10"))); if (k0) Fdefine_key (function_key_map, build_ext_string (k0, FORMAT_BINARY), - vector1 (intern (k0_name))); + vector1 (intern (k_semi ? "f0" : "f10"))); } /* Set up cookies for numbered function keys above f10. */ @@ -1487,42 +1485,40 @@ term_get_fkeys_1 (Lisp_Object function_key_map) } } } - } + } /* * Various mappings to try and get a better fit. */ - { -#define CONDITIONAL_REASSIGN(cap1, cap2, sym) \ - if (!tgetstr (cap1, address)) \ - { \ - char *sequence = tgetstr (cap2, address); \ - if (sequence) \ - Fdefine_key (function_key_map, \ - build_ext_string (sequence, FORMAT_BINARY), \ - vector1 (intern (sym))); \ - } +#define CONDITIONAL_REASSIGN(cap1, cap2, keyname) \ + if (!tgetstr (cap1, address)) \ + { \ + char *sequence = tgetstr (cap2, address); \ + if (sequence) \ + Fdefine_key (function_key_map, \ + build_ext_string (sequence, FORMAT_BINARY), \ + vector1 (intern (keyname))); \ + } - /* if there's no key_next keycap, map key_npage to `next' keysym */ - CONDITIONAL_REASSIGN ("%5", "kN", "next"); - /* if there's no key_prev keycap, map key_ppage to `previous' keysym */ - CONDITIONAL_REASSIGN ("%8", "kP", "prior"); - /* if there's no key_dc keycap, map key_ic to `insert' keysym */ - CONDITIONAL_REASSIGN ("kD", "kI", "insert"); - - /* IBM has their own non-standard dialect of terminfo. - If the standard name isn't found, try the IBM name. */ - CONDITIONAL_REASSIGN ("kB", "KO", "backtab"); - CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */ - CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */ - CONDITIONAL_REASSIGN ("%7", "ki", "menu"); - CONDITIONAL_REASSIGN ("@7", "kw", "end"); - CONDITIONAL_REASSIGN ("F1", "k<", "f11"); - CONDITIONAL_REASSIGN ("F2", "k>", "f12"); - CONDITIONAL_REASSIGN ("%1", "kq", "help"); - CONDITIONAL_REASSIGN ("*6", "kU", "select"); + /* if there's no key_next keycap, map key_npage to `next' keysym */ + CONDITIONAL_REASSIGN ("%5", "kN", "next"); + /* if there's no key_prev keycap, map key_ppage to `previous' keysym */ + CONDITIONAL_REASSIGN ("%8", "kP", "prior"); + /* if there's no key_dc keycap, map key_ic to `insert' keysym */ + CONDITIONAL_REASSIGN ("kD", "kI", "insert"); + + /* IBM has their own non-standard dialect of terminfo. + If the standard name isn't found, try the IBM name. */ + CONDITIONAL_REASSIGN ("kB", "KO", "backtab"); + CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */ + CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */ + CONDITIONAL_REASSIGN ("%7", "ki", "menu"); + CONDITIONAL_REASSIGN ("@7", "kw", "end"); + CONDITIONAL_REASSIGN ("F1", "k<", "f11"); + CONDITIONAL_REASSIGN ("F2", "k>", "f12"); + CONDITIONAL_REASSIGN ("%1", "kq", "help"); + CONDITIONAL_REASSIGN ("*6", "kU", "select"); #undef CONDITIONAL_REASSIGN - } return Qnil; } diff --git a/src/redisplay-x.c b/src/redisplay-x.c index cf1766e..d599c91 100644 --- a/src/redisplay-x.c +++ b/src/redisplay-x.c @@ -54,17 +54,10 @@ Boston, MA 02111-1307, USA. */ #endif /* Number of pixels below each line. */ -/* #### implement me */ -int x_interline_space; +int x_interline_space; /* #### implement me */ #define EOL_CURSOR_WIDTH 5 -static void x_output_pixmap (struct window *w, struct display_line *dl, - Lisp_Object image_instance, int xpos, - int xoffset, - int start_pixpos, int width, face_index findex, - int cursor_start, int cursor_width, - int cursor_height); static void x_output_vertical_divider (struct window *w, int clear); static void x_output_blank (struct window *w, struct display_line *dl, struct rune *rb, int start_pixpos, @@ -79,7 +72,6 @@ static void x_output_eol_cursor (struct window *w, struct display_line *dl, int xpos, face_index findex); static void x_clear_frame (struct frame *f); static void x_clear_frame_windows (Lisp_Object window); -void bevel_modeline (struct window *w, struct display_line *dl); /* Note: We do not use the Xmb*() functions and XFontSets. @@ -408,10 +400,10 @@ x_output_display_block (struct window *w, struct display_line *dl, int block, else if (rb->object.chr.ch == '\n') { /* Clear in case a cursor was formerly here. */ - int height = dl->ascent + dl->descent - dl->clip; - - redisplay_clear_region (window, findex, xpos, dl->ypos - dl->ascent, - rb->width, height); + redisplay_clear_region (window, findex, xpos, + DISPLAY_LINE_YPOS (dl), + rb->width, + DISPLAY_LINE_HEIGHT (dl)); elt++; } } @@ -445,6 +437,11 @@ x_output_display_block (struct window *w, struct display_line *dl, int block, else if (rb->type == RUNE_DGLYPH) { Lisp_Object instance; + struct display_box dbox; + struct display_glyph_area dga; + redisplay_calculate_display_boxes (dl, rb->xpos, rb->object.dglyph.xoffset, + start_pixpos, rb->width, + &dbox, &dga); XSETWINDOW (window, w); instance = glyph_image_instance (rb->object.dglyph.glyph, @@ -475,26 +472,29 @@ x_output_display_block (struct window *w, struct display_line *dl, int block, case IMAGE_MONO_PIXMAP: case IMAGE_COLOR_PIXMAP: - x_output_pixmap (w, dl, instance, xpos, - rb->object.dglyph.xoffset, start_pixpos, - rb->width, findex, cursor_start, - cursor_width, cursor_height); + redisplay_output_pixmap (w, instance, &dbox, &dga, findex, + cursor_start, cursor_width, + cursor_height, 0); break; - case IMAGE_POINTER: - abort (); - case IMAGE_WIDGET: case IMAGE_SUBWINDOW: - redisplay_output_subwindow (w, dl, instance, xpos, - rb->object.dglyph.xoffset, start_pixpos, - rb->width, findex, cursor_start, - cursor_width, cursor_height); + redisplay_output_subwindow (w, instance, &dbox, &dga, findex, + cursor_start, cursor_width, + cursor_height); + break; + + case IMAGE_LAYOUT: + redisplay_output_layout (w, instance, &dbox, &dga, findex, + cursor_start, cursor_width, + cursor_height); + break; case IMAGE_NOTHING: /* nothing is as nothing does */ break; + case IMAGE_POINTER: default: abort (); } @@ -531,7 +531,7 @@ x_output_display_block (struct window *w, struct display_line *dl, int block, static void x_bevel_area (struct window *w, face_index findex, int x, int y, int width, int height, - int shadow_thickness) + int shadow_thickness, int edges, enum edge_style style) { struct frame *f = XFRAME (w->frame); struct device *d = XDEVICE (f->device); @@ -549,6 +549,7 @@ x_bevel_area (struct window *w, face_index findex, int flip_gcs = 0; unsigned long mask; + assert (shadow_thickness >=0); memset (&gcv, ~0, sizeof (XGCValues)); tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, findex); @@ -618,24 +619,33 @@ x_bevel_area (struct window *w, face_index findex, gcv.foreground = background_pixel; background_gc = gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv, mask); - /* possibly revert the GC's in case the shadow thickness is < 0. - This will give a depressed look to the divider */ - if (shadow_thickness < 0) + /* possibly revert the GC's This will give a depressed look to the + divider */ + if (style == EDGE_ETCHED_IN || style == EDGE_BEVEL_IN) { GC temp; temp = top_shadow_gc; top_shadow_gc = bottom_shadow_gc; bottom_shadow_gc = temp; - - /* better avoid a Bad Address XLib error ;-) */ - shadow_thickness = - shadow_thickness; } + if (style == EDGE_ETCHED_IN || style == EDGE_ETCHED_OUT) + shadow_thickness /= 2; + /* Draw the shadows around the divider line */ x_output_shadows (f, x, y, width, height, top_shadow_gc, bottom_shadow_gc, - background_gc, shadow_thickness); + background_gc, shadow_thickness, edges); + + if (style == EDGE_ETCHED_IN || style == EDGE_ETCHED_OUT) + { + /* Draw the shadows around the divider line */ + x_output_shadows (f, x + shadow_thickness, y + shadow_thickness, + width - 2*shadow_thickness, height - 2*shadow_thickness, + bottom_shadow_gc, top_shadow_gc, + background_gc, shadow_thickness, edges); + } } /***************************************************************************** @@ -803,7 +813,7 @@ x_output_string (struct window *w, struct display_line *dl, if (width < 0) width = x_text_width (f, cachel, Dynarr_atp (buf, 0), Dynarr_length (buf)); - height = dl->ascent + dl->descent - dl->clip; + height = DISPLAY_LINE_HEIGHT (dl); /* Regularize the variables passed in. */ @@ -816,6 +826,10 @@ x_output_string (struct window *w, struct display_line *dl, xpos -= xoffset; + /* make sure the area we are about to display is subwindow free. */ + redisplay_unmap_subwindows_maybe (f, clip_start, DISPLAY_LINE_YPOS (dl), + clip_end - clip_start, DISPLAY_LINE_HEIGHT (dl)); + nruns = separate_textual_runs (text_storage, runs, Dynarr_atp (buf, 0), Dynarr_length (buf)); @@ -860,7 +874,7 @@ x_output_string (struct window *w, struct display_line *dl, if (bgc) XFillRectangle (dpy, x_win, bgc, clip_start, - dl->ypos - dl->ascent, clip_end - clip_start, + DISPLAY_LINE_YPOS (dl), clip_end - clip_start, height); for (i = 0; i < nruns; i++) @@ -881,7 +895,7 @@ x_output_string (struct window *w, struct display_line *dl, the given font. It is possible that a font is being displayed on a line taller than it is, so this would cause us to fail to clear some areas. */ - if ((int) fi->height < (int) (height + dl->clip)) + if ((int) fi->height < (int) (height + dl->clip + dl->top_clip)) { int clear_start = max (xpos, clip_start); int clear_end = min (xpos + this_width, clip_end); @@ -892,8 +906,8 @@ x_output_string (struct window *w, struct display_line *dl, ypos1_string = dl->ypos - fi->ascent; ypos2_string = dl->ypos + fi->descent; - ypos1_line = dl->ypos - dl->ascent; - ypos2_line = dl->ypos + dl->descent - dl->clip; + ypos1_line = DISPLAY_LINE_YPOS (dl); + ypos2_line = ypos1_line + DISPLAY_LINE_HEIGHT (dl); /* Make sure we don't clear below the real bottom of the line. */ @@ -919,7 +933,7 @@ x_output_string (struct window *w, struct display_line *dl, else { redisplay_clear_region (window, findex, clear_start, - dl->ypos - dl->ascent, clear_end - clear_start, + DISPLAY_LINE_YPOS (dl), clear_end - clear_start, height); } } @@ -952,7 +966,7 @@ x_output_string (struct window *w, struct display_line *dl, clip_box[0].width = clip_end - clip_start; clip_box[0].height = height; - XSetClipRectangles (dpy, gc, clip_start, dl->ypos - dl->ascent, + XSetClipRectangles (dpy, gc, clip_start, DISPLAY_LINE_YPOS (dl), clip_box, 1, Unsorted); } @@ -1052,7 +1066,7 @@ x_output_string (struct window *w, struct display_line *dl, clip_box[0].width = cursor_width; clip_box[0].height = height; - XSetClipRectangles (dpy, cgc, cursor_start, dl->ypos - dl->ascent, + XSetClipRectangles (dpy, cgc, cursor_start, DISPLAY_LINE_YPOS (dl), clip_box, 1, Unsorted); if (runs[i].dimension == 1) @@ -1112,12 +1126,12 @@ x_output_string (struct window *w, struct display_line *dl, tmp_y = dl->ypos - bogusly_obtained_ascent_value; tmp_height = cursor_height; - if (tmp_y + tmp_height > (int) (dl->ypos - dl->ascent + height)) + if (tmp_y + tmp_height > (int) (DISPLAY_LINE_YPOS(dl) + height)) { - tmp_y = dl->ypos - dl->ascent + height - tmp_height; - if (tmp_y < (int) (dl->ypos - dl->ascent)) - tmp_y = dl->ypos - dl->ascent; - tmp_height = dl->ypos - dl->ascent + height - tmp_y; + tmp_y = DISPLAY_LINE_YPOS (dl) + height - tmp_height; + if (tmp_y < (int) DISPLAY_LINE_YPOS (dl)) + tmp_y = DISPLAY_LINE_YPOS (dl); + tmp_height = DISPLAY_LINE_YPOS (dl) + height - tmp_y; } if (need_clipping) @@ -1153,9 +1167,9 @@ x_output_string (struct window *w, struct display_line *dl, void x_output_x_pixmap (struct frame *f, struct Lisp_Image_Instance *p, int x, - int y, int clip_x, int clip_y, int clip_width, - int clip_height, int width, int height, int pixmap_offset, - unsigned long fg, unsigned long bg, GC override_gc) + int y, int xoffset, int yoffset, + int width, int height, unsigned long fg, unsigned long bg, + GC override_gc) { struct device *d = XDEVICE (f->device); Display *dpy = DEVICE_X_DISPLAY (d); @@ -1164,7 +1178,6 @@ x_output_x_pixmap (struct frame *f, struct Lisp_Image_Instance *p, int x, GC gc; XGCValues gcv; unsigned long pixmap_mask; - int need_clipping = (clip_x || clip_y); if (!override_gc) { @@ -1178,17 +1191,16 @@ x_output_x_pixmap (struct frame *f, struct Lisp_Image_Instance *p, int x, { gcv.function = GXcopy; gcv.clip_mask = IMAGE_INSTANCE_X_MASK (p); - gcv.clip_x_origin = x; - gcv.clip_y_origin = y - pixmap_offset; + gcv.clip_x_origin = x - xoffset; + gcv.clip_y_origin = y - yoffset; pixmap_mask |= (GCFunction | GCClipMask | GCClipXOrigin | GCClipYOrigin); - /* Can't set a clip rectangle below because we already have a mask. - We could conceivably create a new clipmask by zeroing out - everything outside the clip region. Is it worth it? + /* Can't set a clip rectangle because we already have a mask. Is it possible to get an equivalent effect by changing the args to XCopyArea below rather than messing with a clip box? - - dkindred@cs.cmu.edu */ - need_clipping = 0; + - dkindred@cs.cmu.edu + Yes. We don't clip at all now - andy@xemacs.org + */ } gc = gc_cache_lookup (DEVICE_X_GC_CACHE (d), &gcv, pixmap_mask); @@ -1199,19 +1211,6 @@ x_output_x_pixmap (struct frame *f, struct Lisp_Image_Instance *p, int x, /* override_gc might have a mask already--we don't want to nuke it. Maybe we can insist that override_gc have no mask, or use one of the suggestions above. */ - need_clipping = 0; - } - - if (need_clipping) - { - XRectangle clip_box[1]; - - clip_box[0].x = clip_x; - clip_box[0].y = clip_y; - clip_box[0].width = clip_width; - clip_box[0].height = clip_height; - - XSetClipRectangles (dpy, gc, x, y, clip_box, 1, Unsorted); } /* depth of 0 means it's a bitmap, not a pixmap, and we should use @@ -1220,126 +1219,33 @@ x_output_x_pixmap (struct frame *f, struct Lisp_Image_Instance *p, int x, pixel values, instead of symbolic of fg/bg. */ if (IMAGE_INSTANCE_PIXMAP_DEPTH (p) > 0) { - XCopyArea (dpy, IMAGE_INSTANCE_X_PIXMAP (p), x_win, gc, 0, - pixmap_offset, width, + XCopyArea (dpy, + IMAGE_INSTANCE_X_PIXMAP_SLICE + (p, IMAGE_INSTANCE_PIXMAP_SLICE (p)), x_win, gc, xoffset, + yoffset, width, height, x, y); } else { - XCopyPlane (dpy, IMAGE_INSTANCE_X_PIXMAP (p), x_win, gc, 0, - (pixmap_offset < 0 - ? 0 - : pixmap_offset), - width, height, x, - (pixmap_offset < 0 - ? y - pixmap_offset - : y), - 1L); - } - - if (need_clipping) - { - XSetClipMask (dpy, gc, None); - XSetClipOrigin (dpy, gc, 0, 0); + XCopyPlane (dpy, IMAGE_INSTANCE_X_PIXMAP_SLICE + (p, IMAGE_INSTANCE_PIXMAP_SLICE (p)), x_win, gc, + xoffset, yoffset, width, height, x, y, 1L); } } static void -x_output_pixmap (struct window *w, struct display_line *dl, - Lisp_Object image_instance, int xpos, int xoffset, - int start_pixpos, int width, face_index findex, - int cursor_start, int cursor_width, int cursor_height) +x_output_pixmap (struct window *w, Lisp_Object image_instance, + struct display_box *db, struct display_glyph_area *dga, + face_index findex, int cursor_start, int cursor_width, + int cursor_height, int bg_pixmap) { struct frame *f = XFRAME (w->frame); struct device *d = XDEVICE (f->device); struct Lisp_Image_Instance *p = XIMAGE_INSTANCE (image_instance); - Lisp_Object window; Display *dpy = DEVICE_X_DISPLAY (d); Window x_win = XtWindow (FRAME_X_TEXT_WIDGET (f)); - int lheight = dl->ascent + dl->descent - dl->clip; - int pheight = ((int) IMAGE_INSTANCE_PIXMAP_HEIGHT (p) > lheight ? lheight : - IMAGE_INSTANCE_PIXMAP_HEIGHT (p)); - int pwidth = min (width + xoffset, (int) IMAGE_INSTANCE_PIXMAP_WIDTH (p)); - int clip_x, clip_y, clip_width, clip_height; - - /* The pixmap_offset is used to center the pixmap on lines which are - shorter than it is. This results in odd effects when scrolling - pixmaps off of the bottom. Let's try not using it. */ -#if 0 - int pixmap_offset = (int) (IMAGE_INSTANCE_PIXMAP_HEIGHT (p) - lheight) / 2; -#else - int pixmap_offset = 0; -#endif - - XSETWINDOW (window, w); - - if ((start_pixpos >= 0 && start_pixpos > xpos) || xoffset) - { - if (start_pixpos > xpos && start_pixpos > xpos + width) - return; - - clip_x = xoffset; - clip_width = width; - if (start_pixpos > xpos) - { - clip_x += (start_pixpos - xpos); - clip_width -= (start_pixpos - xpos); - } - } - else - { - clip_x = 0; - clip_width = 0; - } - - /* Place markers for possible future functionality (clipping the top - half instead of the bottom half; think pixel scrolling). */ - clip_y = 0; - clip_height = pheight; - - /* Clear the area the pixmap is going into. The pixmap itself will - always take care of the full width. We don't want to clear where - it is going to go in order to avoid flicker. So, all we have to - take care of is any area above or below the pixmap. */ - /* #### We take a shortcut for now. We know that since we have - pixmap_offset hardwired to 0 that the pixmap is against the top - edge so all we have to worry about is below it. */ - /* #### Unless the pixmap has a mask in which case we have to clear - the whole damn thing since we can't yet clear just the area not - included in the mask. */ - if (((int) (dl->ypos - dl->ascent + pheight) < - (int) (dl->ypos + dl->descent - dl->clip)) - || IMAGE_INSTANCE_X_MASK (p)) - { - int clear_x, clear_y, clear_width, clear_height; - - if (IMAGE_INSTANCE_X_MASK (p)) - { - clear_y = dl->ypos - dl->ascent; - clear_height = lheight; - } - else - { - clear_y = dl->ypos - dl->ascent + pheight; - clear_height = lheight - pheight; - } - - if (start_pixpos >= 0 && start_pixpos > xpos) - { - clear_x = start_pixpos; - clear_width = xpos + width - start_pixpos; - } - else - { - clear_x = xpos; - clear_width = width; - } - - redisplay_clear_region (window, findex, clear_x, clear_y, - clear_width, clear_height); - } - + /* Output the pixmap. */ { Lisp_Object tmp_pixel; @@ -1350,20 +1256,19 @@ x_output_pixmap (struct window *w, struct display_line *dl, tmp_pixel = WINDOW_FACE_CACHEL_BACKGROUND (w, findex); tmp_bcolor = COLOR_INSTANCE_X_COLOR (XCOLOR_INSTANCE (tmp_pixel)); - x_output_x_pixmap (f, p, xpos - xoffset, dl->ypos - dl->ascent, clip_x, - clip_y, clip_width, clip_height, - pwidth, pheight, pixmap_offset, + x_output_x_pixmap (f, p, db->xpos, db->ypos, + dga->xoffset, dga->yoffset, + dga->width, dga->height, tmp_fcolor.pixel, tmp_bcolor.pixel, 0); } /* Draw a cursor over top of the pixmap. */ - if (cursor_width && cursor_height && (cursor_start >= xpos) + if (cursor_width && cursor_height && (cursor_start >= db->xpos) && !NILP (w->text_cursor_visible_p) - && (cursor_start < xpos + pwidth)) + && (cursor_start < db->xpos + dga->width)) { GC gc; int focus = EQ (w->frame, DEVICE_FRAME_WITH_FOCUS_REAL (d)); - int y = dl->ypos - dl->ascent; struct face_cachel *cursor_cachel = WINDOW_FACE_CACHEL (w, get_builtin_face_cache_index @@ -1371,17 +1276,17 @@ x_output_pixmap (struct window *w, struct display_line *dl, gc = x_get_gc (d, Qnil, cursor_cachel->background, Qnil, Qnil, Qnil); - if (cursor_width > xpos + pwidth - cursor_start) - cursor_width = xpos + pwidth - cursor_start; + if (cursor_width > db->xpos + dga->width - cursor_start) + cursor_width = db->xpos + dga->width - cursor_start; if (focus) { - XFillRectangle (dpy, x_win, gc, cursor_start, y, cursor_width, + XFillRectangle (dpy, x_win, gc, cursor_start, db->ypos, cursor_width, cursor_height); } else { - XDrawRectangle (dpy, x_win, gc, cursor_start, y, cursor_width, + XDrawRectangle (dpy, x_win, gc, cursor_start, db->ypos, cursor_width, cursor_height); } } @@ -1404,6 +1309,7 @@ x_output_vertical_divider (struct window *w, int clear) XColor tmp_color; XGCValues gcv; GC background_gc; + enum edge_style style; unsigned long mask; int x, y1, y2, width, shadow_thickness, spacing, line_width; @@ -1439,10 +1345,20 @@ x_output_vertical_divider (struct window *w, int clear) x + spacing + shadow_thickness, y1, line_width, y2 - y1); + if (shadow_thickness < 0) + { + shadow_thickness = -shadow_thickness; + style = EDGE_BEVEL_IN; + } + else + { + style = EDGE_BEVEL_OUT; + } + /* Draw the shadows around the divider line */ x_bevel_area (w, div_face, x + spacing, y1, width - 2 * spacing, y2 - y1, - shadow_thickness); + shadow_thickness, EDGE_ALL, style); } /***************************************************************************** @@ -1471,9 +1387,12 @@ x_output_blank (struct window *w, struct display_line *dl, struct rune *rb, buffer); int x = rb->xpos; - int y = dl->ypos - dl->ascent; + int y = DISPLAY_LINE_YPOS (dl); int width = rb->width; - int height = dl->ascent + dl->descent - dl->clip; + int height = DISPLAY_LINE_HEIGHT (dl); + + /* Unmap all subwindows in the area we are going to blank. */ + redisplay_unmap_subwindows_maybe (f, x, y, width, height); if (start_pixpos > x) { @@ -1567,10 +1486,10 @@ x_output_hline (struct window *w, struct display_line *dl, struct rune *rb) int x = rb->xpos; int width = rb->width; - int height = dl->ascent + dl->descent - dl->clip; + int height = DISPLAY_LINE_HEIGHT (dl); int ypos1, ypos2, ypos3, ypos4; - ypos1 = dl->ypos - dl->ascent; + ypos1 = DISPLAY_LINE_YPOS (dl); ypos2 = ypos1 + rb->object.hline.yoffset; ypos3 = ypos2 + rb->object.hline.thickness; ypos4 = dl->ypos + dl->descent - dl->clip; @@ -1609,7 +1528,7 @@ x_output_hline (struct window *w, struct display_line *dl, struct rune *rb) void x_output_shadows (struct frame *f, int x, int y, int width, int height, GC top_shadow_gc, GC bottom_shadow_gc, GC background_gc, - int shadow_thickness) + int shadow_thickness, int edges) { struct device *d = XDEVICE (f->device); @@ -1631,28 +1550,41 @@ x_output_shadows (struct frame *f, int x, int y, int width, int height, for (elt = 0; elt < shadow_thickness; elt++) { int seg1 = elt; - int seg2 = elt + shadow_thickness; - - top_shadow[seg1].x1 = x; - top_shadow[seg1].x2 = x + width - elt - 1; - top_shadow[seg1].y1 = top_shadow[seg1].y2 = y + elt; - - top_shadow[seg2].x1 = top_shadow[seg2].x2 = x + elt; - top_shadow[seg2].y1 = y + shadow_thickness; - top_shadow[seg2].y2 = y + height - elt - 1; + int seg2 = (edges & EDGE_TOP) ? elt + shadow_thickness : elt; + int bot_seg2 = (edges & EDGE_BOTTOM) ? elt + shadow_thickness : elt; - bottom_shadow[seg1].x1 = x + elt + 1; - bottom_shadow[seg1].x2 = x + width - 1; - bottom_shadow[seg1].y1 = bottom_shadow[seg1].y2 = y + height - elt - 1; - - bottom_shadow[seg2].x1 = bottom_shadow[seg2].x2 = x + width - elt - 1; - bottom_shadow[seg2].y1 = y + elt + 1; - bottom_shadow[seg2].y2 = y + height - shadow_thickness; + if (edges & EDGE_TOP) + { + top_shadow[seg1].x1 = x + elt; + top_shadow[seg1].x2 = x + width - elt - 1; + top_shadow[seg1].y1 = top_shadow[seg1].y2 = y + elt; + } + if (edges & EDGE_LEFT) + { + top_shadow[seg2].x1 = top_shadow[seg2].x2 = x + elt; + top_shadow[seg2].y1 = y + elt; + top_shadow[seg2].y2 = y + height - elt - 1; + } + if (edges & EDGE_BOTTOM) + { + bottom_shadow[seg1].x1 = x + elt; + bottom_shadow[seg1].x2 = x + width - elt - 1; + bottom_shadow[seg1].y1 = bottom_shadow[seg1].y2 = y + height - elt - 1; + } + if (edges & EDGE_RIGHT) + { + bottom_shadow[bot_seg2].x1 = bottom_shadow[bot_seg2].x2 = x + width - elt - 1; + bottom_shadow[bot_seg2].y1 = y + elt; + bottom_shadow[bot_seg2].y2 = y + height - elt - 1; + } } - XDrawSegments (dpy, x_win, top_shadow_gc, top_shadow, shadow_thickness * 2); + XDrawSegments (dpy, x_win, top_shadow_gc, top_shadow, + ((edges & EDGE_TOP) ? shadow_thickness : 0) + + ((edges & EDGE_LEFT) ? shadow_thickness : 0)); XDrawSegments (dpy, x_win, bottom_shadow_gc, bottom_shadow, - shadow_thickness * 2); + ((edges & EDGE_BOTTOM) ? shadow_thickness : 0) + + ((edges & EDGE_RIGHT) ? shadow_thickness : 0)); } /***************************************************************************** @@ -1923,9 +1855,9 @@ x_output_eol_cursor (struct window *w, struct display_line *dl, int xpos, WINDOW_BUFFER (w)); int x = xpos; - int y = dl->ypos - dl->ascent; + int y = DISPLAY_LINE_YPOS (dl); int width = EOL_CURSOR_WIDTH; - int height = dl->ascent + dl->descent - dl->clip; + int height = DISPLAY_LINE_HEIGHT (dl); int cursor_height, cursor_y; int defheight, defascent; @@ -2153,4 +2085,6 @@ console_type_create_redisplay_x (void) CONSOLE_HAS_METHOD (x, flash); CONSOLE_HAS_METHOD (x, ring_bell); CONSOLE_HAS_METHOD (x, bevel_area); + CONSOLE_HAS_METHOD (x, output_string); + CONSOLE_HAS_METHOD (x, output_pixmap); } diff --git a/src/redisplay.c b/src/redisplay.c index e2c0511..d9c9855 100644 --- a/src/redisplay.c +++ b/src/redisplay.c @@ -154,6 +154,10 @@ typedef struct position_redisplay_data_type (those off the left side of the screen) need to be skipped before anything is displayed. */ Bytind bi_start_col_enabled; + int start_col_xoffset; /* Number of pixels that still need to + be skipped. This is used for + horizontal scrolling of glyphs, where we want + to be able to scroll over part of the glyph. */ int hscroll_glyph_width_adjust; /* how much the width of the hscroll glyph differs from space_width (w). @@ -259,8 +263,7 @@ static prop_block_dynarr *add_glyph_rune (pos_data *data, int pos_type, int allow_cursor, struct glyph_cachel *cachel); static Bytind create_text_block (struct window *w, struct display_line *dl, - Bytind bi_start_pos, int start_col, - prop_block_dynarr **prop, + Bytind bi_start_pos, prop_block_dynarr **prop, int type); static int create_overlay_glyph_block (struct window *w, struct display_line *dl); @@ -275,9 +278,6 @@ static void free_display_line (struct display_line *dl); static void update_line_start_cache (struct window *w, Bufpos from, Bufpos to, Bufpos point, int no_regen); static int point_visible (struct window *w, Bufpos point, int type); -extern Bytind bi_find_next_emchar_in_string (struct Lisp_String* str, Emchar target, - Bytind st, EMACS_INT count); -extern int string_column_at_point (struct Lisp_String* s, Bufpos init_pos, int tab_width); /* This used to be 10 but 30 seems to give much better performance. */ #define INIT_MAX_PREEMPTS 30 @@ -302,8 +302,8 @@ display_line_dynarr *cmotion_display_lines; /* Used by generate_formatted_string. Global because they get used so much that the dynamic allocation time adds up. */ -Emchar_dynarr *formatted_string_emchar_dynarr; -struct display_line formatted_string_display_line; +static Emchar_dynarr *formatted_string_emchar_dynarr; +static struct display_line formatted_string_display_line; /* We store the extents that we need to generate in a Dynarr and then frob them all on at the end of generating the string. We do it this way rather than adding them as we generate the string because @@ -311,9 +311,9 @@ struct display_line formatted_string_display_line; (to avoid having to resize the string multiple times), and we don't want to go around adding extents to a string when the extents might stretch off the end of the string. */ -EXTENT_dynarr *formatted_string_extent_dynarr; -Bytecount_dynarr *formatted_string_extent_start_dynarr; -Bytecount_dynarr *formatted_string_extent_end_dynarr; +static EXTENT_dynarr *formatted_string_extent_dynarr; +static Bytecount_dynarr *formatted_string_extent_start_dynarr; +static Bytecount_dynarr *formatted_string_extent_end_dynarr; /* #### probably temporary */ @@ -338,7 +338,7 @@ int vertical_clip; int horizontal_clip; /* Set if currently inside update_line_start_cache. */ -int updating_line_start_cache; +static int updating_line_start_cache; /* Nonzero means reading single-character input with prompt so put cursor on minibuffer after the prompt. */ @@ -378,6 +378,11 @@ int glyphs_changed_set; int subwindows_changed; int subwindows_changed_set; +/* non-zero if any displayed subwindow is in need of updating + somewhere. */ +int subwindows_state_changed; +int subwindows_state_changed_set; + /* This variable is 1 if the icon has to be updated. It is set to 1 when `frame-icon-glyph' changes. */ int icon_changed; @@ -453,7 +458,7 @@ Lisp_Object Voverlay_arrow_position; Lisp_Object Voverlay_arrow_string; Lisp_Object Vwindow_size_change_functions; -Lisp_Object Qwindow_scroll_functions, Vwindow_scroll_functions; +Lisp_Object Vwindow_scroll_functions; Lisp_Object Qredisplay_end_trigger_functions, Vredisplay_end_trigger_functions; #define INHIBIT_REDISPLAY_HOOKS /* #### Until we've thought about @@ -465,7 +470,7 @@ Lisp_Object Vpre_redisplay_hook, Vpost_redisplay_hook; Lisp_Object Qpre_redisplay_hook, Qpost_redisplay_hook; #endif /* INHIBIT_REDISPLAY_HOOKS */ -int last_display_warning_tick, display_warning_tick; +static int last_display_warning_tick, display_warning_tick; Lisp_Object Qdisplay_warning_buffer; int inhibit_warning_display; @@ -475,6 +480,10 @@ Lisp_Object Vuse_left_overflow, Vuse_right_overflow; Lisp_Object Vtext_cursor_visible_p; int column_number_start_at_one; + +#define WINDOW_SCROLLED(w) \ +(w->hscroll > 0 || w->left_xoffset) + /***************************************************************************/ /* */ @@ -644,8 +653,8 @@ next_tab_position (struct window *w, int start_pixpos, int left_pixpos) int pix_tab_width = tab_pix_width (w); /* Adjust n_pos for any hscrolling which has happened. */ - if (w->hscroll > 1) - n_pos -= space_width (w) * (w->hscroll - 1); + if (WINDOW_SCROLLED (w)) + n_pos -= space_width (w) * (w->hscroll - 1) + w->left_xoffset; while (n_pos <= start_pixpos) n_pos += pix_tab_width; @@ -697,8 +706,7 @@ calculate_display_line_boundaries (struct window *w, int modeline) static Bufpos generate_display_line (struct window *w, struct display_line *dl, int bounds, - Bufpos start_pos, int start_col, - prop_block_dynarr **prop, + Bufpos start_pos, prop_block_dynarr **prop, int type) { Bufpos ret_bufpos; @@ -731,7 +739,7 @@ generate_display_line (struct window *w, struct display_line *dl, int bounds, /* #### urk urk urk!!! Chuck fix this shit! */ Bytind hacked_up_bytind = create_text_block (w, dl, bufpos_to_bytind (b, start_pos), - start_col, prop, type); + prop, type); if (hacked_up_bytind > BI_BUF_ZV (b)) ret_bufpos = BUF_ZV (b) + 1; else @@ -1548,7 +1556,7 @@ add_glyph_rune (pos_data *data, struct glyph_block *gb, int pos_type, if (!width) return NULL; - if (data->start_col) + if (data->start_col || data->start_col_xoffset) { prop_block_dynarr *retval; int glyph_char_width = width / space_width (w); @@ -1782,8 +1790,7 @@ add_glyph_runes (pos_data *data, int pos_type) static Bytind create_text_block (struct window *w, struct display_line *dl, - Bytind bi_start_pos, int start_col, - prop_block_dynarr **prop, + Bytind bi_start_pos, prop_block_dynarr **prop, int type) { struct frame *f = XFRAME (w->frame); @@ -1927,6 +1934,7 @@ create_text_block (struct window *w, struct display_line *dl, data.cursor_x = -1; data.start_col = w->hscroll; + data.start_col_xoffset = w->left_xoffset; data.bi_start_col_enabled = (w->hscroll ? bi_start_pos : 0); data.hscroll_glyph_width_adjust = 0; @@ -2246,6 +2254,7 @@ create_text_block (struct window *w, struct display_line *dl, data.blank_width = DEVMETH (d, eol_cursor_width, ()); data.findex = DEFAULT_INDEX; data.start_col = 0; + data.start_col_xoffset = 0; data.bi_start_col_enabled = 0; add_emchar_rune (&data); @@ -2279,7 +2288,8 @@ create_text_block (struct window *w, struct display_line *dl, int prop_width = 0; if (data.start_col > 1) - tab_start_pixpos -= (space_width (w) * (data.start_col - 1)); + tab_start_pixpos -= (space_width (w) * (data.start_col - 1)) + + data.start_col_xoffset; next_tab_start = next_tab_position (w, tab_start_pixpos, @@ -2486,6 +2496,7 @@ done: data.blank_width = DEVMETH (d, eol_cursor_width, ()); data.findex = DEFAULT_INDEX; data.start_col = 0; + data.start_col_xoffset = 0; data.bi_start_col_enabled = 0; data.max_pixpos += data.blank_width; @@ -4234,8 +4245,10 @@ create_string_text_block (struct window *w, Lisp_Object disp_string, struct frame *f = XFRAME (w->frame); /* Note that a lot of the buffer controlled stuff has been left in because you might well want to make use of it (selective display - etc), its just the buffer text that we do not use. */ - struct buffer *b = XBUFFER (w->buffer); + etc), its just the buffer text that we do not use. However, it + seems to be possible for buffer to be nil sometimes so protect + against this case. */ + struct buffer *b = BUFFERP (w->buffer) ? XBUFFER (w->buffer) : 0; struct device *d = XDEVICE (f->device); struct Lisp_String* s = XSTRING (disp_string); @@ -4246,7 +4259,7 @@ create_string_text_block (struct window *w, Lisp_Object disp_string, pos_data data; - int truncate_win = window_truncation_on (w); + int truncate_win = b ? window_truncation_on (w) : 0; int end_glyph_width = 0; /* we're going to ditch selective display for static text, its an @@ -4296,10 +4309,10 @@ create_string_text_block (struct window *w, Lisp_Object disp_string, Since more than one display table is possible, you have great flexibility in mapping ranges of characters. */ - Emchar printable_min = (CHAR_OR_CHAR_INTP (b->ctl_arrow) + Emchar printable_min = b ? (CHAR_OR_CHAR_INTP (b->ctl_arrow) ? XCHAR_OR_CHAR_INT (b->ctl_arrow) : ((EQ (b->ctl_arrow, Qt) || EQ (b->ctl_arrow, Qnil)) - ? 255 : 160)); + ? 255 : 160)) : 255; Lisp_Object face_dt, window_dt; @@ -4730,27 +4743,10 @@ done: } else if (data.bi_bufpos == bi_string_zv) { - /* We need to add a marker to the end of the line since there is no - newline character in order for the cursor to get drawn. We label - it as a newline so that it gets handled correctly by the - whitespace routines below. */ - - data.ch = '\n'; - data.blank_width = DEVMETH (d, eol_cursor_width, ()); - data.findex = default_face; - data.start_col = 0; - data.bi_start_col_enabled = 0; - - data.max_pixpos += data.blank_width; - add_emchar_rune (&data); - data.max_pixpos -= data.blank_width; - - /* #### urk! Chuck, this shit is bad news. Going around - manipulating invalid positions is guaranteed to result in - trouble sooner or later. */ - data.bi_bufpos = bi_string_zv + 1; + /* create_text_block () adds a bogus \n marker here which screws + up subwindow display. Since we never have a cursor in the + gutter we can safely ignore it. */ } - /* Calculate left whitespace boundary. */ { int elt = 0; @@ -4854,7 +4850,7 @@ done: dl->end_bufpos = buffer_or_string_bytind_to_bufpos (disp_string, data.bi_bufpos) - 1; if (truncate_win) data.dl->num_chars = - string_column_at_point (s, dl->end_bufpos, XINT (b->tab_width)); + string_column_at_point (s, dl->end_bufpos, b ? XINT (b->tab_width) : 8); else /* This doesn't correctly take into account tabs and control characters but if the window isn't being truncated then this @@ -4909,7 +4905,7 @@ generate_string_display_line (struct window *w, Lisp_Object disp_string, Bufpos ret_bufpos; /* you must set bounds before calling this. */ - + /* Reset what this line is using. */ if (dl->display_blocks) Dynarr_reset (dl->display_blocks); @@ -4970,7 +4966,7 @@ generate_displayable_area (struct window *w, Lisp_Object disp_string, if (NILP (disp_string)) return; - s_zv = XSTRING_CHAR_LENGTH (disp_string) - 1; + s_zv = XSTRING_CHAR_LENGTH (disp_string); bounds.left_out = xpos; bounds.right_out = xpos + width; @@ -5066,6 +5062,7 @@ regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type) struct buffer *b = XBUFFER (w->buffer); int ypos = WINDOW_TEXT_TOP (w); int yend; /* set farther down */ + int yclip = WINDOW_TEXT_TOP_CLIP (w); prop_block_dynarr *prop; layout_bounds bounds; @@ -5140,17 +5137,37 @@ regenerate_window (struct window *w, Bufpos start_pos, Bufpos point, int type) dlp->bounds = bounds; dlp->offset = 0; - start_pos = generate_display_line (w, dlp, 1, start_pos, - w->hscroll, &prop, type); - dlp->ypos = ypos + dlp->ascent; + start_pos = generate_display_line (w, dlp, 1, start_pos, &prop, type); + + if (yclip > dlp->ascent) + { + /* this should never happen, but if it does just display the + whole line */ + yclip = 0; + } + + dlp->ypos = (ypos + dlp->ascent) - yclip; ypos = dlp->ypos + dlp->descent; + /* See if we've been asked to start midway through a line, for + partial display line scrolling. */ + if (yclip) + { + dlp->top_clip = yclip; + yclip = 0; + } + else + dlp->top_clip = 0; + if (ypos > yend) { int visible_height = dlp->ascent + dlp->descent; dlp->clip = (ypos - yend); - visible_height -= dlp->clip; + /* Although this seems strange we could have a single very + tall line visible for which we need to account for both + the top clip and the bottom clip. */ + visible_height -= (dlp->clip + dlp->top_clip); if (visible_height < VERTICAL_CLIP (w, 1)) { @@ -5393,7 +5410,7 @@ regenerate_window_extents_only_changed (struct window *w, Bufpos startp, return 0; new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset, - w->hscroll, &prop, DESIRED_DISP); + &prop, DESIRED_DISP); ddl->offset = 0; /* #### If there is propagated stuff the fail. We could @@ -5412,6 +5429,7 @@ regenerate_window_extents_only_changed (struct window *w, Bufpos startp, if (cdl->ypos != ddl->ypos || cdl->ascent != ddl->ascent || cdl->descent != ddl->descent + || cdl->top_clip != ddl->top_clip || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1) || old_start != ddl->bufpos @@ -5555,7 +5573,7 @@ regenerate_window_incrementally (struct window *w, Bufpos startp, return 0; new_start = generate_display_line (w, ddl, 0, ddl->bufpos + ddl->offset, - w->hscroll, &prop, DESIRED_DISP); + &prop, DESIRED_DISP); ddl->offset = 0; /* If there is propagated stuff then it is pretty much a @@ -5585,6 +5603,7 @@ regenerate_window_incrementally (struct window *w, Bufpos startp, if (cdl->ypos != ddl->ypos || cdl->ascent != ddl->ascent || cdl->descent != ddl->descent + || cdl->top_clip != ddl->top_clip || (cdl->cursor_elt != -1 && ddl->cursor_elt == -1) || (cdl->cursor_elt == -1 && ddl->cursor_elt != -1)) { @@ -5877,10 +5896,11 @@ redisplay_window (Lisp_Object window, int skip_selected) else mark_face_cachels_as_not_updated (w); - /* Ditto the glyph cache elements. */ + /* Ditto the glyph cache elements, although we do *not* invalidate + the cache purely because glyphs have changed - this is now + handled by the dirty flag.*/ if ((!echo_active && b != window_display_buffer (w)) - || !Dynarr_length (w->glyph_cachels) - || f->glyphs_changed) + || !Dynarr_length (w->glyph_cachels)) reset_glyph_cachels (w); else mark_glyph_cachels_as_not_updated (w); @@ -5966,6 +5986,7 @@ redisplay_window (Lisp_Object window, int skip_selected) && !f->faces_changed && !f->glyphs_changed && !f->subwindows_changed + && !f->subwindows_state_changed && !f->point_changed && !f->windows_structure_changed) { @@ -5987,6 +6008,7 @@ redisplay_window (Lisp_Object window, int skip_selected) && !f->faces_changed && !f->glyphs_changed && !f->subwindows_changed + && !f->subwindows_state_changed && !f->windows_structure_changed) { if (point_visible (w, pointm, CURRENT_DISP) @@ -6045,6 +6067,7 @@ redisplay_window (Lisp_Object window, int skip_selected) && !f->faces_changed && !f->glyphs_changed && !f->subwindows_changed + && !f->subwindows_state_changed && !f->windows_structure_changed && !f->frame_changed && !truncation_changed @@ -6141,6 +6164,10 @@ regeneration_done: somewhere else once tty updates occur on a per-frame basis. */ mark_face_cachels_as_clean (w); + /* The glyph cachels only get dirty if someone changed something. */ + if (glyphs_changed) + mark_glyph_cachels_as_clean (w); + w->windows_changed = 0; } @@ -6262,7 +6289,6 @@ redisplay_frame (struct frame *f, int preemption_check) being handled. */ update_frame_menubars (f); #endif /* HAVE_MENUBARS */ - update_frame_gutters (f); /* widgets are similar to menus in that they can call lisp to determine activation etc. Therefore update them before we get into redisplay. This is primarily for connected widgets such as @@ -6273,6 +6299,30 @@ redisplay_frame (struct frame *f, int preemption_check) update_frame_toolbars (f); #endif /* HAVE_TOOLBARS */ + /* If we clear the frame we have to force its contents to be redrawn. */ + if (f->clear) + f->frame_changed = 1; + + /* invalidate the subwindow cache. We use subwindows_changed here to + cause subwindows to get instantiated. This is because + subwindows_state_changed is less strict - dealing with things + like the clicked state of button. We have to do this before + redisplaying the gutters as subwindows get unmapped in the + process.*/ + if (!Dynarr_length (f->subwindow_cachels) + || f->subwindows_changed + || f->frame_changed) + { + reset_subwindow_cachels (f); + /* we have to do this so the gutter gets regenerated. */ + reset_gutter_display_lines (f); + } + else + mark_subwindow_cachels_as_not_updated (f); + /* We can now update the gutters, safe in the knowledge that our + efforts won't get undone. */ + update_frame_gutters (f); + hold_frame_size_changes (); /* ----------------- BEGIN CRITICAL REDISPLAY SECTION ---------------- */ @@ -6299,27 +6349,12 @@ redisplay_frame (struct frame *f, int preemption_check) #### If a frame-size change does occur we should probably actually be preempting redisplay. */ - /* If we clear the frame we have to force its contents to be redrawn. */ - if (f->clear) - f->frame_changed = 1; - /* Erase the frame before outputting its contents. */ if (f->clear) { DEVMETH (d, clear_frame, (f)); } - /* invalidate the subwindow cache. we are going to reuse the glyphs - flag here to cause subwindows to get instantiated. This is - because subwindows changed is less strict - dealing with things - like the clicked state of button. */ - if (!Dynarr_length (f->subwindow_cachels) - || f->glyphs_changed - || f->frame_changed) - reset_subwindow_cachels (f); - else - mark_subwindow_cachels_as_not_updated (f); - /* Do the selected window first. */ redisplay_window (FRAME_SELECTED_WINDOW (f), 0); @@ -6334,24 +6369,9 @@ redisplay_frame (struct frame *f, int preemption_check) update_frame_title (f); - f->buffers_changed = 0; - f->clip_changed = 0; - f->extents_changed = 0; - f->faces_changed = 0; - f->frame_changed = 0; - f->glyphs_changed = 0; - f->subwindows_changed = 0; - f->icon_changed = 0; - f->menubar_changed = 0; - f->modeline_changed = 0; - f->point_changed = 0; - f->toolbar_changed = 0; - f->gutter_changed = 0; - f->windows_changed = 0; - f->windows_structure_changed = 0; + CLASS_RESET_CHANGED_FLAGS (f); f->window_face_cache_reset = 0; f->echo_area_garbaged = 0; - f->clear = 0; if (!f->size_change_pending) @@ -6401,12 +6421,7 @@ redisplay_device (struct device *d) if (FRAME_REPAINT_P (f)) { - if (f->buffers_changed || f->clip_changed || f->extents_changed || - f->faces_changed || f->frame_changed || f->menubar_changed || - f->modeline_changed || f->point_changed || f->size_changed || - f->toolbar_changed || f->windows_changed || f->size_slipped || - f->windows_structure_changed || f->glyphs_changed || - f->subwindows_changed || f->gutter_changed) + if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f)) { preempted = redisplay_frame (f, 0); } @@ -6436,12 +6451,8 @@ redisplay_device (struct device *d) if (FRAME_REPAINT_P (f)) { - if (f->buffers_changed || f->clip_changed || f->extents_changed || - f->faces_changed || f->frame_changed || f->menubar_changed || - f->modeline_changed || f->point_changed || f->size_changed || - f->toolbar_changed || f->windows_changed || - f->windows_structure_changed || f->gutter_changed || - f->glyphs_changed || f->subwindows_changed) + if (CLASS_REDISPLAY_FLAGS_CHANGEDP(f) + || f->size_changed) { preempted = redisplay_frame (f, 0); } @@ -6456,21 +6467,7 @@ redisplay_device (struct device *d) /* If we get here then we redisplayed all of our frames without getting preempted so mark ourselves as clean. */ - d->buffers_changed = 0; - d->clip_changed = 0; - d->extents_changed = 0; - d->faces_changed = 0; - d->frame_changed = 0; - d->glyphs_changed = 0; - d->subwindows_changed = 0; - d->icon_changed = 0; - d->menubar_changed = 0; - d->modeline_changed = 0; - d->point_changed = 0; - d->toolbar_changed = 0; - d->gutter_changed = 0; - d->windows_changed = 0; - d->windows_structure_changed = 0; + CLASS_RESET_CHANGED_FLAGS (d); if (!size_change_failed) d->size_changed = 0; @@ -6505,13 +6502,8 @@ redisplay_without_hooks (void) if (asynch_device_change_pending) handle_asynch_device_change (); - if (!buffers_changed && !clip_changed && !extents_changed && - !faces_changed && !frame_changed && !icon_changed && - !menubar_changed && !modeline_changed && !point_changed && - !size_changed && !toolbar_changed && !windows_changed && - !glyphs_changed && !subwindows_changed && - !gutter_changed && !windows_structure_changed && - !disable_preemption && preemption_count < max_preempts) + if (!GLOBAL_REDISPLAY_FLAGS_CHANGEDP && + !size_changed && !disable_preemption && preemption_count < max_preempts) goto done; DEVICE_LOOP_NO_BREAK (devcons, concons) @@ -6519,12 +6511,8 @@ redisplay_without_hooks (void) struct device *d = XDEVICE (XCAR (devcons)); int preempted; - if (d->buffers_changed || d->clip_changed || d->extents_changed || - d->faces_changed || d->frame_changed || d->icon_changed || - d->menubar_changed || d->modeline_changed || d->point_changed || - d->size_changed || d->toolbar_changed || d->windows_changed || - d->windows_structure_changed || d->gutter_changed || - d->glyphs_changed || d->subwindows_changed) + if (CLASS_REDISPLAY_FLAGS_CHANGEDP (d) + || d->size_changed) { preempted = redisplay_device (d); @@ -6543,20 +6531,7 @@ redisplay_without_hooks (void) preemption_count = 0; /* Mark redisplay as accurate */ - buffers_changed = 0; - clip_changed = 0; - extents_changed = 0; - frame_changed = 0; - glyphs_changed = 0; - subwindows_changed = 0; - icon_changed = 0; - menubar_changed = 0; - modeline_changed = 0; - point_changed = 0; - toolbar_changed = 0; - gutter_changed = 0; - windows_changed = 0; - windows_structure_changed = 0; + GLOBAL_RESET_CHANGED_FLAGS; RESET_CHANGED_SET_FLAGS; if (faces_changed) @@ -6787,7 +6762,6 @@ decode_mode_spec (struct window *w, Emchar spec, int type) case 'p': { Bufpos pos = marker_position (w->start[type]); - Charcount total = BUF_ZV (b) - BUF_BEGV (b); /* This had better be while the desired lines are being done. */ if (w->window_end_pos[type] <= BUF_Z (b) - BUF_ZV (b)) @@ -6804,15 +6778,20 @@ decode_mode_spec (struct window *w, Emchar spec, int type) /* This hard limit is ok since the string it will hold has a fixed maximum length of 3. But just to be safe... */ char buf[10]; + Charcount chars = pos - BUF_BEGV (b); + Charcount total = BUF_ZV (b) - BUF_BEGV (b); - total = ((pos - BUF_BEGV (b)) * 100 + total - 1) / total; + /* Avoid overflow on big buffers */ + int percent = total > LONG_MAX/200 ? + (chars + total/200) / (total / 100) : + (chars * 100 + total/2) / total; /* We can't normally display a 3-digit number, so get us a 2-digit number that is close. */ - if (total == 100) - total = 99; + if (percent == 100) + percent = 99; - sprintf (buf, "%2d%%", total); + sprintf (buf, "%d%%", percent); Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf, strlen (buf)); @@ -6827,7 +6806,6 @@ decode_mode_spec (struct window *w, Emchar spec, int type) { Bufpos toppos = marker_position (w->start[type]); Bufpos botpos = BUF_Z (b) - w->window_end_pos[type]; - Charcount total = BUF_ZV (b) - BUF_BEGV (b); /* botpos is only accurate as of the last redisplay, so we can only treat it as a hint. In particular, after erase-buffer, @@ -6847,18 +6825,23 @@ decode_mode_spec (struct window *w, Emchar spec, int type) /* This hard limit is ok since the string it will hold has a fixed maximum length of around 6. But just to be safe... */ char buf[10]; + Charcount chars = botpos - BUF_BEGV (b); + Charcount total = BUF_ZV (b) - BUF_BEGV (b); - total = ((botpos - BUF_BEGV (b)) * 100 + total - 1) / total; + /* Avoid overflow on big buffers */ + int percent = total > LONG_MAX/200 ? + (chars + total/200) / (total / 100) : + (chars * 100 + total/2) / max (total, 1); /* We can't normally display a 3-digit number, so get us a 2-digit number that is close. */ - if (total == 100) - total = 99; + if (percent == 100) + percent = 99; if (toppos <= BUF_BEGV (b)) - sprintf (buf, "Top%2d%%", total); + sprintf (buf, "Top%d%%", percent); else - sprintf (buf, "%2d%%", total); + sprintf (buf, "%d%%", percent); Dynarr_add_many (mode_spec_bufbyte_string, (Bufbyte *) buf, strlen (buf)); @@ -6961,7 +6944,7 @@ free_display_line (struct display_line *dl) /* Given an array of display lines, free them and all data structures contained within them. */ -static void +void free_display_lines (display_line_dynarr *dla) { int line; @@ -6994,7 +6977,7 @@ free_display_structs (struct window_mirror *mir) static void -mark_glyph_block_dynarr (glyph_block_dynarr *gba, void (*markobj) (Lisp_Object)) +mark_glyph_block_dynarr (glyph_block_dynarr *gba) { if (gba) { @@ -7004,15 +6987,15 @@ mark_glyph_block_dynarr (glyph_block_dynarr *gba, void (*markobj) (Lisp_Object)) for (; gb < gb_last; gb++) { if (!NILP (gb->glyph)) - markobj (gb->glyph); + mark_object (gb->glyph); if (!NILP (gb->extent)) - markobj (gb->extent); + mark_object (gb->extent); } } } static void -mark_redisplay_structs (display_line_dynarr *dla, void (*markobj) (Lisp_Object)) +mark_redisplay_structs (display_line_dynarr *dla) { display_line *dl = Dynarr_atp (dla, 0); display_line *dl_last = Dynarr_atp (dla, Dynarr_length (dla)); @@ -7034,35 +7017,35 @@ mark_redisplay_structs (display_line_dynarr *dla, void (*markobj) (Lisp_Object)) if (r->type == RUNE_DGLYPH) { if (!NILP (r->object.dglyph.glyph)) - markobj (r->object.dglyph.glyph); + mark_object (r->object.dglyph.glyph); if (!NILP (r->object.dglyph.extent)) - markobj (r->object.dglyph.extent); + mark_object (r->object.dglyph.extent); } } } - mark_glyph_block_dynarr (dl->left_glyphs, markobj); - mark_glyph_block_dynarr (dl->right_glyphs, markobj); + mark_glyph_block_dynarr (dl->left_glyphs); + mark_glyph_block_dynarr (dl->right_glyphs); } } static void -mark_window_mirror (struct window_mirror *mir, void (*markobj)(Lisp_Object)) +mark_window_mirror (struct window_mirror *mir) { - mark_redisplay_structs (mir->current_display_lines, markobj); - mark_redisplay_structs (mir->desired_display_lines, markobj); + mark_redisplay_structs (mir->current_display_lines); + mark_redisplay_structs (mir->desired_display_lines); if (mir->next) - mark_window_mirror (mir->next, markobj); + mark_window_mirror (mir->next); if (mir->hchild) - mark_window_mirror (mir->hchild, markobj); + mark_window_mirror (mir->hchild); else if (mir->vchild) - mark_window_mirror (mir->vchild, markobj); + mark_window_mirror (mir->vchild); } void -mark_redisplay (void (*markobj)(Lisp_Object)) +mark_redisplay (void) { Lisp_Object frmcons, devcons, concons; @@ -7070,7 +7053,7 @@ mark_redisplay (void (*markobj)(Lisp_Object)) { struct frame *f = XFRAME (XCAR (frmcons)); update_frame_window_mirror (f); - mark_window_mirror (f->root_mirror, markobj); + mark_window_mirror (f->root_mirror); } } @@ -7134,7 +7117,7 @@ mark_redisplay (void (*markobj)(Lisp_Object)) /* This will get used quite a bit so we don't want to be constantly allocating and freeing it. */ -line_start_cache_dynarr *internal_cache; +static line_start_cache_dynarr *internal_cache; /* Makes internal_cache represent the TYPE display structs and only the TYPE display structs. */ @@ -7653,7 +7636,7 @@ start_with_line_at_pixpos (struct window *w, Bufpos point, int pixpos) } cur_elt--; - if (cur_elt < 0) + while (cur_elt < 0) { Bufpos from, to; int win_char_height; @@ -7673,7 +7656,20 @@ start_with_line_at_pixpos (struct window *w, Bufpos point, int pixpos) update_line_start_cache (w, from, to, point, 0); cur_elt = point_in_line_start_cache (w, cur_pos, 2) - 1; - assert (cur_elt >= 0); + assert (cur_elt >= -1); + /* This used to be cur_elt>=0 under the assumption that if + point is in the top line and not at BUF_BEGV, then + setting the window_start to a newline before the start of + the first line will always cause scrolling. + + However in my (jv) opinion this is wrong. That new line + can be hidden in various ways: invisible extents, an + explicit window-start not at a newline character etc. + The existence of those are indeed known to create crashes + on that assert. So we have no option but to continue the + search if we found point at the top of the line_start_cache + again. */ + cur_pos = Dynarr_atp (w->line_start_cache,0)->start; } prev_pos = cur_pos; } @@ -8969,6 +8965,8 @@ redisplay_variable_changed (Lisp_Object sym, Lisp_Object *val, return 0; } +/* This is called if the built-in glyphs have their properties + changed. */ void redisplay_glyph_changed (Lisp_Object glyph, Lisp_Object property, Lisp_Object locale) @@ -9091,7 +9089,9 @@ init_redisplay (void) preemption_count = 0; max_preempts = INIT_MAX_PREEMPTS; +#ifndef PDUMP if (!initialized) +#endif { cmotion_display_lines = Dynarr_new (display_line); mode_spec_bufbyte_string = Dynarr_new (Bufbyte); @@ -9171,7 +9171,6 @@ syms_of_redisplay (void) #endif /* INHIBIT_REDISPLAY_HOOKS */ defsymbol (&Qdisplay_warning_buffer, "display-warning-buffer"); defsymbol (&Qbar_cursor, "bar-cursor"); - defsymbol (&Qwindow_scroll_functions, "window-scroll-functions"); defsymbol (&Qredisplay_end_trigger_functions, "redisplay-end-trigger-functions"); @@ -9185,8 +9184,16 @@ syms_of_redisplay (void) } void +reinit_vars_of_redisplay (void) +{ + updating_line_start_cache = 0; +} + +void vars_of_redisplay (void) { + reinit_vars_of_redisplay (); + #if 0 staticpro (&last_arrow_position); staticpro (&last_arrow_string); @@ -9194,8 +9201,6 @@ vars_of_redisplay (void) last_arrow_string = Qnil; #endif /* 0 */ - updating_line_start_cache = 0; - /* #### Probably temporary */ DEFVAR_INT ("redisplay-cache-adjustment", &cache_adjustment /* \(Temporary) Setting this will impact the performance of the internal @@ -9280,7 +9285,7 @@ instead. Vwindow_system = Qnil; /* #### Temporary shit until window-system is eliminated. */ - DEFVAR_LISP ("initial-window-system", &Vinitial_window_system /* + DEFVAR_CONST_LISP ("initial-window-system", &Vinitial_window_system /* DON'T TOUCH */ ); Vinitial_window_system = Qnil; diff --git a/src/redisplay.h b/src/redisplay.h index 57c0004..96e2e92 100644 --- a/src/redisplay.h +++ b/src/redisplay.h @@ -145,8 +145,8 @@ struct rune /* HLINE */ struct { - int thickness; /* how thick to make hline */ - int yoffset; /* how far down from top of line to put top */ + short thickness; /* how thick to make hline */ + short yoffset; /* how far down from top of line to put top */ } hline; } object; /* actual rune object */ }; @@ -273,6 +273,8 @@ struct display_line pixel-row itself, I think. */ unsigned short clip; /* amount of bottom of line to clip in pixels.*/ + unsigned short top_clip; /* amount of top of line to clip + in pixels.*/ Bufpos bufpos; /* first buffer position on line */ Bufpos end_bufpos; /* last buffer position on line */ Charcount offset; /* adjustment to bufpos vals */ @@ -301,15 +303,45 @@ struct display_line }; #define DISPLAY_LINE_HEIGHT(dl) \ -(dl->ascent + dl->descent - dl->clip) +(dl->ascent + dl->descent - (dl->clip + dl->top_clip)) #define DISPLAY_LINE_YPOS(dl) \ -(dl->ypos - dl->ascent) +(dl->ypos - (dl->ascent - dl->top_clip)) +#define DISPLAY_LINE_YEND(dl) \ +((dl->ypos + dl->descent) - dl->clip) typedef struct { Dynarr_declare (display_line); } display_line_dynarr; +/* The following two structures are used to represent an area to +displayed and where to display it. Using these two structures all +combinations of clipping and position can be accommodated. */ + +/* This represents an area to be displayed into. */ +typedef struct display_box display_box; +struct display_box +{ + int xpos; /* absolute horizontal position of area */ + int ypos; /* absolute vertical position of area */ + int width, height; +}; + +/* This represents the area from a glyph to be displayed. */ +typedef struct display_glyph_area display_glyph_area; +struct display_glyph_area +{ + int xoffset; /* horizontal offset of the glyph, +ve means + display the glyph with x offset by xoffset, + -ve means display starting xoffset into the + glyph. */ + int yoffset; /* vertical offset of the glyph, +ve means + display the glyph with y offset by yoffset, + -ve means display starting xoffset into the + glyph. */ + int width, height; /* width and height of glyph to display. */ +}; + /* It could be argued that the following two structs belong in extents.h, but they're only used by redisplay and it simplifies the header files to put them here. */ @@ -345,6 +377,12 @@ struct extent_fragment unsigned int invisible_ellipses_already_displayed:1; }; +#define EDGE_TOP 1 +#define EDGE_LEFT 2 +#define EDGE_BOTTOM 4 +#define EDGE_RIGHT 8 +#define EDGE_ALL (EDGE_TOP | EDGE_LEFT | EDGE_BOTTOM | EDGE_RIGHT) + /*************************************************************************/ /* change flags */ @@ -390,6 +428,11 @@ extern int glyphs_changed_set; extern int subwindows_changed; extern int subwindows_changed_set; +/* True if any displayed subwindow is in need of updating + somewhere. */ +extern int subwindows_state_changed; +extern int subwindows_state_changed_set; + /* True if an icon is in need of updating somewhere. */ extern int icon_changed; extern int icon_changed_set; @@ -463,23 +506,100 @@ extern int windows_structure_changed; #define MARK_GUTTER_CHANGED MARK_TYPE_CHANGED (gutter) #define MARK_GLYPHS_CHANGED MARK_TYPE_CHANGED (glyphs) #define MARK_SUBWINDOWS_CHANGED MARK_TYPE_CHANGED (subwindows) +#define MARK_SUBWINDOWS_STATE_CHANGED MARK_TYPE_CHANGED (subwindows_state) + + +#define CLASS_RESET_CHANGED_FLAGS(p) do { \ + (p)->buffers_changed = 0; \ + (p)->clip_changed = 0; \ + (p)->extents_changed = 0; \ + (p)->faces_changed = 0; \ + (p)->frame_changed = 0; \ + (p)->icon_changed = 0; \ + (p)->menubar_changed = 0; \ + (p)->modeline_changed = 0; \ + (p)->point_changed = 0; \ + (p)->toolbar_changed = 0; \ + (p)->gutter_changed = 0; \ + (p)->glyphs_changed = 0; \ + (p)->subwindows_changed = 0; \ + (p)->subwindows_state_changed = 0; \ + (p)->windows_changed = 0; \ + (p)->windows_structure_changed = 0; \ +} while (0) + +#define GLOBAL_RESET_CHANGED_FLAGS do { \ + buffers_changed = 0; \ + clip_changed = 0; \ + extents_changed = 0; \ + faces_changed = 0; \ + frame_changed = 0; \ + icon_changed = 0; \ + menubar_changed = 0; \ + modeline_changed = 0; \ + point_changed = 0; \ + toolbar_changed = 0; \ + gutter_changed = 0; \ + glyphs_changed = 0; \ + subwindows_changed = 0; \ + subwindows_state_changed = 0; \ + windows_changed = 0; \ + windows_structure_changed = 0; \ +} while (0) + +#define CLASS_REDISPLAY_FLAGS_CHANGEDP(p) \ + ( (p)->buffers_changed || \ + (p)->clip_changed || \ + (p)->extents_changed || \ + (p)->faces_changed || \ + (p)->frame_changed || \ + (p)->icon_changed || \ + (p)->menubar_changed || \ + (p)->modeline_changed || \ + (p)->point_changed || \ + (p)->toolbar_changed || \ + (p)->gutter_changed || \ + (p)->glyphs_changed || \ + (p)->subwindows_changed || \ + (p)->subwindows_state_changed || \ + (p)->windows_changed || \ + (p)->windows_structure_changed ) + +#define GLOBAL_REDISPLAY_FLAGS_CHANGEDP \ + ( buffers_changed || \ + clip_changed || \ + extents_changed || \ + faces_changed || \ + frame_changed || \ + icon_changed || \ + menubar_changed || \ + modeline_changed || \ + point_changed || \ + toolbar_changed || \ + gutter_changed || \ + glyphs_changed || \ + subwindows_changed || \ + subwindows_state_changed || \ + windows_changed || \ + windows_structure_changed ) + /* Anytime a console, device or frame is added or deleted we need to reset these flags. */ -#define RESET_CHANGED_SET_FLAGS \ - do { \ - buffers_changed_set = 0; \ - clip_changed_set = 0; \ - extents_changed_set = 0; \ - icon_changed_set = 0; \ - menubar_changed_set = 0; \ - modeline_changed_set = 0; \ - point_changed_set = 0; \ - toolbar_changed_set = 0; \ - gutter_changed_set = 0; \ - glyphs_changed_set = 0; \ - subwindows_changed_set = 0; \ - } while (0) +#define RESET_CHANGED_SET_FLAGS do { \ + buffers_changed_set = 0; \ + clip_changed_set = 0; \ + extents_changed_set = 0; \ + icon_changed_set = 0; \ + menubar_changed_set = 0; \ + modeline_changed_set = 0; \ + point_changed_set = 0; \ + toolbar_changed_set = 0; \ + gutter_changed_set = 0; \ + glyphs_changed_set = 0; \ + subwindows_changed_set = 0; \ + subwindows_state_changed_set = 0; \ +} while (0) /*************************************************************************/ @@ -555,6 +675,7 @@ int line_at_center (struct window *w, int type, Bufpos start, Bufpos point); int window_half_pixpos (struct window *w); void redisplay_echo_area (void); void free_display_structs (struct window_mirror *mir); +void free_display_lines (display_line_dynarr *dla); Bufbyte *generate_formatted_string (struct window *w, Lisp_Object format_str, Lisp_Object result_str, face_index findex, int type); @@ -571,7 +692,7 @@ int pixel_to_glyph_translation (struct frame *f, int x_coord, Lisp_Object *obj1, Lisp_Object *obj2); void glyph_to_pixel_translation (struct window *w, int char_x, int char_y, int *pix_x, int *pix_y); -void mark_redisplay (void (*) (Lisp_Object)); +void mark_redisplay (void); int point_in_line_start_cache (struct window *w, Bufpos point, int min_past); int point_would_be_visible (struct window *w, Bufpos startp, @@ -599,12 +720,28 @@ int compute_line_start_cache_dynarr_usage (line_start_cache_dynarr *dyn, int get_next_display_block (layout_bounds bounds, display_block_dynarr *dba, int start_pos, int *next_start); -void redisplay_output_subwindow (struct window *w, struct display_line *dl, - Lisp_Object image_instance, int xpos, - int xoffset, int start_pixpos, int width, - face_index findex, int cursor_start, - int cursor_width, int cursor_height); +void redisplay_output_layout (struct window *w, + Lisp_Object image_instance, + struct display_box* db, struct display_glyph_area* dga, + face_index findex, int cursor_start, int cursor_width, + int cursor_height); +void redisplay_output_subwindow (struct window *w, + Lisp_Object image_instance, + struct display_box* db, struct display_glyph_area* dga, + face_index findex, int cursor_start, int cursor_width, + int cursor_height); void redisplay_unmap_subwindows_maybe (struct frame* f, int x, int y, int width, int height); +void redisplay_output_pixmap (struct window *w, + Lisp_Object image_instance, + struct display_box* db, struct display_glyph_area* dga, + face_index findex, int cursor_start, int cursor_width, + int cursor_height, int offset_bitmap); +int redisplay_calculate_display_boxes (struct display_line *dl, int xpos, + int xoffset, int start_pixpos, int width, + struct display_box* dest, + struct display_glyph_area* src); +int redisplay_normalize_glyph_area (struct display_box* dest, + struct display_glyph_area* glyphsrc); void redisplay_clear_to_window_end (struct window *w, int ypos1, int ypos2); void redisplay_clear_region (Lisp_Object window, face_index findex, int x, int y, int width, int height); @@ -614,6 +751,7 @@ void redisplay_clear_bottom_of_window (struct window *w, void redisplay_update_line (struct window *w, int first_line, int last_line, int update_values); void redisplay_output_window (struct window *w); +void bevel_modeline (struct window *w, struct display_line *dl); int redisplay_move_cursor (struct window *w, Bufpos new_point, int no_output_end); void redisplay_redraw_cursor (struct frame *f, int run_begin_end_meths); diff --git a/src/s/cygwin32.h b/src/s/cygwin32.h index 65ee42d..19d7c55 100644 --- a/src/s/cygwin32.h +++ b/src/s/cygwin32.h @@ -105,6 +105,19 @@ extern long random(); #endif #endif +#ifndef SPI_GETWHEELSCROLLLINES +#define SPI_GETWHEELSCROLLLINES 104 +#endif +#ifndef WHEEL_PAGESCROLL +#define WHEEL_PAGESCROLL (UINT_MAX) +#endif +#ifndef WHEEL_DELTA +#define WHEEL_DELTA 120 +#endif +#ifndef WM_MOUSEWHEEL +#define WM_MOUSEWHEEL 0x20A +#endif + #define PBS_SMOOTH 0x01 #ifdef HAVE_MS_WINDOWS diff --git a/src/s/mingw32.h b/src/s/mingw32.h index 4f0fd96..8168d5a 100644 --- a/src/s/mingw32.h +++ b/src/s/mingw32.h @@ -54,6 +54,19 @@ Boston, MA 02111-1307, USA. */ #define SHGFI_EXETYPE 0x2000 #define NSIG 23 +#ifndef SPI_GETWHEELSCROLLLINES +#define SPI_GETWHEELSCROLLLINES 104 +#endif +#ifndef WHEEL_PAGESCROLL +#define WHEEL_PAGESCROLL (UINT_MAX) +#endif +#ifndef WHEEL_DELTA +#define WHEEL_DELTA 120 +#endif +#ifndef WM_MOUSEWHEEL +#define WM_MOUSEWHEEL 0x20A +#endif + /* translate NT world unexec stuff to our a.out definitions */ #define strnicmp strncasecmp diff --git a/src/s/windowsnt.h b/src/s/windowsnt.h index da826bc..50bf0d9 100644 --- a/src/s/windowsnt.h +++ b/src/s/windowsnt.h @@ -370,3 +370,10 @@ int getegid (); #pragma data_seg("xdata") #pragma bss_seg("xdata") #endif + +#ifdef HAVE_SCROLLBARS +/* Ensure the NT 4 mouse definitions in winuser.h are available */ + #ifndef _WIN32_WINNT + #define _WIN32_WINNT 0x0400 + #endif +#endif diff --git a/src/scrollbar-msw.c b/src/scrollbar-msw.c index 20eeb9c..4f5a0fd 100644 --- a/src/scrollbar-msw.c +++ b/src/scrollbar-msw.c @@ -24,6 +24,7 @@ Boston, MA 02111-1307, USA. */ /* Synched up with: Not in FSF. */ #include +#include #include "lisp.h" #include "console-msw.h" @@ -265,6 +266,69 @@ mswindows_handle_scrollbar_event (HWND hwnd, int code, int pos) } } +static int +can_scroll(struct scrollbar_instance* scrollbar) +{ + return scrollbar != NULL + && IsWindowVisible (SCROLLBAR_MSW_HANDLE (scrollbar)) + && IsWindowEnabled (SCROLLBAR_MSW_HANDLE (scrollbar)); +} + +int +mswindows_handle_mousewheel_event (Lisp_Object frame, int keys, int delta) +{ + int hasVertBar, hasHorzBar; /* Indicates prescence of scroll bars */ + unsigned wheelScrollLines = 0; /* Number of lines per wheel notch */ + + /* Find the currently selected window */ + Lisp_Object win = FRAME_SELECTED_WINDOW (XFRAME (frame)); + struct window* w = XWINDOW (win); + struct window_mirror* mirror = find_window_mirror (w); + + /* Check that there is something to scroll */ + hasVertBar = can_scroll (mirror->scrollbar_vertical_instance); + hasHorzBar = can_scroll (mirror->scrollbar_horizontal_instance); + if (!hasVertBar && !hasHorzBar) + return FALSE; + + /* No support for panning and zooming, so ignore */ + if (keys & (MK_SHIFT | MK_CONTROL)) + return FALSE; + + /* Get the number of lines per wheel delta */ + SystemParametersInfo (SPI_GETWHEELSCROLLLINES, 0, &wheelScrollLines, 0); + + /* Calculate the amount to scroll */ + if (wheelScrollLines == WHEEL_PAGESCROLL) + { + /* Scroll by a page */ + Lisp_Object function; + if (hasVertBar) + function = delta > 0 ? Qscrollbar_page_up : Qscrollbar_page_down; + else + function = delta > 0 ? Qscrollbar_page_left : Qscrollbar_page_right; + mswindows_enqueue_misc_user_event (frame, function, Fcons (win, Qnil)); + } + else /* Scroll by a number of lines */ + { + /* Calc the number of lines to scroll */ + int toScroll = MulDiv (delta, wheelScrollLines, WHEEL_DELTA); + + /* Do the scroll */ + Lisp_Object function; + if (hasVertBar) + function = delta > 0 ? Qscrollbar_line_up : Qscrollbar_line_down; + else + function = delta > 0 ? Qscrollbar_char_left : Qscrollbar_char_right; + if (toScroll < 0) + toScroll = -toScroll; + while (toScroll--) + mswindows_enqueue_misc_user_event (frame, function, win); + } + + return TRUE; +} + #ifdef MEMORY_USAGE_STATS static int diff --git a/src/scrollbar-msw.h b/src/scrollbar-msw.h index 615a546..d73a7fe 100644 --- a/src/scrollbar-msw.h +++ b/src/scrollbar-msw.h @@ -57,6 +57,7 @@ EMACS_INT mswindows_window_is_scrollbar (struct frame *f, Window win); */ void mswindows_handle_scrollbar_event (HWND hwnd, int code, int pos); +int mswindows_handle_mousewheel_event (Lisp_Object frame, int keys, int delta); #endif /* HAVE_MS_WINDOWS and HAVE_SCROLLBARS */ #endif /* _XEMACS_SCROLLBAR_MSW_H_ */ diff --git a/src/scrollbar-x.c b/src/scrollbar-x.c index e35084e..7034321 100644 --- a/src/scrollbar-x.c +++ b/src/scrollbar-x.c @@ -27,6 +27,7 @@ Boston, MA 02111-1307, USA. */ #include "lisp.h" #include "console-x.h" +#include "EmacsFrame.h" #include "glyphs-x.h" #include "gui-x.h" #include "scrollbar-x.h" @@ -672,19 +673,6 @@ x_scrollbar_pointer_changed_in_window (struct window *w) 0, (Window) NULL); } -/* Called directly from x_any_window_to_frame in frame-x.c */ -EMACS_INT -x_window_is_scrollbar (struct frame *f, Window win) -{ - if (!FRAME_X_P (f)) - return 0; - - if (f->mirror_dirty) - update_frame_window_mirror (f); - return (EMACS_INT) x_scrollbar_loop (X_WINDOW_IS_SCROLLBAR, f->root_window, - f->root_mirror, 0, win); -} - /* Make sure that all scrollbars on frame are up-to-date. Called directly from x_set_frame_properties in frame-x.c*/ void @@ -745,8 +733,16 @@ console_type_create_scrollbar_x (void) } void +reinit_vars_of_scrollbar_x (void) +{ + stupid_vertical_scrollbar_drag_hack = 1; +} + +void vars_of_scrollbar_x (void) { + reinit_vars_of_scrollbar_x (); + #if defined (LWLIB_SCROLLBARS_LUCID) Fprovide (intern ("lucid-scrollbars")); #elif defined (LWLIB_SCROLLBARS_MOTIF) @@ -754,5 +750,4 @@ vars_of_scrollbar_x (void) #elif defined (LWLIB_SCROLLBARS_ATHENA) Fprovide (intern ("athena-scrollbars")); #endif - stupid_vertical_scrollbar_drag_hack = 1; } diff --git a/src/scrollbar-x.h b/src/scrollbar-x.h index 071cc7c..d4b1652 100644 --- a/src/scrollbar-x.h +++ b/src/scrollbar-x.h @@ -69,7 +69,6 @@ struct x_scrollbar_data void x_update_frame_scrollbars (struct frame *f); void x_set_scrollbar_pointer (struct frame *f, Lisp_Object cursor); -EMACS_INT x_window_is_scrollbar (struct frame *f, Window win); #endif /* HAVE_X_WINDOWS and HAVE_SCROLLBARS */ #endif /* _XEMACS_SCROLLBAR_H_ */ diff --git a/src/search.c b/src/search.c index 445bd87..a66abc0 100644 --- a/src/search.c +++ b/src/search.c @@ -54,10 +54,10 @@ struct regexp_cache { }; /* The instances of that struct. */ -struct regexp_cache searchbufs[REGEXP_CACHE_SIZE]; +static struct regexp_cache searchbufs[REGEXP_CACHE_SIZE]; /* The head of the linked list; points to the most recently used buffer. */ -struct regexp_cache *searchbuf_head; +static struct regexp_cache *searchbuf_head; /* Every call to re_match, etc., must pass &search_regs as the regs @@ -2574,9 +2574,12 @@ syms_of_search (void) } void -vars_of_search (void) +reinit_vars_of_search (void) { - REGISTER int i; + int i; + + last_thing_searched = Qnil; + staticpro_nodump (&last_thing_searched); for (i = 0; i < REGEXP_CACHE_SIZE; ++i) { @@ -2584,13 +2587,16 @@ vars_of_search (void) searchbufs[i].buf.buffer = (unsigned char *) xmalloc (100); searchbufs[i].buf.fastmap = searchbufs[i].fastmap; searchbufs[i].regexp = Qnil; - staticpro (&searchbufs[i].regexp); + staticpro_nodump (&searchbufs[i].regexp); searchbufs[i].next = (i == REGEXP_CACHE_SIZE-1 ? 0 : &searchbufs[i+1]); } searchbuf_head = &searchbufs[0]; +} - last_thing_searched = Qnil; - staticpro (&last_thing_searched); +void +vars_of_search (void) +{ + reinit_vars_of_search (); DEFVAR_LISP ("forward-word-regexp", &Vforward_word_regexp /* *Regular expression to be used in `forward-word'. diff --git a/src/select-x.c b/src/select-x.c index cc6031a..0332a45 100644 --- a/src/select-x.c +++ b/src/select-x.c @@ -1492,15 +1492,18 @@ initialize_cut_buffers (Display *display, Window window) cut_buffers_initialized = 1; } -#define CHECK_CUTBUFFER(symbol) \ - { CHECK_SYMBOL (symbol); \ - if (!EQ((symbol),QCUT_BUFFER0) && !EQ((symbol),QCUT_BUFFER1) && \ - !EQ((symbol),QCUT_BUFFER2) && !EQ((symbol),QCUT_BUFFER3) && \ - !EQ((symbol),QCUT_BUFFER4) && !EQ((symbol),QCUT_BUFFER5) && \ - !EQ((symbol),QCUT_BUFFER6) && !EQ((symbol),QCUT_BUFFER7)) \ - signal_error (Qerror, list2 (build_string ("Doesn't name a cutbuffer"), \ - (symbol))); \ - } +#define CHECK_CUTBUFFER(symbol) do { \ + CHECK_SYMBOL (symbol); \ + if (! (EQ (symbol, QCUT_BUFFER0) || \ + EQ (symbol, QCUT_BUFFER1) || \ + EQ (symbol, QCUT_BUFFER2) || \ + EQ (symbol, QCUT_BUFFER3) || \ + EQ (symbol, QCUT_BUFFER4) || \ + EQ (symbol, QCUT_BUFFER5) || \ + EQ (symbol, QCUT_BUFFER6) || \ + EQ (symbol, QCUT_BUFFER7))) \ + signal_simple_error ("Doesn't name a cutbuffer", symbol); \ +} while (0) DEFUN ("x-get-cutbuffer-internal", Fx_get_cutbuffer_internal, 1, 1, 0, /* Return the value of the named CUTBUFFER (typically CUT_BUFFER0). @@ -1694,18 +1697,24 @@ console_type_create_select_x (void) } void -vars_of_xselect (void) +reinit_vars_of_xselect (void) { -#ifdef CUT_BUFFER_SUPPORT - cut_buffers_initialized = 0; - Fprovide (intern ("cut-buffer")); -#endif - reading_selection_reply = 0; reading_which_selection = 0; selection_reply_timed_out = 0; for_whom_the_bell_tolls = 0; prop_location_tick = 0; +} + +void +vars_of_xselect (void) +{ + reinit_vars_of_xselect (); + +#ifdef CUT_BUFFER_SUPPORT + cut_buffers_initialized = 0; + Fprovide (intern ("cut-buffer")); +#endif DEFVAR_LISP ("x-sent-selection-hooks", &Vx_sent_selection_hooks /* A function or functions to be called after we have responded to some diff --git a/src/sound.c b/src/sound.c index 170efbd..0260728 100644 --- a/src/sound.c +++ b/src/sound.c @@ -25,6 +25,7 @@ Boston, MA 02111-1307, USA. */ Hacked on quite a bit by various others. */ #include +#include #include "lisp.h" #include "buffer.h" @@ -45,6 +46,7 @@ Boston, MA 02111-1307, USA. */ #endif int bell_volume; +int bell_inhibit_time; Lisp_Object Vsound_alist; Lisp_Object Vsynchronous_sounds; Lisp_Object Vnative_sound_only_on_console; @@ -347,25 +349,28 @@ device). */ (arg, sound, device)) { - struct device *d = decode_device (device); + static time_t last_bell_time = (time_t) 0; + static struct device *last_bell_device = (struct device*) 0; + time_t now; + struct device *d = decode_device (device); XSETDEVICE (device, d); + now = time (0); - /* #### This is utterly disgusting, and is probably a remnant from - legacy code that used `ding'+`message' to signal error instead - calling `error'. As a result, there is no way to beep from Lisp - directly, without also invoking this aspect. Maybe we should - define a `ring-bell' function that simply beeps on the console, - which `ding' should invoke? --hniksic */ if (NILP (arg) && !NILP (Vexecuting_macro)) /* Stop executing a keyboard macro. */ error ("Keyboard macro terminated by a command ringing the bell"); + + if (d == last_bell_device && now-last_bell_time < bell_inhibit_time) + return Qnil; else if (visible_bell && DEVMETH (d, flash, (d))) ; else Fplay_sound (sound, Qnil, device); - - return Qnil; + + last_bell_time = now; + last_bell_device = d; + return Qnil; } DEFUN ("wait-for-sounds", Fwait_for_sounds, 0, 1, 0, /* @@ -532,6 +537,11 @@ vars_of_sound (void) *How loud to be, from 0 to 100. */ ); bell_volume = 50; + + DEFVAR_INT ("bell-inhibit-time", &bell_inhibit_time /* +*Don't ring the bell on the same device more than once within this many seconds. +*/ ); + bell_inhibit_time = 0; DEFVAR_LISP ("sound-alist", &Vsound_alist /* An alist associating names with sounds. @@ -559,8 +569,8 @@ You should probably add things to this list by calling the function load-sound-file. Caveats: - - You can only play audio data if running on the console screen of a - Sun SparcStation, SGI, or HP9000s700. + - XEmacs must be built with sound support for your system. Not all + systems support sound. - The pitch, duration, and volume options are available everywhere, but many X servers ignore the `pitch' option. diff --git a/src/specifier.c b/src/specifier.c index 6c5942a..b344d5f 100644 --- a/src/specifier.c +++ b/src/specifier.c @@ -64,7 +64,28 @@ typedef struct Dynarr_declare (specifier_type_entry); } specifier_type_entry_dynarr; -specifier_type_entry_dynarr *the_specifier_type_entry_dynarr; +static specifier_type_entry_dynarr *the_specifier_type_entry_dynarr; + +static const struct lrecord_description ste_description_1[] = { + { XD_LISP_OBJECT, offsetof(specifier_type_entry, symbol), 1 }, + { XD_STRUCT_PTR, offsetof(specifier_type_entry, meths), 1, &specifier_methods_description }, + { XD_END } +}; + +static const struct struct_description ste_description = { + sizeof(specifier_type_entry), + ste_description_1 +}; + +static const struct lrecord_description sted_description_1[] = { + XD_DYNARR_DESC(specifier_type_entry_dynarr, &ste_description), + { XD_END } +}; + +static const struct struct_description sted_description = { + sizeof(specifier_type_entry_dynarr), + sted_description_1 +}; static Lisp_Object Vspecifier_type_list; @@ -180,19 +201,19 @@ kill_specifier_buffer_locals (Lisp_Object buffer) } static Lisp_Object -mark_specifier (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_specifier (Lisp_Object obj) { struct Lisp_Specifier *specifier = XSPECIFIER (obj); - markobj (specifier->global_specs); - markobj (specifier->device_specs); - markobj (specifier->frame_specs); - markobj (specifier->window_specs); - markobj (specifier->buffer_specs); - markobj (specifier->magic_parent); - markobj (specifier->fallback); + mark_object (specifier->global_specs); + mark_object (specifier->device_specs); + mark_object (specifier->frame_specs); + mark_object (specifier->window_specs); + mark_object (specifier->buffer_specs); + mark_object (specifier->magic_parent); + mark_object (specifier->fallback); if (!GHOST_SPECIFIER_P (XSPECIFIER (obj))) - MAYBE_SPECMETH (specifier, mark, (obj, markobj)); + MAYBE_SPECMETH (specifier, mark, (obj)); return Qnil; } @@ -216,24 +237,24 @@ mark_specifier (Lisp_Object obj, void (*markobj) (Lisp_Object)) */ void -prune_specifiers (int (*obj_marked_p) (Lisp_Object)) +prune_specifiers (void) { Lisp_Object rest, prev = Qnil; for (rest = Vall_specifiers; - !GC_NILP (rest); + !NILP (rest); rest = XSPECIFIER (rest)->next_specifier) { - if (! obj_marked_p (rest)) + if (! marked_p (rest)) { struct Lisp_Specifier* sp = XSPECIFIER (rest); /* A bit of assertion that we're removing both parts of the magic one altogether */ - assert (!GC_MAGIC_SPECIFIER_P(sp) - || (GC_BODILY_SPECIFIER_P(sp) && obj_marked_p (sp->fallback)) - || (GC_GHOST_SPECIFIER_P(sp) && obj_marked_p (sp->magic_parent))); + assert (!MAGIC_SPECIFIER_P(sp) + || (BODILY_SPECIFIER_P(sp) && marked_p (sp->fallback)) + || (GHOST_SPECIFIER_P(sp) && marked_p (sp->magic_parent))); /* This specifier is garbage. Remove it from the list. */ - if (GC_NILP (prev)) + if (NILP (prev)) Vall_specifiers = sp->next_specifier; else XSPECIFIER (prev)->next_specifier = sp->next_specifier; @@ -280,7 +301,7 @@ finalize_specifier (void *header, int for_disksave) { struct Lisp_Specifier *sp = (struct Lisp_Specifier *) header; /* don't be snafued by the disksave finalization. */ - if (!for_disksave && !GC_GHOST_SPECIFIER_P(sp) && sp->caching) + if (!for_disksave && !GHOST_SPECIFIER_P(sp) && sp->caching) { xfree (sp->caching); sp->caching = 0; @@ -336,18 +357,51 @@ static size_t sizeof_specifier (CONST void *header) { if (GHOST_SPECIFIER_P ((struct Lisp_Specifier *) header)) - return sizeof (struct Lisp_Specifier); + return offsetof (struct Lisp_Specifier, data); else { CONST struct Lisp_Specifier *p = (CONST struct Lisp_Specifier *) header; - return sizeof (*p) + p->methods->extra_data_size - 1; + return offsetof (struct Lisp_Specifier, data) + p->methods->extra_data_size; } } +static const struct lrecord_description specifier_methods_description_1[] = { + { XD_LISP_OBJECT, offsetof(struct specifier_methods, predicate_symbol), 1 }, + { XD_END } +}; + +const struct struct_description specifier_methods_description = { + sizeof(struct specifier_methods), + specifier_methods_description_1 +}; + +static const struct lrecord_description specifier_caching_description_1[] = { + { XD_END } +}; + +static const struct struct_description specifier_caching_description = { + sizeof(struct specifier_caching), + specifier_caching_description_1 +}; + +static const struct lrecord_description specifier_description[] = { + { XD_STRUCT_PTR, offsetof(struct Lisp_Specifier, methods), 1, &specifier_methods_description }, + { XD_LO_LINK, offsetof(struct Lisp_Specifier, next_specifier) }, + { XD_LISP_OBJECT, offsetof(struct Lisp_Specifier, global_specs), 5 }, + { XD_STRUCT_PTR, offsetof(struct Lisp_Specifier, caching), 1, &specifier_caching_description }, + { XD_LISP_OBJECT, offsetof(struct Lisp_Specifier, magic_parent), 2 }, + { XD_SPECIFIER_END } +}; + +const struct lrecord_description specifier_empty_extra_description[] = { + { XD_END } +}; + DEFINE_LRECORD_SEQUENCE_IMPLEMENTATION ("specifier", specifier, mark_specifier, print_specifier, finalize_specifier, - specifier_equal, specifier_hash, 0, + specifier_equal, specifier_hash, + specifier_description, sizeof_specifier, struct Lisp_Specifier); @@ -414,8 +468,8 @@ make_specifier_internal (struct specifier_methods *spec_meths, { Lisp_Object specifier; struct Lisp_Specifier *sp = (struct Lisp_Specifier *) - alloc_lcrecord (sizeof (struct Lisp_Specifier) + - data_size - 1, &lrecord_specifier); + alloc_lcrecord (offsetof (struct Lisp_Specifier, data) + + data_size, &lrecord_specifier); sp->methods = spec_meths; sp->global_specs = Qnil; @@ -3125,6 +3179,7 @@ void specifier_type_create (void) { the_specifier_type_entry_dynarr = Dynarr_new (specifier_type_entry); + dumpstruct (&the_specifier_type_entry_dynarr, &sted_description); Vspecifier_type_list = Qnil; staticpro (&Vspecifier_type_list); @@ -3149,6 +3204,16 @@ specifier_type_create (void) } void +reinit_specifier_type_create (void) +{ + REINITIALIZE_SPECIFIER_TYPE (generic); + REINITIALIZE_SPECIFIER_TYPE (integer); + REINITIALIZE_SPECIFIER_TYPE (natnum); + REINITIALIZE_SPECIFIER_TYPE (boolean); + REINITIALIZE_SPECIFIER_TYPE (display_table); +} + +void vars_of_specifier (void) { Vcached_specifiers = Qnil; @@ -3157,6 +3222,7 @@ vars_of_specifier (void) /* Do NOT mark through this, or specifiers will never be GC'd. This is the same deal as for weak hash tables. */ Vall_specifiers = Qnil; + pdump_wire_list (&Vall_specifiers); Vuser_defined_tags = Qnil; staticpro (&Vuser_defined_tags); diff --git a/src/specifier.h b/src/specifier.h index 674be41..506319e 100644 --- a/src/specifier.h +++ b/src/specifier.h @@ -83,6 +83,8 @@ Boston, MA 02111-1307, USA. */ same time. */ +extern const struct struct_description specifier_methods_description; + struct specifier_methods { CONST char *name; @@ -95,7 +97,7 @@ struct specifier_methods /* Mark method: Mark any lisp object within specifier data structure. Not required if no specifier data are Lisp_Objects. */ - void (*mark_method) (Lisp_Object specifier, void (*markobj) (Lisp_Object)); + void (*mark_method) (Lisp_Object specifier); /* Equal method: Compare two specifiers. This is called after ensuring that the two specifiers are of the same type, and have @@ -185,6 +187,7 @@ struct specifier_methods void (*after_change_method) (Lisp_Object specifier, Lisp_Object locale); + const struct lrecord_description *extra_description; int extra_data_size; }; @@ -232,7 +235,6 @@ DECLARE_LRECORD (specifier, struct Lisp_Specifier); #define XSPECIFIER(x) XRECORD (x, specifier, struct Lisp_Specifier) #define XSETSPECIFIER(x, p) XSETRECORD (x, p, specifier) #define SPECIFIERP(x) RECORDP (x, specifier) -#define GC_SPECIFIERP(x) GC_RECORDP (x, specifier) #define CHECK_SPECIFIER(x) CHECK_RECORD (x, specifier) #define CONCHECK_SPECIFIER(x) CONCHECK_RECORD (x, specifier) @@ -251,6 +253,9 @@ DECLARE_LRECORD (specifier, struct Lisp_Specifier); /***** Defining new specifier types *****/ +#define specifier_data_offset (offsetof(struct Lisp_Specifier, data)) +extern const struct lrecord_description specifier_empty_extra_description[]; + #ifdef ERROR_CHECK_TYPECHECK #define DECLARE_SPECIFIER_TYPE(type) \ extern struct specifier_methods * type##_specifier_methods; \ @@ -279,10 +284,17 @@ extern struct specifier_methods * type##_specifier_methods struct specifier_methods * type##_specifier_methods #define INITIALIZE_SPECIFIER_TYPE(type, obj_name, pred_sym) do { \ - type##_specifier_methods = xnew_and_zero (struct specifier_methods); \ - type##_specifier_methods->name = obj_name; \ - defsymbol (&type##_specifier_methods->predicate_symbol, pred_sym); \ - add_entry_to_specifier_type_list (Q##type, type##_specifier_methods); \ + type##_specifier_methods = xnew_and_zero (struct specifier_methods); \ + type##_specifier_methods->name = obj_name; \ + type##_specifier_methods->extra_description = \ + specifier_empty_extra_description; \ + defsymbol_nodump (&type##_specifier_methods->predicate_symbol, pred_sym); \ + add_entry_to_specifier_type_list (Q##type, type##_specifier_methods); \ + dumpstruct (&type##_specifier_methods, &specifier_methods_description); \ +} while (0) + +#define REINITIALIZE_SPECIFIER_TYPE(type) do { \ + staticpro_nodump (&type##_specifier_methods->predicate_symbol); \ } while (0) #define INITIALIZE_SPECIFIER_TYPE_WITH_DATA(type, obj_name, pred_sym) \ @@ -290,6 +302,8 @@ do { \ INITIALIZE_SPECIFIER_TYPE (type, obj_name, pred_sym); \ type##_specifier_methods->extra_data_size = \ sizeof (struct type##_specifier); \ + type##_specifier_methods->extra_description = \ + type##_specifier_description; \ } while (0) /* Declare that specifier-type TYPE has method METH; used in @@ -303,24 +317,13 @@ do { \ ((sp)->methods == type##_specifier_methods) /* Any of the two of the magic spec */ -#define MAGIC_SPECIFIER_P(sp) \ - (!NILP((sp)->magic_parent)) +#define MAGIC_SPECIFIER_P(sp) (!NILP((sp)->magic_parent)) /* Normal part of the magic specifier */ -#define BODILY_SPECIFIER_P(sp) \ - (EQ ((sp)->magic_parent, Qt)) +#define BODILY_SPECIFIER_P(sp) EQ ((sp)->magic_parent, Qt) /* Ghost part of the magic specifier */ -#define GHOST_SPECIFIER_P(sp) \ - (SPECIFIERP((sp)->magic_parent)) -/* The same three, when used in GC */ -#define GC_MAGIC_SPECIFIER_P(sp) \ - (!GC_NILP((sp)->magic_parent)) -#define GC_BODILY_SPECIFIER_P(sp) \ - (GC_EQ ((sp)->magic_parent, Qt)) -#define GC_GHOST_SPECIFIER_P(sp) \ - (GC_SPECIFIERP((sp)->magic_parent)) - -#define GHOST_SPECIFIER(sp) \ - (XSPECIFIER ((sp)->fallback)) +#define GHOST_SPECIFIER_P(sp) SPECIFIERP((sp)->magic_parent) + +#define GHOST_SPECIFIER(sp) XSPECIFIER ((sp)->fallback) #ifdef ERROR_CHECK_TYPECHECK # define SPECIFIER_TYPE_DATA(sp, type) \ @@ -425,7 +428,7 @@ void remove_ghost_specifier (Lisp_Object specifier, Lisp_Object locale, int unlock_ghost_specifiers_protected (void); void cleanup_specifiers (void); -void prune_specifiers (int (*obj_marked_p) (Lisp_Object)); +void prune_specifiers (void); void setup_device_initial_specifier_tags (struct device *d); void kill_specifier_buffer_locals (Lisp_Object buffer); diff --git a/src/symbols.c b/src/symbols.c index 9b3192d..8c45073 100644 --- a/src/symbols.c +++ b/src/symbols.c @@ -63,7 +63,7 @@ Lisp_Object Qad_advice_info, Qad_activate; Lisp_Object Qget_value, Qset_value, Qbound_predicate, Qmake_unbound; Lisp_Object Qlocal_predicate, Qmake_local; -Lisp_Object Qboundp, Qfboundp, Qglobally_boundp, Qmakunbound; +Lisp_Object Qboundp, Qglobally_boundp, Qmakunbound; Lisp_Object Qsymbol_value, Qset, Qdefault_boundp, Qdefault_value; Lisp_Object Qset_default, Qsetq_default; Lisp_Object Qmake_variable_buffer_local, Qmake_local_variable; @@ -87,20 +87,20 @@ static Lisp_Object follow_varalias_pointers (Lisp_Object symbol, static Lisp_Object -mark_symbol (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_symbol (Lisp_Object obj) { struct Lisp_Symbol *sym = XSYMBOL (obj); Lisp_Object pname; - markobj (sym->value); - markobj (sym->function); + mark_object (sym->value); + mark_object (sym->function); XSETSTRING (pname, sym->name); - markobj (pname); + mark_object (pname); if (!symbol_next (sym)) return sym->plist; else { - markobj (sym->plist); + mark_object (sym->plist); /* Mark the rest of the symbols in the obarray hash-chain */ sym = symbol_next (sym); XSETSYMBOL (obj, sym); @@ -109,7 +109,8 @@ mark_symbol (Lisp_Object obj, void (*markobj) (Lisp_Object)) } static const struct lrecord_description symbol_description[] = { - { XD_LISP_OBJECT, offsetof(struct Lisp_Symbol, next), 5 } + { XD_LISP_OBJECT, offsetof(struct Lisp_Symbol, next), 5 }, + { XD_END } }; DEFINE_BASIC_LRECORD_IMPLEMENTATION ("symbol", symbol, @@ -895,8 +896,7 @@ Set SYMBOL's property list to NEWPLIST, and return NEWPLIST. symbol to operate on. */ static Lisp_Object -mark_symbol_value_buffer_local (Lisp_Object obj, - void (*markobj) (Lisp_Object)) +mark_symbol_value_buffer_local (Lisp_Object obj) { struct symbol_value_buffer_local *bfwd; @@ -906,15 +906,14 @@ mark_symbol_value_buffer_local (Lisp_Object obj, #endif bfwd = XSYMBOL_VALUE_BUFFER_LOCAL (obj); - markobj (bfwd->default_value); - markobj (bfwd->current_value); - markobj (bfwd->current_buffer); + mark_object (bfwd->default_value); + mark_object (bfwd->current_value); + mark_object (bfwd->current_buffer); return bfwd->current_alist_element; } static Lisp_Object -mark_symbol_value_lisp_magic (Lisp_Object obj, - void (*markobj) (Lisp_Object)) +mark_symbol_value_lisp_magic (Lisp_Object obj) { struct symbol_value_lisp_magic *bfwd; int i; @@ -924,22 +923,21 @@ mark_symbol_value_lisp_magic (Lisp_Object obj, bfwd = XSYMBOL_VALUE_LISP_MAGIC (obj); for (i = 0; i < MAGIC_HANDLER_MAX; i++) { - markobj (bfwd->handler[i]); - markobj (bfwd->harg[i]); + mark_object (bfwd->handler[i]); + mark_object (bfwd->harg[i]); } return bfwd->shadowed; } static Lisp_Object -mark_symbol_value_varalias (Lisp_Object obj, - void (*markobj) (Lisp_Object)) +mark_symbol_value_varalias (Lisp_Object obj) { struct symbol_value_varalias *bfwd; assert (XSYMBOL_VALUE_MAGIC_TYPE (obj) == SYMVAL_VARALIAS); bfwd = XSYMBOL_VALUE_VARALIAS (obj); - markobj (bfwd->shadowed); + mark_object (bfwd->shadowed); return bfwd->aliasee; } @@ -956,8 +954,13 @@ print_symbol_value_magic (Lisp_Object obj, write_c_string (buf, printcharfun); } +static const struct lrecord_description symbol_value_forward_description[] = { + { XD_END } +}; + static const struct lrecord_description symbol_value_buffer_local_description[] = { - { XD_LISP_OBJECT, offsetof(struct symbol_value_buffer_local, default_value), 4 }, + { XD_LISP_OBJECT, offsetof(struct symbol_value_buffer_local, default_value), 1 }, + { XD_LO_RESET_NIL, offsetof(struct symbol_value_buffer_local, current_value), 3 }, { XD_END } }; @@ -974,7 +977,8 @@ static const struct lrecord_description symbol_value_varalias_description[] = { DEFINE_LRECORD_IMPLEMENTATION ("symbol-value-forward", symbol_value_forward, this_one_is_unmarkable, - print_symbol_value_magic, 0, 0, 0, 0, + print_symbol_value_magic, 0, 0, 0, + symbol_value_forward_description, struct symbol_value_forward); DEFINE_LRECORD_IMPLEMENTATION ("symbol-value-buffer-local", @@ -1214,7 +1218,7 @@ store_symval_forwarding (Lisp_Object sym, Lisp_Object ovalue, if (magicfun) magicfun (sym, &newval, Qnil, 0); *((int *) symbol_value_forward_forward (fwd)) - = ((NILP (newval)) ? 0 : 1); + = !NILP (newval); return; case SYMVAL_OBJECT_FORWARD: @@ -1547,7 +1551,9 @@ find_symbol_value (Lisp_Object sym) /* This can also get called while we're preparing to shutdown. #### What should really happen in that case? Should we actually fix things so we can't get here in that case? */ +#ifndef PDUMP assert (!initialized || preparing_for_armageddon); +#endif con = 0; } @@ -1583,7 +1589,9 @@ find_symbol_value_quickly (Lisp_Object symbol_cons, int find_it_p) /* This can also get called while we're preparing to shutdown. #### What should really happen in that case? Should we actually fix things so we can't get here in that case? */ +#ifndef PDUMP assert (!initialized || preparing_for_armageddon); +#endif con = 0; } @@ -3153,6 +3161,19 @@ init_symbols_once_early (void) defsymbol (&Qt, "t"); XSYMBOL (Qt)->value = Qt; /* Veritas aetera */ Vquit_flag = Qnil; + + pdump_wire (&Qnil); + pdump_wire (&Qunbound); + pdump_wire (&Vquit_flag); +} + +void +defsymbol_nodump (Lisp_Object *location, CONST char *name) +{ + *location = Fintern (make_string_nocopy ((CONST Bufbyte *) name, + strlen (name)), + Qnil); + staticpro_nodump (location); } void @@ -3268,11 +3289,11 @@ deferror (Lisp_Object *symbol, CONST char *name, CONST char *messuhhj, assert (SYMBOLP (inherits_from)); conds = Fget (inherits_from, Qerror_conditions, Qnil); - pure_put (*symbol, Qerror_conditions, Fcons (*symbol, conds)); + Fput (*symbol, Qerror_conditions, Fcons (*symbol, conds)); /* NOT build_translated_string (). This function is called at load time and the string needs to get translated at run time. (This happens in the function (display-error) in cmdloop.el.) */ - pure_put (*symbol, Qerror_message, build_string (messuhhj)); + Fput (*symbol, Qerror_message, build_string (messuhhj)); } void @@ -3291,7 +3312,6 @@ syms_of_symbols (void) defsymbol (&Qmake_local, "make-local"); defsymbol (&Qboundp, "boundp"); - defsymbol (&Qfboundp, "fboundp"); defsymbol (&Qglobally_boundp, "globally-boundp"); defsymbol (&Qmakunbound, "makunbound"); defsymbol (&Qsymbol_value, "symbol-value"); diff --git a/src/symeval.h b/src/symeval.h index 7aa5c48..f51e9a4 100644 --- a/src/symeval.h +++ b/src/symeval.h @@ -282,6 +282,7 @@ void defsubr_macro (Lisp_Subr *); #define DEFSUBR_MACRO(Fname) defsubr_macro (&S##Fname) void defsymbol (Lisp_Object *location, CONST char *name); +void defsymbol_nodump (Lisp_Object *location, CONST char *name); void defkeyword (Lisp_Object *location, CONST char *name); diff --git a/src/symsinit.h b/src/symsinit.h index 1e0136a..5fbcd26 100644 --- a/src/symsinit.h +++ b/src/symsinit.h @@ -33,11 +33,13 @@ void init_process_times_very_early (void); void init_ralloc (void); void init_signals_very_early (void); -/* Early Lisp-engine initialization (dump-time only). */ +/* Early Lisp-engine initialization (dump-time for init, run-time for reinit). */ void init_alloc_once_early (void); +void reinit_alloc_once_early (void); void init_symbols_once_early (void); void init_errors_once_early (void); +void reinit_opaque_once_early (void); void init_opaque_once_early (void); /* Declare the built-in symbols and primitives (dump-time only). */ @@ -147,17 +149,21 @@ void syms_of_window (void); void syms_of_xselect (void); void syms_of_eldap (void); -/* Initialize the console types (dump-time only). */ +/* Initialize the console types (dump-time but for reinit_). */ void console_type_create (void); void console_type_create_stream (void); +void reinit_console_type_create_stream (void); void console_type_create_tty (void); +void reinit_console_type_create_tty (void); void console_type_create_device_tty (void); void console_type_create_frame_tty (void); void console_type_create_objects_tty (void); void console_type_create_redisplay_tty (void); void console_type_create_x (void); +void reinit_console_type_create_x (void); void console_type_create_device_x (void); +void reinit_console_type_create_device_x (void); void console_type_create_frame_x (void); void console_type_create_glyphs_x (void); void console_type_create_menubar_x (void); @@ -168,6 +174,7 @@ void console_type_create_select_x (void); void console_type_create_toolbar_x (void); void console_type_create_dialog_x (void); void console_type_create_mswindows (void); +void reinit_console_type_create_mswindows (void); void console_type_create_device_mswindows (void); void console_type_create_frame_mswindows (void); void console_type_create_menubar_mswindows (void); @@ -182,10 +189,15 @@ void console_type_create_select_mswindows (void); /* Initialize the specifier types (dump-time only). */ void specifier_type_create (void); +void reinit_specifier_type_create (void); void specifier_type_create_image (void); +void reinit_specifier_type_create_image (void); void specifier_type_create_gutter (void); +void reinit_specifier_type_create_gutter (void); void specifier_type_create_objects (void); +void reinit_specifier_type_create_objects (void); void specifier_type_create_toolbar (void); +void reinit_specifier_type_create_toolbar (void); /* Initialize the structure types (dump-time only). */ @@ -220,12 +232,13 @@ void process_type_create_unix (void); void init_provide_once (void); -/* Initialize most variables (dump-time only). */ +/* Initialize most variables (dump-time for vars_, run-time for reinit_vars). */ void vars_of_abbrev (void); void vars_of_alloc (void); void vars_of_balloon_x (void); void vars_of_buffer (void); +void reinit_vars_of_buffer (void); void vars_of_bytecode (void); void vars_of_callint (void); void vars_of_callproc (void); @@ -233,15 +246,19 @@ void vars_of_chartab (void); void vars_of_cmdloop (void); void vars_of_cmds (void); void vars_of_console (void); +void reinit_vars_of_console (void); void vars_of_console_stream (void); void vars_of_console_mswindows (void); void vars_of_console_tty (void); void vars_of_data (void); void vars_of_database (void); void vars_of_debug (void); +void reinit_vars_of_debug (void); void vars_of_device (void); +void reinit_vars_of_device (void); void vars_of_device_mswindows (void); void vars_of_device_x (void); +void reinit_vars_of_device_x (void); void vars_of_dialog (void); void vars_of_dialog_x (void); void vars_of_dialog_mswindows (void); @@ -253,17 +270,25 @@ void vars_of_editfns (void); void vars_of_elhash (void); void vars_of_emacs (void); void vars_of_eval (void); +void reinit_vars_of_eval (void); void vars_of_event_stream (void); +void reinit_vars_of_event_stream (void); void vars_of_event_tty (void); +void reinit_vars_of_event_tty (void); void vars_of_event_mswindows (void); +void reinit_vars_of_event_mswindows (void); void vars_of_event_Xt (void); +void reinit_vars_of_event_Xt (void); void vars_of_events (void); +void reinit_vars_of_events (void); void vars_of_extents (void); +void reinit_vars_of_extents (void); void vars_of_faces (void); void vars_of_fileio (void); void vars_of_filelock (void); void vars_of_floatfns (void); void vars_of_font_lock (void); +void reinit_vars_of_font_lock (void); void vars_of_frame_tty (void); void vars_of_frame_mswindows (void); void vars_of_frame_x (void); @@ -271,26 +296,35 @@ void vars_of_frame (void); void vars_of_glyphs_x (void); void vars_of_glyphs_eimage (void); void vars_of_glyphs_widget (void); +void reinit_vars_of_glyphs_widget (void); void vars_of_glyphs_mswindows (void); void vars_of_glyphs (void); +void reinit_vars_of_glyphs (void); void vars_of_gui_x (void); +void reinit_vars_of_gui_x (void); void vars_of_gui (void); void vars_of_gutter (void); void vars_of_input_method_motif (void); void vars_of_input_method_xlib (void); void vars_of_indent (void); void vars_of_insdel (void); +void reinit_vars_of_insdel (void); void vars_of_intl (void); void vars_of_keymap (void); void vars_of_lread (void); +void reinit_vars_of_lread (void); void vars_of_lstream (void); +void reinit_vars_of_lstream (void); void vars_of_macros (void); void vars_of_md5 (void); void vars_of_menubar_x (void); +void reinit_vars_of_menubar_x (void); void vars_of_menubar (void); void vars_of_menubar_mswindows (void); void vars_of_minibuf (void); +void reinit_vars_of_minibuf (void); void vars_of_module (void); +void reinit_vars_of_module (void); void vars_of_mule (void); void vars_of_mule_canna (void); void vars_of_mule_ccl(void); @@ -299,20 +333,25 @@ void vars_of_file_coding (void); void vars_of_mule_wnn (void); void vars_of_ntproc (void); void vars_of_objects (void); +void reinit_vars_of_objects (void); void vars_of_objects_tty (void); void vars_of_objects_mswindows (void); void vars_of_objects_x (void); void vars_of_print (void); +void reinit_vars_of_print (void); void vars_of_process (void); void vars_of_process_nt (void); void vars_of_process_unix (void); void vars_of_profile (void); void vars_of_ralloc (void); void vars_of_redisplay (void); +void reinit_vars_of_redisplay (void); void vars_of_scrollbar_x (void); +void reinit_vars_of_scrollbar_x (void); void vars_of_scrollbar (void); void vars_of_scrollbar_mswindows (void); void vars_of_search (void); +void reinit_vars_of_search (void); void vars_of_select (void); void vars_of_select_mswindows (void); void vars_of_sound (void); @@ -323,8 +362,11 @@ void vars_of_syntax (void); void vars_of_toolbar (void); void vars_of_tooltalk (void); void vars_of_undo (void); +void reinit_vars_of_undo (void); void vars_of_window (void); +void reinit_vars_of_window (void); void vars_of_xselect (void); +void reinit_vars_of_xselect (void); void vars_of_eldap (void); /* Initialize specifier variables (dump-time only). */ @@ -338,7 +380,7 @@ void specifier_vars_of_toolbar (void); void specifier_vars_of_window (void); /* Initialize variables with complex dependencies - on other variables (dump-time only). */ + on other variables (dump-time for complex_vars_, run-time for reinit_). */ void complex_vars_of_regex (void); void complex_vars_of_search (void); @@ -358,11 +400,13 @@ void complex_vars_of_casetab (void); void complex_vars_of_syntax (void); void complex_vars_of_chartab (void); void complex_vars_of_buffer (void); +void reinit_complex_vars_of_buffer (void); void complex_vars_of_console (void); +void reinit_complex_vars_of_console (void); void complex_vars_of_emacs (void); void complex_vars_of_minibuf (void); +void reinit_complex_vars_of_minibuf (void); void complex_vars_of_callproc (void); -void complex_vars_of_filelock (void); void complex_vars_of_keymap (void); /* Reset the Lisp engine (run-time only). */ diff --git a/src/syntax.c b/src/syntax.c index 4fdc4be..4792c2b 100644 --- a/src/syntax.c +++ b/src/syntax.c @@ -327,6 +327,7 @@ syntax table. } + #ifdef MULE /* Return 1 if there is a word boundary between two word-constituent characters C1 and C2 if they appear in this order, else return 0. @@ -337,16 +338,6 @@ syntax table. && word_boundary_p (c1, c2)) extern int word_boundary_p (Emchar c1, Emchar c2); -#else -static int -word_constituent_p (struct buffer *buf, Bufpos pos, - struct Lisp_Char_Table *tab) -{ - enum syntaxcode code = SYNTAX_UNSAFE (tab, BUF_FETCH_CHAR (buf, pos)); - return ((words_include_escapes && - (code == Sescape || code == Scharquote)) - || (code == Sword)); -} #endif /* Return the position across COUNT words from FROM. @@ -358,11 +349,10 @@ scan_words (struct buffer *buf, Bufpos from, int count) { Bufpos limit = count > 0 ? BUF_ZV (buf) : BUF_BEGV (buf); struct Lisp_Char_Table *mirrortab = XCHAR_TABLE (buf->mirror_syntax_table); -#ifdef MULE Emchar ch0, ch1; enum syntaxcode code; -#endif + /* #### is it really worth it to hand expand both cases? JV */ while (count > 0) { QUIT; @@ -371,40 +361,36 @@ scan_words (struct buffer *buf, Bufpos from, int count) { if (from == limit) return 0; -#ifdef MULE + ch0 = BUF_FETCH_CHAR (buf, from); code = SYNTAX_UNSAFE (mirrortab, ch0); -#else - if (word_constituent_p (buf, from, mirrortab)) - break; -#endif - from++; -#ifdef MULE + if (words_include_escapes && (code == Sescape || code == Scharquote)) break; if (code == Sword) break; -#endif + + from++; } QUIT; - while ((from != limit) -#ifndef MULE - && word_constituent_p (buf, from, mirrortab) -#endif - ) + while (from != limit) { -#ifdef MULE ch1 = BUF_FETCH_CHAR (buf, from); code = SYNTAX_UNSAFE (mirrortab, ch1); if (!(words_include_escapes && (code == Sescape || code == Scharquote))) - if (code != Sword || WORD_BOUNDARY_P (ch0, ch1)) + if (code != Sword +#ifdef MULE + || WORD_BOUNDARY_P (ch0, ch1) +#endif + ) break; +#ifdef MULE ch0 = ch1; -#endif +#endif from++; } count--; @@ -418,12 +404,7 @@ scan_words (struct buffer *buf, Bufpos from, int count) { if (from == limit) return 0; -#ifndef MULE - if (word_constituent_p (buf, from - 1, mirrortab)) - break; -#endif - from--; -#ifdef MULE + ch1 = BUF_FETCH_CHAR (buf, from - 1); code = SYNTAX_UNSAFE (mirrortab, ch1); if (words_include_escapes @@ -431,24 +412,25 @@ scan_words (struct buffer *buf, Bufpos from, int count) break; if (code == Sword) break; -#endif + + from--; } QUIT; - while ((from != limit) -#ifndef MULE - && word_constituent_p (buf, from - 1, mirrortab) -#endif - ) + while (from != limit) { -#ifdef MULE ch0 = BUF_FETCH_CHAR (buf, from - 1); code = SYNTAX_UNSAFE (mirrortab, ch0); if (!(words_include_escapes && (code == Sescape || code == Scharquote))) - if (code != Sword || WORD_BOUNDARY_P (ch0, ch1)) + if (code != Sword +#ifdef MULE + || WORD_BOUNDARY_P (ch0, ch1) +#endif + ) break; +#ifdef MULE ch1 = ch0; #endif from--; diff --git a/src/syntax.h b/src/syntax.h index e141eb0..4c57a7a 100644 --- a/src/syntax.h +++ b/src/syntax.h @@ -238,9 +238,9 @@ extern CONST unsigned char syntax_spec_code[0400]; extern CONST unsigned char syntax_code_spec[]; -Lisp_Object scan_lists (struct buffer *buf, int from, int count, +Lisp_Object scan_lists (struct buffer *buf, Bufpos from, int count, int depth, int sexpflag, int no_error); -int char_quoted (struct buffer *buf, int pos); +int char_quoted (struct buffer *buf, Bufpos pos); /* NOTE: This does not refer to the mirror table, but to the syntax table itself. */ diff --git a/src/syssignal.h b/src/syssignal.h index 1332f39..1a3de7b 100644 --- a/src/syssignal.h +++ b/src/syssignal.h @@ -213,7 +213,7 @@ signal_handler_t sys_do_signal (int signal_number, signal_handler_t action); #define EMACS_KILLPG(gid, signo) killpg (gid, signo) #else #ifdef WINDOWSNT -#define EMACS_KILLPG(gid, signo) (kill (gid, signo)) +#define EMACS_KILLPG(gid, signo) kill (gid, signo) #else #define EMACS_KILLPG(gid, signo) kill (-(gid), signo) #endif diff --git a/src/terminfo.c b/src/terminfo.c index bbdb9da..bc49f8c 100644 --- a/src/terminfo.c +++ b/src/terminfo.c @@ -81,7 +81,7 @@ emacs_tparam (CONST char *string, char *outstring, int len, int arg1, temp = (char *) tparm (string, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); if (outstring == 0) - outstring = ((char *) (xmalloc ((strlen (temp)) + 1))); + outstring = (char *) xmalloc (strlen (temp) + 1); strcpy (outstring, temp); return outstring; } diff --git a/src/toolbar-msw.c b/src/toolbar-msw.c index 8d6389b..5a4acfd 100644 --- a/src/toolbar-msw.c +++ b/src/toolbar-msw.c @@ -59,6 +59,9 @@ GetDlgItem(FRAME_MSWINDOWS_HANDLE(f), TOOLBAR_ID_BIAS + p) #define MSWINDOWS_BLANK_SIZE 5 #define MSWINDOWS_MINIMUM_TOOLBAR_SIZE 8 +static void +mswindows_move_toolbar (struct frame *f, enum toolbar_pos pos); + #define SET_TOOLBAR_WAS_VISIBLE_FLAG(frame, pos, flag) \ do { \ switch (pos) \ @@ -460,6 +463,9 @@ mswindows_output_toolbar (struct frame *f, enum toolbar_pos pos) /* now display the window */ ShowWindow (toolbarwnd, SW_SHOW); + /* no idea why this is necessary but initial display will not + happen otherwise. */ + mswindows_move_toolbar (f, pos); if (button_tbl) xfree (button_tbl); @@ -525,6 +531,13 @@ mswindows_redraw_exposed_toolbars (struct frame *f, int x, int y, int width, } static void +mswindows_redraw_frame_toolbars (struct frame *f) +{ + mswindows_redraw_exposed_toolbars (f, 0, 0, FRAME_PIXWIDTH (f), + FRAME_PIXHEIGHT (f)); +} + +static void mswindows_initialize_frame_toolbars (struct frame *f) { @@ -636,5 +649,6 @@ console_type_create_toolbar_mswindows (void) CONSOLE_HAS_METHOD (mswindows, initialize_frame_toolbars); CONSOLE_HAS_METHOD (mswindows, free_frame_toolbars); CONSOLE_HAS_METHOD (mswindows, redraw_exposed_toolbars); + CONSOLE_HAS_METHOD (mswindows, redraw_frame_toolbars); } diff --git a/src/toolbar-x.c b/src/toolbar-x.c index 9961950..5b0fb72 100644 --- a/src/toolbar-x.c +++ b/src/toolbar-x.c @@ -77,7 +77,8 @@ x_draw_blank_toolbar_button (struct frame *f, int x, int y, int width, /* Draw the outline. */ x_output_shadows (f, sx, sy, swidth, sheight, top_shadow_gc, - bottom_shadow_gc, background_gc, shadow_thickness); + bottom_shadow_gc, background_gc, shadow_thickness, + EDGE_ALL); /* Blank the middle. */ XFillRectangle (dpy, x_win, background_gc, sx + shadow_thickness, @@ -158,7 +159,8 @@ x_output_toolbar_button (struct frame *f, Lisp_Object button) x_output_shadows (f, tb->x + x_adj, tb->y + y_adj, tb->width + width_adj, tb->height + height_adj, top_shadow_gc, - bottom_shadow_gc, background_gc, shadow_thickness); + bottom_shadow_gc, background_gc, shadow_thickness, + EDGE_ALL); /* Clear the pixmap area. */ XFillRectangle (dpy, x_win, background_gc, tb->x + x_adj + shadow_thickness, @@ -211,8 +213,8 @@ x_output_toolbar_button (struct frame *f, Lisp_Object button) } x_output_x_pixmap (f, XIMAGE_INSTANCE (instance), tb->x + x_offset, - tb->y + y_offset, 0, 0, 0, 0, width, height, - 0, 0, 0, background_gc); + tb->y + y_offset, 0, 0, width, height, + 0, 0, background_gc); } else if (IMAGE_INSTANCE_TYPE (p) == IMAGE_TEXT) { diff --git a/src/toolbar.c b/src/toolbar.c index db2c69e..31732af 100644 --- a/src/toolbar.c +++ b/src/toolbar.c @@ -57,19 +57,19 @@ Lisp_Object Qinit_toolbar_from_resources; static Lisp_Object -mark_toolbar_button (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_toolbar_button (Lisp_Object obj) { struct toolbar_button *data = XTOOLBAR_BUTTON (obj); - markobj (data->next); - markobj (data->frame); - markobj (data->up_glyph); - markobj (data->down_glyph); - markobj (data->disabled_glyph); - markobj (data->cap_up_glyph); - markobj (data->cap_down_glyph); - markobj (data->cap_disabled_glyph); - markobj (data->callback); - markobj (data->enabled_p); + mark_object (data->next); + mark_object (data->frame); + mark_object (data->up_glyph); + mark_object (data->down_glyph); + mark_object (data->disabled_glyph); + mark_object (data->cap_up_glyph); + mark_object (data->cap_down_glyph); + mark_object (data->cap_disabled_glyph); + mark_object (data->callback); + mark_object (data->enabled_p); return data->help_string; } @@ -1312,6 +1312,12 @@ specifier_type_create_toolbar (void) } void +reinit_specifier_type_create_toolbar (void) +{ + REINITIALIZE_SPECIFIER_TYPE (toolbar); +} + +void specifier_vars_of_toolbar (void) { Lisp_Object fb; diff --git a/src/toolbar.h b/src/toolbar.h index 543ed2c..6440767 100644 --- a/src/toolbar.h +++ b/src/toolbar.h @@ -73,7 +73,6 @@ DECLARE_LRECORD (toolbar_button, struct toolbar_button); #define XTOOLBAR_BUTTON(x) XRECORD (x, toolbar_button, struct toolbar_button) #define XSETTOOLBAR_BUTTON(x, p) XSETRECORD (x, p, toolbar_button) #define TOOLBAR_BUTTONP(x) RECORDP (x, toolbar_button) -#define GC_TOOLBAR_BUTTONP(x) GC_RECORDP (x, toolbar_button) #define CHECK_TOOLBAR_BUTTON(x) CHECK_RECORD (x, toolbar_button) #define CONCHECK_TOOLBAR_BUTTON(x) CONCHECK_RECORD (x, toolbar_button) diff --git a/src/tooltalk.c b/src/tooltalk.c index 3f24b2e..b53f3f4 100644 --- a/src/tooltalk.c +++ b/src/tooltalk.c @@ -151,9 +151,9 @@ struct Lisp_Tooltalk_Message }; static Lisp_Object -mark_tooltalk_message (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_tooltalk_message (Lisp_Object obj) { - markobj (XTOOLTALK_MESSAGE (obj)->callback); + mark_object (XTOOLTALK_MESSAGE (obj)->callback); return XTOOLTALK_MESSAGE (obj)->plist_sym; } @@ -225,9 +225,9 @@ struct Lisp_Tooltalk_Pattern }; static Lisp_Object -mark_tooltalk_pattern (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_tooltalk_pattern (Lisp_Object obj) { - markobj (XTOOLTALK_PATTERN (obj)->callback); + mark_object (XTOOLTALK_PATTERN (obj)->callback); return XTOOLTALK_PATTERN (obj)->plist_sym; } diff --git a/src/tooltalk.h b/src/tooltalk.h index bede554..16e991b 100644 --- a/src/tooltalk.h +++ b/src/tooltalk.h @@ -31,7 +31,6 @@ DECLARE_LRECORD (tooltalk_message, struct Lisp_Tooltalk_Message); #define XTOOLTALK_MESSAGE(x) XRECORD (x, tooltalk_message, struct Lisp_Tooltalk_Message) #define XSETTOOLTALK_MESSAGE(x, p) XSETRECORD (x, p, tooltalk_message) #define TOOLTALK_MESSAGEP(x) RECORDP (x, tooltalk_message) -#define GC_TOOLTALK_MESSAGEP(x) GC_RECORDP (x, tooltalk_message) #define CHECK_TOOLTALK_MESSAGE(x) CHECK_RECORD (x, tooltalk_message) struct Lisp_Tooltalk_Pattern; @@ -39,7 +38,6 @@ DECLARE_LRECORD (tooltalk_pattern, struct Lisp_Tooltalk_Pattern); #define XTOOLTALK_PATTERN(x) XRECORD (x, tooltalk_pattern, struct Lisp_Tooltalk_Pattern) #define XSETTOOLTALK_PATTERN(x, p) XSETRECORD (x, p, tooltalk_pattern) #define TOOLTALK_PATTERNP(x) RECORDP (x, tooltalk_pattern) -#define GC_TOOLTALK_PATTERNP(x) GC_RECORDP (x, tooltalk_pattern) #define CHECK_TOOLTALK_PATTERN(x) CHECK_RECORD (x, tooltalk_pattern) #define TOOLTALK_MESSAGE_KEY 100 diff --git a/src/undo.c b/src/undo.c index dd9a443..41af38e 100644 --- a/src/undo.c +++ b/src/undo.c @@ -46,7 +46,7 @@ Lisp_Object Qinhibit_read_only; which will be added to the list at the end of the command. This ensures we can't run out of space while trying to make an undo-boundary. */ -Lisp_Object pending_boundary; +static Lisp_Object pending_boundary; static void undo_boundary (struct buffer *b) @@ -547,9 +547,16 @@ syms_of_undo (void) } void -vars_of_undo (void) +reinit_vars_of_undo (void) { inside_undo = 0; +} + +void +vars_of_undo (void) +{ + reinit_vars_of_undo (); + pending_boundary = Qnil; staticpro (&pending_boundary); last_undo_buffer = Qnil; diff --git a/src/unexelf.c b/src/unexelf.c index 785915e..733a0f6 100644 --- a/src/unexelf.c +++ b/src/unexelf.c @@ -18,7 +18,7 @@ along with XEmacs; see the file COPYING. If not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* Synched up with: FSF 20.2. */ +/* Synched up with: FSF 20.4. */ /* * unexec.c - Convert a running program into an a.out file. @@ -424,10 +424,98 @@ extern void fatal (CONST char *, ...); #include #include #include +#if !defined (__NetBSD__) && !defined (__OpenBSD__) #include +#endif #include +#if defined (__sony_news) && defined (_SYSTYPE_SYSV) +#include +#include +#endif /* __sony_news && _SYSTYPE_SYSV */ +#ifdef __sgi +#include /* for HDRR declaration */ +#endif /* __sgi */ + +#if defined (__alpha__) && !defined (__NetBSD__) && !defined (__OpenBSD__) +/* Declare COFF debugging symbol table. This used to be in + /usr/include/sym.h, but this file is no longer included in Red Hat + 5.0 and presumably in any other glibc 2.x based distribution. */ +typedef struct { + short magic; + short vstamp; + int ilineMax; + int idnMax; + int ipdMax; + int isymMax; + int ioptMax; + int iauxMax; + int issMax; + int issExtMax; + int ifdMax; + int crfd; + int iextMax; + long cbLine; + long cbLineOffset; + long cbDnOffset; + long cbPdOffset; + long cbSymOffset; + long cbOptOffset; + long cbAuxOffset; + long cbSsOffset; + long cbSsExtOffset; + long cbFdOffset; + long cbRfdOffset; + long cbExtOffset; +} HDRR, *pHDRR; +#define cbHDRR sizeof(HDRR) +#define hdrNil ((pHDRR)0) +#endif + +#ifdef __NetBSD__ +/* + * NetBSD does not have normal-looking user-land ELF support. + */ +# ifdef __alpha__ +# define ELFSIZE 64 +# else +# define ELFSIZE 32 +# endif +# include + +# define PT_LOAD Elf_pt_load +# define SHT_SYMTAB Elf_sht_symtab +# define SHT_DYNSYM Elf_sht_dynsym +# define SHT_NULL Elf_sht_null +# define SHT_NOBITS Elf_sht_nobits +# define SHT_REL Elf_sht_rel +# define SHT_RELA Elf_sht_rela + +# define SHN_UNDEF Elf_eshn_undefined +# define SHN_ABS Elf_eshn_absolute +# define SHN_COMMON Elf_eshn_common + +/* + * The magic of picking the right size types is handled by the ELFSIZE + * definition above. + */ +# ifdef __STDC__ +# define ElfW(type) Elf_##type +# else +# define ElfW(type) Elf_/**/type +# endif + +# ifdef __alpha__ +# include +# define HDRR struct ecoff_symhdr +# define pHDRR HDRR * +# endif +#endif /* __NetBSD__ */ -#if __GLIBC__ - 0 >= 2 +#ifdef __OpenBSD__ +# include +#endif + +#if __GNU_LIBRARY__ - 0 >= 6 # include /* get ElfW etc */ #endif @@ -487,8 +575,8 @@ typedef unsigned char byte; /* Round X up to a multiple of Y. */ -static int -round_up (int x, int y) +static ElfW(Addr) +round_up (ElfW(Addr) x, ElfW(Addr) y) { int rem = x % y; if (rem == 0) @@ -531,7 +619,8 @@ unexec (char *new_name, char *old_name, unsigned int data_start, ElfW(Off) new_data2_offset; ElfW(Addr) new_data2_addr; - int n, nn, old_bss_index, old_data_index; + int n, nn, old_bss_index, old_data_index, new_data2_index; + int old_sbss_index, old_mdebug_index; struct stat stat_buf; /* Open the old file & map it into the address space. */ @@ -544,7 +633,7 @@ unexec (char *new_name, char *old_name, unsigned int data_start, if (fstat (old_file, &stat_buf) == -1) fatal ("Can't fstat (%s): errno %d\n", old_name, errno); - old_base = mmap (0, stat_buf.st_size, PROT_READ, MAP_SHARED, old_file, 0); + old_base = (caddr_t) mmap (0, stat_buf.st_size, PROT_READ, MAP_SHARED, old_file, 0); if (old_base == (caddr_t) -1) fatal ("Can't mmap (%s): errno %d\n", old_name, errno); @@ -580,8 +669,48 @@ unexec (char *new_name, char *old_name, unsigned int data_start, if (old_bss_index == old_file_h->e_shnum) fatal ("Can't find .bss in %s.\n", old_name, 0); - old_bss_addr = OLD_SECTION_H (old_bss_index).sh_addr; - old_bss_size = OLD_SECTION_H (old_bss_index).sh_size; + for (old_sbss_index = 1; old_sbss_index < (int) old_file_h->e_shnum; + old_sbss_index++) + { +#ifdef DEBUG + fprintf (stderr, "Looking for .sbss - found %s\n", + old_section_names + OLD_SECTION_H (old_sbss_index).sh_name); +#endif + if (!strcmp (old_section_names + OLD_SECTION_H (old_sbss_index).sh_name, + ".sbss")) + break; + } + if (old_sbss_index == old_file_h->e_shnum) + { + old_sbss_index = -1; + old_bss_addr = OLD_SECTION_H(old_bss_index).sh_addr; + old_bss_size = OLD_SECTION_H(old_bss_index).sh_size; + new_data2_offset = OLD_SECTION_H(old_bss_index).sh_offset; + new_data2_index = old_bss_index; + } + else + { + old_bss_addr = OLD_SECTION_H(old_sbss_index).sh_addr; + old_bss_size = OLD_SECTION_H(old_bss_index).sh_size + + OLD_SECTION_H(old_sbss_index).sh_size; + new_data2_offset = OLD_SECTION_H(old_sbss_index).sh_offset; + new_data2_index = old_sbss_index; + } + + for (old_mdebug_index = 1; old_mdebug_index < (int) old_file_h->e_shnum; + old_mdebug_index++) + { +#ifdef DEBUG + fprintf (stderr, "Looking for .mdebug - found %s\n", + old_section_names + OLD_SECTION_H (old_mdebug_index).sh_name); +#endif + if (!strcmp (old_section_names + OLD_SECTION_H (old_mdebug_index).sh_name, + ".mdebug")) + break; + } + if (old_mdebug_index == old_file_h->e_shnum) + old_mdebug_index = 0; + #if defined (emacs) || !defined (DEBUG) new_bss_addr = (ElfW(Addr)) sbrk (0); #else @@ -589,7 +718,6 @@ unexec (char *new_name, char *old_name, unsigned int data_start, #endif new_data2_addr = old_bss_addr; new_data2_size = new_bss_addr - old_bss_addr; - new_data2_offset = OLD_SECTION_H (old_bss_index).sh_offset; #ifdef DEBUG fprintf (stderr, "old_bss_index %d\n", old_bss_index); @@ -618,13 +746,13 @@ unexec (char *new_name, char *old_name, unsigned int data_start, if (ftruncate (new_file, new_file_size)) fatal ("Can't ftruncate (%s): errno %d\n", new_name, errno); + new_base = (caddr_t) mmap (0, new_file_size, PROT_READ | PROT_WRITE, #ifdef UNEXEC_USE_MAP_PRIVATE - new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, - new_file, 0); + MAP_PRIVATE, #else - new_base = mmap (0, new_file_size, PROT_READ | PROT_WRITE, MAP_SHARED, - new_file, 0); + MAP_SHARED, #endif + new_file, 0); if (new_base == (caddr_t) -1) fatal ("Can't mmap (%s): errno %d\n", new_name, errno); @@ -674,24 +802,31 @@ unexec (char *new_name, char *old_name, unsigned int data_start, if ((OLD_SECTION_H (old_bss_index)).sh_addralign > alignment) alignment = OLD_SECTION_H (old_bss_index).sh_addralign; -#ifndef __mips /* ifndef added by jwz at suggestion of - r02kar@x4u2.desy.de (Karsten Kuenne) to avoid - "Program segment above .bss" when dumping. - */ - if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz > old_bss_addr) - fatal ("Program segment above .bss in %s\n", old_name, 0); -#endif /* __mips */ +#ifdef __mips + /* According to r02kar@x4u2.desy.de (Karsten Kuenne) + and oliva@gnu.org (Alexandre Oliva), on IRIX 5.2, we + always get "Program segment above .bss" when dumping + when the executable doesn't have an sbss section. */ + if (old_sbss_index != -1) +#endif /* __mips */ + if (NEW_PROGRAM_H (n).p_vaddr + NEW_PROGRAM_H (n).p_filesz + > (old_sbss_index == -1 + ? old_bss_addr + : round_up (old_bss_addr, alignment))) + fatal ("Program segment above .bss in %s\n", old_name, 0); if (NEW_PROGRAM_H (n).p_type == PT_LOAD - && (round_up ((int) ((NEW_PROGRAM_H (n)).p_vaddr - + (NEW_PROGRAM_H (n)).p_filesz), + && (round_up ((NEW_PROGRAM_H (n)).p_vaddr + + (NEW_PROGRAM_H (n)).p_filesz, alignment) - == round_up ((int) old_bss_addr, alignment))) + == round_up (old_bss_addr, alignment))) break; } if (n < 0) fatal ("Couldn't find segment next to .bss in %s\n", old_name, 0); + /* Make sure that the size includes any padding before the old .bss + section. */ NEW_PROGRAM_H (n).p_filesz = new_bss_addr - NEW_PROGRAM_H (n).p_vaddr; NEW_PROGRAM_H (n).p_memsz = NEW_PROGRAM_H (n).p_filesz; @@ -726,8 +861,10 @@ unexec (char *new_name, char *old_name, unsigned int data_start, for (n = 1, nn = 1; n < (int) old_file_h->e_shnum; n++, nn++) { caddr_t src; - /* If it is bss section, insert the new data2 section before it. */ - if (n == old_bss_index) + /* If it is (s)bss section, insert the new data2 section before it. */ + /* new_data2_index is the index of either old_sbss or old_bss, that was + chosen as a section for new_data2. */ + if (n == new_data2_index) { /* Steal the data section header for this data2 section. */ memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (old_data_index), @@ -744,21 +881,24 @@ unexec (char *new_name, char *old_name, unsigned int data_start, /* Now copy over what we have in the memory now. */ memcpy (NEW_SECTION_H (nn).sh_offset + new_base, (caddr_t) OLD_SECTION_H (n).sh_addr, - /* #### mrb: should be old_bss_size instead? */ new_data2_size); nn++; } memcpy (&NEW_SECTION_H (nn), &OLD_SECTION_H (n), old_file_h->e_shentsize); - - /* The new bss section's size is zero, and its file offset and virtual - address should be off by NEW_DATA2_SIZE. */ - if (n == old_bss_index) + + if (n == old_bss_index + /* The new bss and sbss section's size is zero, and its file offset + and virtual address should be off by NEW_DATA2_SIZE. */ + || n == old_sbss_index + ) { - /* NN should be `old_bss_index + 1' at this point. */ - NEW_SECTION_H (nn).sh_offset += new_data2_size; - NEW_SECTION_H (nn).sh_addr += new_data2_size; + /* NN should be `old_s?bss_index + 1' at this point. */ + NEW_SECTION_H (nn).sh_offset = + NEW_SECTION_H (new_data2_index).sh_offset + new_data2_size; + NEW_SECTION_H (nn).sh_addr = + NEW_SECTION_H (new_data2_index).sh_addr + new_data2_size; /* Let the new bss section address alignment be the same as the section address alignment followed the old bss section, so this section will be placed in exactly the same place. */ @@ -782,7 +922,9 @@ unexec (char *new_name, char *old_name, unsigned int data_start, >= OLD_SECTION_H (old_bss_index-1).sh_offset) NEW_SECTION_H (nn).sh_offset += new_data2_size; #else - if (NEW_SECTION_H (nn).sh_offset >= new_data2_offset) + if (round_up (NEW_SECTION_H (nn).sh_offset, + OLD_SECTION_H (old_bss_index).sh_addralign) + >= new_data2_offset) NEW_SECTION_H (nn).sh_offset += new_data2_size; #endif /* Any section that was originally placed after the section @@ -811,17 +953,24 @@ unexec (char *new_name, char *old_name, unsigned int data_start, /* Write out the sections. .data and .data1 (and data2, called ".data" in the strings table) get copied from the current process instead of the old file. */ -#ifdef __powerpc__ - /* The PowerPC has additional 'data' segments which need to be saved */ - if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data") || - !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data1") || - !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".sdata") || - !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".sdata1")) -#else if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data") || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), - ".data1")) + ".sdata") + /* Taking these sections from the current process, breaks + Linux in a subtle way. Binaries only run on the + architecture (e.g. i586 vs i686) of the dumping machine */ +#ifdef __sgi + || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), + ".lit4") + || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), + ".lit8") + || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), + ".got") #endif + || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), + ".sdata1") + || !strcmp ((old_section_names + NEW_SECTION_H (n).sh_name), + ".data1")) src = (caddr_t) OLD_SECTION_H (n).sh_addr; else src = old_base + OLD_SECTION_H (n).sh_offset; @@ -829,6 +978,106 @@ unexec (char *new_name, char *old_name, unsigned int data_start, memcpy (NEW_SECTION_H (nn).sh_offset + new_base, src, NEW_SECTION_H (nn).sh_size); +#ifdef __alpha__ + /* Update Alpha COFF symbol table: */ + if (strcmp (old_section_names + OLD_SECTION_H (n).sh_name, ".mdebug") + == 0) + { + pHDRR symhdr = (pHDRR) (NEW_SECTION_H (nn).sh_offset + new_base); + + symhdr->cbLineOffset += new_data2_size; + symhdr->cbDnOffset += new_data2_size; + symhdr->cbPdOffset += new_data2_size; + symhdr->cbSymOffset += new_data2_size; + symhdr->cbOptOffset += new_data2_size; + symhdr->cbAuxOffset += new_data2_size; + symhdr->cbSsOffset += new_data2_size; + symhdr->cbSsExtOffset += new_data2_size; + symhdr->cbFdOffset += new_data2_size; + symhdr->cbRfdOffset += new_data2_size; + symhdr->cbExtOffset += new_data2_size; + } +#endif /* __alpha__ */ + +#if defined (__sony_news) && defined (_SYSTYPE_SYSV) + if (NEW_SECTION_H (nn).sh_type == SHT_MIPS_DEBUG && old_mdebug_index) + { + int diff = NEW_SECTION_H(nn).sh_offset + - OLD_SECTION_H(old_mdebug_index).sh_offset; + HDRR *phdr = (HDRR *)(NEW_SECTION_H (nn).sh_offset + new_base); + + if (diff) + { + phdr->cbLineOffset += diff; + phdr->cbDnOffset += diff; + phdr->cbPdOffset += diff; + phdr->cbSymOffset += diff; + phdr->cbOptOffset += diff; + phdr->cbAuxOffset += diff; + phdr->cbSsOffset += diff; + phdr->cbSsExtOffset += diff; + phdr->cbFdOffset += diff; + phdr->cbRfdOffset += diff; + phdr->cbExtOffset += diff; + } + } +#endif /* __sony_news && _SYSTYPE_SYSV */ + +#ifdef __sgi + /* Adjust the HDRR offsets in .mdebug and copy the + line data if it's in its usual 'hole' in the object. + Makes the new file debuggable with dbx. + patches up two problems: the absolute file offsets + in the HDRR record of .mdebug (see /usr/include/syms.h), and + the ld bug that gets the line table in a hole in the + elf file rather than in the .mdebug section proper. + David Anderson. davea@sgi.com Jan 16,1994. */ + if (n == old_mdebug_index) + { +#define MDEBUGADJUST(__ct,__fileaddr) \ + if (n_phdrr->__ct > 0) \ + { \ + n_phdrr->__fileaddr += movement; \ + } + + HDRR * o_phdrr = (HDRR *)((byte *)old_base + OLD_SECTION_H (n).sh_offset); + HDRR * n_phdrr = (HDRR *)((byte *)new_base + NEW_SECTION_H (nn).sh_offset); + unsigned movement = new_data2_size; + + MDEBUGADJUST (idnMax, cbDnOffset); + MDEBUGADJUST (ipdMax, cbPdOffset); + MDEBUGADJUST (isymMax, cbSymOffset); + MDEBUGADJUST (ioptMax, cbOptOffset); + MDEBUGADJUST (iauxMax, cbAuxOffset); + MDEBUGADJUST (issMax, cbSsOffset); + MDEBUGADJUST (issExtMax, cbSsExtOffset); + MDEBUGADJUST (ifdMax, cbFdOffset); + MDEBUGADJUST (crfd, cbRfdOffset); + MDEBUGADJUST (iextMax, cbExtOffset); + /* The Line Section, being possible off in a hole of the object, + requires special handling. */ + if (n_phdrr->cbLine > 0) + { + if (o_phdrr->cbLineOffset > (OLD_SECTION_H (n).sh_offset + + OLD_SECTION_H (n).sh_size)) + { + /* line data is in a hole in elf. do special copy and adjust + for this ld mistake. + */ + n_phdrr->cbLineOffset += movement; + + memcpy (n_phdrr->cbLineOffset + new_base, + o_phdrr->cbLineOffset + old_base, n_phdrr->cbLine); + } + else + { + /* somehow line data is in .mdebug as it is supposed to be. */ + MDEBUGADJUST (cbLine, cbLineOffset); + } + } + } +#endif /* __sgi */ + /* If it is the symbol table, its st_shndx field needs to be patched. */ if (NEW_SECTION_H (nn).sh_type == SHT_SYMTAB || NEW_SECTION_H (nn).sh_type == SHT_DYNSYM) @@ -886,17 +1135,21 @@ unexec (char *new_name, char *old_name, unsigned int data_start, be no harm in that provided that r_offset is always the first member. */ nn = section.sh_info; -#ifdef __powerpc__ - /* The PowerPC has additional 'data' segments which need to be saved */ - if (!strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data") || - !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".data1") || - !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".sdata") || - !strcmp (old_section_names + NEW_SECTION_H (n).sh_name, ".sdata1")) -#else if (!strcmp (old_section_names + NEW_SECTION_H (nn).sh_name, ".data") || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), - ".data1")) + ".sdata") +#ifdef __sgi + || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), + ".lit4") + || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), + ".lit8") + || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), + ".got") #endif + || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), + ".sdata1") + || !strcmp ((old_section_names + NEW_SECTION_H (nn).sh_name), + ".data1")) { ElfW(Addr) offset = NEW_SECTION_H (nn).sh_addr - NEW_SECTION_H (nn).sh_offset; @@ -905,6 +1158,13 @@ unexec (char *new_name, char *old_name, unsigned int data_start, reloc += section.sh_entsize) { ElfW(Addr) addr = ((ElfW(Rel) *) reloc)->r_offset - offset; +#ifdef __alpha__ + /* The Alpha ELF binutils currently have a bug that + sometimes results in relocs that contain all + zeroes. Work around this for now... */ + if (((ElfW(Rel) *) reloc)->r_offset == 0) + continue; +#endif memcpy (new_base + addr, old_base + addr, sizeof(ElfW(Addr))); } } diff --git a/src/unexnt.c b/src/unexnt.c index 60c8fe4..f13684f 100644 --- a/src/unexnt.c +++ b/src/unexnt.c @@ -261,7 +261,7 @@ unexec (char *new_name, char *old_name, void *start_data, void *start_bss, int -open_output_file (file_data *p_file, char *filename, unsigned long size) +open_output_file (file_data *p_file, CONST char *filename, unsigned long size) { HANDLE file; HANDLE file_mapping; diff --git a/src/window.c b/src/window.c index 85a196b..a63fe35 100644 --- a/src/window.c +++ b/src/window.c @@ -41,7 +41,7 @@ Boston, MA 02111-1307, USA. */ #include "gutter.h" Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configurationp; -Lisp_Object Qscroll_up, Qscroll_down, Qdisplay_buffer; +Lisp_Object Qdisplay_buffer; #ifdef MEMORY_USAGE_STATS Lisp_Object Qface_cache, Qglyph_cache, Qline_start_cache, Qother_redisplay; @@ -85,6 +85,9 @@ Lisp_Object Vvertical_divider_line_width; /* Spacing between outer egde of divider border and window edge */ Lisp_Object Vvertical_divider_spacing; +/* How much to scroll by per-line. */ +Lisp_Object Vwindow_pixel_scroll_increment; + /* Scroll if point lands on the bottom line and that line is partially clipped. */ int scroll_on_clipped_lines; @@ -118,7 +121,7 @@ Lisp_Object Qtemp_buffer_show_hook; int next_screen_context_lines; /* List of freed window configurations with 1 - 10 windows. */ -Lisp_Object Vwindow_configuration_free_list[10]; +static Lisp_Object Vwindow_configuration_free_list[10]; #define SET_LAST_MODIFIED(w, cache_too) \ do { \ @@ -138,38 +141,38 @@ do { \ #define MARK_DISP_VARIABLE(field) \ - markobj (window->field[CURRENT_DISP]); \ - markobj (window->field[DESIRED_DISP]); \ - markobj (window->field[CMOTION_DISP]); + mark_object (window->field[CURRENT_DISP]); \ + mark_object (window->field[DESIRED_DISP]); \ + mark_object (window->field[CMOTION_DISP]); static Lisp_Object -mark_window (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_window (Lisp_Object obj) { struct window *window = XWINDOW (obj); - markobj (window->frame); - markobj (window->mini_p); - markobj (window->next); - markobj (window->prev); - markobj (window->hchild); - markobj (window->vchild); - markobj (window->parent); - markobj (window->buffer); + mark_object (window->frame); + mark_object (window->mini_p); + mark_object (window->next); + mark_object (window->prev); + mark_object (window->hchild); + mark_object (window->vchild); + mark_object (window->parent); + mark_object (window->buffer); MARK_DISP_VARIABLE (start); MARK_DISP_VARIABLE (pointm); - markobj (window->sb_point); /* #### move to scrollbar.c? */ - markobj (window->use_time); + mark_object (window->sb_point); /* #### move to scrollbar.c? */ + mark_object (window->use_time); MARK_DISP_VARIABLE (last_modified); MARK_DISP_VARIABLE (last_point); MARK_DISP_VARIABLE (last_start); MARK_DISP_VARIABLE (last_facechange); - markobj (window->line_cache_last_updated); - markobj (window->redisplay_end_trigger); - markobj (window->subwindow_instance_cache); + mark_object (window->line_cache_last_updated); + mark_object (window->redisplay_end_trigger); + mark_object (window->subwindow_instance_cache); - mark_face_cachels (window->face_cachels, markobj); - mark_glyph_cachels (window->glyph_cachels, markobj); + mark_face_cachels (window->face_cachels); + mark_glyph_cachels (window->glyph_cachels); -#define WINDOW_SLOT(slot, compare) ((void) (markobj (window->slot))) +#define WINDOW_SLOT(slot, compare) mark_object (window->slot) #include "winslots.h" return Qnil; @@ -706,6 +709,11 @@ window_full_height_p (struct window *w) int window_truncation_on (struct window *w) { + /* Minibuffer windows are never truncated. + ### is this the right way ? */ + if (MINI_WINDOW_P (w)) + return 0; + /* Horizontally scrolled windows are truncated. */ if (w->hscroll) return 1; @@ -724,6 +732,17 @@ window_truncation_on (struct window *w) return 0; } +DEFUN ("window-truncated-p", Fwindow_truncated_p, 0, 1, 0, /* +Returns Non-Nil iff the window is truncated. +*/ + (window)) +{ + struct window *w = decode_window (window); + + return window_truncation_on (w) ? Qt : Qnil; +} + + static int have_undivided_common_edge (struct window *w_right, void *closure) { @@ -1096,6 +1115,26 @@ be used. Otherwise, the selected frame is used. } } +DEFUN ("last-nonminibuf-window", Flast_nonminibuf_window, 0, 1, 0, /* +Return the last selected window that is not a minibuffer window. +If the optional argument CON-DEV-OR-FRAME is specified and is a frame, +return the last non-minibuffer window used by that frame. If +CON-DEV-OR-FRAME is a device, then the selected frame on that device +will be used. If CON-DEV-OR-FRAME is a console, the selected frame on +that console's selected device will be used. Otherwise, the selected +frame is used. +*/ + (con_dev_or_frame)) +{ + if (NILP (con_dev_or_frame) && NILP (Fselected_device (Qnil))) + return Qnil; /* happens at startup */ + + { + struct frame *f = decode_frame_or_selected (con_dev_or_frame); + return FRAME_LAST_NONMINIBUF_WINDOW (f); + } +} + DEFUN ("minibuffer-window", Fminibuffer_window, 0, 1, 0, /* Return the window used now for minibuffers. If the optional argument CON-DEV-OR-FRAME is specified and is a frame, return @@ -3910,7 +3949,8 @@ change_window_height (struct window *win, int delta, int widthflag, -/* Scroll contents of window WINDOW up N lines. */ +/* Scroll contents of window WINDOW up N lines. If N < (top line height / + average line height) then we just adjust the top clip. */ void window_scroll (Lisp_Object window, Lisp_Object n, int direction, Error_behavior errb) @@ -3920,6 +3960,9 @@ window_scroll (Lisp_Object window, Lisp_Object n, int direction, int selected = EQ (window, Fselected_window (Qnil)); int value = 0; Lisp_Object point, tem; + display_line_dynarr *dla; + int fheight, fwidth, modeline = 0; + struct display_line* dl; if (selected) point = make_int (BUF_PT (b)); @@ -3949,6 +3992,7 @@ window_scroll (Lisp_Object window, Lisp_Object n, int direction, window, Qnil); Fset_marker (w->start[CURRENT_DISP], point, w->buffer); w->start_at_line_beg = beginning_of_line_p (b, XINT (point)); + WINDOW_TEXT_TOP_CLIP (w) = 0; MARK_WINDOWS_CHANGED (w); } @@ -3992,82 +4036,146 @@ window_scroll (Lisp_Object window, Lisp_Object n, int direction, { return; } - else if (value > 0) - { - int vtarget; - Bufpos startp, old_start; - old_start = marker_position (w->start[CURRENT_DISP]); - startp = vmotion (w, old_start, value, &vtarget); + /* Determine parameters to test for partial line scrolling with. */ + dla = window_display_lines (w, CURRENT_DISP); + + if (INTP (Vwindow_pixel_scroll_increment)) + fheight = XINT (Vwindow_pixel_scroll_increment); + else if (!NILP (Vwindow_pixel_scroll_increment)); + default_face_height_and_width (window, &fheight, &fwidth); + + if (Dynarr_length (dla) >= 1) + modeline = Dynarr_atp (dla, 0)->modeline; - if (vtarget < value && - (w->window_end_pos[CURRENT_DISP] == -1 - || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)))) + dl = Dynarr_atp (dla, modeline); + + if (value > 0) + { + /* Go for partial display line scrolling. This just means bumping + the clip by a reasonable amount and redisplaying, everything else + remains unchanged. */ + if (!NILP (Vwindow_pixel_scroll_increment) + && + Dynarr_length (dla) >= (1 + modeline) + && + (dl->ascent - dl->top_clip) - fheight * value > 0) { - maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb); - return; + WINDOW_TEXT_TOP_CLIP (w) += value * fheight; + MARK_WINDOWS_CHANGED (w); } else { - set_marker_restricted (w->start[CURRENT_DISP], make_int (startp), - w->buffer); - w->force_start = 1; - w->start_at_line_beg = beginning_of_line_p (b, startp); - MARK_WINDOWS_CHANGED (w); + int vtarget; + Bufpos startp, old_start; + + if (WINDOW_TEXT_TOP_CLIP (w)) + { + WINDOW_TEXT_TOP_CLIP (w) = 0; + MARK_WINDOWS_CHANGED (w); + } - if (!point_would_be_visible (w, startp, XINT (point))) + old_start = marker_position (w->start[CURRENT_DISP]); + startp = vmotion (w, old_start, value, &vtarget); + + if (vtarget < value && + (w->window_end_pos[CURRENT_DISP] == -1 + || (BUF_Z (b) - w->window_end_pos[CURRENT_DISP] > BUF_ZV (b)))) { - if (selected) - BUF_SET_PT (b, startp); - else - set_marker_restricted (w->pointm[CURRENT_DISP], - make_int (startp), - w->buffer); + maybe_signal_error (Qend_of_buffer, Qnil, Qwindow, errb); + return; + } + else + { + set_marker_restricted (w->start[CURRENT_DISP], make_int (startp), + w->buffer); + w->force_start = 1; + w->start_at_line_beg = beginning_of_line_p (b, startp); + MARK_WINDOWS_CHANGED (w); + + if (!point_would_be_visible (w, startp, XINT (point))) + { + if (selected) + BUF_SET_PT (b, startp); + else + set_marker_restricted (w->pointm[CURRENT_DISP], + make_int (startp), + w->buffer); + } } } } else if (value < 0) { - int vtarget; - Bufpos startp, old_start; - - old_start = marker_position (w->start[CURRENT_DISP]); - startp = vmotion (w, old_start, value, &vtarget); - - if (vtarget > value - && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b)) + /* Go for partial display line scrolling. This just means bumping + the clip by a reasonable amount and redisplaying, everything else + remains unchanged. */ + if (!NILP (Vwindow_pixel_scroll_increment) + && + Dynarr_length (dla) >= (1 + modeline) + && + (dl->ascent - dl->top_clip) - fheight * value < + (dl->ascent + dl->descent - dl->clip) + && + WINDOW_TEXT_TOP_CLIP (w) + value * fheight > 0) { - maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb); - return; + WINDOW_TEXT_TOP_CLIP (w) += value * fheight; + MARK_WINDOWS_CHANGED (w); } else { - set_marker_restricted (w->start[CURRENT_DISP], make_int (startp), - w->buffer); - w->force_start = 1; - w->start_at_line_beg = beginning_of_line_p (b, startp); - MARK_WINDOWS_CHANGED (w); - - if (!point_would_be_visible (w, startp, XINT (point))) + int vtarget; + Bufpos startp, old_start; + + if (WINDOW_TEXT_TOP_CLIP (w)) { - Bufpos new_point; - - if (MINI_WINDOW_P (w)) - new_point = startp; - else - new_point = start_of_last_line (w, startp); - - if (selected) - BUF_SET_PT (b, new_point); - else - set_marker_restricted (w->pointm[CURRENT_DISP], - make_int (new_point), - w->buffer); + WINDOW_TEXT_TOP_CLIP (w) = 0; + MARK_WINDOWS_CHANGED (w); + } + + old_start = marker_position (w->start[CURRENT_DISP]); + startp = vmotion (w, old_start, value, &vtarget); + + if (vtarget > value + && marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b)) + { + maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb); + return; + } + else + { + set_marker_restricted (w->start[CURRENT_DISP], make_int (startp), + w->buffer); + w->force_start = 1; + w->start_at_line_beg = beginning_of_line_p (b, startp); + MARK_WINDOWS_CHANGED (w); + + if (!point_would_be_visible (w, startp, XINT (point))) + { + Bufpos new_point; + + if (MINI_WINDOW_P (w)) + new_point = startp; + else + new_point = start_of_last_line (w, startp); + + if (selected) + BUF_SET_PT (b, new_point); + else + set_marker_restricted (w->pointm[CURRENT_DISP], + make_int (new_point), + w->buffer); + } } } } else /* value == 0 && direction == -1 */ { + if (WINDOW_TEXT_TOP_CLIP (w)) + { + WINDOW_TEXT_TOP_CLIP (w) = 0; + MARK_WINDOWS_CHANGED (w); + } if (marker_position (w->start[CURRENT_DISP]) == BUF_BEGV (b)) { maybe_signal_error (Qbeginning_of_buffer, Qnil, Qwindow, errb); @@ -4105,7 +4213,6 @@ window_scroll (Lisp_Object window, Lisp_Object n, int direction, } } } - } DEFUN ("scroll-up", Fscroll_up, 0, 1, "_P", /* @@ -4622,32 +4729,32 @@ struct window_config #define CHECK_WINDOW_CONFIGURATION(x) CHECK_RECORD (x, window_configuration) static Lisp_Object -mark_window_config (Lisp_Object obj, void (*markobj) (Lisp_Object)) +mark_window_config (Lisp_Object obj) { struct window_config *config = XWINDOW_CONFIGURATION (obj); int i; - markobj (config->current_window); - markobj (config->current_buffer); - markobj (config->minibuffer_scroll_window); - markobj (config->root_window); + mark_object (config->current_window); + mark_object (config->current_buffer); + mark_object (config->minibuffer_scroll_window); + mark_object (config->root_window); for (i = 0; i < config->saved_windows_count; i++) { struct saved_window *s = SAVED_WINDOW_N (config, i); - markobj (s->window); - markobj (s->buffer); - markobj (s->start); - markobj (s->pointm); - markobj (s->sb_point); - markobj (s->mark); + mark_object (s->window); + mark_object (s->buffer); + mark_object (s->start); + mark_object (s->pointm); + mark_object (s->sb_point); + mark_object (s->mark); #if 0 /* #### This looked like this. I do not see why specifier cached values should not be marked, as such specifiers as toolbars might have GC-able instances. Freed configs are not marked, aren't they? -- kkm */ - markobj (s->dedicated); + mark_object (s->dedicated); #else -#define WINDOW_SLOT(slot, compare) ((void) (markobj (s->slot))) +#define WINDOW_SLOT(slot, compare) mark_object (s->slot) #include "winslots.h" #endif } @@ -5050,7 +5157,7 @@ by `current-window-configuration' (which see). SET_LAST_FACECHANGE (w); w->config_mark = 0; -#define WINDOW_SLOT(slot, compare) w->slot = p->slot; +#define WINDOW_SLOT(slot, compare) w->slot = p->slot #include "winslots.h" /* Reinstall the saved buffer and pointers into it. */ @@ -5324,7 +5431,7 @@ save_window_save (Lisp_Object window, struct window_config *config, int i) p->hscroll = w->hscroll; p->modeline_hscroll = w->modeline_hscroll; -#define WINDOW_SLOT(slot, compare) p->slot = w->slot; +#define WINDOW_SLOT(slot, compare) p->slot = w->slot #include "winslots.h" if (!NILP (w->buffer)) @@ -5466,6 +5573,78 @@ Does not restore the value of point in current buffer. return unbind_to (speccount, val); } +DEFUN ("current-pixel-column", Fcurrent_pixel_column, 0, 2, 0, /* +Return the horizontal pixel position of POS in window. +Beginning of line is column 0. This is calculated using the redisplay +display tables. If WINDOW is nil, the current window is assumed. +If POS is nil, point is assumed. Note that POS must be visible for +a non-nil result to be returned. +*/ + (window, pos)) +{ + struct window* w = decode_window (window); + display_line_dynarr *dla = window_display_lines (w, CURRENT_DISP); + + struct display_line *dl = 0; + struct display_block *db = 0; + struct rune* rb = 0; + int y = w->last_point_y[CURRENT_DISP]; + int x = w->last_point_x[CURRENT_DISP]; + + if (MINI_WINDOW_P (w)) + return Qnil; + + if (y<0 || x<0 || y >= Dynarr_length (dla) || !NILP (pos)) + { + int first_line, i; + Bufpos point; + + if (NILP (pos)) + pos = Fwindow_point (window); + + CHECK_INT (pos); + point = XINT (pos); + + if (Dynarr_length (dla) && Dynarr_atp (dla, 0)->modeline) + first_line = 1; + else + first_line = 0; + + for (i = first_line; i < Dynarr_length (dla); i++) + { + dl = Dynarr_atp (dla, i); + /* find the vertical location first */ + if (point >= dl->bufpos && point <= dl->end_bufpos) + { + db = get_display_block_from_line (dl, TEXT); + for (i = 0; i < Dynarr_length (db->runes); i++) + { + rb = Dynarr_atp (db->runes, i); + if (point <= rb->bufpos) + goto found_bufpos; + } + return Qnil; + } + } + return Qnil; + found_bufpos: + ; + } + else + { + /* optimised case */ + dl = Dynarr_atp (dla, y); + db = get_display_block_from_line (dl, TEXT); + + if (x >= Dynarr_length (db->runes)) + return Qnil; + + rb = Dynarr_atp (db->runes, x); + } + + return make_int (rb->xpos - WINDOW_LEFT (w)); +} + #ifdef DEBUG_XEMACS /* This is short and simple in elisp, but... it was written to debug @@ -5518,8 +5697,6 @@ syms_of_window (void) defsymbol (&Qwindowp, "windowp"); defsymbol (&Qwindow_live_p, "window-live-p"); defsymbol (&Qwindow_configurationp, "window-configuration-p"); - defsymbol (&Qscroll_up, "scroll-up"); - defsymbol (&Qscroll_down, "scroll-down"); defsymbol (&Qtemp_buffer_show_hook, "temp-buffer-show-hook"); defsymbol (&Qdisplay_buffer, "display-buffer"); @@ -5535,6 +5712,7 @@ syms_of_window (void) #endif DEFSUBR (Fselected_window); + DEFSUBR (Flast_nonminibuf_window); DEFSUBR (Fminibuffer_window); DEFSUBR (Fwindow_minibuffer_p); DEFSUBR (Fwindowp); @@ -5545,6 +5723,7 @@ syms_of_window (void) DEFSUBR (Fwindow_previous_child); DEFSUBR (Fwindow_parent); DEFSUBR (Fwindow_lowest_p); + DEFSUBR (Fwindow_truncated_p); DEFSUBR (Fwindow_highest_p); DEFSUBR (Fwindow_leftmost_p); DEFSUBR (Fwindow_rightmost_p); @@ -5613,14 +5792,30 @@ syms_of_window (void) DEFSUBR (Fset_window_configuration); DEFSUBR (Fcurrent_window_configuration); DEFSUBR (Fsave_window_excursion); + DEFSUBR (Fcurrent_pixel_column); } void -vars_of_window (void) +reinit_vars_of_window (void) { + int i; /* Make sure all windows get marked */ minibuf_window = Qnil; - staticpro (&minibuf_window); + staticpro_nodump (&minibuf_window); + + for (i = 0; i < countof (Vwindow_configuration_free_list); i++) + { + Vwindow_configuration_free_list[i] = + make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1), + &lrecord_window_configuration); + staticpro_nodump (&Vwindow_configuration_free_list[i]); + } +} + +void +vars_of_window (void) +{ + reinit_vars_of_window (); DEFVAR_BOOL ("scroll-on-clipped-lines", &scroll_on_clipped_lines /* *Non-nil means to scroll if point lands on a line which is clipped. @@ -5651,6 +5846,13 @@ If non-nil, this is a buffer and \\[scroll-other-window] should scroll its windo */ ); Vother_window_scroll_buffer = Qnil; + DEFVAR_LISP ("window-pixel-scroll-increment", &Vwindow_pixel_scroll_increment /* +*Number of pixels to scroll by per requested line. +If nil then normal line scrolling occurs regardless of line height. +If t then scrolling is done in increments equal to the height of the default face. +*/ ); + Vwindow_pixel_scroll_increment = Qt; + DEFVAR_INT ("next-screen-context-lines", &next_screen_context_lines /* *Number of lines of continuity when scrolling by screenfuls. */ ); @@ -5665,18 +5867,6 @@ If non-nil, this is a buffer and \\[scroll-other-window] should scroll its windo *Delete any window less than this wide. */ ); window_min_width = 10; - - { - int i; - - for (i = 0; i < countof (Vwindow_configuration_free_list); i++) - { - Vwindow_configuration_free_list[i] = - make_lcrecord_list (sizeof_window_config_for_n_windows (i + 1), - &lrecord_window_configuration); - staticpro (&Vwindow_configuration_free_list[i]); - } - } } void diff --git a/src/window.h b/src/window.h index 342ad44..043a9fc 100644 --- a/src/window.h +++ b/src/window.h @@ -130,6 +130,14 @@ struct window int hscroll; /* Idem for the window's modeline */ int modeline_hscroll; + /* Amount to clip off the top line for pixel-based scrolling. Point + will remain constant but this will be incremented to + incrementally shift lines up. */ + int top_yoffset; + /* Amount to clip off the left of the lines for pixel-based + scrolling. Hscroll will remain constant but this will be + incremented to incrementally shift lines left.*/ + int left_xoffset; /* Number saying how recently window was selected */ Lisp_Object use_time; /* text.modified of displayed buffer as of last time display completed */ @@ -254,7 +262,6 @@ DECLARE_LRECORD (window, struct window); #define XWINDOW(x) XRECORD (x, window, struct window) #define XSETWINDOW(x, p) XSETRECORD (x, p, window) #define WINDOWP(x) RECORDP (x, window) -#define GC_WINDOWP(x) GC_RECORDP (x, window) #define CHECK_WINDOW(x) CHECK_RECORD (x, window) #define CONCHECK_WINDOW(x) CONCHECK_RECORD (x, window) @@ -382,6 +389,7 @@ int window_divider_width (struct window *w); /* XEmacs window size and positioning macros. */ #define WINDOW_TOP(w) ((w)->pixel_top) #define WINDOW_TEXT_TOP(w) (WINDOW_TOP (w) + window_top_gutter_height (w)) +#define WINDOW_TEXT_TOP_CLIP(w) ((w)->top_yoffset) #define WINDOW_BOTTOM(w) ((w)->pixel_top + (w)->pixel_height) #define WINDOW_TEXT_BOTTOM(w) (WINDOW_BOTTOM (w) - window_bottom_gutter_height (w)) #define WINDOW_LEFT(w) ((w)->pixel_left) diff --git a/src/xmu.h b/src/xmu.h index f2d42d1..715d2ee 100644 --- a/src/xmu.h +++ b/src/xmu.h @@ -9,6 +9,7 @@ # include # include # include +# include /* Do the EDITRES protocol if running X11R5 (or later) version */ #if (XtSpecificationRelease >= 5) @@ -27,5 +28,11 @@ int XmuReadBitmapDataFromFile (CONST char *filename, unsigned int *width, int XmuPrintDefaultErrorMessage (Display *dpy, XErrorEvent *event, FILE *fp); void XmuCopyISOLatin1Lowered (char *, CONST char *); +#define Max(x, y) (((x) > (y)) ? (x) : (y)) +#define Min(x, y) (((x) < (y)) ? (x) : (y)) +#define AssignMax(x, y) {if ((y) > (x)) x = (y);} +#define AssignMin(x, y) {if ((y) < (x)) x = (y);} +typedef enum {XtorientHorizontal, XtorientVertical} XtOrientation; + #endif diff --git a/tests/ChangeLog b/tests/ChangeLog index e055147..5c35ad8 100644 --- a/tests/ChangeLog +++ b/tests/ChangeLog @@ -1,3 +1,7 @@ +1999-11-10 XEmacs Build Bot + + * XEmacs 21.2.20 is released + 1999-07-30 XEmacs Build Bot * XEmacs 21.2.19 is released diff --git a/tests/automated/hash-table-tests.el b/tests/automated/hash-table-tests.el index d68e399..0c7247e 100644 --- a/tests/automated/hash-table-tests.el +++ b/tests/automated/hash-table-tests.el @@ -37,30 +37,41 @@ (require 'test-harness)))) ;; Test all combinations of make-hash-table keywords -(dolist (type '(non-weak weak key-weak value-weak)) - (dolist (test '(eq eql equal)) - (dolist (size '(0 1 100)) - (dolist (rehash-size '(1.1 9.9)) - (dolist (rehash-threshold '(0.2 .9)) +(dolist (test '(eq eql equal)) + (dolist (size '(0 1 100)) + (dolist (rehash-size '(1.1 9.9)) + (dolist (rehash-threshold '(0.2 .9)) + (dolist (weakness '(nil t key value)) (dolist (data '(() (1 2) (1 2 3 4))) - (let ((ht (make-hash-table :test test - :type type - :size size - :rehash-size rehash-size - :rehash-threshold rehash-threshold))) + (let ((ht (make-hash-table + :test test + :size size + :rehash-size rehash-size + :rehash-threshold rehash-threshold + :weakness weakness))) (Assert (equal ht (car (let ((print-readably t)) (read-from-string (prin1-to-string ht)))))) (Assert (eq test (hash-table-test ht))) - (Assert (eq type (hash-table-type ht))) (Assert (<= size (hash-table-size ht))) (Assert (eql rehash-size (hash-table-rehash-size ht))) - (Assert (eql rehash-threshold (hash-table-rehash-threshold ht)))))))))) + (Assert (eql rehash-threshold (hash-table-rehash-threshold ht))) + (Assert (eq weakness (hash-table-weakness ht)))))))))) -(loop for (fun type) in '((make-hashtable non-weak) - (make-weak-hashtable weak) - (make-key-weak-hashtable key-weak) - (make-value-weak-hashtable value-weak)) - do (Assert (eq type (hash-table-type (funcall fun 10))))) +(loop for (fun weakness) in '((make-hashtable nil) + (make-weak-hashtable t) + (make-key-weak-hashtable key) + (make-value-weak-hashtable value)) + do (Assert (eq weakness (hash-table-weakness (funcall fun 10))))) + +(loop for (type weakness) in '((non-weak nil) + (weak t) + (key-weak key) + (value-weak value)) + do (Assert (equal (make-hash-table :type type) + (make-hash-table :weakness weakness)))) + +(Assert (not (equal (make-hash-table :weakness nil) + (make-hash-table :weakness t)))) (let ((ht (make-hash-table :size 20 :rehash-threshold .75 :test 'eq)) (size 80)) @@ -69,6 +80,7 @@ (Assert (eq 'eq (hash-table-test ht))) (Assert (eq 'non-weak (hash-table-type ht))) (Assert (eq 'non-weak (hashtable-type ht))) + (Assert (eq 'nil (hash-table-weakness ht))) (dotimes (j size) (puthash j (- j) ht) (Assert (eq (gethash j ht) (- j))) @@ -193,13 +205,13 @@ )) ;; Test that weak hash-tables are properly handled -(loop for (type expected-count expected-k-sum expected-v-sum) in - '((non-weak 6 38 25) - (weak 3 6 9) - (key-weak 4 38 9) - (value-weak 4 6 25)) +(loop for (weakness expected-count expected-k-sum expected-v-sum) in + '((nil 6 38 25) + (t 3 6 9) + (key 4 38 9) + (value 4 6 25)) do - (let* ((ht (make-hash-table :type type)) + (let* ((ht (make-hash-table :weakness weakness)) (my-obj (cons ht ht))) (garbage-collect) (puthash my-obj 1 ht) @@ -238,9 +250,9 @@ (Assert (= v-sum k-sum)))) ;;; Test reading and printing of hash-table objects -(let ((h1 #s(hashtable type weak rehash-size 3.0 rehash-threshold .2 test eq data (1 2 3 4))) - (h2 #s(hash-table type weak rehash-size 3.0 rehash-threshold .2 test eq data (1 2 3 4))) - (h3 (make-hash-table :type 'weak :rehash-size 3.0 :rehash-threshold .2 :test 'eq))) +(let ((h1 #s(hashtable weakness t rehash-size 3.0 rehash-threshold .2 test eq data (1 2 3 4))) + (h2 #s(hash-table weakness t rehash-size 3.0 rehash-threshold .2 test eq data (1 2 3 4))) + (h3 (make-hash-table :weakness t :rehash-size 3.0 :rehash-threshold .2 :test 'eq))) (Assert (equal h1 h2)) (Assert (not (equal h1 h3))) (puthash 1 2 h3) @@ -267,3 +279,7 @@ (clrhash h2) (Assert (equal h1 h2)) ) + +;;; Test sxhash +(Assert (= (sxhash "foo") (sxhash "foo"))) +(Assert (= (sxhash '(1 2 3)) (sxhash '(1 2 3)))) diff --git a/tests/automated/lisp-tests.el b/tests/automated/lisp-tests.el index 3ee719b..2ace595 100644 --- a/tests/automated/lisp-tests.el +++ b/tests/automated/lisp-tests.el @@ -229,6 +229,8 @@ (Assert (= (+ 1.0 1) 2.0)) (Assert (= (+ 1.0 1 1) 3.0)) (Assert (= (+ 1 1 1.0) 3.0)) +(Assert (eq (1+ most-positive-fixnum) most-negative-fixnum)) +(Assert (eq (+ most-positive-fixnum 1) most-negative-fixnum)) ;; Test `-' (Check-Error wrong-number-of-arguments (-)) @@ -253,6 +255,9 @@ (Assert (= (- 1.5 1) .5)) (Assert (= (- 1 1.5) (- .5))) +(Assert (eq (1- most-negative-fixnum) most-positive-fixnum)) +(Assert (eq (- most-negative-fixnum 1) most-positive-fixnum)) + ;; Test `/' ;; Test division by zero errors diff --git a/tests/glyph-test.el b/tests/glyph-test.el index 511bbc8..365322c 100644 --- a/tests/glyph-test.el +++ b/tests/glyph-test.el @@ -1,24 +1,28 @@ -(setq str "Hello There") (set-extent-begin-glyph - (make-extent 0 0 str) - (make-glyph [xpm :file "../etc/xemacs-icon.xpm"])) + (make-extent (point) (point)) + (setq im (make-glyph [xpm :file "xemacs-icon.xpm"]))) (defun foo () - (interactive) - (ding)) -; (setq ok-select (not ok-select))) + (interactive) + (setq ok-select (not ok-select))) + +(defun fee () (interactive) (message "hello")) ;; button in a group (setq ok-select nil) (set-extent-begin-glyph (make-extent (point) (point)) - (make-glyph [button :descriptor ["ok " (setq ok-select t) - :style radio :selected ok-select]])) + (setq radio-button1 + (make-glyph + [button :descriptor ["ok " (setq ok-select t) + :style radio :selected ok-select]]))) ;; button in a group (set-extent-begin-glyph (make-extent (point) (point)) - (make-glyph [button :descriptor ["ok" (setq ok-select nil) :style radio - :selected (not ok-select)]])) + (setq radio-button2 + (make-glyph + [button :descriptor ["ok" (setq ok-select nil) :style radio + :selected (not ok-select)]]))) ;; toggle button (set-extent-begin-glyph (make-extent (point) (point)) @@ -28,19 +32,20 @@ :selected (not ok-select)]]))) (set-extent-begin-glyph (make-extent (point) (point)) - (make-glyph [button :descriptor ["ok" :style toggle - :callback - (setq ok-select (not ok-select)) - :selected ok-select]])) + (setq toggle-button + (make-glyph [button :descriptor ["ok" :style toggle + :callback + (setq ok-select (not ok-select)) + :selected ok-select]]))) ;; normal pushbutton (set-extent-begin-glyph (make-extent (point) (point)) - (setq pbutton (make-glyph - [button :width 10 :height 2 - :face modeline-mousable - :descriptor "ok" :callback foo - :selected t]))) + (setq push-button + (make-glyph [button :width 10 :height 2 + :face modeline-mousable + :descriptor "ok" :callback foo + :selected t]))) ;; tree view (set-extent-begin-glyph (make-extent (point) (point)) @@ -58,9 +63,9 @@ (make-extent (point) (point)) (setq tab (make-glyph [tab-control :descriptor "My Tab" - :face default + :face highlight :properties (:items (["One" foo] - ["Two" foo] + ["Two" fee] ["Three" foo]))]))) ;; progress gauge @@ -94,8 +99,7 @@ (make-glyph [button :face modeline-mousable :descriptor "ok" :callback foo - :image (make-glyph - [xpm :file "../etc/xemacs-icon.xpm"])])) + :image [xpm :file "../etc/xemacs-icon.xpm"]])) ;; normal pushbutton (set-extent-begin-glyph @@ -105,20 +109,25 @@ ;; edit box (set-extent-begin-glyph (make-extent (point) (point)) - (setq hedit (make-glyph [edit-field :pixel-width 50 :pixel-height 30 - :face bold-italic - :descriptor ["Hello"]]))) + (setq edit-field (make-glyph [edit-field :pixel-width 50 :pixel-height 30 + :face bold-italic + :descriptor ["Hello"]]))) ;; combo box (set-extent-begin-glyph (make-extent (point) (point)) - (setq hcombo (make-glyph - [combo-box :width 10 :height 3 :descriptor ["Hello"] - :properties (:items ("One" "Two" "Three"))]))) + (setq combo-box (make-glyph + [combo-box :width 10 :descriptor ["Hello"] + :properties (:items ("One" "Two" "Three"))]))) + +;; label +(set-extent-begin-glyph + (make-extent (point) (point)) + (setq label (make-glyph [label :pixel-width 150 :descriptor "Hello"]))) -;; line +;; string (set-extent-begin-glyph (make-extent (point) (point)) - (make-glyph [label :pixel-width 150 :descriptor "Hello"])) + (setq str (make-glyph [string :data "Hello There"]))) ;; scrollbar ;(set-extent-begin-glyph @@ -129,3 +138,17 @@ (setq sw (make-glyph [subwindow :pixel-width 50 :pixel-height 70])) (set-extent-begin-glyph (make-extent (point) (point)) sw) +;; layout +(setq layout + (make-glyph + [layout :pixel-width 200 :pixel-height 250 + :orientation vertical + :justify left + :border [string :data "Hello There Mrs"] + :items ([layout :orientation horizontal + :items (radio-button1 radio-button2)] + edit-field toggle-button label str)])) +(set-glyph-face layout 'gui-element) +(set-extent-begin-glyph + (make-extent (point) (point)) layout) +