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) */