Mercurial > emacs
diff src/termhooks.h @ 83004:7900111db01c
Converted display hooks to be display-local. Plus many bugfixes.
lib-src/emacsclient.c (window_change_signal): Renamed to pass_signal_to_emacs.
(init_signal): Pass SIGINT and SIGQUIT to the emacs process.
lisp/faces.el (face-valid-attribute-values): Use the window-system
function, not the variable.
(read-face-attribute, face-spec-set-match-display, frame-set-background-mode)
(face-set-after-frame-default): Ditto.
lisp/frame.el (make-frame-on-tty): Added interactive declaration
(suggested by Robert J. Chassell). Use tty-create-frame-with-faces,
not make-terminal-frame.
src/termhooks.h (struct display_method): Renamed to display for brevity.
(struct display): Added all display hook variables as members of this structure.
Added next_display, reference_count, type and display_info components.
(FRAME_MUST_WRITE_SPACES, FRAME_FAST_CLEAR_END_OF_LINE, FRAME_LINE_INS_DEL_OK)
(FRAME_CHAR_INS_DEL_OK, FRAME_SCROLL_REGION_OK, FRAME_SCROLL_REGION_COST)
(FRAME_MEMORY_BELOW_FRAME, FRAME_RIF): Updated for struct display.
(FRAME_DISPLAY): New macro.
(create_display, delete_display): New prototypes.
src/frame.h (struct frame): Added `display' member, removed display_method.
(FRAME_LIVE_P): Look at f->display, not f->output_data.
src/termchar.h (struct tty_display_info): Removed display_method component.
(FRAME_TTY): Use the display structure, not output_data.
src/term.c (display_list): New variable.
(cursor_to_hook, raw_cursor_to_hook, clear_to_end_hook, clear_frame_hook)
(clear_end_of_line_hook, ins_del_lines_hook, delete_glyphs_hook)
(ring_bell_hook, reset_terminal_modes_hook, set_terminal_modes_hook)
(update_begin_hook, update_end_hook, set_terminal_window_hook)
(insert_glyphs_hook, write_glyphs_hook, delete_glyphs_hoo, read_socket_hook)
(frame_up_to_date_hook, mouse_position_hook, frame_rehighlight_hook)
(frame_raise_lower_hook, set_vertical_scroll_bar_hook, condemn_scroll_bars_hook)
(redeem_scroll_bar_hook, judge_scroll_bars_hook): Moved to struct display.
(tty_display_method_template): Removed.
(syms_of_term): Don't initialize tty_display_method_template.
(ring_bell, set_terminal_modes, reset_terminal_modes, update_begin)
(update_end, set_terminal_window, cursor_to, raw_cursor_to, clear_to_end)
(clear_frame, clear_end_of_line, write_glyphs, insert_glyphs)
(delete_glyphs, ins_del_lines): Access display hooks through the frame pointer.
(Ftty_display_color_p): Use the frame given as a parameter, or else return nil.
(Ftty_display_color_cells): Ditto.
(get_named_tty): Renamed to get_named_tty_display, changed return type to struct display.
(term_dummy_init): Renamed to initial_term_init. Create and return an initial display.
(term_init): Initialize a new struct display and return a pointer to
it instead of tty_display_info. Removed frame initialization kludge.
(Fdelete_tty): Updated for struct display.
(delete_tty): The parameter type is now struct display, not tty_display_info.
Delete the display, too.
(create_tty_output): New function for creating tty_output structures.
(delete_tty_output): New function for deleting tty_output structures.
(create_display): New function for creating and registering display structures.
(delete_display): New function for deleting and unregistering display structures.
src/dispextern.h: Updated prototypes.
src/dispnew.c: Include frame.h before termhooks.h.
(init_display): Updated term_init call to new signature.
src/emacs.c: Include frame.h (for termhooks.h).
src/keymap.c: Ditto.
src/lread.c: Ditto.
src/xsmfns.c: Ditto.
src/process.c: Include frame.h before termhooks.h.
src/frame.c (Fwindow_system): New function.
(syms_of_frame): Initialize it.
(make_terminal_frame): Open the terminal device before creating the new frame.
Disable scrollbars here, term_init cannot do that anymore.
(Fdelete_frame): Use the new delete_frame_hook, don't do display-specific
frame deletion here. Ditto for delete_display_hook.
(Fmouse_position, Fmouse_pixel_position, Fraise_frame, Flower_frame)
(Fredirect_frame_focus): Access display hooks through the frame pointer.
src/keyboard.c: Include frame.h before termhooks.h.
(start_polling, input_polling_used, stop_polling, gobble_input): Ignore read_socket_hook.
(kbd_buffer_get_event, Fset_input_mode): Access display hooks through the frame pointer.
(read_avail_input): Loop through all display devices for and call all read_socket_hook functions. Check ttys even if read_socket_hook returned an error.
src/sysdep.c (discard_tty_input): Ignore read_socket_hook.
(stuff_char): Don't do anything if the current frame is not on a termcap display.
(request_sigio, unrequest_sigio): Ignore read_socket_hook.
(init_sys_modes): Always call narrow_foreground_group. Set up terminal modes and sigio even under X.
src/xdisp.c (message2_nolog, message3_nolog, redisplay_internal)
(set_vertical_scroll_bar, redisplay_window): Access display hooks through the frame pointer.
(echo_area_display): Don't be afraid of termcap frames during an X+tty combo session.
src/xfaces.c: Include termhooks.h.
(Ftty_supports_face_attributes_p): Use the given frame, not selected_frame.
src/xfns.c (x_set_scroll_bar_foreground, x_set_scroll_bar_background): Access display hooks through the frame pointer.
(Fx_create_frame, x_create_tip_frame): Initialize the frame's display structure.
src/xmenu.c: Include termhooks.h after frame.h.
src/xselect.c (x_own_selection, some_frame_on_display, x_get_foreign_selection)
(Fx_disown_selection_internal, Fx_get_cut_buffer_internal)
(Fx_store_cut_buffer_internal, Fx_rotate_cut_buffers_internal): Don't do anything
if the selected frame is not an X frame.
src/xterm.c (x_display_method): Removed.
(x_create_frame_display, x_delete_frame_display): New functions for handling struct display objects.
(x_term_init): Set up a new struct display object, too.
(x_delete_display): Delete the struct display corresponding to the X display.
(x_initialize): Moved hook initialization to x_create_frame_display.
src/xterm.h (x_display_method): Removed.
(struct x_display_info): Added frame_display component.
git-archimport-id: lorentey@elte.hu--2004/emacs--multi-tty--0--patch-44
| author | Karoly Lorentey <lorentey@elte.hu> |
|---|---|
| date | Mon, 05 Jan 2004 05:54:35 +0000 |
| parents | 5de4189e659d |
| children | 040dd41ed7d0 |
line wrap: on
line diff
--- a/src/termhooks.h Sat Jan 03 19:06:35 2004 +0000 +++ b/src/termhooks.h Mon Jan 05 05:54:35 2004 +0000 @@ -1,5 +1,4 @@ -/* Hooks by which low level terminal operations - can be made to call other routines. +/* Parameters and display hooks for output devices Copyright (C) 1985,86,93,94,2003 Free Software Foundation, Inc. This file is part of GNU Emacs. @@ -30,75 +29,6 @@ #define P_(X) () #endif -/* Device-local parameters. */ -struct display_method -{ - /* Terminal characteristics. */ - - int must_write_spaces; /* Nonzero means spaces in the text must - actually be output; can't just skip over - some columns to leave them blank. */ - int fast_clear_end_of_line; /* Nonzero means terminal has a `ce' string */ - - int line_ins_del_ok; /* Terminal can insert and delete lines */ - int char_ins_del_ok; /* Terminal can insert and delete chars */ - int scroll_region_ok; /* Terminal supports setting the scroll - window */ - int scroll_region_cost; /* Cost of setting the scroll window, - measured in characters. */ - int memory_below_frame; /* Terminal remembers lines scrolled - off bottom */ - -#if 0 /* These are not used anywhere. */ - /* EMACS_INT baud_rate; */ /* Output speed in baud */ - int min_padding_speed; /* Speed below which no padding necessary. */ - int dont_calculate_costs; /* Nonzero means don't bother computing - various cost tables; we won't use them. */ -#endif - - /* Window-based redisplay interface for this frame (0 for termcap - frames). */ - struct redisplay_interface *rif; - - /* XXX Display hooks will go here. */ -}; - -#define FRAME_MUST_WRITE_SPACES(f) ((f)->display_method->must_write_spaces) -#define FRAME_FAST_CLEAR_END_OF_LINE(f) ((f)->display_method->fast_clear_end_of_line) -#define FRAME_LINE_INS_DEL_OK(f) ((f)->display_method->line_ins_del_ok) -#define FRAME_CHAR_INS_DEL_OK(f) ((f)->display_method->char_ins_del_ok) -#define FRAME_SCROLL_REGION_OK(f) ((f)->display_method->scroll_region_ok) -#define FRAME_SCROLL_REGION_COST(f) ((f)->display_method->scroll_region_cost) -#define FRAME_MEMORY_BELOW_FRAME(f) ((f)->display_method->memory_below_frame) - -#define FRAME_RIF(f) ((f)->display_method->rif) - -/* Text display hooks. */ - -extern void (*cursor_to_hook) P_ ((int vpos, int hpos)); -extern void (*raw_cursor_to_hook) P_ ((int, int)); - -extern void (*clear_to_end_hook) P_ ((void)); -extern void (*clear_frame_hook) P_ ((void)); -extern void (*clear_end_of_line_hook) P_ ((int)); - -extern void (*ins_del_lines_hook) P_ ((int, int)); - -extern void (*insert_glyphs_hook) P_ ((struct glyph *s, int n)); -extern void (*write_glyphs_hook) P_ ((struct glyph *s, int n)); -extern void (*delete_glyphs_hook) P_ ((int)); - -extern void (*ring_bell_hook) P_ ((void)); - -extern void (*reset_terminal_modes_hook) P_ ((void)); -extern void (*set_terminal_modes_hook) P_ ((void)); -extern void (*update_begin_hook) P_ ((struct frame *)); -extern void (*update_end_hook) P_ ((struct frame *)); -extern void (*set_terminal_window_hook) P_ ((int)); - - - -/* Multi-frame and mouse support hooks. */ enum scroll_bar_part { scroll_bar_above_handle, @@ -112,125 +42,6 @@ scroll_bar_move_ratio }; -/* Return the current position of the mouse. - - Set *f to the frame the mouse is in, or zero if the mouse is in no - Emacs frame. If it is set to zero, all the other arguments are - garbage. - - If the motion started in a scroll bar, set *bar_window to the - scroll bar's window, *part to the part the mouse is currently over, - *x to the position of the mouse along the scroll bar, and *y to the - overall length of the scroll bar. - - Otherwise, set *bar_window to Qnil, and *x and *y to the column and - row of the character cell the mouse is over. - - Set *time to the time the mouse was at the returned position. - - This should clear mouse_moved until the next motion - event arrives. */ -extern void (*mouse_position_hook) P_ ((struct frame **f, int, - Lisp_Object *bar_window, - enum scroll_bar_part *part, - Lisp_Object *x, - Lisp_Object *y, - unsigned long *time)); - -/* The window system handling code should set this if the mouse has - moved since the last call to the mouse_position_hook. Calling that - hook should clear this. */ -extern int mouse_moved; - -/* When a frame's focus redirection is changed, this hook tells the - window system code to re-decide where to put the highlight. Under - X, this means that Emacs lies about where the focus is. */ -extern void (*frame_rehighlight_hook) P_ ((struct frame *)); - -/* If we're displaying frames using a window system that can stack - frames on top of each other, this hook allows you to bring a frame - to the front, or bury it behind all the other windows. If this - hook is zero, that means the device we're displaying on doesn't - support overlapping frames, so there's no need to raise or lower - anything. - - If RAISE is non-zero, F is brought to the front, before all other - windows. If RAISE is zero, F is sent to the back, behind all other - windows. */ -extern void (*frame_raise_lower_hook) P_ ((struct frame *f, int raise)); - - -/* Scroll bar hooks. */ - -/* The representation of scroll bars is determined by the code which - implements them, except for one thing: they must be represented by - lisp objects. This allows us to place references to them in - Lisp_Windows without worrying about those references becoming - dangling references when the scroll bar is destroyed. - - The window-system-independent portion of Emacs just refers to - scroll bars via their windows, and never looks inside the scroll bar - representation; it always uses hook functions to do all the - scroll bar manipulation it needs. - - The `vertical_scroll_bar' field of a Lisp_Window refers to that - window's scroll bar, or is nil if the window doesn't have a - scroll bar. - - The `scroll_bars' and `condemned_scroll_bars' fields of a Lisp_Frame - are free for use by the scroll bar implementation in any way it sees - fit. They are marked by the garbage collector. */ - - -/* Set the vertical scroll bar for WINDOW to have its upper left corner - at (TOP, LEFT), and be LENGTH rows high. Set its handle to - indicate that we are displaying PORTION characters out of a total - of WHOLE characters, starting at POSITION. If WINDOW doesn't yet - have a scroll bar, create one for it. */ -extern void (*set_vertical_scroll_bar_hook) - P_ ((struct window *window, - int portion, int whole, int position)); - - -/* The following three hooks are used when we're doing a thorough - redisplay of the frame. We don't explicitly know which scroll bars - are going to be deleted, because keeping track of when windows go - away is a real pain - can you say set-window-configuration? - Instead, we just assert at the beginning of redisplay that *all* - scroll bars are to be removed, and then save scroll bars from the - fiery pit when we actually redisplay their window. */ - -/* Arrange for all scroll bars on FRAME to be removed at the next call - to `*judge_scroll_bars_hook'. A scroll bar may be spared if - `*redeem_scroll_bar_hook' is applied to its window before the judgement. - - This should be applied to each frame each time its window tree is - redisplayed, even if it is not displaying scroll bars at the moment; - if the HAS_SCROLL_BARS flag has just been turned off, only calling - this and the judge_scroll_bars_hook will get rid of them. - - If non-zero, this hook should be safe to apply to any frame, - whether or not it can support scroll bars, and whether or not it is - currently displaying them. */ -extern void (*condemn_scroll_bars_hook) P_ ((struct frame *frame)); - -/* Unmark WINDOW's scroll bar for deletion in this judgement cycle. - Note that it's okay to redeem a scroll bar that is not condemned. */ -extern void (*redeem_scroll_bar_hook) P_ ((struct window *window)); - -/* Remove all scroll bars on FRAME that haven't been saved since the - last call to `*condemn_scroll_bars_hook'. - - This should be applied to each frame after each time its window - tree is redisplayed, even if it is not displaying scroll bars at the - moment; if the HAS_SCROLL_BARS flag has just been turned off, only - calling this and condemn_scroll_bars_hook will get rid of them. - - If non-zero, this hook should be safe to apply to any frame, - whether or not it can support scroll bars, and whether or not it is - currently displaying them. */ -extern void (*judge_scroll_bars_hook) P_ ((struct frame *FRAME)); - /* Input queue declarations and hooks. */ @@ -413,13 +224,6 @@ #define EVENT_INIT(event) bzero (&(event), sizeof (struct input_event)) -/* Called to read input events. */ -extern int (*read_socket_hook) P_ ((struct input_event *, int, int)); - -/* Called when a frame's display becomes entirely up to date. */ -extern void (*frame_up_to_date_hook) P_ ((struct frame *)); - - /* Bits in the modifiers member of the input_event structure. Note that reorder_modifiers assumes that the bits are in canonical order. @@ -471,5 +275,258 @@ #endif /* CONSP */ + +/* Display-local parameters. */ +struct display +{ + /* Chain of all displays. */ + struct display *next_display; + + /* The number of frames that are on this display. */ + int reference_count; + + /* The type of the display. */ + enum output_method type; + + /* Display-type dependent data shared amongst all frames on this display. */ + union display_info + { + struct tty_display_info *tty; /* termchar.h */ + struct x_display_info *x; /* xterm.h */ + } display_info; + + + /* Terminal characteristics. */ + /* XXX Are these really used on non-termcap displays? */ + + int must_write_spaces; /* Nonzero means spaces in the text must + actually be output; can't just skip over + some columns to leave them blank. */ + int fast_clear_end_of_line; /* Nonzero means terminal has a `ce' string */ + + int line_ins_del_ok; /* Terminal can insert and delete lines */ + int char_ins_del_ok; /* Terminal can insert and delete chars */ + int scroll_region_ok; /* Terminal supports setting the scroll + window */ + int scroll_region_cost; /* Cost of setting the scroll window, + measured in characters. */ + int memory_below_frame; /* Terminal remembers lines scrolled + off bottom */ + +#if 0 /* These are not used anywhere. */ + /* EMACS_INT baud_rate; */ /* Output speed in baud */ + int min_padding_speed; /* Speed below which no padding necessary. */ + int dont_calculate_costs; /* Nonzero means don't bother computing + various cost tables; we won't use them. */ +#endif + + + /* Window-based redisplay interface for this device (0 for tty + devices). */ + struct redisplay_interface *rif; + + /* Frame-based redisplay interface. */ + + /* Text display hooks. */ + + void (*cursor_to_hook) P_ ((int vpos, int hpos)); + void (*raw_cursor_to_hook) P_ ((int, int)); + + void (*clear_to_end_hook) P_ ((void)); + void (*clear_frame_hook) P_ ((void)); + void (*clear_end_of_line_hook) P_ ((int)); + + void (*ins_del_lines_hook) P_ ((int, int)); + + void (*insert_glyphs_hook) P_ ((struct glyph *s, int n)); + void (*write_glyphs_hook) P_ ((struct glyph *s, int n)); + void (*delete_glyphs_hook) P_ ((int)); + + void (*ring_bell_hook) P_ ((void)); + + void (*reset_terminal_modes_hook) P_ ((void)); + void (*set_terminal_modes_hook) P_ ((void)); + void (*update_begin_hook) P_ ((struct frame *)); + void (*update_end_hook) P_ ((struct frame *)); + void (*set_terminal_window_hook) P_ ((int)); + + /* Multi-frame and mouse support hooks. */ + + /* Return the current position of the mouse. + + Set *f to the frame the mouse is in, or zero if the mouse is in no + Emacs frame. If it is set to zero, all the other arguments are + garbage. + + If the motion started in a scroll bar, set *bar_window to the + scroll bar's window, *part to the part the mouse is currently over, + *x to the position of the mouse along the scroll bar, and *y to the + overall length of the scroll bar. + + Otherwise, set *bar_window to Qnil, and *x and *y to the column and + row of the character cell the mouse is over. + + Set *time to the time the mouse was at the returned position. + + This should clear mouse_moved until the next motion + event arrives. */ + void (*mouse_position_hook) P_ ((struct frame **f, int, + Lisp_Object *bar_window, + enum scroll_bar_part *part, + Lisp_Object *x, + Lisp_Object *y, + unsigned long *time)); + + /* The window system handling code should set this if the mouse has + moved since the last call to the mouse_position_hook. Calling that + hook should clear this. */ + int mouse_moved; + + /* When a frame's focus redirection is changed, this hook tells the + window system code to re-decide where to put the highlight. Under + X, this means that Emacs lies about where the focus is. */ + void (*frame_rehighlight_hook) P_ ((struct frame *)); + + /* If we're displaying frames using a window system that can stack + frames on top of each other, this hook allows you to bring a frame + to the front, or bury it behind all the other windows. If this + hook is zero, that means the device we're displaying on doesn't + support overlapping frames, so there's no need to raise or lower + anything. + + If RAISE is non-zero, F is brought to the front, before all other + windows. If RAISE is zero, F is sent to the back, behind all other + windows. */ + void (*frame_raise_lower_hook) P_ ((struct frame *f, int raise)); + + + /* Scroll bar hooks. */ + + /* The representation of scroll bars is determined by the code which + implements them, except for one thing: they must be represented by + lisp objects. This allows us to place references to them in + Lisp_Windows without worrying about those references becoming + dangling references when the scroll bar is destroyed. + + The window-system-independent portion of Emacs just refers to + scroll bars via their windows, and never looks inside the scroll bar + representation; it always uses hook functions to do all the + scroll bar manipulation it needs. + + The `vertical_scroll_bar' field of a Lisp_Window refers to that + window's scroll bar, or is nil if the window doesn't have a + scroll bar. + + The `scroll_bars' and `condemned_scroll_bars' fields of a Lisp_Frame + are free for use by the scroll bar implementation in any way it sees + fit. They are marked by the garbage collector. */ + + + /* Set the vertical scroll bar for WINDOW to have its upper left corner + at (TOP, LEFT), and be LENGTH rows high. Set its handle to + indicate that we are displaying PORTION characters out of a total + of WHOLE characters, starting at POSITION. If WINDOW doesn't yet + have a scroll bar, create one for it. */ + void (*set_vertical_scroll_bar_hook) P_ ((struct window *window, + int portion, int whole, + int position)); + + + /* The following three hooks are used when we're doing a thorough + redisplay of the frame. We don't explicitly know which scroll bars + are going to be deleted, because keeping track of when windows go + away is a real pain - can you say set-window-configuration? + Instead, we just assert at the beginning of redisplay that *all* + scroll bars are to be removed, and then save scroll bars from the + fiery pit when we actually redisplay their window. */ + + /* Arrange for all scroll bars on FRAME to be removed at the next call + to `*judge_scroll_bars_hook'. A scroll bar may be spared if + `*redeem_scroll_bar_hook' is applied to its window before the judgement. + + This should be applied to each frame each time its window tree is + redisplayed, even if it is not displaying scroll bars at the moment; + if the HAS_SCROLL_BARS flag has just been turned off, only calling + this and the judge_scroll_bars_hook will get rid of them. + + If non-zero, this hook should be safe to apply to any frame, + whether or not it can support scroll bars, and whether or not it is + currently displaying them. */ + void (*condemn_scroll_bars_hook) P_ ((struct frame *frame)); + + /* Unmark WINDOW's scroll bar for deletion in this judgement cycle. + Note that it's okay to redeem a scroll bar that is not condemned. */ + void (*redeem_scroll_bar_hook) P_ ((struct window *window)); + + /* Remove all scroll bars on FRAME that haven't been saved since the + last call to `*condemn_scroll_bars_hook'. + + This should be applied to each frame after each time its window + tree is redisplayed, even if it is not displaying scroll bars at the + moment; if the HAS_SCROLL_BARS flag has just been turned off, only + calling this and condemn_scroll_bars_hook will get rid of them. + + If non-zero, this hook should be safe to apply to any frame, + whether or not it can support scroll bars, and whether or not it is + currently displaying them. */ + void (*judge_scroll_bars_hook) P_ ((struct frame *FRAME)); + + + /* Called to read input events. */ + int (*read_socket_hook) P_ ((struct input_event *, int, int)); + + /* Called when a frame's display becomes entirely up to date. */ + void (*frame_up_to_date_hook) P_ ((struct frame *)); + + + /* Called to delete the device-specific portions of a frame that is + on this display. */ + void (*delete_frame_hook) P_ ((struct frame *)); + + /* Called after the last frame on this display is deleted. + If this is NULL, then the generic delete_frame() is called. + + Fdelete_frame ensures that there are no live frames on the + display when it calls this hook. */ + void (*delete_display_hook) P_ ((struct display *)); + +}; + + +/* Chain of all displays currently in use. */ +extern struct display *display_list; + +#define FRAME_MUST_WRITE_SPACES(f) ((f)->display->must_write_spaces) +#define FRAME_FAST_CLEAR_END_OF_LINE(f) ((f)->display->fast_clear_end_of_line) +#define FRAME_LINE_INS_DEL_OK(f) ((f)->display->line_ins_del_ok) +#define FRAME_CHAR_INS_DEL_OK(f) ((f)->display->char_ins_del_ok) +#define FRAME_SCROLL_REGION_OK(f) ((f)->display->scroll_region_ok) +#define FRAME_SCROLL_REGION_COST(f) ((f)->display->scroll_region_cost) +#define FRAME_MEMORY_BELOW_FRAME(f) ((f)->display->memory_below_frame) + +#define FRAME_RIF(f) ((f)->display->rif) + +#define FRAME_DISPLAY(f) ((f)->display) + +/* FRAME_WINDOW_P tests whether the frame is a window, and is + defined to be the predicate for the window system being used. */ + +#ifdef HAVE_X_WINDOWS +#define FRAME_WINDOW_P(f) FRAME_X_P (f) +#endif +#ifdef HAVE_NTGUI +#define FRAME_WINDOW_P(f) FRAME_W32_P (f) +#endif +#ifdef MAC_OS +#define FRAME_WINDOW_P(f) FRAME_MAC_P (f) +#endif +#ifndef FRAME_WINDOW_P +#define FRAME_WINDOW_P(f) (0) +#endif + + +extern struct display *create_display P_ ((void)); +extern void delete_display P_ ((struct display *)); + /* arch-tag: 33a00ecc-52b5-4186-a410-8801ac9f087d (do not change this comment) */
