]> code.delx.au - gnu-emacs/blob - src/macterm.c
* macterm.c (mac_to_x_fontname): Removed spurious argument.
[gnu-emacs] / src / macterm.c
1 /* Implementation of GUI terminal on the Mac OS.
2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005 Free Software Foundation, Inc.
3
4 This file is part of GNU Emacs.
5
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
8 the Free Software Foundation; either version 2, or (at your option)
9 any later version.
10
11 GNU Emacs is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with GNU Emacs; see the file COPYING. If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA. */
20
21 /* Contributed by Andrew Choi (akochoi@mac.com). */
22
23 #include <config.h>
24 #include <signal.h>
25 #include <stdio.h>
26 #include <stdlib.h>
27 #include "lisp.h"
28 #include "charset.h"
29 #include "blockinput.h"
30
31 #include "macterm.h"
32
33 #ifndef MAC_OSX
34 #include <alloca.h>
35 #endif
36
37 #ifdef MAC_OSX
38 /* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to
39 obtain events from the event queue. If set to 0, WaitNextEvent is
40 used instead. */
41 #define USE_CARBON_EVENTS 1
42 #else /* not MAC_OSX */
43 #include <Quickdraw.h>
44 #include <ToolUtils.h>
45 #include <Sound.h>
46 #include <Events.h>
47 #include <Script.h>
48 #include <Resources.h>
49 #include <Fonts.h>
50 #include <TextUtils.h>
51 #include <LowMem.h>
52 #include <Controls.h>
53 #include <Windows.h>
54 #if defined (__MRC__) || (__MSL__ >= 0x6000)
55 #include <ControlDefinitions.h>
56 #endif
57
58 #if __profile__
59 #include <profiler.h>
60 #endif
61 #endif /* not MAC_OSX */
62
63 #include "systty.h"
64 #include "systime.h"
65 #include "atimer.h"
66 #include "keymap.h"
67
68 #include <ctype.h>
69 #include <errno.h>
70 #include <setjmp.h>
71 #include <sys/stat.h>
72 #include <sys/param.h>
73
74 #include "keyboard.h"
75 #include "frame.h"
76 #include "dispextern.h"
77 #include "fontset.h"
78 #include "termhooks.h"
79 #include "termopts.h"
80 #include "termchar.h"
81 #include "gnu.h"
82 #include "disptab.h"
83 #include "buffer.h"
84 #include "window.h"
85 #include "intervals.h"
86 #include "composite.h"
87 #include "coding.h"
88
89 /* Set of macros that handle mapping of Mac modifier keys to emacs. */
90 #define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
91 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
92 #define macShiftKey (shiftKey)
93 #define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
94 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
95 : controlKey)
96 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
97
98 \f
99
100 /* Non-nil means Emacs uses toolkit scroll bars. */
101
102 Lisp_Object Vx_toolkit_scroll_bars;
103
104 /* If Non-nil, the text will be rendered using Core Graphics text rendering which may anti-alias the text. */
105 Lisp_Object Vmac_use_core_graphics;
106
107
108 /* Non-zero means that a HELP_EVENT has been generated since Emacs
109 start. */
110
111 static int any_help_event_p;
112
113 /* Non-zero means autoselect window with the mouse cursor. */
114
115 int x_autoselect_window_p;
116
117 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
118
119 int x_use_underline_position_properties;
120
121 /* Non-zero means draw block and hollow cursor as wide as the glyph
122 under it. For example, if a block cursor is over a tab, it will be
123 drawn as wide as that tab on the display. */
124
125
126 /* This is a chain of structures for all the X displays currently in
127 use. */
128
129 struct x_display_info *x_display_list;
130
131 /* This is a list of cons cells, each of the form (NAME
132 . FONT-LIST-CACHE), one for each element of x_display_list and in
133 the same order. NAME is the name of the frame. FONT-LIST-CACHE
134 records previous values returned by x-list-fonts. */
135
136 Lisp_Object x_display_name_list;
137
138 /* This is display since Mac does not support multiple ones. */
139 struct mac_display_info one_mac_display_info;
140
141 /* Frame being updated by update_frame. This is declared in term.c.
142 This is set by update_begin and looked at by all the XT functions.
143 It is zero while not inside an update. In that case, the XT
144 functions assume that `selected_frame' is the frame to apply to. */
145
146 extern struct frame *updating_frame;
147
148 extern int waiting_for_input;
149
150 /* This is a frame waiting to be auto-raised, within XTread_socket. */
151
152 struct frame *pending_autoraise_frame;
153
154 /* Non-zero means user is interacting with a toolkit scroll bar. */
155
156 static int toolkit_scroll_bar_interaction;
157
158 /* Mouse movement.
159
160 Formerly, we used PointerMotionHintMask (in standard_event_mask)
161 so that we would have to call XQueryPointer after each MotionNotify
162 event to ask for another such event. However, this made mouse tracking
163 slow, and there was a bug that made it eventually stop.
164
165 Simply asking for MotionNotify all the time seems to work better.
166
167 In order to avoid asking for motion events and then throwing most
168 of them away or busy-polling the server for mouse positions, we ask
169 the server for pointer motion hints. This means that we get only
170 one event per group of mouse movements. "Groups" are delimited by
171 other kinds of events (focus changes and button clicks, for
172 example), or by XQueryPointer calls; when one of these happens, we
173 get another MotionNotify event the next time the mouse moves. This
174 is at least as efficient as getting motion events when mouse
175 tracking is on, and I suspect only negligibly worse when tracking
176 is off. */
177
178 /* Where the mouse was last time we reported a mouse event. */
179
180 static Rect last_mouse_glyph;
181 static Lisp_Object last_mouse_press_frame;
182
183 /* The scroll bar in which the last X motion event occurred.
184
185 If the last X motion event occurred in a scroll bar, we set this so
186 XTmouse_position can know whether to report a scroll bar motion or
187 an ordinary motion.
188
189 If the last X motion event didn't occur in a scroll bar, we set
190 this to Qnil, to tell XTmouse_position to return an ordinary motion
191 event. */
192
193 static Lisp_Object last_mouse_scroll_bar;
194
195 /* This is a hack. We would really prefer that XTmouse_position would
196 return the time associated with the position it returns, but there
197 doesn't seem to be any way to wrest the time-stamp from the server
198 along with the position query. So, we just keep track of the time
199 of the last movement we received, and return that in hopes that
200 it's somewhat accurate. */
201
202 static Time last_mouse_movement_time;
203
204 struct scroll_bar *tracked_scroll_bar = NULL;
205
206 /* Incremented by XTread_socket whenever it really tries to read
207 events. */
208
209 #ifdef __STDC__
210 static int volatile input_signal_count;
211 #else
212 static int input_signal_count;
213 #endif
214
215 /* Used locally within XTread_socket. */
216
217 static int x_noop_count;
218
219 /* Initial values of argv and argc. */
220
221 extern char **initial_argv;
222 extern int initial_argc;
223
224 extern Lisp_Object Vcommand_line_args, Vsystem_name;
225
226 /* Tells if a window manager is present or not. */
227
228 extern Lisp_Object Vx_no_window_manager;
229
230 extern int errno;
231
232 /* A mask of extra modifier bits to put into every keyboard char. */
233
234 extern int extra_keyboard_modifiers;
235
236 /* The keysyms to use for the various modifiers. */
237
238 static Lisp_Object Qalt, Qhyper, Qsuper, Qmodifier_value;
239
240 static Lisp_Object Qvendor_specific_keysyms;
241
242 #if 0
243 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
244 #endif
245
246 extern int inhibit_window_system;
247
248 #if __MRC__
249 QDGlobals qd; /* QuickDraw global information structure. */
250 #endif
251
252
253 struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
254 struct mac_display_info *mac_display_info_for_display (Display *);
255 static void x_update_window_end P_ ((struct window *, int, int));
256 static void mac_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
257 static int x_io_error_quitter P_ ((Display *));
258 int x_catch_errors P_ ((Display *));
259 void x_uncatch_errors P_ ((Display *, int));
260 void x_lower_frame P_ ((struct frame *));
261 void x_scroll_bar_clear P_ ((struct frame *));
262 int x_had_errors_p P_ ((Display *));
263 void x_wm_set_size_hint P_ ((struct frame *, long, int));
264 void x_raise_frame P_ ((struct frame *));
265 void x_set_window_size P_ ((struct frame *, int, int, int));
266 void x_wm_set_window_state P_ ((struct frame *, int));
267 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
268 void mac_initialize P_ ((void));
269 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
270 static int x_compute_min_glyph_bounds P_ ((struct frame *));
271 static void x_update_end P_ ((struct frame *));
272 static void XTframe_up_to_date P_ ((struct frame *));
273 static void XTreassert_line_highlight P_ ((int, int));
274 static void x_change_line_highlight P_ ((int, int, int, int));
275 static void XTset_terminal_modes P_ ((void));
276 static void XTreset_terminal_modes P_ ((void));
277 static void x_clear_frame P_ ((void));
278 static void frame_highlight P_ ((struct frame *));
279 static void frame_unhighlight P_ ((struct frame *));
280 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
281 static void XTframe_rehighlight P_ ((struct frame *));
282 static void x_frame_rehighlight P_ ((struct x_display_info *));
283 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
284 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
285 enum text_cursor_kinds));
286
287 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC));
288 static void x_flush P_ ((struct frame *f));
289 static void x_update_begin P_ ((struct frame *));
290 static void x_update_window_begin P_ ((struct window *));
291 static void x_after_update_window_line P_ ((struct glyph_row *));
292
293 void activate_scroll_bars (FRAME_PTR);
294 void deactivate_scroll_bars (FRAME_PTR);
295
296 static int is_emacs_window (WindowPtr);
297
298 int x_bitmap_icon (struct frame *, Lisp_Object);
299 void x_make_frame_visible (struct frame *);
300
301 extern void window_scroll (Lisp_Object, int, int, int);
302
303 /* Defined in macmenu.h. */
304 extern void menubar_selection_callback (FRAME_PTR, int);
305 extern void set_frame_menubar (FRAME_PTR, int, int);
306
307 /* X display function emulation */
308
309 void
310 XFreePixmap (display, pixmap)
311 Display *display; /* not used */
312 Pixmap pixmap;
313 {
314 DisposeGWorld (pixmap);
315 }
316
317
318 /* Set foreground color for subsequent QuickDraw commands. Assume
319 graphic port has already been set. */
320
321 static void
322 mac_set_forecolor (unsigned long color)
323 {
324 RGBColor fg_color;
325
326 fg_color.red = RED16_FROM_ULONG (color);
327 fg_color.green = GREEN16_FROM_ULONG (color);
328 fg_color.blue = BLUE16_FROM_ULONG (color);
329
330 RGBForeColor (&fg_color);
331 }
332
333
334 /* Set background color for subsequent QuickDraw commands. Assume
335 graphic port has already been set. */
336
337 static void
338 mac_set_backcolor (unsigned long color)
339 {
340 RGBColor bg_color;
341
342 bg_color.red = RED16_FROM_ULONG (color);
343 bg_color.green = GREEN16_FROM_ULONG (color);
344 bg_color.blue = BLUE16_FROM_ULONG (color);
345
346 RGBBackColor (&bg_color);
347 }
348
349 /* Set foreground and background color for subsequent QuickDraw
350 commands. Assume that the graphic port has already been set. */
351
352 static void
353 mac_set_colors (GC gc)
354 {
355 mac_set_forecolor (gc->foreground);
356 mac_set_backcolor (gc->background);
357 }
358
359 /* Mac version of XDrawLine. */
360
361 static void
362 XDrawLine (display, w, gc, x1, y1, x2, y2)
363 Display *display;
364 WindowPtr w;
365 GC gc;
366 int x1, y1, x2, y2;
367 {
368 SetPortWindowPort (w);
369
370 mac_set_colors (gc);
371
372 MoveTo (x1, y1);
373 LineTo (x2, y2);
374 }
375
376 void
377 mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2)
378 Display *display;
379 Pixmap p;
380 GC gc;
381 int x1, y1, x2, y2;
382 {
383 CGrafPtr old_port;
384 GDHandle old_gdh;
385
386 GetGWorld (&old_port, &old_gdh);
387 SetGWorld (p, NULL);
388
389 mac_set_colors (gc);
390
391 LockPixels (GetGWorldPixMap (p));
392 MoveTo (x1, y1);
393 LineTo (x2, y2);
394 UnlockPixels (GetGWorldPixMap (p));
395
396 SetGWorld (old_port, old_gdh);
397 }
398
399 /* Mac version of XClearArea. */
400
401 void
402 XClearArea (display, w, x, y, width, height, exposures)
403 Display *display;
404 WindowPtr w;
405 int x, y;
406 unsigned int width, height;
407 int exposures;
408 {
409 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
410 Rect r;
411 XGCValues xgc;
412
413 xgc.foreground = mwp->x_compatible.foreground_pixel;
414 xgc.background = mwp->x_compatible.background_pixel;
415
416 SetPortWindowPort (w);
417
418 mac_set_colors (&xgc);
419 SetRect (&r, x, y, x + width, y + height);
420
421 EraseRect (&r);
422 }
423
424 /* Mac version of XClearWindow. */
425
426 static void
427 XClearWindow (display, w)
428 Display *display;
429 WindowPtr w;
430 {
431 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
432 XGCValues xgc;
433
434 xgc.foreground = mwp->x_compatible.foreground_pixel;
435 xgc.background = mwp->x_compatible.background_pixel;
436
437 SetPortWindowPort (w);
438
439 mac_set_colors (&xgc);
440
441 #if TARGET_API_MAC_CARBON
442 {
443 Rect r;
444
445 GetWindowPortBounds (w, &r);
446 EraseRect (&r);
447 }
448 #else /* not TARGET_API_MAC_CARBON */
449 EraseRect (&(w->portRect));
450 #endif /* not TARGET_API_MAC_CARBON */
451 }
452
453
454 /* Mac replacement for XCopyArea. */
455
456 static void
457 mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p)
458 Display *display;
459 WindowPtr w;
460 GC gc;
461 int x, y, width, height;
462 unsigned short *bits;
463 int overlay_p;
464 {
465 BitMap bitmap;
466 Rect r;
467
468 bitmap.rowBytes = sizeof(unsigned short);
469 bitmap.baseAddr = (char *)bits;
470 SetRect (&(bitmap.bounds), 0, 0, width, height);
471
472 SetPortWindowPort (w);
473
474 mac_set_colors (gc);
475 SetRect (&r, x, y, x + width, y + height);
476
477 #if TARGET_API_MAC_CARBON
478 LockPortBits (GetWindowPort (w));
479 CopyBits (&bitmap, GetPortBitMapForCopyBits (GetWindowPort (w)),
480 &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
481 UnlockPortBits (GetWindowPort (w));
482 #else /* not TARGET_API_MAC_CARBON */
483 CopyBits (&bitmap, &(w->portBits), &(bitmap.bounds), &r,
484 overlay_p ? srcOr : srcCopy, 0);
485 #endif /* not TARGET_API_MAC_CARBON */
486 }
487
488
489 /* Mac replacement for XSetClipRectangles. */
490
491 static void
492 mac_set_clip_rectangle (display, w, r)
493 Display *display;
494 WindowPtr w;
495 Rect *r;
496 {
497 SetPortWindowPort (w);
498
499 ClipRect (r);
500 }
501
502
503 /* Mac replacement for XSetClipMask. */
504
505 static void
506 mac_reset_clipping (display, w)
507 Display *display;
508 WindowPtr w;
509 {
510 Rect r;
511
512 SetPortWindowPort (w);
513
514 SetRect (&r, -32767, -32767, 32767, 32767);
515 ClipRect (&r);
516 }
517
518
519 /* Mac replacement for XCreateBitmapFromBitmapData. */
520
521 static void
522 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
523 BitMap *bitmap;
524 char *bits;
525 int w, h;
526 {
527 static unsigned char swap_nibble[16]
528 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */
529 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */
530 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */
531 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */
532 int i, j, w1;
533 char *p;
534
535 w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */
536 bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
537 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
538 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
539 for (i = 0; i < h; i++)
540 {
541 p = bitmap->baseAddr + i * bitmap->rowBytes;
542 for (j = 0; j < w1; j++)
543 {
544 /* Bitswap XBM bytes to match how Mac does things. */
545 unsigned char c = *bits++;
546 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4)
547 | (swap_nibble[(c>>4) & 0xf]));;
548 }
549 }
550
551 SetRect (&(bitmap->bounds), 0, 0, w, h);
552 }
553
554
555 static void
556 mac_free_bitmap (bitmap)
557 BitMap *bitmap;
558 {
559 xfree (bitmap->baseAddr);
560 }
561
562
563 Pixmap
564 XCreatePixmap (display, w, width, height, depth)
565 Display *display; /* not used */
566 WindowPtr w;
567 unsigned int width, height;
568 unsigned int depth;
569 {
570 Pixmap pixmap;
571 Rect r;
572 QDErr err;
573
574 SetPortWindowPort (w);
575
576 SetRect (&r, 0, 0, width, height);
577 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
578 if (err != noErr)
579 return NULL;
580 return pixmap;
581 }
582
583
584 Pixmap
585 XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
586 Display *display; /* not used */
587 WindowPtr w;
588 char *data;
589 unsigned int width, height;
590 unsigned long fg, bg;
591 unsigned int depth; /* not used */
592 {
593 Pixmap pixmap;
594 BitMap bitmap;
595 CGrafPtr old_port;
596 GDHandle old_gdh;
597
598 pixmap = XCreatePixmap (display, w, width, height, depth);
599 if (pixmap == NULL)
600 return NULL;
601
602 GetGWorld (&old_port, &old_gdh);
603 SetGWorld (pixmap, NULL);
604 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
605 mac_set_forecolor (fg);
606 mac_set_backcolor (bg);
607 LockPixels (GetGWorldPixMap (pixmap));
608 #if TARGET_API_MAC_CARBON
609 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
610 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
611 #else /* not TARGET_API_MAC_CARBON */
612 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
613 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
614 #endif /* not TARGET_API_MAC_CARBON */
615 UnlockPixels (GetGWorldPixMap (pixmap));
616 SetGWorld (old_port, old_gdh);
617 mac_free_bitmap (&bitmap);
618
619 return pixmap;
620 }
621
622
623 /* Mac replacement for XFillRectangle. */
624
625 static void
626 XFillRectangle (display, w, gc, x, y, width, height)
627 Display *display;
628 WindowPtr w;
629 GC gc;
630 int x, y;
631 unsigned int width, height;
632 {
633 Rect r;
634
635 SetPortWindowPort (w);
636
637 mac_set_colors (gc);
638 SetRect (&r, x, y, x + width, y + height);
639
640 PaintRect (&r); /* using foreground color of gc */
641 }
642
643
644 #if 0 /* TODO: figure out if we need to do this on Mac. */
645 static void
646 mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height)
647 Display *display;
648 Pixmap p;
649 GC gc;
650 int x, y;
651 unsigned int width, height;
652 {
653 CGrafPtr old_port;
654 GDHandle old_gdh;
655 Rect r;
656
657 GetGWorld (&old_port, &old_gdh);
658 SetGWorld (p, NULL);
659 mac_set_colors (gc);
660 SetRect (&r, x, y, x + width, y + height);
661
662 LockPixels (GetGWorldPixMap (p));
663 PaintRect (&r); /* using foreground color of gc */
664 UnlockPixels (GetGWorldPixMap (p));
665
666 SetGWorld (old_port, old_gdh);
667 }
668 #endif
669
670
671 /* Mac replacement for XDrawRectangle: dest is a window. */
672
673 static void
674 mac_draw_rectangle (display, w, gc, x, y, width, height)
675 Display *display;
676 WindowPtr w;
677 GC gc;
678 int x, y;
679 unsigned int width, height;
680 {
681 Rect r;
682
683 SetPortWindowPort (w);
684
685 mac_set_colors (gc);
686 SetRect (&r, x, y, x + width + 1, y + height + 1);
687
688 FrameRect (&r); /* using foreground color of gc */
689 }
690
691
692 #if 0 /* TODO: figure out if we need to do this on Mac. */
693 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
694
695 static void
696 mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
697 Display *display;
698 Pixmap p;
699 GC gc;
700 int x, y;
701 unsigned int width, height;
702 {
703 CGrafPtr old_port;
704 GDHandle old_gdh;
705 Rect r;
706
707 GetGWorld (&old_port, &old_gdh);
708 SetGWorld (p, NULL);
709 mac_set_colors (gc);
710 SetRect (&r, x, y, x + width + 1, y + height + 1);
711
712 LockPixels (GetGWorldPixMap (p));
713 FrameRect (&r); /* using foreground color of gc */
714 UnlockPixels (GetGWorldPixMap (p));
715
716 SetGWorld (old_port, old_gdh);
717 }
718 #endif
719
720
721 static void
722 mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
723 bytes_per_char)
724 Display *display;
725 WindowPtr w;
726 GC gc;
727 int x, y;
728 char *buf;
729 int nchars, mode, bytes_per_char;
730 {
731 SetPortWindowPort (w);
732 #ifdef MAC_OS_X_VERSION_10_2
733 UInt32 textFlags, savedFlags;
734 if (!NILP(Vmac_use_core_graphics)) {
735 textFlags = kQDUseCGTextRendering;
736 savedFlags = SwapQDTextFlags(textFlags);
737 }
738 #endif
739
740 mac_set_colors (gc);
741
742 TextFont (gc->font->mac_fontnum);
743 TextSize (gc->font->mac_fontsize);
744 TextFace (gc->font->mac_fontface);
745 TextMode (mode);
746
747 MoveTo (x, y);
748 DrawText (buf, 0, nchars * bytes_per_char);
749 #ifdef MAC_OS_X_VERSION_10_2
750 if (!NILP(Vmac_use_core_graphics))
751 SwapQDTextFlags(savedFlags);
752 #endif
753 }
754
755
756 /* Mac replacement for XDrawString. */
757
758 static void
759 XDrawString (display, w, gc, x, y, buf, nchars)
760 Display *display;
761 WindowPtr w;
762 GC gc;
763 int x, y;
764 char *buf;
765 int nchars;
766 {
767 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
768 }
769
770
771 /* Mac replacement for XDrawString16. */
772
773 static void
774 XDrawString16 (display, w, gc, x, y, buf, nchars)
775 Display *display;
776 WindowPtr w;
777 GC gc;
778 int x, y;
779 XChar2b *buf;
780 int nchars;
781 {
782 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
783 2);
784 }
785
786
787 /* Mac replacement for XDrawImageString. */
788
789 static void
790 XDrawImageString (display, w, gc, x, y, buf, nchars)
791 Display *display;
792 WindowPtr w;
793 GC gc;
794 int x, y;
795 char *buf;
796 int nchars;
797 {
798 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
799 }
800
801
802 /* Mac replacement for XDrawString16. */
803
804 static void
805 XDrawImageString16 (display, w, gc, x, y, buf, nchars)
806 Display *display;
807 WindowPtr w;
808 GC gc;
809 int x, y;
810 XChar2b *buf;
811 int nchars;
812 {
813 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
814 2);
815 }
816
817
818 /* Mac replacement for XCopyArea: dest must be window. */
819
820 static void
821 mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
822 dest_y)
823 Display *display;
824 Pixmap src;
825 WindowPtr dest;
826 GC gc;
827 int src_x, src_y;
828 unsigned int width, height;
829 int dest_x, dest_y;
830 {
831 Rect src_r, dest_r;
832
833 SetPortWindowPort (dest);
834
835 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
836 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
837
838 ForeColor (blackColor);
839 BackColor (whiteColor);
840
841 LockPixels (GetGWorldPixMap (src));
842 #if TARGET_API_MAC_CARBON
843 LockPortBits (GetWindowPort (dest));
844 CopyBits (GetPortBitMapForCopyBits (src),
845 GetPortBitMapForCopyBits (GetWindowPort (dest)),
846 &src_r, &dest_r, srcCopy, 0);
847 UnlockPortBits (GetWindowPort (dest));
848 #else /* not TARGET_API_MAC_CARBON */
849 CopyBits (&(((GrafPtr)src)->portBits), &(dest->portBits),
850 &src_r, &dest_r, srcCopy, 0);
851 #endif /* not TARGET_API_MAC_CARBON */
852 UnlockPixels (GetGWorldPixMap (src));
853 }
854
855
856 static void
857 mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
858 width, height, dest_x, dest_y)
859 Display *display;
860 Pixmap src, mask;
861 WindowPtr dest;
862 GC gc;
863 int src_x, src_y;
864 unsigned int width, height;
865 int dest_x, dest_y;
866 {
867 Rect src_r, dest_r;
868
869 SetPortWindowPort (dest);
870
871 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
872 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
873
874 ForeColor (blackColor);
875 BackColor (whiteColor);
876
877 LockPixels (GetGWorldPixMap (src));
878 LockPixels (GetGWorldPixMap (mask));
879 #if TARGET_API_MAC_CARBON
880 LockPortBits (GetWindowPort (dest));
881 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
882 GetPortBitMapForCopyBits (GetWindowPort (dest)),
883 &src_r, &src_r, &dest_r);
884 UnlockPortBits (GetWindowPort (dest));
885 #else /* not TARGET_API_MAC_CARBON */
886 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
887 &(dest->portBits), &src_r, &src_r, &dest_r);
888 #endif /* not TARGET_API_MAC_CARBON */
889 UnlockPixels (GetGWorldPixMap (mask));
890 UnlockPixels (GetGWorldPixMap (src));
891 }
892
893
894 #if 0
895 /* Convert a pair of local coordinates to global (screen) coordinates.
896 Assume graphic port has been properly set. */
897 static void
898 local_to_global_coord (short *h, short *v)
899 {
900 Point p;
901
902 p.h = *h;
903 p.v = *v;
904
905 LocalToGlobal (&p);
906
907 *h = p.h;
908 *v = p.v;
909 }
910 #endif
911
912 /* Mac replacement for XCopyArea: used only for scrolling. */
913
914 static void
915 mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
916 Display *display;
917 WindowPtr w;
918 GC gc;
919 int src_x, src_y;
920 unsigned int width, height;
921 int dest_x, dest_y;
922 {
923 #if TARGET_API_MAC_CARBON
924 Rect src_r;
925 RgnHandle dummy = NewRgn (); /* For avoiding update events. */
926
927 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
928 ScrollWindowRect (w, &src_r, dest_x - src_x, dest_y - src_y,
929 kScrollWindowNoOptions, dummy);
930 DisposeRgn (dummy);
931 #else /* not TARGET_API_MAC_CARBON */
932 Rect src_r, dest_r;
933
934 SetPort (w);
935 #if 0
936 mac_set_colors (gc);
937 #endif
938
939 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
940 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
941
942 #if 0
943 /* Need to use global coordinates and screenBits since src and dest
944 areas overlap in general. */
945 local_to_global_coord (&src_r.left, &src_r.top);
946 local_to_global_coord (&src_r.right, &src_r.bottom);
947 local_to_global_coord (&dest_r.left, &dest_r.top);
948 local_to_global_coord (&dest_r.right, &dest_r.bottom);
949
950 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
951 #else
952 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
953 color mapping in CopyBits. Otherwise, it will be slow. */
954 ForeColor (blackColor);
955 BackColor (whiteColor);
956 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
957
958 mac_set_colors (gc);
959 #endif
960 #endif /* not TARGET_API_MAC_CARBON */
961 }
962
963
964 #if 0 /* TODO: figure out if we need to do this on Mac. */
965 /* Mac replacement for XCopyArea: dest must be Pixmap. */
966
967 static void
968 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
969 dest_x, dest_y)
970 Display *display;
971 Pixmap src, dest;
972 GC gc;
973 int src_x, src_y;
974 unsigned int width, height;
975 int dest_x, dest_y;
976 {
977 CGrafPtr old_port;
978 GDHandle old_gdh;
979 Rect src_r, dest_r;
980
981 GetGWorld (&old_port, &old_gdh);
982 SetGWorld (dest, NULL);
983 ForeColor (blackColor);
984 BackColor (whiteColor);
985
986 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
987 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
988
989 LockPixels (GetGWorldPixMap (src));
990 LockPixels (GetGWorldPixMap (dest));
991 #if TARGET_API_MAC_CARBON
992 CopyBits (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (dest),
993 &src_r, &dest_r, srcCopy, 0);
994 #else /* not TARGET_API_MAC_CARBON */
995 CopyBits (&(((GrafPtr)src)->portBits), &(((GrafPtr)dest)->portBits),
996 &src_r, &dest_r, srcCopy, 0);
997 #endif /* not TARGET_API_MAC_CARBON */
998 UnlockPixels (GetGWorldPixMap (dest));
999 UnlockPixels (GetGWorldPixMap (src));
1000
1001 SetGWorld (old_port, old_gdh);
1002 }
1003
1004
1005 static void
1006 mac_copy_area_with_mask_to_pixmap (display, src, mask, dest, gc, src_x, src_y,
1007 width, height, dest_x, dest_y)
1008 Display *display;
1009 Pixmap src, mask, dest;
1010 GC gc;
1011 int src_x, src_y;
1012 unsigned int width, height;
1013 int dest_x, dest_y;
1014 {
1015 CGrafPtr old_port;
1016 GDHandle old_gdh;
1017 Rect src_r, dest_r;
1018
1019 GetGWorld (&old_port, &old_gdh);
1020 SetGWorld (dest, NULL);
1021 ForeColor (blackColor);
1022 BackColor (whiteColor);
1023
1024 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1025 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1026
1027 LockPixels (GetGWorldPixMap (src));
1028 LockPixels (GetGWorldPixMap (mask));
1029 LockPixels (GetGWorldPixMap (dest));
1030 #if TARGET_API_MAC_CARBON
1031 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
1032 GetPortBitMapForCopyBits (dest), &src_r, &src_r, &dest_r);
1033 #else /* not TARGET_API_MAC_CARBON */
1034 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
1035 &(((GrafPtr)dest)->portBits), &src_r, &src_r, &dest_r);
1036 #endif /* not TARGET_API_MAC_CARBON */
1037 UnlockPixels (GetGWorldPixMap (dest));
1038 UnlockPixels (GetGWorldPixMap (mask));
1039 UnlockPixels (GetGWorldPixMap (src));
1040
1041 SetGWorld (old_port, old_gdh);
1042 }
1043 #endif
1044
1045
1046 /* Mac replacement for XChangeGC. */
1047
1048 static void
1049 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
1050 XGCValues *xgcv)
1051 {
1052 if (mask & GCForeground)
1053 gc->foreground = xgcv->foreground;
1054 if (mask & GCBackground)
1055 gc->background = xgcv->background;
1056 if (mask & GCFont)
1057 gc->font = xgcv->font;
1058 }
1059
1060
1061 /* Mac replacement for XCreateGC. */
1062
1063 XGCValues *
1064 XCreateGC (void * ignore, Window window, unsigned long mask,
1065 XGCValues *xgcv)
1066 {
1067 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
1068 bzero (gc, sizeof (XGCValues));
1069
1070 XChangeGC (ignore, gc, mask, xgcv);
1071
1072 return gc;
1073 }
1074
1075
1076 /* Used in xfaces.c. */
1077
1078 void
1079 XFreeGC (display, gc)
1080 Display *display;
1081 GC gc;
1082 {
1083 xfree (gc);
1084 }
1085
1086
1087 /* Mac replacement for XGetGCValues. */
1088
1089 static void
1090 XGetGCValues (void* ignore, XGCValues *gc,
1091 unsigned long mask, XGCValues *xgcv)
1092 {
1093 XChangeGC (ignore, xgcv, mask, gc);
1094 }
1095
1096
1097 /* Mac replacement for XSetForeground. */
1098
1099 void
1100 XSetForeground (display, gc, color)
1101 Display *display;
1102 GC gc;
1103 unsigned long color;
1104 {
1105 gc->foreground = color;
1106 }
1107
1108
1109 /* Mac replacement for XSetBackground. */
1110
1111 void
1112 XSetBackground (display, gc, color)
1113 Display *display;
1114 GC gc;
1115 unsigned long color;
1116 {
1117 gc->background = color;
1118 }
1119
1120
1121 /* Mac replacement for XSetWindowBackground. */
1122
1123 void
1124 XSetWindowBackground (display, w, color)
1125 Display *display;
1126 WindowPtr w;
1127 unsigned long color;
1128 {
1129 #if !TARGET_API_MAC_CARBON
1130 AuxWinHandle aw_handle;
1131 CTabHandle ctab_handle;
1132 ColorSpecPtr ct_table;
1133 short ct_size;
1134 #endif
1135 RGBColor bg_color;
1136
1137 bg_color.red = RED16_FROM_ULONG (color);
1138 bg_color.green = GREEN16_FROM_ULONG (color);
1139 bg_color.blue = BLUE16_FROM_ULONG (color);
1140
1141 #if TARGET_API_MAC_CARBON
1142 SetWindowContentColor (w, &bg_color);
1143 #else
1144 if (GetAuxWin (w, &aw_handle))
1145 {
1146 ctab_handle = (*aw_handle)->awCTable;
1147 HandToHand ((Handle *) &ctab_handle);
1148 ct_table = (*ctab_handle)->ctTable;
1149 ct_size = (*ctab_handle)->ctSize;
1150 while (ct_size > -1)
1151 {
1152 if (ct_table->value == 0)
1153 {
1154 ct_table->rgb = bg_color;
1155 CTabChanged (ctab_handle);
1156 SetWinColor (w, (WCTabHandle) ctab_handle);
1157 }
1158 ct_size--;
1159 }
1160 }
1161 #endif
1162 }
1163
1164
1165 /* Mac replacement for XSetFont. */
1166
1167 static void
1168 XSetFont (display, gc, font)
1169 Display *display;
1170 GC gc;
1171 XFontStruct *font;
1172 {
1173 gc->font = font;
1174 }
1175
1176
1177 static void
1178 XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
1179 int *direction,int *font_ascent,
1180 int *font_descent, XCharStruct *cs)
1181 {
1182 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1183 }
1184
1185
1186 /* x_sync is a no-op on Mac. */
1187 void
1188 x_sync (f)
1189 void *f;
1190 {
1191 }
1192
1193
1194 /* Flush display of frame F, or of all frames if F is null. */
1195
1196 static void
1197 x_flush (f)
1198 struct frame *f;
1199 {
1200 #if TARGET_API_MAC_CARBON
1201 BLOCK_INPUT;
1202 if (f)
1203 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL);
1204 else
1205 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL);
1206 UNBLOCK_INPUT;
1207 #endif
1208 }
1209
1210
1211 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1212 Calls to XFlush should be unnecessary because the X output buffer
1213 is flushed automatically as needed by calls to XPending,
1214 XNextEvent, or XWindowEvent according to the XFlush man page.
1215 XTread_socket calls XPending. Removing XFlush improves
1216 performance. */
1217
1218 #define XFlush(DISPLAY) (void) 0
1219
1220 \f
1221 /* Return the struct mac_display_info corresponding to DPY. There's
1222 only one. */
1223
1224 struct mac_display_info *
1225 mac_display_info_for_display (dpy)
1226 Display *dpy;
1227 {
1228 return &one_mac_display_info;
1229 }
1230
1231
1232 \f
1233 /***********************************************************************
1234 Starting and ending an update
1235 ***********************************************************************/
1236
1237 /* Start an update of frame F. This function is installed as a hook
1238 for update_begin, i.e. it is called when update_begin is called.
1239 This function is called prior to calls to x_update_window_begin for
1240 each window being updated. */
1241
1242 static void
1243 x_update_begin (f)
1244 struct frame *f;
1245 {
1246 #if TARGET_API_MAC_CARBON
1247 /* During update of a frame, availability of input events is
1248 periodically checked with ReceiveNextEvent if
1249 redisplay-dont-pause is nil. That normally flushes window buffer
1250 changes for every check, and thus screen update looks waving even
1251 if no input is available. So we disable screen updates during
1252 update of a frame. */
1253 BLOCK_INPUT;
1254 DisableScreenUpdates ();
1255 UNBLOCK_INPUT;
1256 #endif
1257 }
1258
1259
1260 /* Start update of window W. Set the global variable updated_window
1261 to the window being updated and set output_cursor to the cursor
1262 position of W. */
1263
1264 static void
1265 x_update_window_begin (w)
1266 struct window *w;
1267 {
1268 struct frame *f = XFRAME (WINDOW_FRAME (w));
1269 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1270
1271 updated_window = w;
1272 set_output_cursor (&w->cursor);
1273
1274 BLOCK_INPUT;
1275
1276 if (f == display_info->mouse_face_mouse_frame)
1277 {
1278 /* Don't do highlighting for mouse motion during the update. */
1279 display_info->mouse_face_defer = 1;
1280
1281 /* If F needs to be redrawn, simply forget about any prior mouse
1282 highlighting. */
1283 if (FRAME_GARBAGED_P (f))
1284 display_info->mouse_face_window = Qnil;
1285
1286 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1287 their mouse_face_p flag set, which means that they are always
1288 unequal to rows in a desired matrix which never have that
1289 flag set. So, rows containing mouse-face glyphs are never
1290 scrolled, and we don't have to switch the mouse highlight off
1291 here to prevent it from being scrolled. */
1292
1293 /* Can we tell that this update does not affect the window
1294 where the mouse highlight is? If so, no need to turn off.
1295 Likewise, don't do anything if the frame is garbaged;
1296 in that case, the frame's current matrix that we would use
1297 is all wrong, and we will redisplay that line anyway. */
1298 if (!NILP (display_info->mouse_face_window)
1299 && w == XWINDOW (display_info->mouse_face_window))
1300 {
1301 int i;
1302
1303 for (i = 0; i < w->desired_matrix->nrows; ++i)
1304 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1305 break;
1306
1307 if (i < w->desired_matrix->nrows)
1308 clear_mouse_face (display_info);
1309 }
1310 #endif /* 0 */
1311 }
1312
1313 UNBLOCK_INPUT;
1314 }
1315
1316
1317 /* Draw a vertical window border from (x,y0) to (x,y1) */
1318
1319 static void
1320 mac_draw_vertical_window_border (w, x, y0, y1)
1321 struct window *w;
1322 int x, y0, y1;
1323 {
1324 struct frame *f = XFRAME (WINDOW_FRAME (w));
1325
1326 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1327 f->output_data.mac->normal_gc, x, y0, x, y1);
1328 }
1329
1330
1331 /* End update of window W (which is equal to updated_window).
1332
1333 Draw vertical borders between horizontally adjacent windows, and
1334 display W's cursor if CURSOR_ON_P is non-zero.
1335
1336 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1337 glyphs in mouse-face were overwritten. In that case we have to
1338 make sure that the mouse-highlight is properly redrawn.
1339
1340 W may be a menu bar pseudo-window in case we don't have X toolkit
1341 support. Such windows don't have a cursor, so don't display it
1342 here. */
1343
1344 static void
1345 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1346 struct window *w;
1347 int cursor_on_p, mouse_face_overwritten_p;
1348 {
1349 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1350
1351 if (!w->pseudo_window_p)
1352 {
1353 BLOCK_INPUT;
1354
1355 if (cursor_on_p)
1356 display_and_set_cursor (w, 1, output_cursor.hpos,
1357 output_cursor.vpos,
1358 output_cursor.x, output_cursor.y);
1359
1360 if (draw_window_fringes (w, 1))
1361 x_draw_vertical_border (w);
1362
1363 UNBLOCK_INPUT;
1364 }
1365
1366 /* If a row with mouse-face was overwritten, arrange for
1367 XTframe_up_to_date to redisplay the mouse highlight. */
1368 if (mouse_face_overwritten_p)
1369 {
1370 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1371 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1372 dpyinfo->mouse_face_window = Qnil;
1373 }
1374
1375 #if 0
1376 /* Unhide the caret. This won't actually show the cursor, unless it
1377 was visible before the corresponding call to HideCaret in
1378 x_update_window_begin. */
1379 if (w32_use_visible_system_caret)
1380 SendMessage (w32_system_caret_hwnd, WM_EMACS_SHOW_CARET, 0, 0);
1381 #endif
1382
1383 updated_window = NULL;
1384 }
1385
1386
1387 /* End update of frame F. This function is installed as a hook in
1388 update_end. */
1389
1390 static void
1391 x_update_end (f)
1392 struct frame *f;
1393 {
1394 /* Mouse highlight may be displayed again. */
1395 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1396
1397 BLOCK_INPUT;
1398 /* Reset the background color of Mac OS Window to that of the frame after
1399 update so that it is used by Mac Toolbox to clear the update region before
1400 an update event is generated. */
1401 SetPortWindowPort (FRAME_MAC_WINDOW (f));
1402
1403 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
1404
1405 #if TARGET_API_MAC_CARBON
1406 EnableScreenUpdates ();
1407 #endif
1408 XFlush (FRAME_MAC_DISPLAY (f));
1409 UNBLOCK_INPUT;
1410 }
1411
1412
1413 /* This function is called from various places in xdisp.c whenever a
1414 complete update has been performed. The global variable
1415 updated_window is not available here. */
1416
1417 static void
1418 XTframe_up_to_date (f)
1419 struct frame *f;
1420 {
1421 if (FRAME_MAC_P (f))
1422 {
1423 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
1424
1425 if (dpyinfo->mouse_face_deferred_gc
1426 || f == dpyinfo->mouse_face_mouse_frame)
1427 {
1428 BLOCK_INPUT;
1429 if (dpyinfo->mouse_face_mouse_frame)
1430 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1431 dpyinfo->mouse_face_mouse_x,
1432 dpyinfo->mouse_face_mouse_y);
1433 dpyinfo->mouse_face_deferred_gc = 0;
1434 UNBLOCK_INPUT;
1435 }
1436 }
1437 }
1438
1439
1440 /* Draw truncation mark bitmaps, continuation mark bitmaps, overlay
1441 arrow bitmaps, or clear the fringes if no bitmaps are required
1442 before DESIRED_ROW is made current. The window being updated is
1443 found in updated_window. This function is called from
1444 update_window_line only if it is known that there are differences
1445 between bitmaps to be drawn between current row and DESIRED_ROW. */
1446
1447 static void
1448 x_after_update_window_line (desired_row)
1449 struct glyph_row *desired_row;
1450 {
1451 struct window *w = updated_window;
1452 struct frame *f;
1453 int width, height;
1454
1455 xassert (w);
1456
1457 if (!desired_row->mode_line_p && !w->pseudo_window_p)
1458 desired_row->redraw_fringe_bitmaps_p = 1;
1459
1460 /* When a window has disappeared, make sure that no rest of
1461 full-width rows stays visible in the internal border. Could
1462 check here if updated_window is the leftmost/rightmost window,
1463 but I guess it's not worth doing since vertically split windows
1464 are almost never used, internal border is rarely set, and the
1465 overhead is very small. */
1466 if (windows_or_buffers_changed
1467 && desired_row->full_width_p
1468 && (f = XFRAME (w->frame),
1469 width = FRAME_INTERNAL_BORDER_WIDTH (f),
1470 width != 0)
1471 && (height = desired_row->visible_height,
1472 height > 0))
1473 {
1474 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
1475 /* Internal border is drawn below the tool bar. */
1476 if (WINDOWP (f->tool_bar_window)
1477 && w == XWINDOW (f->tool_bar_window))
1478 y -= width;
1479
1480 BLOCK_INPUT;
1481
1482 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1483 0, y, width, height, 0);
1484 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1485 FRAME_PIXEL_WIDTH (f) - width, y,
1486 width, height, 0);
1487
1488 UNBLOCK_INPUT;
1489 }
1490 }
1491
1492
1493 /* Draw the bitmap WHICH in one of the left or right fringes of
1494 window W. ROW is the glyph row for which to display the bitmap; it
1495 determines the vertical position at which the bitmap has to be
1496 drawn. */
1497
1498 static void
1499 x_draw_fringe_bitmap (w, row, p)
1500 struct window *w;
1501 struct glyph_row *row;
1502 struct draw_fringe_bitmap_params *p;
1503 {
1504 struct frame *f = XFRAME (WINDOW_FRAME (w));
1505 Display *display = FRAME_MAC_DISPLAY (f);
1506 WindowPtr window = FRAME_MAC_WINDOW (f);
1507 XGCValues gcv;
1508 GC gc = f->output_data.mac->normal_gc;
1509 struct face *face = p->face;
1510 int rowY;
1511
1512 /* Must clip because of partially visible lines. */
1513 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
1514 if (p->y < rowY)
1515 {
1516 /* Adjust position of "bottom aligned" bitmap on partially
1517 visible last row. */
1518 int oldY = row->y;
1519 int oldVH = row->visible_height;
1520 row->visible_height = p->h;
1521 row->y -= rowY - p->y;
1522 x_clip_to_row (w, row, -1, gc);
1523 row->y = oldY;
1524 row->visible_height = oldVH;
1525 }
1526 else
1527 x_clip_to_row (w, row, -1, gc);
1528
1529 if (p->bx >= 0 && !p->overlay_p)
1530 {
1531 XGCValues gcv;
1532 gcv.foreground = face->background;
1533
1534 #if 0 /* MAC_TODO: stipple */
1535 /* In case the same realized face is used for fringes and
1536 for something displayed in the text (e.g. face `region' on
1537 mono-displays, the fill style may have been changed to
1538 FillSolid in x_draw_glyph_string_background. */
1539 if (face->stipple)
1540 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled);
1541 else
1542 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background);
1543 #endif
1544
1545 XFillRectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1546 &gcv,
1547 p->bx, p->by, p->nx, p->ny);
1548
1549 #if 0 /* MAC_TODO: stipple */
1550 if (!face->stipple)
1551 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground);
1552 #endif
1553 }
1554
1555 if (p->which)
1556 {
1557 unsigned short *bits = p->bits + p->dh;
1558
1559 gcv.foreground = (p->cursor_p
1560 ? (p->overlay_p ? face->background
1561 : f->output_data.mac->cursor_pixel)
1562 : face->foreground);
1563 gcv.background = face->background;
1564
1565 mac_draw_bitmap (display, window, &gcv, p->x, p->y,
1566 p->wd, p->h, bits, p->overlay_p);
1567 }
1568
1569 mac_reset_clipping (display, window);
1570 }
1571
1572 \f
1573 /* This is called when starting Emacs and when restarting after
1574 suspend. When starting Emacs, no window is mapped. And nothing
1575 must be done to Emacs's own window if it is suspended (though that
1576 rarely happens). */
1577
1578 static void
1579 XTset_terminal_modes ()
1580 {
1581 }
1582
1583 /* This is called when exiting or suspending Emacs. Exiting will make
1584 the windows go away, and suspending requires no action. */
1585
1586 static void
1587 XTreset_terminal_modes ()
1588 {
1589 }
1590
1591 \f
1592 /***********************************************************************
1593 Display Iterator
1594 ***********************************************************************/
1595
1596 /* Function prototypes of this page. */
1597
1598 static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *));
1599 static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *));
1600
1601
1602 /* Return a pointer to per-char metric information in FONT of a
1603 character pointed by B which is a pointer to an XChar2b. */
1604
1605 #define PER_CHAR_METRIC(font, b) \
1606 ((font)->per_char \
1607 ? ((font)->per_char + (b)->byte2 - (font)->min_char_or_byte2 \
1608 + (((font)->min_byte1 || (font)->max_byte1) \
1609 ? (((b)->byte1 - (font)->min_byte1) \
1610 * ((font)->max_char_or_byte2 - (font)->min_char_or_byte2 + 1)) \
1611 : 0)) \
1612 : &((font)->max_bounds))
1613
1614
1615 /* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B
1616 is not contained in the font. */
1617
1618 static INLINE XCharStruct *
1619 x_per_char_metric (font, char2b)
1620 XFontStruct *font;
1621 XChar2b *char2b;
1622 {
1623 /* The result metric information. */
1624 XCharStruct *pcm = NULL;
1625
1626 xassert (font && char2b);
1627
1628 if (font->per_char != NULL)
1629 {
1630 if (font->min_byte1 == 0 && font->max_byte1 == 0)
1631 {
1632 /* min_char_or_byte2 specifies the linear character index
1633 corresponding to the first element of the per_char array,
1634 max_char_or_byte2 is the index of the last character. A
1635 character with non-zero CHAR2B->byte1 is not in the font.
1636 A character with byte2 less than min_char_or_byte2 or
1637 greater max_char_or_byte2 is not in the font. */
1638 if (char2b->byte1 == 0
1639 && char2b->byte2 >= font->min_char_or_byte2
1640 && char2b->byte2 <= font->max_char_or_byte2)
1641 pcm = font->per_char + char2b->byte2 - font->min_char_or_byte2;
1642 }
1643 else
1644 {
1645 /* If either min_byte1 or max_byte1 are nonzero, both
1646 min_char_or_byte2 and max_char_or_byte2 are less than
1647 256, and the 2-byte character index values corresponding
1648 to the per_char array element N (counting from 0) are:
1649
1650 byte1 = N/D + min_byte1
1651 byte2 = N\D + min_char_or_byte2
1652
1653 where:
1654
1655 D = max_char_or_byte2 - min_char_or_byte2 + 1
1656 / = integer division
1657 \ = integer modulus */
1658 if (char2b->byte1 >= font->min_byte1
1659 && char2b->byte1 <= font->max_byte1
1660 && char2b->byte2 >= font->min_char_or_byte2
1661 && char2b->byte2 <= font->max_char_or_byte2)
1662 {
1663 pcm = (font->per_char
1664 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1)
1665 * (char2b->byte1 - font->min_byte1))
1666 + (char2b->byte2 - font->min_char_or_byte2));
1667 }
1668 }
1669 }
1670 else
1671 {
1672 /* If the per_char pointer is null, all glyphs between the first
1673 and last character indexes inclusive have the same
1674 information, as given by both min_bounds and max_bounds. */
1675 if (char2b->byte2 >= font->min_char_or_byte2
1676 && char2b->byte2 <= font->max_char_or_byte2)
1677 pcm = &font->max_bounds;
1678 }
1679
1680 return ((pcm == NULL
1681 || (pcm->width == 0 && (pcm->rbearing - pcm->lbearing) == 0))
1682 ? NULL : pcm);
1683 }
1684
1685 /* RIF:
1686 */
1687
1688 static XCharStruct *
1689 mac_per_char_metric (font, char2b, font_type)
1690 XFontStruct *font;
1691 XChar2b *char2b;
1692 int font_type;
1693 {
1694 return x_per_char_metric (font, char2b);
1695 }
1696
1697 /* RIF:
1698 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is
1699 the two-byte form of C. Encoding is returned in *CHAR2B. */
1700
1701 static int
1702 mac_encode_char (c, char2b, font_info, two_byte_p)
1703 int c;
1704 XChar2b *char2b;
1705 struct font_info *font_info;
1706 int *two_byte_p;
1707 {
1708 int charset = CHAR_CHARSET (c);
1709 XFontStruct *font = font_info->font;
1710
1711 /* FONT_INFO may define a scheme by which to encode byte1 and byte2.
1712 This may be either a program in a special encoder language or a
1713 fixed encoding. */
1714 if (font_info->font_encoder)
1715 {
1716 /* It's a program. */
1717 struct ccl_program *ccl = font_info->font_encoder;
1718
1719 if (CHARSET_DIMENSION (charset) == 1)
1720 {
1721 ccl->reg[0] = charset;
1722 ccl->reg[1] = char2b->byte2;
1723 }
1724 else
1725 {
1726 ccl->reg[0] = charset;
1727 ccl->reg[1] = char2b->byte1;
1728 ccl->reg[2] = char2b->byte2;
1729 }
1730
1731 ccl_driver (ccl, NULL, NULL, 0, 0, NULL);
1732
1733 /* We assume that MSBs are appropriately set/reset by CCL
1734 program. */
1735 if (font->max_byte1 == 0) /* 1-byte font */
1736 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1];
1737 else
1738 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2];
1739 }
1740 else if (font_info->encoding[charset])
1741 {
1742 /* Fixed encoding scheme. See fontset.h for the meaning of the
1743 encoding numbers. */
1744 int enc = font_info->encoding[charset];
1745
1746 if ((enc == 1 || enc == 2)
1747 && CHARSET_DIMENSION (charset) == 2)
1748 char2b->byte1 |= 0x80;
1749
1750 if (enc == 1 || enc == 3)
1751 char2b->byte2 |= 0x80;
1752
1753 if (enc == 4)
1754 {
1755 int sjis1, sjis2;
1756
1757 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2);
1758 char2b->byte1 = sjis1;
1759 char2b->byte2 = sjis2;
1760 }
1761 }
1762
1763 if (two_byte_p)
1764 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0;
1765
1766 return FONT_TYPE_UNKNOWN;
1767 }
1768
1769
1770 \f
1771 /***********************************************************************
1772 Glyph display
1773 ***********************************************************************/
1774
1775
1776 static void x_set_glyph_string_clipping P_ ((struct glyph_string *));
1777 static void x_set_glyph_string_gc P_ ((struct glyph_string *));
1778 static void x_draw_glyph_string_background P_ ((struct glyph_string *,
1779 int));
1780 static void x_draw_glyph_string_foreground P_ ((struct glyph_string *));
1781 static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *));
1782 static void x_draw_glyph_string_box P_ ((struct glyph_string *));
1783 static void x_draw_glyph_string P_ ((struct glyph_string *));
1784 static void x_set_cursor_gc P_ ((struct glyph_string *));
1785 static void x_set_mode_line_face_gc P_ ((struct glyph_string *));
1786 static void x_set_mouse_face_gc P_ ((struct glyph_string *));
1787 /*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap,
1788 unsigned long *, double, int));*/
1789 static void x_setup_relief_color P_ ((struct frame *, struct relief *,
1790 double, int, unsigned long));
1791 static void x_setup_relief_colors P_ ((struct glyph_string *));
1792 static void x_draw_image_glyph_string P_ ((struct glyph_string *));
1793 static void x_draw_image_relief P_ ((struct glyph_string *));
1794 static void x_draw_image_foreground P_ ((struct glyph_string *));
1795 static void x_draw_image_foreground_1 P_ ((struct glyph_string *, Pixmap));
1796 static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int,
1797 int, int, int));
1798 static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int,
1799 int, int, int, int, int, int,
1800 Rect *));
1801 static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int,
1802 int, int, int, Rect *));
1803
1804 #if GLYPH_DEBUG
1805 static void x_check_font P_ ((struct frame *, XFontStruct *));
1806 #endif
1807
1808
1809 /* Set S->gc to a suitable GC for drawing glyph string S in cursor
1810 face. */
1811
1812 static void
1813 x_set_cursor_gc (s)
1814 struct glyph_string *s;
1815 {
1816 if (s->font == FRAME_FONT (s->f)
1817 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f)
1818 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f)
1819 && !s->cmp)
1820 s->gc = s->f->output_data.mac->cursor_gc;
1821 else
1822 {
1823 /* Cursor on non-default face: must merge. */
1824 XGCValues xgcv;
1825 unsigned long mask;
1826
1827 xgcv.background = s->f->output_data.mac->cursor_pixel;
1828 xgcv.foreground = s->face->background;
1829
1830 /* If the glyph would be invisible, try a different foreground. */
1831 if (xgcv.foreground == xgcv.background)
1832 xgcv.foreground = s->face->foreground;
1833 if (xgcv.foreground == xgcv.background)
1834 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel;
1835 if (xgcv.foreground == xgcv.background)
1836 xgcv.foreground = s->face->foreground;
1837
1838 /* Make sure the cursor is distinct from text in this face. */
1839 if (xgcv.background == s->face->background
1840 && xgcv.foreground == s->face->foreground)
1841 {
1842 xgcv.background = s->face->foreground;
1843 xgcv.foreground = s->face->background;
1844 }
1845
1846 IF_DEBUG (x_check_font (s->f, s->font));
1847 xgcv.font = s->font;
1848 mask = GCForeground | GCBackground | GCFont;
1849
1850 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1851 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1852 mask, &xgcv);
1853 else
1854 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1855 = XCreateGC (s->display, s->window, mask, &xgcv);
1856
1857 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1858 }
1859 }
1860
1861
1862 /* Set up S->gc of glyph string S for drawing text in mouse face. */
1863
1864 static void
1865 x_set_mouse_face_gc (s)
1866 struct glyph_string *s;
1867 {
1868 int face_id;
1869 struct face *face;
1870
1871 /* What face has to be used last for the mouse face? */
1872 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id;
1873 face = FACE_FROM_ID (s->f, face_id);
1874 if (face == NULL)
1875 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
1876
1877 if (s->first_glyph->type == CHAR_GLYPH)
1878 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch);
1879 else
1880 face_id = FACE_FOR_CHAR (s->f, face, 0);
1881 s->face = FACE_FROM_ID (s->f, face_id);
1882 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1883
1884 /* If font in this face is same as S->font, use it. */
1885 if (s->font == s->face->font)
1886 s->gc = s->face->gc;
1887 else
1888 {
1889 /* Otherwise construct scratch_cursor_gc with values from FACE
1890 but font FONT. */
1891 XGCValues xgcv;
1892 unsigned long mask;
1893
1894 xgcv.background = s->face->background;
1895 xgcv.foreground = s->face->foreground;
1896 IF_DEBUG (x_check_font (s->f, s->font));
1897 xgcv.font = s->font;
1898 mask = GCForeground | GCBackground | GCFont;
1899
1900 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc)
1901 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc,
1902 mask, &xgcv);
1903 else
1904 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc
1905 = XCreateGC (s->display, s->window, mask, &xgcv);
1906
1907 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc;
1908 }
1909
1910 xassert (s->gc != 0);
1911 }
1912
1913
1914 /* Set S->gc of glyph string S to a GC suitable for drawing a mode line.
1915 Faces to use in the mode line have already been computed when the
1916 matrix was built, so there isn't much to do, here. */
1917
1918 static INLINE void
1919 x_set_mode_line_face_gc (s)
1920 struct glyph_string *s;
1921 {
1922 s->gc = s->face->gc;
1923 }
1924
1925
1926 /* Set S->gc of glyph string S for drawing that glyph string. Set
1927 S->stippled_p to a non-zero value if the face of S has a stipple
1928 pattern. */
1929
1930 static INLINE void
1931 x_set_glyph_string_gc (s)
1932 struct glyph_string *s;
1933 {
1934 PREPARE_FACE_FOR_DISPLAY (s->f, s->face);
1935
1936 if (s->hl == DRAW_NORMAL_TEXT)
1937 {
1938 s->gc = s->face->gc;
1939 s->stippled_p = s->face->stipple != 0;
1940 }
1941 else if (s->hl == DRAW_INVERSE_VIDEO)
1942 {
1943 x_set_mode_line_face_gc (s);
1944 s->stippled_p = s->face->stipple != 0;
1945 }
1946 else if (s->hl == DRAW_CURSOR)
1947 {
1948 x_set_cursor_gc (s);
1949 s->stippled_p = 0;
1950 }
1951 else if (s->hl == DRAW_MOUSE_FACE)
1952 {
1953 x_set_mouse_face_gc (s);
1954 s->stippled_p = s->face->stipple != 0;
1955 }
1956 else if (s->hl == DRAW_IMAGE_RAISED
1957 || s->hl == DRAW_IMAGE_SUNKEN)
1958 {
1959 s->gc = s->face->gc;
1960 s->stippled_p = s->face->stipple != 0;
1961 }
1962 else
1963 {
1964 s->gc = s->face->gc;
1965 s->stippled_p = s->face->stipple != 0;
1966 }
1967
1968 /* GC must have been set. */
1969 xassert (s->gc != 0);
1970 }
1971
1972
1973 /* Set clipping for output of glyph string S. S may be part of a mode
1974 line or menu if we don't have X toolkit support. */
1975
1976 static INLINE void
1977 x_set_glyph_string_clipping (s)
1978 struct glyph_string *s;
1979 {
1980 Rect r;
1981 get_glyph_string_clip_rect (s, &r);
1982 mac_set_clip_rectangle (s->display, s->window, &r);
1983 }
1984
1985
1986 /* RIF:
1987 Compute left and right overhang of glyph string S. If S is a glyph
1988 string for a composition, assume overhangs don't exist. */
1989
1990 static void
1991 mac_compute_glyph_string_overhangs (s)
1992 struct glyph_string *s;
1993 {
1994 #if 0
1995 /* MAC_TODO: XTextExtents16 does nothing yet... */
1996
1997 if (s->cmp == NULL
1998 && s->first_glyph->type == CHAR_GLYPH)
1999 {
2000 XCharStruct cs;
2001 int direction, font_ascent, font_descent;
2002 XTextExtents16 (s->font, s->char2b, s->nchars, &direction,
2003 &font_ascent, &font_descent, &cs);
2004 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0;
2005 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0;
2006 }
2007 #endif
2008 }
2009
2010
2011 /* Fill rectangle X, Y, W, H with background color of glyph string S. */
2012
2013 static INLINE void
2014 x_clear_glyph_string_rect (s, x, y, w, h)
2015 struct glyph_string *s;
2016 int x, y, w, h;
2017 {
2018 XGCValues xgcv;
2019
2020 xgcv.foreground = s->gc->background;
2021 XFillRectangle (s->display, s->window, &xgcv, x, y, w, h);
2022 }
2023
2024
2025 /* We prefer not to use XDrawImageString (srcCopy text transfer mode)
2026 on Mac OS X because:
2027 - Screen is double-buffered. (In srcCopy mode, a text is drawn
2028 into an offscreen graphics world first. So performance gain
2029 cannot be expected.)
2030 - It lowers rendering quality.
2031 - Some fonts leave garbage on cursor movement. */
2032
2033 /* Draw the background of glyph_string S. If S->background_filled_p
2034 is non-zero don't draw it. FORCE_P non-zero means draw the
2035 background even if it wouldn't be drawn normally. This is used
2036 when a string preceding S draws into the background of S, or S
2037 contains the first component of a composition. */
2038
2039 static void
2040 x_draw_glyph_string_background (s, force_p)
2041 struct glyph_string *s;
2042 int force_p;
2043 {
2044 /* Nothing to do if background has already been drawn or if it
2045 shouldn't be drawn in the first place. */
2046 if (!s->background_filled_p)
2047 {
2048 int box_line_width = max (s->face->box_line_width, 0);
2049
2050 #if 0 /* MAC_TODO: stipple */
2051 if (s->stippled_p)
2052 {
2053 /* Fill background with a stipple pattern. */
2054 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2055 XFillRectangle (s->display, s->window, s->gc, s->x,
2056 s->y + box_line_width,
2057 s->background_width,
2058 s->height - 2 * box_line_width);
2059 XSetFillStyle (s->display, s->gc, FillSolid);
2060 s->background_filled_p = 1;
2061 }
2062 else
2063 #endif
2064 #ifdef MAC_OS8
2065 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2066 || s->font_not_found_p
2067 || s->extends_to_end_of_line_p
2068 || force_p)
2069 #endif
2070 {
2071 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width,
2072 s->background_width,
2073 s->height - 2 * box_line_width);
2074 s->background_filled_p = 1;
2075 }
2076 }
2077 }
2078
2079
2080 /* Draw the foreground of glyph string S. */
2081
2082 static void
2083 x_draw_glyph_string_foreground (s)
2084 struct glyph_string *s;
2085 {
2086 int i, x;
2087
2088 /* If first glyph of S has a left box line, start drawing the text
2089 of S to the right of that box line. */
2090 if (s->face->box != FACE_NO_BOX
2091 && s->first_glyph->left_box_line_p)
2092 x = s->x + abs (s->face->box_line_width);
2093 else
2094 x = s->x;
2095
2096 /* Draw characters of S as rectangles if S's font could not be
2097 loaded. */
2098 if (s->font_not_found_p)
2099 {
2100 for (i = 0; i < s->nchars; ++i)
2101 {
2102 struct glyph *g = s->first_glyph + i;
2103 mac_draw_rectangle (s->display, s->window,
2104 s->gc, x, s->y, g->pixel_width - 1,
2105 s->height - 1);
2106 x += g->pixel_width;
2107 }
2108 }
2109 else
2110 {
2111 char *char1b = (char *) s->char2b;
2112 int boff = s->font_info->baseline_offset;
2113
2114 if (s->font_info->vertical_centering)
2115 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff;
2116
2117 /* If we can use 8-bit functions, condense S->char2b. */
2118 if (!s->two_byte_p)
2119 for (i = 0; i < s->nchars; ++i)
2120 char1b[i] = s->char2b[i].byte2;
2121
2122 #ifdef MAC_OS8
2123 /* Draw text with XDrawString if background has already been
2124 filled. Otherwise, use XDrawImageString. (Note that
2125 XDrawImageString is usually faster than XDrawString.) Always
2126 use XDrawImageString when drawing the cursor so that there is
2127 no chance that characters under a box cursor are invisible. */
2128 if (s->for_overlaps_p
2129 || (s->background_filled_p && s->hl != DRAW_CURSOR))
2130 #endif
2131 {
2132 /* Draw characters with 16-bit or 8-bit functions. */
2133 if (s->two_byte_p)
2134 XDrawString16 (s->display, s->window, s->gc, x,
2135 s->ybase - boff, s->char2b, s->nchars);
2136 else
2137 XDrawString (s->display, s->window, s->gc, x,
2138 s->ybase - boff, char1b, s->nchars);
2139 }
2140 #ifdef MAC_OS8
2141 else
2142 {
2143 if (s->two_byte_p)
2144 XDrawImageString16 (s->display, s->window, s->gc, x,
2145 s->ybase - boff, s->char2b, s->nchars);
2146 else
2147 XDrawImageString (s->display, s->window, s->gc, x,
2148 s->ybase - boff, char1b, s->nchars);
2149 }
2150 #endif
2151 }
2152 }
2153
2154 /* Draw the foreground of composite glyph string S. */
2155
2156 static void
2157 x_draw_composite_glyph_string_foreground (s)
2158 struct glyph_string *s;
2159 {
2160 int i, x;
2161
2162 /* If first glyph of S has a left box line, start drawing the text
2163 of S to the right of that box line. */
2164 if (s->face->box != FACE_NO_BOX
2165 && s->first_glyph->left_box_line_p)
2166 x = s->x + abs (s->face->box_line_width);
2167 else
2168 x = s->x;
2169
2170 /* S is a glyph string for a composition. S->gidx is the index of
2171 the first character drawn for glyphs of this composition.
2172 S->gidx == 0 means we are drawing the very first character of
2173 this composition. */
2174
2175 /* Draw a rectangle for the composition if the font for the very
2176 first character of the composition could not be loaded. */
2177 if (s->font_not_found_p)
2178 {
2179 if (s->gidx == 0)
2180 mac_draw_rectangle (s->display, s->window, s->gc, x, s->y,
2181 s->width - 1, s->height - 1);
2182 }
2183 else
2184 {
2185 for (i = 0; i < s->nchars; i++, ++s->gidx)
2186 XDrawString16 (s->display, s->window, s->gc,
2187 x + s->cmp->offsets[s->gidx * 2],
2188 s->ybase - s->cmp->offsets[s->gidx * 2 + 1],
2189 s->char2b + i, 1);
2190 }
2191 }
2192
2193
2194 #ifdef USE_X_TOOLKIT
2195
2196 static struct frame *x_frame_of_widget P_ ((Widget));
2197
2198
2199 /* Return the frame on which widget WIDGET is used.. Abort if frame
2200 cannot be determined. */
2201
2202 static struct frame *
2203 x_frame_of_widget (widget)
2204 Widget widget;
2205 {
2206 struct x_display_info *dpyinfo;
2207 Lisp_Object tail;
2208 struct frame *f;
2209
2210 dpyinfo = x_display_info_for_display (XtDisplay (widget));
2211
2212 /* Find the top-level shell of the widget. Note that this function
2213 can be called when the widget is not yet realized, so XtWindow
2214 (widget) == 0. That's the reason we can't simply use
2215 x_any_window_to_frame. */
2216 while (!XtIsTopLevelShell (widget))
2217 widget = XtParent (widget);
2218
2219 /* Look for a frame with that top-level widget. Allocate the color
2220 on that frame to get the right gamma correction value. */
2221 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail))
2222 if (GC_FRAMEP (XCAR (tail))
2223 && (f = XFRAME (XCAR (tail)),
2224 (f->output_data.nothing != 1
2225 && FRAME_X_DISPLAY_INFO (f) == dpyinfo))
2226 && f->output_data.x->widget == widget)
2227 return f;
2228
2229 abort ();
2230 }
2231
2232
2233 /* Allocate the color COLOR->pixel on the screen and display of
2234 widget WIDGET in colormap CMAP. If an exact match cannot be
2235 allocated, try the nearest color available. Value is non-zero
2236 if successful. This is called from lwlib. */
2237
2238 int
2239 x_alloc_nearest_color_for_widget (widget, cmap, color)
2240 Widget widget;
2241 Colormap cmap;
2242 XColor *color;
2243 {
2244 struct frame *f = x_frame_of_widget (widget);
2245 return x_alloc_nearest_color (f, cmap, color);
2246 }
2247
2248
2249 #endif /* USE_X_TOOLKIT */
2250
2251 #if 0 /* MAC_TODO */
2252
2253 /* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap
2254 CMAP. If an exact match can't be allocated, try the nearest color
2255 available. Value is non-zero if successful. Set *COLOR to the
2256 color allocated. */
2257
2258 int
2259 x_alloc_nearest_color (f, cmap, color)
2260 struct frame *f;
2261 Colormap cmap;
2262 XColor *color;
2263 {
2264 Display *display = FRAME_X_DISPLAY (f);
2265 Screen *screen = FRAME_X_SCREEN (f);
2266 int rc;
2267
2268 gamma_correct (f, color);
2269 rc = XAllocColor (display, cmap, color);
2270 if (rc == 0)
2271 {
2272 /* If we got to this point, the colormap is full, so we're going
2273 to try to get the next closest color. The algorithm used is
2274 a least-squares matching, which is what X uses for closest
2275 color matching with StaticColor visuals. */
2276 int nearest, i;
2277 unsigned long nearest_delta = ~0;
2278 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen));
2279 XColor *cells = (XColor *) alloca (ncells * sizeof *cells);
2280
2281 for (i = 0; i < ncells; ++i)
2282 cells[i].pixel = i;
2283 XQueryColors (display, cmap, cells, ncells);
2284
2285 for (nearest = i = 0; i < ncells; ++i)
2286 {
2287 long dred = (color->red >> 8) - (cells[i].red >> 8);
2288 long dgreen = (color->green >> 8) - (cells[i].green >> 8);
2289 long dblue = (color->blue >> 8) - (cells[i].blue >> 8);
2290 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue;
2291
2292 if (delta < nearest_delta)
2293 {
2294 nearest = i;
2295 nearest_delta = delta;
2296 }
2297 }
2298
2299 color->red = cells[nearest].red;
2300 color->green = cells[nearest].green;
2301 color->blue = cells[nearest].blue;
2302 rc = XAllocColor (display, cmap, color);
2303 }
2304
2305 #ifdef DEBUG_X_COLORS
2306 if (rc)
2307 register_color (color->pixel);
2308 #endif /* DEBUG_X_COLORS */
2309
2310 return rc;
2311 }
2312
2313
2314 /* Allocate color PIXEL on frame F. PIXEL must already be allocated.
2315 It's necessary to do this instead of just using PIXEL directly to
2316 get color reference counts right. */
2317
2318 unsigned long
2319 x_copy_color (f, pixel)
2320 struct frame *f;
2321 unsigned long pixel;
2322 {
2323 XColor color;
2324
2325 color.pixel = pixel;
2326 BLOCK_INPUT;
2327 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2328 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color);
2329 UNBLOCK_INPUT;
2330 #ifdef DEBUG_X_COLORS
2331 register_color (pixel);
2332 #endif
2333 return color.pixel;
2334 }
2335
2336
2337 /* Allocate color PIXEL on display DPY. PIXEL must already be allocated.
2338 It's necessary to do this instead of just using PIXEL directly to
2339 get color reference counts right. */
2340
2341 unsigned long
2342 x_copy_dpy_color (dpy, cmap, pixel)
2343 Display *dpy;
2344 Colormap cmap;
2345 unsigned long pixel;
2346 {
2347 XColor color;
2348
2349 color.pixel = pixel;
2350 BLOCK_INPUT;
2351 XQueryColor (dpy, cmap, &color);
2352 XAllocColor (dpy, cmap, &color);
2353 UNBLOCK_INPUT;
2354 #ifdef DEBUG_X_COLORS
2355 register_color (pixel);
2356 #endif
2357 return color.pixel;
2358 }
2359
2360 #endif /* MAC_TODO */
2361
2362
2363 /* Brightness beyond which a color won't have its highlight brightness
2364 boosted.
2365
2366 Nominally, highlight colors for `3d' faces are calculated by
2367 brightening an object's color by a constant scale factor, but this
2368 doesn't yield good results for dark colors, so for colors who's
2369 brightness is less than this value (on a scale of 0-255) have to
2370 use an additional additive factor.
2371
2372 The value here is set so that the default menu-bar/mode-line color
2373 (grey75) will not have its highlights changed at all. */
2374 #define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187
2375
2376
2377 /* Allocate a color which is lighter or darker than *COLOR by FACTOR
2378 or DELTA. Try a color with RGB values multiplied by FACTOR first.
2379 If this produces the same color as COLOR, try a color where all RGB
2380 values have DELTA added. Return the allocated color in *COLOR.
2381 DISPLAY is the X display, CMAP is the colormap to operate on.
2382 Value is non-zero if successful. */
2383
2384 static int
2385 mac_alloc_lighter_color (f, color, factor, delta)
2386 struct frame *f;
2387 unsigned long *color;
2388 double factor;
2389 int delta;
2390 {
2391 unsigned long new;
2392 long bright;
2393
2394 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */
2395 delta /= 256;
2396
2397 /* Change RGB values by specified FACTOR. Avoid overflow! */
2398 xassert (factor >= 0);
2399 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))),
2400 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))),
2401 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color))));
2402
2403 /* Calculate brightness of COLOR. */
2404 bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color)
2405 + BLUE_FROM_ULONG (*color)) / 6;
2406
2407 /* We only boost colors that are darker than
2408 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */
2409 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT)
2410 /* Make an additive adjustment to NEW, because it's dark enough so
2411 that scaling by FACTOR alone isn't enough. */
2412 {
2413 /* How far below the limit this color is (0 - 1, 1 being darker). */
2414 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT;
2415 /* The additive adjustment. */
2416 int min_delta = delta * dimness * factor / 2;
2417
2418 if (factor < 1)
2419 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)),
2420 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)),
2421 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta)));
2422 else
2423 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))),
2424 max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))),
2425 max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color)))));
2426 }
2427
2428 if (new == *color)
2429 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))),
2430 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))),
2431 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color)))));
2432
2433 /* MAC_TODO: Map to palette and retry with delta if same? */
2434 /* MAC_TODO: Free colors (if using palette)? */
2435
2436 if (new == *color)
2437 return 0;
2438
2439 *color = new;
2440
2441 return 1;
2442 }
2443
2444
2445 /* Set up the foreground color for drawing relief lines of glyph
2446 string S. RELIEF is a pointer to a struct relief containing the GC
2447 with which lines will be drawn. Use a color that is FACTOR or
2448 DELTA lighter or darker than the relief's background which is found
2449 in S->f->output_data.x->relief_background. If such a color cannot
2450 be allocated, use DEFAULT_PIXEL, instead. */
2451
2452 static void
2453 x_setup_relief_color (f, relief, factor, delta, default_pixel)
2454 struct frame *f;
2455 struct relief *relief;
2456 double factor;
2457 int delta;
2458 unsigned long default_pixel;
2459 {
2460 XGCValues xgcv;
2461 struct mac_output *di = f->output_data.mac;
2462 unsigned long mask = GCForeground;
2463 unsigned long pixel;
2464 unsigned long background = di->relief_background;
2465 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
2466
2467 /* MAC_TODO: Free colors (if using palette)? */
2468
2469 /* Allocate new color. */
2470 xgcv.foreground = default_pixel;
2471 pixel = background;
2472 if (dpyinfo->n_planes != 1
2473 && mac_alloc_lighter_color (f, &pixel, factor, delta))
2474 {
2475 relief->allocated_p = 1;
2476 xgcv.foreground = relief->pixel = pixel;
2477 }
2478
2479 if (relief->gc == 0)
2480 {
2481 #if 0 /* MAC_TODO: stipple */
2482 xgcv.stipple = dpyinfo->gray;
2483 mask |= GCStipple;
2484 #endif
2485 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv);
2486 }
2487 else
2488 XChangeGC (NULL, relief->gc, mask, &xgcv);
2489 }
2490
2491
2492 /* Set up colors for the relief lines around glyph string S. */
2493
2494 static void
2495 x_setup_relief_colors (s)
2496 struct glyph_string *s;
2497 {
2498 struct mac_output *di = s->f->output_data.mac;
2499 unsigned long color;
2500
2501 if (s->face->use_box_color_for_shadows_p)
2502 color = s->face->box_color;
2503 else if (s->first_glyph->type == IMAGE_GLYPH
2504 && s->img->pixmap
2505 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
2506 color = IMAGE_BACKGROUND (s->img, s->f, 0);
2507 else
2508 {
2509 XGCValues xgcv;
2510
2511 /* Get the background color of the face. */
2512 XGetGCValues (s->display, s->gc, GCBackground, &xgcv);
2513 color = xgcv.background;
2514 }
2515
2516 if (di->white_relief.gc == 0
2517 || color != di->relief_background)
2518 {
2519 di->relief_background = color;
2520 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000,
2521 WHITE_PIX_DEFAULT (s->f));
2522 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000,
2523 BLACK_PIX_DEFAULT (s->f));
2524 }
2525 }
2526
2527
2528 /* Draw a relief on frame F inside the rectangle given by LEFT_X,
2529 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief
2530 to draw, it must be >= 0. RAISED_P non-zero means draw a raised
2531 relief. LEFT_P non-zero means draw a relief on the left side of
2532 the rectangle. RIGHT_P non-zero means draw a relief on the right
2533 side of the rectangle. CLIP_RECT is the clipping rectangle to use
2534 when drawing. */
2535
2536 static void
2537 x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width,
2538 raised_p, top_p, bot_p, left_p, right_p, clip_rect)
2539 struct frame *f;
2540 int left_x, top_y, right_x, bottom_y, width;
2541 int top_p, bot_p, left_p, right_p, raised_p;
2542 Rect *clip_rect;
2543 {
2544 Display *dpy = FRAME_MAC_DISPLAY (f);
2545 Window window = FRAME_MAC_WINDOW (f);
2546 int i;
2547 GC gc;
2548
2549 if (raised_p)
2550 gc = f->output_data.mac->white_relief.gc;
2551 else
2552 gc = f->output_data.mac->black_relief.gc;
2553 mac_set_clip_rectangle (dpy, window, clip_rect);
2554
2555 /* Top. */
2556 if (top_p)
2557 for (i = 0; i < width; ++i)
2558 XDrawLine (dpy, window, gc,
2559 left_x + i * left_p, top_y + i,
2560 right_x - i * right_p, top_y + i);
2561
2562 /* Left. */
2563 if (left_p)
2564 for (i = 0; i < width; ++i)
2565 XDrawLine (dpy, window, gc,
2566 left_x + i, top_y + i, left_x + i, bottom_y - i);
2567
2568 mac_reset_clipping (dpy, window);
2569 if (raised_p)
2570 gc = f->output_data.mac->black_relief.gc;
2571 else
2572 gc = f->output_data.mac->white_relief.gc;
2573 mac_set_clip_rectangle (dpy, window,
2574 clip_rect);
2575
2576 /* Bottom. */
2577 if (bot_p)
2578 for (i = 0; i < width; ++i)
2579 XDrawLine (dpy, window, gc,
2580 left_x + i * left_p, bottom_y - i,
2581 right_x - i * right_p, bottom_y - i);
2582
2583 /* Right. */
2584 if (right_p)
2585 for (i = 0; i < width; ++i)
2586 XDrawLine (dpy, window, gc,
2587 right_x - i, top_y + i + 1, right_x - i, bottom_y - i - 1);
2588
2589 mac_reset_clipping (dpy, window);
2590 }
2591
2592
2593 /* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y,
2594 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to
2595 draw, it must be >= 0. LEFT_P non-zero means draw a line on the
2596 left side of the rectangle. RIGHT_P non-zero means draw a line
2597 on the right side of the rectangle. CLIP_RECT is the clipping
2598 rectangle to use when drawing. */
2599
2600 static void
2601 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2602 left_p, right_p, clip_rect)
2603 struct glyph_string *s;
2604 int left_x, top_y, right_x, bottom_y, width, left_p, right_p;
2605 Rect *clip_rect;
2606 {
2607 XGCValues xgcv;
2608
2609 xgcv.foreground = s->face->box_color;
2610 mac_set_clip_rectangle (s->display, s->window, clip_rect);
2611
2612 /* Top. */
2613 XFillRectangle (s->display, s->window, &xgcv,
2614 left_x, top_y, right_x - left_x + 1, width);
2615
2616 /* Left. */
2617 if (left_p)
2618 XFillRectangle (s->display, s->window, &xgcv,
2619 left_x, top_y, width, bottom_y - top_y + 1);
2620
2621 /* Bottom. */
2622 XFillRectangle (s->display, s->window, &xgcv,
2623 left_x, bottom_y - width + 1, right_x - left_x + 1, width);
2624
2625 /* Right. */
2626 if (right_p)
2627 XFillRectangle (s->display, s->window, &xgcv,
2628 right_x - width + 1, top_y, width, bottom_y - top_y + 1);
2629
2630 mac_reset_clipping (s->display, s->window);
2631 }
2632
2633
2634 /* Draw a box around glyph string S. */
2635
2636 static void
2637 x_draw_glyph_string_box (s)
2638 struct glyph_string *s;
2639 {
2640 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p;
2641 int left_p, right_p;
2642 struct glyph *last_glyph;
2643 Rect clip_rect;
2644
2645 last_x = window_box_right (s->w, s->area);
2646 if (s->row->full_width_p
2647 && !s->w->pseudo_window_p)
2648 {
2649 last_x += WINDOW_RIGHT_SCROLL_BAR_AREA_WIDTH (s->w);
2650 if (s->area != RIGHT_MARGIN_AREA
2651 || WINDOW_HAS_FRINGES_OUTSIDE_MARGINS (s->w))
2652 last_x += WINDOW_RIGHT_FRINGE_WIDTH (s->w);
2653 }
2654
2655 /* The glyph that may have a right box line. */
2656 last_glyph = (s->cmp || s->img
2657 ? s->first_glyph
2658 : s->first_glyph + s->nchars - 1);
2659
2660 width = abs (s->face->box_line_width);
2661 raised_p = s->face->box == FACE_RAISED_BOX;
2662 left_x = s->x;
2663 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p
2664 ? last_x - 1
2665 : min (last_x, s->x + s->background_width) - 1);
2666 top_y = s->y;
2667 bottom_y = top_y + s->height - 1;
2668
2669 left_p = (s->first_glyph->left_box_line_p
2670 || (s->hl == DRAW_MOUSE_FACE
2671 && (s->prev == NULL
2672 || s->prev->hl != s->hl)));
2673 right_p = (last_glyph->right_box_line_p
2674 || (s->hl == DRAW_MOUSE_FACE
2675 && (s->next == NULL
2676 || s->next->hl != s->hl)));
2677
2678 get_glyph_string_clip_rect (s, &clip_rect);
2679
2680 if (s->face->box == FACE_SIMPLE_BOX)
2681 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width,
2682 left_p, right_p, &clip_rect);
2683 else
2684 {
2685 x_setup_relief_colors (s);
2686 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y,
2687 width, raised_p, 1, 1, left_p, right_p, &clip_rect);
2688 }
2689 }
2690
2691
2692 /* Draw foreground of image glyph string S. */
2693
2694 static void
2695 x_draw_image_foreground (s)
2696 struct glyph_string *s;
2697 {
2698 int x = s->x;
2699 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2700
2701 /* If first glyph of S has a left box line, start drawing it to the
2702 right of that line. */
2703 if (s->face->box != FACE_NO_BOX
2704 && s->first_glyph->left_box_line_p
2705 && s->slice.x == 0)
2706 x += abs (s->face->box_line_width);
2707
2708 /* If there is a margin around the image, adjust x- and y-position
2709 by that margin. */
2710 if (s->slice.x == 0)
2711 x += s->img->hmargin;
2712 if (s->slice.y == 0)
2713 y += s->img->vmargin;
2714
2715 if (s->img->pixmap)
2716 {
2717 x_set_glyph_string_clipping (s);
2718
2719 if (s->img->mask)
2720 mac_copy_area_with_mask (s->display, s->img->pixmap, s->img->mask,
2721 s->window, s->gc, s->slice.x, s->slice.y,
2722 s->slice.width, s->slice.height, x, y);
2723 else
2724 {
2725 mac_copy_area (s->display, s->img->pixmap,
2726 s->window, s->gc, s->slice.x, s->slice.y,
2727 s->slice.width, s->slice.height, x, y);
2728
2729 /* When the image has a mask, we can expect that at
2730 least part of a mouse highlight or a block cursor will
2731 be visible. If the image doesn't have a mask, make
2732 a block cursor visible by drawing a rectangle around
2733 the image. I believe it's looking better if we do
2734 nothing here for mouse-face. */
2735 if (s->hl == DRAW_CURSOR)
2736 {
2737 int r = s->img->relief;
2738 if (r < 0) r = -r;
2739 mac_draw_rectangle (s->display, s->window, s->gc,
2740 x - r, y - r,
2741 s->slice.width + r*2 - 1,
2742 s->slice.height + r*2 - 1);
2743 }
2744 }
2745 }
2746 else
2747 /* Draw a rectangle if image could not be loaded. */
2748 mac_draw_rectangle (s->display, s->window, s->gc, x, y,
2749 s->slice.width - 1, s->slice.height - 1);
2750 }
2751
2752
2753 /* Draw a relief around the image glyph string S. */
2754
2755 static void
2756 x_draw_image_relief (s)
2757 struct glyph_string *s;
2758 {
2759 int x0, y0, x1, y1, thick, raised_p;
2760 Rect r;
2761 int x = s->x;
2762 int y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2763
2764 /* If first glyph of S has a left box line, start drawing it to the
2765 right of that line. */
2766 if (s->face->box != FACE_NO_BOX
2767 && s->first_glyph->left_box_line_p
2768 && s->slice.x == 0)
2769 x += abs (s->face->box_line_width);
2770
2771 /* If there is a margin around the image, adjust x- and y-position
2772 by that margin. */
2773 if (s->slice.x == 0)
2774 x += s->img->hmargin;
2775 if (s->slice.y == 0)
2776 y += s->img->vmargin;
2777
2778 if (s->hl == DRAW_IMAGE_SUNKEN
2779 || s->hl == DRAW_IMAGE_RAISED)
2780 {
2781 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
2782 raised_p = s->hl == DRAW_IMAGE_RAISED;
2783 }
2784 else
2785 {
2786 thick = abs (s->img->relief);
2787 raised_p = s->img->relief > 0;
2788 }
2789
2790 x0 = x - thick;
2791 y0 = y - thick;
2792 x1 = x + s->slice.width + thick - 1;
2793 y1 = y + s->slice.height + thick - 1;
2794
2795 x_setup_relief_colors (s);
2796 get_glyph_string_clip_rect (s, &r);
2797 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p,
2798 s->slice.y == 0,
2799 s->slice.y + s->slice.height == s->img->height,
2800 s->slice.x == 0,
2801 s->slice.x + s->slice.width == s->img->width,
2802 &r);
2803 }
2804
2805
2806 #if 0 /* TODO: figure out if we need to do this on Mac. */
2807 /* Draw the foreground of image glyph string S to PIXMAP. */
2808
2809 static void
2810 x_draw_image_foreground_1 (s, pixmap)
2811 struct glyph_string *s;
2812 Pixmap pixmap;
2813 {
2814 int x = 0;
2815 int y = s->ybase - s->y - image_ascent (s->img, s->face, &s->slice);
2816
2817 /* If first glyph of S has a left box line, start drawing it to the
2818 right of that line. */
2819 if (s->face->box != FACE_NO_BOX
2820 && s->first_glyph->left_box_line_p
2821 && s->slice.x == 0)
2822 x += abs (s->face->box_line_width);
2823
2824 /* If there is a margin around the image, adjust x- and y-position
2825 by that margin. */
2826 if (s->slice.x == 0)
2827 x += s->img->hmargin;
2828 if (s->slice.y == 0)
2829 y += s->img->vmargin;
2830
2831 if (s->img->pixmap)
2832 {
2833 if (s->img->mask)
2834 mac_copy_area_with_mask_to_pixmap (s->display, s->img->pixmap,
2835 s->img->mask, pixmap, s->gc,
2836 s->slice.x, s->slice.y,
2837 s->slice.width, s->slice.height,
2838 x, y);
2839 else
2840 {
2841 mac_copy_area_to_pixmap (s->display, s->img->pixmap, pixmap, s->gc,
2842 s->slice.x, s->slice.y,
2843 s->slice.width, s->slice.height,
2844 x, y);
2845
2846 /* When the image has a mask, we can expect that at
2847 least part of a mouse highlight or a block cursor will
2848 be visible. If the image doesn't have a mask, make
2849 a block cursor visible by drawing a rectangle around
2850 the image. I believe it's looking better if we do
2851 nothing here for mouse-face. */
2852 if (s->hl == DRAW_CURSOR)
2853 {
2854 int r = s->img->relief;
2855 if (r < 0) r = -r;
2856 mac_draw_rectangle (s->display, s->window, s->gc, x - r, y - r,
2857 s->slice.width + r*2 - 1,
2858 s->slice.height + r*2 - 1);
2859 }
2860 }
2861 }
2862 else
2863 /* Draw a rectangle if image could not be loaded. */
2864 mac_draw_rectangle_to_pixmap (s->display, pixmap, s->gc, x, y,
2865 s->slice.width - 1, s->slice.height - 1);
2866 }
2867 #endif
2868
2869
2870 /* Draw part of the background of glyph string S. X, Y, W, and H
2871 give the rectangle to draw. */
2872
2873 static void
2874 x_draw_glyph_string_bg_rect (s, x, y, w, h)
2875 struct glyph_string *s;
2876 int x, y, w, h;
2877 {
2878 #if 0 /* MAC_TODO: stipple */
2879 if (s->stippled_p)
2880 {
2881 /* Fill background with a stipple pattern. */
2882 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2883 XFillRectangle (s->display, s->window, s->gc, x, y, w, h);
2884 XSetFillStyle (s->display, s->gc, FillSolid);
2885 }
2886 else
2887 #endif /* MAC_TODO */
2888 x_clear_glyph_string_rect (s, x, y, w, h);
2889 }
2890
2891
2892 /* Draw image glyph string S.
2893
2894 s->y
2895 s->x +-------------------------
2896 | s->face->box
2897 |
2898 | +-------------------------
2899 | | s->img->margin
2900 | |
2901 | | +-------------------
2902 | | | the image
2903
2904 */
2905
2906 static void
2907 x_draw_image_glyph_string (s)
2908 struct glyph_string *s;
2909 {
2910 int x, y;
2911 int box_line_hwidth = abs (s->face->box_line_width);
2912 int box_line_vwidth = max (s->face->box_line_width, 0);
2913 int height;
2914 Pixmap pixmap = 0;
2915
2916 height = s->height - 2 * box_line_vwidth;
2917
2918
2919 /* Fill background with face under the image. Do it only if row is
2920 taller than image or if image has a clip mask to reduce
2921 flickering. */
2922 s->stippled_p = s->face->stipple != 0;
2923 if (height > s->slice.height
2924 || s->img->hmargin
2925 || s->img->vmargin
2926 || s->img->mask
2927 || s->img->pixmap == 0
2928 || s->width != s->background_width)
2929 {
2930 x = s->x;
2931 if (s->first_glyph->left_box_line_p
2932 && s->slice.x == 0)
2933 x += box_line_hwidth;
2934
2935 y = s->y;
2936 if (s->slice.y == 0)
2937 y += box_line_vwidth;
2938
2939 #if 0 /* TODO: figure out if we need to do this on Mac. */
2940 if (s->img->mask)
2941 {
2942 /* Create a pixmap as large as the glyph string. Fill it
2943 with the background color. Copy the image to it, using
2944 its mask. Copy the temporary pixmap to the display. */
2945 int depth = one_mac_display_info.n_planes;
2946
2947 /* Create a pixmap as large as the glyph string. */
2948 pixmap = XCreatePixmap (s->display, s->window,
2949 s->background_width,
2950 s->height, depth);
2951
2952 /* Fill the pixmap with the background color/stipple. */
2953 #if 0 /* TODO: stipple */
2954 if (s->stippled_p)
2955 {
2956 /* Fill background with a stipple pattern. */
2957 XSetFillStyle (s->display, s->gc, FillOpaqueStippled);
2958 XFillRectangle (s->display, pixmap, s->gc,
2959 0, 0, s->background_width, s->height);
2960 XSetFillStyle (s->display, s->gc, FillSolid);
2961 }
2962 else
2963 #endif
2964 {
2965 XGCValues xgcv;
2966 XGetGCValues (s->display, s->gc, GCForeground | GCBackground,
2967 &xgcv);
2968 XSetForeground (s->display, s->gc, xgcv.background);
2969 mac_fill_rectangle_to_pixmap (s->display, pixmap, s->gc,
2970 0, 0, s->background_width,
2971 s->height);
2972 XSetForeground (s->display, s->gc, xgcv.foreground);
2973 }
2974 }
2975 else
2976 #endif
2977 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height);
2978
2979 s->background_filled_p = 1;
2980 }
2981
2982 /* Draw the foreground. */
2983 #if 0 /* TODO: figure out if we need to do this on Mac. */
2984 if (pixmap != 0)
2985 {
2986 x_draw_image_foreground_1 (s, pixmap);
2987 x_set_glyph_string_clipping (s);
2988 mac_copy_area (s->display, pixmap, s->window, s->gc,
2989 0, 0, s->background_width, s->height, s->x, s->y);
2990 mac_reset_clipping (s->display, s->window);
2991 XFreePixmap (s->display, pixmap);
2992 }
2993 else
2994 #endif
2995 x_draw_image_foreground (s);
2996
2997 /* If we must draw a relief around the image, do it. */
2998 if (s->img->relief
2999 || s->hl == DRAW_IMAGE_RAISED
3000 || s->hl == DRAW_IMAGE_SUNKEN)
3001 x_draw_image_relief (s);
3002 }
3003
3004
3005 /* Draw stretch glyph string S. */
3006
3007 static void
3008 x_draw_stretch_glyph_string (s)
3009 struct glyph_string *s;
3010 {
3011 xassert (s->first_glyph->type == STRETCH_GLYPH);
3012 s->stippled_p = s->face->stipple != 0;
3013
3014 if (s->hl == DRAW_CURSOR
3015 && !x_stretch_cursor_p)
3016 {
3017 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor
3018 as wide as the stretch glyph. */
3019 int width = min (FRAME_COLUMN_WIDTH (s->f), s->background_width);
3020
3021 /* Draw cursor. */
3022 x_draw_glyph_string_bg_rect (s, s->x, s->y, width, s->height);
3023
3024 /* Clear rest using the GC of the original non-cursor face. */
3025 if (width < s->background_width)
3026 {
3027 int x = s->x + width, y = s->y;
3028 int w = s->background_width - width, h = s->height;
3029 Rect r;
3030 GC gc;
3031
3032 if (s->row->mouse_face_p
3033 && cursor_in_mouse_face_p (s->w))
3034 {
3035 x_set_mouse_face_gc (s);
3036 gc = s->gc;
3037 }
3038 else
3039 gc = s->face->gc;
3040
3041 get_glyph_string_clip_rect (s, &r);
3042 mac_set_clip_rectangle (s->display, s->window, &r);
3043
3044 #if 0 /* MAC_TODO: stipple */
3045 if (s->face->stipple)
3046 {
3047 /* Fill background with a stipple pattern. */
3048 XSetFillStyle (s->display, gc, FillOpaqueStippled);
3049 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3050 XSetFillStyle (s->display, gc, FillSolid);
3051 }
3052 else
3053 #endif /* MAC_TODO */
3054 {
3055 XGCValues xgcv;
3056 XGetGCValues (s->display, gc, GCForeground | GCBackground, &xgcv);
3057 XSetForeground (s->display, gc, xgcv.background);
3058 XFillRectangle (s->display, s->window, gc, x, y, w, h);
3059 XSetForeground (s->display, gc, xgcv.foreground);
3060 }
3061
3062 mac_reset_clipping (s->display, s->window);
3063 }
3064 }
3065 else if (!s->background_filled_p)
3066 x_draw_glyph_string_bg_rect (s, s->x, s->y, s->background_width,
3067 s->height);
3068
3069 s->background_filled_p = 1;
3070 }
3071
3072
3073 /* Draw glyph string S. */
3074
3075 static void
3076 x_draw_glyph_string (s)
3077 struct glyph_string *s;
3078 {
3079 int relief_drawn_p = 0;
3080
3081 /* If S draws into the background of its successor, draw the
3082 background of the successor first so that S can draw into it.
3083 This makes S->next use XDrawString instead of XDrawImageString. */
3084 if (s->next && s->right_overhang && !s->for_overlaps_p)
3085 {
3086 xassert (s->next->img == NULL);
3087 x_set_glyph_string_gc (s->next);
3088 x_set_glyph_string_clipping (s->next);
3089 x_draw_glyph_string_background (s->next, 1);
3090 }
3091
3092 /* Set up S->gc, set clipping and draw S. */
3093 x_set_glyph_string_gc (s);
3094
3095 /* Draw relief (if any) in advance for char/composition so that the
3096 glyph string can be drawn over it. */
3097 if (!s->for_overlaps_p
3098 && s->face->box != FACE_NO_BOX
3099 && (s->first_glyph->type == CHAR_GLYPH
3100 || s->first_glyph->type == COMPOSITE_GLYPH))
3101
3102 {
3103 x_set_glyph_string_clipping (s);
3104 x_draw_glyph_string_background (s, 1);
3105 x_draw_glyph_string_box (s);
3106 x_set_glyph_string_clipping (s);
3107 relief_drawn_p = 1;
3108 }
3109 else
3110 x_set_glyph_string_clipping (s);
3111
3112 switch (s->first_glyph->type)
3113 {
3114 case IMAGE_GLYPH:
3115 x_draw_image_glyph_string (s);
3116 break;
3117
3118 case STRETCH_GLYPH:
3119 x_draw_stretch_glyph_string (s);
3120 break;
3121
3122 case CHAR_GLYPH:
3123 if (s->for_overlaps_p)
3124 s->background_filled_p = 1;
3125 else
3126 x_draw_glyph_string_background (s, 0);
3127 x_draw_glyph_string_foreground (s);
3128 break;
3129
3130 case COMPOSITE_GLYPH:
3131 if (s->for_overlaps_p || s->gidx > 0)
3132 s->background_filled_p = 1;
3133 else
3134 x_draw_glyph_string_background (s, 1);
3135 x_draw_composite_glyph_string_foreground (s);
3136 break;
3137
3138 default:
3139 abort ();
3140 }
3141
3142 if (!s->for_overlaps_p)
3143 {
3144 /* Draw underline. */
3145 if (s->face->underline_p)
3146 {
3147 unsigned long h = 1;
3148 unsigned long dy = s->height - h;
3149
3150 if (s->face->underline_defaulted_p)
3151 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3152 s->width, h);
3153 else
3154 {
3155 XGCValues xgcv;
3156 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3157 XSetForeground (s->display, s->gc, s->face->underline_color);
3158 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3159 s->width, h);
3160 XSetForeground (s->display, s->gc, xgcv.foreground);
3161 }
3162 }
3163
3164 /* Draw overline. */
3165 if (s->face->overline_p)
3166 {
3167 unsigned long dy = 0, h = 1;
3168
3169 if (s->face->overline_color_defaulted_p)
3170 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3171 s->width, h);
3172 else
3173 {
3174 XGCValues xgcv;
3175 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3176 XSetForeground (s->display, s->gc, s->face->overline_color);
3177 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3178 s->width, h);
3179 XSetForeground (s->display, s->gc, xgcv.foreground);
3180 }
3181 }
3182
3183 /* Draw strike-through. */
3184 if (s->face->strike_through_p)
3185 {
3186 unsigned long h = 1;
3187 unsigned long dy = (s->height - h) / 2;
3188
3189 if (s->face->strike_through_color_defaulted_p)
3190 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3191 s->width, h);
3192 else
3193 {
3194 XGCValues xgcv;
3195 XGetGCValues (s->display, s->gc, GCForeground, &xgcv);
3196 XSetForeground (s->display, s->gc, s->face->strike_through_color);
3197 XFillRectangle (s->display, s->window, s->gc, s->x, s->y + dy,
3198 s->width, h);
3199 XSetForeground (s->display, s->gc, xgcv.foreground);
3200 }
3201 }
3202
3203 /* Draw relief if not yet drawn. */
3204 if (!relief_drawn_p && s->face->box != FACE_NO_BOX)
3205 x_draw_glyph_string_box (s);
3206 }
3207
3208 /* Reset clipping. */
3209 mac_reset_clipping (s->display, s->window);
3210 }
3211
3212 /* Shift display to make room for inserted glyphs. */
3213
3214 void
3215 mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by)
3216 struct frame *f;
3217 int x, y, width, height, shift_by;
3218 {
3219 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
3220 f->output_data.mac->normal_gc,
3221 x, y, width, height,
3222 x + shift_by, y);
3223 }
3224
3225 /* Delete N glyphs at the nominal cursor position. Not implemented
3226 for X frames. */
3227
3228 static void
3229 x_delete_glyphs (n)
3230 register int n;
3231 {
3232 abort ();
3233 }
3234
3235
3236 /* Clear entire frame. If updating_frame is non-null, clear that
3237 frame. Otherwise clear the selected frame. */
3238
3239 static void
3240 x_clear_frame ()
3241 {
3242 struct frame *f;
3243
3244 if (updating_frame)
3245 f = updating_frame;
3246 else
3247 f = SELECTED_FRAME ();
3248
3249 /* Clearing the frame will erase any cursor, so mark them all as no
3250 longer visible. */
3251 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
3252 output_cursor.hpos = output_cursor.vpos = 0;
3253 output_cursor.x = -1;
3254
3255 /* We don't set the output cursor here because there will always
3256 follow an explicit cursor_to. */
3257 BLOCK_INPUT;
3258 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
3259
3260 #if 0 /* Clearing frame on Mac OS clears scroll bars. */
3261 /* We have to clear the scroll bars, too. If we have changed
3262 colors or something like that, then they should be notified. */
3263 x_scroll_bar_clear (f);
3264 #endif
3265
3266 XFlush (FRAME_MAC_DISPLAY (f));
3267 UNBLOCK_INPUT;
3268 }
3269
3270
3271 \f
3272 /* Invert the middle quarter of the frame for .15 sec. */
3273
3274 /* We use the select system call to do the waiting, so we have to make
3275 sure it's available. If it isn't, we just won't do visual bells. */
3276
3277 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3278
3279
3280 /* Subtract the `struct timeval' values X and Y, storing the result in
3281 *RESULT. Return 1 if the difference is negative, otherwise 0. */
3282
3283 static int
3284 timeval_subtract (result, x, y)
3285 struct timeval *result, x, y;
3286 {
3287 /* Perform the carry for the later subtraction by updating y. This
3288 is safer because on some systems the tv_sec member is unsigned. */
3289 if (x.tv_usec < y.tv_usec)
3290 {
3291 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
3292 y.tv_usec -= 1000000 * nsec;
3293 y.tv_sec += nsec;
3294 }
3295
3296 if (x.tv_usec - y.tv_usec > 1000000)
3297 {
3298 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
3299 y.tv_usec += 1000000 * nsec;
3300 y.tv_sec -= nsec;
3301 }
3302
3303 /* Compute the time remaining to wait. tv_usec is certainly
3304 positive. */
3305 result->tv_sec = x.tv_sec - y.tv_sec;
3306 result->tv_usec = x.tv_usec - y.tv_usec;
3307
3308 /* Return indication of whether the result should be considered
3309 negative. */
3310 return x.tv_sec < y.tv_sec;
3311 }
3312
3313 void
3314 XTflash (f)
3315 struct frame *f;
3316 {
3317 BLOCK_INPUT;
3318
3319 FlashMenuBar (0);
3320
3321 {
3322 struct timeval wakeup;
3323
3324 EMACS_GET_TIME (wakeup);
3325
3326 /* Compute time to wait until, propagating carry from usecs. */
3327 wakeup.tv_usec += 150000;
3328 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
3329 wakeup.tv_usec %= 1000000;
3330
3331 /* Keep waiting until past the time wakeup. */
3332 while (1)
3333 {
3334 struct timeval timeout;
3335
3336 EMACS_GET_TIME (timeout);
3337
3338 /* In effect, timeout = wakeup - timeout.
3339 Break if result would be negative. */
3340 if (timeval_subtract (&timeout, wakeup, timeout))
3341 break;
3342
3343 /* Try to wait that long--but we might wake up sooner. */
3344 select (0, NULL, NULL, NULL, &timeout);
3345 }
3346 }
3347
3348 FlashMenuBar (0);
3349
3350 UNBLOCK_INPUT;
3351 }
3352
3353 #endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */
3354
3355
3356 /* Make audible bell. */
3357
3358 void
3359 XTring_bell ()
3360 {
3361 struct frame *f = SELECTED_FRAME ();
3362
3363 #if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT)
3364 if (visible_bell)
3365 XTflash (f);
3366 else
3367 #endif
3368 {
3369 BLOCK_INPUT;
3370 SysBeep (1);
3371 XFlush (FRAME_MAC_DISPLAY (f));
3372 UNBLOCK_INPUT;
3373 }
3374 }
3375
3376
3377 \f
3378 /* Specify how many text lines, from the top of the window,
3379 should be affected by insert-lines and delete-lines operations.
3380 This, and those operations, are used only within an update
3381 that is bounded by calls to x_update_begin and x_update_end. */
3382
3383 static void
3384 XTset_terminal_window (n)
3385 register int n;
3386 {
3387 /* This function intentionally left blank. */
3388 }
3389
3390
3391 \f
3392 /***********************************************************************
3393 Line Dance
3394 ***********************************************************************/
3395
3396 /* Perform an insert-lines or delete-lines operation, inserting N
3397 lines or deleting -N lines at vertical position VPOS. */
3398
3399 static void
3400 x_ins_del_lines (vpos, n)
3401 int vpos, n;
3402 {
3403 abort ();
3404 }
3405
3406
3407 /* Scroll part of the display as described by RUN. */
3408
3409 static void
3410 x_scroll_run (w, run)
3411 struct window *w;
3412 struct run *run;
3413 {
3414 struct frame *f = XFRAME (w->frame);
3415 int x, y, width, height, from_y, to_y, bottom_y;
3416
3417 /* Get frame-relative bounding box of the text display area of W,
3418 without mode lines. Include in this box the left and right
3419 fringe of W. */
3420 window_box (w, -1, &x, &y, &width, &height);
3421
3422 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
3423 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
3424 bottom_y = y + height;
3425
3426 if (to_y < from_y)
3427 {
3428 /* Scrolling up. Make sure we don't copy part of the mode
3429 line at the bottom. */
3430 if (from_y + run->height > bottom_y)
3431 height = bottom_y - from_y;
3432 else
3433 height = run->height;
3434 }
3435 else
3436 {
3437 /* Scolling down. Make sure we don't copy over the mode line.
3438 at the bottom. */
3439 if (to_y + run->height > bottom_y)
3440 height = bottom_y - to_y;
3441 else
3442 height = run->height;
3443 }
3444
3445 BLOCK_INPUT;
3446
3447 /* Cursor off. Will be switched on again in x_update_window_end. */
3448 updated_window = w;
3449 x_clear_cursor (w);
3450
3451 mac_scroll_area (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
3452 f->output_data.mac->normal_gc,
3453 x, from_y,
3454 width, height,
3455 x, to_y);
3456
3457 UNBLOCK_INPUT;
3458 }
3459
3460
3461 \f
3462 /***********************************************************************
3463 Exposure Events
3464 ***********************************************************************/
3465
3466 \f
3467 static void
3468 frame_highlight (f)
3469 struct frame *f;
3470 {
3471 x_update_cursor (f, 1);
3472 }
3473
3474 static void
3475 frame_unhighlight (f)
3476 struct frame *f;
3477 {
3478 x_update_cursor (f, 1);
3479 }
3480
3481 /* The focus has changed. Update the frames as necessary to reflect
3482 the new situation. Note that we can't change the selected frame
3483 here, because the Lisp code we are interrupting might become confused.
3484 Each event gets marked with the frame in which it occurred, so the
3485 Lisp code can tell when the switch took place by examining the events. */
3486
3487 static void
3488 x_new_focus_frame (dpyinfo, frame)
3489 struct x_display_info *dpyinfo;
3490 struct frame *frame;
3491 {
3492 struct frame *old_focus = dpyinfo->x_focus_frame;
3493
3494 if (frame != dpyinfo->x_focus_frame)
3495 {
3496 /* Set this before calling other routines, so that they see
3497 the correct value of x_focus_frame. */
3498 dpyinfo->x_focus_frame = frame;
3499
3500 if (old_focus && old_focus->auto_lower)
3501 x_lower_frame (old_focus);
3502
3503 #if 0
3504 selected_frame = frame;
3505 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame,
3506 selected_frame);
3507 Fselect_window (selected_frame->selected_window, Qnil);
3508 choose_minibuf_frame ();
3509 #endif /* ! 0 */
3510
3511 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise)
3512 pending_autoraise_frame = dpyinfo->x_focus_frame;
3513 else
3514 pending_autoraise_frame = 0;
3515 }
3516
3517 x_frame_rehighlight (dpyinfo);
3518 }
3519
3520 /* Handle an event saying the mouse has moved out of an Emacs frame. */
3521
3522 void
3523 x_mouse_leave (dpyinfo)
3524 struct x_display_info *dpyinfo;
3525 {
3526 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame);
3527 }
3528
3529 /* The focus has changed, or we have redirected a frame's focus to
3530 another frame (this happens when a frame uses a surrogate
3531 mini-buffer frame). Shift the highlight as appropriate.
3532
3533 The FRAME argument doesn't necessarily have anything to do with which
3534 frame is being highlighted or un-highlighted; we only use it to find
3535 the appropriate X display info. */
3536
3537 static void
3538 XTframe_rehighlight (frame)
3539 struct frame *frame;
3540 {
3541 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame));
3542 }
3543
3544 static void
3545 x_frame_rehighlight (dpyinfo)
3546 struct x_display_info *dpyinfo;
3547 {
3548 struct frame *old_highlight = dpyinfo->x_highlight_frame;
3549
3550 if (dpyinfo->x_focus_frame)
3551 {
3552 dpyinfo->x_highlight_frame
3553 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)))
3554 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
3555 : dpyinfo->x_focus_frame);
3556 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame))
3557 {
3558 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
3559 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
3560 }
3561 }
3562 else
3563 dpyinfo->x_highlight_frame = 0;
3564
3565 if (dpyinfo->x_highlight_frame != old_highlight)
3566 {
3567 if (old_highlight)
3568 frame_unhighlight (old_highlight);
3569 if (dpyinfo->x_highlight_frame)
3570 frame_highlight (dpyinfo->x_highlight_frame);
3571 }
3572 }
3573
3574
3575 \f
3576 /* Keyboard processing - modifier keys, vendor-specific keysyms, etc. */
3577
3578 #if 0 /* MAC_TODO */
3579 /* Initialize mode_switch_bit and modifier_meaning. */
3580 static void
3581 x_find_modifier_meanings (dpyinfo)
3582 struct x_display_info *dpyinfo;
3583 {
3584 int min_code, max_code;
3585 KeySym *syms;
3586 int syms_per_code;
3587 XModifierKeymap *mods;
3588
3589 dpyinfo->meta_mod_mask = 0;
3590 dpyinfo->shift_lock_mask = 0;
3591 dpyinfo->alt_mod_mask = 0;
3592 dpyinfo->super_mod_mask = 0;
3593 dpyinfo->hyper_mod_mask = 0;
3594
3595 #ifdef HAVE_X11R4
3596 XDisplayKeycodes (dpyinfo->display, &min_code, &max_code);
3597 #else
3598 min_code = dpyinfo->display->min_keycode;
3599 max_code = dpyinfo->display->max_keycode;
3600 #endif
3601
3602 syms = XGetKeyboardMapping (dpyinfo->display,
3603 min_code, max_code - min_code + 1,
3604 &syms_per_code);
3605 mods = XGetModifierMapping (dpyinfo->display);
3606
3607 /* Scan the modifier table to see which modifier bits the Meta and
3608 Alt keysyms are on. */
3609 {
3610 int row, col; /* The row and column in the modifier table. */
3611
3612 for (row = 3; row < 8; row++)
3613 for (col = 0; col < mods->max_keypermod; col++)
3614 {
3615 KeyCode code
3616 = mods->modifiermap[(row * mods->max_keypermod) + col];
3617
3618 /* Zeroes are used for filler. Skip them. */
3619 if (code == 0)
3620 continue;
3621
3622 /* Are any of this keycode's keysyms a meta key? */
3623 {
3624 int code_col;
3625
3626 for (code_col = 0; code_col < syms_per_code; code_col++)
3627 {
3628 int sym = syms[((code - min_code) * syms_per_code) + code_col];
3629
3630 switch (sym)
3631 {
3632 case XK_Meta_L:
3633 case XK_Meta_R:
3634 dpyinfo->meta_mod_mask |= (1 << row);
3635 break;
3636
3637 case XK_Alt_L:
3638 case XK_Alt_R:
3639 dpyinfo->alt_mod_mask |= (1 << row);
3640 break;
3641
3642 case XK_Hyper_L:
3643 case XK_Hyper_R:
3644 dpyinfo->hyper_mod_mask |= (1 << row);
3645 break;
3646
3647 case XK_Super_L:
3648 case XK_Super_R:
3649 dpyinfo->super_mod_mask |= (1 << row);
3650 break;
3651
3652 case XK_Shift_Lock:
3653 /* Ignore this if it's not on the lock modifier. */
3654 if ((1 << row) == LockMask)
3655 dpyinfo->shift_lock_mask = LockMask;
3656 break;
3657 }
3658 }
3659 }
3660 }
3661 }
3662
3663 /* If we couldn't find any meta keys, accept any alt keys as meta keys. */
3664 if (! dpyinfo->meta_mod_mask)
3665 {
3666 dpyinfo->meta_mod_mask = dpyinfo->alt_mod_mask;
3667 dpyinfo->alt_mod_mask = 0;
3668 }
3669
3670 /* If some keys are both alt and meta,
3671 make them just meta, not alt. */
3672 if (dpyinfo->alt_mod_mask & dpyinfo->meta_mod_mask)
3673 {
3674 dpyinfo->alt_mod_mask &= ~dpyinfo->meta_mod_mask;
3675 }
3676
3677 XFree ((char *) syms);
3678 XFreeModifiermap (mods);
3679 }
3680
3681 #endif /* MAC_TODO */
3682
3683 /* Convert between the modifier bits X uses and the modifier bits
3684 Emacs uses. */
3685
3686 static unsigned int
3687 x_mac_to_emacs_modifiers (dpyinfo, state)
3688 struct x_display_info *dpyinfo;
3689 unsigned short state;
3690 {
3691 return (((state & shiftKey) ? shift_modifier : 0)
3692 | ((state & controlKey) ? ctrl_modifier : 0)
3693 | ((state & cmdKey) ? meta_modifier : 0)
3694 | ((state & optionKey) ? alt_modifier : 0));
3695 }
3696
3697 #if 0 /* MAC_TODO */
3698 static unsigned short
3699 x_emacs_to_x_modifiers (dpyinfo, state)
3700 struct x_display_info *dpyinfo;
3701 unsigned int state;
3702 {
3703 return ( ((state & alt_modifier) ? dpyinfo->alt_mod_mask : 0)
3704 | ((state & super_modifier) ? dpyinfo->super_mod_mask : 0)
3705 | ((state & hyper_modifier) ? dpyinfo->hyper_mod_mask : 0)
3706 | ((state & shift_modifier) ? ShiftMask : 0)
3707 | ((state & ctrl_modifier) ? ControlMask : 0)
3708 | ((state & meta_modifier) ? dpyinfo->meta_mod_mask : 0));
3709 }
3710 #endif /* MAC_TODO */
3711
3712 /* Convert a keysym to its name. */
3713
3714 char *
3715 x_get_keysym_name (keysym)
3716 int keysym;
3717 {
3718 char *value;
3719
3720 BLOCK_INPUT;
3721 #if 0
3722 value = XKeysymToString (keysym);
3723 #else
3724 value = 0;
3725 #endif
3726 UNBLOCK_INPUT;
3727
3728 return value;
3729 }
3730
3731
3732 \f
3733 #if 0
3734 /* Mouse clicks and mouse movement. Rah. */
3735
3736 /* Prepare a mouse-event in *RESULT for placement in the input queue.
3737
3738 If the event is a button press, then note that we have grabbed
3739 the mouse. */
3740
3741 static Lisp_Object
3742 construct_mouse_click (result, event, f)
3743 struct input_event *result;
3744 EventRecord *event;
3745 struct frame *f;
3746 {
3747 Point mouseLoc;
3748
3749 result->kind = MOUSE_CLICK_EVENT;
3750 result->code = 0; /* only one mouse button */
3751 result->timestamp = event->when;
3752 result->modifiers = event->what == mouseDown ? down_modifier : up_modifier;
3753
3754 mouseLoc = event->where;
3755
3756 SetPortWindowPort (FRAME_MAC_WINDOW (f));
3757
3758 GlobalToLocal (&mouseLoc);
3759 XSETINT (result->x, mouseLoc.h);
3760 XSETINT (result->y, mouseLoc.v);
3761
3762 XSETFRAME (result->frame_or_window, f);
3763
3764 result->arg = Qnil;
3765 return Qnil;
3766 }
3767 #endif
3768
3769 \f
3770 /* Function to report a mouse movement to the mainstream Emacs code.
3771 The input handler calls this.
3772
3773 We have received a mouse movement event, which is given in *event.
3774 If the mouse is over a different glyph than it was last time, tell
3775 the mainstream emacs code by setting mouse_moved. If not, ask for
3776 another motion event, so we can check again the next time it moves. */
3777
3778 static Point last_mouse_motion_position;
3779 static Lisp_Object last_mouse_motion_frame;
3780
3781 static void
3782 note_mouse_movement (frame, pos)
3783 FRAME_PTR frame;
3784 Point *pos;
3785 {
3786 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame);
3787 #if TARGET_API_MAC_CARBON
3788 Rect r;
3789 #endif
3790
3791 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */
3792 last_mouse_motion_position = *pos;
3793 XSETFRAME (last_mouse_motion_frame, frame);
3794
3795 #if TARGET_API_MAC_CARBON
3796 if (!PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)))
3797 #else
3798 if (!PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect))
3799 #endif
3800 {
3801 if (frame == dpyinfo->mouse_face_mouse_frame)
3802 /* This case corresponds to LeaveNotify in X11. */
3803 {
3804 /* If we move outside the frame, then we're certainly no
3805 longer on any text in the frame. */
3806 clear_mouse_face (dpyinfo);
3807 dpyinfo->mouse_face_mouse_frame = 0;
3808 if (!dpyinfo->grabbed)
3809 rif->define_frame_cursor (frame,
3810 frame->output_data.mac->nontext_cursor);
3811 }
3812 }
3813 /* Has the mouse moved off the glyph it was on at the last sighting? */
3814 else if (pos->h < last_mouse_glyph.left
3815 || pos->h >= last_mouse_glyph.right
3816 || pos->v < last_mouse_glyph.top
3817 || pos->v >= last_mouse_glyph.bottom)
3818 {
3819 frame->mouse_moved = 1;
3820 last_mouse_scroll_bar = Qnil;
3821 note_mouse_highlight (frame, pos->h, pos->v);
3822 }
3823 }
3824
3825 /* This is used for debugging, to turn off note_mouse_highlight. */
3826
3827 int disable_mouse_highlight;
3828
3829
3830 \f
3831 /************************************************************************
3832 Mouse Face
3833 ************************************************************************/
3834
3835 static struct scroll_bar *x_window_to_scroll_bar ();
3836 static void x_scroll_bar_report_motion ();
3837 static int glyph_rect P_ ((struct frame *f, int, int, Rect *));
3838
3839
3840 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3841
3842 static void
3843 redo_mouse_highlight ()
3844 {
3845 if (!NILP (last_mouse_motion_frame)
3846 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame)))
3847 note_mouse_highlight (XFRAME (last_mouse_motion_frame),
3848 last_mouse_motion_position.h,
3849 last_mouse_motion_position.v);
3850 }
3851
3852
3853 /* Try to determine frame pixel position and size of the glyph under
3854 frame pixel coordinates X/Y on frame F . Return the position and
3855 size in *RECT. Value is non-zero if we could compute these
3856 values. */
3857
3858 static int
3859 glyph_rect (f, x, y, rect)
3860 struct frame *f;
3861 int x, y;
3862 Rect *rect;
3863 {
3864 Lisp_Object window;
3865
3866 window = window_from_coordinates (f, x, y, 0, &x, &y, 0);
3867
3868 if (!NILP (window))
3869 {
3870 struct window *w = XWINDOW (window);
3871 struct glyph_row *r = MATRIX_FIRST_TEXT_ROW (w->current_matrix);
3872 struct glyph_row *end = r + w->current_matrix->nrows - 1;
3873
3874 for (; r < end && r->enabled_p; ++r)
3875 if (r->y <= y && r->y + r->height > y)
3876 {
3877 /* Found the row at y. */
3878 struct glyph *g = r->glyphs[TEXT_AREA];
3879 struct glyph *end = g + r->used[TEXT_AREA];
3880 int gx;
3881
3882 rect->top = WINDOW_TO_FRAME_PIXEL_Y (w, r->y);
3883 rect->bottom = rect->top + r->height;
3884
3885 if (x < r->x)
3886 {
3887 /* x is to the left of the first glyph in the row. */
3888 /* Shouldn't this be a pixel value?
3889 WINDOW_LEFT_EDGE_X (w) seems to be the right value.
3890 ++KFS */
3891 rect->left = WINDOW_LEFT_EDGE_COL (w);
3892 rect->right = WINDOW_TO_FRAME_PIXEL_X (w, r->x);
3893 return 1;
3894 }
3895
3896 for (gx = r->x; g < end; gx += g->pixel_width, ++g)
3897 if (gx <= x && gx + g->pixel_width > x)
3898 {
3899 /* x is on a glyph. */
3900 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3901 rect->right = rect->left + g->pixel_width;
3902 return 1;
3903 }
3904
3905 /* x is to the right of the last glyph in the row. */
3906 rect->left = WINDOW_TO_FRAME_PIXEL_X (w, gx);
3907 /* Shouldn't this be a pixel value?
3908 WINDOW_RIGHT_EDGE_X (w) seems to be the right value.
3909 ++KFS */
3910 rect->right = WINDOW_RIGHT_EDGE_COL (w);
3911 return 1;
3912 }
3913 }
3914
3915 /* The y is not on any row. */
3916 return 0;
3917 }
3918
3919 /* MAC TODO: This should be called from somewhere (or removed) ++KFS */
3920
3921 /* Record the position of the mouse in last_mouse_glyph. */
3922 static void
3923 remember_mouse_glyph (f1, gx, gy)
3924 struct frame * f1;
3925 int gx, gy;
3926 {
3927 if (!glyph_rect (f1, gx, gy, &last_mouse_glyph))
3928 {
3929 int width = FRAME_SMALLEST_CHAR_WIDTH (f1);
3930 int height = FRAME_SMALLEST_FONT_HEIGHT (f1);
3931
3932 /* Arrange for the division in FRAME_PIXEL_X_TO_COL etc. to
3933 round down even for negative values. */
3934 if (gx < 0)
3935 gx -= width - 1;
3936 if (gy < 0)
3937 gy -= height - 1;
3938 #if 0
3939 /* This was the original code from XTmouse_position, but it seems
3940 to give the position of the glyph diagonally next to the one
3941 the mouse is over. */
3942 gx = (gx + width - 1) / width * width;
3943 gy = (gy + height - 1) / height * height;
3944 #else
3945 gx = gx / width * width;
3946 gy = gy / height * height;
3947 #endif
3948
3949 last_mouse_glyph.left = gx;
3950 last_mouse_glyph.top = gy;
3951 last_mouse_glyph.right = gx + width;
3952 last_mouse_glyph.bottom = gy + height;
3953 }
3954 }
3955
3956
3957 static WindowPtr
3958 front_emacs_window ()
3959 {
3960 #if TARGET_API_MAC_CARBON
3961 WindowPtr wp = GetFrontWindowOfClass (kDocumentWindowClass, true);
3962
3963 while (wp && !is_emacs_window (wp))
3964 wp = GetNextWindowOfClass (wp, kDocumentWindowClass, true);
3965 #else
3966 WindowPtr wp = FrontWindow ();
3967
3968 while (wp && (wp == tip_window || !is_emacs_window (wp)))
3969 wp = GetNextWindow (wp);
3970 #endif
3971
3972 return wp;
3973 }
3974
3975 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
3976
3977 /* Return the current position of the mouse.
3978 *fp should be a frame which indicates which display to ask about.
3979
3980 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3981 and *part to the frame, window, and scroll bar part that the mouse
3982 is over. Set *x and *y to the portion and whole of the mouse's
3983 position on the scroll bar.
3984
3985 If the mouse movement started elsewhere, set *fp to the frame the
3986 mouse is on, *bar_window to nil, and *x and *y to the character cell
3987 the mouse is over.
3988
3989 Set *time to the server time-stamp for the time at which the mouse
3990 was at this position.
3991
3992 Don't store anything if we don't have a valid set of values to report.
3993
3994 This clears the mouse_moved flag, so we can wait for the next mouse
3995 movement. */
3996
3997 static void
3998 XTmouse_position (fp, insist, bar_window, part, x, y, time)
3999 FRAME_PTR *fp;
4000 int insist;
4001 Lisp_Object *bar_window;
4002 enum scroll_bar_part *part;
4003 Lisp_Object *x, *y;
4004 unsigned long *time;
4005 {
4006 Point mouse_pos;
4007 int ignore1, ignore2;
4008 WindowPtr wp = front_emacs_window ();
4009 struct frame *f;
4010 Lisp_Object frame, tail;
4011
4012 if (is_emacs_window(wp))
4013 f = mac_window_to_frame (wp);
4014
4015 BLOCK_INPUT;
4016
4017 if (! NILP (last_mouse_scroll_bar) && insist == 0)
4018 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
4019 else
4020 {
4021 /* Clear the mouse-moved flag for every frame on this display. */
4022 FOR_EACH_FRAME (tail, frame)
4023 XFRAME (frame)->mouse_moved = 0;
4024
4025 last_mouse_scroll_bar = Qnil;
4026
4027 SetPortWindowPort (wp);
4028
4029 GetMouse (&mouse_pos);
4030
4031 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
4032 &last_mouse_glyph, insist);
4033
4034 *bar_window = Qnil;
4035 *part = scroll_bar_handle;
4036 *fp = f;
4037 XSETINT (*x, mouse_pos.h);
4038 XSETINT (*y, mouse_pos.v);
4039 *time = last_mouse_movement_time;
4040 }
4041
4042 UNBLOCK_INPUT;
4043 }
4044
4045 \f
4046 /***********************************************************************
4047 Tool-bars
4048 ***********************************************************************/
4049
4050 /* Handle mouse button event on the tool-bar of frame F, at
4051 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
4052 or ButtonRelase. */
4053
4054 static void
4055 mac_handle_tool_bar_click (f, button_event)
4056 struct frame *f;
4057 EventRecord *button_event;
4058 {
4059 int x = button_event->where.h;
4060 int y = button_event->where.v;
4061
4062 if (button_event->what == mouseDown)
4063 handle_tool_bar_click (f, x, y, 1, 0);
4064 else
4065 handle_tool_bar_click (f, x, y, 0,
4066 x_mac_to_emacs_modifiers (FRAME_MAC_DISPLAY_INFO (f),
4067 button_event->modifiers));
4068 }
4069
4070 \f
4071 /************************************************************************
4072 Scroll bars, general
4073 ************************************************************************/
4074
4075 /* Create a scroll bar and return the scroll bar vector for it. W is
4076 the Emacs window on which to create the scroll bar. TOP, LEFT,
4077 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4078 scroll bar. */
4079
4080 static struct scroll_bar *
4081 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
4082 struct window *w;
4083 int top, left, width, height, disp_top, disp_height;
4084 {
4085 struct frame *f = XFRAME (w->frame);
4086 struct scroll_bar *bar
4087 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
4088 Rect r;
4089 ControlHandle ch;
4090
4091 BLOCK_INPUT;
4092
4093 r.left = left;
4094 r.top = disp_top;
4095 r.right = left + width;
4096 r.bottom = disp_top + disp_height;
4097
4098 #if TARGET_API_MAC_CARBON
4099 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
4100 kControlScrollBarProc, 0L);
4101 #else
4102 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
4103 0L);
4104 #endif
4105 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
4106 SetControlReference (ch, (long) bar);
4107
4108 XSETWINDOW (bar->window, w);
4109 XSETINT (bar->top, top);
4110 XSETINT (bar->left, left);
4111 XSETINT (bar->width, width);
4112 XSETINT (bar->height, height);
4113 XSETINT (bar->start, 0);
4114 XSETINT (bar->end, 0);
4115 bar->dragging = Qnil;
4116
4117 /* Add bar to its frame's list of scroll bars. */
4118 bar->next = FRAME_SCROLL_BARS (f);
4119 bar->prev = Qnil;
4120 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4121 if (!NILP (bar->next))
4122 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4123
4124 UNBLOCK_INPUT;
4125 return bar;
4126 }
4127
4128
4129 /* Draw BAR's handle in the proper position.
4130
4131 If the handle is already drawn from START to END, don't bother
4132 redrawing it, unless REBUILD is non-zero; in that case, always
4133 redraw it. (REBUILD is handy for drawing the handle after expose
4134 events.)
4135
4136 Normally, we want to constrain the start and end of the handle to
4137 fit inside its rectangle, but if the user is dragging the scroll
4138 bar handle, we want to let them drag it down all the way, so that
4139 the bar's top is as far down as it goes; otherwise, there's no way
4140 to move to the very end of the buffer. */
4141
4142 static void
4143 x_scroll_bar_set_handle (bar, start, end, rebuild)
4144 struct scroll_bar *bar;
4145 int start, end;
4146 int rebuild;
4147 {
4148 int dragging = ! NILP (bar->dragging);
4149 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4150 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4151 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4152 int length = end - start;
4153
4154 /* If the display is already accurate, do nothing. */
4155 if (! rebuild
4156 && start == XINT (bar->start)
4157 && end == XINT (bar->end))
4158 return;
4159
4160 BLOCK_INPUT;
4161
4162 /* Make sure the values are reasonable, and try to preserve the
4163 distance between start and end. */
4164 if (start < 0)
4165 start = 0;
4166 else if (start > top_range)
4167 start = top_range;
4168 end = start + length;
4169
4170 if (end < start)
4171 end = start;
4172 else if (end > top_range && ! dragging)
4173 end = top_range;
4174
4175 /* Store the adjusted setting in the scroll bar. */
4176 XSETINT (bar->start, start);
4177 XSETINT (bar->end, end);
4178
4179 /* Clip the end position, just for display. */
4180 if (end > top_range)
4181 end = top_range;
4182
4183 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4184 top positions, to make sure the handle is always at least that
4185 many pixels tall. */
4186 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
4187
4188 SetControlMinimum (ch, 0);
4189 /* Don't inadvertently activate deactivated scroll bars */
4190 if (GetControlMaximum (ch) != -1)
4191 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
4192 - (end - start));
4193 SetControlValue (ch, start);
4194 #if TARGET_API_MAC_CARBON
4195 SetControlViewSize (ch, end - start);
4196 #endif
4197
4198 UNBLOCK_INPUT;
4199 }
4200
4201
4202 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4203 nil. */
4204
4205 static void
4206 x_scroll_bar_remove (bar)
4207 struct scroll_bar *bar;
4208 {
4209 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4210
4211 BLOCK_INPUT;
4212
4213 /* Destroy the Mac scroll bar control */
4214 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
4215
4216 /* Disassociate this scroll bar from its window. */
4217 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
4218
4219 UNBLOCK_INPUT;
4220 }
4221
4222 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4223 that we are displaying PORTION characters out of a total of WHOLE
4224 characters, starting at POSITION. If WINDOW has no scroll bar,
4225 create one. */
4226 static void
4227 XTset_vertical_scroll_bar (w, portion, whole, position)
4228 struct window *w;
4229 int portion, whole, position;
4230 {
4231 struct frame *f = XFRAME (w->frame);
4232 struct scroll_bar *bar;
4233 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
4234 int window_y, window_height;
4235
4236 /* Get window dimensions. */
4237 window_box (w, -1, 0, &window_y, 0, &window_height);
4238 top = window_y;
4239 #ifdef MAC_OSX
4240 width = 16;
4241 #else
4242 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
4243 #endif
4244 height = window_height;
4245
4246 /* Compute the left edge of the scroll bar area. */
4247 left = WINDOW_SCROLL_BAR_AREA_X (w);
4248
4249 /* Compute the width of the scroll bar which might be less than
4250 the width of the area reserved for the scroll bar. */
4251 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
4252 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
4253 else
4254 sb_width = width;
4255
4256 /* Compute the left edge of the scroll bar. */
4257 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
4258 sb_left = left + width - sb_width - (width - sb_width) / 2;
4259 else
4260 sb_left = left + (width - sb_width) / 2;
4261
4262 /* Adjustments according to Inside Macintosh to make it look nice */
4263 disp_top = top;
4264 disp_height = height;
4265 if (disp_top == 0)
4266 {
4267 disp_top = -1;
4268 disp_height++;
4269 }
4270 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
4271 {
4272 disp_top++;
4273 disp_height--;
4274 }
4275
4276 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
4277 sb_left++;
4278
4279 /* Does the scroll bar exist yet? */
4280 if (NILP (w->vertical_scroll_bar))
4281 {
4282 BLOCK_INPUT;
4283 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4284 left, top, width, height, 0);
4285 UNBLOCK_INPUT;
4286 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
4287 disp_height);
4288 XSETVECTOR (w->vertical_scroll_bar, bar);
4289 }
4290 else
4291 {
4292 /* It may just need to be moved and resized. */
4293 ControlHandle ch;
4294
4295 bar = XSCROLL_BAR (w->vertical_scroll_bar);
4296 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4297
4298 BLOCK_INPUT;
4299
4300 /* If already correctly positioned, do nothing. */
4301 if (XINT (bar->left) == sb_left
4302 && XINT (bar->top) == top
4303 && XINT (bar->width) == sb_width
4304 && XINT (bar->height) == height)
4305 Draw1Control (ch);
4306 else
4307 {
4308 /* Clear areas not covered by the scroll bar because it's not as
4309 wide as the area reserved for it . This makes sure a
4310 previous mode line display is cleared after C-x 2 C-x 1, for
4311 example. */
4312 int area_width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
4313 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4314 left, top, area_width, height, 0);
4315
4316 #if 0
4317 if (sb_left + sb_width >= FRAME_PIXEL_WIDTH (f))
4318 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4319 sb_left - 1, top, 1, height, 0);
4320 #endif
4321
4322 HideControl (ch);
4323 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
4324 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4325 disp_height);
4326 ShowControl (ch);
4327
4328 /* Remember new settings. */
4329 XSETINT (bar->left, sb_left);
4330 XSETINT (bar->top, top);
4331 XSETINT (bar->width, sb_width);
4332 XSETINT (bar->height, height);
4333 }
4334
4335 UNBLOCK_INPUT;
4336 }
4337
4338 /* Set the scroll bar's current state, unless we're currently being
4339 dragged. */
4340 if (NILP (bar->dragging))
4341 {
4342 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
4343
4344 if (whole == 0)
4345 x_scroll_bar_set_handle (bar, 0, top_range, 0);
4346 else
4347 {
4348 int start = ((double) position * top_range) / whole;
4349 int end = ((double) (position + portion) * top_range) / whole;
4350 x_scroll_bar_set_handle (bar, start, end, 0);
4351 }
4352 }
4353 }
4354
4355
4356 /* The following three hooks are used when we're doing a thorough
4357 redisplay of the frame. We don't explicitly know which scroll bars
4358 are going to be deleted, because keeping track of when windows go
4359 away is a real pain - "Can you say set-window-configuration, boys
4360 and girls?" Instead, we just assert at the beginning of redisplay
4361 that *all* scroll bars are to be removed, and then save a scroll bar
4362 from the fiery pit when we actually redisplay its window. */
4363
4364 /* Arrange for all scroll bars on FRAME to be removed at the next call
4365 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4366 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4367
4368 static void
4369 XTcondemn_scroll_bars (frame)
4370 FRAME_PTR frame;
4371 {
4372 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4373 while (! NILP (FRAME_SCROLL_BARS (frame)))
4374 {
4375 Lisp_Object bar;
4376 bar = FRAME_SCROLL_BARS (frame);
4377 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
4378 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
4379 XSCROLL_BAR (bar)->prev = Qnil;
4380 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
4381 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
4382 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
4383 }
4384 }
4385
4386
4387 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4388 Note that WINDOW isn't necessarily condemned at all. */
4389
4390 static void
4391 XTredeem_scroll_bar (window)
4392 struct window *window;
4393 {
4394 struct scroll_bar *bar;
4395
4396 /* We can't redeem this window's scroll bar if it doesn't have one. */
4397 if (NILP (window->vertical_scroll_bar))
4398 abort ();
4399
4400 bar = XSCROLL_BAR (window->vertical_scroll_bar);
4401
4402 /* Unlink it from the condemned list. */
4403 {
4404 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
4405
4406 if (NILP (bar->prev))
4407 {
4408 /* If the prev pointer is nil, it must be the first in one of
4409 the lists. */
4410 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
4411 /* It's not condemned. Everything's fine. */
4412 return;
4413 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4414 window->vertical_scroll_bar))
4415 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
4416 else
4417 /* If its prev pointer is nil, it must be at the front of
4418 one or the other! */
4419 abort ();
4420 }
4421 else
4422 XSCROLL_BAR (bar->prev)->next = bar->next;
4423
4424 if (! NILP (bar->next))
4425 XSCROLL_BAR (bar->next)->prev = bar->prev;
4426
4427 bar->next = FRAME_SCROLL_BARS (f);
4428 bar->prev = Qnil;
4429 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4430 if (! NILP (bar->next))
4431 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4432 }
4433 }
4434
4435 /* Remove all scroll bars on FRAME that haven't been saved since the
4436 last call to `*condemn_scroll_bars_hook'. */
4437
4438 static void
4439 XTjudge_scroll_bars (f)
4440 FRAME_PTR f;
4441 {
4442 Lisp_Object bar, next;
4443
4444 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
4445
4446 /* Clear out the condemned list now so we won't try to process any
4447 more events on the hapless scroll bars. */
4448 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
4449
4450 for (; ! NILP (bar); bar = next)
4451 {
4452 struct scroll_bar *b = XSCROLL_BAR (bar);
4453
4454 x_scroll_bar_remove (b);
4455
4456 next = b->next;
4457 b->next = b->prev = Qnil;
4458 }
4459
4460 /* Now there should be no references to the condemned scroll bars,
4461 and they should get garbage-collected. */
4462 }
4463
4464
4465 void
4466 activate_scroll_bars (frame)
4467 FRAME_PTR frame;
4468 {
4469 Lisp_Object bar;
4470 ControlHandle ch;
4471
4472 bar = FRAME_SCROLL_BARS (frame);
4473 while (! NILP (bar))
4474 {
4475 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
4476 #if 1 /* TARGET_API_MAC_CARBON */
4477 ActivateControl (ch);
4478 #else
4479 SetControlMaximum (ch,
4480 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
4481 XINT (XSCROLL_BAR (bar)
4482 ->height)) - 1);
4483 #endif
4484 bar = XSCROLL_BAR (bar)->next;
4485 }
4486 }
4487
4488
4489 void
4490 deactivate_scroll_bars (frame)
4491 FRAME_PTR frame;
4492 {
4493 Lisp_Object bar;
4494 ControlHandle ch;
4495
4496 bar = FRAME_SCROLL_BARS (frame);
4497 while (! NILP (bar))
4498 {
4499 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
4500 #if 1 /* TARGET_API_MAC_CARBON */
4501 DeactivateControl (ch);
4502 #else
4503 SetControlMaximum (ch, -1);
4504 #endif
4505 bar = XSCROLL_BAR (bar)->next;
4506 }
4507 }
4508
4509 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4510 is set to something other than NO_EVENT, it is enqueued.
4511
4512 This may be called from a signal handler, so we have to ignore GC
4513 mark bits. */
4514
4515 static void
4516 x_scroll_bar_handle_click (bar, part_code, er, bufp)
4517 struct scroll_bar *bar;
4518 int part_code;
4519 EventRecord *er;
4520 struct input_event *bufp;
4521 {
4522 int win_y, top_range;
4523
4524 if (! GC_WINDOWP (bar->window))
4525 abort ();
4526
4527 bufp->kind = SCROLL_BAR_CLICK_EVENT;
4528 bufp->frame_or_window = bar->window;
4529 bufp->arg = Qnil;
4530
4531 bar->dragging = Qnil;
4532
4533 switch (part_code)
4534 {
4535 case kControlUpButtonPart:
4536 bufp->part = scroll_bar_up_arrow;
4537 break;
4538 case kControlDownButtonPart:
4539 bufp->part = scroll_bar_down_arrow;
4540 break;
4541 case kControlPageUpPart:
4542 bufp->part = scroll_bar_above_handle;
4543 break;
4544 case kControlPageDownPart:
4545 bufp->part = scroll_bar_below_handle;
4546 break;
4547 #if TARGET_API_MAC_CARBON
4548 default:
4549 #else
4550 case kControlIndicatorPart:
4551 #endif
4552 if (er->what == mouseDown)
4553 bar->dragging = make_number (0);
4554 XSETVECTOR (last_mouse_scroll_bar, bar);
4555 bufp->part = scroll_bar_handle;
4556 break;
4557 }
4558
4559 win_y = XINT (bufp->y) - XINT (bar->top);
4560 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar->height));
4561
4562 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
4563
4564 win_y -= 24;
4565
4566 if (! NILP (bar->dragging))
4567 win_y -= XINT (bar->dragging);
4568
4569 if (win_y < 0)
4570 win_y = 0;
4571 if (win_y > top_range)
4572 win_y = top_range;
4573
4574 XSETINT (bufp->x, win_y);
4575 XSETINT (bufp->y, top_range);
4576 }
4577
4578
4579 /* Handle some mouse motion while someone is dragging the scroll bar.
4580
4581 This may be called from a signal handler, so we have to ignore GC
4582 mark bits. */
4583
4584 static void
4585 x_scroll_bar_note_movement (bar, y_pos, t)
4586 struct scroll_bar *bar;
4587 int y_pos;
4588 Time t;
4589 {
4590 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
4591
4592 last_mouse_movement_time = t;
4593
4594 f->mouse_moved = 1;
4595 XSETVECTOR (last_mouse_scroll_bar, bar);
4596
4597 /* If we're dragging the bar, display it. */
4598 if (! GC_NILP (bar->dragging))
4599 {
4600 /* Where should the handle be now? */
4601 int new_start = y_pos - 24;
4602
4603 if (new_start != XINT (bar->start))
4604 {
4605 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
4606
4607 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
4608 }
4609 }
4610 }
4611
4612
4613 /* Return information to the user about the current position of the
4614 mouse on the scroll bar. */
4615
4616 static void
4617 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
4618 FRAME_PTR *fp;
4619 Lisp_Object *bar_window;
4620 enum scroll_bar_part *part;
4621 Lisp_Object *x, *y;
4622 unsigned long *time;
4623 {
4624 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
4625 WindowPtr wp = front_emacs_window ();
4626 Point mouse_pos;
4627 struct frame *f = mac_window_to_frame (wp);
4628 int win_y, top_range;
4629
4630 SetPortWindowPort (wp);
4631
4632 GetMouse (&mouse_pos);
4633
4634 win_y = mouse_pos.v - XINT (bar->top);
4635 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4636
4637 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
4638
4639 win_y -= 24;
4640
4641 if (! NILP (bar->dragging))
4642 win_y -= XINT (bar->dragging);
4643
4644 if (win_y < 0)
4645 win_y = 0;
4646 if (win_y > top_range)
4647 win_y = top_range;
4648
4649 *fp = f;
4650 *bar_window = bar->window;
4651
4652 if (! NILP (bar->dragging))
4653 *part = scroll_bar_handle;
4654 else if (win_y < XINT (bar->start))
4655 *part = scroll_bar_above_handle;
4656 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
4657 *part = scroll_bar_handle;
4658 else
4659 *part = scroll_bar_below_handle;
4660
4661 XSETINT (*x, win_y);
4662 XSETINT (*y, top_range);
4663
4664 f->mouse_moved = 0;
4665 last_mouse_scroll_bar = Qnil;
4666
4667 *time = last_mouse_movement_time;
4668 }
4669 \f
4670 /***********************************************************************
4671 Text Cursor
4672 ***********************************************************************/
4673
4674 /* Set clipping for output in glyph row ROW. W is the window in which
4675 we operate. GC is the graphics context to set clipping in.
4676
4677 ROW may be a text row or, e.g., a mode line. Text rows must be
4678 clipped to the interior of the window dedicated to text display,
4679 mode lines must be clipped to the whole window. */
4680
4681 static void
4682 x_clip_to_row (w, row, area, gc)
4683 struct window *w;
4684 struct glyph_row *row;
4685 int area;
4686 GC gc;
4687 {
4688 struct frame *f = XFRAME (WINDOW_FRAME (w));
4689 Rect clip_rect;
4690 int window_x, window_y, window_width;
4691
4692 window_box (w, area, &window_x, &window_y, &window_width, 0);
4693
4694 clip_rect.left = window_x;
4695 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4696 clip_rect.top = max (clip_rect.top, window_y);
4697 clip_rect.right = clip_rect.left + window_width;
4698 clip_rect.bottom = clip_rect.top + row->visible_height;
4699
4700 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
4701 }
4702
4703
4704 /* Draw a hollow box cursor on window W in glyph row ROW. */
4705
4706 static void
4707 x_draw_hollow_cursor (w, row)
4708 struct window *w;
4709 struct glyph_row *row;
4710 {
4711 struct frame *f = XFRAME (WINDOW_FRAME (w));
4712 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4713 Display *dpy = FRAME_MAC_DISPLAY (f);
4714 int x, y, wd, h;
4715 XGCValues xgcv;
4716 struct glyph *cursor_glyph;
4717 GC gc;
4718
4719 /* Get the glyph the cursor is on. If we can't tell because
4720 the current matrix is invalid or such, give up. */
4721 cursor_glyph = get_phys_cursor_glyph (w);
4722 if (cursor_glyph == NULL)
4723 return;
4724
4725 /* Compute the width of the rectangle to draw. If on a stretch
4726 glyph, and `x-stretch-block-cursor' is nil, don't draw a
4727 rectangle as wide as the glyph, but use a canonical character
4728 width instead. */
4729 wd = cursor_glyph->pixel_width - 1;
4730 if (cursor_glyph->type == STRETCH_GLYPH
4731 && !x_stretch_cursor_p)
4732 wd = min (FRAME_COLUMN_WIDTH (f), wd);
4733 w->phys_cursor_width = wd;
4734
4735 /* Compute frame-relative coordinates from window-relative
4736 coordinates. */
4737 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
4738 y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y);
4739
4740 /* Compute the proper height and ascent of the rectangle, based
4741 on the actual glyph. Using the full height of the row looks
4742 bad when there are tall images on that row. */
4743 h = max (min (FRAME_LINE_HEIGHT (f), row->height),
4744 cursor_glyph->ascent + cursor_glyph->descent);
4745 if (h < row->height)
4746 y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
4747 h--;
4748
4749 /* The foreground of cursor_gc is typically the same as the normal
4750 background color, which can cause the cursor box to be invisible. */
4751 xgcv.foreground = f->output_data.mac->cursor_pixel;
4752 if (dpyinfo->scratch_cursor_gc)
4753 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
4754 else
4755 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
4756 GCForeground, &xgcv);
4757 gc = dpyinfo->scratch_cursor_gc;
4758
4759 /* Set clipping, draw the rectangle, and reset clipping again. */
4760 x_clip_to_row (w, row, TEXT_AREA, gc);
4761 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
4762 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4763 }
4764
4765
4766 /* Draw a bar cursor on window W in glyph row ROW.
4767
4768 Implementation note: One would like to draw a bar cursor with an
4769 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4770 Unfortunately, I didn't find a font yet that has this property set.
4771 --gerd. */
4772
4773 static void
4774 x_draw_bar_cursor (w, row, width, kind)
4775 struct window *w;
4776 struct glyph_row *row;
4777 int width;
4778 enum text_cursor_kinds kind;
4779 {
4780 struct frame *f = XFRAME (w->frame);
4781 struct glyph *cursor_glyph;
4782
4783 /* If cursor is out of bounds, don't draw garbage. This can happen
4784 in mini-buffer windows when switching between echo area glyphs
4785 and mini-buffer. */
4786 cursor_glyph = get_phys_cursor_glyph (w);
4787 if (cursor_glyph == NULL)
4788 return;
4789
4790 /* If on an image, draw like a normal cursor. That's usually better
4791 visible than drawing a bar, esp. if the image is large so that
4792 the bar might not be in the window. */
4793 if (cursor_glyph->type == IMAGE_GLYPH)
4794 {
4795 struct glyph_row *row;
4796 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
4797 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
4798 }
4799 else
4800 {
4801 Display *dpy = FRAME_MAC_DISPLAY (f);
4802 Window window = FRAME_MAC_WINDOW (f);
4803 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
4804 unsigned long mask = GCForeground | GCBackground;
4805 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
4806 XGCValues xgcv;
4807
4808 /* If the glyph's background equals the color we normally draw
4809 the bar cursor in, the bar cursor in its normal color is
4810 invisible. Use the glyph's foreground color instead in this
4811 case, on the assumption that the glyph's colors are chosen so
4812 that the glyph is legible. */
4813 if (face->background == f->output_data.mac->cursor_pixel)
4814 xgcv.background = xgcv.foreground = face->foreground;
4815 else
4816 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
4817
4818 if (gc)
4819 XChangeGC (dpy, gc, mask, &xgcv);
4820 else
4821 {
4822 gc = XCreateGC (dpy, window, mask, &xgcv);
4823 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
4824 }
4825
4826 if (width < 0)
4827 width = FRAME_CURSOR_WIDTH (f);
4828 width = min (cursor_glyph->pixel_width, width);
4829
4830 w->phys_cursor_width = width;
4831 x_clip_to_row (w, row, TEXT_AREA, gc);
4832
4833 if (kind == BAR_CURSOR)
4834 XFillRectangle (dpy, window, gc,
4835 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
4836 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
4837 width, row->height);
4838 else
4839 XFillRectangle (dpy, window, gc,
4840 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
4841 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
4842 row->height - width),
4843 cursor_glyph->pixel_width,
4844 width);
4845
4846 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4847 }
4848 }
4849
4850
4851 /* RIF: Define cursor CURSOR on frame F. */
4852
4853 static void
4854 mac_define_frame_cursor (f, cursor)
4855 struct frame *f;
4856 Cursor cursor;
4857 {
4858 #if TARGET_API_MAC_CARBON
4859 SetThemeCursor (cursor);
4860 #else
4861 SetCursor (*cursor);
4862 #endif
4863 }
4864
4865
4866 /* RIF: Clear area on frame F. */
4867
4868 static void
4869 mac_clear_frame_area (f, x, y, width, height)
4870 struct frame *f;
4871 int x, y, width, height;
4872 {
4873 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4874 x, y, width, height, 0);
4875 }
4876
4877
4878 /* RIF: Draw cursor on window W. */
4879
4880 static void
4881 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
4882 struct window *w;
4883 struct glyph_row *glyph_row;
4884 int x, y;
4885 int cursor_type, cursor_width;
4886 int on_p, active_p;
4887 {
4888 if (on_p)
4889 {
4890 w->phys_cursor_type = cursor_type;
4891 w->phys_cursor_on_p = 1;
4892
4893 if (glyph_row->exact_window_width_line_p
4894 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
4895 {
4896 glyph_row->cursor_in_fringe_p = 1;
4897 draw_fringe_bitmap (w, glyph_row, 0);
4898 }
4899 else
4900 switch (cursor_type)
4901 {
4902 case HOLLOW_BOX_CURSOR:
4903 x_draw_hollow_cursor (w, glyph_row);
4904 break;
4905
4906 case FILLED_BOX_CURSOR:
4907 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
4908 break;
4909
4910 case BAR_CURSOR:
4911 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
4912 break;
4913
4914 case HBAR_CURSOR:
4915 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
4916 break;
4917
4918 case NO_CURSOR:
4919 w->phys_cursor_width = 0;
4920 break;
4921
4922 default:
4923 abort ();
4924 }
4925 }
4926 }
4927
4928 \f
4929 /* Icons. */
4930
4931 #if 0 /* MAC_TODO: no icon support yet. */
4932 int
4933 x_bitmap_icon (f, icon)
4934 struct frame *f;
4935 Lisp_Object icon;
4936 {
4937 HANDLE hicon;
4938
4939 if (FRAME_W32_WINDOW (f) == 0)
4940 return 1;
4941
4942 if (NILP (icon))
4943 hicon = LoadIcon (hinst, EMACS_CLASS);
4944 else if (STRINGP (icon))
4945 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
4946 LR_DEFAULTSIZE | LR_LOADFROMFILE);
4947 else if (SYMBOLP (icon))
4948 {
4949 LPCTSTR name;
4950
4951 if (EQ (icon, intern ("application")))
4952 name = (LPCTSTR) IDI_APPLICATION;
4953 else if (EQ (icon, intern ("hand")))
4954 name = (LPCTSTR) IDI_HAND;
4955 else if (EQ (icon, intern ("question")))
4956 name = (LPCTSTR) IDI_QUESTION;
4957 else if (EQ (icon, intern ("exclamation")))
4958 name = (LPCTSTR) IDI_EXCLAMATION;
4959 else if (EQ (icon, intern ("asterisk")))
4960 name = (LPCTSTR) IDI_ASTERISK;
4961 else if (EQ (icon, intern ("winlogo")))
4962 name = (LPCTSTR) IDI_WINLOGO;
4963 else
4964 return 1;
4965
4966 hicon = LoadIcon (NULL, name);
4967 }
4968 else
4969 return 1;
4970
4971 if (hicon == NULL)
4972 return 1;
4973
4974 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
4975 (LPARAM) hicon);
4976
4977 return 0;
4978 }
4979 #endif /* MAC_TODO */
4980 \f
4981 /************************************************************************
4982 Handling X errors
4983 ************************************************************************/
4984
4985 /* Display Error Handling functions not used on W32. Listing them here
4986 helps diff stay in step when comparing w32term.c with xterm.c.
4987
4988 x_error_catcher (display, error)
4989 x_catch_errors (dpy)
4990 x_catch_errors_unwind (old_val)
4991 x_check_errors (dpy, format)
4992 x_had_errors_p (dpy)
4993 x_clear_errors (dpy)
4994 x_uncatch_errors (dpy, count)
4995 x_trace_wire ()
4996 x_connection_signal (signalnum)
4997 x_connection_closed (dpy, error_message)
4998 x_error_quitter (display, error)
4999 x_error_handler (display, error)
5000 x_io_error_quitter (display)
5001
5002 */
5003
5004 \f
5005 /* Changing the font of the frame. */
5006
5007 /* Give frame F the font named FONTNAME as its default font, and
5008 return the full name of that font. FONTNAME may be a wildcard
5009 pattern; in that case, we choose some font that fits the pattern.
5010 The return value shows which font we chose. */
5011
5012 Lisp_Object
5013 x_new_font (f, fontname)
5014 struct frame *f;
5015 register char *fontname;
5016 {
5017 struct font_info *fontp
5018 = FS_LOAD_FONT (f, 0, fontname, -1);
5019
5020 if (!fontp)
5021 return Qnil;
5022
5023 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
5024 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
5025 FRAME_FONTSET (f) = -1;
5026
5027 FRAME_COLUMN_WIDTH (f) = fontp->average_width;
5028 FRAME_SPACE_WIDTH (f) = fontp->space_width;
5029 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
5030
5031 compute_fringe_widths (f, 1);
5032
5033 /* Compute the scroll bar width in character columns. */
5034 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
5035 {
5036 int wid = FRAME_COLUMN_WIDTH (f);
5037 FRAME_CONFIG_SCROLL_BAR_COLS (f)
5038 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
5039 }
5040 else
5041 {
5042 int wid = FRAME_COLUMN_WIDTH (f);
5043 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
5044 }
5045
5046 /* Now make the frame display the given font. */
5047 if (FRAME_MAC_WINDOW (f) != 0)
5048 {
5049 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
5050 FRAME_FONT (f));
5051 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
5052 FRAME_FONT (f));
5053 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
5054 FRAME_FONT (f));
5055
5056 /* Don't change the size of a tip frame; there's no point in
5057 doing it because it's done in Fx_show_tip, and it leads to
5058 problems because the tip frame has no widget. */
5059 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
5060 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
5061 }
5062
5063 return build_string (fontp->full_name);
5064 }
5065
5066 /* Give frame F the fontset named FONTSETNAME as its default font, and
5067 return the full name of that fontset. FONTSETNAME may be a wildcard
5068 pattern; in that case, we choose some fontset that fits the pattern.
5069 The return value shows which fontset we chose. */
5070
5071 Lisp_Object
5072 x_new_fontset (f, fontsetname)
5073 struct frame *f;
5074 char *fontsetname;
5075 {
5076 int fontset = fs_query_fontset (build_string (fontsetname), 0);
5077 Lisp_Object result;
5078
5079 if (fontset < 0)
5080 return Qnil;
5081
5082 if (FRAME_FONTSET (f) == fontset)
5083 /* This fontset is already set in frame F. There's nothing more
5084 to do. */
5085 return fontset_name (fontset);
5086
5087 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
5088
5089 if (!STRINGP (result))
5090 /* Can't load ASCII font. */
5091 return Qnil;
5092
5093 /* Since x_new_font doesn't update any fontset information, do it now. */
5094 FRAME_FONTSET(f) = fontset;
5095
5096 return build_string (fontsetname);
5097 }
5098
5099 \f
5100 /***********************************************************************
5101 TODO: W32 Input Methods
5102 ***********************************************************************/
5103 /* Listing missing functions from xterm.c helps diff stay in step.
5104
5105 xim_destroy_callback (xim, client_data, call_data)
5106 xim_open_dpy (dpyinfo, resource_name)
5107 struct xim_inst_t
5108 xim_instantiate_callback (display, client_data, call_data)
5109 xim_initialize (dpyinfo, resource_name)
5110 xim_close_dpy (dpyinfo)
5111
5112 */
5113
5114 \f
5115 void
5116 mac_get_window_bounds (f, inner, outer)
5117 struct frame *f;
5118 Rect *inner, *outer;
5119 {
5120 #if TARGET_API_MAC_CARBON
5121 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
5122 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
5123 #else /* not TARGET_API_MAC_CARBON */
5124 RgnHandle region = NewRgn ();
5125
5126 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
5127 *inner = (*region)->rgnBBox;
5128 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
5129 *outer = (*region)->rgnBBox;
5130 DisposeRgn (region);
5131 #endif /* not TARGET_API_MAC_CARBON */
5132 }
5133
5134
5135 /* Calculate the absolute position in frame F
5136 from its current recorded position values and gravity. */
5137
5138 void
5139 x_calc_absolute_position (f)
5140 struct frame *f;
5141 {
5142 int width_diff = 0, height_diff = 0;
5143 int flags = f->size_hint_flags;
5144 Rect inner, outer;
5145
5146 /* We have nothing to do if the current position
5147 is already for the top-left corner. */
5148 if (! ((flags & XNegative) || (flags & YNegative)))
5149 return;
5150
5151 /* Find the offsets of the outside upper-left corner of
5152 the inner window, with respect to the outer window. */
5153 mac_get_window_bounds (f, &inner, &outer);
5154
5155 width_diff = (outer.right - outer.left) - (inner.right - inner.left);
5156 height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
5157
5158 /* Treat negative positions as relative to the leftmost bottommost
5159 position that fits on the screen. */
5160 if (flags & XNegative)
5161 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
5162 - width_diff
5163 - FRAME_PIXEL_WIDTH (f)
5164 + f->left_pos);
5165
5166 if (flags & YNegative)
5167 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
5168 - height_diff
5169 - FRAME_PIXEL_HEIGHT (f)
5170 + f->top_pos);
5171
5172 /* The left_pos and top_pos
5173 are now relative to the top and left screen edges,
5174 so the flags should correspond. */
5175 f->size_hint_flags &= ~ (XNegative | YNegative);
5176 }
5177
5178 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5179 to really change the position, and 0 when calling from
5180 x_make_frame_visible (in that case, XOFF and YOFF are the current
5181 position values). It is -1 when calling from x_set_frame_parameters,
5182 which means, do adjust for borders but don't change the gravity. */
5183
5184 void
5185 x_set_offset (f, xoff, yoff, change_gravity)
5186 struct frame *f;
5187 register int xoff, yoff;
5188 int change_gravity;
5189 {
5190 if (change_gravity > 0)
5191 {
5192 f->top_pos = yoff;
5193 f->left_pos = xoff;
5194 f->size_hint_flags &= ~ (XNegative | YNegative);
5195 if (xoff < 0)
5196 f->size_hint_flags |= XNegative;
5197 if (yoff < 0)
5198 f->size_hint_flags |= YNegative;
5199 f->win_gravity = NorthWestGravity;
5200 }
5201 x_calc_absolute_position (f);
5202
5203 BLOCK_INPUT;
5204 x_wm_set_size_hint (f, (long) 0, 0);
5205
5206 #if TARGET_API_MAC_CARBON
5207 MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
5208 /* If the title bar is completely outside the screen, adjust the
5209 position. */
5210 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
5211 kWindowConstrainMoveRegardlessOfFit
5212 | kWindowConstrainAllowPartial, NULL, NULL);
5213 x_real_positions (f, &f->left_pos, &f->top_pos);
5214 #else
5215 {
5216 Rect inner, outer, screen_rect, dummy;
5217 RgnHandle region = NewRgn ();
5218
5219 mac_get_window_bounds (f, &inner, &outer);
5220 f->x_pixels_diff = inner.left - outer.left;
5221 f->y_pixels_diff = inner.top - outer.top;
5222 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5223 f->top_pos + f->y_pixels_diff, false);
5224
5225 /* If the title bar is completely outside the screen, adjust the
5226 position. The variable `outer' holds the title bar rectangle.
5227 The variable `inner' holds slightly smaller one than `outer',
5228 so that the calculation of overlapping may not become too
5229 strict. */
5230 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
5231 outer = (*region)->rgnBBox;
5232 DisposeRgn (region);
5233 inner = outer;
5234 InsetRect (&inner, 8, 8);
5235 screen_rect = qd.screenBits.bounds;
5236 screen_rect.top += GetMBarHeight ();
5237
5238 if (!SectRect (&inner, &screen_rect, &dummy))
5239 {
5240 if (inner.right <= screen_rect.left)
5241 f->left_pos = screen_rect.left;
5242 else if (inner.left >= screen_rect.right)
5243 f->left_pos = screen_rect.right - (outer.right - outer.left);
5244
5245 if (inner.bottom <= screen_rect.top)
5246 f->top_pos = screen_rect.top;
5247 else if (inner.top >= screen_rect.bottom)
5248 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
5249
5250 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5251 f->top_pos + f->y_pixels_diff, false);
5252 }
5253 }
5254 #endif
5255
5256 UNBLOCK_INPUT;
5257 }
5258
5259 /* Call this to change the size of frame F's x-window.
5260 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5261 for this size change and subsequent size changes.
5262 Otherwise we leave the window gravity unchanged. */
5263
5264 void
5265 x_set_window_size (f, change_gravity, cols, rows)
5266 struct frame *f;
5267 int change_gravity;
5268 int cols, rows;
5269 {
5270 int pixelwidth, pixelheight;
5271
5272 BLOCK_INPUT;
5273
5274 check_frame_size (f, &rows, &cols);
5275 f->scroll_bar_actual_width
5276 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
5277
5278 compute_fringe_widths (f, 0);
5279
5280 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5281 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
5282
5283 f->win_gravity = NorthWestGravity;
5284 x_wm_set_size_hint (f, (long) 0, 0);
5285
5286 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
5287
5288 /* Now, strictly speaking, we can't be sure that this is accurate,
5289 but the window manager will get around to dealing with the size
5290 change request eventually, and we'll hear how it went when the
5291 ConfigureNotify event gets here.
5292
5293 We could just not bother storing any of this information here,
5294 and let the ConfigureNotify event set everything up, but that
5295 might be kind of confusing to the Lisp code, since size changes
5296 wouldn't be reported in the frame parameters until some random
5297 point in the future when the ConfigureNotify event arrives.
5298
5299 We pass 1 for DELAY since we can't run Lisp code inside of
5300 a BLOCK_INPUT. */
5301 change_frame_size (f, rows, cols, 0, 1, 0);
5302 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5303 FRAME_PIXEL_HEIGHT (f) = pixelheight;
5304
5305 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5306 receive in the ConfigureNotify event; if we get what we asked
5307 for, then the event won't cause the screen to become garbaged, so
5308 we have to make sure to do it here. */
5309 SET_FRAME_GARBAGED (f);
5310
5311 XFlush (FRAME_X_DISPLAY (f));
5312
5313 /* If cursor was outside the new size, mark it as off. */
5314 mark_window_cursors_off (XWINDOW (f->root_window));
5315
5316 /* Clear out any recollection of where the mouse highlighting was,
5317 since it might be in a place that's outside the new frame size.
5318 Actually checking whether it is outside is a pain in the neck,
5319 so don't try--just let the highlighting be done afresh with new size. */
5320 cancel_mouse_face (f);
5321
5322 UNBLOCK_INPUT;
5323 }
5324 \f
5325 /* Mouse warping. */
5326
5327 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5328
5329 void
5330 x_set_mouse_position (f, x, y)
5331 struct frame *f;
5332 int x, y;
5333 {
5334 int pix_x, pix_y;
5335
5336 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5337 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
5338
5339 if (pix_x < 0) pix_x = 0;
5340 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
5341
5342 if (pix_y < 0) pix_y = 0;
5343 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
5344
5345 x_set_mouse_pixel_position (f, pix_x, pix_y);
5346 }
5347
5348 void
5349 x_set_mouse_pixel_position (f, pix_x, pix_y)
5350 struct frame *f;
5351 int pix_x, pix_y;
5352 {
5353 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5354 BLOCK_INPUT;
5355
5356 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5357 0, 0, 0, 0, pix_x, pix_y);
5358 UNBLOCK_INPUT;
5359 #endif
5360 }
5361
5362 \f
5363 /* focus shifting, raising and lowering. */
5364
5365 void
5366 x_focus_on_frame (f)
5367 struct frame *f;
5368 {
5369 #if 0 /* This proves to be unpleasant. */
5370 x_raise_frame (f);
5371 #endif
5372 #if 0
5373 /* I don't think that the ICCCM allows programs to do things like this
5374 without the interaction of the window manager. Whatever you end up
5375 doing with this code, do it to x_unfocus_frame too. */
5376 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5377 RevertToPointerRoot, CurrentTime);
5378 #endif /* ! 0 */
5379 }
5380
5381 void
5382 x_unfocus_frame (f)
5383 struct frame *f;
5384 {
5385 }
5386
5387 /* Raise frame F. */
5388 void
5389 x_raise_frame (f)
5390 struct frame *f;
5391 {
5392 if (f->async_visible)
5393 {
5394 BLOCK_INPUT;
5395 SelectWindow (FRAME_MAC_WINDOW (f));
5396 UNBLOCK_INPUT;
5397 }
5398 }
5399
5400 /* Lower frame F. */
5401 void
5402 x_lower_frame (f)
5403 struct frame *f;
5404 {
5405 if (f->async_visible)
5406 {
5407 BLOCK_INPUT;
5408 SendBehind (FRAME_MAC_WINDOW (f), nil);
5409 UNBLOCK_INPUT;
5410 }
5411 }
5412
5413 static void
5414 XTframe_raise_lower (f, raise_flag)
5415 FRAME_PTR f;
5416 int raise_flag;
5417 {
5418 if (raise_flag)
5419 x_raise_frame (f);
5420 else
5421 x_lower_frame (f);
5422 }
5423 \f
5424 /* Change of visibility. */
5425
5426 /* This tries to wait until the frame is really visible.
5427 However, if the window manager asks the user where to position
5428 the frame, this will return before the user finishes doing that.
5429 The frame will not actually be visible at that time,
5430 but it will become visible later when the window manager
5431 finishes with it. */
5432
5433 void
5434 x_make_frame_visible (f)
5435 struct frame *f;
5436 {
5437 Lisp_Object type;
5438 int original_top, original_left;
5439
5440 BLOCK_INPUT;
5441
5442 if (! FRAME_VISIBLE_P (f))
5443 {
5444 /* We test FRAME_GARBAGED_P here to make sure we don't
5445 call x_set_offset a second time
5446 if we get to x_make_frame_visible a second time
5447 before the window gets really visible. */
5448 if (! FRAME_ICONIFIED_P (f)
5449 && ! f->output_data.mac->asked_for_visible)
5450 x_set_offset (f, f->left_pos, f->top_pos, 0);
5451
5452 f->output_data.mac->asked_for_visible = 1;
5453
5454 #if TARGET_API_MAC_CARBON
5455 if (!(FRAME_SIZE_HINTS (f)->flags & (USPosition | PPosition)))
5456 {
5457 struct frame *sf = SELECTED_FRAME ();
5458 if (!FRAME_MAC_P (sf))
5459 RepositionWindow (FRAME_MAC_WINDOW (f), NULL,
5460 kWindowCenterOnMainScreen);
5461 else
5462 RepositionWindow (FRAME_MAC_WINDOW (f),
5463 FRAME_MAC_WINDOW (sf),
5464 #ifdef MAC_OS_X_VERSION_10_2
5465 kWindowCascadeStartAtParentWindowScreen
5466 #else
5467 kWindowCascadeOnParentWindowScreen
5468 #endif
5469 );
5470 x_real_positions (f, &f->left_pos, &f->top_pos);
5471 }
5472 #endif
5473 ShowWindow (FRAME_MAC_WINDOW (f));
5474 }
5475
5476 XFlush (FRAME_MAC_DISPLAY (f));
5477
5478 /* Synchronize to ensure Emacs knows the frame is visible
5479 before we do anything else. We do this loop with input not blocked
5480 so that incoming events are handled. */
5481 {
5482 Lisp_Object frame;
5483 int count;
5484
5485 /* This must come after we set COUNT. */
5486 UNBLOCK_INPUT;
5487
5488 XSETFRAME (frame, f);
5489
5490 /* Wait until the frame is visible. Process X events until a
5491 MapNotify event has been seen, or until we think we won't get a
5492 MapNotify at all.. */
5493 for (count = input_signal_count + 10;
5494 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5495 {
5496 /* Force processing of queued events. */
5497 x_sync (f);
5498
5499 /* Machines that do polling rather than SIGIO have been
5500 observed to go into a busy-wait here. So we'll fake an
5501 alarm signal to let the handler know that there's something
5502 to be read. We used to raise a real alarm, but it seems
5503 that the handler isn't always enabled here. This is
5504 probably a bug. */
5505 if (input_polling_used ())
5506 {
5507 /* It could be confusing if a real alarm arrives while
5508 processing the fake one. Turn it off and let the
5509 handler reset it. */
5510 extern void poll_for_input_1 P_ ((void));
5511 int old_poll_suppress_count = poll_suppress_count;
5512 poll_suppress_count = 1;
5513 poll_for_input_1 ();
5514 poll_suppress_count = old_poll_suppress_count;
5515 }
5516
5517 /* See if a MapNotify event has been processed. */
5518 FRAME_SAMPLE_VISIBILITY (f);
5519 }
5520 }
5521 }
5522
5523 /* Change from mapped state to withdrawn state. */
5524
5525 /* Make the frame visible (mapped and not iconified). */
5526
5527 void
5528 x_make_frame_invisible (f)
5529 struct frame *f;
5530 {
5531 /* Don't keep the highlight on an invisible frame. */
5532 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5533 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5534
5535 BLOCK_INPUT;
5536
5537 HideWindow (FRAME_MAC_WINDOW (f));
5538
5539 /* We can't distinguish this from iconification
5540 just by the event that we get from the server.
5541 So we can't win using the usual strategy of letting
5542 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5543 and synchronize with the server to make sure we agree. */
5544 f->visible = 0;
5545 FRAME_ICONIFIED_P (f) = 0;
5546 f->async_visible = 0;
5547 f->async_iconified = 0;
5548
5549 UNBLOCK_INPUT;
5550 }
5551
5552 /* Change window state from mapped to iconified. */
5553
5554 void
5555 x_iconify_frame (f)
5556 struct frame *f;
5557 {
5558 /* Don't keep the highlight on an invisible frame. */
5559 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5560 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5561
5562 #if 0
5563 /* Review: Since window is still visible in dock, still allow updates? */
5564 if (f->async_iconified)
5565 return;
5566 #endif
5567
5568 BLOCK_INPUT;
5569
5570 CollapseWindow (FRAME_MAC_WINDOW (f), true);
5571
5572 UNBLOCK_INPUT;
5573 }
5574
5575 \f
5576 /* Free X resources of frame F. */
5577
5578 void
5579 x_free_frame_resources (f)
5580 struct frame *f;
5581 {
5582 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5583 WindowPtr wp = FRAME_MAC_WINDOW (f);
5584
5585 BLOCK_INPUT;
5586
5587 DisposeWindow (wp);
5588 if (wp == tip_window)
5589 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5590 closed' event. So we reset tip_window here. */
5591 tip_window = NULL;
5592
5593 free_frame_menubar (f);
5594
5595 if (FRAME_FACE_CACHE (f))
5596 free_frame_faces (f);
5597
5598 x_free_gcs (f);
5599
5600 if (FRAME_SIZE_HINTS (f))
5601 xfree (FRAME_SIZE_HINTS (f));
5602
5603 xfree (f->output_data.mac);
5604 f->output_data.mac = NULL;
5605
5606 if (f == dpyinfo->x_focus_frame)
5607 dpyinfo->x_focus_frame = 0;
5608 if (f == dpyinfo->x_focus_event_frame)
5609 dpyinfo->x_focus_event_frame = 0;
5610 if (f == dpyinfo->x_highlight_frame)
5611 dpyinfo->x_highlight_frame = 0;
5612
5613 if (f == dpyinfo->mouse_face_mouse_frame)
5614 {
5615 dpyinfo->mouse_face_beg_row
5616 = dpyinfo->mouse_face_beg_col = -1;
5617 dpyinfo->mouse_face_end_row
5618 = dpyinfo->mouse_face_end_col = -1;
5619 dpyinfo->mouse_face_window = Qnil;
5620 dpyinfo->mouse_face_deferred_gc = 0;
5621 dpyinfo->mouse_face_mouse_frame = 0;
5622 }
5623
5624 UNBLOCK_INPUT;
5625 }
5626
5627
5628 /* Destroy the X window of frame F. */
5629
5630 void
5631 x_destroy_window (f)
5632 struct frame *f;
5633 {
5634 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5635
5636 x_free_frame_resources (f);
5637
5638 dpyinfo->reference_count--;
5639 }
5640
5641 \f
5642 /* Setting window manager hints. */
5643
5644 /* Set the normal size hints for the window manager, for frame F.
5645 FLAGS is the flags word to use--or 0 meaning preserve the flags
5646 that the window now has.
5647 If USER_POSITION is nonzero, we set the USPosition
5648 flag (this is useful when FLAGS is 0). */
5649 void
5650 x_wm_set_size_hint (f, flags, user_position)
5651 struct frame *f;
5652 long flags;
5653 int user_position;
5654 {
5655 int base_width, base_height, width_inc, height_inc;
5656 int min_rows = 0, min_cols = 0;
5657 XSizeHints *size_hints;
5658
5659 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
5660 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
5661 width_inc = FRAME_COLUMN_WIDTH (f);
5662 height_inc = FRAME_LINE_HEIGHT (f);
5663
5664 check_frame_size (f, &min_rows, &min_cols);
5665
5666 size_hints = FRAME_SIZE_HINTS (f);
5667 if (size_hints == NULL)
5668 {
5669 size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints));
5670 bzero (size_hints, sizeof (XSizeHints));
5671 }
5672
5673 size_hints->flags |= PResizeInc | PMinSize | PBaseSize ;
5674 size_hints->width_inc = width_inc;
5675 size_hints->height_inc = height_inc;
5676 size_hints->min_width = base_width + min_cols * width_inc;
5677 size_hints->min_height = base_height + min_rows * height_inc;
5678 size_hints->base_width = base_width;
5679 size_hints->base_height = base_height;
5680
5681 if (flags)
5682 size_hints->flags = flags;
5683 else if (user_position)
5684 {
5685 size_hints->flags &= ~ PPosition;
5686 size_hints->flags |= USPosition;
5687 }
5688 }
5689
5690 #if 0 /* MAC_TODO: hide application instead of iconify? */
5691 /* Used for IconicState or NormalState */
5692
5693 void
5694 x_wm_set_window_state (f, state)
5695 struct frame *f;
5696 int state;
5697 {
5698 #ifdef USE_X_TOOLKIT
5699 Arg al[1];
5700
5701 XtSetArg (al[0], XtNinitialState, state);
5702 XtSetValues (f->output_data.x->widget, al, 1);
5703 #else /* not USE_X_TOOLKIT */
5704 Window window = FRAME_X_WINDOW (f);
5705
5706 f->output_data.x->wm_hints.flags |= StateHint;
5707 f->output_data.x->wm_hints.initial_state = state;
5708
5709 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5710 #endif /* not USE_X_TOOLKIT */
5711 }
5712
5713 void
5714 x_wm_set_icon_pixmap (f, pixmap_id)
5715 struct frame *f;
5716 int pixmap_id;
5717 {
5718 Pixmap icon_pixmap;
5719
5720 #ifndef USE_X_TOOLKIT
5721 Window window = FRAME_X_WINDOW (f);
5722 #endif
5723
5724 if (pixmap_id > 0)
5725 {
5726 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
5727 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
5728 }
5729 else
5730 {
5731 /* It seems there is no way to turn off use of an icon pixmap.
5732 The following line does it, only if no icon has yet been created,
5733 for some window managers. But with mwm it crashes.
5734 Some people say it should clear the IconPixmapHint bit in this case,
5735 but that doesn't work, and the X consortium said it isn't the
5736 right thing at all. Since there is no way to win,
5737 best to explicitly give up. */
5738 #if 0
5739 f->output_data.x->wm_hints.icon_pixmap = None;
5740 #else
5741 return;
5742 #endif
5743 }
5744
5745 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
5746
5747 {
5748 Arg al[1];
5749 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
5750 XtSetValues (f->output_data.x->widget, al, 1);
5751 }
5752
5753 #else /* not USE_X_TOOLKIT */
5754
5755 f->output_data.x->wm_hints.flags |= IconPixmapHint;
5756 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5757
5758 #endif /* not USE_X_TOOLKIT */
5759 }
5760
5761 #endif /* MAC_TODO */
5762
5763 void
5764 x_wm_set_icon_position (f, icon_x, icon_y)
5765 struct frame *f;
5766 int icon_x, icon_y;
5767 {
5768 #if 0 /* MAC_TODO: no icons on Mac */
5769 #ifdef USE_X_TOOLKIT
5770 Window window = XtWindow (f->output_data.x->widget);
5771 #else
5772 Window window = FRAME_X_WINDOW (f);
5773 #endif
5774
5775 f->output_data.x->wm_hints.flags |= IconPositionHint;
5776 f->output_data.x->wm_hints.icon_x = icon_x;
5777 f->output_data.x->wm_hints.icon_y = icon_y;
5778
5779 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5780 #endif /* MAC_TODO */
5781 }
5782
5783 \f
5784 /***********************************************************************
5785 Fonts
5786 ***********************************************************************/
5787
5788 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
5789
5790 struct font_info *
5791 x_get_font_info (f, font_idx)
5792 FRAME_PTR f;
5793 int font_idx;
5794 {
5795 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
5796 }
5797
5798 /* the global font name table */
5799 char **font_name_table = NULL;
5800 int font_name_table_size = 0;
5801 int font_name_count = 0;
5802
5803 #if 0
5804 /* compare two strings ignoring case */
5805 static int
5806 stricmp (const char *s, const char *t)
5807 {
5808 for ( ; tolower (*s) == tolower (*t); s++, t++)
5809 if (*s == '\0')
5810 return 0;
5811 return tolower (*s) - tolower (*t);
5812 }
5813
5814 /* compare two strings ignoring case and handling wildcard */
5815 static int
5816 wildstrieq (char *s1, char *s2)
5817 {
5818 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
5819 return true;
5820
5821 return stricmp (s1, s2) == 0;
5822 }
5823
5824 /* Assume parameter 1 is fully qualified, no wildcards. */
5825 static int
5826 mac_font_pattern_match (fontname, pattern)
5827 char * fontname;
5828 char * pattern;
5829 {
5830 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
5831 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
5832 char *ptr;
5833
5834 /* Copy fontname so we can modify it during comparison. */
5835 strcpy (font_name_copy, fontname);
5836
5837 ptr = regex;
5838 *ptr++ = '^';
5839
5840 /* Turn pattern into a regexp and do a regexp match. */
5841 for (; *pattern; pattern++)
5842 {
5843 if (*pattern == '?')
5844 *ptr++ = '.';
5845 else if (*pattern == '*')
5846 {
5847 *ptr++ = '.';
5848 *ptr++ = '*';
5849 }
5850 else
5851 *ptr++ = *pattern;
5852 }
5853 *ptr = '$';
5854 *(ptr + 1) = '\0';
5855
5856 return (fast_c_string_match_ignore_case (build_string (regex),
5857 font_name_copy) >= 0);
5858 }
5859
5860 /* Two font specs are considered to match if their foundry, family,
5861 weight, slant, and charset match. */
5862 static int
5863 mac_font_match (char *mf, char *xf)
5864 {
5865 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
5866 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
5867
5868 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5869 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
5870 return mac_font_pattern_match (mf, xf);
5871
5872 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5873 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
5874 return mac_font_pattern_match (mf, xf);
5875
5876 return (wildstrieq (m_foundry, x_foundry)
5877 && wildstrieq (m_family, x_family)
5878 && wildstrieq (m_weight, x_weight)
5879 && wildstrieq (m_slant, x_slant)
5880 && wildstrieq (m_charset, x_charset))
5881 || mac_font_pattern_match (mf, xf);
5882 }
5883 #endif
5884
5885 static Lisp_Object Qbig5, Qcn_gb, Qsjis, Qeuc_kr;
5886
5887 static void
5888 decode_mac_font_name (name, size, scriptcode)
5889 char *name;
5890 int size;
5891 #if TARGET_API_MAC_CARBON
5892 int scriptcode;
5893 #else
5894 short scriptcode;
5895 #endif
5896 {
5897 Lisp_Object coding_system;
5898 struct coding_system coding;
5899 char *buf;
5900
5901 switch (scriptcode)
5902 {
5903 case smTradChinese:
5904 coding_system = Qbig5;
5905 break;
5906 case smSimpChinese:
5907 coding_system = Qcn_gb;
5908 break;
5909 case smJapanese:
5910 coding_system = Qsjis;
5911 break;
5912 case smKorean:
5913 coding_system = Qeuc_kr;
5914 break;
5915 default:
5916 return;
5917 }
5918
5919 setup_coding_system (coding_system, &coding);
5920 coding.src_multibyte = 0;
5921 coding.dst_multibyte = 1;
5922 coding.mode |= CODING_MODE_LAST_BLOCK;
5923 coding.composing = COMPOSITION_DISABLED;
5924 buf = (char *) alloca (size);
5925
5926 decode_coding (&coding, name, buf, strlen (name), size - 1);
5927 bcopy (buf, name, coding.produced);
5928 name[coding.produced] = '\0';
5929 }
5930
5931
5932 static char *
5933 mac_to_x_fontname (name, size, style, scriptcode)
5934 char *name;
5935 int size;
5936 Style style;
5937 #if TARGET_API_MAC_CARBON
5938 int scriptcode;
5939 #else
5940 short scriptcode;
5941 #endif
5942 {
5943 char foundry[32], family[32], cs[32];
5944 char xf[256], *result, *p;
5945
5946 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
5947 {
5948 strcpy(foundry, "Apple");
5949 strcpy(family, name);
5950
5951 switch (scriptcode)
5952 {
5953 case smTradChinese: /* == kTextEncodingMacChineseTrad */
5954 strcpy(cs, "big5-0");
5955 break;
5956 case smSimpChinese: /* == kTextEncodingMacChineseSimp */
5957 strcpy(cs, "gb2312.1980-0");
5958 break;
5959 case smJapanese: /* == kTextEncodingMacJapanese */
5960 strcpy(cs, "jisx0208.1983-sjis");
5961 break;
5962 case -smJapanese:
5963 /* Each Apple Japanese font is entered into the font table
5964 twice: once as a jisx0208.1983-sjis font and once as a
5965 jisx0201.1976-0 font. The latter can be used to display
5966 the ascii charset and katakana-jisx0201 charset. A
5967 negative script code signals that the name of this latter
5968 font is being built. */
5969 strcpy(cs, "jisx0201.1976-0");
5970 break;
5971 case smKorean: /* == kTextEncodingMacKorean */
5972 strcpy(cs, "ksc5601.1989-0");
5973 break;
5974 #if TARGET_API_MAC_CARBON
5975 case kTextEncodingMacCyrillic:
5976 strcpy(cs, "mac-cyrillic");
5977 break;
5978 case kTextEncodingMacCentralEurRoman:
5979 strcpy(cs, "mac-centraleurroman");
5980 break;
5981 case kTextEncodingMacSymbol:
5982 case kTextEncodingMacDingbats:
5983 strcpy(cs, "adobe-fontspecific");
5984 break;
5985 #endif
5986 default:
5987 strcpy(cs, "mac-roman");
5988 break;
5989 }
5990 }
5991
5992 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
5993 foundry, family, style & bold ? "bold" : "medium",
5994 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
5995
5996 result = (char *) xmalloc (strlen (xf) + 1);
5997 strcpy (result, xf);
5998 for (p = result; *p; p++)
5999 *p = tolower(*p);
6000 return result;
6001 }
6002
6003
6004 /* Convert an X font spec to the corresponding mac font name, which
6005 can then be passed to GetFNum after conversion to a Pascal string.
6006 For ordinary Mac fonts, this should just be their names, like
6007 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
6008 collection contain their charset designation in their names, like
6009 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
6010 names are handled accordingly. */
6011 static void
6012 x_font_name_to_mac_font_name (char *xf, char *mf)
6013 {
6014 char foundry[32], family[32], weight[20], slant[2], cs[32];
6015 Lisp_Object coding_system = Qnil;
6016 struct coding_system coding;
6017
6018 strcpy (mf, "");
6019
6020 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6021 foundry, family, weight, slant, cs) != 5 &&
6022 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6023 foundry, family, weight, slant, cs) != 5)
6024 return;
6025
6026 if (strcmp (cs, "big5-0") == 0)
6027 coding_system = Qbig5;
6028 else if (strcmp (cs, "gb2312.1980-0") == 0)
6029 coding_system = Qcn_gb;
6030 else if (strcmp (cs, "jisx0208.1983-sjis") == 0
6031 || strcmp (cs, "jisx0201.1976-0") == 0)
6032 coding_system = Qsjis;
6033 else if (strcmp (cs, "ksc5601.1989-0") == 0)
6034 coding_system = Qeuc_kr;
6035 else if (strcmp (cs, "mac-roman") == 0
6036 || strcmp (cs, "mac-cyrillic") == 0
6037 || strcmp (cs, "mac-centraleurroman") == 0
6038 || strcmp (cs, "adobe-fontspecific") == 0)
6039 strcpy (mf, family);
6040 else
6041 sprintf (mf, "%s-%s-%s", foundry, family, cs);
6042
6043 if (!NILP (coding_system))
6044 {
6045 setup_coding_system (coding_system, &coding);
6046 coding.src_multibyte = 1;
6047 coding.dst_multibyte = 1;
6048 coding.mode |= CODING_MODE_LAST_BLOCK;
6049 encode_coding (&coding, family, mf, strlen (family), sizeof (Str32) - 1);
6050 mf[coding.produced] = '\0';
6051 }
6052 }
6053
6054
6055 static void
6056 add_font_name_table_entry (char *font_name)
6057 {
6058 if (font_name_table_size == 0)
6059 {
6060 font_name_table_size = 16;
6061 font_name_table = (char **)
6062 xmalloc (font_name_table_size * sizeof (char *));
6063 }
6064 else if (font_name_count + 1 >= font_name_table_size)
6065 {
6066 font_name_table_size += 16;
6067 font_name_table = (char **)
6068 xrealloc (font_name_table,
6069 font_name_table_size * sizeof (char *));
6070 }
6071
6072 font_name_table[font_name_count++] = font_name;
6073 }
6074
6075 /* Sets up the table font_name_table to contain the list of all fonts
6076 in the system the first time the table is used so that the Resource
6077 Manager need not be accessed every time this information is
6078 needed. */
6079
6080 static void
6081 init_font_name_table ()
6082 {
6083 #if TARGET_API_MAC_CARBON
6084 SInt32 sv;
6085
6086 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
6087 {
6088 FMFontFamilyIterator ffi;
6089 FMFontFamilyInstanceIterator ffii;
6090 FMFontFamily ff;
6091
6092 /* Create a dummy instance iterator here to avoid creating and
6093 destroying it in the loop. */
6094 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
6095 return;
6096 /* Create an iterator to enumerate the font families. */
6097 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
6098 != noErr)
6099 {
6100 FMDisposeFontFamilyInstanceIterator (&ffii);
6101 return;
6102 }
6103
6104 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
6105 {
6106 Str255 name;
6107 FMFont font;
6108 FMFontStyle style;
6109 FMFontSize size;
6110 TextEncoding encoding;
6111 TextEncodingBase sc;
6112
6113 if (FMGetFontFamilyName (ff, name) != noErr)
6114 break;
6115 p2cstr (name);
6116 if (*name == '.')
6117 continue;
6118
6119 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr)
6120 break;
6121 sc = GetTextEncodingBase (encoding);
6122 decode_mac_font_name (name, sizeof (name), sc);
6123
6124 /* Point the instance iterator at the current font family. */
6125 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
6126 break;
6127
6128 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
6129 == noErr)
6130 {
6131 /* Both jisx0208.1983-sjis and jisx0201.1976-0 parts are
6132 contained in Apple Japanese (SJIS) font. */
6133 again:
6134 if (size == 0)
6135 {
6136 add_font_name_table_entry (mac_to_x_fontname (name, size,
6137 style, sc));
6138 add_font_name_table_entry (mac_to_x_fontname (name, size,
6139 italic, sc));
6140 add_font_name_table_entry (mac_to_x_fontname (name, size,
6141 bold, sc));
6142 add_font_name_table_entry (mac_to_x_fontname (name, size,
6143 italic | bold,
6144 sc));
6145 }
6146 else
6147 add_font_name_table_entry (mac_to_x_fontname (name, size,
6148 style, sc));
6149 if (sc == smJapanese)
6150 {
6151 sc = -smJapanese;
6152 goto again;
6153 }
6154 else if (sc == -smJapanese)
6155 sc = smJapanese;
6156 }
6157 }
6158
6159 /* Dispose of the iterators. */
6160 FMDisposeFontFamilyIterator (&ffi);
6161 FMDisposeFontFamilyInstanceIterator (&ffii);
6162 }
6163 else
6164 {
6165 #endif /* TARGET_API_MAC_CARBON */
6166 GrafPtr port;
6167 SInt16 fontnum, old_fontnum;
6168 int num_mac_fonts = CountResources('FOND');
6169 int i, j;
6170 Handle font_handle, font_handle_2;
6171 short id, scriptcode;
6172 ResType type;
6173 Str32 name;
6174 struct FontAssoc *fat;
6175 struct AsscEntry *assc_entry;
6176
6177 GetPort (&port); /* save the current font number used */
6178 #if TARGET_API_MAC_CARBON
6179 old_fontnum = GetPortTextFont (port);
6180 #else
6181 old_fontnum = port->txFont;
6182 #endif
6183
6184 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
6185 {
6186 font_handle = GetIndResource ('FOND', i);
6187 if (!font_handle)
6188 continue;
6189
6190 GetResInfo (font_handle, &id, &type, name);
6191 GetFNum (name, &fontnum);
6192 p2cstr (name);
6193 if (fontnum == 0)
6194 continue;
6195
6196 TextFont (fontnum);
6197 scriptcode = FontToScript (fontnum);
6198 decode_mac_font_name (name, sizeof (name), scriptcode);
6199 do
6200 {
6201 HLock (font_handle);
6202
6203 if (GetResourceSizeOnDisk (font_handle)
6204 >= sizeof (struct FamRec))
6205 {
6206 fat = (struct FontAssoc *) (*font_handle
6207 + sizeof (struct FamRec));
6208 assc_entry
6209 = (struct AsscEntry *) (*font_handle
6210 + sizeof (struct FamRec)
6211 + sizeof (struct FontAssoc));
6212
6213 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
6214 {
6215 if (font_name_table_size == 0)
6216 {
6217 font_name_table_size = 16;
6218 font_name_table = (char **)
6219 xmalloc (font_name_table_size * sizeof (char *));
6220 }
6221 else if (font_name_count >= font_name_table_size)
6222 {
6223 font_name_table_size += 16;
6224 font_name_table = (char **)
6225 xrealloc (font_name_table,
6226 font_name_table_size * sizeof (char *));
6227 }
6228 font_name_table[font_name_count++]
6229 = mac_to_x_fontname (name,
6230 assc_entry->fontSize,
6231 assc_entry->fontStyle,
6232 scriptcode);
6233 /* Both jisx0208.1983-sjis and jisx0201.1976-0
6234 parts are contained in Apple Japanese (SJIS)
6235 font. */
6236 if (smJapanese == scriptcode)
6237 {
6238 font_name_table[font_name_count++]
6239 = mac_to_x_fontname (name,
6240 assc_entry->fontSize,
6241 assc_entry->fontStyle,
6242 -smJapanese);
6243 }
6244 }
6245 }
6246
6247 HUnlock (font_handle);
6248 font_handle_2 = GetNextFOND (font_handle);
6249 ReleaseResource (font_handle);
6250 font_handle = font_handle_2;
6251 }
6252 while (ResError () == noErr && font_handle);
6253 }
6254
6255 TextFont (old_fontnum);
6256 #if TARGET_API_MAC_CARBON
6257 }
6258 #endif /* TARGET_API_MAC_CARBON */
6259 }
6260
6261
6262 void
6263 mac_clear_font_name_table ()
6264 {
6265 int i;
6266
6267 for (i = 0; i < font_name_count; i++)
6268 xfree (font_name_table[i]);
6269 xfree (font_name_table);
6270 font_name_table = NULL;
6271 font_name_table_size = font_name_count = 0;
6272 }
6273
6274
6275 enum xlfd_scalable_field_index
6276 {
6277 XLFD_SCL_PIXEL_SIZE,
6278 XLFD_SCL_POINT_SIZE,
6279 XLFD_SCL_AVGWIDTH,
6280 XLFD_SCL_LAST
6281 };
6282
6283 static int xlfd_scalable_fields[] =
6284 {
6285 6, /* PIXEL_SIZE */
6286 7, /* POINT_SIZE */
6287 11, /* AVGWIDTH */
6288 -1
6289 };
6290
6291 static Lisp_Object
6292 mac_c_string_match (regexp, string, nonspecial, exact)
6293 Lisp_Object regexp;
6294 const char *string, *nonspecial;
6295 int exact;
6296 {
6297 if (exact)
6298 {
6299 if (strcmp (string, nonspecial) == 0)
6300 return build_string (string);
6301 }
6302 else if (strstr (string, nonspecial))
6303 {
6304 Lisp_Object str = build_string (string);
6305
6306 if (fast_string_match (regexp, str) >= 0)
6307 return str;
6308 }
6309
6310 return Qnil;
6311 }
6312
6313 static Lisp_Object
6314 mac_do_list_fonts (pattern, maxnames)
6315 char *pattern;
6316 int maxnames;
6317 {
6318 int i, n_fonts = 0;
6319 Lisp_Object font_list = Qnil, pattern_regex, fontname;
6320 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
6321 char scaled[256];
6322 char *ptr;
6323 int scl_val[XLFD_SCL_LAST], *field, *val;
6324 char *longest_start, *cur_start, *nonspecial;
6325 int longest_len, exact;
6326
6327 if (font_name_table == NULL) /* Initialize when first used. */
6328 init_font_name_table ();
6329
6330 for (i = 0; i < XLFD_SCL_LAST; i++)
6331 scl_val[i] = -1;
6332
6333 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
6334 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
6335 fonts are scaled according to the specified size. */
6336 ptr = pattern;
6337 i = 0;
6338 field = xlfd_scalable_fields;
6339 val = scl_val;
6340 if (*ptr == '-')
6341 do
6342 {
6343 ptr++;
6344 if (i == *field)
6345 {
6346 if ('1' <= *ptr && *ptr <= '9')
6347 {
6348 *val = *ptr++ - '0';
6349 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
6350 *val = *val * 10 + *ptr++ - '0';
6351 if (*ptr != '-')
6352 *val = -1;
6353 }
6354 field++;
6355 val++;
6356 }
6357 ptr = strchr (ptr, '-');
6358 i++;
6359 }
6360 while (ptr && i < 14);
6361
6362 if (i == 14 && ptr == NULL)
6363 {
6364 if (scl_val[XLFD_SCL_POINT_SIZE] > 0)
6365 {
6366 scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_POINT_SIZE] / 10;
6367 scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_POINT_SIZE];
6368 }
6369 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0)
6370 {
6371 scl_val[XLFD_SCL_POINT_SIZE] =
6372 scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_PIXEL_SIZE] * 10;
6373 }
6374 else if (scl_val[XLFD_SCL_AVGWIDTH] > 0)
6375 {
6376 scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_AVGWIDTH] / 10;
6377 scl_val[XLFD_SCL_POINT_SIZE] = scl_val[XLFD_SCL_AVGWIDTH];
6378 }
6379 }
6380 else
6381 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
6382
6383 ptr = regex;
6384 *ptr++ = '^';
6385
6386 longest_start = cur_start = ptr;
6387 longest_len = 0;
6388 exact = 1;
6389
6390 /* Turn pattern into a regexp and do a regexp match. Also find the
6391 longest substring containing no special characters. */
6392 for (; *pattern; pattern++)
6393 {
6394 if (*pattern == '?' || *pattern == '*')
6395 {
6396 if (ptr - cur_start > longest_len)
6397 {
6398 longest_start = cur_start;
6399 longest_len = ptr - cur_start;
6400 }
6401 exact = 0;
6402
6403 if (*pattern == '?')
6404 *ptr++ = '.';
6405 else /* if (*pattern == '*') */
6406 {
6407 *ptr++ = '.';
6408 *ptr++ = '*';
6409 }
6410 cur_start = ptr;
6411 }
6412 else
6413 *ptr++ = tolower (*pattern);
6414 }
6415
6416 if (ptr - cur_start > longest_len)
6417 {
6418 longest_start = cur_start;
6419 longest_len = ptr - cur_start;
6420 }
6421
6422 *ptr = '$';
6423 *(ptr + 1) = '\0';
6424
6425 nonspecial = xmalloc (longest_len + 1);
6426 strncpy (nonspecial, longest_start, longest_len);
6427 nonspecial[longest_len] = '\0';
6428
6429 pattern_regex = build_string (regex);
6430
6431 for (i = 0; i < font_name_count; i++)
6432 {
6433 fontname = mac_c_string_match (pattern_regex, font_name_table[i],
6434 nonspecial, exact);
6435 if (!NILP (fontname))
6436 {
6437 font_list = Fcons (fontname, font_list);
6438 if (exact || maxnames > 0 && ++n_fonts >= maxnames)
6439 break;
6440 }
6441 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
6442 && (ptr = strstr (font_name_table[i], "-0-0-75-75-m-0-")))
6443 {
6444 int former_len = ptr - font_name_table[i];
6445
6446 memcpy (scaled, font_name_table[i], former_len);
6447 sprintf (scaled + former_len,
6448 "-%d-%d-75-75-m-%d-%s",
6449 scl_val[XLFD_SCL_PIXEL_SIZE],
6450 scl_val[XLFD_SCL_POINT_SIZE],
6451 scl_val[XLFD_SCL_AVGWIDTH],
6452 ptr + sizeof ("-0-0-75-75-m-0-") - 1);
6453 fontname = mac_c_string_match (pattern_regex, scaled,
6454 nonspecial, exact);
6455 if (!NILP (fontname))
6456 {
6457 font_list = Fcons (fontname, font_list);
6458 if (exact || maxnames > 0 && ++n_fonts >= maxnames)
6459 break;
6460 }
6461 }
6462 }
6463
6464 xfree (nonspecial);
6465
6466 return font_list;
6467 }
6468
6469 /* Return a list of at most MAXNAMES font specs matching the one in
6470 PATTERN. Cache matching fonts for patterns in
6471 dpyinfo->name_list_element to avoid looking them up again by
6472 calling mac_font_pattern_match (slow). Return as many matching
6473 fonts as possible if MAXNAMES = -1. */
6474
6475 Lisp_Object
6476 x_list_fonts (struct frame *f,
6477 Lisp_Object pattern,
6478 int size,
6479 int maxnames)
6480 {
6481 Lisp_Object newlist = Qnil, tem, key;
6482 struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
6483
6484 if (dpyinfo)
6485 {
6486 tem = XCDR (dpyinfo->name_list_element);
6487 key = Fcons (pattern, make_number (maxnames));
6488
6489 newlist = Fassoc (key, tem);
6490 if (!NILP (newlist))
6491 {
6492 newlist = Fcdr_safe (newlist);
6493 goto label_cached;
6494 }
6495 }
6496
6497 BLOCK_INPUT;
6498 newlist = mac_do_list_fonts (SDATA (pattern), maxnames);
6499 UNBLOCK_INPUT;
6500
6501 /* MAC_TODO: add code for matching outline fonts here */
6502
6503 if (dpyinfo)
6504 {
6505 XSETCDR (dpyinfo->name_list_element,
6506 Fcons (Fcons (key, newlist),
6507 XCDR (dpyinfo->name_list_element)));
6508 }
6509 label_cached:
6510
6511 return newlist;
6512 }
6513
6514
6515 #if GLYPH_DEBUG
6516
6517 /* Check that FONT is valid on frame F. It is if it can be found in F's
6518 font table. */
6519
6520 static void
6521 x_check_font (f, font)
6522 struct frame *f;
6523 XFontStruct *font;
6524 {
6525 int i;
6526 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6527
6528 xassert (font != NULL);
6529
6530 for (i = 0; i < dpyinfo->n_fonts; i++)
6531 if (dpyinfo->font_table[i].name
6532 && font == dpyinfo->font_table[i].font)
6533 break;
6534
6535 xassert (i < dpyinfo->n_fonts);
6536 }
6537
6538 #endif /* GLYPH_DEBUG != 0 */
6539
6540 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6541 Note: There are (broken) X fonts out there with invalid XFontStruct
6542 min_bounds contents. For example, handa@etl.go.jp reports that
6543 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6544 have font->min_bounds.width == 0. */
6545
6546 static INLINE void
6547 x_font_min_bounds (font, w, h)
6548 MacFontStruct *font;
6549 int *w, *h;
6550 {
6551 *h = FONT_HEIGHT (font);
6552 *w = font->min_bounds.width;
6553 }
6554
6555
6556 /* Compute the smallest character width and smallest font height over
6557 all fonts available on frame F. Set the members smallest_char_width
6558 and smallest_font_height in F's x_display_info structure to
6559 the values computed. Value is non-zero if smallest_font_height or
6560 smallest_char_width become smaller than they were before. */
6561
6562 int
6563 x_compute_min_glyph_bounds (f)
6564 struct frame *f;
6565 {
6566 int i;
6567 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6568 MacFontStruct *font;
6569 int old_width = dpyinfo->smallest_char_width;
6570 int old_height = dpyinfo->smallest_font_height;
6571
6572 dpyinfo->smallest_font_height = 100000;
6573 dpyinfo->smallest_char_width = 100000;
6574
6575 for (i = 0; i < dpyinfo->n_fonts; ++i)
6576 if (dpyinfo->font_table[i].name)
6577 {
6578 struct font_info *fontp = dpyinfo->font_table + i;
6579 int w, h;
6580
6581 font = (MacFontStruct *) fontp->font;
6582 xassert (font != (MacFontStruct *) ~0);
6583 x_font_min_bounds (font, &w, &h);
6584
6585 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
6586 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
6587 }
6588
6589 xassert (dpyinfo->smallest_char_width > 0
6590 && dpyinfo->smallest_font_height > 0);
6591
6592 return (dpyinfo->n_fonts == 1
6593 || dpyinfo->smallest_char_width < old_width
6594 || dpyinfo->smallest_font_height < old_height);
6595 }
6596
6597
6598 /* Determine whether given string is a fully-specified XLFD: all 14
6599 fields are present, none is '*'. */
6600
6601 static int
6602 is_fully_specified_xlfd (char *p)
6603 {
6604 int i;
6605 char *q;
6606
6607 if (*p != '-')
6608 return 0;
6609
6610 for (i = 0; i < 13; i++)
6611 {
6612 q = strchr (p + 1, '-');
6613 if (q == NULL)
6614 return 0;
6615 if (q - p == 2 && *(p + 1) == '*')
6616 return 0;
6617 p = q;
6618 }
6619
6620 if (strchr (p + 1, '-') != NULL)
6621 return 0;
6622
6623 if (*(p + 1) == '*' && *(p + 2) == '\0')
6624 return 0;
6625
6626 return 1;
6627 }
6628
6629
6630 const int kDefaultFontSize = 9;
6631
6632
6633 /* XLoadQueryFont creates and returns an internal representation for a
6634 font in a MacFontStruct struct. There is really no concept
6635 corresponding to "loading" a font on the Mac. But we check its
6636 existence and find the font number and all other information for it
6637 and store them in the returned MacFontStruct. */
6638
6639 static MacFontStruct *
6640 XLoadQueryFont (Display *dpy, char *fontname)
6641 {
6642 int i, size, is_two_byte_font, char_width;
6643 char *name;
6644 GrafPtr port;
6645 SInt16 old_fontnum, old_fontsize;
6646 Style old_fontface;
6647 Str32 mfontname;
6648 SInt16 fontnum;
6649 Style fontface = normal;
6650 MacFontStruct *font;
6651 FontInfo the_fontinfo;
6652 char s_weight[7], c_slant;
6653
6654 if (is_fully_specified_xlfd (fontname))
6655 name = fontname;
6656 else
6657 {
6658 Lisp_Object matched_fonts;
6659
6660 matched_fonts = mac_do_list_fonts (fontname, 1);
6661 if (NILP (matched_fonts))
6662 return NULL;
6663 name = SDATA (XCAR (matched_fonts));
6664 }
6665
6666 GetPort (&port); /* save the current font number used */
6667 #if TARGET_API_MAC_CARBON
6668 old_fontnum = GetPortTextFont (port);
6669 old_fontsize = GetPortTextSize (port);
6670 old_fontface = GetPortTextFace (port);
6671 #else
6672 old_fontnum = port->txFont;
6673 old_fontsize = port->txSize;
6674 old_fontface = port->txFace;
6675 #endif
6676
6677 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
6678 size = kDefaultFontSize;
6679
6680 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
6681 if (strcmp (s_weight, "bold") == 0)
6682 fontface |= bold;
6683
6684 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
6685 if (c_slant == 'i')
6686 fontface |= italic;
6687
6688 x_font_name_to_mac_font_name (name, mfontname);
6689 c2pstr (mfontname);
6690 GetFNum (mfontname, &fontnum);
6691 if (fontnum == 0)
6692 return NULL;
6693
6694 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
6695
6696 font->fontname = (char *) xmalloc (strlen (name) + 1);
6697 bcopy (name, font->fontname, strlen (name) + 1);
6698
6699 font->mac_fontnum = fontnum;
6700 font->mac_fontsize = size;
6701 font->mac_fontface = fontface;
6702 font->mac_scriptcode = FontToScript (fontnum);
6703
6704 /* Apple Japanese (SJIS) font is listed as both
6705 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
6706 (Roman script) in init_font_name_table (). The latter should be
6707 treated as a one-byte font. */
6708 {
6709 char cs[32];
6710
6711 if (sscanf (name,
6712 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6713 cs) == 1
6714 && 0 == strcmp (cs, "jisx0201.1976-0"))
6715 font->mac_scriptcode = smRoman;
6716 }
6717
6718 is_two_byte_font = font->mac_scriptcode == smJapanese ||
6719 font->mac_scriptcode == smTradChinese ||
6720 font->mac_scriptcode == smSimpChinese ||
6721 font->mac_scriptcode == smKorean;
6722
6723 TextFont (fontnum);
6724 TextSize (size);
6725 TextFace (fontface);
6726
6727 GetFontInfo (&the_fontinfo);
6728
6729 font->ascent = the_fontinfo.ascent;
6730 font->descent = the_fontinfo.descent;
6731
6732 font->min_byte1 = 0;
6733 if (is_two_byte_font)
6734 font->max_byte1 = 1;
6735 else
6736 font->max_byte1 = 0;
6737 font->min_char_or_byte2 = 0x20;
6738 font->max_char_or_byte2 = 0xff;
6739
6740 if (is_two_byte_font)
6741 {
6742 /* Use the width of an "ideographic space" of that font because
6743 the_fontinfo.widMax returns the wrong width for some fonts. */
6744 switch (font->mac_scriptcode)
6745 {
6746 case smJapanese:
6747 char_width = StringWidth("\p\x81\x40");
6748 break;
6749 case smTradChinese:
6750 char_width = StringWidth("\p\xa1\x40");
6751 break;
6752 case smSimpChinese:
6753 char_width = StringWidth("\p\xa1\xa1");
6754 break;
6755 case smKorean:
6756 char_width = StringWidth("\p\xa1\xa1");
6757 break;
6758 }
6759 }
6760 else
6761 /* Do this instead of use the_fontinfo.widMax, which incorrectly
6762 returns 15 for 12-point Monaco! */
6763 char_width = CharWidth ('m');
6764
6765 font->max_bounds.rbearing = char_width;
6766 font->max_bounds.lbearing = 0;
6767 font->max_bounds.width = char_width;
6768 font->max_bounds.ascent = the_fontinfo.ascent;
6769 font->max_bounds.descent = the_fontinfo.descent;
6770
6771 font->min_bounds = font->max_bounds;
6772
6773 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
6774 font->per_char = NULL;
6775 else
6776 {
6777 font->per_char = (XCharStruct *)
6778 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
6779 {
6780 int c, min_width, max_width;
6781
6782 min_width = max_width = char_width;
6783 for (c = 0x20; c <= 0xff; c++)
6784 {
6785 font->per_char[c - 0x20] = font->max_bounds;
6786 char_width = CharWidth (c);
6787 font->per_char[c - 0x20].width = char_width;
6788 font->per_char[c - 0x20].rbearing = char_width;
6789 /* Some Japanese fonts (in SJIS encoding) return 0 as the
6790 character width of 0x7f. */
6791 if (char_width > 0)
6792 {
6793 min_width = min (min_width, char_width);
6794 max_width = max (max_width, char_width);
6795 }
6796 }
6797 font->min_bounds.width = min_width;
6798 font->max_bounds.width = max_width;
6799 }
6800 }
6801
6802 TextFont (old_fontnum); /* restore previous font number, size and face */
6803 TextSize (old_fontsize);
6804 TextFace (old_fontface);
6805
6806 return font;
6807 }
6808
6809
6810 void
6811 mac_unload_font (dpyinfo, font)
6812 struct mac_display_info *dpyinfo;
6813 XFontStruct *font;
6814 {
6815 xfree (font->fontname);
6816 if (font->per_char)
6817 xfree (font->per_char);
6818 xfree (font);
6819 }
6820
6821
6822 /* Load font named FONTNAME of the size SIZE for frame F, and return a
6823 pointer to the structure font_info while allocating it dynamically.
6824 If SIZE is 0, load any size of font.
6825 If loading is failed, return NULL. */
6826
6827 struct font_info *
6828 x_load_font (f, fontname, size)
6829 struct frame *f;
6830 register char *fontname;
6831 int size;
6832 {
6833 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6834 Lisp_Object font_names;
6835
6836 /* Get a list of all the fonts that match this name. Once we
6837 have a list of matching fonts, we compare them against the fonts
6838 we already have by comparing names. */
6839 font_names = x_list_fonts (f, build_string (fontname), size, 1);
6840
6841 if (!NILP (font_names))
6842 {
6843 Lisp_Object tail;
6844 int i;
6845
6846 for (i = 0; i < dpyinfo->n_fonts; i++)
6847 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
6848 if (dpyinfo->font_table[i].name
6849 && (!strcmp (dpyinfo->font_table[i].name,
6850 SDATA (XCAR (tail)))
6851 || !strcmp (dpyinfo->font_table[i].full_name,
6852 SDATA (XCAR (tail)))))
6853 return (dpyinfo->font_table + i);
6854 }
6855
6856 /* Load the font and add it to the table. */
6857 {
6858 char *full_name;
6859 struct MacFontStruct *font;
6860 struct font_info *fontp;
6861 unsigned long value;
6862 int i;
6863
6864 /* If we have found fonts by x_list_font, load one of them. If
6865 not, we still try to load a font by the name given as FONTNAME
6866 because XListFonts (called in x_list_font) of some X server has
6867 a bug of not finding a font even if the font surely exists and
6868 is loadable by XLoadQueryFont. */
6869 if (size > 0 && !NILP (font_names))
6870 fontname = (char *) SDATA (XCAR (font_names));
6871
6872 BLOCK_INPUT;
6873 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
6874 UNBLOCK_INPUT;
6875 if (!font)
6876 return NULL;
6877
6878 /* Find a free slot in the font table. */
6879 for (i = 0; i < dpyinfo->n_fonts; ++i)
6880 if (dpyinfo->font_table[i].name == NULL)
6881 break;
6882
6883 /* If no free slot found, maybe enlarge the font table. */
6884 if (i == dpyinfo->n_fonts
6885 && dpyinfo->n_fonts == dpyinfo->font_table_size)
6886 {
6887 int sz;
6888 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
6889 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
6890 dpyinfo->font_table
6891 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
6892 }
6893
6894 fontp = dpyinfo->font_table + i;
6895 if (i == dpyinfo->n_fonts)
6896 ++dpyinfo->n_fonts;
6897
6898 /* Now fill in the slots of *FONTP. */
6899 BLOCK_INPUT;
6900 bzero (fontp, sizeof (*fontp));
6901 fontp->font = font;
6902 fontp->font_idx = i;
6903 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
6904 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
6905
6906 if (font->min_bounds.width == font->max_bounds.width)
6907 {
6908 /* Fixed width font. */
6909 fontp->average_width = fontp->space_width = font->min_bounds.width;
6910 }
6911 else
6912 {
6913 XChar2b char2b;
6914 XCharStruct *pcm;
6915
6916 char2b.byte1 = 0x00, char2b.byte2 = 0x20;
6917 pcm = mac_per_char_metric (font, &char2b, 0);
6918 if (pcm)
6919 fontp->space_width = pcm->width;
6920 else
6921 fontp->space_width = FONT_WIDTH (font);
6922
6923 if (pcm)
6924 {
6925 int width = pcm->width;
6926 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++)
6927 if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL)
6928 width += pcm->width;
6929 fontp->average_width = width / 95;
6930 }
6931 else
6932 fontp->average_width = FONT_WIDTH (font);
6933 }
6934
6935 fontp->full_name = fontp->name;
6936
6937 fontp->size = font->max_bounds.width;
6938 fontp->height = FONT_HEIGHT (font);
6939 {
6940 /* For some font, ascent and descent in max_bounds field is
6941 larger than the above value. */
6942 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
6943 if (max_height > fontp->height)
6944 fontp->height = max_height;
6945 }
6946
6947 /* The slot `encoding' specifies how to map a character
6948 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6949 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
6950 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
6951 2:0xA020..0xFF7F). For the moment, we don't know which charset
6952 uses this font. So, we set information in fontp->encoding[1]
6953 which is never used by any charset. If mapping can't be
6954 decided, set FONT_ENCODING_NOT_DECIDED. */
6955 if (font->mac_scriptcode == smJapanese)
6956 fontp->encoding[1] = 4;
6957 else
6958 {
6959 fontp->encoding[1]
6960 = (font->max_byte1 == 0
6961 /* 1-byte font */
6962 ? (font->min_char_or_byte2 < 0x80
6963 ? (font->max_char_or_byte2 < 0x80
6964 ? 0 /* 0x20..0x7F */
6965 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
6966 : 1) /* 0xA0..0xFF */
6967 /* 2-byte font */
6968 : (font->min_byte1 < 0x80
6969 ? (font->max_byte1 < 0x80
6970 ? (font->min_char_or_byte2 < 0x80
6971 ? (font->max_char_or_byte2 < 0x80
6972 ? 0 /* 0x2020..0x7F7F */
6973 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
6974 : 3) /* 0x20A0..0x7FFF */
6975 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
6976 : (font->min_char_or_byte2 < 0x80
6977 ? (font->max_char_or_byte2 < 0x80
6978 ? 2 /* 0xA020..0xFF7F */
6979 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
6980 : 1))); /* 0xA0A0..0xFFFF */
6981 }
6982
6983 #if 0 /* MAC_TODO: fill these out with more reasonably values */
6984 fontp->baseline_offset
6985 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
6986 ? (long) value : 0);
6987 fontp->relative_compose
6988 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
6989 ? (long) value : 0);
6990 fontp->default_ascent
6991 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
6992 ? (long) value : 0);
6993 #else
6994 fontp->baseline_offset = 0;
6995 fontp->relative_compose = 0;
6996 fontp->default_ascent = 0;
6997 #endif
6998
6999 /* Set global flag fonts_changed_p to non-zero if the font loaded
7000 has a character with a smaller width than any other character
7001 before, or if the font loaded has a smalle>r height than any
7002 other font loaded before. If this happens, it will make a
7003 glyph matrix reallocation necessary. */
7004 fonts_changed_p = x_compute_min_glyph_bounds (f);
7005 UNBLOCK_INPUT;
7006 return fontp;
7007 }
7008 }
7009
7010
7011 /* Return a pointer to struct font_info of a font named FONTNAME for
7012 frame F. If no such font is loaded, return NULL. */
7013
7014 struct font_info *
7015 x_query_font (f, fontname)
7016 struct frame *f;
7017 register char *fontname;
7018 {
7019 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
7020 int i;
7021
7022 for (i = 0; i < dpyinfo->n_fonts; i++)
7023 if (dpyinfo->font_table[i].name
7024 && (!strcmp (dpyinfo->font_table[i].name, fontname)
7025 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
7026 return (dpyinfo->font_table + i);
7027 return NULL;
7028 }
7029
7030
7031 /* Find a CCL program for a font specified by FONTP, and set the member
7032 `encoder' of the structure. */
7033
7034 void
7035 x_find_ccl_program (fontp)
7036 struct font_info *fontp;
7037 {
7038 Lisp_Object list, elt;
7039
7040 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
7041 {
7042 elt = XCAR (list);
7043 if (CONSP (elt)
7044 && STRINGP (XCAR (elt))
7045 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
7046 >= 0))
7047 break;
7048 }
7049 if (! NILP (list))
7050 {
7051 struct ccl_program *ccl
7052 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
7053
7054 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
7055 xfree (ccl);
7056 else
7057 fontp->font_encoder = ccl;
7058 }
7059 }
7060
7061
7062 \f
7063 /* The Mac Event loop code */
7064
7065 #ifndef MAC_OSX
7066 #include <Events.h>
7067 #include <Quickdraw.h>
7068 #include <Balloons.h>
7069 #include <Devices.h>
7070 #include <Fonts.h>
7071 #include <Gestalt.h>
7072 #include <Menus.h>
7073 #include <Processes.h>
7074 #include <Sound.h>
7075 #include <ToolUtils.h>
7076 #include <TextUtils.h>
7077 #include <Dialogs.h>
7078 #include <Script.h>
7079 #include <Types.h>
7080 #include <TextEncodingConverter.h>
7081 #include <Resources.h>
7082
7083 #if __MWERKS__
7084 #include <unix.h>
7085 #endif
7086 #endif /* ! MAC_OSX */
7087
7088 #define M_APPLE 128
7089 #define I_ABOUT 1
7090
7091 #define WINDOW_RESOURCE 128
7092 #define TERM_WINDOW_RESOURCE 129
7093
7094 #define DEFAULT_NUM_COLS 80
7095
7096 #define MIN_DOC_SIZE 64
7097 #define MAX_DOC_SIZE 32767
7098
7099 /* sleep time for WaitNextEvent */
7100 #define WNE_SLEEP_AT_SUSPEND 10
7101 #define WNE_SLEEP_AT_RESUME 1
7102
7103 /* true when cannot handle any Mac OS events */
7104 static int handling_window_update = 0;
7105
7106 #if 0
7107 /* the flag appl_is_suspended is used both for determining the sleep
7108 time to be passed to WaitNextEvent and whether the cursor should be
7109 drawn when updating the display. The cursor is turned off when
7110 Emacs is suspended. Redrawing it is unnecessary and what needs to
7111 be done depends on whether the cursor lies inside or outside the
7112 redraw region. So we might as well skip drawing it when Emacs is
7113 suspended. */
7114 static Boolean app_is_suspended = false;
7115 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
7116 #endif
7117
7118 #define EXTRA_STACK_ALLOC (256 * 1024)
7119
7120 #define ARGV_STRING_LIST_ID 129
7121 #define ABOUT_ALERT_ID 128
7122 #define RAM_TOO_LARGE_ALERT_ID 129
7123
7124 Boolean terminate_flag = false;
7125
7126 /* Contains the string "reverse", which is a constant for mouse button emu.*/
7127 Lisp_Object Qreverse;
7128
7129 /* True if using command key as meta key. */
7130 Lisp_Object Vmac_command_key_is_meta;
7131
7132 /* Modifier associated with the option key, or nil for normal behavior. */
7133 Lisp_Object Vmac_option_modifier;
7134
7135 /* True if the ctrl and meta keys should be reversed. */
7136 Lisp_Object Vmac_reverse_ctrl_meta;
7137
7138 /* True if the option and command modifiers should be used to emulate
7139 a three button mouse */
7140 Lisp_Object Vmac_emulate_three_button_mouse;
7141
7142 #if USE_CARBON_EVENTS
7143 /* True if the mouse wheel button (i.e. button 4) should map to
7144 mouse-2, instead of mouse-3. */
7145 Lisp_Object Vmac_wheel_button_is_mouse_2;
7146
7147 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
7148 for processing before Emacs sees it. */
7149 Lisp_Object Vmac_pass_command_to_system;
7150
7151 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7152 for processing before Emacs sees it. */
7153 Lisp_Object Vmac_pass_control_to_system;
7154 #endif
7155
7156 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
7157 to this text encoding */
7158 int mac_keyboard_text_encoding;
7159 int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
7160
7161 /* Set in term/mac-win.el to indicate that event loop can now generate
7162 drag and drop events. */
7163 Lisp_Object Qmac_ready_for_drag_n_drop;
7164
7165 Lisp_Object drag_and_drop_file_list;
7166
7167 Point saved_menu_event_location;
7168
7169 #if !TARGET_API_MAC_CARBON
7170 /* Place holder for the default arrow cursor. */
7171 CursPtr arrow_cursor;
7172 #endif
7173
7174 /* Apple Events */
7175 static void init_required_apple_events (void);
7176 static pascal OSErr
7177 do_ae_open_application (const AppleEvent *, AppleEvent *, long);
7178 static pascal OSErr
7179 do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
7180 static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
7181 static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
7182
7183 #if TARGET_API_MAC_CARBON
7184 /* Drag and Drop */
7185 static pascal OSErr mac_do_track_drag (DragTrackingMessage, WindowPtr, void*, DragReference);
7186 static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
7187 #endif
7188
7189 #if USE_CARBON_EVENTS
7190 /* Preliminary Support for the OSX Services Menu */
7191 static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
7192 static void init_service_handler ();
7193 /* Window Event Handler */
7194 static pascal OSStatus mac_handle_window_event (EventHandlerCallRef,
7195 EventRef, void *);
7196 #endif
7197 OSErr install_window_handler (WindowPtr);
7198
7199 extern void init_emacs_passwd_dir ();
7200 extern int emacs_main (int, char **, char **);
7201 extern void check_alarm ();
7202
7203 extern void initialize_applescript();
7204 extern void terminate_applescript();
7205
7206 static unsigned int
7207 #if USE_CARBON_EVENTS
7208 mac_to_emacs_modifiers (UInt32 mods)
7209 #else
7210 mac_to_emacs_modifiers (EventModifiers mods)
7211 #endif
7212 {
7213 unsigned int result = 0;
7214 if (mods & macShiftKey)
7215 result |= shift_modifier;
7216 if (mods & macCtrlKey)
7217 result |= ctrl_modifier;
7218 if (mods & macMetaKey)
7219 result |= meta_modifier;
7220 if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
7221 result |= alt_modifier;
7222 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) {
7223 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value);
7224 if (!NILP(val))
7225 result |= XUINT(val);
7226 }
7227
7228 return result;
7229 }
7230
7231 static int
7232 mac_get_emulated_btn ( UInt32 modifiers )
7233 {
7234 int result = 0;
7235 if (!NILP (Vmac_emulate_three_button_mouse)) {
7236 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
7237 if (modifiers & cmdKey)
7238 result = cmdIs3 ? 2 : 1;
7239 else if (modifiers & optionKey)
7240 result = cmdIs3 ? 1 : 2;
7241 }
7242 return result;
7243 }
7244
7245 #if USE_CARBON_EVENTS
7246 /* Obtains the event modifiers from the event ref and then calls
7247 mac_to_emacs_modifiers. */
7248 static int
7249 mac_event_to_emacs_modifiers (EventRef eventRef)
7250 {
7251 UInt32 mods = 0;
7252 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
7253 sizeof (UInt32), NULL, &mods);
7254 if (!NILP (Vmac_emulate_three_button_mouse) &&
7255 GetEventClass(eventRef) == kEventClassMouse)
7256 {
7257 mods &= ~(optionKey | cmdKey);
7258 }
7259 return mac_to_emacs_modifiers (mods);
7260 }
7261
7262 /* Given an event ref, return the code to use for the mouse button
7263 code in the emacs input_event. */
7264 static int
7265 mac_get_mouse_btn (EventRef ref)
7266 {
7267 EventMouseButton result = kEventMouseButtonPrimary;
7268 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
7269 sizeof (EventMouseButton), NULL, &result);
7270 switch (result)
7271 {
7272 case kEventMouseButtonPrimary:
7273 if (NILP (Vmac_emulate_three_button_mouse))
7274 return 0;
7275 else {
7276 UInt32 mods = 0;
7277 GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL,
7278 sizeof (UInt32), NULL, &mods);
7279 return mac_get_emulated_btn(mods);
7280 }
7281 case kEventMouseButtonSecondary:
7282 return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
7283 case kEventMouseButtonTertiary:
7284 case 4: /* 4 is the number for the mouse wheel button */
7285 return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
7286 default:
7287 return 0;
7288 }
7289 }
7290
7291 /* Normally, ConvertEventRefToEventRecord will correctly handle all
7292 events. However the click of the mouse wheel is not converted to a
7293 mouseDown or mouseUp event. This calls ConvertEventRef, but then
7294 checks to see if it is a mouse up or down carbon event that has not
7295 been converted, and if so, converts it by hand (to be picked up in
7296 the XTread_socket loop). */
7297 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
7298 {
7299 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
7300 /* Do special case for mouse wheel button. */
7301 if (!result && GetEventClass (eventRef) == kEventClassMouse)
7302 {
7303 UInt32 kind = GetEventKind (eventRef);
7304 if (kind == kEventMouseDown && !(eventRec->what == mouseDown))
7305 {
7306 eventRec->what = mouseDown;
7307 result=1;
7308 }
7309 if (kind == kEventMouseUp && !(eventRec->what == mouseUp))
7310 {
7311 eventRec->what = mouseUp;
7312 result=1;
7313 }
7314 if (result)
7315 {
7316 /* Need where and when. */
7317 UInt32 mods;
7318 GetEventParameter (eventRef, kEventParamMouseLocation,
7319 typeQDPoint, NULL, sizeof (Point),
7320 NULL, &eventRec->where);
7321 /* Use two step process because new event modifiers are
7322 32-bit and old are 16-bit. Currently, only loss is
7323 NumLock & Fn. */
7324 GetEventParameter (eventRef, kEventParamKeyModifiers,
7325 typeUInt32, NULL, sizeof (UInt32),
7326 NULL, &mods);
7327 eventRec->modifiers = mods;
7328
7329 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
7330 }
7331 }
7332 return result;
7333 }
7334
7335 #endif
7336
7337 static void
7338 do_get_menus (void)
7339 {
7340 Handle menubar_handle;
7341 MenuHandle menu_handle;
7342
7343 menubar_handle = GetNewMBar (128);
7344 if(menubar_handle == NULL)
7345 abort ();
7346 SetMenuBar (menubar_handle);
7347 DrawMenuBar ();
7348
7349 menu_handle = GetMenuHandle (M_APPLE);
7350 if(menu_handle != NULL)
7351 AppendResMenu (menu_handle,'DRVR');
7352 else
7353 abort ();
7354 }
7355
7356
7357 static void
7358 do_init_managers (void)
7359 {
7360 #if !TARGET_API_MAC_CARBON
7361 InitGraf (&qd.thePort);
7362 InitFonts ();
7363 FlushEvents (everyEvent, 0);
7364 InitWindows ();
7365 InitMenus ();
7366 TEInit ();
7367 InitDialogs (NULL);
7368 #endif /* !TARGET_API_MAC_CARBON */
7369 InitCursor ();
7370
7371 #if !TARGET_API_MAC_CARBON
7372 arrow_cursor = &qd.arrow;
7373
7374 /* set up some extra stack space for use by emacs */
7375 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
7376
7377 /* MaxApplZone must be called for AppleScript to execute more
7378 complicated scripts */
7379 MaxApplZone ();
7380 MoreMasters ();
7381 #endif /* !TARGET_API_MAC_CARBON */
7382 }
7383
7384 static void
7385 do_check_ram_size (void)
7386 {
7387 SInt32 physical_ram_size, logical_ram_size;
7388
7389 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
7390 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
7391 || physical_ram_size > (1 << VALBITS)
7392 || logical_ram_size > (1 << VALBITS))
7393 {
7394 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
7395 exit (1);
7396 }
7397 }
7398
7399 static void
7400 do_window_update (WindowPtr win)
7401 {
7402 struct frame *f = mac_window_to_frame (win);
7403
7404 BeginUpdate (win);
7405
7406 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED
7407 below. */
7408 if (win != tip_window)
7409 {
7410 if (f->async_visible == 0)
7411 {
7412 f->async_visible = 1;
7413 f->async_iconified = 0;
7414 SET_FRAME_GARBAGED (f);
7415
7416 /* An update event is equivalent to MapNotify on X, so report
7417 visibility changes properly. */
7418 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
7419 /* Force a redisplay sooner or later to update the
7420 frame titles in case this is the second frame. */
7421 record_asynch_buffer_change ();
7422 }
7423 else
7424 {
7425 Rect r;
7426
7427 handling_window_update = 1;
7428
7429 #if TARGET_API_MAC_CARBON
7430 {
7431 RgnHandle region = NewRgn ();
7432
7433 GetPortVisibleRegion (GetWindowPort (win), region);
7434 UpdateControls (win, region);
7435 GetRegionBounds (region, &r);
7436 DisposeRgn (region);
7437 }
7438 #else
7439 UpdateControls (win, win->visRgn);
7440 r = (*win->visRgn)->rgnBBox;
7441 #endif
7442 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top);
7443
7444 handling_window_update = 0;
7445 }
7446 }
7447
7448 EndUpdate (win);
7449 }
7450
7451 static int
7452 is_emacs_window (WindowPtr win)
7453 {
7454 Lisp_Object tail, frame;
7455
7456 if (!win)
7457 return 0;
7458
7459 FOR_EACH_FRAME (tail, frame)
7460 if (FRAME_MAC_P (XFRAME (frame)))
7461 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
7462 return 1;
7463
7464 return 0;
7465 }
7466
7467 static void
7468 do_app_resume ()
7469 {
7470 /* Window-activate events will do the job. */
7471 #if 0
7472 WindowPtr wp;
7473 struct frame *f;
7474
7475 wp = front_emacs_window ();
7476 if (wp)
7477 {
7478 f = mac_window_to_frame (wp);
7479
7480 if (f)
7481 {
7482 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
7483 activate_scroll_bars (f);
7484 }
7485 }
7486
7487 app_is_suspended = false;
7488 app_sleep_time = WNE_SLEEP_AT_RESUME;
7489 #endif
7490 }
7491
7492 static void
7493 do_app_suspend ()
7494 {
7495 /* Window-deactivate events will do the job. */
7496 #if 0
7497 WindowPtr wp;
7498 struct frame *f;
7499
7500 wp = front_emacs_window ();
7501 if (wp)
7502 {
7503 f = mac_window_to_frame (wp);
7504
7505 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
7506 {
7507 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
7508 deactivate_scroll_bars (f);
7509 }
7510 }
7511
7512 app_is_suspended = true;
7513 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
7514 #endif
7515 }
7516
7517
7518 static void
7519 do_mouse_moved (mouse_pos, f)
7520 Point mouse_pos;
7521 FRAME_PTR *f;
7522 {
7523 WindowPtr wp = front_emacs_window ();
7524 struct x_display_info *dpyinfo;
7525
7526 if (wp)
7527 {
7528 *f = mac_window_to_frame (wp);
7529 dpyinfo = FRAME_MAC_DISPLAY_INFO (*f);
7530
7531 if (dpyinfo->mouse_face_hidden)
7532 {
7533 dpyinfo->mouse_face_hidden = 0;
7534 clear_mouse_face (dpyinfo);
7535 }
7536
7537 SetPortWindowPort (wp);
7538
7539 GlobalToLocal (&mouse_pos);
7540
7541 if (dpyinfo->grabbed && tracked_scroll_bar)
7542 x_scroll_bar_note_movement (tracked_scroll_bar,
7543 mouse_pos.v
7544 - XINT (tracked_scroll_bar->top),
7545 TickCount() * (1000 / 60));
7546 else
7547 note_mouse_movement (*f, &mouse_pos);
7548 }
7549 }
7550
7551
7552 static void
7553 do_apple_menu (SInt16 menu_item)
7554 {
7555 #if !TARGET_API_MAC_CARBON
7556 Str255 item_name;
7557 SInt16 da_driver_refnum;
7558
7559 if (menu_item == I_ABOUT)
7560 NoteAlert (ABOUT_ALERT_ID, NULL);
7561 else
7562 {
7563 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
7564 da_driver_refnum = OpenDeskAcc (item_name);
7565 }
7566 #endif /* !TARGET_API_MAC_CARBON */
7567 }
7568
7569 void
7570 do_menu_choice (SInt32 menu_choice)
7571 {
7572 SInt16 menu_id, menu_item;
7573
7574 menu_id = HiWord (menu_choice);
7575 menu_item = LoWord (menu_choice);
7576
7577 if (menu_id == 0)
7578 return;
7579
7580 switch (menu_id)
7581 {
7582 case M_APPLE:
7583 do_apple_menu (menu_item);
7584 break;
7585
7586 default:
7587 {
7588 struct frame *f = mac_window_to_frame (front_emacs_window ());
7589 MenuHandle menu = GetMenuHandle (menu_id);
7590 if (menu)
7591 {
7592 UInt32 refcon;
7593
7594 GetMenuItemRefCon (menu, menu_item, &refcon);
7595 menubar_selection_callback (f, refcon);
7596 }
7597 }
7598 }
7599
7600 HiliteMenu (0);
7601 }
7602
7603
7604 /* Handle drags in size box. Based on code contributed by Ben
7605 Mesander and IM - Window Manager A. */
7606
7607 static void
7608 do_grow_window (WindowPtr w, EventRecord *e)
7609 {
7610 Rect limit_rect;
7611 int rows, columns, width, height;
7612 struct frame *f = mac_window_to_frame (w);
7613 XSizeHints *size_hints = FRAME_SIZE_HINTS (f);
7614 int min_width = MIN_DOC_SIZE, min_height = MIN_DOC_SIZE;
7615 #if TARGET_API_MAC_CARBON
7616 Rect new_rect;
7617 #else
7618 long grow_size;
7619 #endif
7620
7621 if (size_hints->flags & PMinSize)
7622 {
7623 min_width = size_hints->min_width;
7624 min_height = size_hints->min_height;
7625 }
7626 SetRect (&limit_rect, min_width, min_height, MAX_DOC_SIZE, MAX_DOC_SIZE);
7627
7628 #if TARGET_API_MAC_CARBON
7629 if (!ResizeWindow (w, e->where, &limit_rect, &new_rect))
7630 return;
7631 height = new_rect.bottom - new_rect.top;
7632 width = new_rect.right - new_rect.left;
7633 #else
7634 grow_size = GrowWindow (w, e->where, &limit_rect);
7635 /* see if it really changed size */
7636 if (grow_size == 0)
7637 return;
7638 height = HiWord (grow_size);
7639 width = LoWord (grow_size);
7640 #endif
7641
7642 if (width != FRAME_PIXEL_WIDTH (f)
7643 || height != FRAME_PIXEL_HEIGHT (f))
7644 {
7645 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
7646 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
7647
7648 x_set_window_size (f, 0, columns, rows);
7649 }
7650 }
7651
7652
7653 /* Handle clicks in zoom box. Calculation of "standard state" based
7654 on code in IM - Window Manager A and code contributed by Ben
7655 Mesander. The standard state of an Emacs window is 80-characters
7656 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
7657
7658 static void
7659 do_zoom_window (WindowPtr w, int zoom_in_or_out)
7660 {
7661 GrafPtr save_port;
7662 Rect zoom_rect, port_rect;
7663 Point top_left;
7664 int w_title_height, columns, rows, width, height;
7665 struct frame *f = mac_window_to_frame (w);
7666
7667 #if TARGET_API_MAC_CARBON
7668 {
7669 Point standard_size;
7670
7671 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7672 standard_size.v = FRAME_MAC_DISPLAY_INFO (f)->height;
7673
7674 if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
7675 zoom_in_or_out = inZoomIn;
7676 else
7677 {
7678 /* Adjust the standard size according to character boundaries. */
7679
7680 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
7681 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7682 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
7683 standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7684 GetWindowBounds (w, kWindowContentRgn, &port_rect);
7685 if (IsWindowInStandardState (w, &standard_size, &zoom_rect)
7686 && port_rect.left == zoom_rect.left
7687 && port_rect.top == zoom_rect.top)
7688 zoom_in_or_out = inZoomIn;
7689 else
7690 zoom_in_or_out = inZoomOut;
7691 }
7692
7693 ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
7694 }
7695 #else /* not TARGET_API_MAC_CARBON */
7696 GetPort (&save_port);
7697
7698 SetPortWindowPort (w);
7699
7700 /* Clear window to avoid flicker. */
7701 EraseRect (&(w->portRect));
7702 if (zoom_in_or_out == inZoomOut)
7703 {
7704 SetPt (&top_left, w->portRect.left, w->portRect.top);
7705 LocalToGlobal (&top_left);
7706
7707 /* calculate height of window's title bar */
7708 w_title_height = top_left.v - 1
7709 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
7710
7711 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
7712 zoom_rect = qd.screenBits.bounds;
7713 zoom_rect.top += w_title_height;
7714 InsetRect (&zoom_rect, 8, 4); /* not too tight */
7715
7716 zoom_rect.right = zoom_rect.left
7717 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7718
7719 /* Adjust the standard size according to character boundaries. */
7720 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7721 zoom_rect.bottom =
7722 zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7723
7724 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
7725 = zoom_rect;
7726 }
7727
7728 ZoomWindow (w, zoom_in_or_out, w == front_emacs_window ());
7729
7730 SetPort (save_port);
7731 #endif /* not TARGET_API_MAC_CARBON */
7732
7733 /* retrieve window size and update application values */
7734 #if TARGET_API_MAC_CARBON
7735 GetWindowPortBounds (w, &port_rect);
7736 #else
7737 port_rect = w->portRect;
7738 #endif
7739 height = port_rect.bottom - port_rect.top;
7740 width = port_rect.right - port_rect.left;
7741
7742 if (width != FRAME_PIXEL_WIDTH (f)
7743 || height != FRAME_PIXEL_HEIGHT (f))
7744 {
7745 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height);
7746 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width);
7747
7748 change_frame_size (f, rows, columns, 0, 1, 0);
7749 SET_FRAME_GARBAGED (f);
7750 cancel_mouse_face (f);
7751
7752 FRAME_PIXEL_WIDTH (f) = width;
7753 FRAME_PIXEL_HEIGHT (f) = height;
7754 }
7755 x_real_positions (f, &f->left_pos, &f->top_pos);
7756 }
7757
7758 /* Intialize AppleEvent dispatcher table for the required events. */
7759 void
7760 init_required_apple_events ()
7761 {
7762 OSErr err;
7763 long result;
7764
7765 /* Make sure we have apple events before starting. */
7766 err = Gestalt (gestaltAppleEventsAttr, &result);
7767 if (err != noErr)
7768 abort ();
7769
7770 if (!(result & (1 << gestaltAppleEventsPresent)))
7771 abort ();
7772
7773 #if TARGET_API_MAC_CARBON
7774 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7775 NewAEEventHandlerUPP
7776 ((AEEventHandlerProcPtr) do_ae_open_application),
7777 0L, false);
7778 #else
7779 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7780 NewAEEventHandlerProc
7781 ((AEEventHandlerProcPtr) do_ae_open_application),
7782 0L, false);
7783 #endif
7784 if (err != noErr)
7785 abort ();
7786
7787 #if TARGET_API_MAC_CARBON
7788 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7789 NewAEEventHandlerUPP
7790 ((AEEventHandlerProcPtr) do_ae_open_documents),
7791 0L, false);
7792 #else
7793 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7794 NewAEEventHandlerProc
7795 ((AEEventHandlerProcPtr) do_ae_open_documents),
7796 0L, false);
7797 #endif
7798 if (err != noErr)
7799 abort ();
7800
7801 #if TARGET_API_MAC_CARBON
7802 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7803 NewAEEventHandlerUPP
7804 ((AEEventHandlerProcPtr) do_ae_print_documents),
7805 0L, false);
7806 #else
7807 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7808 NewAEEventHandlerProc
7809 ((AEEventHandlerProcPtr) do_ae_print_documents),
7810 0L, false);
7811 #endif
7812 if (err != noErr)
7813 abort ();
7814
7815 #if TARGET_API_MAC_CARBON
7816 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7817 NewAEEventHandlerUPP
7818 ((AEEventHandlerProcPtr) do_ae_quit_application),
7819 0L, false);
7820 #else
7821 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7822 NewAEEventHandlerProc
7823 ((AEEventHandlerProcPtr) do_ae_quit_application),
7824 0L, false);
7825 #endif
7826 if (err != noErr)
7827 abort ();
7828 }
7829
7830 #if USE_CARBON_EVENTS
7831
7832 void
7833 init_service_handler ()
7834 {
7835 EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
7836 {kEventClassService, kEventServiceCopy},
7837 {kEventClassService, kEventServicePaste}};
7838 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
7839 3, specs, NULL, NULL);
7840 }
7841
7842 /*
7843 MAC_TODO: Check to see if this is called by AEProcessDesc...
7844 */
7845 OSStatus
7846 mac_handle_service_event (EventHandlerCallRef callRef,
7847 EventRef event, void *data)
7848 {
7849 OSStatus err = noErr;
7850 switch (GetEventKind (event))
7851 {
7852 case kEventServiceGetTypes:
7853 {
7854 CFMutableArrayRef copyTypes, pasteTypes;
7855 CFStringRef type;
7856 Boolean selection = true;
7857 /*
7858 GetEventParameter(event, kEventParamServicePasteTypes,
7859 typeCFMutableArrayRef, NULL,
7860 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
7861 */
7862 GetEventParameter(event, kEventParamServiceCopyTypes,
7863 typeCFMutableArrayRef, NULL,
7864 sizeof (CFMutableArrayRef), NULL, &copyTypes);
7865 type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
7866 if (type) {
7867 CFArrayAppendValue (copyTypes, type);
7868 //CFArrayAppendValue (pasteTypes, type);
7869 CFRelease (type);
7870 }
7871 }
7872 case kEventServiceCopy:
7873 {
7874 ScrapRef currentScrap, specificScrap;
7875 char * buf = "";
7876 Size byteCount = 0;
7877
7878 GetCurrentScrap (&currentScrap);
7879
7880 err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
7881 if (err == noErr)
7882 {
7883 void *buffer = xmalloc (byteCount);
7884 if (buffer != NULL)
7885 {
7886 GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
7887 sizeof (ScrapRef), NULL, &specificScrap);
7888
7889 err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
7890 &byteCount, buffer);
7891 if (err == noErr)
7892 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
7893 kScrapFlavorMaskNone, byteCount, buffer);
7894 xfree (buffer);
7895 }
7896 }
7897 err = noErr;
7898 }
7899 case kEventServicePaste:
7900 {
7901 /*
7902 // Get the current location
7903 Size byteCount;
7904 ScrapRef specificScrap;
7905 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
7906 sizeof(ScrapRef), NULL, &specificScrap);
7907 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
7908 if (err == noErr) {
7909 void * buffer = xmalloc(byteCount);
7910 if (buffer != NULL ) {
7911 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
7912 &byteCount, buffer);
7913 if (err == noErr) {
7914 // Actually place in the buffer
7915 BLOCK_INPUT;
7916 // Get the current "selection" string here
7917 UNBLOCK_INPUT;
7918 }
7919 }
7920 xfree(buffer);
7921 }
7922 */
7923 }
7924 }
7925 return err;
7926 }
7927
7928
7929 static pascal OSStatus
7930 mac_handle_window_event (next_handler, event, data)
7931 EventHandlerCallRef next_handler;
7932 EventRef event;
7933 void *data;
7934 {
7935 extern Lisp_Object Qcontrol;
7936
7937 WindowPtr wp;
7938 OSStatus result;
7939 UInt32 attributes;
7940 XSizeHints *size_hints;
7941
7942 GetEventParameter (event, kEventParamDirectObject, typeWindowRef,
7943 NULL, sizeof (WindowPtr), NULL, &wp);
7944
7945 switch (GetEventKind (event))
7946 {
7947 case kEventWindowUpdate:
7948 result = CallNextEventHandler (next_handler, event);
7949 if (result != eventNotHandledErr)
7950 return result;
7951
7952 do_window_update (wp);
7953 break;
7954
7955 case kEventWindowBoundsChanging:
7956 result = CallNextEventHandler (next_handler, event);
7957 if (result != eventNotHandledErr)
7958 return result;
7959
7960 GetEventParameter (event, kEventParamAttributes, typeUInt32,
7961 NULL, sizeof (UInt32), NULL, &attributes);
7962 size_hints = FRAME_SIZE_HINTS (mac_window_to_frame (wp));
7963 if ((attributes & kWindowBoundsChangeUserResize)
7964 && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize))
7965 == (PResizeInc | PBaseSize | PMinSize)))
7966 {
7967 Rect bounds;
7968 int width, height;
7969
7970 GetEventParameter (event, kEventParamCurrentBounds,
7971 typeQDRectangle,
7972 NULL, sizeof (Rect), NULL, &bounds);
7973 width = bounds.right - bounds.left;
7974 height = bounds.bottom - bounds.top;
7975
7976 if (width < size_hints->min_width)
7977 width = size_hints->min_width;
7978 else
7979 width = size_hints->base_width
7980 + (int) ((width - size_hints->base_width)
7981 / (float) size_hints->width_inc + .5)
7982 * size_hints->width_inc;
7983
7984 if (height < size_hints->min_height)
7985 height = size_hints->min_height;
7986 else
7987 height = size_hints->base_height
7988 + (int) ((height - size_hints->base_height)
7989 / (float) size_hints->height_inc + .5)
7990 * size_hints->height_inc;
7991
7992 bounds.right = bounds.left + width;
7993 bounds.bottom = bounds.top + height;
7994 SetEventParameter (event, kEventParamCurrentBounds,
7995 typeQDRectangle, sizeof (Rect), &bounds);
7996 return noErr;
7997 }
7998 break;
7999 }
8000
8001 return eventNotHandledErr;
8002 }
8003 #endif /* USE_CARBON_EVENTS */
8004
8005
8006 OSErr
8007 install_window_handler (window)
8008 WindowPtr window;
8009 {
8010 OSErr err = noErr;
8011 #if USE_CARBON_EVENTS
8012 EventTypeSpec specs[] = {{kEventClassWindow, kEventWindowUpdate},
8013 {kEventClassWindow, kEventWindowBoundsChanging}};
8014 static EventHandlerUPP handle_window_event_UPP = NULL;
8015
8016 if (handle_window_event_UPP == NULL)
8017 handle_window_event_UPP = NewEventHandlerUPP (mac_handle_window_event);
8018
8019 err = InstallWindowEventHandler (window, handle_window_event_UPP,
8020 GetEventTypeCount (specs), specs,
8021 NULL, NULL);
8022 #endif
8023 #if TARGET_API_MAC_CARBON
8024 if (err == noErr)
8025 err = InstallTrackingHandler (mac_do_track_drag, window, NULL);
8026 if (err == noErr)
8027 err = InstallReceiveHandler (mac_do_receive_drag, window, NULL);
8028 #endif
8029 return err;
8030 }
8031
8032
8033 /* Open Application Apple Event */
8034 static pascal OSErr
8035 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
8036 {
8037 return noErr;
8038 }
8039
8040
8041 /* Defined in mac.c. */
8042 extern int
8043 path_from_vol_dir_name (char *, int, short, long, char *);
8044
8045
8046 /* Called when we receive an AppleEvent with an ID of
8047 "kAEOpenDocuments". This routine gets the direct parameter,
8048 extracts the FSSpecs in it, and puts their names on a list. */
8049 #pragma options align=mac68k
8050 typedef struct SelectionRange {
8051 short unused1; // 0 (not used)
8052 short lineNum; // line to select (<0 to specify range)
8053 long startRange; // start of selection range (if line < 0)
8054 long endRange; // end of selection range (if line < 0)
8055 long unused2; // 0 (not used)
8056 long theDate; // modification date/time
8057 } SelectionRange;
8058 #pragma options align=reset
8059
8060 static pascal OSErr
8061 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
8062 {
8063 OSErr err, err2;
8064 AEDesc the_desc;
8065 AEKeyword keyword;
8066 DescType actual_type;
8067 Size actual_size;
8068 SelectionRange position;
8069
8070 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
8071 if (err != noErr)
8072 goto descriptor_error_exit;
8073
8074 err = AEGetParamPtr (message, keyAEPosition, typeChar, &actual_type, &position, sizeof(SelectionRange), &actual_size);
8075 if (err == noErr)
8076 drag_and_drop_file_list = Fcons (list3 (make_number (position.lineNum + 1),
8077 make_number (position.startRange + 1),
8078 make_number (position.endRange + 1)),
8079 drag_and_drop_file_list);
8080
8081 /* Check to see that we got all of the required parameters from the
8082 event descriptor. For an 'odoc' event this should just be the
8083 file list. */
8084 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
8085 &actual_type, (Ptr) &keyword,
8086 sizeof (keyword), &actual_size);
8087 /* No error means that we found some unused parameters.
8088 errAEDescNotFound means that there are no more parameters. If we
8089 get an error code other than that, flag it. */
8090 if ((err == noErr) || (err != errAEDescNotFound))
8091 {
8092 err = errAEEventNotHandled;
8093 goto error_exit;
8094 }
8095 err = noErr;
8096
8097 /* Got all the parameters we need. Now, go through the direct
8098 object list and parse it up. */
8099 {
8100 long num_files_to_open;
8101
8102 err = AECountItems (&the_desc, &num_files_to_open);
8103 if (err == noErr)
8104 {
8105 int i;
8106
8107 /* AE file list is one based so just use that for indexing here. */
8108 for (i = 1; i <= num_files_to_open; i++)
8109 {
8110 #ifdef MAC_OSX
8111 FSRef fref;
8112 char unix_path_name[MAXPATHLEN];
8113
8114 err = AEGetNthPtr (&the_desc, i, typeFSRef, &keyword,
8115 &actual_type, &fref, sizeof (FSRef),
8116 &actual_size);
8117 if (err != noErr || actual_type != typeFSRef)
8118 continue;
8119
8120 if (FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name))
8121 == noErr)
8122 #else
8123 FSSpec fs;
8124 Str255 path_name, unix_path_name;
8125
8126 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
8127 (Ptr) &fs, sizeof (fs), &actual_size);
8128 if (err != noErr) continue;
8129
8130 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
8131 fs.name) &&
8132 mac_to_posix_pathname (path_name, unix_path_name, 255))
8133 #endif
8134 /* x-dnd functions expect undecoded filenames. */
8135 drag_and_drop_file_list =
8136 Fcons (make_unibyte_string (unix_path_name,
8137 strlen (unix_path_name)),
8138 drag_and_drop_file_list);
8139 }
8140 }
8141 }
8142
8143 error_exit:
8144 /* Nuke the coerced file list in any case */
8145 err2 = AEDisposeDesc(&the_desc);
8146
8147 descriptor_error_exit:
8148 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
8149 return err;
8150 }
8151
8152
8153 #if TARGET_API_MAC_CARBON
8154 static pascal OSErr
8155 mac_do_track_drag (DragTrackingMessage message, WindowPtr window,
8156 void *handlerRefCon, DragReference theDrag)
8157 {
8158 static int can_accept;
8159 short items;
8160 short index;
8161 ItemReference theItem;
8162 FlavorFlags theFlags;
8163 OSErr result;
8164
8165 if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
8166 return dragNotAcceptedErr;
8167
8168 switch (message)
8169 {
8170 case kDragTrackingEnterHandler:
8171 CountDragItems (theDrag, &items);
8172 can_accept = 0;
8173 for (index = 1; index <= items; index++)
8174 {
8175 GetDragItemReferenceNumber (theDrag, index, &theItem);
8176 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
8177 if (result == noErr)
8178 {
8179 can_accept = 1;
8180 break;
8181 }
8182 }
8183 break;
8184
8185 case kDragTrackingEnterWindow:
8186 if (can_accept)
8187 {
8188 RgnHandle hilite_rgn = NewRgn ();
8189 Rect r;
8190 struct frame *f = mac_window_to_frame (window);
8191
8192 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
8193 GetWindowPortBounds (window, &r);
8194 OffsetRect (&r, -r.left, -r.top);
8195 RectRgn (hilite_rgn, &r);
8196 ShowDragHilite (theDrag, hilite_rgn, true);
8197 DisposeRgn (hilite_rgn);
8198 SetThemeCursor (kThemeCopyArrowCursor);
8199 }
8200 break;
8201
8202 case kDragTrackingInWindow:
8203 break;
8204
8205 case kDragTrackingLeaveWindow:
8206 if (can_accept)
8207 {
8208 struct frame *f = mac_window_to_frame (window);
8209
8210 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
8211 HideDragHilite (theDrag);
8212 SetThemeCursor (kThemeArrowCursor);
8213 }
8214 break;
8215
8216 case kDragTrackingLeaveHandler:
8217 break;
8218 }
8219
8220 return noErr;
8221 }
8222
8223 static pascal OSErr
8224 mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
8225 DragReference theDrag)
8226 {
8227 short items;
8228 short index;
8229 FlavorFlags theFlags;
8230 Point mouse;
8231 OSErr result;
8232 ItemReference theItem;
8233 HFSFlavor data;
8234 Size size = sizeof (HFSFlavor);
8235
8236 if (GetFrontWindowOfClass (kMovableModalWindowClass, false))
8237 return dragNotAcceptedErr;
8238
8239 drag_and_drop_file_list = Qnil;
8240 GetDragMouse (theDrag, &mouse, 0L);
8241 CountDragItems (theDrag, &items);
8242 for (index = 1; index <= items; index++)
8243 {
8244 /* Only handle file references. */
8245 GetDragItemReferenceNumber (theDrag, index, &theItem);
8246 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
8247 if (result == noErr)
8248 {
8249 #ifdef MAC_OSX
8250 FSRef fref;
8251 char unix_path_name[MAXPATHLEN];
8252 #else
8253 Str255 path_name, unix_path_name;
8254 #endif
8255 GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
8256 #ifdef MAC_OSX
8257 /* Use Carbon routines, otherwise it converts the file name
8258 to /Macintosh HD/..., which is not correct. */
8259 FSpMakeFSRef (&data.fileSpec, &fref);
8260 if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
8261 #else
8262 if (path_from_vol_dir_name (path_name, 255, data.fileSpec.vRefNum,
8263 data.fileSpec.parID, data.fileSpec.name) &&
8264 mac_to_posix_pathname (path_name, unix_path_name, 255))
8265 #endif
8266 /* x-dnd functions expect undecoded filenames. */
8267 drag_and_drop_file_list =
8268 Fcons (make_unibyte_string (unix_path_name,
8269 strlen (unix_path_name)),
8270 drag_and_drop_file_list);
8271 }
8272 }
8273 /* If there are items in the list, construct an event and post it to
8274 the queue like an interrupt using kbd_buffer_store_event. */
8275 if (!NILP (drag_and_drop_file_list))
8276 {
8277 struct input_event event;
8278 Lisp_Object frame;
8279 struct frame *f = mac_window_to_frame (window);
8280 SInt16 modifiers;
8281
8282 GlobalToLocal (&mouse);
8283 GetDragModifiers (theDrag, NULL, NULL, &modifiers);
8284
8285 event.kind = DRAG_N_DROP_EVENT;
8286 event.code = 0;
8287 event.modifiers = mac_to_emacs_modifiers (modifiers);
8288 event.timestamp = TickCount () * (1000 / 60);
8289 XSETINT (event.x, mouse.h);
8290 XSETINT (event.y, mouse.v);
8291 XSETFRAME (frame, f);
8292 event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
8293 event.arg = Qnil;
8294 /* Post to the interrupt queue */
8295 kbd_buffer_store_event (&event);
8296 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
8297 {
8298 ProcessSerialNumber psn;
8299 GetCurrentProcess (&psn);
8300 SetFrontProcess (&psn);
8301 }
8302
8303 return noErr;
8304 }
8305 else
8306 return dragNotAcceptedErr;
8307 }
8308 #endif
8309
8310
8311 /* Print Document Apple Event */
8312 static pascal OSErr
8313 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
8314 {
8315 return errAEEventNotHandled;
8316 }
8317
8318
8319 static pascal OSErr
8320 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
8321 {
8322 /* FixMe: Do we need an unwind-protect or something here? And what
8323 do we do about unsaved files. Currently just forces quit rather
8324 than doing recursive callback to get user input. */
8325
8326 terminate_flag = true;
8327
8328 /* Fkill_emacs doesn't return. We have to return. (TI) */
8329 return noErr;
8330 }
8331
8332
8333 #if __profile__
8334 void
8335 profiler_exit_proc ()
8336 {
8337 ProfilerDump ("\pEmacs.prof");
8338 ProfilerTerm ();
8339 }
8340 #endif
8341
8342 /* These few functions implement Emacs as a normal Mac application
8343 (almost): set up the heap and the Toolbox, handle necessary
8344 system events plus a few simple menu events. They also set up
8345 Emacs's access to functions defined in the rest of this file.
8346 Emacs uses function hooks to perform all its terminal I/O. A
8347 complete list of these functions appear in termhooks.h. For what
8348 they do, read the comments there and see also w32term.c and
8349 xterm.c. What's noticeably missing here is the event loop, which
8350 is normally present in most Mac application. After performing the
8351 necessary Mac initializations, main passes off control to
8352 emacs_main (corresponding to main in emacs.c). Emacs_main calls
8353 mac_read_socket (defined further below) to read input. This is
8354 where WaitNextEvent is called to process Mac events. This is also
8355 where check_alarm in sysdep.c is called to simulate alarm signals.
8356 This makes the cursor jump back to its correct position after
8357 briefly jumping to that of the matching parenthesis, print useful
8358 hints and prompts in the minibuffer after the user stops typing for
8359 a wait, etc. */
8360
8361 #if !TARGET_API_MAC_CARBON
8362 #undef main
8363 int
8364 main (void)
8365 {
8366 #if __profile__ /* is the profiler on? */
8367 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
8368 exit(1);
8369 #endif
8370
8371 #if __MWERKS__
8372 /* set creator and type for files created by MSL */
8373 _fcreator = 'EMAx';
8374 _ftype = 'TEXT';
8375 #endif
8376
8377 do_init_managers ();
8378
8379 do_get_menus ();
8380
8381 #ifndef USE_LSB_TAG
8382 do_check_ram_size ();
8383 #endif
8384
8385 init_emacs_passwd_dir ();
8386
8387 init_environ ();
8388
8389 initialize_applescript ();
8390
8391 init_required_apple_events ();
8392
8393 {
8394 char **argv;
8395 int argc = 0;
8396
8397 /* set up argv array from STR# resource */
8398 get_string_list (&argv, ARGV_STRING_LIST_ID);
8399 while (argv[argc])
8400 argc++;
8401
8402 /* free up AppleScript resources on exit */
8403 atexit (terminate_applescript);
8404
8405 #if __profile__ /* is the profiler on? */
8406 atexit (profiler_exit_proc);
8407 #endif
8408
8409 /* 3rd param "envp" never used in emacs_main */
8410 (void) emacs_main (argc, argv, 0);
8411 }
8412
8413 /* Never reached - real exit in Fkill_emacs */
8414 return 0;
8415 }
8416 #endif
8417
8418 /* Table for translating Mac keycode to X keysym values. Contributed
8419 by Sudhir Shenoy. */
8420 static unsigned char keycode_to_xkeysym_table[] = {
8421 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8422 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8423 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8424
8425 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8426 /*0x34*/ 0, 0x1b /*escape*/, 0, 0,
8427 /*0x38*/ 0, 0, 0, 0,
8428 /*0x3C*/ 0, 0, 0, 0,
8429
8430 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
8431 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x7f /*kp-clear*/,
8432 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
8433 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
8434
8435 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8436 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8437 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8438 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8439
8440 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8441 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8442 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
8443 /*0x6C*/ 0, 0xc7 /*f10*/, 0, 0xc9 /*f12*/,
8444
8445 /*0x70*/ 0, 0xcc /*f15*/, 0x9e /*insert (or 0x6a==help)*/, 0x95 /*home*/,
8446 /*0x74*/ 0x9a /*pgup*/, 0x9f /*delete*/, 0xc1 /*f4*/, 0x9c /*end*/,
8447 /*0x78*/ 0xbf /*f2*/, 0x9b /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8448 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8449 };
8450
8451 static int
8452 keycode_to_xkeysym (int keyCode, int *xKeySym)
8453 {
8454 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
8455 return *xKeySym != 0;
8456 }
8457
8458 #if !USE_CARBON_EVENTS
8459 static RgnHandle mouse_region = NULL;
8460
8461 Boolean
8462 mac_wait_next_event (er, sleep_time, dequeue)
8463 EventRecord *er;
8464 UInt32 sleep_time;
8465 Boolean dequeue;
8466 {
8467 static EventRecord er_buf = {nullEvent};
8468 UInt32 target_tick, current_tick;
8469 EventMask event_mask;
8470
8471 if (mouse_region == NULL)
8472 mouse_region = NewRgn ();
8473
8474 event_mask = everyEvent;
8475 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
8476 event_mask -= highLevelEventMask;
8477
8478 current_tick = TickCount ();
8479 target_tick = current_tick + sleep_time;
8480
8481 if (er_buf.what == nullEvent)
8482 while (!WaitNextEvent (event_mask, &er_buf,
8483 target_tick - current_tick, mouse_region))
8484 {
8485 current_tick = TickCount ();
8486 if (target_tick <= current_tick)
8487 return false;
8488 }
8489
8490 *er = er_buf;
8491 if (dequeue)
8492 er_buf.what = nullEvent;
8493 return true;
8494 }
8495 #endif /* not USE_CARBON_EVENTS */
8496
8497 /* Emacs calls this whenever it wants to read an input event from the
8498 user. */
8499 int
8500 XTread_socket (sd, expected, hold_quit)
8501 int sd, expected;
8502 struct input_event *hold_quit;
8503 {
8504 struct input_event inev;
8505 int count = 0;
8506 #if USE_CARBON_EVENTS
8507 EventRef eventRef;
8508 EventTargetRef toolbox_dispatcher;
8509 #endif
8510 EventRecord er;
8511 struct mac_display_info *dpyinfo = &one_mac_display_info;
8512
8513 if (interrupt_input_blocked)
8514 {
8515 interrupt_input_pending = 1;
8516 return -1;
8517 }
8518
8519 interrupt_input_pending = 0;
8520 BLOCK_INPUT;
8521
8522 /* So people can tell when we have read the available input. */
8523 input_signal_count++;
8524
8525 /* Don't poll for events to process (specifically updateEvt) if
8526 window update currently already in progress. A call to redisplay
8527 (in do_window_update) can be preempted by another call to
8528 redisplay, causing blank regions to be left on the screen and the
8529 cursor to be left at strange places. */
8530 if (handling_window_update)
8531 {
8532 UNBLOCK_INPUT;
8533 return 0;
8534 }
8535
8536 if (terminate_flag)
8537 Fkill_emacs (make_number (1));
8538
8539 #if USE_CARBON_EVENTS
8540 toolbox_dispatcher = GetEventDispatcherTarget ();
8541
8542 while (!ReceiveNextEvent (0, NULL, kEventDurationNoWait,
8543 kEventRemoveFromQueue, &eventRef))
8544 #else /* !USE_CARBON_EVENTS */
8545 while (mac_wait_next_event (&er, 0, true))
8546 #endif /* !USE_CARBON_EVENTS */
8547 {
8548 int do_help = 0;
8549 struct frame *f;
8550
8551 /* It is necessary to set this (additional) argument slot of an
8552 event to nil because keyboard.c protects incompletely
8553 processed event from being garbage collected by placing them
8554 in the kbd_buffer_gcpro vector. */
8555 EVENT_INIT (inev);
8556 inev.kind = NO_EVENT;
8557 inev.arg = Qnil;
8558
8559 #if USE_CARBON_EVENTS
8560 /* Handle new events */
8561 if (!mac_convert_event_ref (eventRef, &er))
8562 switch (GetEventClass (eventRef))
8563 {
8564 case kEventClassWindow:
8565 if (GetEventKind (eventRef) == kEventWindowBoundsChanged)
8566 {
8567 WindowPtr window_ptr;
8568 GetEventParameter(eventRef, kEventParamDirectObject,
8569 typeWindowRef, NULL, sizeof(WindowPtr),
8570 NULL, &window_ptr);
8571 f = mac_window_to_frame (window_ptr);
8572 if (f && !f->async_iconified)
8573 x_real_positions (f, &f->left_pos, &f->top_pos);
8574 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8575 }
8576 break;
8577 case kEventClassMouse:
8578 if (GetEventKind (eventRef) == kEventMouseWheelMoved)
8579 {
8580 SInt32 delta;
8581 Point point;
8582 WindowPtr window_ptr = front_emacs_window ();
8583
8584 if (!IsValidWindowPtr (window_ptr))
8585 {
8586 SysBeep(1);
8587 break;
8588 }
8589
8590 GetEventParameter(eventRef, kEventParamMouseWheelDelta,
8591 typeSInt32, NULL, sizeof (SInt32),
8592 NULL, &delta);
8593 GetEventParameter(eventRef, kEventParamMouseLocation,
8594 typeQDPoint, NULL, sizeof (Point),
8595 NULL, &point);
8596 inev.kind = WHEEL_EVENT;
8597 inev.code = 0;
8598 inev.modifiers = (mac_event_to_emacs_modifiers (eventRef)
8599 | ((delta < 0) ? down_modifier
8600 : up_modifier));
8601 SetPortWindowPort (window_ptr);
8602 GlobalToLocal (&point);
8603 XSETINT (inev.x, point.h);
8604 XSETINT (inev.y, point.v);
8605 XSETFRAME (inev.frame_or_window,
8606 mac_window_to_frame (window_ptr));
8607 inev.timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
8608 }
8609 else
8610 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8611
8612 break;
8613
8614 default:
8615 /* Send the event to the appropriate receiver. */
8616 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8617 }
8618 else
8619 #endif /* USE_CARBON_EVENTS */
8620 switch (er.what)
8621 {
8622 case mouseDown:
8623 case mouseUp:
8624 {
8625 WindowPtr window_ptr;
8626 SInt16 part_code;
8627 int tool_bar_p = 0;
8628
8629 #if USE_CARBON_EVENTS
8630 /* This is needed to send mouse events like aqua window
8631 buttons to the correct handler. */
8632 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8633 != eventNotHandledErr)
8634 break;
8635 #endif
8636
8637 if (dpyinfo->grabbed && last_mouse_frame
8638 && FRAME_LIVE_P (last_mouse_frame))
8639 {
8640 window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
8641 part_code = inContent;
8642 }
8643 else
8644 {
8645 part_code = FindWindow (er.where, &window_ptr);
8646 if (tip_window && window_ptr == tip_window)
8647 {
8648 HideWindow (tip_window);
8649 part_code = FindWindow (er.where, &window_ptr);
8650 }
8651 }
8652
8653 if (er.what != mouseDown && part_code != inContent)
8654 break;
8655
8656 switch (part_code)
8657 {
8658 case inMenuBar:
8659 f = mac_window_to_frame (front_emacs_window ());
8660 saved_menu_event_location = er.where;
8661 inev.kind = MENU_BAR_ACTIVATE_EVENT;
8662 XSETFRAME (inev.frame_or_window, f);
8663 break;
8664
8665 case inContent:
8666 if (window_ptr != front_emacs_window ())
8667 SelectWindow (window_ptr);
8668 else
8669 {
8670 SInt16 control_part_code;
8671 ControlHandle ch;
8672 Point mouse_loc = er.where;
8673
8674 f = mac_window_to_frame (window_ptr);
8675 /* convert to local coordinates of new window */
8676 SetPortWindowPort (window_ptr);
8677
8678 GlobalToLocal (&mouse_loc);
8679 #if TARGET_API_MAC_CARBON
8680 ch = FindControlUnderMouse (mouse_loc, window_ptr,
8681 &control_part_code);
8682 #else
8683 control_part_code = FindControl (mouse_loc, window_ptr,
8684 &ch);
8685 #endif
8686
8687 #if USE_CARBON_EVENTS
8688 inev.code = mac_get_mouse_btn (eventRef);
8689 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
8690 #else
8691 inev.code = mac_get_emulated_btn (er.modifiers);
8692 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
8693 #endif
8694 XSETINT (inev.x, mouse_loc.h);
8695 XSETINT (inev.y, mouse_loc.v);
8696 inev.timestamp = er.when * (1000 / 60);
8697 /* ticks to milliseconds */
8698
8699 if (dpyinfo->grabbed && tracked_scroll_bar
8700 #if TARGET_API_MAC_CARBON
8701 || ch != 0
8702 #else
8703 || control_part_code != 0
8704 #endif
8705 )
8706 {
8707 struct scroll_bar *bar;
8708
8709 if (dpyinfo->grabbed && tracked_scroll_bar)
8710 {
8711 bar = tracked_scroll_bar;
8712 control_part_code = kControlIndicatorPart;
8713 }
8714 else
8715 bar = (struct scroll_bar *) GetControlReference (ch);
8716 x_scroll_bar_handle_click (bar, control_part_code,
8717 &er, &inev);
8718 if (er.what == mouseDown
8719 && control_part_code == kControlIndicatorPart)
8720 tracked_scroll_bar = bar;
8721 else
8722 tracked_scroll_bar = NULL;
8723 }
8724 else
8725 {
8726 Lisp_Object window;
8727 int x = mouse_loc.h;
8728 int y = mouse_loc.v;
8729
8730 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
8731 if (EQ (window, f->tool_bar_window))
8732 {
8733 if (er.what == mouseDown)
8734 handle_tool_bar_click (f, x, y, 1, 0);
8735 else
8736 handle_tool_bar_click (f, x, y, 0,
8737 inev.modifiers);
8738 tool_bar_p = 1;
8739 }
8740 else
8741 {
8742 XSETFRAME (inev.frame_or_window, f);
8743 inev.kind = MOUSE_CLICK_EVENT;
8744 }
8745 }
8746
8747 if (er.what == mouseDown)
8748 {
8749 dpyinfo->grabbed |= (1 << inev.code);
8750 last_mouse_frame = f;
8751 /* Ignore any mouse motion that happened
8752 before this event; any subsequent
8753 mouse-movement Emacs events should reflect
8754 only motion after the ButtonPress. */
8755 if (f != 0)
8756 f->mouse_moved = 0;
8757
8758 if (!tool_bar_p)
8759 last_tool_bar_item = -1;
8760 }
8761 else
8762 {
8763 if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
8764 /* If a button is released though it was not
8765 previously pressed, that would be because
8766 of multi-button emulation. */
8767 dpyinfo->grabbed = 0;
8768 else
8769 dpyinfo->grabbed &= ~(1 << inev.code);
8770 }
8771
8772 switch (er.what)
8773 {
8774 case mouseDown:
8775 inev.modifiers |= down_modifier;
8776 break;
8777 case mouseUp:
8778 inev.modifiers |= up_modifier;
8779 break;
8780 }
8781 }
8782 break;
8783
8784 case inDrag:
8785 #if TARGET_API_MAC_CARBON
8786 DragWindow (window_ptr, er.where, NULL);
8787 #else /* not TARGET_API_MAC_CARBON */
8788 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
8789 #endif /* not TARGET_API_MAC_CARBON */
8790 /* Update the frame parameters. */
8791 {
8792 struct frame *f = mac_window_to_frame (window_ptr);
8793
8794 if (f && !f->async_iconified)
8795 x_real_positions (f, &f->left_pos, &f->top_pos);
8796 }
8797 break;
8798
8799 case inGoAway:
8800 if (TrackGoAway (window_ptr, er.where))
8801 {
8802 inev.kind = DELETE_WINDOW_EVENT;
8803 XSETFRAME (inev.frame_or_window,
8804 mac_window_to_frame (window_ptr));
8805 }
8806 break;
8807
8808 /* window resize handling added --ben */
8809 case inGrow:
8810 do_grow_window (window_ptr, &er);
8811 break;
8812
8813 /* window zoom handling added --ben */
8814 case inZoomIn:
8815 case inZoomOut:
8816 if (TrackBox (window_ptr, er.where, part_code))
8817 do_zoom_window (window_ptr, part_code);
8818 break;
8819
8820 default:
8821 break;
8822 }
8823 }
8824 break;
8825
8826 case updateEvt:
8827 #if USE_CARBON_EVENTS
8828 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8829 != eventNotHandledErr)
8830 break;
8831 #else
8832 do_window_update ((WindowPtr) er.message);
8833 #endif
8834 break;
8835
8836 case osEvt:
8837 #if USE_CARBON_EVENTS
8838 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8839 != eventNotHandledErr)
8840 break;
8841 #endif
8842 switch ((er.message >> 24) & 0x000000FF)
8843 {
8844 case suspendResumeMessage:
8845 if ((er.message & resumeFlag) == 1)
8846 do_app_resume ();
8847 else
8848 do_app_suspend ();
8849 break;
8850
8851 case mouseMovedMessage:
8852 #if !USE_CARBON_EVENTS
8853 SetRectRgn (mouse_region, er.where.h, er.where.v,
8854 er.where.h + 1, er.where.v + 1);
8855 #endif
8856 previous_help_echo_string = help_echo_string;
8857 help_echo_string = help_echo_object = help_echo_window = Qnil;
8858 help_echo_pos = -1;
8859
8860 do_mouse_moved (er.where, &f);
8861
8862 /* If the contents of the global variable
8863 help_echo_string has changed, generate a
8864 HELP_EVENT. */
8865 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
8866 do_help = 1;
8867 break;
8868 }
8869 break;
8870
8871 case activateEvt:
8872 {
8873 WindowPtr window_ptr = (WindowPtr) er.message;
8874
8875 #if USE_CARBON_EVENTS
8876 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8877 != eventNotHandledErr)
8878 break;
8879 #endif
8880 if (window_ptr == tip_window)
8881 {
8882 HideWindow (tip_window);
8883 break;
8884 }
8885
8886 if (!is_emacs_window (window_ptr))
8887 break;
8888
8889 f = mac_window_to_frame (window_ptr);
8890
8891 if ((er.modifiers & activeFlag) != 0)
8892 {
8893 /* A window has been activated */
8894 Point mouse_loc = er.where;
8895
8896 x_new_focus_frame (dpyinfo, f);
8897 activate_scroll_bars (f);
8898
8899 SetPortWindowPort (window_ptr);
8900 GlobalToLocal (&mouse_loc);
8901 /* Window-activated event counts as mouse movement,
8902 so update things that depend on mouse position. */
8903 note_mouse_movement (mac_window_to_frame (window_ptr),
8904 &mouse_loc);
8905 }
8906 else
8907 {
8908 /* A window has been deactivated */
8909 dpyinfo->grabbed = 0;
8910
8911 if (f == dpyinfo->x_focus_frame)
8912 {
8913 x_new_focus_frame (dpyinfo, 0);
8914 deactivate_scroll_bars (f);
8915 }
8916
8917
8918 if (f == dpyinfo->mouse_face_mouse_frame)
8919 {
8920 /* If we move outside the frame, then we're
8921 certainly no longer on any text in the
8922 frame. */
8923 clear_mouse_face (dpyinfo);
8924 dpyinfo->mouse_face_mouse_frame = 0;
8925 }
8926
8927 /* Generate a nil HELP_EVENT to cancel a help-echo.
8928 Do it only if there's something to cancel.
8929 Otherwise, the startup message is cleared when the
8930 mouse leaves the frame. */
8931 if (any_help_event_p)
8932 do_help = -1;
8933 }
8934 }
8935 break;
8936
8937 case keyDown:
8938 case autoKey:
8939 {
8940 int keycode = (er.message & keyCodeMask) >> 8;
8941 int xkeysym;
8942
8943 #if USE_CARBON_EVENTS
8944 /* When using Carbon Events, we need to pass raw keyboard
8945 events to the TSM ourselves. If TSM handles it, it
8946 will pass back noErr, otherwise it will pass back
8947 "eventNotHandledErr" and we can process it
8948 normally. */
8949 if ((!NILP (Vmac_pass_command_to_system)
8950 || !(er.modifiers & cmdKey))
8951 && (!NILP (Vmac_pass_control_to_system)
8952 || !(er.modifiers & controlKey)))
8953 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8954 != eventNotHandledErr)
8955 break;
8956 #endif
8957
8958 #if TARGET_API_MAC_CARBON
8959 if (!IsValidWindowPtr (front_emacs_window ()))
8960 {
8961 SysBeep (1);
8962 break;
8963 }
8964 #endif
8965
8966 ObscureCursor ();
8967
8968 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
8969 {
8970 clear_mouse_face (dpyinfo);
8971 dpyinfo->mouse_face_hidden = 1;
8972 }
8973
8974 if (keycode_to_xkeysym (keycode, &xkeysym))
8975 {
8976 inev.code = 0xff00 | xkeysym;
8977 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
8978 }
8979 else
8980 {
8981 if (er.modifiers & (controlKey |
8982 (NILP (Vmac_command_key_is_meta) ? optionKey
8983 : cmdKey)))
8984 {
8985 /* This code comes from Keyboard Resource,
8986 Appendix C of IM - Text. This is necessary
8987 since shift is ignored in KCHR table
8988 translation when option or command is pressed.
8989 It also does not translate correctly
8990 control-shift chars like C-% so mask off shift
8991 here also */
8992 int new_modifiers = er.modifiers & 0xe600;
8993 /* mask off option and command */
8994 int new_keycode = keycode | new_modifiers;
8995 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8996 unsigned long some_state = 0;
8997 inev.code = KeyTranslate (kchr_ptr, new_keycode,
8998 &some_state) & 0xff;
8999 } else if (!NILP(Vmac_option_modifier) && (er.modifiers & optionKey))
9000 {
9001 /* When using the option key as an emacs modifier, convert
9002 the pressed key code back to one without the Mac option
9003 modifier applied. */
9004 int new_modifiers = er.modifiers & ~optionKey;
9005 int new_keycode = keycode | new_modifiers;
9006 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
9007 unsigned long some_state = 0;
9008 inev.code = KeyTranslate (kchr_ptr, new_keycode,
9009 &some_state) & 0xff;
9010 }
9011 else
9012 inev.code = er.message & charCodeMask;
9013 inev.kind = ASCII_KEYSTROKE_EVENT;
9014 }
9015 }
9016
9017 /* If variable mac-convert-keyboard-input-to-latin-1 is
9018 non-nil, convert non-ASCII characters typed at the Mac
9019 keyboard (presumed to be in the Mac Roman encoding) to
9020 iso-latin-1 encoding before they are passed to Emacs.
9021 This enables the Mac keyboard to be used to enter
9022 non-ASCII iso-latin-1 characters directly. */
9023 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
9024 && inev.kind == ASCII_KEYSTROKE_EVENT && inev.code >= 128)
9025 {
9026 static TECObjectRef converter = NULL;
9027 OSStatus the_err = noErr;
9028 OSStatus convert_status = noErr;
9029
9030 if (converter == NULL)
9031 {
9032 the_err = TECCreateConverter (&converter,
9033 kTextEncodingMacRoman,
9034 mac_keyboard_text_encoding);
9035 current_mac_keyboard_text_encoding
9036 = mac_keyboard_text_encoding;
9037 }
9038 else if (mac_keyboard_text_encoding
9039 != current_mac_keyboard_text_encoding)
9040 {
9041 /* Free the converter for the current encoding
9042 before creating a new one. */
9043 TECDisposeConverter (converter);
9044 the_err = TECCreateConverter (&converter,
9045 kTextEncodingMacRoman,
9046 mac_keyboard_text_encoding);
9047 current_mac_keyboard_text_encoding
9048 = mac_keyboard_text_encoding;
9049 }
9050
9051 if (the_err == noErr)
9052 {
9053 unsigned char ch = inev.code;
9054 ByteCount actual_input_length, actual_output_length;
9055 unsigned char outbuf[32];
9056
9057 convert_status = TECConvertText (converter, &ch, 1,
9058 &actual_input_length,
9059 outbuf, 1,
9060 &actual_output_length);
9061 if (convert_status == noErr
9062 && actual_input_length == 1
9063 && actual_output_length == 1)
9064 inev.code = *outbuf;
9065
9066 /* Reset internal states of the converter object.
9067 If it fails, create another one. */
9068 convert_status = TECFlushText (converter, outbuf,
9069 sizeof (outbuf),
9070 &actual_output_length);
9071 if (convert_status != noErr)
9072 {
9073 TECDisposeConverter (converter);
9074 TECCreateConverter (&converter,
9075 kTextEncodingMacRoman,
9076 mac_keyboard_text_encoding);
9077 }
9078 }
9079 }
9080
9081 #if USE_CARBON_EVENTS
9082 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
9083 #else
9084 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
9085 #endif
9086 XSETFRAME (inev.frame_or_window,
9087 mac_window_to_frame (front_emacs_window ()));
9088 inev.timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
9089 break;
9090
9091 case kHighLevelEvent:
9092 drag_and_drop_file_list = Qnil;
9093
9094 AEProcessAppleEvent(&er);
9095
9096 /* Build a DRAG_N_DROP_EVENT type event as is done in
9097 constuct_drag_n_drop in w32term.c. */
9098 if (!NILP (drag_and_drop_file_list))
9099 {
9100 struct frame *f = NULL;
9101 WindowPtr wp;
9102 Lisp_Object frame;
9103
9104 wp = front_emacs_window ();
9105
9106 if (!wp)
9107 {
9108 struct frame *f = XFRAME (XCAR (Vframe_list));
9109 CollapseWindow (FRAME_MAC_WINDOW (f), false);
9110 wp = front_emacs_window ();
9111 }
9112
9113 if (wp)
9114 f = mac_window_to_frame (wp);
9115
9116 inev.kind = DRAG_N_DROP_EVENT;
9117 inev.code = 0;
9118 inev.timestamp = er.when * (1000 / 60);
9119 /* ticks to milliseconds */
9120 #if USE_CARBON_EVENTS
9121 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
9122 #else
9123 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
9124 #endif
9125
9126 XSETINT (inev.x, 0);
9127 XSETINT (inev.y, 0);
9128
9129 XSETFRAME (frame, f);
9130 inev.frame_or_window = Fcons (frame, drag_and_drop_file_list);
9131
9132 /* Regardless of whether Emacs was suspended or in the
9133 foreground, ask it to redraw its entire screen.
9134 Otherwise parts of the screen can be left in an
9135 inconsistent state. */
9136 if (wp)
9137 #if TARGET_API_MAC_CARBON
9138 {
9139 Rect r;
9140
9141 GetWindowPortBounds (wp, &r);
9142 InvalWindowRect (wp, &r);
9143 }
9144 #else /* not TARGET_API_MAC_CARBON */
9145 InvalRect (&(wp->portRect));
9146 #endif /* not TARGET_API_MAC_CARBON */
9147 }
9148 default:
9149 break;
9150 }
9151 #if USE_CARBON_EVENTS
9152 ReleaseEvent (eventRef);
9153 #endif
9154
9155 if (inev.kind != NO_EVENT)
9156 {
9157 kbd_buffer_store_event_hold (&inev, hold_quit);
9158 count++;
9159 }
9160
9161 if (do_help
9162 && !(hold_quit && hold_quit->kind != NO_EVENT))
9163 {
9164 Lisp_Object frame;
9165
9166 if (f)
9167 XSETFRAME (frame, f);
9168 else
9169 frame = Qnil;
9170
9171 if (do_help > 0)
9172 {
9173 any_help_event_p = 1;
9174 gen_help_event (help_echo_string, frame, help_echo_window,
9175 help_echo_object, help_echo_pos);
9176 }
9177 else
9178 {
9179 help_echo_string = Qnil;
9180 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
9181 }
9182 count++;
9183 }
9184
9185 }
9186
9187 /* If the focus was just given to an autoraising frame,
9188 raise it now. */
9189 /* ??? This ought to be able to handle more than one such frame. */
9190 if (pending_autoraise_frame)
9191 {
9192 x_raise_frame (pending_autoraise_frame);
9193 pending_autoraise_frame = 0;
9194 }
9195
9196 #if !TARGET_API_MAC_CARBON
9197 check_alarm (); /* simulate the handling of a SIGALRM */
9198 #endif
9199
9200 UNBLOCK_INPUT;
9201 return count;
9202 }
9203
9204
9205 /* Need to override CodeWarrior's input function so no conversion is
9206 done on newlines Otherwise compiled functions in .elc files will be
9207 read incorrectly. Defined in ...:MSL C:MSL
9208 Common:Source:buffer_io.c. */
9209 #ifdef __MWERKS__
9210 void
9211 __convert_to_newlines (unsigned char * p, size_t * n)
9212 {
9213 #pragma unused(p,n)
9214 }
9215
9216 void
9217 __convert_from_newlines (unsigned char * p, size_t * n)
9218 {
9219 #pragma unused(p,n)
9220 }
9221 #endif
9222
9223 #ifdef MAC_OS8
9224 void
9225 make_mac_terminal_frame (struct frame *f)
9226 {
9227 Lisp_Object frame;
9228 Rect r;
9229
9230 XSETFRAME (frame, f);
9231
9232 f->output_method = output_mac;
9233 f->output_data.mac = (struct mac_output *)
9234 xmalloc (sizeof (struct mac_output));
9235 bzero (f->output_data.mac, sizeof (struct mac_output));
9236
9237 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
9238
9239 FRAME_COLS (f) = 96;
9240 FRAME_LINES (f) = 4;
9241
9242 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
9243 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
9244
9245 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
9246
9247 f->output_data.mac->cursor_pixel = 0;
9248 f->output_data.mac->border_pixel = 0x00ff00;
9249 f->output_data.mac->mouse_pixel = 0xff00ff;
9250 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
9251
9252 f->output_data.mac->text_cursor = GetCursor (iBeamCursor);
9253 f->output_data.mac->nontext_cursor = &arrow_cursor;
9254 f->output_data.mac->modeline_cursor = &arrow_cursor;
9255 f->output_data.mac->hand_cursor = &arrow_cursor;
9256 f->output_data.mac->hourglass_cursor = GetCursor (watchCursor);
9257 f->output_data.mac->horizontal_drag_cursor = &arrow_cursor;
9258
9259 FRAME_FONTSET (f) = -1;
9260 f->output_data.mac->explicit_parent = 0;
9261 f->left_pos = 8;
9262 f->top_pos = 32;
9263 f->border_width = 0;
9264
9265 f->internal_border_width = 0;
9266
9267 f->auto_raise = 1;
9268 f->auto_lower = 1;
9269
9270 f->new_text_cols = 0;
9271 f->new_text_lines = 0;
9272
9273 SetRect (&r, f->left_pos, f->top_pos,
9274 f->left_pos + FRAME_PIXEL_WIDTH (f),
9275 f->top_pos + FRAME_PIXEL_HEIGHT (f));
9276
9277 BLOCK_INPUT;
9278
9279 if (!(FRAME_MAC_WINDOW (f) =
9280 NewCWindow (NULL, &r, "\p", true, dBoxProc,
9281 (WindowPtr) -1, 1, (long) f->output_data.mac)))
9282 abort ();
9283 /* so that update events can find this mac_output struct */
9284 f->output_data.mac->mFP = f; /* point back to emacs frame */
9285
9286 UNBLOCK_INPUT;
9287
9288 x_make_gc (f);
9289
9290 /* Need to be initialized for unshow_buffer in window.c. */
9291 selected_window = f->selected_window;
9292
9293 Fmodify_frame_parameters (frame,
9294 Fcons (Fcons (Qfont,
9295 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
9296 Fmodify_frame_parameters (frame,
9297 Fcons (Fcons (Qforeground_color,
9298 build_string ("black")), Qnil));
9299 Fmodify_frame_parameters (frame,
9300 Fcons (Fcons (Qbackground_color,
9301 build_string ("white")), Qnil));
9302 }
9303 #endif
9304
9305 \f
9306 /***********************************************************************
9307 Initialization
9308 ***********************************************************************/
9309
9310 int mac_initialized = 0;
9311
9312 void
9313 mac_initialize_display_info ()
9314 {
9315 struct mac_display_info *dpyinfo = &one_mac_display_info;
9316 GDHandle main_device_handle;
9317
9318 bzero (dpyinfo, sizeof (*dpyinfo));
9319
9320 #ifdef MAC_OSX
9321 dpyinfo->mac_id_name
9322 = (char *) xmalloc (SCHARS (Vinvocation_name)
9323 + SCHARS (Vsystem_name)
9324 + 2);
9325 sprintf (dpyinfo->mac_id_name, "%s@%s",
9326 SDATA (Vinvocation_name), SDATA (Vsystem_name));
9327 #else
9328 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
9329 strcpy (dpyinfo->mac_id_name, "Mac Display");
9330 #endif
9331
9332 main_device_handle = LMGetMainDevice();
9333
9334 dpyinfo->reference_count = 0;
9335 dpyinfo->resx = 75.0;
9336 dpyinfo->resy = 75.0;
9337 dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
9338 #ifdef MAC_OSX
9339 /* HasDepth returns true if it is possible to have a 32 bit display,
9340 but this may not be what is actually used. Mac OSX can do better.
9341 CGMainDisplayID is only available on OSX 10.2 and higher, but the
9342 header for CGGetActiveDisplayList says that the first display returned
9343 is the active one, so we use that. */
9344 {
9345 CGDirectDisplayID disp_id[1];
9346 CGDisplayCount disp_count;
9347 CGDisplayErr error_code;
9348
9349 error_code = CGGetActiveDisplayList (1, disp_id, &disp_count);
9350 if (error_code != 0)
9351 error ("No display found, CGGetActiveDisplayList error %d", error_code);
9352
9353 dpyinfo->n_planes = CGDisplayBitsPerPixel (disp_id[0]);
9354 }
9355 #else
9356 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
9357 if (HasDepth (main_device_handle, dpyinfo->n_planes,
9358 gdDevType, dpyinfo->color_p))
9359 break;
9360 #endif
9361 dpyinfo->height = (**main_device_handle).gdRect.bottom;
9362 dpyinfo->width = (**main_device_handle).gdRect.right;
9363 dpyinfo->grabbed = 0;
9364 dpyinfo->root_window = NULL;
9365 dpyinfo->image_cache = make_image_cache ();
9366
9367 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
9368 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
9369 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
9370 dpyinfo->mouse_face_window = Qnil;
9371 dpyinfo->mouse_face_overlay = Qnil;
9372 dpyinfo->mouse_face_hidden = 0;
9373 }
9374
9375 /* Create an xrdb-style database of resources to supercede registry settings.
9376 The database is just a concatenation of C strings, finished by an additional
9377 \0. The string are submitted to some basic normalization, so
9378
9379 [ *]option[ *]:[ *]value...
9380
9381 becomes
9382
9383 option:value...
9384
9385 but any whitespace following value is not removed. */
9386
9387 static char *
9388 mac_make_rdb (xrm_option)
9389 char *xrm_option;
9390 {
9391 char *buffer = xmalloc (strlen (xrm_option) + 2);
9392 char *current = buffer;
9393 char ch;
9394 int in_option = 1;
9395 int before_value = 0;
9396
9397 do {
9398 ch = *xrm_option++;
9399
9400 if (ch == '\n')
9401 {
9402 *current++ = '\0';
9403 in_option = 1;
9404 before_value = 0;
9405 }
9406 else if (ch != ' ')
9407 {
9408 *current++ = ch;
9409 if (in_option && (ch == ':'))
9410 {
9411 in_option = 0;
9412 before_value = 1;
9413 }
9414 else if (before_value)
9415 {
9416 before_value = 0;
9417 }
9418 }
9419 else if (!(in_option || before_value))
9420 {
9421 *current++ = ch;
9422 }
9423 } while (ch);
9424
9425 *current = '\0';
9426
9427 return buffer;
9428 }
9429
9430 struct mac_display_info *
9431 mac_term_init (display_name, xrm_option, resource_name)
9432 Lisp_Object display_name;
9433 char *xrm_option;
9434 char *resource_name;
9435 {
9436 struct mac_display_info *dpyinfo;
9437
9438 BLOCK_INPUT;
9439
9440 if (!mac_initialized)
9441 {
9442 mac_initialize ();
9443 mac_initialized = 1;
9444 }
9445
9446 if (x_display_list)
9447 error ("Sorry, this version can only handle one display");
9448
9449 mac_initialize_display_info ();
9450
9451 dpyinfo = &one_mac_display_info;
9452
9453 dpyinfo->xrdb = xrm_option ? mac_make_rdb (xrm_option) : NULL;
9454
9455 /* Put this display on the chain. */
9456 dpyinfo->next = x_display_list;
9457 x_display_list = dpyinfo;
9458
9459 /* Put it on x_display_name_list. */
9460 x_display_name_list = Fcons (Fcons (display_name, Qnil),
9461 x_display_name_list);
9462 dpyinfo->name_list_element = XCAR (x_display_name_list);
9463
9464 UNBLOCK_INPUT;
9465
9466 return dpyinfo;
9467 }
9468 /* Get rid of display DPYINFO, assuming all frames are already gone. */
9469
9470 void
9471 x_delete_display (dpyinfo)
9472 struct mac_display_info *dpyinfo;
9473 {
9474 int i;
9475
9476 /* Discard this display from x_display_name_list and x_display_list.
9477 We can't use Fdelq because that can quit. */
9478 if (! NILP (x_display_name_list)
9479 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element))
9480 x_display_name_list = XCDR (x_display_name_list);
9481 else
9482 {
9483 Lisp_Object tail;
9484
9485 tail = x_display_name_list;
9486 while (CONSP (tail) && CONSP (XCDR (tail)))
9487 {
9488 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element))
9489 {
9490 XSETCDR (tail, XCDR (XCDR (tail)));
9491 break;
9492 }
9493 tail = XCDR (tail);
9494 }
9495 }
9496
9497 if (x_display_list == dpyinfo)
9498 x_display_list = dpyinfo->next;
9499 else
9500 {
9501 struct x_display_info *tail;
9502
9503 for (tail = x_display_list; tail; tail = tail->next)
9504 if (tail->next == dpyinfo)
9505 tail->next = tail->next->next;
9506 }
9507
9508 /* Free the font names in the font table. */
9509 for (i = 0; i < dpyinfo->n_fonts; i++)
9510 if (dpyinfo->font_table[i].name)
9511 {
9512 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name)
9513 xfree (dpyinfo->font_table[i].full_name);
9514 xfree (dpyinfo->font_table[i].name);
9515 }
9516
9517 if (dpyinfo->font_table->font_encoder)
9518 xfree (dpyinfo->font_table->font_encoder);
9519
9520 xfree (dpyinfo->font_table);
9521 xfree (dpyinfo->mac_id_name);
9522
9523 if (x_display_list == 0)
9524 {
9525 mac_clear_font_name_table ();
9526 bzero (dpyinfo, sizeof (*dpyinfo));
9527 }
9528 }
9529
9530 \f
9531 #ifdef MAC_OSX
9532 void
9533 mac_check_bundle()
9534 {
9535 extern int inhibit_window_system;
9536 extern int noninteractive;
9537 CFBundleRef appsBundle;
9538 pid_t child;
9539
9540 /* No need to test if already -nw*/
9541 if (inhibit_window_system || noninteractive)
9542 return;
9543
9544 appsBundle = CFBundleGetMainBundle();
9545 if (appsBundle != NULL)
9546 {
9547 CFStringRef cfBI = CFSTR("CFBundleIdentifier");
9548 CFTypeRef res = CFBundleGetValueForInfoDictionaryKey(appsBundle, cfBI);
9549 /* We found the bundle identifier, now we know we are valid. */
9550 if (res != NULL)
9551 {
9552 CFRelease(res);
9553 return;
9554 }
9555 }
9556 /* MAC_TODO: Have this start the bundled executable */
9557
9558 /* For now, prevent the fatal error by bringing it up in the terminal */
9559 inhibit_window_system = 1;
9560 }
9561
9562 void
9563 MakeMeTheFrontProcess ()
9564 {
9565 ProcessSerialNumber psn;
9566 OSErr err;
9567
9568 err = GetCurrentProcess (&psn);
9569 if (err == noErr)
9570 (void) SetFrontProcess (&psn);
9571 }
9572
9573 /***** Code to handle C-g testing *****/
9574
9575 /* Contains the Mac modifier formed from quit_char */
9576 static mac_quit_char_modifiers = 0;
9577 static mac_quit_char_keycode;
9578 extern int quit_char;
9579
9580 static void
9581 mac_determine_quit_char_modifiers()
9582 {
9583 /* Todo: Determine modifiers from quit_char. */
9584 UInt32 qc_modifiers = ctrl_modifier;
9585
9586 /* Map modifiers */
9587 mac_quit_char_modifiers = 0;
9588 if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= macCtrlKey;
9589 if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey;
9590 if (qc_modifiers & meta_modifier) mac_quit_char_modifiers |= macMetaKey;
9591 if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= macAltKey;
9592 }
9593
9594 static void
9595 init_quit_char_handler ()
9596 {
9597 /* TODO: Let this support keys other the 'g' */
9598 mac_quit_char_keycode = 5;
9599 /* Look at <architecture/adb_kb_map.h> for details */
9600 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
9601
9602 mac_determine_quit_char_modifiers();
9603 }
9604
9605 static Boolean
9606 quit_char_comp (EventRef inEvent, void *inCompData)
9607 {
9608 if (GetEventClass(inEvent) != kEventClassKeyboard)
9609 return false;
9610 if (GetEventKind(inEvent) != kEventRawKeyDown)
9611 return false;
9612 {
9613 UInt32 keyCode;
9614 UInt32 keyModifiers;
9615 GetEventParameter(inEvent, kEventParamKeyCode,
9616 typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
9617 if (keyCode != mac_quit_char_keycode)
9618 return false;
9619 GetEventParameter(inEvent, kEventParamKeyModifiers,
9620 typeUInt32, NULL, sizeof(UInt32), NULL, &keyModifiers);
9621 if (keyModifiers != mac_quit_char_modifiers)
9622 return false;
9623 }
9624 return true;
9625 }
9626
9627 void
9628 mac_check_for_quit_char ()
9629 {
9630 EventRef event;
9631 static EMACS_TIME last_check_time = { 0, 0 };
9632 static EMACS_TIME one_second = { 1, 0 };
9633 EMACS_TIME now, t;
9634
9635 /* If windows are not initialized, return immediately (keep it bouncin'). */
9636 if (!mac_quit_char_modifiers)
9637 return;
9638
9639 /* Don't check if last check is less than a second ago. */
9640 EMACS_GET_TIME (now);
9641 EMACS_SUB_TIME (t, now, last_check_time);
9642 if (EMACS_TIME_LT (t, one_second))
9643 return;
9644 last_check_time = now;
9645
9646 /* Redetermine modifiers because they are based on lisp variables */
9647 mac_determine_quit_char_modifiers ();
9648
9649 /* Fill the queue with events */
9650 BLOCK_INPUT;
9651 ReceiveNextEvent (0, NULL, kEventDurationNoWait, false, &event);
9652 event = FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp,
9653 NULL);
9654 UNBLOCK_INPUT;
9655 if (event)
9656 {
9657 struct input_event e;
9658
9659 /* Use an input_event to emulate what the interrupt handler does. */
9660 EVENT_INIT (e);
9661 e.kind = ASCII_KEYSTROKE_EVENT;
9662 e.code = quit_char;
9663 e.arg = Qnil;
9664 e.modifiers = NULL;
9665 e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60);
9666 XSETFRAME (e.frame_or_window, mac_window_to_frame (front_emacs_window ()));
9667 /* Remove event from queue to prevent looping. */
9668 RemoveEventFromQueue (GetMainEventQueue (), event);
9669 ReleaseEvent (event);
9670 kbd_buffer_store_event (&e);
9671 }
9672 }
9673
9674 #endif /* MAC_OSX */
9675
9676 /* Set up use of X before we make the first connection. */
9677
9678 extern frame_parm_handler mac_frame_parm_handlers[];
9679
9680 static struct redisplay_interface x_redisplay_interface =
9681 {
9682 mac_frame_parm_handlers,
9683 x_produce_glyphs,
9684 x_write_glyphs,
9685 x_insert_glyphs,
9686 x_clear_end_of_line,
9687 x_scroll_run,
9688 x_after_update_window_line,
9689 x_update_window_begin,
9690 x_update_window_end,
9691 x_cursor_to,
9692 x_flush,
9693 0, /* flush_display_optional */
9694 x_clear_window_mouse_face,
9695 x_get_glyph_overhangs,
9696 x_fix_overlapping_area,
9697 x_draw_fringe_bitmap,
9698 0, /* define_fringe_bitmap */
9699 0, /* destroy_fringe_bitmap */
9700 mac_per_char_metric,
9701 mac_encode_char,
9702 NULL, /* mac_compute_glyph_string_overhangs */
9703 x_draw_glyph_string,
9704 mac_define_frame_cursor,
9705 mac_clear_frame_area,
9706 mac_draw_window_cursor,
9707 mac_draw_vertical_window_border,
9708 mac_shift_glyphs_for_insert
9709 };
9710
9711 void
9712 mac_initialize ()
9713 {
9714 rif = &x_redisplay_interface;
9715
9716 clear_frame_hook = x_clear_frame;
9717 ins_del_lines_hook = x_ins_del_lines;
9718 delete_glyphs_hook = x_delete_glyphs;
9719 ring_bell_hook = XTring_bell;
9720 reset_terminal_modes_hook = XTreset_terminal_modes;
9721 set_terminal_modes_hook = XTset_terminal_modes;
9722 update_begin_hook = x_update_begin;
9723 update_end_hook = x_update_end;
9724 set_terminal_window_hook = XTset_terminal_window;
9725 read_socket_hook = XTread_socket;
9726 frame_up_to_date_hook = XTframe_up_to_date;
9727 mouse_position_hook = XTmouse_position;
9728 frame_rehighlight_hook = XTframe_rehighlight;
9729 frame_raise_lower_hook = XTframe_raise_lower;
9730
9731 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
9732 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
9733 redeem_scroll_bar_hook = XTredeem_scroll_bar;
9734 judge_scroll_bars_hook = XTjudge_scroll_bars;
9735
9736 scroll_region_ok = 1; /* we'll scroll partial frames */
9737 char_ins_del_ok = 1;
9738 line_ins_del_ok = 1; /* we'll just blt 'em */
9739 fast_clear_end_of_line = 1; /* X does this well */
9740 memory_below_frame = 0; /* we don't remember what scrolls
9741 off the bottom */
9742 baud_rate = 19200;
9743
9744 x_noop_count = 0;
9745 last_tool_bar_item = -1;
9746 any_help_event_p = 0;
9747
9748 /* Try to use interrupt input; if we can't, then start polling. */
9749 Fset_input_mode (Qt, Qnil, Qt, Qnil);
9750
9751 #ifdef USE_X_TOOLKIT
9752 XtToolkitInitialize ();
9753 Xt_app_con = XtCreateApplicationContext ();
9754 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
9755
9756 /* Install an asynchronous timer that processes Xt timeout events
9757 every 0.1s. This is necessary because some widget sets use
9758 timeouts internally, for example the LessTif menu bar, or the
9759 Xaw3d scroll bar. When Xt timouts aren't processed, these
9760 widgets don't behave normally. */
9761 {
9762 EMACS_TIME interval;
9763 EMACS_SET_SECS_USECS (interval, 0, 100000);
9764 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
9765 }
9766 #endif
9767
9768 #if USE_TOOLKIT_SCROLL_BARS
9769 xaw3d_arrow_scroll = False;
9770 xaw3d_pick_top = True;
9771 #endif
9772
9773 #if 0
9774 /* Note that there is no real way portable across R3/R4 to get the
9775 original error handler. */
9776 XSetErrorHandler (x_error_handler);
9777 XSetIOErrorHandler (x_io_error_quitter);
9778
9779 /* Disable Window Change signals; they are handled by X events. */
9780 #ifdef SIGWINCH
9781 signal (SIGWINCH, SIG_DFL);
9782 #endif /* ! defined (SIGWINCH) */
9783
9784 signal (SIGPIPE, x_connection_signal);
9785 #endif
9786
9787 BLOCK_INPUT;
9788
9789 #if TARGET_API_MAC_CARBON
9790 init_required_apple_events ();
9791
9792 #if USE_CARBON_EVENTS
9793 init_service_handler ();
9794
9795 init_quit_char_handler ();
9796 #endif
9797
9798 DisableMenuCommand (NULL, kHICommandQuit);
9799
9800 if (!inhibit_window_system)
9801 MakeMeTheFrontProcess ();
9802 #endif
9803 UNBLOCK_INPUT;
9804 }
9805
9806
9807 void
9808 syms_of_macterm ()
9809 {
9810 #if 0
9811 staticpro (&x_error_message_string);
9812 x_error_message_string = Qnil;
9813 #endif
9814
9815 Qmodifier_value = intern ("modifier-value");
9816 Qalt = intern ("alt");
9817 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
9818 Qhyper = intern ("hyper");
9819 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
9820 Qsuper = intern ("super");
9821 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
9822
9823 #ifdef MAC_OSX
9824 Fprovide (intern ("mac-carbon"), Qnil);
9825 #endif
9826
9827 staticpro (&Qreverse);
9828 Qreverse = intern ("reverse");
9829
9830 staticpro (&x_display_name_list);
9831 x_display_name_list = Qnil;
9832
9833 staticpro (&last_mouse_scroll_bar);
9834 last_mouse_scroll_bar = Qnil;
9835
9836 staticpro (&Qvendor_specific_keysyms);
9837 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
9838
9839 staticpro (&last_mouse_press_frame);
9840 last_mouse_press_frame = Qnil;
9841
9842 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
9843 staticpro (&Qmac_ready_for_drag_n_drop);
9844
9845 Qbig5 = intern ("big5");
9846 staticpro (&Qbig5);
9847
9848 Qcn_gb = intern ("cn-gb");
9849 staticpro (&Qcn_gb);
9850
9851 Qsjis = intern ("sjis");
9852 staticpro (&Qsjis);
9853
9854 Qeuc_kr = intern ("euc-kr");
9855 staticpro (&Qeuc_kr);
9856
9857 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
9858 doc: /* *Non-nil means autoselect window with mouse pointer. */);
9859 x_autoselect_window_p = 0;
9860
9861 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
9862 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
9863 Vx_toolkit_scroll_bars = Qt;
9864
9865 DEFVAR_BOOL ("x-use-underline-position-properties",
9866 &x_use_underline_position_properties,
9867 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
9868 nil means ignore them. If you encounter fonts with bogus
9869 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9870 to 4.1, set this to nil. */);
9871 x_use_underline_position_properties = 0;
9872
9873 staticpro (&last_mouse_motion_frame);
9874 last_mouse_motion_frame = Qnil;
9875
9876 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
9877 doc: /* Non-nil means that the command key is used as the Emacs meta key.
9878 Otherwise the option key is used. */);
9879 Vmac_command_key_is_meta = Qt;
9880
9881 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier,
9882 doc: /* Modifier to use for the Mac alt/option key. The value can
9883 be alt, hyper, or super for the respective modifier. If the value is
9884 nil then the key will act as the normal Mac option modifier. */);
9885 Vmac_option_modifier = Qnil;
9886
9887 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
9888 doc: /* Non-nil means that the control and meta keys are reversed. This is
9889 useful for non-standard keyboard layouts. */);
9890 Vmac_reverse_ctrl_meta = Qnil;
9891
9892 DEFVAR_LISP ("mac-emulate-three-button-mouse",
9893 &Vmac_emulate_three_button_mouse,
9894 doc: /* t means that when the option-key is held down while pressing the
9895 mouse button, the click will register as mouse-2 and while the
9896 command-key is held down, the click will register as mouse-3.
9897 'reverse means that the the option-key will register for mouse-3
9898 and the command-key will register for mouse-2. nil means that
9899 not emulation should be done and the modifiers should be placed
9900 on the mouse-1 event. */);
9901 Vmac_emulate_three_button_mouse = Qnil;
9902
9903 #if USE_CARBON_EVENTS
9904 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
9905 doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
9906 the right click will be mouse-3.
9907 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
9908 Vmac_wheel_button_is_mouse_2 = Qt;
9909
9910 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
9911 doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
9912 Toolbox for processing before Emacs sees it. */);
9913 Vmac_pass_command_to_system = Qt;
9914
9915 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
9916 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
9917 Toolbox for processing before Emacs sees it. */);
9918 Vmac_pass_control_to_system = Qt;
9919
9920 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
9921 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
9922 Toolbox for processing before Emacs sees it. */);
9923 Vmac_pass_control_to_system = Qt;
9924 #endif
9925
9926 DEFVAR_LISP ("mac-allow-anti-aliasing", &Vmac_use_core_graphics,
9927 doc: /* If non-nil, the text will be rendered using Core Graphics text rendering which may anti-alias the text. */);
9928 Vmac_use_core_graphics = Qnil;
9929
9930 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
9931 doc: /* One of the Text Encoding Base constant values defined in the
9932 Basic Text Constants section of Inside Macintosh - Text Encoding
9933 Conversion Manager. Its value determines the encoding characters
9934 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
9935 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
9936 its default value, no conversion takes place. If it is set to
9937 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
9938 characters typed on Mac keyboard are first converted into the
9939 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
9940 passed to Emacs. Together with Emacs's set-keyboard-coding-system
9941 command, this enables the Mac keyboard to be used to enter non-ASCII
9942 characters directly. */);
9943 mac_keyboard_text_encoding = kTextEncodingMacRoman;
9944 }
9945
9946 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
9947 (do not change this comment) */