Mercurial > hg > xemacs-beta
annotate lwlib/lwlib.c @ 4981:4aebb0131297
Cleanups/renaming of EXTERNAL_TO_C_STRING and friends
-------------------- ChangeLog entries follow: --------------------
modules/ChangeLog addition:
2010-02-05 Ben Wing <ben@xemacs.org>
* postgresql/postgresql.c:
* postgresql/postgresql.c (CHECK_LIVE_CONNECTION):
* postgresql/postgresql.c (Fpq_connectdb):
* postgresql/postgresql.c (Fpq_connect_start):
* postgresql/postgresql.c (Fpq_lo_import):
* postgresql/postgresql.c (Fpq_lo_export):
* ldap/eldap.c (Fldap_open):
* ldap/eldap.c (Fldap_search_basic):
* ldap/eldap.c (Fldap_add):
* ldap/eldap.c (Fldap_modify):
* ldap/eldap.c (Fldap_delete):
* canna/canna_api.c (Fcanna_initialize):
* canna/canna_api.c (Fcanna_store_yomi):
* canna/canna_api.c (Fcanna_parse):
* canna/canna_api.c (Fcanna_henkan_begin):
EXTERNAL_TO_C_STRING returns its argument instead of storing it
in a parameter, and is renamed to EXTERNAL_TO_ITEXT. Similar
things happen to related macros. See entry in src/ChangeLog.
More Mule-izing of postgresql.c. Extract out common code
between `pq-connectdb' and `pq-connect-start'. Fix places
that signal an error string using a formatted string to instead
follow the standard and have a fixed reason followed by the
particular error message stored as one of the frobs.
src/ChangeLog addition:
2010-02-05 Ben Wing <ben@xemacs.org>
* console-msw.c (write_string_to_mswindows_debugging_output):
* console-msw.c (Fmswindows_message_box):
* console-x.c (x_perhaps_init_unseen_key_defaults):
* console.c:
* database.c (dbm_get):
* database.c (dbm_put):
* database.c (dbm_remove):
* database.c (berkdb_get):
* database.c (berkdb_put):
* database.c (berkdb_remove):
* database.c (Fopen_database):
* device-gtk.c (gtk_init_device):
* device-msw.c (msprinter_init_device_internal):
* device-msw.c (msprinter_default_printer):
* device-msw.c (msprinter_init_device):
* device-msw.c (sync_printer_with_devmode):
* device-msw.c (Fmsprinter_select_settings):
* device-x.c (sanity_check_geometry_resource):
* device-x.c (Dynarr_add_validified_lisp_string):
* device-x.c (x_init_device):
* device-x.c (Fx_put_resource):
* device-x.c (Fx_valid_keysym_name_p):
* device-x.c (Fx_set_font_path):
* dialog-msw.c (push_lisp_string_as_unicode):
* dialog-msw.c (handle_directory_dialog_box):
* dialog-msw.c (handle_file_dialog_box):
* dialog-x.c (dbox_descriptor_to_widget_value):
* editfns.c (Fformat_time_string):
* editfns.c (Fencode_time):
* editfns.c (Fset_time_zone_rule):
* emacs.c (make_argc_argv):
* emacs.c (Fdump_emacs):
* emodules.c (emodules_load):
* eval.c:
* eval.c (maybe_signal_error_1):
* event-msw.c (Fdde_alloc_advise_item):
* event-msw.c (mswindows_dde_callback):
* event-msw.c (mswindows_wnd_proc):
* fileio.c (report_error_with_errno):
* fileio.c (Fsysnetunam):
* fileio.c (Fdo_auto_save):
* font-mgr.c (extract_fcapi_string):
* font-mgr.c (Ffc_config_app_font_add_file):
* font-mgr.c (Ffc_config_app_font_add_dir):
* font-mgr.c (Ffc_config_filename):
* frame-gtk.c (gtk_set_frame_text_value):
* frame-gtk.c (gtk_create_widgets):
* frame-msw.c (mswindows_init_frame_1):
* frame-msw.c (mswindows_set_title_from_ibyte):
* frame-msw.c (msprinter_init_frame_3):
* frame-x.c (x_set_frame_text_value):
* frame-x.c (x_set_frame_properties):
* frame-x.c (start_drag_internal_1):
* frame-x.c (x_cde_transfer_callback):
* frame-x.c (x_create_widgets):
* glyphs-eimage.c (my_jpeg_output_message):
* glyphs-eimage.c (jpeg_instantiate):
* glyphs-eimage.c (gif_instantiate):
* glyphs-eimage.c (png_instantiate):
* glyphs-eimage.c (tiff_instantiate):
* glyphs-gtk.c (xbm_instantiate_1):
* glyphs-gtk.c (gtk_xbm_instantiate):
* glyphs-gtk.c (gtk_xpm_instantiate):
* glyphs-gtk.c (gtk_xface_instantiate):
* glyphs-gtk.c (cursor_font_instantiate):
* glyphs-gtk.c (gtk_redisplay_widget):
* glyphs-gtk.c (gtk_widget_instantiate_1):
* glyphs-gtk.c (gtk_add_tab_item):
* glyphs-msw.c (mswindows_xpm_instantiate):
* glyphs-msw.c (bmp_instantiate):
* glyphs-msw.c (mswindows_resource_instantiate):
* glyphs-msw.c (xbm_instantiate_1):
* glyphs-msw.c (mswindows_xbm_instantiate):
* glyphs-msw.c (mswindows_xface_instantiate):
* glyphs-msw.c (mswindows_redisplay_widget):
* glyphs-msw.c (mswindows_widget_instantiate):
* glyphs-msw.c (add_tree_item):
* glyphs-msw.c (add_tab_item):
* glyphs-msw.c (mswindows_combo_box_instantiate):
* glyphs-msw.c (mswindows_widget_query_string_geometry):
* glyphs-x.c (x_locate_pixmap_file):
* glyphs-x.c (xbm_instantiate_1):
* glyphs-x.c (x_xbm_instantiate):
* glyphs-x.c (extract_xpm_color_names):
* glyphs-x.c (x_xpm_instantiate):
* glyphs-x.c (x_xface_instantiate):
* glyphs-x.c (autodetect_instantiate):
* glyphs-x.c (safe_XLoadFont):
* glyphs-x.c (cursor_font_instantiate):
* glyphs-x.c (x_redisplay_widget):
* glyphs-x.c (Fchange_subwindow_property):
* glyphs-x.c (x_widget_instantiate):
* glyphs-x.c (x_tab_control_redisplay):
* glyphs.c (pixmap_to_lisp_data):
* gui-x.c (menu_separator_style_and_to_external):
* gui-x.c (add_accel_and_to_external):
* gui-x.c (button_item_to_widget_value):
* hpplay.c (player_error_internal):
* hpplay.c (play_sound_file):
* hpplay.c (play_sound_data):
* intl.c (Fset_current_locale):
* lisp.h:
* menubar-gtk.c (gtk_xemacs_set_accel_keys):
* menubar-msw.c (populate_menu_add_item):
* menubar-msw.c (populate_or_checksum_helper):
* menubar-x.c (menu_item_descriptor_to_widget_value_1):
* nt.c (init_user_info):
* nt.c (get_long_basename):
* nt.c (nt_get_resource):
* nt.c (init_mswindows_environment):
* nt.c (get_cached_volume_information):
* nt.c (mswindows_readdir):
* nt.c (read_unc_volume):
* nt.c (mswindows_stat):
* nt.c (mswindows_getdcwd):
* nt.c (mswindows_executable_type):
* nt.c (Fmswindows_short_file_name):
* ntplay.c (nt_play_sound_file):
* objects-gtk.c:
* objects-gtk.c (gtk_valid_color_name_p):
* objects-gtk.c (gtk_initialize_font_instance):
* objects-gtk.c (gtk_font_list):
* objects-msw.c (font_enum_callback_2):
* objects-msw.c (parse_font_spec):
* objects-x.c (x_parse_nearest_color):
* objects-x.c (x_valid_color_name_p):
* objects-x.c (x_initialize_font_instance):
* objects-x.c (x_font_instance_truename):
* objects-x.c (x_font_list):
* objects-xlike-inc.c (XFUN):
* objects-xlike-inc.c (xft_find_charset_font):
* process-nt.c (mswindows_report_winsock_error):
* process-nt.c (nt_create_process):
* process-nt.c (get_internet_address):
* process-nt.c (nt_open_network_stream):
* process-unix.c:
* process-unix.c (allocate_pty):
* process-unix.c (get_internet_address):
* process-unix.c (unix_canonicalize_host_name):
* process-unix.c (unix_open_network_stream):
* realpath.c:
* select-common.h (lisp_data_to_selection_data):
* select-gtk.c (symbol_to_gtk_atom):
* select-gtk.c (atom_to_symbol):
* select-msw.c (symbol_to_ms_cf):
* select-msw.c (mswindows_register_selection_data_type):
* select-x.c (symbol_to_x_atom):
* select-x.c (x_atom_to_symbol):
* select-x.c (hack_motif_clipboard_selection):
* select-x.c (Fx_store_cutbuffer_internal):
* sound.c (Fplay_sound_file):
* sound.c (Fplay_sound):
* sound.h (sound_perror):
* sysdep.c:
* sysdep.c (qxe_allocating_getcwd):
* sysdep.c (qxe_execve):
* sysdep.c (copy_in_passwd):
* sysdep.c (qxe_getpwnam):
* sysdep.c (qxe_ctime):
* sysdll.c (dll_open):
* sysdll.c (dll_function):
* sysdll.c (dll_variable):
* sysdll.c (search_linked_libs):
* sysdll.c (dll_error):
* sysfile.h:
* sysfile.h (PATHNAME_CONVERT_OUT_TSTR):
* sysfile.h (PATHNAME_CONVERT_OUT_UTF_8):
* sysfile.h (PATHNAME_CONVERT_OUT):
* sysfile.h (LISP_PATHNAME_CONVERT_OUT):
* syswindows.h (ITEXT_TO_TSTR):
* syswindows.h (LOCAL_FILE_FORMAT_TO_TSTR):
* syswindows.h (TSTR_TO_LOCAL_FILE_FORMAT):
* syswindows.h (LOCAL_FILE_FORMAT_TO_INTERNAL_MSWIN):
* syswindows.h (LISP_LOCAL_FILE_FORMAT_MAYBE_URL_TO_TSTR):
* text.h:
* text.h (eicpy_ext_len):
* text.h (enum new_dfc_src_type):
* text.h (EXTERNAL_TO_ITEXT):
* text.h (GET_STRERROR):
* tooltalk.c (check_status):
* tooltalk.c (Fadd_tooltalk_message_arg):
* tooltalk.c (Fadd_tooltalk_pattern_attribute):
* tooltalk.c (Fadd_tooltalk_pattern_arg):
* win32.c (tstr_to_local_file_format):
* win32.c (mswindows_lisp_error_1):
* win32.c (mswindows_report_process_error):
* win32.c (Fmswindows_shell_execute):
* win32.c (mswindows_read_link_1):
Changes involving external/internal format conversion,
mostly code cleanup and renaming.
1. Eliminate the previous macros like LISP_STRING_TO_EXTERNAL
that stored its result in a parameter. The new version of
LISP_STRING_TO_EXTERNAL returns its result through the
return value, same as the previous NEW_LISP_STRING_TO_EXTERNAL.
Use the new-style macros throughout the code.
2. Rename C_STRING_TO_EXTERNAL and friends to ITEXT_TO_EXTERNAL,
in keeping with overall naming rationalization involving
Itext and related types.
Macros involved in previous two:
EXTERNAL_TO_C_STRING -> EXTERNAL_TO_ITEXT
EXTERNAL_TO_C_STRING_MALLOC -> EXTERNAL_TO_ITEXT_MALLOC
SIZED_EXTERNAL_TO_C_STRING -> SIZED_EXTERNAL_TO_ITEXT
SIZED_EXTERNAL_TO_C_STRING_MALLOC -> SIZED_EXTERNAL_TO_ITEXT_MALLOC
C_STRING_TO_EXTERNAL -> ITEXT_TO_EXTERNAL
C_STRING_TO_EXTERNAL_MALLOC -> ITEXT_TO_EXTERNAL_MALLOC
LISP_STRING_TO_EXTERNAL
LISP_STRING_TO_EXTERNAL_MALLOC
LISP_STRING_TO_TSTR
C_STRING_TO_TSTR -> ITEXT_TO_TSTR
TSTR_TO_C_STRING -> TSTR_TO_ITEXT
The following four still return their values through parameters,
since they have more than one value to return:
C_STRING_TO_SIZED_EXTERNAL -> ITEXT_TO_SIZED_EXTERNAL
LISP_STRING_TO_SIZED_EXTERNAL
C_STRING_TO_SIZED_EXTERNAL_MALLOC -> ITEXT_TO_SIZED_EXTERNAL_MALLOC
LISP_STRING_TO_SIZED_EXTERNAL_MALLOC
Sometimes additional casts had to be inserted, since the old
macros played strange games and completely defeated the type system
of the store params.
3. Rewrite many places where direct calls to TO_EXTERNAL_FORMAT
occurred with calls to one of the convenience macros listed above,
or to make_extstring().
4. Eliminate SIZED_C_STRING macros (they were hardly used, anyway)
and use a direct call to TO_EXTERNAL_FORMAT or TO_INTERNAL_FORMAT.
4. Use LISP_PATHNAME_CONVERT_OUT in many places instead of something
like LISP_STRING_TO_EXTERNAL(..., Qfile_name).
5. Eliminate some temporary variables that are no longer necessary
now that we return a value rather than storing it into a variable.
6. Some Mule-izing in database.c.
7. Error functions:
-- A bit of code cleanup in maybe_signal_error_1.
-- Eliminate report_file_type_error; it's just an alias for
signal_error_2 with params in a different order.
-- Fix some places in the hostname-handling code that directly
inserted externally-retrieved error strings into the
supposed ASCII "reason" param instead of doing the right thing
and sticking text descriptive of what was going on in "reason"
and putting the external message in a frob.
8. Use Ascbyte instead of CIbyte in process-unix.c and maybe one
or two other places.
9. Some code cleanup in copy_in_passwd() in sysdep.c.
10. Fix a real bug due to accidental variable shadowing in
tstr_to_local_file_format() in win32.c.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Fri, 05 Feb 2010 11:02:24 -0600 |
parents | aa5ed11f473b |
children | ade4c7e2c6cb |
rev | line source |
---|---|
428 | 1 /* A general interface to the widgets of different toolkits. |
2 Copyright (C) 1992, 1993, 1994 Lucid, Inc. | |
3 Copyright (C) 1995 Tinker Systems and INS Engineering Corp. | |
4 | |
5 This file is part of the Lucid Widget Library. | |
6 | |
7 The Lucid Widget Library is free software; you can redistribute it and/or | |
8 modify it under the terms of the GNU General Public License as published by | |
9 the Free Software Foundation; either version 2, or (at your option) | |
10 any later version. | |
11 | |
12 The Lucid Widget Library is distributed in the hope that it will be useful, | |
13 but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 GNU General Public License for more details. | |
16 | |
17 You should have received a copy of the GNU General Public License | |
18 along with XEmacs; see the file COPYING. If not, write to | |
19 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
20 Boston, MA 02111-1307, USA. */ | |
21 | |
22 #include <config.h> | |
23 #include <stdio.h> | |
24 #include <stdlib.h> | |
25 #include <string.h> | |
26 #include <sys/types.h> | |
27 #ifdef HAVE_UNISTD_H | |
28 #include <unistd.h> | |
29 #endif | |
30 #include <X11/StringDefs.h> | |
31 #include "lwlib-internal.h" | |
32 #include "lwlib-utils.h" | |
33 | |
34 #ifdef NEED_LUCID | |
35 #include "lwlib-Xlw.h" | |
36 #endif | |
37 #ifdef NEED_MOTIF | |
38 #include "lwlib-Xm.h" | |
434 | 39 #ifdef LWLIB_WIDGETS_MOTIF |
40 #include <Xm/Xm.h> | |
41 #endif | |
428 | 42 #endif |
43 #ifdef NEED_ATHENA | |
44 #include "lwlib-Xaw.h" | |
45 #endif | |
46 | |
47 /* #### Does a check need to be put back in here to make sure we have | |
48 sufficient defines to function properly or are the checks in the | |
49 makefile sufficient? */ | |
50 | |
51 /* List of all widgets managed by the library. Note that each "widget" | |
52 listed here may actually be a tree of widgets; for example, a | |
53 single entry here might represent a single menubar or popup menu, | |
54 each of which might be implemented with a tree of widgets. | |
55 */ | |
56 static widget_info *all_widget_info = NULL; | |
57 | |
58 /* boolean flag indicating that the menubar is active */ | |
59 int lw_menu_active = 0; | |
60 | |
61 /* X11 menubar widget */ | |
62 Widget lw_menubar_widget = NULL; | |
63 | |
64 /* whether the last menu operation was a keyboard accelerator */ | |
65 int lw_menu_accelerate = False; | |
66 | |
67 | |
68 /* Forward declarations */ | |
434 | 69 static void instantiate_widget_instance (widget_instance *instance); |
70 static void free_widget_value_args (widget_value* wv); | |
428 | 71 |
72 | |
73 /* utility functions for widget_instance and widget_info */ | |
74 static char * | |
442 | 75 safe_strdup (const char *s) |
428 | 76 { |
77 char *result; | |
78 if (! s) return 0; | |
79 result = (char *) malloc (strlen (s) + 1); | |
80 if (! result) | |
81 return 0; | |
82 strcpy (result, s); | |
83 return result; | |
84 } | |
85 | |
86 static void | |
87 safe_free_str (char *s) | |
88 { | |
89 if (s) free (s); | |
90 } | |
91 | |
92 static widget_value *widget_value_free_list = 0; | |
93 | |
94 widget_value * | |
95 malloc_widget_value (void) | |
96 { | |
97 widget_value *wv; | |
98 if (widget_value_free_list) | |
99 { | |
100 wv = widget_value_free_list; | |
101 widget_value_free_list = wv->free_list; | |
102 wv->free_list = 0; | |
103 } | |
104 else | |
105 { | |
106 wv = (widget_value *) malloc (sizeof (widget_value)); | |
107 } | |
108 if (wv) | |
109 { | |
438 | 110 memset (wv, '\0', sizeof (widget_value)); |
428 | 111 } |
112 return wv; | |
113 } | |
114 | |
115 /* this is analogous to free(). It frees only what was allocated | |
116 by malloc_widget_value(), and no substructures. | |
117 */ | |
118 void | |
119 free_widget_value (widget_value *wv) | |
120 { | |
121 if (wv->free_list) | |
122 abort (); | |
123 wv->free_list = widget_value_free_list; | |
124 widget_value_free_list = wv; | |
125 } | |
126 | |
127 static void | |
128 free_widget_value_contents (widget_value *wv) | |
129 { | |
130 if (wv->name) free (wv->name); | |
131 if (wv->value) free (wv->value); | |
132 if (wv->key) free (wv->key); | |
133 | |
134 /* #### - all of this 0xDEADBEEF stuff should be unnecessary | |
135 in production code... it should be conditionalized. */ | |
136 wv->name = wv->value = wv->key = (char *) 0xDEADBEEF; | |
137 | |
138 if (wv->toolkit_data && wv->free_toolkit_data) | |
139 { | |
140 XtFree ((char *) wv->toolkit_data); | |
141 wv->toolkit_data = (void *) 0xDEADBEEF; | |
142 } | |
143 #ifdef NEED_SCROLLBARS | |
144 if (wv->scrollbar_data) | |
145 { | |
146 free (wv->scrollbar_data); | |
147 wv->scrollbar_data = NULL; | |
148 } | |
149 #endif | |
150 if (wv->contents && (wv->contents != (widget_value*)1)) | |
151 { | |
152 free_widget_value_tree (wv->contents); | |
153 wv->contents = (widget_value *) 0xDEADBEEF; | |
154 } | |
434 | 155 |
156 free_widget_value_args (wv); | |
157 | |
428 | 158 if (wv->next) |
159 { | |
160 free_widget_value_tree (wv->next); | |
161 wv->next = (widget_value *) 0xDEADBEEF; | |
162 } | |
163 } | |
164 | |
165 void | |
166 free_widget_value_tree (widget_value *wv) | |
167 { | |
168 if (!wv) | |
169 return; | |
170 | |
171 free_widget_value_contents (wv); | |
172 free_widget_value (wv); | |
173 } | |
174 | |
175 #ifdef NEED_SCROLLBARS | |
176 | |
177 static void | |
178 copy_scrollbar_values (widget_value *val, widget_value *copy) | |
179 { | |
180 if (!copy->scrollbar_data) | |
181 copy->scrollbar_data = | |
182 (scrollbar_values *) malloc (sizeof (scrollbar_values)); | |
183 | |
184 if (val->scrollbar_data) | |
185 *copy->scrollbar_data = *val->scrollbar_data; | |
186 else | |
438 | 187 memset (copy->scrollbar_data, '\0', sizeof (scrollbar_values)); |
428 | 188 } |
189 | |
190 /* | |
191 * Return true if old->scrollbar_data were not equivalent | |
3025 | 192 * to new_->scrollbar_data. |
428 | 193 */ |
194 static Boolean | |
1201 | 195 merge_scrollbar_values (widget_value *old, widget_value *new_) |
428 | 196 { |
197 Boolean changed = False; | |
198 | |
1201 | 199 if (new_->scrollbar_data && !old->scrollbar_data) |
428 | 200 { |
1201 | 201 copy_scrollbar_values (new_, old); |
428 | 202 changed = True; |
203 } | |
1201 | 204 else if (!new_->scrollbar_data && old->scrollbar_data) |
428 | 205 { |
206 free (old->scrollbar_data); | |
207 old->scrollbar_data = NULL; | |
208 } | |
1201 | 209 else if (new_->scrollbar_data && old->scrollbar_data) |
428 | 210 { |
211 scrollbar_values *old_sb = old->scrollbar_data; | |
1201 | 212 scrollbar_values *new_sb = new_->scrollbar_data; |
428 | 213 |
214 if ((old_sb->line_increment != new_sb->line_increment) || | |
215 (old_sb->page_increment != new_sb->page_increment) || | |
216 (old_sb->minimum != new_sb->minimum) || | |
217 (old_sb->maximum != new_sb->maximum) || | |
218 (old_sb->slider_size != new_sb->slider_size) || | |
219 (old_sb->slider_position != new_sb->slider_position) || | |
220 (old_sb->scrollbar_width != new_sb->scrollbar_width) || | |
221 (old_sb->scrollbar_height != new_sb->scrollbar_height) || | |
222 (old_sb->scrollbar_x != new_sb->scrollbar_x) || | |
223 (old_sb->scrollbar_y != new_sb->scrollbar_y)) | |
224 changed = True; | |
225 | |
226 *old_sb = *new_sb; | |
227 } | |
228 | |
229 return changed; | |
230 } | |
231 | |
232 #endif /* NEED_SCROLLBARS */ | |
233 | |
771 | 234 #ifdef HAVE_X_WIDGETS |
434 | 235 /* |
236 * Return true if old->args was not equivalent | |
3025 | 237 * to new_->args. |
434 | 238 */ |
239 static Boolean | |
3025 | 240 merge_widget_value_args (widget_value *old, widget_value *new_) |
434 | 241 { |
242 Boolean changed = False; | |
243 | |
3025 | 244 if (new_->args && !old->args) |
434 | 245 { |
3025 | 246 lw_copy_widget_value_args (new_, old); |
434 | 247 changed = True; |
248 } | |
249 /* Generally we don't want to lose values that are already in the | |
250 widget. */ | |
3025 | 251 else if (!new_->args && old->args) |
434 | 252 { |
3025 | 253 lw_copy_widget_value_args (old, new_); |
434 | 254 changed = True; |
255 } | |
3025 | 256 else if (new_->args && old->args && new_->args != old->args) |
434 | 257 { |
258 /* #### Do something more sensible here than just copying the | |
259 new values (like actually merging the values). */ | |
3025 | 260 lw_copy_widget_value_args (new_, old); |
434 | 261 changed = True; |
262 } | |
3025 | 263 else if (new_->args && new_->args == old->args && new_->args->args_changed == True) |
450 | 264 { |
265 changed = True; | |
266 } | |
434 | 267 |
268 return changed; | |
269 } | |
771 | 270 #endif /* HAVE_X_WIDGETS */ |
434 | 271 |
428 | 272 /* Make a complete copy of a widget_value tree. Store CHANGE into |
273 the widget_value tree's `change' field. */ | |
274 | |
442 | 275 widget_value * |
428 | 276 copy_widget_value_tree (widget_value *val, change_type change) |
277 { | |
278 widget_value *copy; | |
279 | |
280 if (!val) | |
281 return NULL; | |
282 if (val == (widget_value *) 1) | |
283 return val; | |
284 | |
285 copy = malloc_widget_value (); | |
286 if (copy) | |
287 { | |
288 /* #### - don't seg fault *here* if out of memory. Menus will be | |
289 truncated inexplicably. */ | |
290 copy->type = val->type; | |
291 copy->name = safe_strdup (val->name); | |
292 copy->value = safe_strdup (val->value); | |
293 copy->key = safe_strdup (val->key); | |
294 copy->accel = val->accel; | |
295 copy->enabled = val->enabled; | |
296 copy->selected = val->selected; | |
297 copy->edited = False; | |
298 copy->change = change; | |
299 copy->contents = copy_widget_value_tree (val->contents, change); | |
300 copy->call_data = val->call_data; | |
301 copy->next = copy_widget_value_tree (val->next, change); | |
302 copy->toolkit_data = NULL; | |
303 copy->free_toolkit_data = False; | |
434 | 304 |
305 lw_copy_widget_value_args (val, copy); | |
428 | 306 #ifdef NEED_SCROLLBARS |
307 copy_scrollbar_values (val, copy); | |
308 #endif | |
309 } | |
310 return copy; | |
311 } | |
312 | |
313 /* This function is used to implement incremental menu construction. */ | |
314 | |
315 widget_value * | |
316 replace_widget_value_tree (widget_value *node, widget_value *newtree) | |
317 { | |
318 widget_value *copy; | |
319 | |
320 if (!node || !newtree) | |
321 abort (); | |
322 | |
323 copy = copy_widget_value_tree (newtree, STRUCTURAL_CHANGE); | |
324 | |
325 free_widget_value_contents (node); | |
326 *node = *copy; | |
327 free_widget_value (copy); /* free the node, but not its contents. */ | |
328 return node; | |
329 } | |
330 | |
331 static widget_info * | |
442 | 332 allocate_widget_info (const char *type, const char *name, |
428 | 333 LWLIB_ID id, widget_value *val, |
334 lw_callback pre_activate_cb, lw_callback selection_cb, | |
335 lw_callback post_activate_cb) | |
336 { | |
337 widget_info *info = (widget_info *) malloc (sizeof (widget_info)); | |
338 info->type = safe_strdup (type); | |
339 info->name = safe_strdup (name); | |
340 info->id = id; | |
341 info->val = copy_widget_value_tree (val, STRUCTURAL_CHANGE); | |
342 info->busy = False; | |
343 info->pre_activate_cb = pre_activate_cb; | |
344 info->selection_cb = selection_cb; | |
345 info->post_activate_cb = post_activate_cb; | |
346 info->instances = NULL; | |
347 | |
348 info->next = all_widget_info; | |
349 all_widget_info = info; | |
350 | |
351 return info; | |
352 } | |
353 | |
354 static void | |
355 free_widget_info (widget_info *info) | |
356 { | |
357 safe_free_str (info->type); | |
358 safe_free_str (info->name); | |
359 free_widget_value_tree (info->val); | |
438 | 360 memset (info, '\0', sizeof (widget_info)); |
428 | 361 free (info); |
362 } | |
363 | |
364 static void | |
2286 | 365 mark_widget_destroyed (Widget widget, XtPointer closure, |
366 XtPointer UNUSED (call_data)) | |
428 | 367 { |
368 widget_instance *instance = (widget_instance*)closure; | |
369 | |
370 /* be very conservative */ | |
371 if (instance->widget == widget) | |
372 instance->widget = NULL; | |
373 } | |
374 | |
375 static widget_instance * | |
376 allocate_widget_instance (widget_info *info, Widget parent, Boolean pop_up_p) | |
377 { | |
378 widget_instance *instance = | |
379 (widget_instance *) malloc (sizeof (widget_instance)); | |
380 instance->parent = parent; | |
381 instance->pop_up_p = pop_up_p; | |
382 instance->info = info; | |
383 instance->next = info->instances; | |
384 info->instances = instance; | |
385 | |
386 instantiate_widget_instance (instance); | |
387 | |
388 XtAddCallback (instance->widget, XtNdestroyCallback, | |
389 mark_widget_destroyed, (XtPointer)instance); | |
390 return instance; | |
391 } | |
392 | |
393 static void | |
394 free_widget_instance (widget_instance *instance) | |
395 { | |
438 | 396 memset (instance, '\0', sizeof (widget_instance)); |
428 | 397 free (instance); |
398 } | |
399 | |
400 static widget_info * | |
401 get_widget_info (LWLIB_ID id, Boolean remove_p) | |
402 { | |
403 widget_info *info; | |
404 widget_info *prev; | |
405 for (prev = NULL, info = all_widget_info; | |
406 info; | |
407 prev = info, info = info->next) | |
408 if (info->id == id) | |
409 { | |
410 if (remove_p) | |
411 { | |
412 if (prev) | |
413 prev->next = info->next; | |
414 else | |
415 all_widget_info = info->next; | |
416 } | |
417 return info; | |
418 } | |
419 return NULL; | |
420 } | |
421 | |
422 /* Internal function used by the library dependent implementation to get the | |
423 widget_value for a given widget in an instance */ | |
424 widget_info * | |
425 lw_get_widget_info (LWLIB_ID id) | |
426 { | |
427 return get_widget_info (id, 0); | |
428 } | |
429 | |
430 static int | |
431 map_widget_values (widget_value *value, int (*mapfunc) (widget_value *value, | |
432 void *closure), | |
433 void *closure) | |
434 { | |
435 int retval = 0; | |
436 | |
437 if (value->contents) | |
438 retval = map_widget_values (value->contents, mapfunc, closure); | |
439 if (retval) | |
440 return retval; | |
441 | |
442 if (value->next) | |
443 retval = map_widget_values (value->next, mapfunc, closure); | |
444 if (retval) | |
445 return retval; | |
446 | |
447 return (mapfunc) (value, closure); | |
448 } | |
449 | |
450 int | |
451 lw_map_widget_values (LWLIB_ID id, int (*mapfunc) (widget_value *value, | |
452 void *closure), | |
453 void *closure) | |
454 { | |
455 widget_info *info = get_widget_info (id, 0); | |
456 | |
457 if (!info) | |
458 abort (); | |
459 | |
460 if (info->val) | |
461 return map_widget_values (info->val, mapfunc, closure); | |
462 return 0; | |
463 } | |
464 | |
465 static widget_instance * | |
466 get_widget_instance (Widget widget, Boolean remove_p) | |
467 { | |
468 widget_info *info; | |
469 widget_instance *instance; | |
470 widget_instance *prev; | |
471 for (info = all_widget_info; info; info = info->next) | |
472 for (prev = NULL, instance = info->instances; | |
473 instance; | |
474 prev = instance, instance = instance->next) | |
475 if (instance->widget == widget) | |
476 { | |
477 if (remove_p) | |
478 { | |
479 if (prev) | |
480 prev->next = instance->next; | |
481 else | |
482 info->instances = instance->next; | |
483 } | |
484 return instance; | |
485 } | |
486 return (widget_instance *) 0; | |
487 } | |
488 | |
489 static widget_instance* | |
490 find_instance (LWLIB_ID id, Widget parent, Boolean pop_up_p) | |
491 { | |
492 widget_info *info = get_widget_info (id, False); | |
493 widget_instance *instance; | |
494 | |
495 if (info) | |
496 for (instance = info->instances; instance; instance = instance->next) | |
497 if (instance->parent == parent && instance->pop_up_p == pop_up_p) | |
498 return instance; | |
499 | |
500 return NULL; | |
501 } | |
502 | |
503 | |
504 /* utility function for widget_value */ | |
505 static Boolean | |
442 | 506 safe_strcmp (const char *s1, const char *s2) |
428 | 507 { |
508 if (!!s1 ^ !!s2) return True; | |
509 return (s1 && s2) ? strcmp (s1, s2) : s1 ? False : !!s2; | |
510 } | |
511 | |
512 #if 0 | |
513 # define EXPLAIN(name, oc, nc, desc, a1, a2) \ | |
514 printf ("Change: \"%s\"\tmax(%s=%d,%s=%d)\t%s %d %d\n", \ | |
515 name, \ | |
516 (oc == NO_CHANGE ? "none" : \ | |
517 (oc == INVISIBLE_CHANGE ? "invisible" : \ | |
518 (oc == VISIBLE_CHANGE ? "visible" : \ | |
519 (oc == STRUCTURAL_CHANGE ? "structural" : "???")))), \ | |
520 oc, \ | |
521 (nc == NO_CHANGE ? "none" : \ | |
522 (nc == INVISIBLE_CHANGE ? "invisible" : \ | |
523 (nc == VISIBLE_CHANGE ? "visible" : \ | |
524 (nc == STRUCTURAL_CHANGE ? "structural" : "???")))), \ | |
525 nc, desc, a1, a2) | |
526 #else | |
527 # define EXPLAIN(name, oc, nc, desc, a1, a2) | |
528 #endif | |
529 | |
530 | |
531 static widget_value * | |
532 merge_widget_value (widget_value *val1, widget_value *val2, int level) | |
533 { | |
534 change_type change; | |
535 widget_value *merged_next; | |
536 widget_value *merged_contents; | |
537 | |
538 if (!val1) | |
539 { | |
540 if (val2) | |
541 return copy_widget_value_tree (val2, STRUCTURAL_CHANGE); | |
542 else | |
543 return NULL; | |
544 } | |
545 if (!val2) | |
546 { | |
547 free_widget_value_tree (val1); | |
548 return NULL; | |
549 } | |
550 | |
551 change = NO_CHANGE; | |
552 | |
553 if (val1->type != val2->type) | |
554 { | |
555 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "type change", | |
556 val1->type, val2->type); | |
557 change = max (change, STRUCTURAL_CHANGE); | |
558 val1->type = val2->type; | |
559 } | |
560 if (safe_strcmp (val1->name, val2->name)) | |
561 { | |
562 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "name change", | |
563 val1->name, val2->name); | |
564 change = max (change, STRUCTURAL_CHANGE); | |
565 safe_free_str (val1->name); | |
566 val1->name = safe_strdup (val2->name); | |
567 } | |
568 if (safe_strcmp (val1->value, val2->value)) | |
569 { | |
570 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "value change", | |
571 val1->value, val2->value); | |
572 change = max (change, VISIBLE_CHANGE); | |
573 safe_free_str (val1->value); | |
574 val1->value = safe_strdup (val2->value); | |
575 } | |
576 if (safe_strcmp (val1->key, val2->key)) | |
577 { | |
578 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "key change", | |
579 val1->key, val2->key); | |
580 change = max (change, VISIBLE_CHANGE); | |
581 safe_free_str (val1->key); | |
582 val1->key = safe_strdup (val2->key); | |
583 } | |
584 if (val1->accel != val2->accel) | |
585 { | |
586 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "accelerator change", | |
587 val1->accel, val2->accel); | |
588 change = max (change, VISIBLE_CHANGE); | |
589 val1->accel = val2->accel; | |
590 } | |
591 if (val1->enabled != val2->enabled) | |
592 { | |
593 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "enablement change", | |
594 val1->enabled, val2->enabled); | |
595 change = max (change, VISIBLE_CHANGE); | |
596 val1->enabled = val2->enabled; | |
597 } | |
598 if (val1->selected != val2->selected) | |
599 { | |
600 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "selection change", | |
601 val1->selected, val2->selected); | |
602 change = max (change, VISIBLE_CHANGE); | |
603 val1->selected = val2->selected; | |
604 } | |
605 if (val1->call_data != val2->call_data) | |
606 { | |
607 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "call-data change", | |
608 val1->call_data, val2->call_data); | |
609 change = max (change, INVISIBLE_CHANGE); | |
610 val1->call_data = val2->call_data; | |
611 } | |
771 | 612 #ifdef HAVE_X_WIDGETS |
434 | 613 if (merge_widget_value_args (val1, val2)) |
614 { | |
615 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "widget change", 0, 0); | |
616 change = max (change, VISIBLE_CHANGE); | |
617 } | |
618 #endif | |
619 | |
428 | 620 #ifdef NEED_SCROLLBARS |
621 if (merge_scrollbar_values (val1, val2)) | |
622 { | |
623 EXPLAIN (val1->name, change, VISIBLE_CHANGE, "scrollbar change", 0, 0); | |
624 change = max (change, VISIBLE_CHANGE); | |
625 } | |
626 #endif | |
627 | |
628 if (level > 0) | |
629 { | |
630 merged_contents = | |
631 merge_widget_value (val1->contents, val2->contents, level - 1); | |
632 | |
633 if (val1->contents && !merged_contents) | |
634 { | |
635 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents gone)", | |
636 0, 0); | |
637 change = max (change, INVISIBLE_CHANGE); | |
638 } | |
639 else if (merged_contents && merged_contents->change != NO_CHANGE) | |
640 { | |
641 EXPLAIN (val1->name, change, INVISIBLE_CHANGE, "(contents change)", | |
642 0, 0); | |
643 change = max (change, INVISIBLE_CHANGE); | |
644 } | |
645 | |
646 val1->contents = merged_contents; | |
647 } | |
648 | |
649 merged_next = merge_widget_value (val1->next, val2->next, level); | |
650 | |
651 if (val1->next && !merged_next) | |
652 { | |
653 EXPLAIN (val1->name, change, STRUCTURAL_CHANGE, "(following gone)", | |
654 0, 0); | |
655 change = max (change, STRUCTURAL_CHANGE); | |
656 } | |
657 else if (merged_next) | |
658 { | |
659 if (merged_next->change) | |
660 { | |
661 EXPLAIN (val1->name, change, merged_next->change, "(following change)", | |
662 0, 0); | |
2286 | 663 change = max (change, merged_next->change); |
428 | 664 } |
665 } | |
666 | |
667 val1->next = merged_next; | |
668 | |
669 val1->change = change; | |
670 | |
671 if (change > NO_CHANGE && val1->toolkit_data) | |
672 { | |
673 if (val1->free_toolkit_data) | |
674 XtFree ((char *) val1->toolkit_data); | |
675 val1->toolkit_data = NULL; | |
676 } | |
677 | |
678 return val1; | |
679 } | |
680 | |
681 | |
682 /* modifying the widgets */ | |
683 static Widget | |
442 | 684 name_to_widget (widget_instance *instance, const char *name) |
428 | 685 { |
686 Widget widget = NULL; | |
687 | |
688 if (!instance->widget) | |
689 return NULL; | |
690 | |
691 if (!strcmp (XtName (instance->widget), name)) | |
692 widget = instance->widget; | |
693 else | |
694 { | |
695 int length = strlen (name) + 2; | |
696 char *real_name = (char *) alloca (length); | |
697 real_name [0] = '*'; | |
698 strcpy (real_name + 1, name); | |
699 | |
700 widget = XtNameToWidget (instance->widget, real_name); | |
701 } | |
702 return widget; | |
703 } | |
704 | |
705 static void | |
706 set_one_value (widget_instance *instance, widget_value *val, Boolean deep_p) | |
707 { | |
708 Widget widget = name_to_widget (instance, val->name); | |
709 | |
710 if (widget) | |
711 { | |
712 #ifdef NEED_LUCID | |
713 if (lw_lucid_widget_p (instance->widget)) | |
714 xlw_update_one_widget (instance, widget, val, deep_p); | |
715 #endif | |
716 #ifdef NEED_MOTIF | |
717 if (lw_motif_widget_p (instance->widget)) | |
718 xm_update_one_widget (instance, widget, val, deep_p); | |
719 #endif | |
720 #ifdef NEED_ATHENA | |
721 if (lw_xaw_widget_p (instance->widget)) | |
722 xaw_update_one_widget (instance, widget, val, deep_p); | |
723 #endif | |
724 } | |
725 } | |
726 | |
727 static void | |
728 update_one_widget_instance (widget_instance *instance, Boolean deep_p) | |
729 { | |
730 widget_value *val; | |
731 | |
732 if (!instance->widget) | |
733 /* the widget was destroyed */ | |
734 return; | |
735 | |
736 for (val = instance->info->val; val; val = val->next) | |
737 if (val->change != NO_CHANGE) | |
738 set_one_value (instance, val, deep_p); | |
739 } | |
740 | |
741 static void | |
742 update_all_widget_values (widget_info *info, Boolean deep_p) | |
743 { | |
744 widget_instance *instance; | |
745 widget_value *val; | |
746 | |
747 for (instance = info->instances; instance; instance = instance->next) | |
748 update_one_widget_instance (instance, deep_p); | |
749 | |
750 for (val = info->val; val; val = val->next) | |
450 | 751 { |
752 val->change = NO_CHANGE; | |
753 if (val->args) | |
754 val->args->args_changed = False; | |
755 } | |
428 | 756 } |
757 | |
758 void | |
759 lw_modify_all_widgets (LWLIB_ID id, widget_value *val, Boolean deep_p) | |
760 { | |
761 widget_info *info = get_widget_info (id, False); | |
762 widget_value *new_val; | |
763 widget_value *next_new_val; | |
764 widget_value *cur; | |
765 widget_value *prev; | |
766 widget_value *next; | |
767 int found; | |
768 | |
769 if (!info) | |
770 return; | |
771 | |
772 for (new_val = val; new_val; new_val = new_val->next) | |
773 { | |
774 next_new_val = new_val->next; | |
775 new_val->next = NULL; | |
776 found = False; | |
777 for (prev = NULL, cur = info->val; cur; prev = cur, cur = cur->next) | |
778 if (!strcmp (cur->name, new_val->name)) | |
779 { | |
780 found = True; | |
781 next = cur->next; | |
782 cur->next = NULL; | |
783 cur = merge_widget_value (cur, new_val, deep_p ? 1000 : 1); | |
784 if (prev) | |
785 prev->next = cur ? cur : next; | |
786 else | |
787 info->val = cur ? cur : next; | |
788 if (cur) | |
789 cur->next = next; | |
790 break; | |
791 } | |
792 if (!found) | |
793 { | |
794 /* Could not find it, add it */ | |
795 if (prev) | |
796 prev->next = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE); | |
797 else | |
798 info->val = copy_widget_value_tree (new_val, STRUCTURAL_CHANGE); | |
799 } | |
800 new_val->next = next_new_val; | |
801 } | |
802 | |
803 update_all_widget_values (info, deep_p); | |
804 } | |
805 | |
806 | |
807 /* creating the widgets */ | |
808 | |
809 static void | |
810 initialize_widget_instance (widget_instance *instance) | |
811 { | |
812 widget_value *val; | |
813 | |
814 for (val = instance->info->val; val; val = val->next) | |
815 val->change = STRUCTURAL_CHANGE; | |
816 | |
817 update_one_widget_instance (instance, True); | |
818 | |
819 for (val = instance->info->val; val; val = val->next) | |
450 | 820 { |
821 val->change = NO_CHANGE; | |
822 if (val->args) | |
823 val->args->args_changed = False; | |
824 } | |
428 | 825 } |
826 | |
1201 | 827 #if defined (NEED_LUCID) || defined (NEED_ATHENA) || defined (NEED_MOTIF) |
828 | |
442 | 829 /* strcasecmp() is not sufficiently portable or standard, |
830 and it's easier just to write our own. */ | |
831 static int | |
832 ascii_strcasecmp (const char *s1, const char *s2) | |
833 { | |
834 while (1) | |
835 { | |
836 char c1 = *s1++; | |
837 char c2 = *s2++; | |
838 if (c1 >= 'A' && c1 <= 'Z') c1 += 'a' - 'A'; | |
839 if (c2 >= 'A' && c2 <= 'Z') c2 += 'a' - 'A'; | |
840 if (c1 != c2) return c1 - c2; | |
841 if (c1 == '\0') return 0; | |
842 } | |
843 } | |
428 | 844 |
845 static widget_creation_function | |
450 | 846 find_in_table (const char *type, const widget_creation_entry table[]) |
428 | 847 { |
450 | 848 const widget_creation_entry *cur; |
428 | 849 for (cur = table; cur->type; cur++) |
442 | 850 if (!ascii_strcasecmp (type, cur->type)) |
428 | 851 return cur->function; |
852 return NULL; | |
853 } | |
854 | |
872 | 855 #endif |
856 | |
428 | 857 static Boolean |
442 | 858 dialog_spec_p (const char *name) |
428 | 859 { |
860 /* return True if name matches [EILPQeilpq][1-9][Bb] or | |
861 [EILPQeilpq][1-9][Bb][Rr][1-9] */ | |
862 if (!name) | |
863 return False; | |
864 | |
865 switch (name [0]) | |
866 { | |
867 case 'E': case 'I': case 'L': case 'P': case 'Q': | |
868 case 'e': case 'i': case 'l': case 'p': case 'q': | |
869 if (name [1] >= '0' && name [1] <= '9') | |
870 { | |
871 if (name [2] != 'B' && name [2] != 'b') | |
872 return False; | |
873 if (!name [3]) | |
874 return True; | |
875 if ((name [3] == 'T' || name [3] == 't') && !name [4]) | |
876 return True; | |
877 if ((name [3] == 'R' || name [3] == 'r') | |
878 && name [4] >= '0' && name [4] <= '9' && !name [5]) | |
879 return True; | |
880 return False; | |
881 } | |
882 else | |
883 return False; | |
884 | |
885 default: | |
886 return False; | |
887 } | |
888 } | |
889 | |
890 static void | |
891 instantiate_widget_instance (widget_instance *instance) | |
892 { | |
893 widget_creation_function function = NULL; | |
894 | |
895 #ifdef NEED_LUCID | |
896 if (!function) | |
897 function = find_in_table (instance->info->type, xlw_creation_table); | |
898 #endif | |
899 #ifdef NEED_MOTIF | |
900 if (!function) | |
901 function = find_in_table (instance->info->type, xm_creation_table); | |
902 #endif | |
903 #ifdef NEED_ATHENA | |
904 if (!function) | |
905 function = find_in_table (instance->info->type, xaw_creation_table); | |
906 #endif | |
907 | |
908 if (!function) | |
909 { | |
910 if (dialog_spec_p (instance->info->type)) | |
911 { | |
912 #ifdef LWLIB_DIALOGS_MOTIF | |
913 if (!function) | |
914 function = xm_create_dialog; | |
915 #endif | |
916 #ifdef LWLIB_DIALOGS_ATHENA | |
917 if (!function) | |
918 function = xaw_create_dialog; | |
919 #endif | |
920 #ifdef LWLIB_DIALOGS_LUCID | |
921 /* not yet (not ever?) */ | |
922 #endif | |
923 } | |
924 } | |
925 | |
926 if (!function) | |
927 { | |
928 fprintf (stderr, "No creation function for widget type %s\n", | |
929 instance->info->type); | |
930 abort (); | |
931 } | |
932 | |
933 instance->widget = (*function) (instance); | |
934 | |
935 if (!instance->widget) | |
936 abort (); | |
937 | |
938 /* XtRealizeWidget (instance->widget);*/ | |
939 } | |
940 | |
941 void | |
442 | 942 lw_register_widget (const char *type, const char *name, |
428 | 943 LWLIB_ID id, widget_value *val, |
944 lw_callback pre_activate_cb, lw_callback selection_cb, | |
945 lw_callback post_activate_cb) | |
946 { | |
947 if (!get_widget_info (id, False)) | |
948 allocate_widget_info (type, name, id, val, pre_activate_cb, selection_cb, | |
949 post_activate_cb); | |
950 } | |
951 | |
952 Widget | |
953 lw_get_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p) | |
954 { | |
955 widget_instance *instance = find_instance (id, parent, pop_up_p); | |
956 return instance ? instance->widget : NULL; | |
957 } | |
958 | |
959 Widget | |
960 lw_make_widget (LWLIB_ID id, Widget parent, Boolean pop_up_p) | |
961 { | |
962 widget_instance *instance = find_instance (id, parent, pop_up_p); | |
963 | |
964 if (!instance) | |
965 { | |
966 widget_info *info = get_widget_info (id, False); | |
967 if (!info) | |
968 return NULL; | |
969 instance = allocate_widget_instance (info, parent, pop_up_p); | |
970 initialize_widget_instance (instance); | |
971 } | |
972 if (!instance->widget) | |
973 abort (); | |
974 return instance->widget; | |
975 } | |
976 | |
977 Widget | |
442 | 978 lw_create_widget (const char *type, const char *name, |
428 | 979 LWLIB_ID id, widget_value *val, |
980 Widget parent, Boolean pop_up_p, lw_callback pre_activate_cb, | |
981 lw_callback selection_cb, lw_callback post_activate_cb) | |
982 { | |
983 lw_register_widget (type, name, id, val, pre_activate_cb, selection_cb, | |
984 post_activate_cb); | |
985 return lw_make_widget (id, parent, pop_up_p); | |
986 } | |
987 | |
988 | |
989 /* destroying the widgets */ | |
990 static void | |
991 destroy_one_instance (widget_instance *instance) | |
992 { | |
993 /* Remove the destroy callback on the widget; that callback will try to | |
994 dereference the instance object (to set its widget slot to 0, since the | |
995 widget is dead.) Since the instance is now dead, we don't have to worry | |
996 about the fact that its widget is dead too. | |
997 | |
998 This happens in the Phase2Destroy of the widget, so this callback would | |
999 not have been run until arbitrarily long after the instance was freed. | |
1000 */ | |
1001 if (instance->widget) | |
1002 XtRemoveCallback (instance->widget, XtNdestroyCallback, | |
1003 mark_widget_destroyed, (XtPointer)instance); | |
1004 | |
1005 if (instance->widget) | |
1006 { | |
1007 /* The else are pretty tricky here, including the empty statement | |
1008 at the end because it would be very bad to destroy a widget | |
1009 twice. */ | |
1010 #ifdef NEED_LUCID | |
1011 if (lw_lucid_widget_p (instance->widget)) | |
1012 xlw_destroy_instance (instance); | |
1013 else | |
1014 #endif | |
1015 #ifdef NEED_MOTIF | |
1016 if (lw_motif_widget_p (instance->widget)) | |
1017 xm_destroy_instance (instance); | |
1018 else | |
1019 #endif | |
1020 #ifdef NEED_ATHENA | |
1021 if (lw_xaw_widget_p (instance->widget)) | |
1022 xaw_destroy_instance (instance); | |
1023 else | |
1024 #endif | |
1025 { | |
1026 /* do not remove the empty statement */ | |
1027 ; | |
1028 } | |
1029 } | |
1030 | |
1031 free_widget_instance (instance); | |
1032 } | |
1033 | |
1034 void | |
1035 lw_destroy_widget (Widget w) | |
1036 { | |
1037 widget_instance *instance = get_widget_instance (w, True); | |
1038 | |
1039 if (instance) | |
1040 { | |
1041 widget_info *info = instance->info; | |
1042 /* instance has already been removed from the list; free it */ | |
1043 destroy_one_instance (instance); | |
1044 /* if there are no instances left, free the info too */ | |
1045 if (!info->instances) | |
1046 lw_destroy_all_widgets (info->id); | |
1047 } | |
1048 } | |
1049 | |
1050 void | |
1051 lw_destroy_all_widgets (LWLIB_ID id) | |
1052 { | |
1053 widget_info *info = get_widget_info (id, True); | |
1054 widget_instance *instance; | |
1055 widget_instance *next; | |
1056 | |
1057 if (info) | |
1058 { | |
1059 for (instance = info->instances; instance; ) | |
1060 { | |
1061 next = instance->next; | |
1062 destroy_one_instance (instance); | |
1063 instance = next; | |
1064 } | |
1065 free_widget_info (info); | |
1066 } | |
1067 } | |
1068 | |
1069 void | |
442 | 1070 lw_destroy_everything (void) |
428 | 1071 { |
1072 while (all_widget_info) | |
1073 lw_destroy_all_widgets (all_widget_info->id); | |
1074 } | |
1075 | |
1076 void | |
442 | 1077 lw_destroy_all_pop_ups (void) |
428 | 1078 { |
1079 widget_info *info; | |
1080 widget_info *next; | |
1081 widget_instance *instance; | |
1082 | |
1083 for (info = all_widget_info; info; info = next) | |
1084 { | |
1085 next = info->next; | |
1086 instance = info->instances; | |
1087 if (instance && instance->pop_up_p) | |
1088 lw_destroy_all_widgets (info->id); | |
1089 } | |
1090 } | |
1091 | |
1092 Widget | |
1093 lw_raise_all_pop_up_widgets (void) | |
1094 { | |
1095 widget_info *info; | |
1096 widget_instance *instance; | |
1097 Widget result = NULL; | |
1098 | |
1099 for (info = all_widget_info; info; info = info->next) | |
1100 for (instance = info->instances; instance; instance = instance->next) | |
1101 if (instance->pop_up_p) | |
1102 { | |
1103 Widget widget = instance->widget; | |
1104 if (widget) | |
1105 { | |
1106 if (XtIsManaged (widget) | |
1107 #ifdef NEED_MOTIF | |
1108 /* What a complete load of crap!!!! | |
1109 When a dialogShell is on the screen, it is not managed! | |
1110 */ | |
1111 || (lw_motif_widget_p (instance->widget) && | |
1112 XtIsManaged (first_child (widget))) | |
1113 #endif | |
1114 ) | |
1115 { | |
1116 if (!result) | |
1117 result = widget; | |
1118 XMapRaised (XtDisplay (widget), XtWindow (widget)); | |
1119 } | |
1120 } | |
1121 } | |
1122 return result; | |
1123 } | |
1124 | |
1125 static void | |
1126 lw_pop_all_widgets (LWLIB_ID id, Boolean up) | |
1127 { | |
1128 widget_info *info = get_widget_info (id, False); | |
1129 widget_instance *instance; | |
1130 | |
1131 if (info) | |
1132 for (instance = info->instances; instance; instance = instance->next) | |
1133 if (instance->pop_up_p && instance->widget) | |
1134 { | |
1135 #ifdef NEED_LUCID | |
1136 if (lw_lucid_widget_p (instance->widget)) | |
1137 { | |
1138 XtRealizeWidget (instance->widget); | |
1139 xlw_pop_instance (instance, up); | |
1140 } | |
1141 #endif | |
1142 #ifdef NEED_MOTIF | |
1143 if (lw_motif_widget_p (instance->widget)) | |
1144 { | |
1145 XtRealizeWidget (instance->widget); | |
1146 xm_pop_instance (instance, up); | |
1147 } | |
1148 #endif | |
1149 #ifdef NEED_ATHENA | |
1150 if (lw_xaw_widget_p (instance->widget)) | |
1151 { | |
1152 XtRealizeWidget (XtParent (instance->widget)); | |
1153 XtRealizeWidget (instance->widget); | |
1154 xaw_pop_instance (instance, up); | |
1155 } | |
1156 #endif | |
1157 } | |
1158 } | |
1159 | |
1160 void | |
1161 lw_pop_up_all_widgets (LWLIB_ID id) | |
1162 { | |
1163 lw_pop_all_widgets (id, True); | |
1164 } | |
1165 | |
1166 void | |
1167 lw_pop_down_all_widgets (LWLIB_ID id) | |
1168 { | |
1169 lw_pop_all_widgets (id, False); | |
1170 } | |
1171 | |
1172 void | |
1173 lw_popup_menu (Widget widget, XEvent *event) | |
1174 { | |
1175 #ifdef LWLIB_MENUBARS_LUCID | |
1176 if (lw_lucid_widget_p (widget)) | |
1177 xlw_popup_menu (widget, event); | |
1178 #endif | |
1179 #ifdef LWLIB_MENUBARS_MOTIF | |
1180 if (lw_motif_widget_p (widget)) | |
1181 xm_popup_menu (widget, event); | |
1182 #endif | |
1183 #ifdef LWLIB_MENUBARS_ATHENA | |
1184 if (lw_xaw_widget_p (widget)) | |
1185 xaw_popup_menu (widget, event); /* not implemented */ | |
1186 #endif | |
1187 } | |
1188 | |
1189 /* get the values back */ | |
1190 static Boolean | |
1191 get_one_value (widget_instance *instance, widget_value *val) | |
1192 { | |
1193 Widget widget = name_to_widget (instance, val->name); | |
1194 | |
1195 if (widget) | |
1196 { | |
1197 #ifdef NEED_LUCID | |
1198 if (lw_lucid_widget_p (instance->widget)) | |
1199 xlw_update_one_value (instance, widget, val); | |
1200 #endif | |
1201 #ifdef NEED_MOTIF | |
1202 if (lw_motif_widget_p (instance->widget)) | |
1203 xm_update_one_value (instance, widget, val); | |
1204 #endif | |
1205 #ifdef NEED_ATHENA | |
1206 if (lw_xaw_widget_p (instance->widget)) | |
1207 xaw_update_one_value (instance, widget, val); | |
1208 #endif | |
1209 return True; | |
1210 } | |
1211 else | |
1212 return False; | |
1213 } | |
1214 | |
1215 Boolean | |
1216 lw_get_some_values (LWLIB_ID id, widget_value *val_out) | |
1217 { | |
1218 widget_info *info = get_widget_info (id, False); | |
1219 widget_instance *instance; | |
1220 widget_value *val; | |
1221 Boolean result = False; | |
1222 | |
1223 if (!info) | |
1224 return False; | |
1225 | |
1226 instance = info->instances; | |
1227 if (!instance) | |
1228 return False; | |
1229 | |
1230 for (val = val_out; val; val = val->next) | |
1231 if (get_one_value (instance, val)) | |
1232 result = True; | |
1233 | |
1234 return result; | |
1235 } | |
1236 | |
1237 widget_value* | |
1238 lw_get_all_values (LWLIB_ID id) | |
1239 { | |
1240 widget_info *info = get_widget_info (id, False); | |
1241 widget_value *val = info->val; | |
1242 if (lw_get_some_values (id, val)) | |
1243 return val; | |
1244 else | |
1245 return NULL; | |
1246 } | |
1247 | |
1248 /* internal function used by the library dependent implementation to get the | |
1249 widget_value for a given widget in an instance */ | |
1250 widget_value* | |
1251 lw_get_widget_value_for_widget (widget_instance *instance, Widget w) | |
1252 { | |
1253 char *name = XtName (w); | |
1254 widget_value *cur; | |
1255 for (cur = instance->info->val; cur; cur = cur->next) | |
1256 if (!strcmp (cur->name, name)) | |
1257 return cur; | |
1258 return NULL; | |
1259 } | |
1260 | |
1261 | |
1262 /* update other instances value when one thing changed */ | |
1263 /* This function can be used as a an XtCallback for the widgets that get | |
1264 modified to update other instances of the widgets. Closure should be the | |
1265 widget_instance. */ | |
1266 void | |
1267 lw_internal_update_other_instances (Widget widget, XtPointer closure, | |
2286 | 1268 XtPointer UNUSED (call_data)) |
428 | 1269 { |
1270 /* To forbid recursive calls */ | |
1271 static Boolean updating; | |
1272 | |
1273 widget_instance *instance = (widget_instance*)closure; | |
1274 char *name = XtName (widget); | |
1275 widget_info *info; | |
1276 widget_instance *cur; | |
1277 widget_value *val; | |
1278 | |
1279 /* never recurse as this could cause infinite recursions. */ | |
1280 if (updating) | |
1281 return; | |
1282 | |
1283 /* protect against the widget being destroyed */ | |
1284 if (XtWidgetBeingDestroyedP (widget)) | |
1285 return; | |
1286 | |
1287 /* Return immediately if there are no other instances */ | |
1288 info = instance->info; | |
1289 if (!info->instances->next) | |
1290 return; | |
1291 | |
1292 updating = True; | |
1293 | |
1294 for (val = info->val; val && strcmp (val->name, name); val = val->next); | |
1295 | |
1296 if (val && get_one_value (instance, val)) | |
1297 for (cur = info->instances; cur; cur = cur->next) | |
1298 if (cur != instance) | |
1299 set_one_value (cur, val, True); | |
1300 | |
1301 updating = False; | |
1302 } | |
1303 | |
1304 | |
1305 | |
1306 /* get the id */ | |
1307 | |
1308 LWLIB_ID | |
1309 lw_get_widget_id (Widget w) | |
1310 { | |
1311 widget_instance *instance = get_widget_instance (w, False); | |
1312 | |
1313 return instance ? instance->info->id : 0; | |
1314 } | |
1315 | |
1316 | |
1317 /* set the keyboard focus */ | |
1318 void | |
1319 lw_set_keyboard_focus (Widget parent, Widget w) | |
1320 { | |
1321 #if defined(NEED_MOTIF) && !defined(LESSTIF_VERSION) | |
1322 /* This loses with Lesstif v0.75a */ | |
1323 xm_set_keyboard_focus (parent, w); | |
1324 #else | |
1325 XtSetKeyboardFocus (parent, w); | |
1326 #endif | |
1327 } | |
1328 | |
1329 | |
1330 /* Show busy */ | |
1331 static void | |
2286 | 1332 show_one_widget_busy (Widget w, Boolean UNUSED (flag)) |
428 | 1333 { |
1334 Pixel foreground = 0; | |
1335 Pixel background = 1; | |
1336 Widget widget_to_invert = XtNameToWidget (w, "*sheet"); | |
1337 Arg al [2]; | |
1338 | |
1339 if (!widget_to_invert) | |
1340 widget_to_invert = w; | |
1341 | |
1342 XtSetArg (al [0], XtNforeground, &foreground); | |
1343 XtSetArg (al [1], XtNbackground, &background); | |
1344 XtGetValues (widget_to_invert, al, 2); | |
1345 | |
1346 XtSetArg (al [0], XtNforeground, background); | |
1347 XtSetArg (al [1], XtNbackground, foreground); | |
1348 XtSetValues (widget_to_invert, al, 2); | |
1349 } | |
1350 | |
1351 void | |
1352 lw_show_busy (Widget w, Boolean busy) | |
1353 { | |
1354 widget_instance *instance = get_widget_instance (w, False); | |
1355 widget_info *info; | |
1356 widget_instance *next; | |
1357 | |
1358 if (instance) | |
1359 { | |
1360 info = instance->info; | |
1361 if (info->busy != busy) | |
1362 { | |
1363 for (next = info->instances; next; next = next->next) | |
1364 if (next->widget) | |
1365 show_one_widget_busy (next->widget, busy); | |
1366 info->busy = busy; | |
1367 } | |
1368 } | |
1369 } | |
1370 | |
1371 void lw_add_value_args_to_args (widget_value* wv, ArgList addto, int* offset) | |
1372 { | |
1373 int i; | |
434 | 1374 if (wv->args && wv->args->nargs) |
428 | 1375 { |
434 | 1376 for (i = 0; i<wv->args->nargs; i++) |
428 | 1377 { |
434 | 1378 addto[i + *offset] = wv->args->args[i]; |
428 | 1379 } |
434 | 1380 *offset += wv->args->nargs; |
428 | 1381 } |
1382 } | |
1383 | |
4528
726060ee587c
First draft of g++ 4.3 warning removal patch. Builds. *Needs ChangeLogs.*
Stephen J. Turnbull <stephen@xemacs.org>
parents:
4522
diff
changeset
|
1384 XtArgVal lw_get_value_arg (widget_value* wv, const String name) |
639 | 1385 { |
1386 int i; | |
1387 if (wv->args) | |
1388 { | |
1389 for (i = 0; i < wv->args->nargs; i++) | |
1390 { | |
1391 if (!strcmp (wv->args->args[i].name, name)) | |
1392 { | |
1393 return wv->args->args[i].value; | |
1394 } | |
1395 } | |
1396 } | |
1397 return (XtArgVal)0; | |
1398 } | |
1399 | |
434 | 1400 void lw_add_widget_value_arg (widget_value* wv, String name, XtArgVal value) |
1401 { | |
442 | 1402 int i = 0; |
434 | 1403 if (!wv->args) |
1404 { | |
1405 wv->args = (widget_args *) malloc (sizeof (widget_args)); | |
438 | 1406 memset (wv->args, '\0', sizeof (widget_args)); |
434 | 1407 wv->args->ref_count = 1; |
1408 wv->args->nargs = 0; | |
1409 wv->args->args = (ArgList) malloc (sizeof (Arg) * 10); | |
438 | 1410 memset (wv->args->args, '\0', sizeof (Arg) * 10); |
434 | 1411 } |
1412 | |
1413 if (wv->args->nargs > 10) | |
1414 return; | |
1415 | |
450 | 1416 /* Register the change. */ |
1417 wv->args->args_changed = True; | |
442 | 1418 /* If the arg is already there then we must replace it. */ |
1419 for (i = 0; i < wv->args->nargs; i++) | |
1420 { | |
1421 if (!strcmp (wv->args->args[i].name, name)) | |
1422 { | |
1423 XtSetArg (wv->args->args [i], name, value); | |
1424 break; | |
1425 } | |
1426 } | |
1427 if (i >= wv->args->nargs) | |
1428 { | |
1429 XtSetArg (wv->args->args [wv->args->nargs], name, value); wv->args->nargs++; | |
1430 } | |
434 | 1431 } |
1432 | |
1433 static void free_widget_value_args (widget_value* wv) | |
1434 { | |
1435 if (wv->args) | |
1436 { | |
1437 if (--wv->args->ref_count <= 0) | |
1438 { | |
1439 #ifdef LWLIB_WIDGETS_MOTIF | |
1440 int i; | |
1441 for (i = 0; i < wv->args->nargs; i++) | |
1442 { | |
1443 if (!strcmp (wv->args->args[i].name, XmNfontList)) | |
1444 XmFontListFree ((XmFontList)wv->args->args[i].value); | |
1445 } | |
1446 #endif | |
1447 free (wv->args->args); | |
1448 free (wv->args); | |
442 | 1449 wv->args = 0; |
434 | 1450 } |
1451 } | |
1452 } | |
1453 | |
1454 void lw_copy_widget_value_args (widget_value* val, widget_value* copy) | |
1455 { | |
442 | 1456 if (val == copy || val->args == copy->args) |
1457 return; | |
1458 | |
1459 if (copy->args) | |
434 | 1460 { |
442 | 1461 free_widget_value_args (copy); |
434 | 1462 } |
442 | 1463 |
1464 if (val->args) | |
434 | 1465 { |
1466 copy->args = val->args; | |
1467 copy->args->ref_count++; | |
1468 } | |
1469 } | |
1470 | |
442 | 1471 /* Remove %_ and convert %% to %. We can do this in-place because we |
1472 are always shortening, never lengthening, the string. */ | |
1473 void | |
1474 lw_remove_accelerator_spec (char *val) | |
1475 { | |
1476 char *foo = val, *bar = val; | |
1477 | |
1478 while (*bar) | |
1479 { | |
1480 if (*bar == '%' && *(bar+1) == '_') | |
1481 bar += 2; | |
1482 else if (*bar == '%' && *(bar+1) == '%') | |
1483 { | |
1484 *foo++ = *bar++; | |
1485 bar++; | |
1486 } | |
1487 else | |
1488 *foo++ = *bar++; | |
1489 } | |
1490 *foo = '\0'; | |
1491 } |