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