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