Mercurial > emacs
comparison src/xterm.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 | d738d3690836 |
children | cf4c3f01ddb9 |
comparison
equal
deleted
inserted
replaced
1786:5179baee010b | 1787:5e245540d06f |
---|---|
1 /* X Communication module for terminals which understand the X protocol. | 1 /* X Communication module for terminals which understand the X protocol. |
2 Copyright (C) 1989, 1992 Free Software Foundation, Inc. | 2 Copyright (C) 1989, 1992, 1993 Free Software Foundation, Inc. |
3 | 3 |
4 This file is part of GNU Emacs. | 4 This file is part of GNU Emacs. |
5 | 5 |
6 GNU Emacs is free software; you can redistribute it and/or modify | 6 GNU Emacs is free software; you can redistribute it and/or modify |
7 it under the terms of the GNU General Public License as published by | 7 it under the terms of the GNU General Public License as published by |
569 curs_x = f->cursor_x; | 569 curs_x = f->cursor_x; |
570 curs_y = f->cursor_y; | 570 curs_y = f->cursor_y; |
571 } | 571 } |
572 | 572 |
573 dumpglyphs (f, | 573 dumpglyphs (f, |
574 (curs_x * FONT_WIDTH (f->display.x->font) | 574 CHAR_TO_PIXEL_COL (f, curs_x), |
575 + f->display.x->internal_border_width), | 575 CHAR_TO_PIXEL_ROW (f, curs_y), |
576 (curs_y * FONT_HEIGHT (f->display.x->font) | 576 start, len, highlight, f->display.x->font); |
577 + f->display.x->internal_border_width), | |
578 start, len, highlight, f->display.x->font); | |
579 | 577 |
580 /* If we drew on top of the cursor, note that it is turned off. */ | 578 /* If we drew on top of the cursor, note that it is turned off. */ |
581 if (curs_y == f->phys_cursor_y | 579 if (curs_y == f->phys_cursor_y |
582 && curs_x <= f->phys_cursor_x | 580 && curs_x <= f->phys_cursor_x |
583 && curs_x + len > f->phys_cursor_x) | 581 && curs_x + len > f->phys_cursor_x) |
626 && f->phys_cursor_x < first_unused) | 624 && f->phys_cursor_x < first_unused) |
627 f->phys_cursor_x = -1; | 625 f->phys_cursor_x = -1; |
628 | 626 |
629 #ifdef HAVE_X11 | 627 #ifdef HAVE_X11 |
630 XClearArea (x_current_display, FRAME_X_WINDOW (f), | 628 XClearArea (x_current_display, FRAME_X_WINDOW (f), |
631 curs_x * FONT_WIDTH (f->display.x->font) | 629 CHAR_TO_PIXEL_COL (f, curs_x), |
632 + f->display.x->internal_border_width, | 630 CHAR_TO_PIXEL_ROW (f, curs_y), |
633 curs_y * FONT_HEIGHT (f->display.x->font) | |
634 + f->display.x->internal_border_width, | |
635 FONT_WIDTH (f->display.x->font) * (first_unused - curs_x), | 631 FONT_WIDTH (f->display.x->font) * (first_unused - curs_x), |
636 FONT_HEIGHT (f->display.x->font), False); | 632 FONT_HEIGHT (f->display.x->font), False); |
637 | 633 |
638 #else /* ! defined (HAVE_X11) */ | 634 #else /* ! defined (HAVE_X11) */ |
639 XPixSet (FRAME_X_WINDOW (f), | 635 XPixSet (FRAME_X_WINDOW (f), |
640 curs_x * FONT_WIDTH (f->display.x->font) + f->display.x->internal_border_width, | 636 CHAR_TO_PIXEL_COL (f, curs_x), |
641 curs_y * FONT_HEIGHT (f->display.x->font) + f->display.x->internal_border_width, | 637 CHAR_TO_PIXEL_ROW (f, curs_y), |
642 FONT_WIDTH (f->display.x->font) * (first_unused - curs_x), | 638 FONT_WIDTH (f->display.x->font) * (first_unused - curs_x), |
643 FONT_HEIGHT (f->display.x->font), | 639 FONT_HEIGHT (f->display.x->font), |
644 f->display.x->background_pixel); | 640 f->display.x->background_pixel); |
645 #endif /* ! defined (HAVE_X11) */ | 641 #endif /* ! defined (HAVE_X11) */ |
646 | 642 |
841 if ((length > 0) && (newtop <= flexlines)) | 837 if ((length > 0) && (newtop <= flexlines)) |
842 { | 838 { |
843 #ifdef HAVE_X11 | 839 #ifdef HAVE_X11 |
844 XCopyArea (x_current_display, FRAME_X_WINDOW (f), | 840 XCopyArea (x_current_display, FRAME_X_WINDOW (f), |
845 FRAME_X_WINDOW (f), f->display.x->normal_gc, | 841 FRAME_X_WINDOW (f), f->display.x->normal_gc, |
846 intborder, topregion * FONT_HEIGHT (f->display.x->font) + intborder, | 842 intborder, CHAR_TO_PIXEL_ROW (f, topregion), |
847 f->width * FONT_WIDTH (f->display.x->font), | 843 f->width * FONT_WIDTH (f->display.x->font), |
848 length * FONT_HEIGHT (f->display.x->font), intborder, | 844 length * FONT_HEIGHT (f->display.x->font), intborder, |
849 newtop * FONT_HEIGHT (f->display.x->font) + intborder); | 845 CHAR_TO_PIXEL_ROW (f, newtop)); |
850 #else /* ! defined (HAVE_X11) */ | 846 #else /* ! defined (HAVE_X11) */ |
851 XMoveArea (FRAME_X_WINDOW (f), | 847 XMoveArea (FRAME_X_WINDOW (f), |
852 intborder, topregion * FONT_HEIGHT (f->display.x->font) + intborder, | 848 intborder, CHAR_TO_PIXEL_ROW (f, topregion), |
853 intborder, newtop * FONT_HEIGHT (f->display.x->font) + intborder, | 849 intborder, CHAR_TO_PIXEL_ROW (f, newtop), |
854 f->width * FONT_WIDTH (f->display.x->font), | 850 f->width * FONT_WIDTH (f->display.x->font), |
855 length * FONT_HEIGHT (f->display.x->font)); | 851 length * FONT_HEIGHT (f->display.x->font)); |
856 /* Now we must process any ExposeRegion events that occur | 852 /* Now we must process any ExposeRegion events that occur |
857 if the area being copied from is obscured. | 853 if the area being copied from is obscured. |
858 We can't let it wait because further i/d operations | 854 We can't let it wait because further i/d operations |
865 length = newtop - topregion; | 861 length = newtop - topregion; |
866 if (length > 0) | 862 if (length > 0) |
867 { | 863 { |
868 #ifdef HAVE_X11 | 864 #ifdef HAVE_X11 |
869 XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder, | 865 XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder, |
870 topregion * FONT_HEIGHT (f->display.x->font) + intborder, | 866 CHAR_TO_PIXEL_ROW (f, topregion), |
871 f->width * FONT_WIDTH (f->display.x->font), | 867 f->width * FONT_WIDTH (f->display.x->font), |
872 n * FONT_HEIGHT (f->display.x->font), False); | 868 n * FONT_HEIGHT (f->display.x->font), False); |
873 #else /* ! defined (HAVE_X11) */ | 869 #else /* ! defined (HAVE_X11) */ |
874 XPixSet (FRAME_X_WINDOW (f), | 870 XPixSet (FRAME_X_WINDOW (f), |
875 intborder, | 871 intborder, |
876 topregion * FONT_HEIGHT (f->display.x->font) + intborder, | 872 CHAR_TO_PIXEL_ROW (f, topregion), |
877 f->width * FONT_WIDTH (f->display.x->font), | 873 f->width * FONT_WIDTH (f->display.x->font), |
878 n * FONT_HEIGHT (f->display.x->font), | 874 n * FONT_HEIGHT (f->display.x->font), |
879 f->display.x->background_pixel); | 875 f->display.x->background_pixel); |
880 #endif /* ! defined (HAVE_X11) */ | 876 #endif /* ! defined (HAVE_X11) */ |
881 } | 877 } |
903 { | 899 { |
904 if (flexlines >= (curs_y + 1)) | 900 if (flexlines >= (curs_y + 1)) |
905 { | 901 { |
906 #ifdef HAVE_X11 | 902 #ifdef HAVE_X11 |
907 XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder, | 903 XClearArea (x_current_display, FRAME_X_WINDOW (f), intborder, |
908 curs_y * FONT_HEIGHT (f->display.x->font) + intborder, | 904 CHAR_TO_PIXEL_ROW (f, curs_y), |
909 f->width * FONT_WIDTH (f->display.x->font), | 905 f->width * FONT_WIDTH (f->display.x->font), |
910 (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font), False); | 906 (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font), False); |
911 #else /* ! defined (HAVE_X11) */ | 907 #else /* ! defined (HAVE_X11) */ |
912 XPixSet (FRAME_X_WINDOW (f), | 908 XPixSet (FRAME_X_WINDOW (f), |
913 intborder, curs_y * FONT_HEIGHT (f->display.x->font) + intborder, | 909 intborder, CHAR_TO_PIXEL_ROW (f, curs_y), |
914 f->width * FONT_WIDTH (f->display.x->font), | 910 f->width * FONT_WIDTH (f->display.x->font), |
915 (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font), | 911 (flexlines - curs_y) * FONT_HEIGHT (f->display.x->font), |
916 f->display.x->background_pixel); | 912 f->display.x->background_pixel); |
917 #endif /* ! defined (HAVE_X11) */ | 913 #endif /* ! defined (HAVE_X11) */ |
918 } | 914 } |
921 { | 917 { |
922 #ifdef HAVE_X11 | 918 #ifdef HAVE_X11 |
923 XCopyArea (x_current_display, FRAME_X_WINDOW (f), | 919 XCopyArea (x_current_display, FRAME_X_WINDOW (f), |
924 FRAME_X_WINDOW (f), f->display.x->normal_gc, | 920 FRAME_X_WINDOW (f), f->display.x->normal_gc, |
925 intborder, | 921 intborder, |
926 (curs_y + n) * FONT_HEIGHT (f->display.x->font) + intborder, | 922 CHAR_TO_PIXEL_ROW (f, curs_y + n), |
927 f->width * FONT_WIDTH (f->display.x->font), | 923 f->width * FONT_WIDTH (f->display.x->font), |
928 (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font), | 924 (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font), |
929 intborder, curs_y * FONT_HEIGHT (f->display.x->font) + intborder); | 925 intborder, CHAR_TO_PIXEL_ROW (f, curs_y)); |
930 XClearArea (x_current_display, FRAME_X_WINDOW (f), | 926 XClearArea (x_current_display, FRAME_X_WINDOW (f), |
931 intborder, | 927 intborder, |
932 (flexlines - n) * FONT_HEIGHT (f->display.x->font) + intborder, | 928 CHAR_TO_PIXEL_ROW (f, flexlines - n), |
933 f->width * FONT_WIDTH (f->display.x->font), | 929 f->width * FONT_WIDTH (f->display.x->font), |
934 n * FONT_HEIGHT (f->display.x->font), False); | 930 n * FONT_HEIGHT (f->display.x->font), False); |
935 #else /* ! defined (HAVE_X11) */ | 931 #else /* ! defined (HAVE_X11) */ |
936 XMoveArea (FRAME_X_WINDOW (f), | 932 XMoveArea (FRAME_X_WINDOW (f), |
937 intborder, | 933 intborder, |
938 (curs_y + n) * FONT_HEIGHT (f->display.x->font) + intborder, | 934 CHAR_TO_PIXEL_ROW (f, curs_y + n), |
939 intborder, curs_y * FONT_HEIGHT (f->display.x->font) + intborder, | 935 intborder, CHAR_TO_PIXEL_ROW (f, curs_y), |
940 f->width * FONT_WIDTH (f->display.x->font), | 936 f->width * FONT_WIDTH (f->display.x->font), |
941 (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font)); | 937 (flexlines - (curs_y + n)) * FONT_HEIGHT (f->display.x->font)); |
942 /* Now we must process any ExposeRegion events that occur | 938 /* Now we must process any ExposeRegion events that occur |
943 if the area being copied from is obscured. | 939 if the area being copied from is obscured. |
944 We can't let it wait because further i/d operations | 940 We can't let it wait because further i/d operations |
945 may want to copy this area to another area. */ | 941 may want to copy this area to another area. */ |
946 x_read_exposes (); | 942 x_read_exposes (); |
947 XPixSet (FRAME_X_WINDOW (f), intborder, | 943 XPixSet (FRAME_X_WINDOW (f), intborder, |
948 (flexlines - n) * FONT_HEIGHT (f->display.x->font) + intborder, | 944 CHAR_TO_PIXEL_ROW (f, flexlines - n), |
949 f->width * FONT_WIDTH (f->display.x->font), | 945 f->width * FONT_WIDTH (f->display.x->font), |
950 n * FONT_HEIGHT (f->display.x->font), f->display.x->background_pixel); | 946 n * FONT_HEIGHT (f->display.x->font), f->display.x->background_pixel); |
951 #endif /* ! defined (HAVE_X11) */ | 947 #endif /* ! defined (HAVE_X11) */ |
952 } | 948 } |
953 } | 949 } |
994 register int y; | 990 register int y; |
995 | 991 |
996 if (FRAME_GARBAGED_P (f)) | 992 if (FRAME_GARBAGED_P (f)) |
997 return; | 993 return; |
998 | 994 |
999 top -= f->display.x->internal_border_width; | |
1000 left -= f->display.x->internal_border_width; | |
1001 | |
1002 /* Express rectangle as four edges, instead of position-and-size. */ | 995 /* Express rectangle as four edges, instead of position-and-size. */ |
1003 bottom = top + rows; | 996 bottom = top + rows; |
1004 right = left + cols; | 997 right = left + cols; |
1005 | 998 |
1006 #ifndef HAVE_X11 /* Window manger does this for X11. */ | 999 #ifndef HAVE_X11 /* Window manger does this for X11. */ |
1007 /* If the rectangle includes any of the internal border area, | 1000 { |
1008 redisplay the border emphasis. */ | 1001 int intborder = f->display.x->internal_border_width; |
1009 if (top < 0 || left < 0 | 1002 |
1010 || bottom > f->height * FONT_HEIGHT (f->display.x->font) | 1003 /* If the rectangle includes any of the internal border area, |
1011 || right > f->width * FONT_WIDTH (f->display.x->font)) | 1004 redisplay the border emphasis. */ |
1012 dumpborder (f, 0); | 1005 if (top < intborder || left < intborder |
1006 || bottom > intborder + f->height * FONT_HEIGHT (f->display.x->font) | |
1007 || right > intborder + f->width * FONT_WIDTH (f->display.x->font)) | |
1008 dumpborder (f, 0); | |
1009 } | |
1013 #endif /* HAVE_X11 /* Window manger does this for X11. */ */ | 1010 #endif /* HAVE_X11 /* Window manger does this for X11. */ */ |
1014 | 1011 |
1015 /* Convert rectangle edges in pixels to edges in chars. | 1012 /* Convert rectangle edges in pixels to edges in chars. |
1016 Round down for left and top, up for right and bottom. */ | 1013 Round down for left and top, up for right and bottom. */ |
1017 top /= FONT_HEIGHT (f->display.x->font); | 1014 top = PIXEL_TO_CHAR_ROW (f, top); |
1018 left /= FONT_WIDTH (f->display.x->font); | 1015 left = PIXEL_TO_CHAR_COL (f, left); |
1019 bottom += (FONT_HEIGHT (f->display.x->font) - 1); | 1016 bottom += (FONT_HEIGHT (f->display.x->font) - 1); |
1020 right += (FONT_WIDTH (f->display.x->font) - 1); | 1017 right += (FONT_WIDTH (f->display.x->font) - 1); |
1021 bottom /= FONT_HEIGHT (f->display.x->font); | 1018 bottom = PIXEL_TO_CHAR_ROW (f, bottom); |
1022 right /= FONT_WIDTH (f->display.x->font); | 1019 right = PIXEL_TO_CHAR_COL (f, right); |
1023 | 1020 |
1024 /* Clip the rectangle to what can be visible. */ | 1021 /* Clip the rectangle to what can be visible. */ |
1025 if (left < 0) | 1022 if (left < 0) |
1026 left = 0; | 1023 left = 0; |
1027 if (top < 0) | 1024 if (top < 0) |
1056 | 1053 |
1057 if (! active_frame->enable[y] || left > active_frame->used[y]) | 1054 if (! active_frame->enable[y] || left > active_frame->used[y]) |
1058 continue; | 1055 continue; |
1059 | 1056 |
1060 dumpglyphs (f, | 1057 dumpglyphs (f, |
1061 (left * FONT_WIDTH (f->display.x->font) | 1058 CHAR_TO_PIXEL_COL (f, left), |
1062 + f->display.x->internal_border_width), | 1059 CHAR_TO_PIXEL_ROW (f, y), |
1063 (y * FONT_HEIGHT (f->display.x->font) | 1060 line, min (cols, active_frame->used[y] - left), |
1064 + f->display.x->internal_border_width), | 1061 active_frame->highlight[y], f->display.x->font); |
1065 line, min (cols, active_frame->used[y] - left), | |
1066 active_frame->highlight[y], f->display.x->font); | |
1067 } | 1062 } |
1068 | 1063 |
1069 /* Turn the cursor on if we turned it off. */ | 1064 /* Turn the cursor on if we turned it off. */ |
1070 | 1065 |
1071 if (cursor_cleared) | 1066 if (cursor_cleared) |
1311 FRAME_PTR f; | 1306 FRAME_PTR f; |
1312 register unsigned int pix_x, pix_y; | 1307 register unsigned int pix_x, pix_y; |
1313 register int *x, *y; | 1308 register int *x, *y; |
1314 XRectangle *bounds; | 1309 XRectangle *bounds; |
1315 { | 1310 { |
1316 int ibw = f->display.x->internal_border_width; | 1311 pix_x = PIXEL_TO_CHAR_COL (f, pix_x); |
1317 int width, height; | 1312 pix_y = PIXEL_TO_CHAR_ROW (f, pix_y); |
1318 FONT_TYPE *font = f->display.x->font; | |
1319 | |
1320 width = FONT_WIDTH (font); | |
1321 height = FONT_HEIGHT (font); | |
1322 | |
1323 /* What line is it on? */ | |
1324 if (pix_y < ibw) | |
1325 *y = 0; | |
1326 else if (pix_y > f->display.x->pixel_height - ibw) | |
1327 *y = FRAME_HEIGHT (f) - 1; | |
1328 else | |
1329 *y = (pix_y - ibw) / height; | |
1330 | |
1331 /* And what column? */ | |
1332 if (pix_x < ibw) | |
1333 *x = 0; | |
1334 else if (pix_x > f->display.x->pixel_width - ibw) | |
1335 *x = FRAME_WIDTH (f) - 1; | |
1336 else | |
1337 *x = (pix_x - ibw) / width; | |
1338 | 1313 |
1339 if (bounds) | 1314 if (bounds) |
1340 { | 1315 { |
1341 bounds->width = width; | 1316 bounds->width = FONT_WIDTH (f->display.x->font); |
1342 bounds->height = height; | 1317 bounds->height = FONT_HEIGHT (f->display.x->font); |
1343 bounds->x = ibw + (*x * width); | 1318 bounds->x = CHAR_TO_PIXEL_COL (f, pix_x); |
1344 bounds->y = ibw + (*y * height); | 1319 bounds->y = CHAR_TO_PIXEL_ROW (f, pix_y); |
1345 } | 1320 } |
1321 | |
1322 if (pix_x < 0) pix_x = 0; | |
1323 else if (pix_x > f->width) pix_x = f->width; | |
1324 | |
1325 if (pix_y < 0) pix_y = 0; | |
1326 else if (pix_y > f->height) pix_y = f->height; | |
1327 | |
1328 *x = pix_x; | |
1329 *y = pix_y; | |
1346 } | 1330 } |
1347 | 1331 |
1348 /* Any buttons grabbed. */ | 1332 /* Any buttons grabbed. */ |
1349 unsigned int x_mouse_grabbed; | 1333 unsigned int x_mouse_grabbed; |
1350 | 1334 |
1490 int row, column; | 1474 int row, column; |
1491 | 1475 |
1492 pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL); | 1476 pixel_to_glyph_coords (f, event->x, event->y, &column, &row, NULL); |
1493 XFASTINT (result->x) = column; | 1477 XFASTINT (result->x) = column; |
1494 XFASTINT (result->y) = row; | 1478 XFASTINT (result->y) = row; |
1495 result->frame = f; | 1479 XSET (result->frame_or_window, Lisp_Frame, f); |
1496 } | 1480 } |
1497 } | 1481 } |
1498 | 1482 |
1499 | 1483 |
1500 /* Mouse movement. Rah. | 1484 /* Mouse movement. Rah. |
1518 | 1502 |
1519 /* Where the mouse was last time we reported a mouse event. */ | 1503 /* Where the mouse was last time we reported a mouse event. */ |
1520 static FRAME_PTR last_mouse_frame; | 1504 static FRAME_PTR last_mouse_frame; |
1521 static XRectangle last_mouse_glyph; | 1505 static XRectangle last_mouse_glyph; |
1522 | 1506 |
1523 /* If the last-checked mouse motion was in a scrollbar, this is that | 1507 /* The scrollbar in which the last X motion event occurred. |
1524 scrollbar, the part being dragged, and the limits it is moving in. | 1508 |
1525 Otherwise, this is zero. */ | 1509 If the last X motion event occured in a scrollbar, we set this |
1526 static struct scrollbar *last_mouse_bar; | 1510 so XTmouse_position can know whether to report a scrollbar motion or |
1527 static FRAME_PTR last_mouse_bar_frame; | 1511 an ordinary motion. |
1528 static enum scrollbar_part last_mouse_part; | 1512 |
1529 static int last_mouse_scroll_range_start; | 1513 If the last X motion event didn't occur in a scrollbar, we set this |
1530 static int last_mouse_scroll_range_end; | 1514 to Qnil, to tell XTmouse_position to return an ordinary motion event. */ |
1515 static Lisp_Object last_mouse_scrollbar; | |
1531 | 1516 |
1532 /* This is a hack. We would really prefer that XTmouse_position would | 1517 /* This is a hack. We would really prefer that XTmouse_position would |
1533 return the time associated with the position it returns, but there | 1518 return the time associated with the position it returns, but there |
1534 doesn't seem to be any way to wrest the timestamp from the server | 1519 doesn't seem to be any way to wrest the timestamp from the server |
1535 along with the position query. So, we just keep track of the time | 1520 along with the position query. So, we just keep track of the time |
1543 We have received a mouse movement event, which is given in *event. | 1528 We have received a mouse movement event, which is given in *event. |
1544 If the mouse is over a different glyph than it was last time, tell | 1529 If the mouse is over a different glyph than it was last time, tell |
1545 the mainstream emacs code by setting mouse_moved. If not, ask for | 1530 the mainstream emacs code by setting mouse_moved. If not, ask for |
1546 another motion event, so we can check again the next time it moves. */ | 1531 another motion event, so we can check again the next time it moves. */ |
1547 static void | 1532 static void |
1548 note_mouse_position (frame, event) | 1533 note_mouse_movement (frame, event) |
1549 FRAME_PTR frame; | 1534 FRAME_PTR frame; |
1550 XMotionEvent *event; | 1535 XMotionEvent *event; |
1551 | 1536 |
1552 { | 1537 { |
1553 last_mouse_movement_time = event->time; | 1538 last_mouse_movement_time = event->time; |
1555 /* Has the mouse moved off the glyph it was on at the last sighting? */ | 1540 /* Has the mouse moved off the glyph it was on at the last sighting? */ |
1556 if (event->x < last_mouse_glyph.x | 1541 if (event->x < last_mouse_glyph.x |
1557 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width | 1542 || event->x >= last_mouse_glyph.x + last_mouse_glyph.width |
1558 || event->y < last_mouse_glyph.y | 1543 || event->y < last_mouse_glyph.y |
1559 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height) | 1544 || event->y >= last_mouse_glyph.y + last_mouse_glyph.height) |
1560 mouse_moved = 1; | 1545 { |
1546 mouse_moved = 1; | |
1547 last_mouse_scrollbar = Qnil; | |
1548 } | |
1561 else | 1549 else |
1562 { | 1550 { |
1563 /* It's on the same glyph. Call XQueryPointer so we'll get an | 1551 /* It's on the same glyph. Call XQueryPointer so we'll get an |
1564 event the next time the mouse moves and we can see if it's | 1552 event the next time the mouse moves and we can see if it's |
1565 *still* on the same glyph. */ | 1553 *still* on the same glyph. */ |
1570 &dummy, &dummy, &dummy, &dummy, | 1558 &dummy, &dummy, &dummy, &dummy, |
1571 (unsigned int *) &dummy); | 1559 (unsigned int *) &dummy); |
1572 } | 1560 } |
1573 } | 1561 } |
1574 | 1562 |
1563 static struct scrollbar *x_window_to_scrollbar (); | |
1564 static void x_scrollbar_report_motion (); | |
1565 | |
1575 /* Return the current position of the mouse. | 1566 /* Return the current position of the mouse. |
1576 | 1567 |
1568 If the mouse movement started in a scrollbar, set *f, *bar_window, | |
1569 and *part to the frame, window, and scrollbar part that the mouse | |
1570 is over. Set *x and *y to the portion and whole of the mouse's | |
1571 position on the scrollbar. | |
1572 | |
1573 If the mouse movement started elsewhere, set *f to the frame the | |
1574 mouse is on, *bar_window to nil, and *x and *y to the character cell | |
1575 the mouse is over. | |
1576 | |
1577 Set *time to the server timestamp for the time at which the mouse | |
1578 was at this position. | |
1579 | |
1577 This clears the mouse_moved flag, so we can wait for the next mouse | 1580 This clears the mouse_moved flag, so we can wait for the next mouse |
1578 position. This also calls XQueryPointer, which will cause the | 1581 movement. This also calls XQueryPointer, which will cause the |
1579 server to give us another MotionNotify when the mouse moves again. | 1582 server to give us another MotionNotify when the mouse moves |
1580 */ | 1583 again. */ |
1581 | 1584 |
1582 static void | 1585 static void |
1583 XTmouse_position (f, bar, part, x, y, time) | 1586 XTmouse_position (f, bar_window, part, x, y, time) |
1584 FRAME_PTR *f; | 1587 FRAME_PTR *f; |
1585 struct scrollbar **bar; | 1588 Lisp_Object *bar_window; |
1586 enum scrollbar_part *part; | 1589 enum scrollbar_part *part; |
1587 Lisp_Object *x, *y; | 1590 Lisp_Object *x, *y; |
1588 unsigned long *time; | 1591 unsigned long *time; |
1589 { | 1592 { |
1590 int ix, iy, dummy; | |
1591 Display *d = x_current_display; | |
1592 Window guess, root, child; | |
1593 | |
1594 BLOCK_INPUT; | 1593 BLOCK_INPUT; |
1595 | 1594 |
1596 /* I would like to have an X function that just told me the | 1595 if (! NILP (last_mouse_scrollbar)) |
1597 innermost window containing the mouse. | 1596 x_scrollbar_report_motion (f, bar_window, part, x, y, time); |
1598 | 1597 else |
1599 /* There doesn't seem to be any way to just get the innermost window | 1598 { |
1600 containing the pointer, no matter what X frame it's on; you have | 1599 Window root; |
1601 to guess a window, and then X will tell you which one of that | 1600 int root_x, root_y; |
1602 window's children it's in. If the pointer isn't in any of that | 1601 |
1603 window's children, it gives you a root window that contains it. | 1602 Window dummy_window; |
1604 | 1603 int dummy; |
1605 So we start with the selected frame's window and chase down | 1604 |
1606 branches under the guidance of XQueryPointer until we hit a leaf | 1605 mouse_moved = 0; |
1607 (all of the Emacs windows we care about are leaf windows). If at | 1606 last_mouse_scrollbar = Qnil; |
1608 any time XQueryPointer returns false, that means that the current | 1607 |
1609 window does not contain the pointer any more (perhaps it moved), | 1608 /* Figure out which root window we're on. */ |
1610 so we start with the root window XQueryPointer has given us and | 1609 XQueryPointer (x_current_display, |
1611 start again. */ | 1610 DefaultRootWindow (x_current_display), |
1612 | 1611 |
1613 guess = FRAME_X_WINDOW (selected_frame); | 1612 /* The root window which contains the pointer. */ |
1614 for (;;) | 1613 &root, |
1615 if (XQueryPointer (d, guess, &root, &child, | 1614 |
1616 &dummy, &dummy, &ix, &iy, (unsigned int *) &dummy)) | 1615 /* Trash which we can't trust if the pointer is on |
1616 a different screen. */ | |
1617 &dummy_window, | |
1618 | |
1619 /* The position on that root window. */ | |
1620 &root_x, &root_y, | |
1621 | |
1622 /* More trash we can't trust. */ | |
1623 &dummy, &dummy, | |
1624 | |
1625 /* Modifier keys and pointer buttons, about which | |
1626 we don't care. */ | |
1627 (unsigned int *) &dummy); | |
1628 | |
1629 /* Now we have a position on the root; find the innermost window | |
1630 containing the pointer. */ | |
1617 { | 1631 { |
1618 if (child == None) | 1632 Window win, child; |
1619 /* Guess is a leaf window, and it contains the pointer. */ | 1633 int win_x, win_y; |
1620 break; | 1634 int parent_x, parent_y; |
1621 else | 1635 |
1622 guess = child; | 1636 win = root; |
1637 for (;;) | |
1638 { | |
1639 XTranslateCoordinates (x_current_display, | |
1640 | |
1641 /* From-window, to-window. */ | |
1642 root, win, | |
1643 | |
1644 /* From-position, to-position. */ | |
1645 root_x, root_y, &win_x, &win_y, | |
1646 | |
1647 /* Child of win. */ | |
1648 &child); | |
1649 | |
1650 if (child == None) | |
1651 break; | |
1652 | |
1653 win = child; | |
1654 parent_x = win_x; | |
1655 parent_y = win_y; | |
1656 } | |
1657 | |
1658 /* Now we know that: | |
1659 win is the innermost window containing the pointer | |
1660 (XTC says it has no child containing the pointer), | |
1661 win_x and win_y are the pointer's position in it | |
1662 (XTC did this the last time through), and | |
1663 parent_x and parent_y are the pointer's position in win's parent. | |
1664 (They are what win_x and win_y were when win was child. | |
1665 If win is the root window, it has no parent, and | |
1666 parent_{x,y} are invalid, but that's okay, because we'll | |
1667 never use them in that case.) */ | |
1668 | |
1669 /* Is win one of our frames? */ | |
1670 *f = x_window_to_frame (win); | |
1671 | |
1672 /* If not, is it one of our scrollbars? */ | |
1673 if (! *f) | |
1674 { | |
1675 struct scrollbar *bar = x_window_to_scrollbar (win); | |
1676 | |
1677 if (bar) | |
1678 { | |
1679 *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); | |
1680 win_x = parent_x; | |
1681 win_y = parent_y; | |
1682 } | |
1683 } | |
1684 | |
1685 if (*f) | |
1686 { | |
1687 pixel_to_glyph_coords (*f, win_x, win_y, &win_x, &win_y, | |
1688 &last_mouse_glyph); | |
1689 | |
1690 *bar_window = Qnil; | |
1691 *part = 0; | |
1692 XSET (*x, Lisp_Int, win_x); | |
1693 XSET (*y, Lisp_Int, win_y); | |
1694 *time = last_mouse_movement_time; | |
1695 } | |
1623 } | 1696 } |
1624 else | 1697 } |
1625 /* When XQueryPointer returns False, the pointer isn't in guess | |
1626 anymore, but root is the root window of the frame we should | |
1627 try instead. */ | |
1628 guess = root; | |
1629 | |
1630 if (last_mouse_bar) | |
1631 { | |
1632 *f = last_mouse_bar_frame; | |
1633 *bar = last_mouse_bar; | |
1634 *part = last_mouse_part; | |
1635 | |
1636 if (iy < last_mouse_scroll_range_start) | |
1637 iy = last_mouse_scroll_range_start; | |
1638 if (iy > last_mouse_scroll_range_end) | |
1639 iy = last_mouse_scroll_range_end; | |
1640 XSETINT (*x, iy - last_mouse_scroll_range_start); | |
1641 XSETINT (*y, (last_mouse_scroll_range_end | |
1642 - last_mouse_scroll_range_start)); | |
1643 } | |
1644 else | |
1645 { | |
1646 *f = last_mouse_frame = x_window_to_frame (guess); | |
1647 if (! *f) | |
1648 *x = *y = Qnil; | |
1649 else | |
1650 { | |
1651 pixel_to_glyph_coords (*f, ix, iy, &ix, &iy, &last_mouse_glyph); | |
1652 XSET (*x, Lisp_Int, ix); | |
1653 XSET (*y, Lisp_Int, iy); | |
1654 } | |
1655 } | |
1656 | |
1657 mouse_moved = 0; | |
1658 last_mouse_bar = 0; | |
1659 | |
1660 /* I don't know how to find the time for the last movement; it seems | |
1661 like XQueryPointer ought to return it, but it doesn't. So, we'll | |
1662 return the time of the last MotionNotify event we received. Note | |
1663 that the use of motion hints means that this isn't guaranteed to | |
1664 be accurate at all. */ | |
1665 *time = last_mouse_movement_time; | |
1666 | 1698 |
1667 UNBLOCK_INPUT; | 1699 UNBLOCK_INPUT; |
1668 } | 1700 } |
1669 | 1701 |
1670 #else /* ! defined (HAVE_X11) */ | 1702 #else /* ! defined (HAVE_X11) */ |
1671 #define XEvent XKeyPressedEvent | 1703 #define XEvent XKeyPressedEvent |
1672 #endif /* ! defined (HAVE_X11) */ | 1704 #endif /* ! defined (HAVE_X11) */ |
1673 | 1705 |
1674 /* Scrollbar support. */ | 1706 /* Scrollbar support. */ |
1675 | 1707 |
1676 /* Map an X window that implements a scroll bar to the struct | 1708 /* Given an X window ID, find the struct scrollbar which manages it. */ |
1677 scrollbar representing it. */ | |
1678 static struct scrollbar * | 1709 static struct scrollbar * |
1679 x_window_to_scrollbar (window_id) | 1710 x_window_to_scrollbar (window_id) |
1680 Window window_id; | 1711 Window window_id; |
1681 { | 1712 { |
1682 Lisp_Object tail, frame; | 1713 Lisp_Object tail, frame; |
1683 struct frame *f; | |
1684 | 1714 |
1685 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr) | 1715 for (tail = Vframe_list; CONSP (tail); tail = XCONS (tail)->cdr) |
1686 { | 1716 { |
1687 struct scrollbar *bar; | |
1688 Lisp_Object frame = XCONS (tail)->car; | 1717 Lisp_Object frame = XCONS (tail)->car; |
1718 Lisp_Object bar; | |
1689 | 1719 |
1690 /* All elements of Vframe_list should be frames. */ | 1720 /* All elements of Vframe_list should be frames. */ |
1691 if (XTYPE (frame) != Lisp_Frame) | 1721 if (XTYPE (frame) != Lisp_Frame) |
1692 abort (); | 1722 abort (); |
1693 | 1723 |
1694 /* Scan this frame's scrollbar list for a scrollbar with the | 1724 /* Scan this frame's scrollbar list for a scrollbar with the |
1695 right window ID. */ | 1725 right window ID. */ |
1696 for (bar = XFRAME (frame)->display.x->vertical_scrollbars; | 1726 for (bar = FRAME_SCROLLBARS (XFRAME (frame)); |
1697 bar; | 1727 ! NILP (bar); |
1698 bar = bar->next) | 1728 bar = XSCROLLBAR(bar)->next) |
1699 if (bar->window == window_id) | 1729 if (SCROLLBAR_X_WINDOW (XSCROLLBAR (bar)) == window_id) |
1700 return bar; | 1730 return XSCROLLBAR (bar); |
1701 } | 1731 } |
1702 | 1732 |
1703 return 0; | 1733 return 0; |
1704 } | 1734 } |
1705 | 1735 |
1706 | 1736 /* Open a new X window to serve as a scrollbar, and return the |
1707 /* Open a new X window to serve as a scrollbar. */ | 1737 scrollbar vector for it. */ |
1708 static struct scrollbar * | 1738 static struct scrollbar * |
1709 x_scrollbar_create (frame, top, left, width, height) | 1739 x_scrollbar_create (window, top, left, width, height) |
1710 FRAME_PTR frame; | 1740 struct window *window; |
1711 int top, left, width, height; | 1741 int top, left, width, height; |
1712 { | 1742 { |
1713 struct x_display *d = frame->display.x; | 1743 FRAME_PTR frame = XFRAME (WINDOW_FRAME (window)); |
1714 | |
1715 /* We can't signal a malloc error from within redisplay, so call | |
1716 malloc instead of xmalloc. */ | |
1717 struct scrollbar *bar = | 1744 struct scrollbar *bar = |
1718 (struct scrollbar *) malloc (sizeof (struct scrollbar)); | 1745 XSCROLLBAR (Fmake_vector (make_number (SCROLLBAR_VEC_SIZE), Qnil)); |
1719 | |
1720 if (! bar) | |
1721 return 0; | |
1722 | 1746 |
1723 BLOCK_INPUT; | 1747 BLOCK_INPUT; |
1724 | 1748 |
1725 { | 1749 { |
1726 XSetWindowAttributes a; | 1750 XSetWindowAttributes a; |
1727 unsigned long mask; | 1751 unsigned long mask; |
1728 | 1752 |
1729 a.background_pixel = d->background_pixel; | 1753 a.background_pixel = frame->display.x->background_pixel; |
1730 a.border_pixel = d->foreground_pixel; | 1754 a.event_mask = (ButtonPressMask | ButtonReleaseMask |
1731 a.event_mask = (KeyPressMask | 1755 | ButtonMotionMask |
1732 | ButtonPressMask | ButtonReleaseMask | 1756 | ExposureMask); |
1733 | ButtonMotionMask); | |
1734 a.cursor = x_vertical_scrollbar_cursor; | 1757 a.cursor = x_vertical_scrollbar_cursor; |
1735 | 1758 |
1736 mask = (CWBackPixel | CWBorderPixel | CWEventMask | CWCursor); | 1759 mask = (CWBackPixel | CWEventMask | CWCursor); |
1737 | 1760 |
1738 bar->window = | 1761 SET_SCROLLBAR_X_WINDOW |
1739 XCreateWindow (x_current_display, FRAME_X_WINDOW (frame), | 1762 (bar, |
1740 | 1763 XCreateWindow (x_current_display, FRAME_X_WINDOW (frame), |
1741 /* Position and size of scrollbar. */ | 1764 |
1742 top, left, width, height, | 1765 /* Position and size of scrollbar. */ |
1743 | 1766 left, top, width, height, |
1744 /* Border width, depth, class, and visual. */ | 1767 |
1745 1, CopyFromParent, CopyFromParent, CopyFromParent, | 1768 /* Border width, depth, class, and visual. */ |
1746 | 1769 0, CopyFromParent, CopyFromParent, CopyFromParent, |
1747 /* Attributes. */ | 1770 |
1748 mask, &a); | 1771 /* Attributes. */ |
1772 mask, &a)); | |
1749 } | 1773 } |
1750 | 1774 |
1751 bar->frame = frame; | 1775 XSET (bar->window, Lisp_Window, window); |
1752 bar->top = top; | 1776 XSET (bar->top, Lisp_Int, top); |
1753 bar->left = left; | 1777 XSET (bar->left, Lisp_Int, left); |
1754 bar->width = width; | 1778 XSET (bar->width, Lisp_Int, width); |
1755 bar->height = height; | 1779 XSET (bar->height, Lisp_Int, height); |
1756 bar->start = bar->end = 0; | 1780 XSET (bar->start, Lisp_Int, 0); |
1757 bar->judge_timestamp = d->judge_timestamp; | 1781 XSET (bar->end, Lisp_Int, 0); |
1758 bar->dragging = -1; | 1782 bar->dragging = Qnil; |
1759 | 1783 |
1760 /* Add bar to its frame's list of scroll bars. */ | 1784 /* Add bar to its frame's list of scroll bars. */ |
1761 bar->next = d->vertical_scrollbars; | 1785 bar->next = FRAME_SCROLLBARS (frame); |
1762 d->vertical_scrollbars = bar; | 1786 bar->prev = Qnil; |
1763 | 1787 XSET (FRAME_SCROLLBARS (frame), Lisp_Vector, bar); |
1764 XMapWindow (x_current_display, bar->window); | 1788 if (! NILP (bar->next)) |
1789 XSET (XSCROLLBAR (bar->next)->prev, Lisp_Vector, bar); | |
1790 | |
1791 XMapWindow (x_current_display, SCROLLBAR_X_WINDOW (bar)); | |
1765 | 1792 |
1766 UNBLOCK_INPUT; | 1793 UNBLOCK_INPUT; |
1767 } | 1794 |
1768 | 1795 return bar; |
1769 /* Draw BAR's handle in the proper position. */ | 1796 } |
1797 | |
1798 /* Draw BAR's handle in the proper position. | |
1799 If the handle is already drawn from START to END, don't bother | |
1800 redrawing it, unless REBUILD is non-zero; in that case, always | |
1801 redraw it. (REBUILD is handy for drawing the handle after expose | |
1802 events.) | |
1803 | |
1804 Normally, we want to constrain the start and end of the handle to | |
1805 fit inside its rectangle, but if the user is dragging the scrollbar | |
1806 handle, we want to let them drag it down all the way, so that the | |
1807 bar's top is as far down as it goes; otherwise, there's no way to | |
1808 move to the very end of the buffer. */ | |
1770 static void | 1809 static void |
1771 x_scrollbar_set_handle (bar, start, end) | 1810 x_scrollbar_set_handle (bar, start, end, rebuild) |
1772 struct scrollbar *bar; | 1811 struct scrollbar *bar; |
1773 int start, end; | 1812 int start, end; |
1774 { | 1813 int rebuild; |
1814 { | |
1815 int dragging = ! NILP (bar->dragging); | |
1816 Window w = SCROLLBAR_X_WINDOW (bar); | |
1817 GC gc = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))->display.x->normal_gc; | |
1818 | |
1819 /* If the display is already accurate, do nothing. */ | |
1820 if (! rebuild | |
1821 && start == XINT (bar->start) | |
1822 && end == XINT (bar->end)) | |
1823 return; | |
1824 | |
1775 BLOCK_INPUT; | 1825 BLOCK_INPUT; |
1776 | 1826 |
1777 { | 1827 { |
1778 int inside_width = (bar->width | 1828 int inside_width = VERTICAL_SCROLLBAR_INSIDE_WIDTH (XINT (bar->width)); |
1779 - VERTICAL_SCROLLBAR_LEFT_BORDER | 1829 int inside_height = VERTICAL_SCROLLBAR_INSIDE_HEIGHT (XINT (bar->height)); |
1780 - VERTICAL_SCROLLBAR_RIGHT_BORDER); | 1830 int top_range = VERTICAL_SCROLLBAR_TOP_RANGE (XINT (bar->height)); |
1781 int inside_height = (bar->height | |
1782 - VERTICAL_SCROLLBAR_TOP_BORDER | |
1783 - VERTICAL_SCROLLBAR_BOTTOM_BORDER); | |
1784 | 1831 |
1785 /* Make sure the values are reasonable, and try to preserve | 1832 /* Make sure the values are reasonable, and try to preserve |
1786 the distance between start and end. */ | 1833 the distance between start and end. */ |
1787 if (end < start) | 1834 { |
1788 end = start; | 1835 int length = end - start; |
1789 if (start < VERTICAL_SCROLLBAR_TOP_BORDER) | 1836 |
1790 { | 1837 if (start < 0) |
1791 end = VERTICAL_SCROLLBAR_TOP_BORDER + (end - start); | 1838 start = 0; |
1792 start = VERTICAL_SCROLLBAR_TOP_BORDER; | 1839 else if (start > top_range) |
1793 } | 1840 start = top_range; |
1794 if (end > bar->height - VERTICAL_SCROLLBAR_BOTTOM_BORDER) | 1841 end = start + length; |
1795 { | 1842 |
1796 start = ((bar->height - VERTICAL_SCROLLBAR_BOTTOM_BORDER) | 1843 if (end < start) |
1797 - (end - start)); | 1844 end = start; |
1798 end = bar->height - VERTICAL_SCROLLBAR_BOTTOM_BORDER; | 1845 else if (end > top_range && ! dragging) |
1799 } | 1846 end = top_range; |
1800 if (start < VERTICAL_SCROLLBAR_TOP_BORDER) | 1847 } |
1801 start = VERTICAL_SCROLLBAR_TOP_BORDER; | 1848 |
1802 | 1849 /* Store the adjusted setting in the scrollbar. */ |
1803 /* Draw the empty space above the handle. */ | 1850 XSET (bar->start, Lisp_Int, start); |
1804 XClearArea (x_current_display, bar->window, | 1851 XSET (bar->end, Lisp_Int, end); |
1805 | 1852 |
1806 /* x, y, width, height, and exposures. */ | 1853 /* Clip the end position, just for display. */ |
1807 VERTICAL_SCROLLBAR_LEFT_BORDER, | 1854 if (end > top_range) |
1808 VERTICAL_SCROLLBAR_TOP_BORDER, | 1855 end = top_range; |
1809 inside_width + 1, start + 1, | 1856 |
1810 False); | 1857 /* Draw bottom positions VERTICAL_SCROLLBAR_MIN_HANDLE pixels |
1858 below top positions, to make sure the handle is always at least | |
1859 that many pixels tall. */ | |
1860 end += VERTICAL_SCROLLBAR_MIN_HANDLE; | |
1861 | |
1862 /* Draw the empty space above the handle. Note that we can't clear | |
1863 zero-height areas; that means "clear to end of window." */ | |
1864 if (0 < start) | |
1865 XClearArea (x_current_display, w, | |
1866 | |
1867 /* x, y, width, height, and exposures. */ | |
1868 VERTICAL_SCROLLBAR_LEFT_BORDER, | |
1869 VERTICAL_SCROLLBAR_TOP_BORDER, | |
1870 inside_width, start, | |
1871 False); | |
1811 | 1872 |
1812 /* Draw the handle itself. */ | 1873 /* Draw the handle itself. */ |
1813 XFillRectangle (x_current_display, bar->window, | 1874 XFillRectangle (x_current_display, w, gc, |
1814 bar->frame->display.x->normal_gc, | |
1815 | 1875 |
1816 /* x, y, width, height */ | 1876 /* x, y, width, height */ |
1817 VERTICAL_SCROLLBAR_LEFT_BORDER, start, | 1877 VERTICAL_SCROLLBAR_LEFT_BORDER, |
1818 inside_width, (end - start) + 1); | 1878 VERTICAL_SCROLLBAR_TOP_BORDER + start, |
1819 | 1879 inside_width, end - start); |
1820 | 1880 |
1821 /* Draw the empty space below the handle. */ | 1881 |
1822 XClearArea (x_current_display, bar->window, | 1882 /* Draw the empty space below the handle. Note that we can't |
1823 | 1883 clear zero-height areas; that means "clear to end of window." */ |
1824 /* x, y, width, height, and exposures. */ | 1884 if (end < inside_height) |
1825 VERTICAL_SCROLLBAR_LEFT_BORDER, | 1885 XClearArea (x_current_display, w, |
1826 VERTICAL_SCROLLBAR_TOP_BORDER + end, | 1886 |
1827 inside_width + 1, (inside_height - end) + 1, | 1887 /* x, y, width, height, and exposures. */ |
1828 False); | 1888 VERTICAL_SCROLLBAR_LEFT_BORDER, |
1829 | 1889 VERTICAL_SCROLLBAR_TOP_BORDER + end, |
1830 bar->start = start; | 1890 inside_width, inside_height - end, |
1831 bar->end = end; | 1891 False); |
1892 | |
1832 } | 1893 } |
1833 | 1894 |
1834 UNBLOCK_INPUT; | 1895 UNBLOCK_INPUT; |
1835 } | 1896 } |
1836 | 1897 |
1837 /* Remove the scrollbar BAR. */ | 1898 /* Move a scrollbar around on the screen, to accomodate changing |
1838 static void | 1899 window configurations. */ |
1839 x_scrollbar_remove (bar) | |
1840 struct scrollbar *bar; | |
1841 { | |
1842 BLOCK_INPUT; | |
1843 | |
1844 /* Remove bar from the frame's list. */ | |
1845 { | |
1846 struct scrollbar **ptr; | |
1847 | |
1848 for (ptr = &bar->frame->display.x->vertical_scrollbars; | |
1849 *ptr; | |
1850 ptr = &(*ptr)->next) | |
1851 if (*ptr == bar) | |
1852 { | |
1853 *ptr = bar->next; | |
1854 break; | |
1855 } | |
1856 } | |
1857 | |
1858 /* Destroy the window. */ | |
1859 XDestroyWindow (x_current_display, bar->window); | |
1860 | |
1861 /* Free the storage. */ | |
1862 free (bar); | |
1863 | |
1864 UNBLOCK_INPUT; | |
1865 } | |
1866 | |
1867 static void | 1900 static void |
1868 x_scrollbar_move (bar, top, left, width, height) | 1901 x_scrollbar_move (bar, top, left, width, height) |
1869 struct scrollbar *bar; | 1902 struct scrollbar *bar; |
1870 int top, left, width, height; | 1903 int top, left, width, height; |
1871 { | 1904 { |
1878 wc.x = left; | 1911 wc.x = left; |
1879 wc.y = top; | 1912 wc.y = top; |
1880 wc.width = width; | 1913 wc.width = width; |
1881 wc.height = height; | 1914 wc.height = height; |
1882 | 1915 |
1883 if (left != bar->left) mask |= CWX; | 1916 if (left != XINT (bar->left)) mask |= CWX; |
1884 if (top != bar->top) mask |= CWY; | 1917 if (top != XINT (bar->top)) mask |= CWY; |
1885 if (width != bar->width) mask |= CWWidth; | 1918 if (width != XINT (bar->width)) mask |= CWWidth; |
1886 if (height != bar->height) mask |= CWHeight; | 1919 if (height != XINT (bar->height)) mask |= CWHeight; |
1887 | 1920 |
1888 XConfigureWindow (x_current_display, bar->window, mask, &wc); | 1921 if (mask) |
1922 XConfigureWindow (x_current_display, SCROLLBAR_X_WINDOW (bar), | |
1923 mask, &wc); | |
1889 } | 1924 } |
1890 | 1925 |
1926 XSET (bar->left, Lisp_Int, left); | |
1927 XSET (bar->top, Lisp_Int, top); | |
1928 XSET (bar->width, Lisp_Int, width); | |
1929 XSET (bar->height, Lisp_Int, height); | |
1930 | |
1891 UNBLOCK_INPUT; | 1931 UNBLOCK_INPUT; |
1892 } | 1932 } |
1893 | 1933 |
1894 /* Set BAR to be the vertical scroll bar for WINDOW. Set its handle | 1934 /* Destroy the X window for BAR, and set its Emacs window's scrollbar |
1895 to indicate that we are displaying PORTION characters out of a | 1935 to nil. */ |
1896 total of WHOLE characters, starting at POSITION. Return BAR. If | 1936 static void |
1897 BAR is zero, create a new scrollbar and return a pointer to it. */ | 1937 x_scrollbar_remove (bar) |
1898 static struct scrollbar * | |
1899 XTset_scrollbar (bar, window, portion, whole, position) | |
1900 struct scrollbar *bar; | 1938 struct scrollbar *bar; |
1939 { | |
1940 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); | |
1941 | |
1942 BLOCK_INPUT; | |
1943 | |
1944 /* Destroy the window. */ | |
1945 XDestroyWindow (x_current_display, SCROLLBAR_X_WINDOW (bar)); | |
1946 | |
1947 /* Disassociate this scrollbar from its window. */ | |
1948 XWINDOW (bar->window)->vertical_scrollbar = Qnil; | |
1949 | |
1950 UNBLOCK_INPUT; | |
1951 } | |
1952 | |
1953 /* Set the handle of the vertical scroll bar for WINDOW to indicate | |
1954 that we are displaying PORTION characters out of a total of WHOLE | |
1955 characters, starting at POSITION. If WINDOW has no scrollbar, | |
1956 create one. */ | |
1957 static void | |
1958 XTset_vertical_scrollbar (window, portion, whole, position) | |
1901 struct window *window; | 1959 struct window *window; |
1902 int portion, whole, position; | 1960 int portion, whole, position; |
1903 { | 1961 { |
1904 FRAME_PTR f = XFRAME (WINDOW_FRAME (window)); | 1962 FRAME_PTR f = XFRAME (WINDOW_FRAME (window)); |
1905 struct x_display *d = f->display.x; | |
1906 int top = XINT (window->top); | 1963 int top = XINT (window->top); |
1907 int left = WINDOW_VERTICAL_SCROLLBAR_COLUMN (window); | 1964 int left = WINDOW_VERTICAL_SCROLLBAR_COLUMN (window); |
1908 int height = WINDOW_VERTICAL_SCROLLBAR_HEIGHT (window); | 1965 int height = WINDOW_VERTICAL_SCROLLBAR_HEIGHT (window); |
1909 | 1966 |
1910 /* Where should this scrollbar be, pixelwise? */ | 1967 /* Where should this scrollbar be, pixelwise? */ |
1911 int pixel_top = (d->internal_border_width + top * FONT_HEIGHT (d->font)); | 1968 int pixel_top = CHAR_TO_PIXEL_ROW (f, top); |
1912 int pixel_left = (d->internal_border_width + left * FONT_WIDTH (d->font)); | 1969 int pixel_left = CHAR_TO_PIXEL_COL (f, left); |
1913 int pixel_width = VERTICAL_SCROLLBAR_PIXEL_WIDTH (f); | 1970 int pixel_width = VERTICAL_SCROLLBAR_PIXEL_WIDTH (f); |
1914 int pixel_height = VERTICAL_SCROLLBAR_PIXEL_HEIGHT (f, height); | 1971 int pixel_height = VERTICAL_SCROLLBAR_PIXEL_HEIGHT (f, height); |
1915 | 1972 |
1973 struct scrollbar *bar; | |
1974 | |
1916 /* Does the scrollbar exist yet? */ | 1975 /* Does the scrollbar exist yet? */ |
1917 if (! bar) | 1976 if (NILP (window->vertical_scrollbar)) |
1918 bar = x_scrollbar_create (f, | 1977 bar = x_scrollbar_create (window, |
1919 pixel_top, pixel_left, | 1978 pixel_top, pixel_left, |
1920 pixel_width, pixel_height); | 1979 pixel_width, pixel_height); |
1921 else | 1980 else |
1922 /* It may just need to be moved and resized. */ | 1981 { |
1923 x_scrollbar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height); | 1982 /* It may just need to be moved and resized. */ |
1983 bar = XSCROLLBAR (window->vertical_scrollbar); | |
1984 x_scrollbar_move (bar, pixel_top, pixel_left, pixel_width, pixel_height); | |
1985 } | |
1924 | 1986 |
1925 /* Set the scrollbar's current state, unless we're currently being | 1987 /* Set the scrollbar's current state, unless we're currently being |
1926 dragged. */ | 1988 dragged. */ |
1927 | 1989 if (NILP (bar->dragging)) |
1928 if (bar && bar->dragging == -1) | 1990 { |
1929 { | 1991 int top_range = |
1930 int inside_height = (pixel_height | 1992 VERTICAL_SCROLLBAR_TOP_RANGE (pixel_height); |
1931 - VERTICAL_SCROLLBAR_TOP_BORDER | 1993 |
1932 - VERTICAL_SCROLLBAR_BOTTOM_BORDER); | 1994 if (whole == 0) |
1933 int start = (position * inside_height) / whole; | 1995 x_scrollbar_set_handle (bar, 0, top_range, 0); |
1934 int end = ((position + portion) * inside_height) / whole; | 1996 else |
1935 | 1997 { |
1936 x_scrollbar_set_handle (bar, start, end); | 1998 int start = (position * top_range) / whole; |
1937 } | 1999 int end = ((position + portion) * top_range) / whole; |
1938 | 2000 |
1939 return bar; | 2001 x_scrollbar_set_handle (bar, start, end, 0); |
1940 } | 2002 } |
2003 } | |
2004 | |
2005 XSET (window->vertical_scrollbar, Lisp_Vector, bar); | |
2006 } | |
2007 | |
1941 | 2008 |
1942 /* The following three hooks are used when we're doing a thorough | 2009 /* The following three hooks are used when we're doing a thorough |
1943 redisplay of the frame. We don't explicitly know which scrollbars | 2010 redisplay of the frame. We don't explicitly know which scrollbars |
1944 are going to be deleted, because keeping track of when windows go | 2011 are going to be deleted, because keeping track of when windows go |
1945 away is a real pain - can you say set-window-configuration? | 2012 away is a real pain - "Can you say set-window-configuration, boys |
1946 Instead, we just assert at the beginning of redisplay that *all* | 2013 and girls?" Instead, we just assert at the beginning of redisplay |
1947 scrollbars are to be removed, and then save scrollbars from the | 2014 that *all* scrollbars are to be removed, and then save a scrollbar |
1948 firey pit when we actually redisplay their window. */ | 2015 from the fiery pit when we actually redisplay its window. */ |
1949 | 2016 |
1950 /* Arrange for all scrollbars on FRAME to be removed at the next call | 2017 /* Arrange for all scrollbars on FRAME to be removed at the next call |
1951 to `*judge_scrollbars_hook'. A scrollbar may be spared if | 2018 to `*judge_scrollbars_hook'. A scrollbar may be spared if |
1952 `*redeem_scrollbar_hook' is applied to it before the judgement. */ | 2019 `*redeem_scrollbar_hook' is applied to its window before the judgement. */ |
1953 static void | 2020 static void |
1954 XTcondemn_scrollbars (frame) | 2021 XTcondemn_scrollbars (frame) |
1955 FRAME_PTR frame; | 2022 FRAME_PTR frame; |
1956 { | 2023 { |
1957 /* Any scrollbars which don't get caught up to this will be deleted. */ | 2024 /* The condemned list should be empty at this point; if it's not, |
1958 frame->display.x->judge_timestamp++; | 2025 then the rest of Emacs isn't using the condemn/redeem/judge |
1959 } | 2026 protocol correctly. */ |
1960 | 2027 if (! NILP (FRAME_CONDEMNED_SCROLLBARS (frame))) |
1961 /* Unmark BAR for deletion in this judgement cycle. */ | 2028 abort (); |
2029 | |
2030 /* Move them all to the "condemned" list. */ | |
2031 FRAME_CONDEMNED_SCROLLBARS (frame) = FRAME_SCROLLBARS (frame); | |
2032 FRAME_SCROLLBARS (frame) = Qnil; | |
2033 } | |
2034 | |
2035 /* Unmark WINDOW's scrollbar for deletion in this judgement cycle. | |
2036 Note that WINDOW isn't necessarily condemned at all. */ | |
1962 static void | 2037 static void |
1963 XTredeem_scrollbar (bar) | 2038 XTredeem_scrollbar (window) |
1964 struct scrollbar *bar; | 2039 struct window *window; |
1965 { | 2040 { |
1966 bar->judge_timestamp = bar->frame->display.x->judge_timestamp; | 2041 struct scrollbar *bar; |
2042 | |
2043 /* We can't redeem this window's scrollbar if it doesn't have one. */ | |
2044 if (NILP (window->vertical_scrollbar)) | |
2045 abort (); | |
2046 | |
2047 bar = XSCROLLBAR (window->vertical_scrollbar); | |
2048 | |
2049 /* Unlink it from the condemned list. */ | |
2050 { | |
2051 FRAME_PTR f = XFRAME (WINDOW_FRAME (window)); | |
2052 | |
2053 if (NILP (bar->prev)) | |
2054 { | |
2055 /* If the prev pointer is nil, it must be the first in one of | |
2056 the lists. */ | |
2057 if (EQ (FRAME_SCROLLBARS (f), window->vertical_scrollbar)) | |
2058 /* It's not condemned. Everything's fine. */ | |
2059 return; | |
2060 else if (EQ (FRAME_CONDEMNED_SCROLLBARS (f), | |
2061 window->vertical_scrollbar)) | |
2062 FRAME_CONDEMNED_SCROLLBARS (f) = bar->next; | |
2063 else | |
2064 /* If its prev pointer is nil, it must be at the front of | |
2065 one or the other! */ | |
2066 abort (); | |
2067 } | |
2068 else | |
2069 XSCROLLBAR (bar->prev)->next = bar->next; | |
2070 | |
2071 if (! NILP (bar->next)) | |
2072 XSCROLLBAR (bar->next)->prev = bar->prev; | |
2073 | |
2074 bar->next = FRAME_SCROLLBARS (f); | |
2075 bar->prev = Qnil; | |
2076 XSET (FRAME_SCROLLBARS (f), Lisp_Vector, bar); | |
2077 if (! NILP (bar->next)) | |
2078 XSET (XSCROLLBAR (bar->next)->prev, Lisp_Vector, bar); | |
2079 } | |
1967 } | 2080 } |
1968 | 2081 |
1969 /* Remove all scrollbars on FRAME that haven't been saved since the | 2082 /* Remove all scrollbars on FRAME that haven't been saved since the |
1970 last call to `*condemn_scrollbars_hook'. */ | 2083 last call to `*condemn_scrollbars_hook'. */ |
1971 static void | 2084 static void |
1972 XTjudge_scrollbars(frame) | 2085 XTjudge_scrollbars (f) |
1973 FRAME_PTR frame; | 2086 FRAME_PTR f; |
1974 { | 2087 { |
1975 int judge_timestamp = frame->display.x->judge_timestamp; | 2088 Lisp_Object bar, next; |
1976 struct scrollbar *bar, *next; | 2089 |
1977 | 2090 for (bar = FRAME_CONDEMNED_SCROLLBARS (f); |
1978 for (bar = frame->display.x->vertical_scrollbars; bar; bar = next) | 2091 ! NILP (bar); |
1979 { | 2092 bar = next) |
1980 next = bar->next; | 2093 { |
1981 if (bar->judge_timestamp < judge_timestamp) | 2094 struct scrollbar *b = XSCROLLBAR (bar); |
1982 x_scrollbar_remove (bar); | 2095 |
1983 } | 2096 x_scrollbar_remove (b); |
2097 | |
2098 next = b->next; | |
2099 b->next = b->prev = Qnil; | |
2100 } | |
2101 | |
2102 FRAME_CONDEMNED_SCROLLBARS (f) = Qnil; | |
2103 | |
2104 /* Now there should be no references to the condemned scrollbars, | |
2105 and they should get garbage-collected. */ | |
1984 } | 2106 } |
1985 | 2107 |
1986 | 2108 |
1987 /* Handle an Expose or GraphicsExpose event on a scrollbar. */ | 2109 /* Handle an Expose or GraphicsExpose event on a scrollbar. */ |
1988 static void | 2110 static void |
1989 x_scrollbar_expose (bar, event) | 2111 x_scrollbar_expose (bar, event) |
1990 struct scrollbar *bar; | 2112 struct scrollbar *bar; |
1991 XEvent *event; | 2113 XEvent *event; |
1992 { | 2114 { |
2115 Window w = SCROLLBAR_X_WINDOW (bar); | |
2116 GC gc = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)))->display.x->normal_gc; | |
2117 | |
1993 BLOCK_INPUT; | 2118 BLOCK_INPUT; |
1994 | 2119 |
1995 x_scrollbar_set_handle (bar, bar->start, bar->end); | 2120 x_scrollbar_set_handle (bar, XINT (bar->start), XINT (bar->end), 1); |
1996 | 2121 |
1997 /* Draw the extra-thick border on the right. */ | 2122 /* Draw a one-pixel border just inside the edges of the scrollbar. */ |
1998 XFillRectangle (x_current_display, bar->window, | 2123 XDrawRectangle (x_current_display, w, gc, |
1999 bar->frame->display.x->normal_gc, | |
2000 | 2124 |
2001 /* x, y, width, height */ | 2125 /* x, y, width, height */ |
2002 bar->width - VERTICAL_SCROLLBAR_RIGHT_BORDER, 0, | 2126 0, 0, XINT (bar->width) - 1, XINT (bar->height) - 1); |
2003 VERTICAL_SCROLLBAR_RIGHT_BORDER, bar->height + 1); | 2127 |
2004 | 2128 /* Draw another line to make the extra-thick border on the right. */ |
2005 UNBLOCK_INPUT; | 2129 XFillRectangle (x_current_display, w, gc, |
2006 } | 2130 |
2007 | 2131 /* x, y, width, height */ |
2008 /* Handle an exposure event which might be over the extra scrollbar space. */ | 2132 XINT (bar->width) - 2, 1, 1, XINT (bar->height) - 2); |
2009 static void | |
2010 x_scrollbar_background_expose (frame, event) | |
2011 FRAME_PTR frame; | |
2012 XEvent *event; | |
2013 { | |
2014 /* Where is the extra scrollbar space, anyway? */ | |
2015 int width = VERTICAL_SCROLLBAR_PIXEL_WIDTH (frame); | |
2016 int height = PIXEL_HEIGHT (frame); | |
2017 int x = PIXEL_WIDTH (frame) - width; | |
2018 int y = 0; | |
2019 | |
2020 BLOCK_INPUT; | |
2021 | |
2022 /* Clear it out. */ | |
2023 XClearArea (x_current_display, FRAME_X_WINDOW (frame), | |
2024 | |
2025 /* x, y, width, height, expose */ | |
2026 x, y, width+1, height+1, False); | |
2027 | |
2028 /* Draw the border. */ | |
2029 XDrawRectangle (x_current_display, FRAME_X_WINDOW (frame), | |
2030 frame->display.x->normal_gc, | |
2031 x, y, width, height); | |
2032 | |
2033 /* Draw the extra-thick border on the right edge. */ | |
2034 XFillRectangle (x_current_display, FRAME_X_WINDOW (frame), | |
2035 frame->display.x->normal_gc, | |
2036 x + width - VERTICAL_SCROLLBAR_RIGHT_BORDER, 0, | |
2037 VERTICAL_SCROLLBAR_RIGHT_BORDER, height + 1); | |
2038 | 2133 |
2039 UNBLOCK_INPUT; | 2134 UNBLOCK_INPUT; |
2040 } | 2135 } |
2041 | 2136 |
2042 /* Handle a mouse click on the scrollbar BAR. If *EMACS_EVENT's kind | 2137 /* Handle a mouse click on the scrollbar BAR. If *EMACS_EVENT's kind |
2045 x_scrollbar_handle_click (bar, event, emacs_event) | 2140 x_scrollbar_handle_click (bar, event, emacs_event) |
2046 struct scrollbar *bar; | 2141 struct scrollbar *bar; |
2047 XEvent *event; | 2142 XEvent *event; |
2048 struct input_event *emacs_event; | 2143 struct input_event *emacs_event; |
2049 { | 2144 { |
2145 if (XTYPE (bar->window) != Lisp_Window) | |
2146 abort (); | |
2147 | |
2050 emacs_event->kind = scrollbar_click; | 2148 emacs_event->kind = scrollbar_click; |
2051 XSETINT (emacs_event->code, event->xbutton.button - Button1); | 2149 XSET (emacs_event->code, Lisp_Int, event->xbutton.button - Button1); |
2052 emacs_event->modifiers = | 2150 emacs_event->modifiers = |
2053 (x_convert_modifiers (event->xbutton.state) | 2151 (x_convert_modifiers (event->xbutton.state) |
2054 | (event->type == ButtonRelease | 2152 | (event->type == ButtonRelease |
2055 ? up_modifier | 2153 ? up_modifier |
2056 : down_modifier)); | 2154 : down_modifier)); |
2057 emacs_event->part = | 2155 emacs_event->frame_or_window = bar->window; |
2058 ((event->xbutton.x < bar->start) ? scrollbar_above_handle | |
2059 : (event->xbutton.x < bar->end) ? scrollbar_handle | |
2060 : scrollbar_below_handle); | |
2061 emacs_event->scrollbar = bar; | |
2062 | |
2063 if (event->xbutton.y < VERTICAL_SCROLLBAR_TOP_BORDER) | |
2064 event->xbutton.y = VERTICAL_SCROLLBAR_TOP_BORDER; | |
2065 if (event->xbutton.y > bar->height - VERTICAL_SCROLLBAR_BOTTOM_BORDER) | |
2066 event->xbutton.y = bar->height - VERTICAL_SCROLLBAR_BOTTOM_BORDER; | |
2067 XSETINT (emacs_event->x, | |
2068 event->xbutton.y - VERTICAL_SCROLLBAR_TOP_BORDER); | |
2069 XSETINT (emacs_event->y, | |
2070 (bar->height | |
2071 - VERTICAL_SCROLLBAR_TOP_BORDER | |
2072 - VERTICAL_SCROLLBAR_BOTTOM_BORDER)); | |
2073 | |
2074 emacs_event->frame = bar->frame; | |
2075 emacs_event->timestamp = event->xbutton.time; | 2156 emacs_event->timestamp = event->xbutton.time; |
2076 | 2157 { |
2077 if (event->type == ButtonPress | 2158 int internal_height = |
2078 && emacs_event->part == scrollbar_handle) | 2159 VERTICAL_SCROLLBAR_INSIDE_HEIGHT (XINT (bar->height)); |
2079 bar->dragging = event->xbutton.x - bar->start; | 2160 int top_range = |
2080 else | 2161 VERTICAL_SCROLLBAR_TOP_RANGE (XINT (bar->height)); |
2081 { | 2162 int y = event->xbutton.y - VERTICAL_SCROLLBAR_TOP_BORDER; |
2082 int new_start = event->xbutton.x - bar->dragging; | 2163 |
2083 int new_end = new_start + (bar->end - bar->start); | 2164 if (y < 0) y = 0; |
2084 | 2165 if (y > top_range) y = top_range; |
2085 x_scrollbar_set_handle (bar, new_start, new_end); | 2166 |
2086 bar->dragging = -1; | 2167 if (y < XINT (bar->start)) |
2087 } | 2168 emacs_event->part = scrollbar_above_handle; |
2088 } | 2169 else if (y < XINT (bar->end) + VERTICAL_SCROLLBAR_MIN_HANDLE) |
2089 | 2170 emacs_event->part = scrollbar_handle; |
2171 else | |
2172 emacs_event->part = scrollbar_below_handle; | |
2173 | |
2174 /* If the user has just clicked on the handle, record where they're | |
2175 holding it. */ | |
2176 if (event->type == ButtonPress | |
2177 && emacs_event->part == scrollbar_handle) | |
2178 XSET (bar->dragging, Lisp_Int, y - XINT (bar->start)); | |
2179 | |
2180 /* If the user has released the handle, set it to its final position. */ | |
2181 if (event->type == ButtonRelease | |
2182 && ! NILP (bar->dragging)) | |
2183 { | |
2184 int new_start = y - XINT (bar->dragging); | |
2185 int new_end = new_start + (XINT (bar->end) - XINT (bar->start)); | |
2186 | |
2187 x_scrollbar_set_handle (bar, new_start, new_end, 0); | |
2188 bar->dragging = Qnil; | |
2189 } | |
2190 | |
2191 /* Clicks on the handle are always reported as occuring at the top of | |
2192 the handle. */ | |
2193 if (emacs_event->part == scrollbar_handle) | |
2194 emacs_event->x = bar->start; | |
2195 else | |
2196 XSET (emacs_event->x, Lisp_Int, y); | |
2197 | |
2198 XSET (emacs_event->y, Lisp_Int, top_range); | |
2199 } | |
2200 } | |
2090 | 2201 |
2091 /* Handle some mouse motion while someone is dragging the scrollbar. */ | 2202 /* Handle some mouse motion while someone is dragging the scrollbar. */ |
2092 static void | 2203 static void |
2093 x_scrollbar_handle_motion (bar, event) | 2204 x_scrollbar_note_movement (bar, event) |
2094 struct scrollbar *bar; | 2205 struct scrollbar *bar; |
2095 XEvent *event; | 2206 XEvent *event; |
2096 { | 2207 { |
2097 last_mouse_movement_time = event->xmotion.time; | 2208 last_mouse_movement_time = event->xmotion.time; |
2098 | 2209 |
2099 mouse_moved = 1; | 2210 mouse_moved = 1; |
2100 last_mouse_bar = bar; | 2211 XSET (last_mouse_scrollbar, Lisp_Vector, bar); |
2101 last_mouse_bar_frame = bar->frame; | |
2102 last_mouse_part = (bar->dragging == -1 ? scrollbar_handle | |
2103 : (event->xbutton.x < bar->start) ? scrollbar_above_handle | |
2104 : (event->xbutton.x < bar->end) ? scrollbar_handle | |
2105 : scrollbar_below_handle); | |
2106 last_mouse_scroll_range_start = bar->top + VERTICAL_SCROLLBAR_TOP_BORDER; | |
2107 last_mouse_scroll_range_end = (bar->top | |
2108 + bar->height | |
2109 - VERTICAL_SCROLLBAR_BOTTOM_BORDER); | |
2110 | 2212 |
2111 /* If we're dragging the bar, display it. */ | 2213 /* If we're dragging the bar, display it. */ |
2112 if (bar->dragging != -1) | 2214 if (! NILP (bar->dragging)) |
2113 { | 2215 { |
2114 /* Where should the handle be now? */ | 2216 /* Where should the handle be now? */ |
2115 int new_start = event->xmotion.x - bar->dragging; | 2217 int new_start = event->xmotion.y - XINT (bar->dragging); |
2116 | 2218 |
2117 if (new_start != bar->start) | 2219 if (new_start != XINT (bar->start)) |
2118 { | 2220 { |
2119 int new_end = new_start + (bar->end - bar->start); | 2221 int new_end = new_start + (XINT (bar->end) - XINT (bar->start)); |
2120 | 2222 |
2121 x_scrollbar_set_handle (bar, new_start, new_end); | 2223 x_scrollbar_set_handle (bar, new_start, new_end, 0); |
2122 } | 2224 } |
2123 } | 2225 } |
2124 | 2226 |
2125 /* Call XQueryPointer so we'll get an event the next time the mouse | 2227 /* Call XQueryPointer so we'll get an event the next time the mouse |
2126 moves and we can see *still* on the same position. */ | 2228 moves and we can see *still* on the same position. */ |
2130 XQueryPointer (event->xmotion.display, event->xmotion.window, | 2232 XQueryPointer (event->xmotion.display, event->xmotion.window, |
2131 (Window *) &dummy, (Window *) &dummy, | 2233 (Window *) &dummy, (Window *) &dummy, |
2132 &dummy, &dummy, &dummy, &dummy, | 2234 &dummy, &dummy, &dummy, &dummy, |
2133 (unsigned int *) &dummy); | 2235 (unsigned int *) &dummy); |
2134 } | 2236 } |
2237 } | |
2238 | |
2239 /* Return information to the user about the current position of the mouse | |
2240 on the scrollbar. */ | |
2241 static void | |
2242 x_scrollbar_report_motion (f, bar_window, part, x, y, time) | |
2243 FRAME_PTR *f; | |
2244 Lisp_Object *bar_window; | |
2245 enum scrollbar_part *part; | |
2246 Lisp_Object *x, *y; | |
2247 unsigned long *time; | |
2248 { | |
2249 struct scrollbar *bar = XSCROLLBAR (last_mouse_scrollbar); | |
2250 int win_x, win_y; | |
2251 | |
2252 /* Get the mouse's position relative to the scrollbar window, and | |
2253 report that. */ | |
2254 { | |
2255 Window dummy_window; | |
2256 int dummy_coord; | |
2257 unsigned int dummy_mask; | |
2258 | |
2259 if (! XQueryPointer (x_current_display, | |
2260 SCROLLBAR_X_WINDOW (bar), | |
2261 | |
2262 /* Root, child, root x and root y. */ | |
2263 &dummy_window, &dummy_window, | |
2264 &dummy_coord, &dummy_coord, | |
2265 | |
2266 /* Position relative to scrollbar. */ | |
2267 &win_x, &win_y, | |
2268 | |
2269 /* Mouse buttons and modifier keys. */ | |
2270 &dummy_mask)) | |
2271 { | |
2272 *f = 0; | |
2273 return; | |
2274 } | |
2275 } | |
2276 | |
2277 { | |
2278 int inside_height = VERTICAL_SCROLLBAR_INSIDE_HEIGHT (XINT (bar->height)); | |
2279 int top_range = VERTICAL_SCROLLBAR_TOP_RANGE (XINT (bar->height)); | |
2280 | |
2281 win_y -= VERTICAL_SCROLLBAR_TOP_BORDER; | |
2282 | |
2283 if (! NILP (bar->dragging)) | |
2284 win_y -= XINT (bar->dragging); | |
2285 | |
2286 if (win_y < 0) | |
2287 win_y = 0; | |
2288 if (win_y > top_range) | |
2289 win_y = top_range; | |
2290 | |
2291 *f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); | |
2292 *bar_window = bar->window; | |
2293 | |
2294 if (! NILP (bar->dragging)) | |
2295 *part = scrollbar_handle; | |
2296 else if (win_y < XINT (bar->start)) | |
2297 *part = scrollbar_above_handle; | |
2298 else if (win_y < XINT (bar->end) + VERTICAL_SCROLLBAR_MIN_HANDLE) | |
2299 *part = scrollbar_handle; | |
2300 else | |
2301 *part = scrollbar_below_handle; | |
2302 | |
2303 XSET (*x, Lisp_Int, win_y); | |
2304 XSET (*y, Lisp_Int, top_range); | |
2305 *time = last_mouse_movement_time; | |
2306 } | |
2307 | |
2308 mouse_moved = 0; | |
2309 last_mouse_scrollbar = Qnil; | |
2135 } | 2310 } |
2136 | 2311 |
2137 | 2312 |
2138 | 2313 |
2139 /* The main X event-reading loop - XTread_socket. */ | 2314 /* The main X event-reading loop - XTread_socket. */ |
2320 else | 2495 else |
2321 { | 2496 { |
2322 dumprectangle (x_window_to_frame (event.xexpose.window), | 2497 dumprectangle (x_window_to_frame (event.xexpose.window), |
2323 event.xexpose.x, event.xexpose.y, | 2498 event.xexpose.x, event.xexpose.y, |
2324 event.xexpose.width, event.xexpose.height); | 2499 event.xexpose.width, event.xexpose.height); |
2325 x_scrollbar_background_expose (f, &event); | |
2326 } | 2500 } |
2327 } | 2501 } |
2328 else | 2502 else |
2329 { | 2503 { |
2330 struct scrollbar *bar | 2504 struct scrollbar *bar |
2343 { | 2517 { |
2344 dumprectangle (f, | 2518 dumprectangle (f, |
2345 event.xgraphicsexpose.x, event.xgraphicsexpose.y, | 2519 event.xgraphicsexpose.x, event.xgraphicsexpose.y, |
2346 event.xgraphicsexpose.width, | 2520 event.xgraphicsexpose.width, |
2347 event.xgraphicsexpose.height); | 2521 event.xgraphicsexpose.height); |
2348 x_scrollbar_background_expose (f, &event); | |
2349 } | 2522 } |
2350 break; | 2523 break; |
2351 | 2524 |
2352 case NoExpose: /* This occurs when an XCopyArea's | 2525 case NoExpose: /* This occurs when an XCopyArea's |
2353 source area was completely | 2526 source area was completely |
2475 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */ | 2648 || IsKeypadKey (keysym) /* 0xff80 <= x < 0xffbe */ |
2476 || IsFunctionKey (keysym)) /* 0xffbe <= x < 0xffe1 */ | 2649 || IsFunctionKey (keysym)) /* 0xffbe <= x < 0xffe1 */ |
2477 { | 2650 { |
2478 bufp->kind = non_ascii_keystroke; | 2651 bufp->kind = non_ascii_keystroke; |
2479 XSET (bufp->code, Lisp_Int, (unsigned) keysym - 0xff50); | 2652 XSET (bufp->code, Lisp_Int, (unsigned) keysym - 0xff50); |
2480 bufp->frame = f; | 2653 XSET (bufp->frame_or_window, Lisp_Frame, f); |
2481 bufp->modifiers = x_convert_modifiers (modifiers); | 2654 bufp->modifiers = x_convert_modifiers (modifiers); |
2482 bufp->timestamp = event.xkey.time; | 2655 bufp->timestamp = event.xkey.time; |
2483 bufp++; | 2656 bufp++; |
2484 count++; | 2657 count++; |
2485 numchars--; | 2658 numchars--; |
2492 { | 2665 { |
2493 if (modifiers & x_meta_mod_mask) | 2666 if (modifiers & x_meta_mod_mask) |
2494 *copy_buffer |= METABIT; | 2667 *copy_buffer |= METABIT; |
2495 bufp->kind = ascii_keystroke; | 2668 bufp->kind = ascii_keystroke; |
2496 XSET (bufp->code, Lisp_Int, *copy_buffer); | 2669 XSET (bufp->code, Lisp_Int, *copy_buffer); |
2497 bufp->frame = f; | 2670 XSET (bufp->frame_or_window, Lisp_Frame, f); |
2498 bufp->timestamp = event.xkey.time; | 2671 bufp->timestamp = event.xkey.time; |
2499 bufp++; | 2672 bufp++; |
2500 } | 2673 } |
2501 else | 2674 else |
2502 for (i = nbytes - 1; i > 1; i--) | 2675 for (i = nbytes - 1; i > 1; i--) |
2503 { | 2676 { |
2504 bufp->kind = ascii_keystroke; | 2677 bufp->kind = ascii_keystroke; |
2505 XSET (bufp->code, Lisp_Int, copy_buffer[i]); | 2678 XSET (bufp->code, Lisp_Int, copy_buffer[i]); |
2506 bufp->frame = f; | 2679 XSET (bufp->frame_or_window, Lisp_Frame, f); |
2507 bufp->timestamp = event.xkey.time; | 2680 bufp->timestamp = event.xkey.time; |
2508 bufp++; | 2681 bufp++; |
2509 } | 2682 } |
2510 | 2683 |
2511 count += nbytes; | 2684 count += nbytes; |
2551 for (i = 0; i < nbytes; i++) | 2724 for (i = 0; i < nbytes; i++) |
2552 { | 2725 { |
2553 bufp->kind = ascii_keystroke; | 2726 bufp->kind = ascii_keystroke; |
2554 XSET (bufp->code, Lisp_Int, where_mapping[i]); | 2727 XSET (bufp->code, Lisp_Int, where_mapping[i]); |
2555 XSET (bufp->time, Lisp_Int, event.xkey.time); | 2728 XSET (bufp->time, Lisp_Int, event.xkey.time); |
2556 bufp->frame = f; | 2729 XSET (bufp->frame_or_window, Lisp_Frame, f); |
2557 bufp++; | 2730 bufp++; |
2558 } | 2731 } |
2559 count += nbytes; | 2732 count += nbytes; |
2560 numchars -= nbytes; | 2733 numchars -= nbytes; |
2561 } | 2734 } |
2666 #ifdef HAVE_X11 | 2839 #ifdef HAVE_X11 |
2667 case MotionNotify: | 2840 case MotionNotify: |
2668 { | 2841 { |
2669 f = x_window_to_frame (event.xmotion.window); | 2842 f = x_window_to_frame (event.xmotion.window); |
2670 if (f) | 2843 if (f) |
2671 note_mouse_position (f, &event.xmotion); | 2844 note_mouse_movement (f, &event.xmotion); |
2672 else | 2845 else |
2673 { | 2846 { |
2674 struct scrollbar *bar = | 2847 struct scrollbar *bar = |
2675 x_window_to_scrollbar (event.xmotion.window); | 2848 x_window_to_scrollbar (event.xmotion.window); |
2676 | 2849 |
2677 if (bar) | 2850 if (bar) |
2678 x_scrollbar_handle_motion (bar, &event); | 2851 x_scrollbar_note_movement (bar, &event); |
2679 } | 2852 } |
2680 } | 2853 } |
2681 break; | 2854 break; |
2682 | 2855 |
2683 case ConfigureNotify: | 2856 case ConfigureNotify: |
2766 enqueue_event (&event, &x_mouse_queue); | 2939 enqueue_event (&event, &x_mouse_queue); |
2767 if (numchars >= 2) | 2940 if (numchars >= 2) |
2768 { | 2941 { |
2769 bufp->kind = ascii_keystroke; | 2942 bufp->kind = ascii_keystroke; |
2770 bufp->code = (char) 'X' & 037; /* C-x */ | 2943 bufp->code = (char) 'X' & 037; /* C-x */ |
2771 bufp->frame = f; | 2944 XSET (bufp->frame_or_window, Lisp_Frame, f); |
2772 XSET (bufp->time, Lisp_Int, event.xkey.time); | 2945 XSET (bufp->time, Lisp_Int, event.xkey.time); |
2773 bufp++; | 2946 bufp++; |
2774 | 2947 |
2775 bufp->kind = ascii_keystroke; | 2948 bufp->kind = ascii_keystroke; |
2776 bufp->code = (char) 0; /* C-@ */ | 2949 bufp->code = (char) 0; /* C-@ */ |
2777 bufp->frame = f; | 2950 XSET (bufp->frame_or_window, Lisp_Frame, f); |
2778 XSET (bufp->time, Lisp_Int, event.xkey.time); | 2951 XSET (bufp->time, Lisp_Int, event.xkey.time); |
2779 bufp++; | 2952 bufp++; |
2780 | 2953 |
2781 count += 2; | 2954 count += 2; |
2782 numchars -= 2; | 2955 numchars -= 2; |
2912 | 3085 |
2913 static void | 3086 static void |
2914 x_draw_box (f) | 3087 x_draw_box (f) |
2915 struct frame *f; | 3088 struct frame *f; |
2916 { | 3089 { |
2917 int left = f->cursor_x * FONT_WIDTH (f->display.x->font) | 3090 int left = CHAR_TO_PIXEL_COL (f, f->cursor_x); |
2918 + f->display.x->internal_border_width; | 3091 int top = CHAR_TO_PIXEL_ROW (f, f->cursor_y); |
2919 int top = f->cursor_y * FONT_HEIGHT (f->display.x->font) | |
2920 + f->display.x->internal_border_width; | |
2921 int width = FONT_WIDTH (f->display.x->font); | 3092 int width = FONT_WIDTH (f->display.x->font); |
2922 int height = FONT_HEIGHT (f->display.x->font); | 3093 int height = FONT_HEIGHT (f->display.x->font); |
2923 | 3094 |
2924 #ifdef HAVE_X11 | 3095 #ifdef HAVE_X11 |
2925 /* Perhaps we should subtract 1 from width and height... */ | |
2926 XDrawRectangle (x_current_display, FRAME_X_WINDOW (f), | 3096 XDrawRectangle (x_current_display, FRAME_X_WINDOW (f), |
2927 f->display.x->cursor_gc, | 3097 f->display.x->cursor_gc, |
2928 left, top, width - 1, height - 1); | 3098 left, top, width - 1, height - 1); |
2929 #else /* ! defined (HAVE_X11) */ | 3099 #else /* ! defined (HAVE_X11) */ |
2930 XPixSet (FRAME_X_WINDOW (f), | 3100 XPixSet (FRAME_X_WINDOW (f), |
2960 || f->phys_cursor_x < 0) | 3130 || f->phys_cursor_x < 0) |
2961 return; | 3131 return; |
2962 | 3132 |
2963 #ifdef HAVE_X11 | 3133 #ifdef HAVE_X11 |
2964 x_display_cursor (f, 0); | 3134 x_display_cursor (f, 0); |
2965 #if 0 | |
2966 XClearArea (x_current_display, FRAME_X_WINDOW (f), | |
2967 f->phys_cursor_x * FONT_WIDTH (f->display.x->font) | |
2968 + f->display.x->internal_border_width, | |
2969 f->phys_cursor_y * FONT_HEIGHT (f->display.x->font) | |
2970 + f->display.x->internal_border_width, | |
2971 FONT_WIDTH (f->display.x->font) + 1, FONT_HEIGHT (f->display.x->font) + 1, False); | |
2972 #endif /* ! 0 */ | |
2973 #else /* ! defined (HAVE_X11) */ | 3135 #else /* ! defined (HAVE_X11) */ |
2974 XPixSet (FRAME_X_WINDOW (f), | 3136 XPixSet (FRAME_X_WINDOW (f), |
2975 f->phys_cursor_x * FONT_WIDTH (f->display.x->font) + f->display.x->internal_border_width, | 3137 CHAR_TO_PIXEL_COL (f, f->phys_cursor_x), |
2976 f->phys_cursor_y * FONT_HEIGHT (f->display.x->font) + f->display.x->internal_border_width, | 3138 CHAR_TO_PIXEL_ROW (f, f->phys_cursor_y), |
2977 FONT_WIDTH (f->display.x->font), FONT_HEIGHT (f->display.x->font), | 3139 FONT_WIDTH (f->display.x->font), FONT_HEIGHT (f->display.x->font), |
2978 f->display.x->background_pixel); | 3140 f->display.x->background_pixel); |
2979 #endif /* ! defined (HAVE_X11) */ | 3141 #endif /* ! defined (HAVE_X11) */ |
2980 f->phys_cursor_x = -1; | 3142 f->phys_cursor_x = -1; |
2981 } | 3143 } |
2996 | 3158 |
2997 #ifdef HAVE_X11 | 3159 #ifdef HAVE_X11 |
2998 if (phys_x >= 0 && | 3160 if (phys_x >= 0 && |
2999 (!on || phys_x != f->cursor_x || phys_y != f->cursor_y)) | 3161 (!on || phys_x != f->cursor_x || phys_y != f->cursor_y)) |
3000 { | 3162 { |
3001 x1 = phys_x * FONT_WIDTH (f->display.x->font) | 3163 x1 = CHAR_TO_PIXEL_COL (f, phys_x); |
3002 + f->display.x->internal_border_width; | 3164 y1 = CHAR_TO_PIXEL_ROW (f, phys_y) - 1; |
3003 y1 = phys_y * FONT_HEIGHT (f->display.x->font) | |
3004 + f->display.x->internal_border_width - 1; | |
3005 y2 = y1 + FONT_HEIGHT (f->display.x->font) + 1; | 3165 y2 = y1 + FONT_HEIGHT (f->display.x->font) + 1; |
3006 | 3166 |
3007 XDrawLine (x_current_display, FRAME_X_WINDOW (f), | 3167 XDrawLine (x_current_display, FRAME_X_WINDOW (f), |
3008 f->display.x->reverse_gc, x1, y1, x1, y2); | 3168 f->display.x->reverse_gc, x1, y1, x1, y2); |
3009 | 3169 |
3010 f->phys_cursor_x = phys_x = -1; | 3170 f->phys_cursor_x = phys_x = -1; |
3011 } | 3171 } |
3012 | 3172 |
3013 if (on && f == x_highlight_frame) | 3173 if (on && f == x_highlight_frame) |
3014 { | 3174 { |
3015 x1 = f->cursor_x * FONT_WIDTH (f->display.x->font) | 3175 x1 = CHAR_TO_PIXEL_COL (f, f->cursor_x); |
3016 + f->display.x->internal_border_width; | 3176 y1 = CHAR_TO_PIXEL_ROW (f, f->cursor_y) - 1; |
3017 y1 = f->cursor_y * FONT_HEIGHT (f->display.x->font) | |
3018 + f->display.x->internal_border_width - 1; | |
3019 y2 = y1 + FONT_HEIGHT (f->display.x->font) + 1; | 3177 y2 = y1 + FONT_HEIGHT (f->display.x->font) + 1; |
3020 | 3178 |
3021 XDrawLine (x_current_display, FRAME_X_WINDOW (f), | 3179 XDrawLine (x_current_display, FRAME_X_WINDOW (f), |
3022 f->display.x->cursor_gc, x1, y1, x1, y2); | 3180 f->display.x->cursor_gc, x1, y1, x1, y2); |
3023 | 3181 |
3040 int row, column; | 3198 int row, column; |
3041 GLYPH glyph; | 3199 GLYPH glyph; |
3042 int highlight; | 3200 int highlight; |
3043 { | 3201 { |
3044 dumpglyphs (f, | 3202 dumpglyphs (f, |
3045 (column * FONT_WIDTH (f->display.x->font) | 3203 CHAR_TO_PIXEL_COL (f, column), |
3046 + f->display.x->internal_border_width), | 3204 CHAR_TO_PIXEL_ROW (f, row), |
3047 (row * FONT_HEIGHT (f->display.x->font) | |
3048 + f->display.x->internal_border_width), | |
3049 &glyph, 1, highlight, f->display.x->font); | 3205 &glyph, 1, highlight, f->display.x->font); |
3050 } | 3206 } |
3051 | 3207 |
3052 /* Turn the displayed cursor of frame F on or off according to ON. | 3208 /* Turn the displayed cursor of frame F on or off according to ON. |
3053 If ON is nonzero, where to put the cursor is specified | 3209 If ON is nonzero, where to put the cursor is specified |
3309 return 0; | 3465 return 0; |
3310 } | 3466 } |
3311 | 3467 |
3312 /* Handling X errors. */ | 3468 /* Handling X errors. */ |
3313 | 3469 |
3314 /* A handler for SIGPIPE, when it occurs on the X server's connection. | 3470 /* Shut down Emacs in an orderly fashion, because of a SIGPIPE on the |
3315 This basically does an orderly shutdown of Emacs. */ | 3471 X server's connection, or an error reported via the X protocol. */ |
3316 | 3472 |
3317 static SIGTYPE | 3473 static SIGTYPE |
3318 x_connection_closed () | 3474 x_connection_closed () |
3319 { | 3475 { |
3320 if (_Xdebug) | 3476 if (_Xdebug) |
3321 abort (); | 3477 abort (); |
3322 else | 3478 |
3323 Fkill_emacs (make_number (70)); | 3479 shut_down_emacs (0); |
3480 | |
3481 exit (70); | |
3324 } | 3482 } |
3325 | 3483 |
3326 /* An X error handler which prints an error message and then kills Emacs. | 3484 /* An X error handler which prints an error message and then kills Emacs. |
3327 This is what's normally installed as Xlib's handler for protocol and | 3485 This is what's normally installed as Xlib's handler for protocol and |
3328 I/O errors. */ | 3486 I/O errors. */ |
3331 Display *display; | 3489 Display *display; |
3332 XErrorEvent *error; | 3490 XErrorEvent *error; |
3333 { | 3491 { |
3334 char buf[256]; | 3492 char buf[256]; |
3335 | 3493 |
3494 /* Note that there is no real way portable across R3/R4 to get the | |
3495 original error handler. */ | |
3496 | |
3497 XGetErrorText (display, error->error_code, buf, sizeof (buf)); | |
3498 fprintf (stderr, "X protocol error: %s on protocol request %d\n", | |
3499 buf, error->request_code); | |
3500 | |
3336 /* While we're testing Emacs 19, we'll just dump core whenever we | 3501 /* While we're testing Emacs 19, we'll just dump core whenever we |
3337 get an X error, so we can figure out why it happened. */ | 3502 get an X error, so we can figure out why it happened. */ |
3338 abort (); | 3503 abort (); |
3339 | |
3340 /* Note that there is no real way portable across R3/R4 to get the | |
3341 original error handler. */ | |
3342 | |
3343 XGetErrorText (display, error->error_code, buf, sizeof (buf)); | |
3344 fprintf (stderr, "X protocol error: %s on protocol request %d\n", | |
3345 buf, error->request_code); | |
3346 | 3504 |
3347 x_connection_closed (); | 3505 x_connection_closed (); |
3348 } | 3506 } |
3349 | 3507 |
3350 /* A buffer for storing X error messages. */ | 3508 /* A buffer for storing X error messages. */ |
3611 struct frame *f; | 3769 struct frame *f; |
3612 int cols, rows; | 3770 int cols, rows; |
3613 { | 3771 { |
3614 int pixelwidth, pixelheight; | 3772 int pixelwidth, pixelheight; |
3615 int mask; | 3773 int mask; |
3616 int ibw = f->display.x->internal_border_width; | |
3617 | 3774 |
3618 BLOCK_INPUT; | 3775 BLOCK_INPUT; |
3619 | 3776 |
3620 check_frame_size (f, &rows, &cols); | 3777 check_frame_size (f, &rows, &cols); |
3621 f->display.x->vertical_scrollbar_extra = | 3778 f->display.x->vertical_scrollbar_extra = |
3633 /* Now, strictly speaking, we can't be sure that this is accurate, | 3790 /* Now, strictly speaking, we can't be sure that this is accurate, |
3634 but the window manager will get around to dealing with the size | 3791 but the window manager will get around to dealing with the size |
3635 change request eventually, and we'll hear how it went when the | 3792 change request eventually, and we'll hear how it went when the |
3636 ConfigureNotify event gets here. */ | 3793 ConfigureNotify event gets here. */ |
3637 FRAME_WIDTH (f) = cols; | 3794 FRAME_WIDTH (f) = cols; |
3638 FRAME_WIDTH (f) = rows; | 3795 FRAME_HEIGHT (f) = rows; |
3639 PIXEL_WIDTH (f) = pixelwidth; | 3796 PIXEL_WIDTH (f) = pixelwidth; |
3640 PIXEL_HEIGHT (f) = pixelheight; | 3797 PIXEL_HEIGHT (f) = pixelheight; |
3641 | 3798 |
3642 XFlushQueue (); | 3799 XFlushQueue (); |
3643 UNBLOCK_INPUT; | 3800 UNBLOCK_INPUT; |
3645 | 3802 |
3646 #ifndef HAVE_X11 | 3803 #ifndef HAVE_X11 |
3647 x_set_resize_hint (f) | 3804 x_set_resize_hint (f) |
3648 struct frame *f; | 3805 struct frame *f; |
3649 { | 3806 { |
3650 | 3807 XSetResizeHint (FRAME_X_WINDOW (f), |
3651 XSetResizeHint (FRAME_X_WINDOW (f), 2 * f->display.x->internal_border_width, | |
3652 2 * f->display.x->internal_border_width, | 3808 2 * f->display.x->internal_border_width, |
3653 FONT_WIDTH (f->display.x->font), FONT_HEIGHT (f->display.x->font)); | 3809 2 * f->display.x->internal_border_width, |
3810 FONT_WIDTH (f->display.x->font), | |
3811 FONT_HEIGHT (f->display.x->font)); | |
3654 } | 3812 } |
3655 #endif /* HAVE_X11 */ | 3813 #endif /* HAVE_X11 */ |
3656 | 3814 |
3657 /* Mouse warping, focus shifting, raising and lowering. */ | 3815 /* Mouse warping, focus shifting, raising and lowering. */ |
3658 | 3816 |
3662 { | 3820 { |
3663 int pix_x, pix_y; | 3821 int pix_x, pix_y; |
3664 | 3822 |
3665 x_raise_frame (f); | 3823 x_raise_frame (f); |
3666 | 3824 |
3667 pix_x = (f->display.x->internal_border_width | 3825 pix_x = CHAR_TO_PIXEL_COL (f, x) + FONT_WIDTH (f->display.x->font) / 2; |
3668 + x * FONT_WIDTH (f->display.x->font) | 3826 pix_y = CHAR_TO_PIXEL_ROW (f, y) + FONT_HEIGHT (f->display.x->font) / 2; |
3669 + FONT_WIDTH (f->display.x->font) / 2); | |
3670 pix_y = (f->display.x->internal_border_width | |
3671 + y * FONT_HEIGHT (f->display.x->font) | |
3672 + FONT_HEIGHT (f->display.x->font) / 2); | |
3673 | 3827 |
3674 if (pix_x < 0) pix_x = 0; | 3828 if (pix_x < 0) pix_x = 0; |
3675 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f); | 3829 if (pix_x > PIXEL_WIDTH (f)) pix_x = PIXEL_WIDTH (f); |
3676 | 3830 |
3677 if (pix_y < 0) pix_y = 0; | 3831 if (pix_y < 0) pix_y = 0; |
4014 size_hints.y = f->display.x->top_pos; | 4168 size_hints.y = f->display.x->top_pos; |
4015 size_hints.height = PIXEL_HEIGHT (f); | 4169 size_hints.height = PIXEL_HEIGHT (f); |
4016 size_hints.width = PIXEL_WIDTH (f); | 4170 size_hints.width = PIXEL_WIDTH (f); |
4017 size_hints.width_inc = FONT_WIDTH (f->display.x->font); | 4171 size_hints.width_inc = FONT_WIDTH (f->display.x->font); |
4018 size_hints.height_inc = FONT_HEIGHT (f->display.x->font); | 4172 size_hints.height_inc = FONT_HEIGHT (f->display.x->font); |
4019 size_hints.max_width = PIXEL_TO_CHAR_WIDTH (f, x_screen_width); | 4173 size_hints.max_width = x_screen_width - CHAR_TO_PIXEL_WIDTH (f, 0); |
4020 size_hints.max_height = PIXEL_TO_CHAR_HEIGHT (f, x_screen_height); | 4174 size_hints.max_height = x_screen_height - CHAR_TO_PIXEL_HEIGHT (f, 0); |
4021 | 4175 |
4022 { | 4176 { |
4023 int base_width, base_height; | 4177 int base_width, base_height; |
4024 | 4178 |
4025 base_width = CHAR_TO_PIXEL_WIDTH (f, 0); | 4179 base_width = CHAR_TO_PIXEL_WIDTH (f, 0); |
4126 char *defaultvalue; | 4280 char *defaultvalue; |
4127 #ifdef F_SETOWN | 4281 #ifdef F_SETOWN |
4128 extern int old_fcntl_owner; | 4282 extern int old_fcntl_owner; |
4129 #endif /* ! defined (F_SETOWN) */ | 4283 #endif /* ! defined (F_SETOWN) */ |
4130 | 4284 |
4131 { | |
4132 fprintf (stderr, "\ | |
4133 Hey! The Emacs 19 sources currently contain incomplete changes | |
4134 for scrollbars, and don't run properly under X! | |
4135 | |
4136 It is supposed to work under termcap, though. | |
4137 | |
4138 -JimB"); | |
4139 } | |
4140 | |
4141 | |
4142 x_focus_frame = x_highlight_frame = 0; | 4285 x_focus_frame = x_highlight_frame = 0; |
4143 | 4286 |
4144 x_current_display = XOpenDisplay (display_name); | 4287 x_current_display = XOpenDisplay (display_name); |
4145 if (x_current_display == 0) | 4288 if (x_current_display == 0) |
4146 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n", | 4289 fatal ("X server %s not responding; check the DISPLAY environment variable or use \"-d\"\n", |
4241 read_socket_hook = XTread_socket; | 4384 read_socket_hook = XTread_socket; |
4242 cursor_to_hook = XTcursor_to; | 4385 cursor_to_hook = XTcursor_to; |
4243 reassert_line_highlight_hook = XTreassert_line_highlight; | 4386 reassert_line_highlight_hook = XTreassert_line_highlight; |
4244 mouse_position_hook = XTmouse_position; | 4387 mouse_position_hook = XTmouse_position; |
4245 frame_rehighlight_hook = XTframe_rehighlight; | 4388 frame_rehighlight_hook = XTframe_rehighlight; |
4246 set_vertical_scrollbar_hook = XTset_scrollbar; | 4389 set_vertical_scrollbar_hook = XTset_vertical_scrollbar; |
4247 condemn_scrollbars_hook = XTcondemn_scrollbars; | 4390 condemn_scrollbars_hook = XTcondemn_scrollbars; |
4248 redeem_scrollbar_hook = XTredeem_scrollbar; | 4391 redeem_scrollbar_hook = XTredeem_scrollbar; |
4249 judge_scrollbars_hook = XTjudge_scrollbars; | 4392 judge_scrollbars_hook = XTjudge_scrollbars; |
4250 | 4393 |
4251 scroll_region_ok = 1; /* we'll scroll partial frames */ | 4394 scroll_region_ok = 1; /* we'll scroll partial frames */ |
4272 void | 4415 void |
4273 syms_of_xterm () | 4416 syms_of_xterm () |
4274 { | 4417 { |
4275 staticpro (&invocation_name); | 4418 staticpro (&invocation_name); |
4276 invocation_name = Qnil; | 4419 invocation_name = Qnil; |
4420 | |
4421 staticpro (&last_mouse_scrollbar); | |
4277 } | 4422 } |
4278 #endif /* ! defined (HAVE_X11) */ | 4423 #endif /* ! defined (HAVE_X11) */ |
4279 #endif /* ! defined (HAVE_X_WINDOWS) */ | 4424 #endif /* ! defined (HAVE_X_WINDOWS) */ |