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