Mercurial > hg > xemacs-beta
annotate src/gtk-xemacs.c @ 5750:66d2f63df75f
Correct some spelling and formatting in behavior.el.
Mentioned in tracker issue 826, the third thing mentioned there (the file
name at the bottom of the file) had already been fixed.
lisp/ChangeLog addition:
2013-08-05 Aidan Kehoe <kehoea@parhasard.net>
* behavior.el:
(override-behavior):
Correct some spelling and formatting here, thank you Steven
Mitchell in tracker issue 826.
author | Aidan Kehoe <kehoea@parhasard.net> |
---|---|
date | Mon, 05 Aug 2013 10:05:32 +0100 |
parents | 56144c8593a8 |
children |
rev | line source |
---|---|
462 | 1 /* gtk-xemacs.c |
2 ** | |
3 ** Description: A widget to encapsulate a XEmacs 'text widget' | |
4 ** | |
5 ** Created by: William M. Perry | |
6 ** Copyright (c) 2000 William M. Perry <wmperry@gnu.org> | |
5043 | 7 ** Copyright (C) 2010 Ben Wing. |
462 | 8 ** |
4709
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
9 ** This file is part of XEmacs. |
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
10 ** |
5405
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
5231
diff
changeset
|
11 ** XEmacs is free software: you can redistribute it and/or modify it |
4709
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
12 ** under the terms of the GNU General Public License as published by the |
5405
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
5231
diff
changeset
|
13 ** Free Software Foundation, either version 3 of the License, or (at your |
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
5231
diff
changeset
|
14 ** option) any later version. |
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
5231
diff
changeset
|
15 ** |
4709
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
16 ** XEmacs is distributed in the hope that it will be useful, but WITHOUT |
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
17 ** ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
18 ** FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
19 ** for more details. |
5405
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
5231
diff
changeset
|
20 ** |
4709
db7068430402
Add explicit GPL v2 or later notices to Bill Perry's code, where such notices
Jerry James <james@xemacs.org>
parents:
3087
diff
changeset
|
21 ** You should have received a copy of the GNU General Public License |
5405
2aa9cd456ae7
Move src/ to GPLv3.
Mike Sperber <sperber@deinprogramm.de>
parents:
5231
diff
changeset
|
22 ** along with XEmacs. If not, see <http://www.gnu.org/licenses/>. */ |
462 | 23 |
24 #include <config.h> | |
25 | |
26 #include "lisp.h" | |
4908
b3ce27ca7647
various fixes related to gtk, redisplay-xlike-inc.c
Ben Wing <ben@xemacs.org>
parents:
4709
diff
changeset
|
27 |
809 | 28 #include "device.h" |
4908
b3ce27ca7647
various fixes related to gtk, redisplay-xlike-inc.c
Ben Wing <ben@xemacs.org>
parents:
4709
diff
changeset
|
29 #include "faces.h" |
809 | 30 #include "glyphs.h" |
462 | 31 #include "window.h" |
4908
b3ce27ca7647
various fixes related to gtk, redisplay-xlike-inc.c
Ben Wing <ben@xemacs.org>
parents:
4709
diff
changeset
|
32 |
876 | 33 #include "frame-impl.h" |
34 #include "console-gtk-impl.h" | |
35 #include "device-impl.h" | |
4908
b3ce27ca7647
various fixes related to gtk, redisplay-xlike-inc.c
Ben Wing <ben@xemacs.org>
parents:
4709
diff
changeset
|
36 #include "gtk-xemacs.h" |
5176
8b2f75cecb89
rename objects* (.c, .h and .el files) to fontcolor*
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
37 #include "fontcolor-gtk.h" |
462 | 38 |
39 extern Lisp_Object Vmodeline_face; | |
40 extern Lisp_Object Vscrollbar_on_left_p; | |
41 | |
42 EXFUN (Fmake_image_instance, 4); | |
43 | |
44 static void gtk_xemacs_class_init (GtkXEmacsClass *klass); | |
45 static void gtk_xemacs_init (GtkXEmacs *xemacs); | |
46 static void gtk_xemacs_size_allocate (GtkWidget *widget, GtkAllocation *allocaction); | |
47 static void gtk_xemacs_draw (GtkWidget *widget, GdkRectangle *area); | |
48 static void gtk_xemacs_paint (GtkWidget *widget, GdkRectangle *area); | |
49 static void gtk_xemacs_size_request (GtkWidget *widget, GtkRequisition *requisition); | |
50 static void gtk_xemacs_realize (GtkWidget *widget); | |
51 static void gtk_xemacs_style_set (GtkWidget *widget, GtkStyle *previous_style); | |
52 static gint gtk_xemacs_expose (GtkWidget *widget, GdkEventExpose *event); | |
53 | |
54 guint | |
55 gtk_xemacs_get_type (void) | |
56 { | |
57 static guint xemacs_type = 0; | |
58 | |
59 if (!xemacs_type) | |
60 { | |
61 static const GtkTypeInfo xemacs_info = | |
62 { | |
63 "GtkXEmacs", | |
64 sizeof (GtkXEmacs), | |
65 sizeof (GtkXEmacsClass), | |
66 (GtkClassInitFunc) gtk_xemacs_class_init, | |
67 (GtkObjectInitFunc) gtk_xemacs_init, | |
68 /* reserved_1 */ NULL, | |
69 /* reserved_2 */ NULL, | |
70 (GtkClassInitFunc) NULL, | |
71 }; | |
72 | |
73 xemacs_type = gtk_type_unique (gtk_fixed_get_type (), &xemacs_info); | |
74 } | |
75 | |
76 return xemacs_type; | |
77 } | |
78 | |
79 static GtkWidgetClass *parent_class; | |
80 | |
81 static void | |
1204 | 82 gtk_xemacs_class_init (GtkXEmacsClass *class_) |
462 | 83 { |
84 GtkWidgetClass *widget_class; | |
85 | |
1204 | 86 widget_class = (GtkWidgetClass*) class_; |
462 | 87 parent_class = (GtkWidgetClass *) gtk_type_class (gtk_fixed_get_type ()); |
88 | |
89 widget_class->size_allocate = gtk_xemacs_size_allocate; | |
90 widget_class->size_request = gtk_xemacs_size_request; | |
91 widget_class->draw = gtk_xemacs_draw; | |
92 widget_class->expose_event = gtk_xemacs_expose; | |
93 widget_class->realize = gtk_xemacs_realize; | |
94 widget_class->button_press_event = emacs_gtk_button_event_handler; | |
95 widget_class->button_release_event = emacs_gtk_button_event_handler; | |
96 widget_class->key_press_event = emacs_gtk_key_event_handler; | |
97 widget_class->key_release_event = emacs_gtk_key_event_handler; | |
98 widget_class->motion_notify_event = emacs_gtk_motion_event_handler; | |
99 widget_class->style_set = gtk_xemacs_style_set; | |
100 } | |
101 | |
102 static void | |
103 gtk_xemacs_init (GtkXEmacs *xemacs) | |
104 { | |
105 GTK_WIDGET_SET_FLAGS (xemacs, GTK_CAN_FOCUS); | |
106 } | |
107 | |
108 GtkWidget* | |
109 gtk_xemacs_new (struct frame *f) | |
110 { | |
111 GtkXEmacs *xemacs; | |
112 | |
2054 | 113 xemacs = (GtkXEmacs*) gtk_type_new (gtk_xemacs_get_type ()); |
462 | 114 xemacs->f = f; |
115 | |
116 return GTK_WIDGET (xemacs); | |
117 } | |
118 | |
119 static void | |
120 __nuke_background_items (GtkWidget *widget) | |
121 { | |
122 /* This bit of voodoo is here to get around the annoying flicker | |
123 when GDK tries to futz with our background pixmap as well as | |
124 XEmacs doing it | |
125 | |
126 We do NOT set the background of this widget window, that way | |
127 there is NO flickering, etc. The downside is the XEmacs frame | |
128 appears as 'seethru' when XEmacs is too busy to redraw the | |
129 frame. | |
130 | |
131 Well, wait, we do... otherwise there sre weird 'seethru' areas | |
5384
3889ef128488
Fix misspelled words, and some grammar, across the entire source tree.
Jerry James <james@xemacs.org>
parents:
5231
diff
changeset
|
132 even when XEmacs does a full redisplay. Most noticeable in some |
462 | 133 areas of the modeline, or in the right-hand-side of the window |
134 between the scrollbar ad n the edge of the window. | |
135 */ | |
136 if (widget->window) | |
137 { | |
138 gdk_window_set_back_pixmap (widget->window, NULL, 0); | |
139 gdk_window_set_back_pixmap (widget->parent->window, NULL, 0); | |
140 gdk_window_set_background (widget->parent->window, | |
141 &widget->style->bg[GTK_STATE_NORMAL]); | |
142 gdk_window_set_background (widget->window, | |
143 &widget->style->bg[GTK_STATE_NORMAL]); | |
144 } | |
145 } | |
146 | |
147 extern Lisp_Object xemacs_gtk_convert_color(GdkColor *c, GtkWidget *w); | |
148 | |
5176
8b2f75cecb89
rename objects* (.c, .h and .el files) to fontcolor*
Ben Wing <ben@xemacs.org>
parents:
5043
diff
changeset
|
149 /* From fontcolor-gtk.c */ |
462 | 150 extern Lisp_Object __get_gtk_font_truename (GdkFont *gdk_font, int expandp); |
151 | |
152 #define convert_font(f) __get_gtk_font_truename (f, 0) | |
153 | |
778 | 154 #ifdef SMASH_FACE_FALLBACKS |
462 | 155 static void |
156 smash_face_fallbacks (struct frame *f, GtkStyle *style) | |
157 { | |
158 #define FROB(face,prop,slot) do { \ | |
159 Lisp_Object fallback = Qnil; \ | |
160 Lisp_Object specifier = Fget (face, prop, Qnil); \ | |
161 struct Lisp_Specifier *sp = NULL; \ | |
162 if (NILP (specifier)) continue; \ | |
163 sp = XSPECIFIER (specifier); \ | |
164 fallback = sp->fallback; \ | |
165 if (EQ (Fcar (Fcar (Fcar (fallback))), Qgtk)) \ | |
166 fallback = XCDR (fallback); \ | |
167 if (! NILP (slot)) \ | |
168 fallback = acons (list1 (Qgtk), \ | |
169 slot, \ | |
170 fallback); \ | |
171 set_specifier_fallback (specifier, fallback); \ | |
172 } while (0); | |
173 #define FROB_FACE(face,fg_slot,bg_slot) \ | |
174 do { \ | |
175 FROB (face, Qforeground, xemacs_gtk_convert_color (&style->fg_slot[GTK_STATE_NORMAL], FRAME_GTK_SHELL_WIDGET (f))); \ | |
176 FROB (face, Qbackground, xemacs_gtk_convert_color (&style->bg_slot[GTK_STATE_NORMAL], FRAME_GTK_SHELL_WIDGET (f))); \ | |
177 if (style->rc_style && style->rc_style->bg_pixmap_name[GTK_STATE_NORMAL]) \ | |
178 { \ | |
179 FROB (Vdefault_face, Qbackground_pixmap, \ | |
4953
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
4709
diff
changeset
|
180 Fmake_image_instance (build_cistring (style->rc_style->bg_pixmap_name[GTK_STATE_NORMAL]), \ |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
181 f->device, Qnil, make_fixnum (5))); \ |
462 | 182 } \ |
183 else \ | |
184 { \ | |
185 FROB (Vdefault_face, Qbackground_pixmap, Qnil); \ | |
186 } \ | |
187 } while (0) | |
188 | |
189 FROB (Vdefault_face, Qfont, convert_font (style->font)); | |
190 FROB_FACE (Vdefault_face, fg, bg); | |
191 FROB_FACE (Vgui_element_face, text, mid); | |
192 | |
193 #undef FROB | |
194 #undef FROB_FACE | |
195 } | |
778 | 196 #endif /* SMASH_FACE_FALLBACKS */ |
462 | 197 |
198 #ifdef HAVE_SCROLLBARS | |
199 static void | |
200 smash_scrollbar_specifiers (struct frame *f, GtkStyle *style) | |
201 { | |
202 Lisp_Object frame; | |
203 int slider_size = 0; | |
204 int hsize, vsize; | |
205 GtkRangeClass *klass; | |
206 | |
793 | 207 frame = wrap_frame (f); |
462 | 208 |
209 klass = (GtkRangeClass *) gtk_type_class (GTK_TYPE_SCROLLBAR); | |
210 slider_size = klass->slider_width; | |
211 hsize = slider_size + (style->klass->ythickness * 2); | |
212 vsize = slider_size + (style->klass->xthickness * 2); | |
213 | |
214 style = gtk_style_attach (style, | |
215 GTK_WIDGET (DEVICE_GTK_APP_SHELL (XDEVICE (FRAME_DEVICE (f))))->window); | |
216 | |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
217 Fadd_spec_to_specifier (Vscrollbar_width, make_fixnum (vsize), frame, Qnil, Qnil); |
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
218 Fadd_spec_to_specifier (Vscrollbar_height, make_fixnum (hsize), frame, Qnil, Qnil); |
462 | 219 } |
220 #endif /* HAVE_SCROLLBARS */ | |
221 | |
744 | 222 #ifdef HAVE_TOOLBARS |
223 extern Lisp_Object Vtoolbar_shadow_thickness; | |
224 | |
225 static void | |
226 smash_toolbar_specifiers(struct frame *f, GtkStyle *style) | |
227 { | |
228 Lisp_Object frame; | |
229 GtkStyleClass *klass = (GtkStyleClass *) style->klass; | |
230 | |
793 | 231 frame = wrap_frame (f); |
744 | 232 |
5581
56144c8593a8
Mechanically change INT to FIXNUM in our sources.
Aidan Kehoe <kehoea@parhasard.net>
parents:
5474
diff
changeset
|
233 Fadd_spec_to_specifier (Vtoolbar_shadow_thickness, make_fixnum (klass->xthickness), |
744 | 234 Qnil, list2 (Qgtk, Qdefault), Qprepend); |
235 } | |
236 #endif /* HAVE_TOOLBARS */ | |
237 | |
462 | 238 static void |
239 gtk_xemacs_realize (GtkWidget *widget) | |
240 { | |
241 parent_class->realize (widget); | |
242 gtk_xemacs_style_set (widget, gtk_widget_get_style (widget)); | |
243 } | |
244 | |
245 static void | |
246 gtk_xemacs_style_set (GtkWidget *widget, GtkStyle *previous_style) | |
247 { | |
248 GtkStyle *new_style = gtk_widget_get_style (widget); | |
249 GtkXEmacs *x = GTK_XEMACS (widget); | |
250 | |
251 parent_class->style_set (widget, previous_style); | |
252 | |
253 if (x->f) | |
254 { | |
255 __nuke_background_items (widget); | |
778 | 256 #ifdef SMASH_FACE_FALLBACKS |
462 | 257 smash_face_fallbacks (x->f, new_style); |
258 #endif | |
744 | 259 #ifdef HAVE_SCROLLBARS |
462 | 260 smash_scrollbar_specifiers (x->f, new_style); |
744 | 261 #endif |
262 #ifdef HAVE_TOOLBARS | |
263 smash_toolbar_specifiers (x->f, new_style); | |
264 #endif | |
462 | 265 } |
266 } | |
267 | |
268 static void | |
269 gtk_xemacs_size_request (GtkWidget *widget, GtkRequisition *requisition) | |
270 { | |
271 GtkXEmacs *x = GTK_XEMACS (widget); | |
272 struct frame *f = GTK_XEMACS_FRAME (x); | |
273 int width, height; | |
274 | |
275 if (f) | |
276 { | |
5043 | 277 frame_unit_to_pixel_size (f, FRAME_WIDTH (f), FRAME_HEIGHT (f), |
462 | 278 &width, &height); |
279 requisition->width = width; | |
280 requisition->height = height; | |
281 } | |
282 else | |
283 { | |
284 parent_class->size_request (widget, requisition); | |
285 } | |
286 } | |
287 | |
2168 | 288 /* Assign a size and position to the child widgets. This differs from the |
289 super class method in that for all widgets except the scrollbars the size | |
290 and position are not caclulated here. This is because these widgets have | |
291 this function performed for them by the redisplay code (see | |
292 gtk_map_subwindow()). If the superclass method is called then the widgets | |
293 can change size and position as the two pieces of code move the widgets at | |
294 random. | |
295 */ | |
462 | 296 static void |
297 gtk_xemacs_size_allocate (GtkWidget *widget, GtkAllocation *allocation) | |
298 { | |
299 GtkXEmacs *x = GTK_XEMACS (widget); | |
2168 | 300 GtkFixed *fixed = GTK_FIXED (widget); |
462 | 301 struct frame *f = GTK_XEMACS_FRAME (x); |
302 int columns, rows; | |
2168 | 303 GList *children; |
304 guint16 border_width; | |
462 | 305 |
2168 | 306 widget->allocation = *allocation; |
307 if (GTK_WIDGET_REALIZED (widget)) | |
308 gdk_window_move_resize (widget->window, | |
309 allocation->x, | |
310 allocation->y, | |
311 allocation->width, | |
312 allocation->height); | |
313 | |
314 border_width = GTK_CONTAINER (fixed)->border_width; | |
315 | |
316 children = fixed->children; | |
317 while (children) | |
318 { | |
2336 | 319 GtkFixedChild* child = (GtkFixedChild*) children->data; |
2168 | 320 children = children->next; |
321 | |
322 /* | |
323 Scrollbars are the only widget that is managed by GTK. See | |
324 comments in gtk_create_scrollbar_instance(). | |
325 */ | |
326 if (GTK_WIDGET_VISIBLE (child->widget) && | |
327 gtk_type_is_a(GTK_OBJECT_TYPE(child->widget), GTK_TYPE_SCROLLBAR)) | |
328 { | |
329 GtkAllocation child_allocation; | |
330 GtkRequisition child_requisition; | |
331 | |
332 gtk_widget_get_child_requisition (child->widget, &child_requisition); | |
333 child_allocation.x = child->x + border_width; | |
334 child_allocation.y = child->y + border_width; | |
335 child_allocation.width = child_requisition.width; | |
336 child_allocation.height = child_requisition.height; | |
337 gtk_widget_size_allocate (child->widget, &child_allocation); | |
338 } | |
339 } | |
462 | 340 |
341 if (f) | |
342 { | |
343 f->pixwidth = allocation->width; | |
344 f->pixheight = allocation->height; | |
345 | |
5043 | 346 pixel_to_frame_unit_size (f, |
462 | 347 allocation->width, |
348 allocation->height, &columns, &rows); | |
349 | |
5043 | 350 change_frame_size (f, columns, rows, 1); |
462 | 351 } |
352 } | |
353 | |
354 static void | |
355 gtk_xemacs_paint (GtkWidget *widget, GdkRectangle *area) | |
356 { | |
357 GtkXEmacs *x = GTK_XEMACS (widget); | |
358 struct frame *f = GTK_XEMACS_FRAME (x); | |
2195 | 359 |
360 if (GTK_WIDGET_DRAWABLE (widget)) | |
361 redisplay_redraw_exposed_area (f, area->x, area->y, area->width, | |
362 area->height); | |
462 | 363 } |
364 | |
365 static void | |
366 gtk_xemacs_draw (GtkWidget *widget, GdkRectangle *area) | |
367 { | |
368 GtkFixed *fixed = GTK_FIXED (widget); | |
369 GtkFixedChild *child; | |
370 GdkRectangle child_area; | |
371 GList *children; | |
372 | |
373 /* I need to manually iterate over the children instead of just | |
374 chaining to parent_class->draw() because it calls | |
375 gtk_fixed_paint() directly, which clears the background window, | |
376 which causes A LOT of flashing. */ | |
377 | |
2195 | 378 if (GTK_WIDGET_DRAWABLE (widget)) |
379 { | |
380 gtk_xemacs_paint (widget, area); | |
462 | 381 |
2195 | 382 children = fixed->children; |
462 | 383 |
2195 | 384 while (children) |
385 { | |
386 child = (GtkFixedChild*) children->data; | |
387 children = children->next; | |
388 /* #### This is what causes the scrollbar flickering! | |
389 Evidently the scrollbars pretty much take care of drawing | |
390 themselves in most cases. Then we come along and tell them | |
391 to redraw again! | |
462 | 392 |
2195 | 393 But if we just leave it out, then they do not get drawn |
394 correctly the first time! | |
462 | 395 |
2195 | 396 Scrollbar flickering has been greatly helped by the |
397 optimizations in scrollbar-gtk.c / | |
398 gtk_update_scrollbar_instance_status (), so this is not that | |
399 big a deal anymore. | |
400 */ | |
401 if (gtk_widget_intersect (child->widget, area, &child_area)) | |
402 { | |
403 gtk_widget_draw (child->widget, &child_area); | |
404 } | |
405 } | |
406 } | |
462 | 407 } |
408 | |
409 static gint | |
410 gtk_xemacs_expose (GtkWidget *widget, GdkEventExpose *event) | |
411 { | |
412 GtkXEmacs *x = GTK_XEMACS (widget); | |
413 struct frame *f = GTK_XEMACS_FRAME (x); | |
414 GdkRectangle *a = &event->area; | |
415 | |
2195 | 416 if (GTK_WIDGET_DRAWABLE (widget)) |
417 { | |
418 /* This takes care of drawing the scrollbars, etc */ | |
419 parent_class->expose_event (widget, event); | |
462 | 420 |
2195 | 421 /* Now draw the actual frame data */ |
422 if (!check_for_ignored_expose (f, a->x, a->y, a->width, a->height) && | |
423 !find_matching_subwindow (f, a->x, a->y, a->width, a->height)) | |
424 redisplay_redraw_exposed_area (f, a->x, a->y, a->width, a->height); | |
425 return (TRUE); | |
426 } | |
3087 | 427 |
428 return FALSE; | |
462 | 429 } |
430 | |
431 Lisp_Object | |
2286 | 432 xemacs_gtk_convert_color(GdkColor *c, GtkWidget *UNUSED (w)) |
462 | 433 { |
434 char color_buf[255]; | |
435 | |
436 sprintf (color_buf, "#%04x%04x%04x", c->red, c->green, c->blue); | |
437 | |
4953
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
4709
diff
changeset
|
438 return (build_cistring (color_buf)); |
462 | 439 } |