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