From 56ffd194371f38239589eb0f818682a0b2e0dbac Mon Sep 17 00:00:00 2001 From: Thien-Thi Nguyen Date: Thu, 25 Dec 2003 12:13:59 +0000 Subject: (tgetst1): Scan for "%pN"; if all N are continuous in [1,9], remove all "%pN". --- src/ChangeLog | 5 +++++ src/termcap.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 4adadd84db1..f3b9d0f81ea 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2003-12-25 Thien-Thi Nguyen + + * termcap.c (tgetst1): Scan for "%pN"; if all + N are continuous in [1,9], remove all "%pN". + 2003-12-24 Jan Dj,Ad(Brv * gtkutil.c (xg_frame_set_char_size): Call x_wm_set_size_hint. diff --git a/src/termcap.c b/src/termcap.c index b1e0a87936e..a1c068e0964 100644 --- a/src/termcap.c +++ b/src/termcap.c @@ -284,6 +284,52 @@ tgetst1 (ptr, area) } *r++ = c; } + + /* Sometimes entries have "%pN" which means use parameter N in the + next %-substitution. If all such N are continuous in the range + [1,9] we can remove each "%pN" because they are redundant, thus + reducing bandwidth requirements. True, Emacs is well beyond the + days of 150baud teletypes, but some of its users aren't much so. + + This pass could probably be integrated into the one above but + abbreviation expansion makes that effort a little more hairy than + its worth; this is cleaner. */ + { + register int last_p_param = 0; + int remove_p_params = 1; + struct { char *beg; int len; } cut[11]; + + for (cut[0].beg = p = ret; p < r - 3; p++) + { + if (!remove_p_params) + break; + if (*p == '%' && *(p + 1) == 'p') + { + if (*(p + 2) - '0' == 1 + last_p_param) + { + cut[last_p_param].len = p - cut[last_p_param].beg; + last_p_param++; + p += 3; + cut[last_p_param].beg = p; + } + else /* not continuous: bail */ + remove_p_params = 0; + if (last_p_param > 10) /* too many: bail */ + remove_p_params = 0; + } + } + if (remove_p_params && last_p_param) + { + register int i; + char *wp; + + cut[last_p_param].len = r - cut[last_p_param].beg; + for (i = 0, wp = ret; i <= last_p_param; wp += cut[i++].len) + bcopy (cut[i].beg, wp, cut[i].len); + r = wp; + } + } + *r = '\0'; /* Update *AREA. */ if (area) -- cgit v1.2.1 From b91485007d4c4fd637291364eecd363e1cecfa9d Mon Sep 17 00:00:00 2001 From: Lars Hansen Date: Thu, 25 Dec 2003 17:12:59 +0000 Subject: (Fdirectory_files, Fdirectory_files_and_attributes): Arguments GCPRO'ed in call to file name handler. --- src/ChangeLog | 5 +++++ src/dired.c | 27 ++++----------------------- 2 files changed, 9 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index f3b9d0f81ea..1d153f72530 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,8 @@ +2003-12-25 Lars Hansen + + * dired.c (Fdirectory_files, Fdirectory_files_and_attributes): + Arguments GCPRO'ed in call to file name handler. + 2003-12-25 Thien-Thi Nguyen * termcap.c (tgetst1): Scan for "%pN"; if all diff --git a/src/dired.c b/src/dired.c index 52a19f4fdc6..3bcd3051c25 100644 --- a/src/dired.c +++ b/src/dired.c @@ -359,17 +359,8 @@ If NOSORT is non-nil, the list is not sorted--its order is unpredictable. call the corresponding file handler. */ handler = Ffind_file_name_handler (directory, Qdirectory_files); if (!NILP (handler)) - { - Lisp_Object args[6]; - - args[0] = handler; - args[1] = Qdirectory_files; - args[2] = directory; - args[3] = full; - args[4] = match; - args[5] = nosort; - return Ffuncall (6, args); - } + return call5 (handler, Qdirectory_files, directory, + full, match, nosort); return directory_files_internal (directory, full, match, nosort, 0, Qnil); } @@ -395,18 +386,8 @@ ID-FORMAT specifies the preferred format of attributes uid and gid, see call the corresponding file handler. */ handler = Ffind_file_name_handler (directory, Qdirectory_files_and_attributes); if (!NILP (handler)) - { - Lisp_Object args[7]; - - args[0] = handler; - args[1] = Qdirectory_files_and_attributes; - args[2] = directory; - args[3] = full; - args[4] = match; - args[5] = nosort; - args[6] = id_format; - return Ffuncall (7, args); - } + return call6 (handler, Qdirectory_files_and_attributes, + directory, full, match, nosort, id_format); return directory_files_internal (directory, full, match, nosort, 1, id_format); } -- cgit v1.2.1 From 86408abdf4871166dadc6694cfa309244a4c46fb Mon Sep 17 00:00:00 2001 From: Luc Teirlinck Date: Thu, 25 Dec 2003 17:31:23 +0000 Subject: (Fcompleting_read): Undo previous change. --- src/minibuf.c | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/minibuf.c b/src/minibuf.c index 4c98f7ba708..baeb0cef7b5 100644 --- a/src/minibuf.c +++ b/src/minibuf.c @@ -1578,10 +1578,13 @@ Completion ignores case if the ambient value of Lisp_Object prompt, table, predicate, require_match, initial_input; Lisp_Object hist, def, inherit_input_method; { - Lisp_Object val, histvar, histpos; + Lisp_Object val, histvar, histpos, position; + Lisp_Object init; + int pos = 0; int count = SPECPDL_INDEX (); struct gcpro gcpro1; + init = initial_input; GCPRO1 (def); specbind (Qminibuffer_completion_table, table); @@ -1590,6 +1593,23 @@ Completion ignores case if the ambient value of EQ (require_match, Qt) ? Qnil : require_match); last_exact_completion = Qnil; + position = Qnil; + if (!NILP (init)) + { + if (CONSP (init)) + { + position = Fcdr (init); + init = Fcar (init); + } + CHECK_STRING (init); + if (!NILP (position)) + { + CHECK_NUMBER (position); + /* Convert to distance from end of input. */ + pos = XINT (position) - SCHARS (init); + } + } + if (SYMBOLP (hist)) { histvar = hist; @@ -1608,7 +1628,7 @@ Completion ignores case if the ambient value of val = read_minibuf (NILP (require_match) ? Vminibuffer_local_completion_map : Vminibuffer_local_must_match_map, - initial_input, prompt, Qnil, 0, + init, prompt, make_number (pos), 0, histvar, histpos, def, 0, !NILP (inherit_input_method)); -- cgit v1.2.1 From fc052137c5511debc81094aab706ccf1d6a7581f Mon Sep 17 00:00:00 2001 From: Luc Teirlinck Date: Thu, 25 Dec 2003 18:07:44 +0000 Subject: *** empty log message *** --- src/ChangeLog | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index 1d153f72530..fc1445a46dd 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,7 @@ +2003-12-25 Luc Teirlinck + + * minibuf.c (Fcompleting_read): Undo previous change. + 2003-12-25 Lars Hansen * dired.c (Fdirectory_files, Fdirectory_files_and_attributes): -- cgit v1.2.1 From c7211bc5311e640b212da5c3bf780ac10ce5a08f Mon Sep 17 00:00:00 2001 From: Kenichi Handa Date: Fri, 26 Dec 2003 11:39:22 +0000 Subject: *** empty log message *** --- src/composite.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/composite.c b/src/composite.c index b4e931c6a20..f8e655a3685 100644 --- a/src/composite.c +++ b/src/composite.c @@ -842,9 +842,12 @@ syms_of_composite () args[0] = QCtest; args[1] = Qequal; + /* We used to make the hash table weak so that unreferenced + compostions can be garbage-collected. But, usually once + created compositions are repeatedly used in an Emacs session, + and thus it's not worth to save memory in such a way. So, we + make the table not weak. */ args[2] = QCweakness; - /* Fixme: It seems that a weak hash table leads to segfault in GC, - but I have not yet found why. -- handa@m17n.org */ args[3] = Qnil; args[4] = QCsize; args[5] = make_number (311); -- cgit v1.2.1 From 942b13fa0d42e216c3a9fcc012d311f121311d8a Mon Sep 17 00:00:00 2001 From: Kim F. Storm Date: Sat, 27 Dec 2003 22:03:40 +0000 Subject: (eval.o): Depend on dispextern.h. --- src/Makefile.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/Makefile.in b/src/Makefile.in index 07b3c828650..cd9fb8b6f57 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -1171,7 +1171,7 @@ alloc.o: alloc.c process.h frame.h window.h buffer.h puresize.h syssignal.h key bytecode.o: bytecode.c buffer.h syntax.h charset.h window.h $(config_h) data.o: data.c buffer.h puresize.h charset.h syssignal.h keyboard.h $(config_h) eval.o: eval.c commands.h keyboard.h blockinput.h atimer.h systime.h \ - $(config_h) + dispextern.h $(config_h) floatfns.o: floatfns.c $(config_h) fns.o: fns.c commands.h $(config_h) frame.h buffer.h charset.h keyboard.h \ frame.h window.h dispextern.h $(INTERVAL_SRC) coding.h md5.h -- cgit v1.2.1 From 9fc63a8939697c4daa2e56b9829eebe2cc204bf4 Mon Sep 17 00:00:00 2001 From: Kim F. Storm Date: Sat, 27 Dec 2003 22:24:01 +0000 Subject: (show_help_event): Remove unused code. --- src/xmenu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/xmenu.c b/src/xmenu.c index 3e99a1c506d..669d8177c15 100644 --- a/src/xmenu.c +++ b/src/xmenu.c @@ -99,7 +99,6 @@ Lisp_Object Vmenu_updating_frame; Lisp_Object Qdebug_on_next_call; extern Lisp_Object Qmenu_bar; -extern Lisp_Object Qmouse_click, Qevent_kind; extern Lisp_Object QCtoggle, QCradio; @@ -1304,6 +1303,7 @@ show_help_event (f, widget, help) } else { +#if 0 /* This code doesn't do anything useful. ++kfs */ /* WIDGET is the popup menu. It's parent is the frame's widget. See which frame that is. */ xt_or_gtk_widget frame_widget = XtParent (widget); @@ -1317,7 +1317,7 @@ show_help_event (f, widget, help) FRAME_X_P (f) && f->output_data.x->widget == frame_widget)) break; } - +#endif show_help_echo (help, Qnil, Qnil, Qnil, 1); } } -- cgit v1.2.1 From f2dcea2bf92c7cb7d05110b63c187de1b73544ab Mon Sep 17 00:00:00 2001 From: Kim F. Storm Date: Sat, 27 Dec 2003 23:16:53 +0000 Subject: (Qmouse_click, Qevent_kind): Remove unused externs. --- src/w32menu.c | 1 - 1 file changed, 1 deletion(-) (limited to 'src') diff --git a/src/w32menu.c b/src/w32menu.c index 49ced7fd11c..5f8f8a4e5e0 100644 --- a/src/w32menu.c +++ b/src/w32menu.c @@ -153,7 +153,6 @@ Lisp_Object Vmenu_updating_frame; Lisp_Object Qdebug_on_next_call; extern Lisp_Object Qmenu_bar; -extern Lisp_Object Qmouse_click, Qevent_kind; extern Lisp_Object QCtoggle, QCradio; -- cgit v1.2.1 From db4f9403e18676d597721c4e9fa36809bd9e6d0d Mon Sep 17 00:00:00 2001 From: Kim F. Storm Date: Sat, 27 Dec 2003 23:19:43 +0000 Subject: (Qface, Qmouse_face): Remove unused externs. --- src/macterm.c | 2 -- src/w32term.c | 2 -- 2 files changed, 4 deletions(-) (limited to 'src') diff --git a/src/macterm.c b/src/macterm.c index f0f5a3f4722..8ef25e43856 100644 --- a/src/macterm.c +++ b/src/macterm.c @@ -253,8 +253,6 @@ extern Lisp_Object Vcommand_line_args, Vsystem_name; extern Lisp_Object Vx_no_window_manager; -extern Lisp_Object Qface, Qmouse_face; - extern int errno; /* A mask of extra modifier bits to put into every keyboard char. */ diff --git a/src/w32term.c b/src/w32term.c index 3e4543471c3..d7248499c22 100644 --- a/src/w32term.c +++ b/src/w32term.c @@ -221,8 +221,6 @@ static int input_signal_count; extern Lisp_Object Vcommand_line_args, Vsystem_name; -extern Lisp_Object Qface, Qmouse_face; - #ifndef USE_CRT_DLL extern int errno; #endif -- cgit v1.2.1 From 01b1f0c05b794f86c98e6ad36086e02aa8927482 Mon Sep 17 00:00:00 2001 From: Kim F. Storm Date: Sun, 28 Dec 2003 00:09:49 +0000 Subject: (FACE_ID_BITS, MAX_FACE_ID): New defines. (struct glyph): New members, ascent and descent. Used to save this glyph's ascent and descent, instead of having. (struct glyph): Declare member face_id using FACE_ID_BITS. (find_hot_spot): Add prototype. --- src/dispextern.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/dispextern.h b/src/dispextern.h index f306a939db2..25c8227d773 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -321,6 +321,9 @@ struct glyph /* Width in pixels. */ short pixel_width; + /* Ascent and descent in pixels. */ + short ascent, descent; + /* Vertical offset. If < 0, the glyph is displayed raised, if > 0 the glyph is displayed lowered. */ short voffset; @@ -359,8 +362,10 @@ struct glyph doesn't have a glyph in a font. */ unsigned glyph_not_available_p : 1; +#define FACE_ID_BITS 21 + /* Face of the glyph. */ - unsigned face_id : 21; + unsigned face_id : FACE_ID_BITS; /* Type of font used to display the character glyph. May be used to determine which set of functions to use to obtain font metrics @@ -1493,6 +1498,7 @@ enum face_id BASIC_FACE_ID_SENTINEL }; +#define MAX_FACE_ID ((1 << FACE_ID_BITS) - 1) /* A cache of realized faces. Each frame has its own cache because Emacs allows different frame-local face definitions. */ @@ -2536,6 +2542,7 @@ extern void x_draw_vertical_border P_ ((struct window *w)); extern void frame_to_window_pixel_xy P_ ((struct window *, int *, int *)); extern void get_glyph_string_clip_rect P_ ((struct glyph_string *, NativeRectangle *nr)); +extern Lisp_Object find_hot_spot P_ ((Lisp_Object, int, int)); extern void note_mouse_highlight P_ ((struct frame *, int, int)); extern void x_clear_window_mouse_face P_ ((struct window *)); extern void cancel_mouse_face P_ ((struct frame *)); -- cgit v1.2.1 From 60bf162981c3f6fada160812ed248c0f9c6ebc92 Mon Sep 17 00:00:00 2001 From: Kim F. Storm Date: Sun, 28 Dec 2003 00:10:12 +0000 Subject: (buffer_posn_from_coords): Fix calculation of dy for image glyph using image's ascent. (mode_line_string): Return image glyph as object clicked on. Adjust y0 for image glyph using image's ascent. --- src/dispnew.c | 51 +++++++++++++++++++++++++++++++++++++++------------ 1 file changed, 39 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/dispnew.c b/src/dispnew.c index 279c1f10e58..09a651d5d7c 100644 --- a/src/dispnew.c +++ b/src/dispnew.c @@ -5702,8 +5702,6 @@ buffer_posn_from_coords (w, x, y, dx, dy, object, pos) struct it it; struct buffer *old_current_buffer = current_buffer; struct text_pos startp; - struct glyph_row *row; - struct image *img; int x0, x1; current_buffer = XBUFFER (w->buffer); @@ -5716,25 +5714,44 @@ buffer_posn_from_coords (w, x, y, dx, dy, object, pos) move_it_to (&it, -1, x0 + it.first_visible_x, *y, -1, MOVE_TO_X | MOVE_TO_Y); - /* Add extra (default width) columns if clicked after EOL. */ - x1 = max(0, it.current_x + it.pixel_width - it.first_visible_x); - if (x0 > x1) - it.hpos += (x0 - x1) / WINDOW_FRAME_COLUMN_WIDTH (w); - current_buffer = old_current_buffer; *dx = x0 + it.first_visible_x - it.current_x; *dy = *y - it.current_y; + *object = w->buffer; + #ifdef HAVE_WINDOW_SYSTEM - if (it.what == IT_IMAGE - && (img = IMAGE_FROM_ID (it.f, it.image_id)) != NULL - && !NILP (img->spec)) - *object = img->spec; + if (it.what == IT_IMAGE) + { + struct image *img; + if ((img = IMAGE_FROM_ID (it.f, it.image_id)) != NULL + && !NILP (img->spec)) + { + struct glyph_row *row = MATRIX_ROW (w->current_matrix, it.vpos); + struct glyph *glyph; + + if (it.hpos < row->used[TEXT_AREA] + && (glyph = row->glyphs[TEXT_AREA] + it.hpos, + glyph->type == IMAGE_GLYPH)) + { + *dy -= row->ascent - glyph->ascent; + *object = img->spec; + } + } + } else #endif - *object = STRINGP (it.string) ? it.string : w->buffer; + if (STRINGP (it.string)) + *object = it.string; + *pos = it.current; + + /* Add extra (default width) columns if clicked after EOL. */ + x1 = max(0, it.current_x + it.pixel_width - it.first_visible_x); + if (x0 > x1) + it.hpos += (x0 - x1) / WINDOW_FRAME_COLUMN_WIDTH (w); + *x = it.hpos; *y = it.vpos; } @@ -5854,6 +5871,16 @@ marginal_area_string (w, x, y, dx, dy, part, charpos) { string = glyph->object; *charpos = glyph->charpos; +#ifdef HAVE_WINDOW_SYSTEM + if (glyph->type == IMAGE_GLYPH) + { + struct image *img; + img = IMAGE_FROM_ID (WINDOW_XFRAME (w), glyph->u.img_id); + if (img != NULL) + string = img->spec; + y0 -= row->ascent - glyph->ascent; + } +#endif } else /* Add extra (default width) columns if clicked after EOL. */ -- cgit v1.2.1 From 2e3f0f616bd831dbc6a09c9f753085c6caf563f8 Mon Sep 17 00:00:00 2001 From: Kim F. Storm Date: Sun, 28 Dec 2003 00:10:41 +0000 Subject: (Qimage): Remove extern (now in lisp.h). (QCmap): Declare extern. (make_lispy_position): When position is inside image hot-spot, use hot-spot element as posn element. --- src/keyboard.c | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/keyboard.c b/src/keyboard.c index 6148a2510b8..3ac73750afc 100644 --- a/src/keyboard.c +++ b/src/keyboard.c @@ -587,7 +587,7 @@ Lisp_Object Qvertical_scroll_bar; Lisp_Object Qmenu_bar; extern Lisp_Object Qleft_margin, Qright_margin; extern Lisp_Object Qleft_fringe, Qright_fringe; -extern Lisp_Object Qimage; +extern Lisp_Object QCmap; Lisp_Object recursive_edit_unwind (), command_loop (); Lisp_Object Fthis_command_keys (); @@ -5024,6 +5024,19 @@ make_lispy_position (f, x, y, time) string = marginal_area_string (w, &rx, &ry, &dx, &dy, part, &charpos); if (STRINGP (string)) object = Fcons (string, make_number (charpos)); +#ifdef HAVE_WINDOW_SYSTEM + else if (IMAGEP (string)) + { + Lisp_Object image_map, hotspot; + object = string; + if ((image_map = Fplist_get (XCDR (object), QCmap), + !NILP (image_map)) + && (hotspot = find_hot_spot (image_map, dx, dy), + CONSP (hotspot)) + && (hotspot = XCDR (hotspot), CONSP (hotspot))) + posn = XCAR (hotspot); + } +#endif } else if (part == ON_LEFT_FRINGE || part == ON_RIGHT_FRINGE) { @@ -5059,8 +5072,19 @@ make_lispy_position (f, x, y, time) if (STRINGP (string)) object = Fcons (string, make_number (CHARPOS (p.string_pos))); - else if (CONSP (string) && EQ (XCAR (string), Qimage)) - object = string; +#ifdef HAVE_WINDOW_SYSTEM + else if (IMAGEP (string)) + { + Lisp_Object image_map, hotspot; + object = string; + if ((image_map = Fplist_get (XCDR (object), QCmap), + !NILP (image_map)) + && (hotspot = find_hot_spot (image_map, dx, dy), + CONSP (hotspot)) + && (hotspot = XCDR (hotspot), CONSP (hotspot))) + posn = XCAR (hotspot); + } +#endif } } -- cgit v1.2.1 From dea9b52152ce21296c22e996c29e80d3b542b450 Mon Sep 17 00:00:00 2001 From: Kim F. Storm Date: Sun, 28 Dec 2003 00:11:03 +0000 Subject: (IMAGEP): New macro to test for image object type. (Qimage): Declare extern. --- src/lisp.h | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'src') diff --git a/src/lisp.h b/src/lisp.h index 94de2c2960f..e1f939581db 100644 --- a/src/lisp.h +++ b/src/lisp.h @@ -1381,6 +1381,10 @@ typedef unsigned char UCHAR; #define GC_FRAMEP(x) GC_PSEUDOVECTORP (x, PVEC_FRAME) #define SUB_CHAR_TABLE_P(x) (CHAR_TABLE_P (x) && NILP (XCHAR_TABLE (x)->top)) + +/* Test for image (image . spec) */ +#define IMAGEP(x) (CONSP (x) && EQ (XCAR (x), Qimage)) + #define GC_EQ(x, y) EQ (x, y) @@ -2283,6 +2287,7 @@ extern Lisp_Object Qinhibit_point_motion_hooks; extern Lisp_Object Qinhibit_redisplay, Qdisplay; extern Lisp_Object Qinhibit_eval_during_redisplay; extern Lisp_Object Qmessage_truncate_lines; +extern Lisp_Object Qimage; extern Lisp_Object Vmessage_log_max; extern int message_enable_multibyte; extern Lisp_Object echo_area_buffer[2]; -- cgit v1.2.1 From 82cf95a792459f8dd7a1118f47c1a1dbec962bc9 Mon Sep 17 00:00:00 2001 From: Kim F. Storm Date: Sun, 28 Dec 2003 00:11:49 +0000 Subject: (Qimage): Remove extern (now in lisp.h). (valid_image_p, parse_image_spec): Use IMAGEP macro. --- src/macfns.c | 9 ++------- src/w32fns.c | 9 ++------- 2 files changed, 4 insertions(+), 14 deletions(-) (limited to 'src') diff --git a/src/macfns.c b/src/macfns.c index 1634809ca3e..0f87556fb1e 100644 --- a/src/macfns.c +++ b/src/macfns.c @@ -3460,11 +3460,6 @@ If DISPLAY is omitted or nil, that stands for the selected frame's display. */) static struct image_type *image_types; -/* The symbol `image' which is the car of the lists used to represent - images in Lisp. */ - -extern Lisp_Object Qimage; - /* The symbol `xbm' which is used as the type symbol for XBM images. */ Lisp_Object Qxbm; @@ -3543,7 +3538,7 @@ valid_image_p (object) { int valid_p = 0; - if (CONSP (object) && EQ (XCAR (object), Qimage)) + if (IMAGEP (object)) { Lisp_Object symbol = Fplist_get (XCDR (object), QCtype); struct image_type *type = lookup_image_type (symbol); @@ -3633,7 +3628,7 @@ parse_image_spec (spec, keywords, nkeywords, type) int i; Lisp_Object plist; - if (!CONSP (spec) || !EQ (XCAR (spec), Qimage)) + if (!IMAGEP (spec)) return 0; plist = XCDR (spec); diff --git a/src/w32fns.c b/src/w32fns.c index d8572265bef..7bffea34a28 100644 --- a/src/w32fns.c +++ b/src/w32fns.c @@ -6937,11 +6937,6 @@ DEFUN ("x-synchronize", Fx_synchronize, Sx_synchronize, 1, 2, 0, static struct image_type *image_types; -/* The symbol `image' which is the car of the lists used to represent - images in Lisp. */ - -extern Lisp_Object Qimage; - /* The symbol `xbm' which is used as the type symbol for XBM images. */ Lisp_Object Qxbm; @@ -7021,7 +7016,7 @@ valid_image_p (object) { int valid_p = 0; - if (CONSP (object) && EQ (XCAR (object), Qimage)) + if (IMAGEP (object)) { Lisp_Object tem; @@ -7123,7 +7118,7 @@ parse_image_spec (spec, keywords, nkeywords, type) int i; Lisp_Object plist; - if (!CONSP (spec) || !EQ (XCAR (spec), Qimage)) + if (!IMAGEP (spec)) return 0; plist = XCDR (spec); -- cgit v1.2.1 From 493fdc3cc3fad407c3ad3476d88658f6be8eb244 Mon Sep 17 00:00:00 2001 From: Kim F. Storm Date: Sun, 28 Dec 2003 00:12:27 +0000 Subject: (Qarrow, Qhand, Qtext, Qpointer): New variables for pointer types. (Qrelative_width, Qalign_to): Remove unused variables. (Vvoid_text_area_pointer): Replace Vshow_text_cursor_in_void. (QCmap, QCpointer, Qrect, Qcircle, Qpoly): New variables for image maps. (x_y_to_hpos_vpos): Return glyph relative coordinates through new dx and dy args. Remove buffer_only_p arg (always 0). Simplify code accordingly. (get_glyph_string_clip_rect): Draw cursor using glyph's rather than row's ascent and height, to get sensible height on tall rows. (build_desired_tool_bar_string): Remove Qimage extern. (get_tool_bar_item): Fix call to x_y_to_hpos_vpos. (produce_image_glyph): Adjust it.ascent to minimum row ascent if image glyph is alone on the last line. (append_glyph, append_composite_glyph, produce_image_glyph) (append_stretch_glyph): Set glyph's ascent and descent. (on_hot_spot_p): New function to check if position is inside an rectangular, circular, or polygon-shaped image hot-spot, (find_hot_spot): New function to search for image hot-spot. (Flookup_image_map): New defun to search for image hot-spot. (define_frame_cursor1): New aux function to determine frame pointer. (note_mode_line_or_margin_highlight, note_mouse_highlight): Handle `pointer' text property and :pointer image property to control frame pointer shape. Detect image hot-spots for pointer and help_echo properties. Use define_frame_cursor1. (note_mouse_highlight): Use Vvoid_text_area_pointer. (syms_of_xdisp): Defsubr new defun. Intern and staticpro new variables. DEFVAR_LISP Vvoid_text_area_pointer instead of Vshow_text_cursor_in_void. --- src/xdisp.c | 449 +++++++++++++++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 397 insertions(+), 52 deletions(-) (limited to 'src') diff --git a/src/xdisp.c b/src/xdisp.c index c2717552cc5..8a6f36ef17b 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -242,6 +242,9 @@ Lisp_Object Qbuffer_position, Qposition, Qobject; /* Cursor shapes */ Lisp_Object Qbar, Qhbar, Qbox, Qhollow; +/* Pointer shapes */ +Lisp_Object Qarrow, Qhand, Qtext; + Lisp_Object Qrisky_local_variable; /* Holds the list (error). */ @@ -290,7 +293,7 @@ int inhibit_eval_during_redisplay; /* Names of text properties relevant for redisplay. */ -Lisp_Object Qdisplay, Qrelative_width, Qalign_to; +Lisp_Object Qdisplay; extern Lisp_Object Qface, Qinvisible, Qwidth; /* Symbols used in text property values. */ @@ -298,7 +301,7 @@ extern Lisp_Object Qface, Qinvisible, Qwidth; Lisp_Object Vdisplay_pixels_per_inch; Lisp_Object Qspace, QCalign_to, QCrelative_width, QCrelative_height; Lisp_Object Qleft_margin, Qright_margin, Qspace_width, Qraise; -Lisp_Object Qmargin; +Lisp_Object Qmargin, Qpointer; extern Lisp_Object Qheight; extern Lisp_Object QCwidth, QCheight, QCascent; extern Lisp_Object Qscroll_bar; @@ -311,7 +314,7 @@ Lisp_Object Vshow_trailing_whitespace; i.e. in blank areas after eol and eob. This used to be the default in 21.3. */ -Lisp_Object Vshow_text_cursor_in_void; +Lisp_Object Vvoid_text_area_pointer; /* Name of the face used to highlight trailing whitespace. */ @@ -322,6 +325,10 @@ Lisp_Object Qtrailing_whitespace; Lisp_Object Qimage; +/* The image map types. */ +Lisp_Object QCmap, QCpointer; +Lisp_Object Qrect, Qcircle, Qpoly; + /* Non-zero means print newline to stdout before next mini-buffer message. */ @@ -1582,11 +1589,10 @@ glyph_to_pixel_coords (w, hpos, vpos, frame_x, frame_y) date. */ static struct glyph * -x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p) +x_y_to_hpos_vpos (w, x, y, hpos, vpos, dx, dy, area) struct window *w; int x, y; - int *hpos, *vpos, *area; - int buffer_only_p; + int *hpos, *vpos, *dx, *dy, *area; { struct glyph *glyph, *end; struct glyph_row *row = NULL; @@ -1637,23 +1643,22 @@ x_y_to_hpos_vpos (w, x, y, hpos, vpos, area, buffer_only_p) /* Find glyph containing X. */ glyph = row->glyphs[*area]; end = glyph + row->used[*area]; - while (glyph < end) + x -= x0; + while (glyph < end && x >= glyph->pixel_width) { - if (x < x0 + glyph->pixel_width) - { - if (w->pseudo_window_p) - break; - else if (!buffer_only_p || BUFFERP (glyph->object)) - break; - } - - x0 += glyph->pixel_width; + x -= glyph->pixel_width; ++glyph; } if (glyph == end) return NULL; + if (dx) + { + *dx = x; + *dy = y - (row->y + row->ascent - glyph->ascent); + } + *hpos = glyph - row->glyphs[*area]; return glyph; } @@ -1741,20 +1746,28 @@ get_glyph_string_clip_rect (s, nr) r.y = WINDOW_TO_FRAME_PIXEL_Y (s->w, r.y); -#ifdef HAVE_NTGUI - /* ++KFS: From W32 port, but it looks ok for all platforms to me. */ /* If drawing the cursor, don't let glyph draw outside its advertised boundaries. Cleartype does this under some circumstances. */ if (s->hl == DRAW_CURSOR) { + struct glyph *glyph = s->first_glyph; + int height; + if (s->x > r.x) { r.width -= s->x - r.x; r.x = s->x; } - r.width = min (r.width, s->first_glyph->pixel_width); + r.width = min (r.width, glyph->pixel_width); + + /* Don't draw cursor glyph taller than our actual glyph. */ + height = max (FRAME_LINE_HEIGHT (s->f), glyph->ascent + glyph->descent); + if (height < r.height) + { + r.y = s->ybase + glyph->descent - height; + r.height = height; + } } -#endif #ifdef CONVERT_FROM_XRECT CONVERT_FROM_XRECT (r, *nr); @@ -8279,7 +8292,7 @@ build_desired_tool_bar_string (f) int enabled_p = !NILP (PROP (TOOL_BAR_ITEM_ENABLED_P)); int selected_p = !NILP (PROP (TOOL_BAR_ITEM_SELECTED_P)); int hmargin, vmargin, relief, idx, end; - extern Lisp_Object QCrelief, QCmargin, QCconversion, Qimage; + extern Lisp_Object QCrelief, QCmargin, QCconversion; /* If image is a vector, choose the image according to the button state. */ @@ -8696,7 +8709,7 @@ get_tool_bar_item (f, x, y, glyph, hpos, vpos, prop_idx) int area; /* Find the glyph under X/Y. */ - *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, &area, 0); + *glyph = x_y_to_hpos_vpos (w, x, y, hpos, vpos, 0, 0, &area); if (*glyph == NULL) return -1; @@ -17685,6 +17698,8 @@ append_glyph (it) glyph->charpos = CHARPOS (it->position); glyph->object = it->object; glyph->pixel_width = it->pixel_width; + glyph->ascent = it->ascent; + glyph->descent = it->descent; glyph->voffset = it->voffset; glyph->type = CHAR_GLYPH; glyph->multibyte_p = it->multibyte_p; @@ -17719,6 +17734,8 @@ append_composite_glyph (it) glyph->charpos = CHARPOS (it->position); glyph->object = it->object; glyph->pixel_width = it->pixel_width; + glyph->ascent = it->ascent; + glyph->descent = it->descent; glyph->voffset = it->voffset; glyph->type = COMPOSITE_GLYPH; glyph->multibyte_p = it->multibyte_p; @@ -17767,6 +17784,7 @@ produce_image_glyph (it) { struct image *img; struct face *face; + int face_ascent, glyph_ascent; xassert (it->what == IT_IMAGE); @@ -17778,10 +17796,15 @@ produce_image_glyph (it) PREPARE_FACE_FOR_DISPLAY (it->f, face); prepare_image_for_display (it->f, img); - it->ascent = it->phys_ascent = image_ascent (img, face); + it->ascent = it->phys_ascent = glyph_ascent = image_ascent (img, face); it->descent = it->phys_descent = img->height + 2 * img->vmargin - it->ascent; it->pixel_width = img->width + 2 * img->hmargin; + /* If this glyph is alone on the last line, adjust it.ascent to minimum row ascent. */ + face_ascent = face->font ? FONT_BASE (face->font) : FRAME_BASELINE_OFFSET (it->f); + if (face_ascent > it->ascent) + it->ascent = it->phys_ascent = face_ascent; + it->nglyphs = 1; if (face->box != FACE_NO_BOX) @@ -17811,6 +17834,8 @@ produce_image_glyph (it) glyph->charpos = CHARPOS (it->position); glyph->object = it->object; glyph->pixel_width = it->pixel_width; + glyph->ascent = glyph_ascent; + glyph->descent = it->descent; glyph->voffset = it->voffset; glyph->type = IMAGE_GLYPH; glyph->multibyte_p = it->multibyte_p; @@ -17850,6 +17875,8 @@ append_stretch_glyph (it, object, width, height, ascent) glyph->charpos = CHARPOS (it->position); glyph->object = object; glyph->pixel_width = width; + glyph->ascent = ascent; + glyph->descent = height - ascent; glyph->voffset = it->voffset; glyph->type = STRETCH_GLYPH; glyph->multibyte_p = it->multibyte_p; @@ -19945,6 +19972,189 @@ fast_find_string_pos (w, pos, object, hpos, vpos, x, y, right_p) } +/* See if position X, Y is within a hot-spot of an image. */ + +static int +on_hot_spot_p (hot_spot, x, y) + Lisp_Object hot_spot; + int x, y; +{ + if (!CONSP (hot_spot)) + return 0; + + if (EQ (XCAR (hot_spot), Qrect)) + { + /* CDR is (Top-Left . Bottom-Right) = ((x0 . y0) . (x1 . y1)) */ + Lisp_Object rect = XCDR (hot_spot); + Lisp_Object tem; + if (!CONSP (rect)) + return 0; + if (!CONSP (XCAR (rect))) + return 0; + if (!CONSP (XCDR (rect))) + return 0; + if (!(tem = XCAR (XCAR (rect)), INTEGERP (tem) && x >= XINT (tem))) + return 0; + if (!(tem = XCDR (XCAR (rect)), INTEGERP (tem) && y >= XINT (tem))) + return 0; + if (!(tem = XCAR (XCDR (rect)), INTEGERP (tem) && x <= XINT (tem))) + return 0; + if (!(tem = XCDR (XCDR (rect)), INTEGERP (tem) && y <= XINT (tem))) + return 0; + return 1; + } + else if (EQ (XCAR (hot_spot), Qcircle)) + { + /* CDR is (Center . Radius) = ((x0 . y0) . r) */ + Lisp_Object circ = XCDR (hot_spot); + Lisp_Object lr, lx0, ly0; + if (CONSP (circ) + && CONSP (XCAR (circ)) + && (lr = XCDR (circ), INTEGERP (lr) || FLOATP (lr)) + && (lx0 = XCAR (XCAR (circ)), INTEGERP (lx0)) + && (ly0 = XCDR (XCAR (circ)), INTEGERP (ly0))) + { + double r = XFLOATINT (lr); + double dx = XINT (lx0) - x; + double dy = XINT (ly0) - y; + return (dx * dx + dy * dy <= r * r); + } + } + else if (EQ (XCAR (hot_spot), Qpoly)) + { + /* CDR is [x0 y0 x1 y1 x2 y2 ...x(n-1) y(n-1)] */ + if (VECTORP (XCDR (hot_spot))) + { + struct Lisp_Vector *v = XVECTOR (XCDR (hot_spot)); + Lisp_Object *poly = v->contents; + int n = v->size; + int i; + int inside = 0; + Lisp_Object lx, ly; + int x0, y0; + + /* Need an even number of coordinates, and at least 3 edges. */ + if (n < 6 || n & 1) + return 0; + + /* Count edge segments intersecting line from (X,Y) to (X,infinity). + If count is odd, we are inside polygon. Pixels on edges + may or may not be included depending on actual geometry of the + polygon. */ + if ((lx = poly[n-2], !INTEGERP (lx)) + || (ly = poly[n-1], !INTEGERP (lx))) + return 0; + x0 = XINT (lx), y0 = XINT (ly); + for (i = 0; i < n; i += 2) + { + int x1 = x0, y1 = y0; + if ((lx = poly[i], !INTEGERP (lx)) + || (ly = poly[i+1], !INTEGERP (ly))) + return 0; + x0 = XINT (lx), y0 = XINT (ly); + + /* Does this segment cross the X line? */ + if (x0 >= x) + { + if (x1 >= x) + continue; + } + else if (x1 < x) + continue; + if (y > y0 && y > y1) + continue; + if (y < y0 + ((y1 - y0) * (x - x0)) / (x1 - x0)) + inside = !inside; + } + return inside; + } + } + else + return 0; +} + +Lisp_Object +find_hot_spot (map, x, y) + Lisp_Object map; + int x, y; +{ + while (CONSP (map)) + { + if (CONSP (XCAR (map)) + && on_hot_spot_p (XCAR (XCAR (map)), x, y)) + return XCAR (map); + map = XCDR (map); + } + + return Qnil; +} + +DEFUN ("lookup-image-map", Flookup_image_map, Slookup_image_map, + 3, 3, 0, + doc: /* Lookup in image map MAP coordinates X and Y. +An image map is an alist where each element has the format (AREA ID PLIST). +An AREA is specified as either a rectangle, a circle, or a polygon: +A rectangle is a cons (rect . ((x0 . y0) . (x1 . y1))) specifying the +pixel coordinates of the upper left and bottom right corners. +A circle is a cons (circle . ((x0 . y0) . r)) specifying the center +and the radius of the circle; r may be a float or integer. +A polygon is a cons (poly . [x0 y0 x1 y1 ...]) where each pair in the +vector describes one corner in the polygon. +Returns the alist element for the first matching AREA in MAP. */) + (map, x, y) + Lisp_Object map; + Lisp_Object x, y; +{ + int ix, iy; + if (NILP (map)) + return Qnil; + + if (!INTEGERP (x)) + wrong_type_argument (Qintegerp, x); + if (!INTEGERP (y)) + wrong_type_argument (Qintegerp, y); + + return find_hot_spot (map, XINT (x), XINT (y)); +} + + +/* Display frame CURSOR, optionally using shape defined by POINTER. */ +static void +define_frame_cursor1 (f, cursor, pointer) + struct frame *f; + Cursor cursor; + Lisp_Object pointer; +{ + if (!NILP (pointer)) + { + if (EQ (pointer, Qarrow)) + cursor = FRAME_X_OUTPUT (f)->nontext_cursor; + else if (EQ (pointer, Qhand)) + cursor = FRAME_X_OUTPUT (f)->hand_cursor; + else if (EQ (pointer, Qtext)) + cursor = FRAME_X_OUTPUT (f)->text_cursor; + else if (EQ (pointer, intern ("hdrag"))) + cursor = FRAME_X_OUTPUT (f)->horizontal_drag_cursor; +#ifdef HAVE_X_WINDOWS + else if (EQ (pointer, intern ("vdrag"))) + cursor = FRAME_X_DISPLAY_INFO (f)->vertical_scroll_bar_cursor; +#endif + else if (EQ (pointer, intern ("hourglass"))) + cursor = FRAME_X_OUTPUT (f)->hourglass_cursor; + else if (EQ (pointer, Qmodeline)) + cursor = FRAME_X_OUTPUT (f)->modeline_cursor; + else + cursor = FRAME_X_OUTPUT (f)->nontext_cursor; + } + +#ifndef HAVE_CARBON + if (cursor != No_Cursor) +#else + if (bcmp (&cursor, &No_Cursor, sizeof (Cursor))) +#endif + rif->define_frame_cursor (f, cursor); +} + /* Take proper action when mouse has moved to the mode or header line or marginal area AREA of window W, x-position X and y-position Y. X is relative to the start of the text display area of W, so the @@ -19960,18 +20170,24 @@ note_mode_line_or_margin_highlight (w, x, y, area) struct frame *f = XFRAME (w->frame); Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f); Cursor cursor = FRAME_X_OUTPUT (f)->nontext_cursor; - int charpos; - Lisp_Object string, help, map, pos; + Lisp_Object pointer = Qnil; + int charpos, dx, dy; + Lisp_Object string; + Lisp_Object pos, help, image; if (area == ON_MODE_LINE || area == ON_HEADER_LINE) string = mode_line_string (w, &x, &y, 0, 0, area, &charpos); else - string = marginal_area_string (w, &x, &y, 0, 0, area, &charpos); + { + x -= WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w); + string = marginal_area_string (w, &x, &y, &dx, &dy, area, &charpos); + } + + help = Qnil; if (STRINGP (string)) { pos = make_number (charpos); - /* If we're on a string with `help-echo' text property, arrange for the help to be displayed. This is done by setting the global variable help_echo_string to the help string. */ @@ -19984,9 +20200,13 @@ note_mode_line_or_margin_highlight (w, x, y, area) help_echo_pos = charpos; } + if (NILP (pointer)) + pointer = Fget_text_property (pos, Qpointer, string); + /* Change the mouse pointer according to what is under X/Y. */ - if (area == ON_MODE_LINE) + if (NILP (pointer) && area == ON_MODE_LINE) { + Lisp_Object map; map = Fget_text_property (pos, Qlocal_map, string); if (!KEYMAPP (map)) map = Fget_text_property (pos, Qkeymap, string); @@ -19994,8 +20214,42 @@ note_mode_line_or_margin_highlight (w, x, y, area) cursor = dpyinfo->vertical_scroll_bar_cursor; } } + else if (IMAGEP (string)) + { + Lisp_Object image_map, hotspot; + if ((image_map = Fplist_get (XCDR (string), QCmap), + !NILP (image_map)) + && (hotspot = find_hot_spot (image_map, dx, dy), + CONSP (hotspot)) + && (hotspot = XCDR (hotspot), CONSP (hotspot))) + { + Lisp_Object area_id, plist; - rif->define_frame_cursor (f, cursor); + area_id = XCAR (hotspot); + /* Could check AREA_ID to see if we enter/leave this hot-spot. + If so, we could look for mouse-enter, mouse-leave + properties in PLIST (and do something...). */ + if ((plist = XCDR (hotspot), CONSP (plist))) + { + pointer = Fplist_get (plist, Qpointer); + if (NILP (pointer)) + pointer = Qhand; + help = Fplist_get (plist, Qhelp_echo); + if (!NILP (help)) + { + help_echo_string = help; + /* Is this correct? ++kfs */ + XSETWINDOW (help_echo_window, w); + help_echo_object = w->buffer; + help_echo_pos = charpos; + } + } + if (NILP (pointer)) + pointer = Fplist_get (XCDR (string), QCpointer); + } + } + + define_frame_cursor1 (f, cursor, pointer); } @@ -20015,6 +20269,7 @@ note_mouse_highlight (f, x, y) Lisp_Object window; struct window *w; Cursor cursor = No_Cursor; + Lisp_Object pointer = Qnil; /* Takes precedence over cursor! */ struct buffer *b; /* When a menu is active, don't highlight because this looks odd. */ @@ -20052,7 +20307,6 @@ note_mouse_highlight (f, x, y) return; /* Reset help_echo_string. It will get recomputed below. */ - /* ++KFS: X version didn't do this, but it looks harmless. */ help_echo_string = Qnil; /* Convert to window-relative pixel coordinates. */ @@ -20090,7 +20344,7 @@ note_mouse_highlight (f, x, y) && XFASTINT (w->last_modified) == BUF_MODIFF (b) && XFASTINT (w->last_overlay_modified) == BUF_OVERLAY_MODIFF (b)) { - int hpos, vpos, pos, i, area; + int hpos, vpos, pos, i, dx, dy, area; struct glyph *glyph; Lisp_Object object; Lisp_Object mouse_face = Qnil, overlay = Qnil, position; @@ -20100,7 +20354,45 @@ note_mouse_highlight (f, x, y) int obegv, ozv, same_region; /* Find the glyph under X/Y. */ - glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &area, 0); + glyph = x_y_to_hpos_vpos (w, x, y, &hpos, &vpos, &dx, &dy, &area); + + /* Look for :pointer property on image. */ + if (glyph != NULL && glyph->type == IMAGE_GLYPH) + { + struct image *img = IMAGE_FROM_ID (f, glyph->u.img_id); + if (img != NULL && IMAGEP (img->spec)) + { + Lisp_Object image_map, hotspot; + if ((image_map = Fplist_get (XCDR (img->spec), QCmap), + !NILP (image_map)) + && (hotspot = find_hot_spot (image_map, dx, dy), + CONSP (hotspot)) + && (hotspot = XCDR (hotspot), CONSP (hotspot))) + { + Lisp_Object area_id, plist; + + area_id = XCAR (hotspot); + /* Could check AREA_ID to see if we enter/leave this hot-spot. + If so, we could look for mouse-enter, mouse-leave + properties in PLIST (and do something...). */ + if ((plist = XCDR (hotspot), CONSP (plist))) + { + pointer = Fplist_get (plist, Qpointer); + if (NILP (pointer)) + pointer = Qhand; + help_echo_string = Fplist_get (plist, Qhelp_echo); + if (!NILP (help_echo_string)) + { + help_echo_window = window; + help_echo_object = glyph->object; + help_echo_pos = glyph->charpos; + } + } + } + if (NILP (pointer)) + pointer = Fplist_get (XCDR (img->spec), QCpointer); + } + } /* Clear mouse face if X/Y not over text. */ if (glyph == NULL @@ -20109,8 +20401,13 @@ note_mouse_highlight (f, x, y) { if (clear_mouse_face (dpyinfo)) cursor = No_Cursor; - if (NILP (Vshow_text_cursor_in_void)) - cursor = FRAME_X_OUTPUT (f)->nontext_cursor; + if (NILP (pointer)) + { + if (area != TEXT_AREA) + cursor = FRAME_X_OUTPUT (f)->nontext_cursor; + else + pointer = Vvoid_text_area_pointer; + } goto set_cursor; } @@ -20123,9 +20420,6 @@ note_mouse_highlight (f, x, y) if (BUFFERP (object) && pos > BUF_Z (b)) goto set_cursor; - if (glyph->type == IMAGE_GLYPH) - cursor = FRAME_X_OUTPUT (f)->nontext_cursor; - /* Make the window's buffer temporarily current for overlays_at and compute_char_face. */ obuf = current_buffer; @@ -20369,7 +20663,7 @@ note_mouse_highlight (f, x, y) check_help_echo: /* Look for a `help-echo' property. */ - { + if (NILP (help_echo_string)) { Lisp_Object help, overlay; /* Check overlays first. */ @@ -20435,6 +20729,46 @@ note_mouse_highlight (f, x, y) } } + /* Look for a `pointer' property. */ + if (NILP (pointer)) + { + /* Check overlays first. */ + for (i = noverlays - 1; i >= 0 && NILP (pointer); --i) + pointer = Foverlay_get (overlay_vec[i], Qpointer); + + if (NILP (pointer)) + { + Lisp_Object object = glyph->object; + int charpos = glyph->charpos; + + /* Try text properties. */ + if (STRINGP (object) + && charpos >= 0 + && charpos < SCHARS (object)) + { + pointer = Fget_text_property (make_number (charpos), + Qpointer, object); + if (NILP (pointer)) + { + /* If the string itself doesn't specify a pointer, + see if the buffer text ``under'' it does. */ + struct glyph_row *r + = MATRIX_ROW (w->current_matrix, vpos); + int start = MATRIX_ROW_START_CHARPOS (r); + int pos = string_buffer_position (w, object, start); + if (pos > 0) + pointer = Fget_char_property (make_number (pos), + Qpointer, w->buffer); + } + } + else if (BUFFERP (object) + && charpos >= BEGV + && charpos < ZV) + pointer = Fget_text_property (make_number (charpos), + Qpointer, object); + } + } + BEGV = obegv; ZV = ozv; current_buffer = obuf; @@ -20442,12 +20776,7 @@ note_mouse_highlight (f, x, y) set_cursor: -#ifndef HAVE_CARBON - if (cursor != No_Cursor) -#else - if (bcmp (&cursor, &No_Cursor, sizeof (Cursor))) -#endif - rif->define_frame_cursor (f, cursor); + define_frame_cursor1 (f, cursor, pointer); } @@ -21043,6 +21372,7 @@ syms_of_xdisp () #endif #ifdef HAVE_WINDOW_SYSTEM defsubr (&Stool_bar_lines_needed); + defsubr (&Slookup_image_map); #endif defsubr (&Sformat_mode_line); @@ -21076,16 +21406,14 @@ syms_of_xdisp () staticpro (&Qspace); Qmargin = intern ("margin"); staticpro (&Qmargin); + Qpointer = intern ("pointer"); + staticpro (&Qpointer); Qleft_margin = intern ("left-margin"); staticpro (&Qleft_margin); Qright_margin = intern ("right-margin"); staticpro (&Qright_margin); - Qalign_to = intern ("align-to"); - staticpro (&Qalign_to); QCalign_to = intern (":align-to"); staticpro (&QCalign_to); - Qrelative_width = intern ("relative-width"); - staticpro (&Qrelative_width); QCrelative_width = intern (":relative-width"); staticpro (&QCrelative_width); QCrelative_height = intern (":relative-height"); @@ -21104,6 +21432,16 @@ syms_of_xdisp () staticpro (&Qtrailing_whitespace); Qimage = intern ("image"); staticpro (&Qimage); + QCmap = intern (":map"); + staticpro (&QCmap); + QCpointer = intern (":pointer"); + staticpro (&QCpointer); + Qrect = intern ("rect"); + staticpro (&Qrect); + Qcircle = intern ("circle"); + staticpro (&Qcircle); + Qpoly = intern ("poly"); + staticpro (&Qpoly); Qmessage_truncate_lines = intern ("message-truncate-lines"); staticpro (&Qmessage_truncate_lines); Qcursor_in_non_selected_windows = intern ("cursor-in-non-selected-windows"); @@ -21128,6 +21466,12 @@ syms_of_xdisp () staticpro (&Qbox); Qhollow = intern ("hollow"); staticpro (&Qhollow); + Qhand = intern ("hand"); + staticpro (&Qhand); + Qarrow = intern ("arrow"); + staticpro (&Qarrow); + Qtext = intern ("text"); + staticpro (&Qtext); Qrisky_local_variable = intern ("risky-local-variable"); staticpro (&Qrisky_local_variable); Qinhibit_free_realized_faces = intern ("inhibit-free-realized-faces"); @@ -21181,10 +21525,11 @@ wide as that tab on the display. */); The face used for trailing whitespace is `trailing-whitespace'. */); Vshow_trailing_whitespace = Qnil; - DEFVAR_LISP ("show-text-cursor-in-void", &Vshow_text_cursor_in_void, - doc: /* Non-nil means show the text cursor in void text areas. -The default is to show the non-text (typically arrow) cursor. */); - Vshow_text_cursor_in_void = Qnil; + DEFVAR_LISP ("void-text-area-pointer", &Vvoid_text_area_pointer, + doc: /* The pointer shape to show in void text areas. +Nil means to show the text pointer. Other options are `arrow', `text', +`hand', `vdrag', `hdrag', `modeline', and `hourglass'. */); + Vvoid_text_area_pointer = Qarrow; DEFVAR_LISP ("inhibit-redisplay", &Vinhibit_redisplay, doc: /* Non-nil means don't actually do any redisplay. -- cgit v1.2.1 From d7078aefa029a7f6beea9fb0803305600ab7d0f5 Mon Sep 17 00:00:00 2001 From: Kim F. Storm Date: Sun, 28 Dec 2003 00:12:45 +0000 Subject: (cache_face): Abort if c->size exceeds MAX_FACE_ID. --- src/xfaces.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'src') diff --git a/src/xfaces.c b/src/xfaces.c index f079e2e4484..55455abdbd7 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -5577,12 +5577,19 @@ cache_face (c, face, hash) face->id = i; /* Maybe enlarge C->faces_by_id. */ - if (i == c->used && c->used == c->size) + if (i == c->used) { - int new_size = 2 * c->size; - int sz = new_size * sizeof *c->faces_by_id; - c->faces_by_id = (struct face **) xrealloc (c->faces_by_id, sz); - c->size = new_size; + if (c->used == c->size) + { + int new_size, sz; + new_size = min (2 * c->size, MAX_FACE_ID); + if (new_size == c->size) + abort (); /* Alternatives? ++kfs */ + sz = new_size * sizeof *c->faces_by_id; + c->faces_by_id = (struct face **) xrealloc (c->faces_by_id, sz); + c->size = new_size; + } + c->used++; } #if GLYPH_DEBUG @@ -5601,8 +5608,6 @@ cache_face (c, face, hash) #endif /* GLYPH_DEBUG */ c->faces_by_id[i] = face; - if (i == c->used) - ++c->used; } -- cgit v1.2.1 From 15aa58c18e557ead24010b7c9f78bd94d5579cf8 Mon Sep 17 00:00:00 2001 From: Kim F. Storm Date: Sun, 28 Dec 2003 00:13:10 +0000 Subject: (x_set_mouse_color): Remove bogus x_check_errors call. (Qimage): Remove extern (now in lisp.h). (valid_image_p, parse_image_spec): Use IMAGEP macro. --- src/xfns.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/xfns.c b/src/xfns.c index cd50cbbc919..e940b16eba1 100644 --- a/src/xfns.c +++ b/src/xfns.c @@ -1300,7 +1300,6 @@ x_set_mouse_color (f, arg, oldval) hourglass_cursor = XCreateFontCursor (dpy, XC_watch); x_check_errors (dpy, "bad hourglass pointer cursor: %s"); - x_check_errors (dpy, "bad nontext pointer cursor: %s"); if (!NILP (Vx_mode_pointer_shape)) { CHECK_NUMBER (Vx_mode_pointer_shape); @@ -4416,11 +4415,6 @@ the excessive values are ignored. */) static struct image_type *image_types; -/* The symbol `image' which is the car of the lists used to represent - images in Lisp. */ - -extern Lisp_Object Qimage; - /* The symbol `xbm' which is used as the type symbol for XBM images. */ Lisp_Object Qxbm; @@ -4500,7 +4494,7 @@ valid_image_p (object) { int valid_p = 0; - if (CONSP (object) && EQ (XCAR (object), Qimage)) + if (IMAGEP (object)) { Lisp_Object tem; @@ -4602,7 +4596,7 @@ parse_image_spec (spec, keywords, nkeywords, type) int i; Lisp_Object plist; - if (!CONSP (spec) || !EQ (XCAR (spec), Qimage)) + if (!IMAGEP (spec)) return 0; plist = XCDR (spec); -- cgit v1.2.1 From 83c6eb57fcd9dc47e0d9ec84d40be5235985736c Mon Sep 17 00:00:00 2001 From: Kim F. Storm Date: Sun, 28 Dec 2003 00:13:34 +0000 Subject: (Qface, Qmouse_face): Remove unused externs. (x_draw_hollow_cursor): Draw cursor using glyph's rather than row's ascent and descent, to get a sensible height on tall rows. --- src/xterm.c | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/xterm.c b/src/xterm.c index a3117846702..635ba643035 100644 --- a/src/xterm.c +++ b/src/xterm.c @@ -287,7 +287,7 @@ extern Lisp_Object Vcommand_line_args, Vsystem_name; extern Lisp_Object Vx_no_window_manager; -extern Lisp_Object Qface, Qmouse_face, Qeql; +extern Lisp_Object Qeql; extern int errno; @@ -7271,13 +7271,6 @@ x_draw_hollow_cursor (w, row) struct glyph *cursor_glyph; GC gc; - /* Compute frame-relative coordinates from window-relative - coordinates. */ - x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); - y = (WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y) - + row->ascent - w->phys_cursor_ascent); - h = row->height - 1; - /* Get the glyph the cursor is on. If we can't tell because the current matrix is invalid or such, give up. */ cursor_glyph = get_phys_cursor_glyph (w); @@ -7294,6 +7287,19 @@ x_draw_hollow_cursor (w, row) wd = min (FRAME_COLUMN_WIDTH (f), wd); w->phys_cursor_width = wd; + /* Compute frame-relative coordinates from window-relative + coordinates. */ + x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x); + y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y); + + /* Compute the proper height and ascent of the rectangle, based + on the actual glyph. Using the full height of the row looks + bad when there are tall images on that row. */ + h = max (FRAME_LINE_HEIGHT (f), cursor_glyph->ascent + cursor_glyph->descent); + if (h < row->height) + y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h; + h--; + /* The foreground of cursor_gc is typically the same as the normal background color, which can cause the cursor box to be invisible. */ xgcv.foreground = f->output_data.x->cursor_pixel; -- cgit v1.2.1 From 204fb75e80e828ddcc944a41907a7fcd69099964 Mon Sep 17 00:00:00 2001 From: Kim F. Storm Date: Sun, 28 Dec 2003 00:15:01 +0000 Subject: Fix cursor glyph height on tall rows. Add image map feature. Add pointer text property. --- src/ChangeLog | 77 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 77 insertions(+) (limited to 'src') diff --git a/src/ChangeLog b/src/ChangeLog index fc1445a46dd..53cc3b8ad2f 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,80 @@ +2003-12-28 Kim F. Storm + + * Makefile.in (eval.o): Depend on dispextern.h. + + * dispnew.c (buffer_posn_from_coords): Fix calculation of dy for + image glyph using image's ascent. + (mode_line_string): Return image glyph as object clicked on. + Adjust y0 for image glyph using image's ascent. + + * dispextern.h (FACE_ID_BITS, MAX_FACE_ID): New defines. + (struct glyph): New members, ascent and descent. Used to save + this glyph's ascent and descent, instead of having. + (struct glyph): Declare member face_id using FACE_ID_BITS. + (find_hot_spot): Add prototype. + + * keyboard.c (Qimage): Remove extern (now in lisp.h). + (QCmap): Declare extern. + (make_lispy_position): When position is inside image hot-spot, + use hot-spot element's id as posn element. + + * lisp.h (IMAGEP): New macro to test for image object type. + (Qimage): Declare extern. + + * macfns.c (Qimage): Remove extern (now in lisp.h). + (valid_image_p, parse_image_spec): Use IMAGEP macro. + + * macterm.c (Qface, Qmouse_face): Remove unused externs. + + * w32fns.c (Qimage): Remove extern (now in lisp.h). + (valid_image_p, parse_image_spec): Use IMAGEP macro. + + * w32menu.c (Qmouse_click, Qevent_kind): Remove unused externs. + + * w32term.c (Qface, Qmouse_face): Remove unused externs. + + * xdisp.c (Qarrow, Qhand, Qtext, Qpointer): New variables for + pointer types. + (Qrelative_width, Qalign_to): Remove unused variables. + (Vvoid_text_area_pointer): Replace Vshow_text_cursor_in_void. + (QCmap, QCpointer, Qrect, Qcircle, Qpoly): New variables for + image maps. + (x_y_to_hpos_vpos): Return glyph relative coordinates through + new dx and dy args. + Remove buffer_only_p arg (always 0). Simplify code accordingly. + (get_glyph_string_clip_rect): Draw cursor using glyph's rather + than row's ascent and height, to get sensible height on tall rows. + (build_desired_tool_bar_string): Remove Qimage extern. + (get_tool_bar_item): Fix call to x_y_to_hpos_vpos. + (produce_image_glyph): Adjust it.ascent to minimum row ascent if + image glyph is alone on the last line. + (append_glyph, append_composite_glyph, produce_image_glyph) + (append_stretch_glyph): Set glyph's ascent and descent. + (on_hot_spot_p): New function to check if position is inside an + rectangular, circular, or polygon-shaped image hot-spot, + (find_hot_spot): New function to search for image hot-spot. + (Flookup_image_map): New defun to search for image hot-spot. + (define_frame_cursor1): New aux function to determine frame pointer. + (note_mode_line_or_margin_highlight, note_mouse_highlight): + Handle `pointer' text property and :pointer image property to + control frame pointer shape. Detect image hot-spots for pointer + and help_echo properties. Use define_frame_cursor1. + (note_mouse_highlight): Use Vvoid_text_area_pointer. + (syms_of_xdisp): Defsubr new defun. Intern and staticpro new variables. + DEFVAR_LISP Vvoid_text_area_pointer instead of Vshow_text_cursor_in_void. + + * xfaces.c (cache_face): Abort if c->size exceeds MAX_FACE_ID. + + * xfns.c (x_set_mouse_color): Remove bogus x_check_errors call. + (Qimage): Remove extern (now in lisp.h). + (valid_image_p, parse_image_spec): Use IMAGEP macro. + + * xmenu.c (show_help_event): Remove unused code. + + * xterm.c (Qface, Qmouse_face): Remove unused externs. + (x_draw_hollow_cursor): Draw cursor using glyph's rather than + row's ascent and descent, to get a sensible height on tall rows. + 2003-12-25 Luc Teirlinck * minibuf.c (Fcompleting_read): Undo previous change. -- cgit v1.2.1