Mercurial > emacs
view src/cmds.c @ 1787:5e245540d06f
Make scrollbar structures into lisp objects, so that they can be
GC'd; this allows windows and scrollbars can refer to each other
without worrying about dangling pointers.
* xterm.h (struct x_display): vertical_scrollbars and
judge_timestamp members deleted.
(struct scrollbar): Redesigned to be a template for a Lisp_Vector.
(SCROLLBAR_VEC_SIZE, XSCROLLBAR, SCROLLBAR_PACK, SCROLLBAR_UNPACK,
SCROLLBAR_X_WINDOW, SET_SCROLLBAR_X_WINDOW,
VERTICAL_SCROLLBAR_INSIDE_WIDTH, VERTICAL_SCROLLBAR_TOP_RANGE,
VERTICAL_SCROLLBAR_INSIDE_HEIGHT, VERTICAL_SCROLLBAR_MIN_HANDLE):
New macros, to help deal with the lispy structures, and deal with
the graphics.
* frame.h (WINDOW_VERTICAL_SCROLLBAR): Macro deleted.
(struct frame): New fields `scrollbars' and
`condemned_scrollbars', for use by the scrollbar implementation.
[MULTI_FRAME and not MULTI_FRAME] (FRAME_SCROLLBARS,
FRAME_CONDEMNED_SCROLLBARS): Accessors for the new field.
* window.h (struct window): Doc fix for vertical_scrollbar field.
* frame.c (make_frame): Initialize the `scrollbars' and
`condemned_scrollbars' fields of the new frame.
* alloc.c (mark_object): Mark the `scrollbars' and
`condemned_scrollbars' slots of frames.
* xterm.c (x_window_to_scrollbar): Scrollbars are chained on
frames' scrollbar field, not their x.display->vertical_scrollbars
field.
(x_scrollbar_create, x_scrollbar_set_handle, x_scrollbar_move,
x_scrollbar_remove, XTset_vertical_scrollbar,
XTcondemn_scrollbars, XTredeem_scrollbar, XTjudge_scrollbars,
x_scrollbar_expose, x_scrollbar_handle_click,
x_scrollbar_handle_motion): Substantially rewritten to correct
typos and brainos, and to accomodate the lispy structures.
* xterm.c (x_scrollbar_background_expose): Function deleted; we
don't want anything in the background there after all.
(XTread_socket): Don't call x_scrollbar_background_expose. We
don't care.
* xterm.h (CHAR_TO_PIXEL_WIDTH, CHAR_TO_PIXEL_HEIGHT,
PIXEL_TO_CHAR_WIDTH, PIXEL_TO_CHAR_HEIGHT): Rewritten, using:
(CHAR_TO_PIXEL_ROW, CHAR_TO_PIXEL_COL, PIXEL_TO_CHAR_ROW,
PIXEL_TO_CHAR_COL): New macros.
* xfns.c [not HAVE_X11] (Fx_create_frame): Use the
PIXEL_TO_CHAR_{HEIGHT,WIDTH} macros to figure the frame's
character size, and the CHAR_TO_PIXEL* macros for vice versa.
* xterm.c (XTwrite_glyphs, XTclear_end_of_line, stufflines,
scraplines, dumprectangle, pixel_to_glyph_coords, x_draw_box,
clear_cursor, x_display_bar_cursor, x_draw_single_glyph,
x_set_mouse_position): Use the CHAR_TO_PIXEL_* macros.
* xterm.c (x_wm_set_size_hint): The max_width and max_height
members of the size_hints are expressed in pixels, not columns.
* xterm.c (x_set_window_size): Remove ibw var; it's not used.
Set FRAME_WIDTH (f) to cols instead of rows. Duh.
* xterm.c (pixel_to_glyph_coords): Properly set *bounds to the
character cell bounding the position, even when the position is
off the frame.
* termhooks.h (mouse_position_hook): Doc fix.
(set_vertical_scrollbar_hook): This doesn't return anything any
more, and doesn't take a struct scrollbar * argument any more.
(condemn_scrollbars_hook, redeem_scrollbar_hook,
judge_scrollbars_hook): Doc fixes.
* term.c (mouse_position_hook): Doc fix.
(set_vertical_scrollbar_hook): This doesn't return
anything any more. Doc fixes.
* keyboard.c (kbd_buffer_get_event): Receive the scrollbar's
window from *mouse_position_hook and pass it to
make_lispy_movement, instead of working with a pointer to a struct
scrollbar.
(make_lispy_event): We don't need a window_from_scrollbar function
anymore; we are given the window directly in *EVENT.
Unify the code which generates
text-area mouse clicks and scrollbar clicks; use the same code to
distinguish clicks from drags on the scrollbar as in the text area.
Distinguish clicks from drags by storing a copy of the lispy
position list returned as part of the event.
(button_down_location): Make this a lisp vector, rather than an
array of random structures.
(struct mouse_position): Remove this; it's been replaced by a lisp
list.
(make_lispy_movement): Accept the scrollbar's window as a
parameter, rather than the scrollbar itself.
If FRAME is zero, assume that the other arguments are garbage.
(syms_of_keyboard): No need to staticpro each window of
button_down_location now; just initialize and staticpro it.
* window.c (window_from_scrollbar): Function deleted; no longer
needed.
* xdisp.c (redisplay_window): Just pass the window to
set_vertical_scrollbar hook; don't pass the scrollbar object too.
* xterm.c (XTmouse_position): Don't return a pointer to the
scrollbar for scrollbar motion; instead, return the scrollbar's
window.
* xterm.c (XTmouse_position): Entirely rewritten, using
XTranslateCoordinates. Call x_scrollbar_report_motion to handle
scrollbar movement events.
(x_scrollbar_report_motion): New function, to help out
XTmouse_position.
* termhooks.h (struct input_event): Replace the frame member with
a Lisp_Object member by the name of frame_or_window. Doc fixes.
Remove the scrollbar member; instead, use frame_or_window to hold the
window whose scrollbar was clicked.
* keyboard.c (kbd_buffer_store_event, kbd_buffer_get_event,
make_lispy_event): Adjust references to frame member of struct
input_event to use frame_or_window now.
* xterm.c (construct_mouse_click, XTread_socket): Same.
* xterm.c (last_mouse_bar, last_mouse_bar_frame, last_mouse_part,
last_mouse_scroll_range_start, last_mouse_scroll_range_end):
Replaced with...
(last_mouse_scrollbar): New variable.
(note_mouse_movement): Clear last_mouse_scrollbar when we have
receieved a new motion.
(syms_of_xterm): Staticpro last_mouse_scrollbar.
* xterm.c (note_mouse_position): Renamed to note_mouse_movement,
because that's what it really does.
(x_scrollbar_handle_motion): Renamed to x_scrollbar_note_movement,
for consistency.
(XTread_socket): Adjusted.
* xterm.c (XTset_scrollbar): Renamed to XTset_vertical_scrollbar.
(x_term_init): Adjusted.
* emacs.c (shut_down_emacs): New function.
(fatal_error_signal, Fkill_emacs): Call it, instead of writing it out.
* xterm.c (x_connection_closed): Call shut_down_emacs instead of
Fkill_emacs; the latter will try to perform operations on the X
server and die a horrible death.
* lisp.h (shut_down_emacs): Add extern declaration for it.
* xterm.c (x_error_quitter): Move the abort call to after we print
the error message. No harm in that.
author | Jim Blandy <jimb@redhat.com> |
---|---|
date | Thu, 14 Jan 1993 15:34:14 +0000 |
parents | 79f020f34683 |
children | e7b8107294b7 |
line wrap: on
line source
/* Simple built-in editing commands. Copyright (C) 1985, 1992 Free Software Foundation, Inc. This file is part of GNU Emacs. GNU Emacs is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. GNU Emacs is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GNU Emacs; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "config.h" #include "lisp.h" #include "commands.h" #include "buffer.h" #include "syntax.h" Lisp_Object Qkill_forward_chars, Qkill_backward_chars, Vblink_paren_function; DEFUN ("forward-char", Fforward_char, Sforward_char, 0, 1, "p", "Move point right ARG characters (left if ARG negative).\n\ On reaching end of buffer, stop and signal error.") (n) Lisp_Object n; { if (NILP (n)) XFASTINT (n) = 1; else CHECK_NUMBER (n, 0); SET_PT (point + XINT (n)); if (point < BEGV) { SET_PT (BEGV); Fsignal (Qbeginning_of_buffer, Qnil); } if (point > ZV) { SET_PT (ZV); Fsignal (Qend_of_buffer, Qnil); } return Qnil; } DEFUN ("backward-char", Fbackward_char, Sbackward_char, 0, 1, "p", "Move point left ARG characters (right if ARG negative).\n\ On attempt to pass beginning or end of buffer, stop and signal error.") (n) Lisp_Object n; { if (NILP (n)) XFASTINT (n) = 1; else CHECK_NUMBER (n, 0); XSETINT (n, - XINT (n)); return Fforward_char (n); } DEFUN ("forward-line", Fforward_line, Sforward_line, 0, 1, "p", "Move ARG lines forward (backward if ARG is negative).\n\ Precisely, if point is on line I, move to the start of line I + ARG.\n\ If there isn't room, go as far as possible (no error).\n\ Returns the count of lines left to move. If moving forward,\n\ that is ARG - number of lines moved; if backward, ARG + number moved.\n\ With positive ARG, a non-empty line at the end counts as one line\n\ successfully moved (for the return value).") (n) Lisp_Object n; { int pos2 = point; int pos; int count, shortage, negp; if (NILP (n)) count = 1; else { CHECK_NUMBER (n, 0); count = XINT (n); } negp = count <= 0; pos = scan_buffer ('\n', pos2, count - negp, &shortage); if (shortage > 0 && (negp || (ZV > BEGV && pos != pos2 && FETCH_CHAR (pos - 1) != '\n'))) shortage--; SET_PT (pos); return make_number (negp ? - shortage : shortage); } DEFUN ("beginning-of-line", Fbeginning_of_line, Sbeginning_of_line, 0, 1, "p", "Move point to beginning of current line.\n\ With argument ARG not nil or 1, move forward ARG - 1 lines first.\n\ If scan reaches end of buffer, stop there without error.") (n) Lisp_Object n; { if (NILP (n)) XFASTINT (n) = 1; else CHECK_NUMBER (n, 0); Fforward_line (make_number (XINT (n) - 1)); return Qnil; } DEFUN ("end-of-line", Fend_of_line, Send_of_line, 0, 1, "p", "Move point to end of current line.\n\ With argument ARG not nil or 1, move forward ARG - 1 lines first.\n\ If scan reaches end of buffer, stop there without error.") (n) Lisp_Object n; { register int pos; register int stop; if (NILP (n)) XFASTINT (n) = 1; else CHECK_NUMBER (n, 0); if (XINT (n) != 1) Fforward_line (make_number (XINT (n) - 1)); pos = point; stop = ZV; while (pos < stop && FETCH_CHAR (pos) != '\n') pos++; SET_PT (pos); return Qnil; } DEFUN ("delete-char", Fdelete_char, Sdelete_char, 1, 2, "p\nP", "Delete the following ARG characters (previous, with negative arg).\n\ Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\ Interactively, ARG is the prefix arg, and KILLFLAG is set if\n\ ARG was explicitly specified.") (n, killflag) Lisp_Object n, killflag; { CHECK_NUMBER (n, 0); if (NILP (killflag)) { if (XINT (n) < 0) { if (point + XINT (n) < BEGV) Fsignal (Qbeginning_of_buffer, Qnil); else del_range (point + XINT (n), point); } else { if (point + XINT (n) > ZV) Fsignal (Qend_of_buffer, Qnil); else del_range (point, point + XINT (n)); } } else { call1 (Qkill_forward_chars, n); } return Qnil; } DEFUN ("delete-backward-char", Fdelete_backward_char, Sdelete_backward_char, 1, 2, "p\nP", "Delete the previous ARG characters (following, with negative ARG).\n\ Optional second arg KILLFLAG non-nil means kill instead (save in kill ring).\n\ Interactively, ARG is the prefix arg, and KILLFLAG is set if\n\ ARG was explicitly specified.") (n, killflag) Lisp_Object n, killflag; { CHECK_NUMBER (n, 0); return Fdelete_char (make_number (-XINT (n)), killflag); } DEFUN ("self-insert-command", Fself_insert_command, Sself_insert_command, 1, 1, "p", "Insert the character you type.\n\ Whichever character you type to run this command is inserted.") (arg) Lisp_Object arg; { CHECK_NUMBER (arg, 0); /* Barf if the key that invoked this was not a character. */ if (XTYPE (last_command_char) != Lisp_Int) bitch_at_user (); else while (XINT (arg) > 0) { XFASTINT (arg)--; /* Ok since old and new vals both nonneg */ internal_self_insert (XINT (last_command_char), XFASTINT (arg) != 0); } return Qnil; } DEFUN ("newline", Fnewline, Snewline, 0, 1, "P", "Insert a newline. With arg, insert that many newlines.\n\ In Auto Fill mode, if no numeric arg, break the preceding line if it's long.") (arg1) Lisp_Object arg1; { int flag; Lisp_Object arg; char c1 = '\n'; arg = Fprefix_numeric_value (arg1); if (!NILP (current_buffer->read_only)) Fsignal (Qbuffer_read_only, Qnil); /* Inserting a newline at the end of a line produces better redisplay in try_window_id than inserting at the ebginning fo a line, And the textual result is the same. So if at beginning, pretend to be at the end. Must avoid internal_self_insert in that case since point is wrong. Luckily internal_self_insert's special features all do nothing in that case. */ flag = point > BEGV && FETCH_CHAR (point - 1) == '\n'; if (flag) SET_PT (point - 1); while (XINT (arg) > 0) { if (flag) insert (&c1, 1); else internal_self_insert ('\n', !NILP (arg1)); XFASTINT (arg)--; /* Ok since old and new vals both nonneg */ } if (flag) SET_PT (point + 1); return Qnil; } /* Insert character C1. If NOAUTOFILL is nonzero, don't do autofill even if it is enabled. If this insertion is suitable for direct output (completely simple), return 0. A value of 1 indicates this *might* not have been simple. */ internal_self_insert (c1, noautofill) char c1; int noautofill; { extern Lisp_Object Fexpand_abbrev (); int hairy = 0; Lisp_Object tem; register enum syntaxcode synt; register int c = c1; if (!NILP (Vbefore_change_function) || !NILP (Vafter_change_function)) hairy = 1; if (!NILP (current_buffer->overwrite_mode) && point < ZV && c != '\n' && FETCH_CHAR (point) != '\n' && (FETCH_CHAR (point) != '\t' || XINT (current_buffer->tab_width) <= 0 || !((current_column () + 1) % XFASTINT (current_buffer->tab_width)))) { del_range (point, point + 1); hairy = 1; } if (!NILP (current_buffer->abbrev_mode) && SYNTAX (c) != Sword && NILP (current_buffer->read_only) && point > BEGV && SYNTAX (FETCH_CHAR (point - 1)) == Sword) { int modiff = MODIFF; Fexpand_abbrev (); /* We can't trust the value of Fexpand_abbrev, but if Fexpand_abbrev changed the buffer, assume it expanded something. */ if (MODIFF != modiff) hairy = 1; } if ((c == ' ' || c == '\n') && !noautofill && !NILP (current_buffer->auto_fill_function) && current_column () > XFASTINT (current_buffer->fill_column)) { if (c1 != '\n') insert (&c1, 1); call0 (current_buffer->auto_fill_function); if (c1 == '\n') insert (&c1, 1); hairy = 1; } else insert (&c1, 1); synt = SYNTAX (c); if ((synt == Sclose || synt == Smath) && !NILP (Vblink_paren_function) && INTERACTIVE) { call0 (Vblink_paren_function); hairy = 1; } return hairy; } /* module initialization */ syms_of_cmds () { Qkill_backward_chars = intern ("kill-backward-chars"); staticpro (&Qkill_backward_chars); Qkill_forward_chars = intern ("kill-forward-chars"); staticpro (&Qkill_forward_chars); DEFVAR_LISP ("blink-paren-function", &Vblink_paren_function, "Function called, if non-nil, whenever a close parenthesis is inserted.\n\ More precisely, a char with closeparen syntax is self-inserted."); Vblink_paren_function = Qnil; defsubr (&Sforward_char); defsubr (&Sbackward_char); defsubr (&Sforward_line); defsubr (&Sbeginning_of_line); defsubr (&Send_of_line); defsubr (&Sdelete_char); defsubr (&Sdelete_backward_char); defsubr (&Sself_insert_command); defsubr (&Snewline); } keys_of_cmds () { int n; initial_define_key (global_map, Ctl('M'), "newline"); initial_define_key (global_map, Ctl('I'), "self-insert-command"); for (n = 040; n < 0177; n++) initial_define_key (global_map, n, "self-insert-command"); initial_define_key (global_map, Ctl ('A'), "beginning-of-line"); initial_define_key (global_map, Ctl ('B'), "backward-char"); initial_define_key (global_map, Ctl ('D'), "delete-char"); initial_define_key (global_map, Ctl ('E'), "end-of-line"); initial_define_key (global_map, Ctl ('F'), "forward-char"); initial_define_key (global_map, 0177, "delete-backward-char"); }