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