]> code.delx.au - gnu-emacs/blob - src/macterm.c
macterm.c (x_raise_frame): Add BLOCK_INPUT around SelectWindow
[gnu-emacs] / 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 #include <Windows.h>
54 #if defined (__MRC__) || (__MSL__ >= 0x6000)
55 #include <ControlDefinitions.h>
56 #endif
57
58 #if __profile__
59 #include <profiler.h>
60 #endif
61 #endif /* not MAC_OSX */
62
63 #include "systty.h"
64 #include "systime.h"
65 #include "atimer.h"
66 #include "keymap.h"
67
68 #include <ctype.h>
69 #include <errno.h>
70 #include <setjmp.h>
71 #include <sys/stat.h>
72
73 #include "keyboard.h"
74 #include "frame.h"
75 #include "dispextern.h"
76 #include "fontset.h"
77 #include "termhooks.h"
78 #include "termopts.h"
79 #include "termchar.h"
80 #include "gnu.h"
81 #include "disptab.h"
82 #include "buffer.h"
83 #include "window.h"
84 #include "intervals.h"
85 #include "composite.h"
86 #include "coding.h"
87
88 /* Set of macros that handle mapping of Mac modifier keys to emacs. */
89 #define macCtrlKey (NILP (Vmac_reverse_ctrl_meta) ? controlKey : \
90 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey))
91 #define macShiftKey (shiftKey)
92 #define macMetaKey (NILP (Vmac_reverse_ctrl_meta) ? \
93 (NILP (Vmac_command_key_is_meta) ? optionKey : cmdKey) \
94 : controlKey)
95 #define macAltKey (NILP (Vmac_command_key_is_meta) ? cmdKey : optionKey)
96
97 \f
98
99 /* Non-nil means Emacs uses toolkit scroll bars. */
100
101 Lisp_Object Vx_toolkit_scroll_bars;
102
103 /* Non-zero means that a HELP_EVENT has been generated since Emacs
104 start. */
105
106 static int any_help_event_p;
107
108 /* Non-zero means autoselect window with the mouse cursor. */
109
110 int x_autoselect_window_p;
111
112 /* Non-zero means make use of UNDERLINE_POSITION font properties. */
113
114 int x_use_underline_position_properties;
115
116 /* Non-zero means draw block and hollow cursor as wide as the glyph
117 under it. For example, if a block cursor is over a tab, it will be
118 drawn as wide as that tab on the display. */
119
120
121 /* This is a chain of structures for all the X displays currently in
122 use. */
123
124 struct x_display_info *x_display_list;
125
126 /* This is a list of cons cells, each of the form (NAME
127 . FONT-LIST-CACHE), one for each element of x_display_list and in
128 the same order. NAME is the name of the frame. FONT-LIST-CACHE
129 records previous values returned by x-list-fonts. */
130
131 Lisp_Object x_display_name_list;
132
133 /* This is display since Mac does not support multiple ones. */
134 struct mac_display_info one_mac_display_info;
135
136 /* Frame being updated by update_frame. This is declared in term.c.
137 This is set by update_begin and looked at by all the XT functions.
138 It is zero while not inside an update. In that case, the XT
139 functions assume that `selected_frame' is the frame to apply to. */
140
141 extern struct frame *updating_frame;
142
143 extern int waiting_for_input;
144
145 /* This is a frame waiting to be auto-raised, within XTread_socket. */
146
147 struct frame *pending_autoraise_frame;
148
149 /* Non-zero means user is interacting with a toolkit scroll bar. */
150
151 static int toolkit_scroll_bar_interaction;
152
153 /* Mouse movement.
154
155 Formerly, we used PointerMotionHintMask (in standard_event_mask)
156 so that we would have to call XQueryPointer after each MotionNotify
157 event to ask for another such event. However, this made mouse tracking
158 slow, and there was a bug that made it eventually stop.
159
160 Simply asking for MotionNotify all the time seems to work better.
161
162 In order to avoid asking for motion events and then throwing most
163 of them away or busy-polling the server for mouse positions, we ask
164 the server for pointer motion hints. This means that we get only
165 one event per group of mouse movements. "Groups" are delimited by
166 other kinds of events (focus changes and button clicks, for
167 example), or by XQueryPointer calls; when one of these happens, we
168 get another MotionNotify event the next time the mouse moves. This
169 is at least as efficient as getting motion events when mouse
170 tracking is on, and I suspect only negligibly worse when tracking
171 is off. */
172
173 /* Where the mouse was last time we reported a mouse event. */
174
175 static Rect last_mouse_glyph;
176 static Lisp_Object last_mouse_press_frame;
177
178 /* The scroll bar in which the last X motion event occurred.
179
180 If the last X motion event occurred in a scroll bar, we set this so
181 XTmouse_position can know whether to report a scroll bar motion or
182 an ordinary motion.
183
184 If the last X motion event didn't occur in a scroll bar, we set
185 this to Qnil, to tell XTmouse_position to return an ordinary motion
186 event. */
187
188 static Lisp_Object last_mouse_scroll_bar;
189
190 /* This is a hack. We would really prefer that XTmouse_position would
191 return the time associated with the position it returns, but there
192 doesn't seem to be any way to wrest the time-stamp from the server
193 along with the position query. So, we just keep track of the time
194 of the last movement we received, and return that in hopes that
195 it's somewhat accurate. */
196
197 static Time last_mouse_movement_time;
198
199 struct scroll_bar *tracked_scroll_bar = NULL;
200
201 /* Incremented by XTread_socket whenever it really tries to read
202 events. */
203
204 #ifdef __STDC__
205 static int volatile input_signal_count;
206 #else
207 static int input_signal_count;
208 #endif
209
210 /* Used locally within XTread_socket. */
211
212 static int x_noop_count;
213
214 /* Initial values of argv and argc. */
215
216 extern char **initial_argv;
217 extern int initial_argc;
218
219 extern Lisp_Object Vcommand_line_args, Vsystem_name;
220
221 /* Tells if a window manager is present or not. */
222
223 extern Lisp_Object Vx_no_window_manager;
224
225 extern int errno;
226
227 /* A mask of extra modifier bits to put into every keyboard char. */
228
229 extern int extra_keyboard_modifiers;
230
231 static Lisp_Object Qvendor_specific_keysyms;
232
233 #if 0
234 extern XrmDatabase x_load_resources P_ ((Display *, char *, char *, char *));
235 #endif
236
237 extern int inhibit_window_system;
238
239 #if __MRC__
240 QDGlobals qd; /* QuickDraw global information structure. */
241 #endif
242
243
244 struct frame * x_window_to_frame (struct mac_display_info *, WindowPtr);
245 struct mac_display_info *mac_display_info_for_display (Display *);
246 static void x_update_window_end P_ ((struct window *, int, int));
247 static void mac_handle_tool_bar_click P_ ((struct frame *, EventRecord *));
248 static int x_io_error_quitter P_ ((Display *));
249 int x_catch_errors P_ ((Display *));
250 void x_uncatch_errors P_ ((Display *, int));
251 void x_lower_frame P_ ((struct frame *));
252 void x_scroll_bar_clear P_ ((struct frame *));
253 int x_had_errors_p P_ ((Display *));
254 void x_wm_set_size_hint P_ ((struct frame *, long, int));
255 void x_raise_frame P_ ((struct frame *));
256 void x_set_window_size P_ ((struct frame *, int, int, int));
257 void x_wm_set_window_state P_ ((struct frame *, int));
258 void x_wm_set_icon_pixmap P_ ((struct frame *, int));
259 void mac_initialize P_ ((void));
260 static void x_font_min_bounds P_ ((XFontStruct *, int *, int *));
261 static int x_compute_min_glyph_bounds P_ ((struct frame *));
262 static void x_update_end P_ ((struct frame *));
263 static void XTframe_up_to_date P_ ((struct frame *));
264 static void XTreassert_line_highlight P_ ((int, int));
265 static void x_change_line_highlight P_ ((int, int, int, int));
266 static void XTset_terminal_modes P_ ((void));
267 static void XTreset_terminal_modes P_ ((void));
268 static void x_clear_frame P_ ((void));
269 static void frame_highlight P_ ((struct frame *));
270 static void frame_unhighlight P_ ((struct frame *));
271 static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *));
272 static void XTframe_rehighlight P_ ((struct frame *));
273 static void x_frame_rehighlight P_ ((struct x_display_info *));
274 static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *));
275 static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int,
276 enum text_cursor_kinds));
277
278 static void x_clip_to_row P_ ((struct window *, struct glyph_row *, GC));
279 static void x_flush P_ ((struct frame *f));
280 static void x_update_begin P_ ((struct frame *));
281 static void x_update_window_begin P_ ((struct window *));
282 static void x_after_update_window_line P_ ((struct glyph_row *));
283
284 void activate_scroll_bars (FRAME_PTR);
285 void deactivate_scroll_bars (FRAME_PTR);
286
287 static int is_emacs_window (WindowPtr);
288
289 int x_bitmap_icon (struct frame *, Lisp_Object);
290 void x_make_frame_visible (struct frame *);
291
292 extern void window_scroll (Lisp_Object, int, int, int);
293
294 /* Defined in macmenu.h. */
295 extern void menubar_selection_callback (FRAME_PTR, int);
296 extern void set_frame_menubar (FRAME_PTR, int, int);
297
298 /* X display function emulation */
299
300 void
301 XFreePixmap (display, pixmap)
302 Display *display; /* not used */
303 Pixmap pixmap;
304 {
305 DisposeGWorld (pixmap);
306 }
307
308
309 /* Set foreground color for subsequent QuickDraw commands. Assume
310 graphic port has already been set. */
311
312 static void
313 mac_set_forecolor (unsigned long color)
314 {
315 RGBColor fg_color;
316
317 fg_color.red = RED16_FROM_ULONG (color);
318 fg_color.green = GREEN16_FROM_ULONG (color);
319 fg_color.blue = BLUE16_FROM_ULONG (color);
320
321 RGBForeColor (&fg_color);
322 }
323
324
325 /* Set background color for subsequent QuickDraw commands. Assume
326 graphic port has already been set. */
327
328 static void
329 mac_set_backcolor (unsigned long color)
330 {
331 RGBColor bg_color;
332
333 bg_color.red = RED16_FROM_ULONG (color);
334 bg_color.green = GREEN16_FROM_ULONG (color);
335 bg_color.blue = BLUE16_FROM_ULONG (color);
336
337 RGBBackColor (&bg_color);
338 }
339
340 /* Set foreground and background color for subsequent QuickDraw
341 commands. Assume that the graphic port has already been set. */
342
343 static void
344 mac_set_colors (GC gc)
345 {
346 mac_set_forecolor (gc->foreground);
347 mac_set_backcolor (gc->background);
348 }
349
350 /* Mac version of XDrawLine. */
351
352 static void
353 XDrawLine (display, w, gc, x1, y1, x2, y2)
354 Display *display;
355 WindowPtr w;
356 GC gc;
357 int x1, y1, x2, y2;
358 {
359 SetPortWindowPort (w);
360
361 mac_set_colors (gc);
362
363 MoveTo (x1, y1);
364 LineTo (x2, y2);
365 }
366
367 void
368 mac_draw_line_to_pixmap (display, p, gc, x1, y1, x2, y2)
369 Display *display;
370 Pixmap p;
371 GC gc;
372 int x1, y1, x2, y2;
373 {
374 CGrafPtr old_port;
375 GDHandle old_gdh;
376
377 GetGWorld (&old_port, &old_gdh);
378 SetGWorld (p, NULL);
379
380 mac_set_colors (gc);
381
382 LockPixels (GetGWorldPixMap (p));
383 MoveTo (x1, y1);
384 LineTo (x2, y2);
385 UnlockPixels (GetGWorldPixMap (p));
386
387 SetGWorld (old_port, old_gdh);
388 }
389
390 /* Mac version of XClearArea. */
391
392 void
393 XClearArea (display, w, x, y, width, height, exposures)
394 Display *display;
395 WindowPtr w;
396 int x, y;
397 unsigned int width, height;
398 int exposures;
399 {
400 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
401 Rect r;
402 XGCValues xgc;
403
404 xgc.foreground = mwp->x_compatible.foreground_pixel;
405 xgc.background = mwp->x_compatible.background_pixel;
406
407 SetPortWindowPort (w);
408
409 mac_set_colors (&xgc);
410 SetRect (&r, x, y, x + width, y + height);
411
412 EraseRect (&r);
413 }
414
415 /* Mac version of XClearWindow. */
416
417 static void
418 XClearWindow (display, w)
419 Display *display;
420 WindowPtr w;
421 {
422 struct mac_output *mwp = (mac_output *) GetWRefCon (w);
423 XGCValues xgc;
424
425 xgc.foreground = mwp->x_compatible.foreground_pixel;
426 xgc.background = mwp->x_compatible.background_pixel;
427
428 SetPortWindowPort (w);
429
430 mac_set_colors (&xgc);
431
432 #if TARGET_API_MAC_CARBON
433 {
434 Rect r;
435
436 GetWindowPortBounds (w, &r);
437 EraseRect (&r);
438 }
439 #else /* not TARGET_API_MAC_CARBON */
440 EraseRect (&(w->portRect));
441 #endif /* not TARGET_API_MAC_CARBON */
442 }
443
444
445 /* Mac replacement for XCopyArea. */
446
447 static void
448 mac_draw_bitmap (display, w, gc, x, y, width, height, bits, overlay_p)
449 Display *display;
450 WindowPtr w;
451 GC gc;
452 int x, y, width, height;
453 unsigned short *bits;
454 int overlay_p;
455 {
456 BitMap bitmap;
457 Rect r;
458
459 bitmap.rowBytes = sizeof(unsigned short);
460 bitmap.baseAddr = (char *)bits;
461 SetRect (&(bitmap.bounds), 0, 0, width, height);
462
463 SetPortWindowPort (w);
464
465 mac_set_colors (gc);
466 SetRect (&r, x, y, x + width, y + height);
467
468 #if TARGET_API_MAC_CARBON
469 LockPortBits (GetWindowPort (w));
470 CopyBits (&bitmap, GetPortBitMapForCopyBits (GetWindowPort (w)),
471 &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0);
472 UnlockPortBits (GetWindowPort (w));
473 #else /* not TARGET_API_MAC_CARBON */
474 CopyBits (&bitmap, &(w->portBits), &(bitmap.bounds), &r,
475 overlay_p ? srcOr : srcCopy, 0);
476 #endif /* not TARGET_API_MAC_CARBON */
477 }
478
479
480 /* Mac replacement for XSetClipRectangles. */
481
482 static void
483 mac_set_clip_rectangle (display, w, r)
484 Display *display;
485 WindowPtr w;
486 Rect *r;
487 {
488 SetPortWindowPort (w);
489
490 ClipRect (r);
491 }
492
493
494 /* Mac replacement for XSetClipMask. */
495
496 static void
497 mac_reset_clipping (display, w)
498 Display *display;
499 WindowPtr w;
500 {
501 Rect r;
502
503 SetPortWindowPort (w);
504
505 SetRect (&r, -32767, -32767, 32767, 32767);
506 ClipRect (&r);
507 }
508
509
510 /* XBM bits seem to be backward within bytes compared with how
511 Mac does things. */
512 static unsigned char
513 reflect_byte (orig)
514 unsigned char orig;
515 {
516 int i;
517 unsigned char reflected = 0x00;
518 for (i = 0; i < 8; i++)
519 {
520 if (orig & (0x01 << i))
521 reflected |= 0x80 >> i;
522 }
523 return reflected;
524 }
525
526
527 /* Mac replacement for XCreateBitmapFromBitmapData. */
528
529 static void
530 mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h)
531 BitMap *bitmap;
532 char *bits;
533 int w, h;
534 {
535 int i, j, w1;
536 char *p;
537
538 w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */
539 bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */
540 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h);
541 bzero (bitmap->baseAddr, bitmap->rowBytes * h);
542 for (i = 0; i < h; i++)
543 {
544 p = bitmap->baseAddr + i * bitmap->rowBytes;
545 for (j = 0; j < w1; j++)
546 *p++ = reflect_byte (*bits++);
547 }
548
549 SetRect (&(bitmap->bounds), 0, 0, w, h);
550 }
551
552
553 static void
554 mac_free_bitmap (bitmap)
555 BitMap *bitmap;
556 {
557 xfree (bitmap->baseAddr);
558 }
559
560
561 Pixmap
562 XCreatePixmap (display, w, width, height, depth)
563 Display *display; /* not used */
564 WindowPtr w;
565 unsigned int width, height;
566 unsigned int depth; /* not used */
567 {
568 Pixmap pixmap;
569 Rect r;
570 QDErr err;
571
572 SetPortWindowPort (w);
573
574 SetRect (&r, 0, 0, width, height);
575 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0);
576 if (err != noErr)
577 return NULL;
578 return pixmap;
579 }
580
581
582 Pixmap
583 XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth)
584 Display *display; /* not used */
585 WindowPtr w;
586 char *data;
587 unsigned int width, height;
588 unsigned long fg, bg;
589 unsigned int depth; /* not used */
590 {
591 Pixmap pixmap;
592 BitMap bitmap;
593 CGrafPtr old_port;
594 GDHandle old_gdh;
595
596 pixmap = XCreatePixmap (display, w, width, height, depth);
597 if (pixmap == NULL)
598 return NULL;
599
600 GetGWorld (&old_port, &old_gdh);
601 SetGWorld (pixmap, NULL);
602 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height);
603 mac_set_forecolor (fg);
604 mac_set_backcolor (bg);
605 LockPixels (GetGWorldPixMap (pixmap));
606 #if TARGET_API_MAC_CARBON
607 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap),
608 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
609 #else /* not TARGET_API_MAC_CARBON */
610 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits),
611 &bitmap.bounds, &bitmap.bounds, srcCopy, 0);
612 #endif /* not TARGET_API_MAC_CARBON */
613 UnlockPixels (GetGWorldPixMap (pixmap));
614 SetGWorld (old_port, old_gdh);
615 mac_free_bitmap (&bitmap);
616
617 return pixmap;
618 }
619
620
621 /* Mac replacement for XFillRectangle. */
622
623 static void
624 XFillRectangle (display, w, gc, x, y, width, height)
625 Display *display;
626 WindowPtr w;
627 GC gc;
628 int x, y;
629 unsigned int width, height;
630 {
631 Rect r;
632
633 SetPortWindowPort (w);
634
635 mac_set_colors (gc);
636 SetRect (&r, x, y, x + width, y + height);
637
638 PaintRect (&r); /* using foreground color of gc */
639 }
640
641
642 static void
643 mac_fill_rectangle_to_pixmap (display, p, gc, x, y, width, height)
644 Display *display;
645 Pixmap p;
646 GC gc;
647 int x, y;
648 unsigned int width, height;
649 {
650 CGrafPtr old_port;
651 GDHandle old_gdh;
652 Rect r;
653
654 GetGWorld (&old_port, &old_gdh);
655 SetGWorld (p, NULL);
656 mac_set_colors (gc);
657 SetRect (&r, x, y, x + width, y + height);
658
659 LockPixels (GetGWorldPixMap (p));
660 PaintRect (&r); /* using foreground color of gc */
661 UnlockPixels (GetGWorldPixMap (p));
662
663 SetGWorld (old_port, old_gdh);
664 }
665
666
667 /* Mac replacement for XDrawRectangle: dest is a window. */
668
669 static void
670 mac_draw_rectangle (display, w, gc, x, y, width, height)
671 Display *display;
672 WindowPtr w;
673 GC gc;
674 int x, y;
675 unsigned int width, height;
676 {
677 Rect r;
678
679 SetPortWindowPort (w);
680
681 mac_set_colors (gc);
682 SetRect (&r, x, y, x + width + 1, y + height + 1);
683
684 FrameRect (&r); /* using foreground color of gc */
685 }
686
687
688 /* Mac replacement for XDrawRectangle: dest is a Pixmap. */
689
690 static void
691 mac_draw_rectangle_to_pixmap (display, p, gc, x, y, width, height)
692 Display *display;
693 Pixmap p;
694 GC gc;
695 int x, y;
696 unsigned int width, height;
697 {
698 CGrafPtr old_port;
699 GDHandle old_gdh;
700 Rect r;
701
702 GetGWorld (&old_port, &old_gdh);
703 SetGWorld (p, NULL);
704 mac_set_colors (gc);
705 SetRect (&r, x, y, x + width + 1, y + height + 1);
706
707 LockPixels (GetGWorldPixMap (p));
708 FrameRect (&r); /* using foreground color of gc */
709 UnlockPixels (GetGWorldPixMap (p));
710
711 SetGWorld (old_port, old_gdh);
712 }
713
714
715 static void
716 mac_draw_string_common (display, w, gc, x, y, buf, nchars, mode,
717 bytes_per_char)
718 Display *display;
719 WindowPtr w;
720 GC gc;
721 int x, y;
722 char *buf;
723 int nchars, mode, bytes_per_char;
724 {
725 SetPortWindowPort (w);
726
727 mac_set_colors (gc);
728
729 TextFont (gc->font->mac_fontnum);
730 TextSize (gc->font->mac_fontsize);
731 TextFace (gc->font->mac_fontface);
732 TextMode (mode);
733
734 MoveTo (x, y);
735 DrawText (buf, 0, nchars * bytes_per_char);
736 }
737
738
739 /* Mac replacement for XDrawString. */
740
741 static void
742 XDrawString (display, w, gc, x, y, buf, nchars)
743 Display *display;
744 WindowPtr w;
745 GC gc;
746 int x, y;
747 char *buf;
748 int nchars;
749 {
750 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcOr, 1);
751 }
752
753
754 /* Mac replacement for XDrawString16. */
755
756 static void
757 XDrawString16 (display, w, gc, x, y, buf, nchars)
758 Display *display;
759 WindowPtr w;
760 GC gc;
761 int x, y;
762 XChar2b *buf;
763 int nchars;
764 {
765 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcOr,
766 2);
767 }
768
769
770 /* Mac replacement for XDrawImageString. */
771
772 static void
773 XDrawImageString (display, w, gc, x, y, buf, nchars)
774 Display *display;
775 WindowPtr w;
776 GC gc;
777 int x, y;
778 char *buf;
779 int nchars;
780 {
781 mac_draw_string_common (display, w, gc, x, y, buf, nchars, srcCopy, 1);
782 }
783
784
785 /* Mac replacement for XDrawString16. */
786
787 static void
788 XDrawImageString16 (display, w, gc, x, y, buf, nchars)
789 Display *display;
790 WindowPtr w;
791 GC gc;
792 int x, y;
793 XChar2b *buf;
794 int nchars;
795 {
796 mac_draw_string_common (display, w, gc, x, y, (char *) buf, nchars, srcCopy,
797 2);
798 }
799
800
801 /* Mac replacement for XCopyArea: dest must be window. */
802
803 static void
804 mac_copy_area (display, src, dest, gc, src_x, src_y, width, height, dest_x,
805 dest_y)
806 Display *display;
807 Pixmap src;
808 WindowPtr dest;
809 GC gc;
810 int src_x, src_y;
811 unsigned int width, height;
812 int dest_x, dest_y;
813 {
814 Rect src_r, dest_r;
815
816 SetPortWindowPort (dest);
817
818 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
819 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
820
821 ForeColor (blackColor);
822 BackColor (whiteColor);
823
824 LockPixels (GetGWorldPixMap (src));
825 #if TARGET_API_MAC_CARBON
826 LockPortBits (GetWindowPort (dest));
827 CopyBits (GetPortBitMapForCopyBits (src),
828 GetPortBitMapForCopyBits (GetWindowPort (dest)),
829 &src_r, &dest_r, srcCopy, 0);
830 UnlockPortBits (GetWindowPort (dest));
831 #else /* not TARGET_API_MAC_CARBON */
832 CopyBits (&(((GrafPtr)src)->portBits), &(dest->portBits),
833 &src_r, &dest_r, srcCopy, 0);
834 #endif /* not TARGET_API_MAC_CARBON */
835 UnlockPixels (GetGWorldPixMap (src));
836 }
837
838
839 static void
840 mac_copy_area_with_mask (display, src, mask, dest, gc, src_x, src_y,
841 width, height, dest_x, dest_y)
842 Display *display;
843 Pixmap src, mask;
844 WindowPtr dest;
845 GC gc;
846 int src_x, src_y;
847 unsigned int width, height;
848 int dest_x, dest_y;
849 {
850 Rect src_r, dest_r;
851
852 SetPortWindowPort (dest);
853
854 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
855 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
856
857 ForeColor (blackColor);
858 BackColor (whiteColor);
859
860 LockPixels (GetGWorldPixMap (src));
861 LockPixels (GetGWorldPixMap (mask));
862 #if TARGET_API_MAC_CARBON
863 LockPortBits (GetWindowPort (dest));
864 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
865 GetPortBitMapForCopyBits (GetWindowPort (dest)),
866 &src_r, &src_r, &dest_r);
867 UnlockPortBits (GetWindowPort (dest));
868 #else /* not TARGET_API_MAC_CARBON */
869 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
870 &(dest->portBits), &src_r, &src_r, &dest_r);
871 #endif /* not TARGET_API_MAC_CARBON */
872 UnlockPixels (GetGWorldPixMap (mask));
873 UnlockPixels (GetGWorldPixMap (src));
874 }
875
876
877 #if 0
878 /* Convert a pair of local coordinates to global (screen) coordinates.
879 Assume graphic port has been properly set. */
880 static void
881 local_to_global_coord (short *h, short *v)
882 {
883 Point p;
884
885 p.h = *h;
886 p.v = *v;
887
888 LocalToGlobal (&p);
889
890 *h = p.h;
891 *v = p.v;
892 }
893 #endif
894
895 /* Mac replacement for XCopyArea: used only for scrolling. */
896
897 static void
898 mac_scroll_area (display, w, gc, src_x, src_y, width, height, dest_x, dest_y)
899 Display *display;
900 WindowPtr w;
901 GC gc;
902 int src_x, src_y;
903 unsigned int width, height;
904 int dest_x, dest_y;
905 {
906 #if TARGET_API_MAC_CARBON
907 Rect gw_r, src_r, dest_r;
908
909 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
910 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
911
912 SetPortWindowPort (w);
913
914 ForeColor (blackColor);
915 BackColor (whiteColor);
916
917 LockPortBits (GetWindowPort (w));
918 {
919 const BitMap *bitmap = GetPortBitMapForCopyBits (GetWindowPort (w));
920 CopyBits (bitmap, bitmap, &src_r, &dest_r, srcCopy, 0);
921 }
922 UnlockPortBits (GetWindowPort (w));
923
924 mac_set_colors (gc);
925 #else /* not TARGET_API_MAC_CARBON */
926 Rect src_r, dest_r;
927
928 SetPort (w);
929 #if 0
930 mac_set_colors (gc);
931 #endif
932
933 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
934 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
935
936 #if 0
937 /* Need to use global coordinates and screenBits since src and dest
938 areas overlap in general. */
939 local_to_global_coord (&src_r.left, &src_r.top);
940 local_to_global_coord (&src_r.right, &src_r.bottom);
941 local_to_global_coord (&dest_r.left, &dest_r.top);
942 local_to_global_coord (&dest_r.right, &dest_r.bottom);
943
944 CopyBits (&qd.screenBits, &qd.screenBits, &src_r, &dest_r, srcCopy, 0);
945 #else
946 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid
947 color mapping in CopyBits. Otherwise, it will be slow. */
948 ForeColor (blackColor);
949 BackColor (whiteColor);
950 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0);
951
952 mac_set_colors (gc);
953 #endif
954 #endif /* not TARGET_API_MAC_CARBON */
955 }
956
957
958 /* Mac replacement for XCopyArea: dest must be Pixmap. */
959
960 static void
961 mac_copy_area_to_pixmap (display, src, dest, gc, src_x, src_y, width, height,
962 dest_x, dest_y)
963 Display *display;
964 Pixmap src, dest;
965 GC gc;
966 int src_x, src_y;
967 unsigned int width, height;
968 int dest_x, dest_y;
969 {
970 CGrafPtr old_port;
971 GDHandle old_gdh;
972 Rect src_r, dest_r;
973
974 GetGWorld (&old_port, &old_gdh);
975 SetGWorld (dest, NULL);
976 ForeColor (blackColor);
977 BackColor (whiteColor);
978
979 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
980 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
981
982 LockPixels (GetGWorldPixMap (src));
983 LockPixels (GetGWorldPixMap (dest));
984 #if TARGET_API_MAC_CARBON
985 CopyBits (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (dest),
986 &src_r, &dest_r, srcCopy, 0);
987 #else /* not TARGET_API_MAC_CARBON */
988 CopyBits (&(((GrafPtr)src)->portBits), &(((GrafPtr)dest)->portBits),
989 &src_r, &dest_r, srcCopy, 0);
990 #endif /* not TARGET_API_MAC_CARBON */
991 UnlockPixels (GetGWorldPixMap (dest));
992 UnlockPixels (GetGWorldPixMap (src));
993
994 SetGWorld (old_port, old_gdh);
995 }
996
997
998 static void
999 mac_copy_area_with_mask_to_pixmap (display, src, mask, dest, gc, src_x, src_y,
1000 width, height, dest_x, dest_y)
1001 Display *display;
1002 Pixmap src, mask, dest;
1003 GC gc;
1004 int src_x, src_y;
1005 unsigned int width, height;
1006 int dest_x, dest_y;
1007 {
1008 CGrafPtr old_port;
1009 GDHandle old_gdh;
1010 Rect src_r, dest_r;
1011
1012 GetGWorld (&old_port, &old_gdh);
1013 SetGWorld (dest, NULL);
1014 ForeColor (blackColor);
1015 BackColor (whiteColor);
1016
1017 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height);
1018 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height);
1019
1020 LockPixels (GetGWorldPixMap (src));
1021 LockPixels (GetGWorldPixMap (mask));
1022 LockPixels (GetGWorldPixMap (dest));
1023 #if TARGET_API_MAC_CARBON
1024 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask),
1025 GetPortBitMapForCopyBits (dest), &src_r, &src_r, &dest_r);
1026 #else /* not TARGET_API_MAC_CARBON */
1027 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits),
1028 &(((GrafPtr)dest)->portBits), &src_r, &src_r, &dest_r);
1029 #endif /* not TARGET_API_MAC_CARBON */
1030 UnlockPixels (GetGWorldPixMap (dest));
1031 UnlockPixels (GetGWorldPixMap (mask));
1032 UnlockPixels (GetGWorldPixMap (src));
1033
1034 SetGWorld (old_port, old_gdh);
1035 }
1036
1037
1038 /* Mac replacement for XChangeGC. */
1039
1040 static void
1041 XChangeGC (void * ignore, XGCValues* gc, unsigned long mask,
1042 XGCValues *xgcv)
1043 {
1044 if (mask & GCForeground)
1045 gc->foreground = xgcv->foreground;
1046 if (mask & GCBackground)
1047 gc->background = xgcv->background;
1048 if (mask & GCFont)
1049 gc->font = xgcv->font;
1050 }
1051
1052
1053 /* Mac replacement for XCreateGC. */
1054
1055 XGCValues *
1056 XCreateGC (void * ignore, Window window, unsigned long mask,
1057 XGCValues *xgcv)
1058 {
1059 XGCValues *gc = (XGCValues *) xmalloc (sizeof (XGCValues));
1060 bzero (gc, sizeof (XGCValues));
1061
1062 XChangeGC (ignore, gc, mask, xgcv);
1063
1064 return gc;
1065 }
1066
1067
1068 /* Used in xfaces.c. */
1069
1070 void
1071 XFreeGC (display, gc)
1072 Display *display;
1073 GC gc;
1074 {
1075 xfree (gc);
1076 }
1077
1078
1079 /* Mac replacement for XGetGCValues. */
1080
1081 static void
1082 XGetGCValues (void* ignore, XGCValues *gc,
1083 unsigned long mask, XGCValues *xgcv)
1084 {
1085 XChangeGC (ignore, xgcv, mask, gc);
1086 }
1087
1088
1089 /* Mac replacement for XSetForeground. */
1090
1091 void
1092 XSetForeground (display, gc, color)
1093 Display *display;
1094 GC gc;
1095 unsigned long color;
1096 {
1097 gc->foreground = color;
1098 }
1099
1100
1101 /* Mac replacement for XSetFont. */
1102
1103 static void
1104 XSetFont (display, gc, font)
1105 Display *display;
1106 GC gc;
1107 XFontStruct *font;
1108 {
1109 gc->font = font;
1110 }
1111
1112
1113 static void
1114 XTextExtents16 (XFontStruct *font, XChar2b *text, int nchars,
1115 int *direction,int *font_ascent,
1116 int *font_descent, XCharStruct *cs)
1117 {
1118 /* MAC_TODO: Use GetTextMetrics to do this and inline it below. */
1119 }
1120
1121
1122 /* x_sync is a no-op on Mac. */
1123 void
1124 x_sync (f)
1125 void *f;
1126 {
1127 }
1128
1129
1130 /* Remove calls to XFlush by defining XFlush to an empty replacement.
1131 Calls to XFlush should be unnecessary because the X output buffer
1132 is flushed automatically as needed by calls to XPending,
1133 XNextEvent, or XWindowEvent according to the XFlush man page.
1134 XTread_socket calls XPending. Removing XFlush improves
1135 performance. */
1136
1137 #if TARGET_API_MAC_CARBON
1138 #define XFlush(DISPLAY) QDFlushPortBuffer (GetQDGlobalsThePort (), NULL)
1139 #else
1140 #define XFlush(DISPLAY) (void) 0
1141 #endif
1142
1143 /* Flush display of frame F, or of all frames if F is null. */
1144
1145 void
1146 x_flush (f)
1147 struct frame *f;
1148 {
1149 #if TARGET_API_MAC_CARBON
1150 BLOCK_INPUT;
1151 if (f == NULL)
1152 {
1153 Lisp_Object rest, frame;
1154 FOR_EACH_FRAME (rest, frame)
1155 x_flush (XFRAME (frame));
1156 }
1157 else if (FRAME_MAC_P (f))
1158 XFlush (FRAME_MAC_DISPLAY (f));
1159 UNBLOCK_INPUT;
1160 #endif /* TARGET_API_MAC_CARBON */
1161 }
1162
1163
1164 \f
1165 /* Return the struct mac_display_info corresponding to DPY. There's
1166 only one. */
1167
1168 struct mac_display_info *
1169 mac_display_info_for_display (dpy)
1170 Display *dpy;
1171 {
1172 return &one_mac_display_info;
1173 }
1174
1175
1176 \f
1177 /***********************************************************************
1178 Starting and ending an update
1179 ***********************************************************************/
1180
1181 /* Start an update of frame F. This function is installed as a hook
1182 for update_begin, i.e. it is called when update_begin is called.
1183 This function is called prior to calls to x_update_window_begin for
1184 each window being updated. */
1185
1186 static void
1187 x_update_begin (f)
1188 struct frame *f;
1189 {
1190 /* Nothing to do. */
1191 }
1192
1193
1194 /* Start update of window W. Set the global variable updated_window
1195 to the window being updated and set output_cursor to the cursor
1196 position of W. */
1197
1198 static void
1199 x_update_window_begin (w)
1200 struct window *w;
1201 {
1202 struct frame *f = XFRAME (WINDOW_FRAME (w));
1203 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f);
1204
1205 updated_window = w;
1206 set_output_cursor (&w->cursor);
1207
1208 BLOCK_INPUT;
1209
1210 if (f == display_info->mouse_face_mouse_frame)
1211 {
1212 /* Don't do highlighting for mouse motion during the update. */
1213 display_info->mouse_face_defer = 1;
1214
1215 /* If F needs to be redrawn, simply forget about any prior mouse
1216 highlighting. */
1217 if (FRAME_GARBAGED_P (f))
1218 display_info->mouse_face_window = Qnil;
1219
1220 #if 0 /* Rows in a current matrix containing glyphs in mouse-face have
1221 their mouse_face_p flag set, which means that they are always
1222 unequal to rows in a desired matrix which never have that
1223 flag set. So, rows containing mouse-face glyphs are never
1224 scrolled, and we don't have to switch the mouse highlight off
1225 here to prevent it from being scrolled. */
1226
1227 /* Can we tell that this update does not affect the window
1228 where the mouse highlight is? If so, no need to turn off.
1229 Likewise, don't do anything if the frame is garbaged;
1230 in that case, the frame's current matrix that we would use
1231 is all wrong, and we will redisplay that line anyway. */
1232 if (!NILP (display_info->mouse_face_window)
1233 && w == XWINDOW (display_info->mouse_face_window))
1234 {
1235 int i;
1236
1237 for (i = 0; i < w->desired_matrix->nrows; ++i)
1238 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i))
1239 break;
1240
1241 if (i < w->desired_matrix->nrows)
1242 clear_mouse_face (display_info);
1243 }
1244 #endif /* 0 */
1245 }
1246
1247 UNBLOCK_INPUT;
1248 }
1249
1250
1251 /* Draw a vertical window border from (x,y0) to (x,y1) */
1252
1253 static void
1254 mac_draw_vertical_window_border (w, x, y0, y1)
1255 struct window *w;
1256 int x, y0, y1;
1257 {
1258 struct frame *f = XFRAME (WINDOW_FRAME (w));
1259
1260 XDrawLine (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
1261 f->output_data.mac->normal_gc, x, y0, x, y1);
1262 }
1263
1264
1265 /* End update of window W (which is equal to updated_window).
1266
1267 Draw vertical borders between horizontally adjacent windows, and
1268 display W's cursor if CURSOR_ON_P is non-zero.
1269
1270 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing
1271 glyphs in mouse-face were overwritten. In that case we have to
1272 make sure that the mouse-highlight is properly redrawn.
1273
1274 W may be a menu bar pseudo-window in case we don't have X toolkit
1275 support. Such windows don't have a cursor, so don't display it
1276 here. */
1277
1278 static void
1279 x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p)
1280 struct window *w;
1281 int cursor_on_p, mouse_face_overwritten_p;
1282 {
1283 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame));
1284
1285 if (!w->pseudo_window_p)
1286 {
1287 BLOCK_INPUT;
1288
1289 if (cursor_on_p)
1290 display_and_set_cursor (w, 1, output_cursor.hpos,
1291 output_cursor.vpos,
1292 output_cursor.x, output_cursor.y);
1293
1294 if (draw_window_fringes (w, 1))
1295 x_draw_vertical_border (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 /* Mouse highlight may be displayed again. */
1329 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0;
1330
1331 BLOCK_INPUT;
1332 /* Reset the background color of Mac OS Window to that of the frame after
1333 update so that it is used by Mac Toolbox to clear the update region before
1334 an update event is generated. */
1335 SetPortWindowPort (FRAME_MAC_WINDOW (f));
1336
1337 mac_set_backcolor (FRAME_BACKGROUND_PIXEL (f));
1338
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 front_emacs_window ()
3891 {
3892 #if TARGET_API_MAC_CARBON
3893 WindowPtr wp = GetFrontWindowOfClass (kDocumentWindowClass, true);
3894
3895 while (wp && !is_emacs_window (wp))
3896 wp = GetNextWindowOfClass (wp, kDocumentWindowClass, true);
3897 #else
3898 WindowPtr wp = FrontWindow ();
3899
3900 while (wp && (wp == tip_window || !is_emacs_window (wp)))
3901 wp = GetNextWindow (wp);
3902 #endif
3903
3904 return wp;
3905 }
3906
3907 #define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP)
3908
3909 /* Return the current position of the mouse.
3910 *fp should be a frame which indicates which display to ask about.
3911
3912 If the mouse movement started in a scroll bar, set *fp, *bar_window,
3913 and *part to the frame, window, and scroll bar part that the mouse
3914 is over. Set *x and *y to the portion and whole of the mouse's
3915 position on the scroll bar.
3916
3917 If the mouse movement started elsewhere, set *fp to the frame the
3918 mouse is on, *bar_window to nil, and *x and *y to the character cell
3919 the mouse is over.
3920
3921 Set *time to the server time-stamp for the time at which the mouse
3922 was at this position.
3923
3924 Don't store anything if we don't have a valid set of values to report.
3925
3926 This clears the mouse_moved flag, so we can wait for the next mouse
3927 movement. */
3928
3929 static void
3930 XTmouse_position (fp, insist, bar_window, part, x, y, time)
3931 FRAME_PTR *fp;
3932 int insist;
3933 Lisp_Object *bar_window;
3934 enum scroll_bar_part *part;
3935 Lisp_Object *x, *y;
3936 unsigned long *time;
3937 {
3938 Point mouse_pos;
3939 int ignore1, ignore2;
3940 WindowPtr wp = front_emacs_window ();
3941 struct frame *f;
3942 Lisp_Object frame, tail;
3943
3944 if (is_emacs_window(wp))
3945 f = mac_window_to_frame (wp);
3946
3947 BLOCK_INPUT;
3948
3949 if (! NILP (last_mouse_scroll_bar) && insist == 0)
3950 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time);
3951 else
3952 {
3953 /* Clear the mouse-moved flag for every frame on this display. */
3954 FOR_EACH_FRAME (tail, frame)
3955 XFRAME (frame)->mouse_moved = 0;
3956
3957 last_mouse_scroll_bar = Qnil;
3958
3959 SetPortWindowPort (wp);
3960
3961 GetMouse (&mouse_pos);
3962
3963 pixel_to_glyph_coords (f, mouse_pos.h, mouse_pos.v, &ignore1, &ignore2,
3964 &last_mouse_glyph, insist);
3965
3966 *bar_window = Qnil;
3967 *part = scroll_bar_handle;
3968 *fp = f;
3969 XSETINT (*x, mouse_pos.h);
3970 XSETINT (*y, mouse_pos.v);
3971 *time = last_mouse_movement_time;
3972 }
3973
3974 UNBLOCK_INPUT;
3975 }
3976
3977 \f
3978 /***********************************************************************
3979 Tool-bars
3980 ***********************************************************************/
3981
3982 /* Handle mouse button event on the tool-bar of frame F, at
3983 frame-relative coordinates X/Y. EVENT_TYPE is either ButtionPress
3984 or ButtonRelase. */
3985
3986 static void
3987 mac_handle_tool_bar_click (f, button_event)
3988 struct frame *f;
3989 EventRecord *button_event;
3990 {
3991 int x = button_event->where.h;
3992 int y = button_event->where.v;
3993
3994 if (button_event->what == mouseDown)
3995 handle_tool_bar_click (f, x, y, 1, 0);
3996 else
3997 handle_tool_bar_click (f, x, y, 0,
3998 x_mac_to_emacs_modifiers (FRAME_MAC_DISPLAY_INFO (f),
3999 button_event->modifiers));
4000 }
4001
4002 \f
4003 /************************************************************************
4004 Scroll bars, general
4005 ************************************************************************/
4006
4007 /* Create a scroll bar and return the scroll bar vector for it. W is
4008 the Emacs window on which to create the scroll bar. TOP, LEFT,
4009 WIDTH and HEIGHT are the pixel coordinates and dimensions of the
4010 scroll bar. */
4011
4012 static struct scroll_bar *
4013 x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height)
4014 struct window *w;
4015 int top, left, width, height, disp_top, disp_height;
4016 {
4017 struct frame *f = XFRAME (w->frame);
4018 struct scroll_bar *bar
4019 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil));
4020 Rect r;
4021 ControlHandle ch;
4022
4023 BLOCK_INPUT;
4024
4025 r.left = left;
4026 r.top = disp_top;
4027 r.right = left + width;
4028 r.bottom = disp_top + disp_height;
4029
4030 #ifdef TARGET_API_MAC_CARBON
4031 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0,
4032 kControlScrollBarProc, 0L);
4033 #else
4034 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 1, 0, 0, 0, scrollBarProc,
4035 0L);
4036 #endif
4037 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch);
4038 SetControlReference (ch, (long) bar);
4039
4040 XSETWINDOW (bar->window, w);
4041 XSETINT (bar->top, top);
4042 XSETINT (bar->left, left);
4043 XSETINT (bar->width, width);
4044 XSETINT (bar->height, height);
4045 XSETINT (bar->start, 0);
4046 XSETINT (bar->end, 0);
4047 bar->dragging = Qnil;
4048
4049 /* Add bar to its frame's list of scroll bars. */
4050 bar->next = FRAME_SCROLL_BARS (f);
4051 bar->prev = Qnil;
4052 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4053 if (!NILP (bar->next))
4054 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4055
4056 UNBLOCK_INPUT;
4057 return bar;
4058 }
4059
4060
4061 /* Draw BAR's handle in the proper position.
4062
4063 If the handle is already drawn from START to END, don't bother
4064 redrawing it, unless REBUILD is non-zero; in that case, always
4065 redraw it. (REBUILD is handy for drawing the handle after expose
4066 events.)
4067
4068 Normally, we want to constrain the start and end of the handle to
4069 fit inside its rectangle, but if the user is dragging the scroll
4070 bar handle, we want to let them drag it down all the way, so that
4071 the bar's top is as far down as it goes; otherwise, there's no way
4072 to move to the very end of the buffer. */
4073
4074 static void
4075 x_scroll_bar_set_handle (bar, start, end, rebuild)
4076 struct scroll_bar *bar;
4077 int start, end;
4078 int rebuild;
4079 {
4080 int dragging = ! NILP (bar->dragging);
4081 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4082 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4083 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4084 int length = end - start;
4085
4086 /* If the display is already accurate, do nothing. */
4087 if (! rebuild
4088 && start == XINT (bar->start)
4089 && end == XINT (bar->end))
4090 return;
4091
4092 BLOCK_INPUT;
4093
4094 /* Make sure the values are reasonable, and try to preserve the
4095 distance between start and end. */
4096 if (start < 0)
4097 start = 0;
4098 else if (start > top_range)
4099 start = top_range;
4100 end = start + length;
4101
4102 if (end < start)
4103 end = start;
4104 else if (end > top_range && ! dragging)
4105 end = top_range;
4106
4107 /* Store the adjusted setting in the scroll bar. */
4108 XSETINT (bar->start, start);
4109 XSETINT (bar->end, end);
4110
4111 /* Clip the end position, just for display. */
4112 if (end > top_range)
4113 end = top_range;
4114
4115 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below
4116 top positions, to make sure the handle is always at least that
4117 many pixels tall. */
4118 end += VERTICAL_SCROLL_BAR_MIN_HANDLE;
4119
4120 SetControlMinimum (ch, 0);
4121 /* Don't inadvertently activate deactivated scroll bars */
4122 if (GetControlMaximum (ch) != -1)
4123 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE
4124 - (end - start));
4125 SetControlValue (ch, start);
4126 #if TARGET_API_MAC_CARBON
4127 SetControlViewSize (ch, end - start);
4128 #endif
4129
4130 UNBLOCK_INPUT;
4131 }
4132
4133
4134 /* Destroy scroll bar BAR, and set its Emacs window's scroll bar to
4135 nil. */
4136
4137 static void
4138 x_scroll_bar_remove (bar)
4139 struct scroll_bar *bar;
4140 {
4141 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window)));
4142
4143 BLOCK_INPUT;
4144
4145 /* Destroy the Mac scroll bar control */
4146 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar));
4147
4148 /* Disassociate this scroll bar from its window. */
4149 XWINDOW (bar->window)->vertical_scroll_bar = Qnil;
4150
4151 UNBLOCK_INPUT;
4152 }
4153
4154 /* Set the handle of the vertical scroll bar for WINDOW to indicate
4155 that we are displaying PORTION characters out of a total of WHOLE
4156 characters, starting at POSITION. If WINDOW has no scroll bar,
4157 create one. */
4158 static void
4159 XTset_vertical_scroll_bar (w, portion, whole, position)
4160 struct window *w;
4161 int portion, whole, position;
4162 {
4163 struct frame *f = XFRAME (w->frame);
4164 struct scroll_bar *bar;
4165 int top, height, left, sb_left, width, sb_width, disp_top, disp_height;
4166 int window_y, window_height;
4167
4168 /* Get window dimensions. */
4169 window_box (w, -1, 0, &window_y, 0, &window_height);
4170 top = window_y;
4171 #ifdef MAC_OSX
4172 width = 16;
4173 #else
4174 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f);
4175 #endif
4176 height = window_height;
4177
4178 /* Compute the left edge of the scroll bar area. */
4179 left = WINDOW_SCROLL_BAR_AREA_X (w);
4180
4181 /* Compute the width of the scroll bar which might be less than
4182 the width of the area reserved for the scroll bar. */
4183 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0)
4184 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w);
4185 else
4186 sb_width = width;
4187
4188 /* Compute the left edge of the scroll bar. */
4189 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w))
4190 sb_left = left + width - sb_width - (width - sb_width) / 2;
4191 else
4192 sb_left = left + (width - sb_width) / 2;
4193
4194 /* Adjustments according to Inside Macintosh to make it look nice */
4195 disp_top = top;
4196 disp_height = height;
4197 if (disp_top == 0)
4198 {
4199 disp_top = -1;
4200 disp_height++;
4201 }
4202 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16)
4203 {
4204 disp_top++;
4205 disp_height--;
4206 }
4207
4208 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f))
4209 sb_left++;
4210
4211 /* Does the scroll bar exist yet? */
4212 if (NILP (w->vertical_scroll_bar))
4213 {
4214 BLOCK_INPUT;
4215 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4216 left, top, width, height, 0);
4217 UNBLOCK_INPUT;
4218 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top,
4219 disp_height);
4220 XSETVECTOR (w->vertical_scroll_bar, bar);
4221 }
4222 else
4223 {
4224 /* It may just need to be moved and resized. */
4225 ControlHandle ch;
4226
4227 bar = XSCROLL_BAR (w->vertical_scroll_bar);
4228 ch = SCROLL_BAR_CONTROL_HANDLE (bar);
4229
4230 BLOCK_INPUT;
4231
4232 /* If already correctly positioned, do nothing. */
4233 if (XINT (bar->left) == sb_left
4234 && XINT (bar->top) == top
4235 && XINT (bar->width) == sb_width
4236 && XINT (bar->height) == height)
4237 Draw1Control (ch);
4238 else
4239 {
4240 /* Clear areas not covered by the scroll bar because it's not as
4241 wide as the area reserved for it . This makes sure a
4242 previous mode line display is cleared after C-x 2 C-x 1, for
4243 example. */
4244 int area_width = WINDOW_SCROLL_BAR_AREA_WIDTH (w);
4245 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4246 left, top, area_width, height, 0);
4247
4248 #if 0
4249 if (sb_left + sb_width >= FRAME_PIXEL_WIDTH (f))
4250 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4251 sb_left - 1, top, 1, height, 0);
4252 #endif
4253
4254 HideControl (ch);
4255 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top);
4256 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2,
4257 disp_height);
4258 ShowControl (ch);
4259
4260 /* Remember new settings. */
4261 XSETINT (bar->left, sb_left);
4262 XSETINT (bar->top, top);
4263 XSETINT (bar->width, sb_width);
4264 XSETINT (bar->height, height);
4265 }
4266
4267 UNBLOCK_INPUT;
4268 }
4269
4270 /* Set the scroll bar's current state, unless we're currently being
4271 dragged. */
4272 if (NILP (bar->dragging))
4273 {
4274 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height);
4275
4276 if (whole == 0)
4277 x_scroll_bar_set_handle (bar, 0, top_range, 0);
4278 else
4279 {
4280 int start = ((double) position * top_range) / whole;
4281 int end = ((double) (position + portion) * top_range) / whole;
4282 x_scroll_bar_set_handle (bar, start, end, 0);
4283 }
4284 }
4285 }
4286
4287
4288 /* The following three hooks are used when we're doing a thorough
4289 redisplay of the frame. We don't explicitly know which scroll bars
4290 are going to be deleted, because keeping track of when windows go
4291 away is a real pain - "Can you say set-window-configuration, boys
4292 and girls?" Instead, we just assert at the beginning of redisplay
4293 that *all* scroll bars are to be removed, and then save a scroll bar
4294 from the fiery pit when we actually redisplay its window. */
4295
4296 /* Arrange for all scroll bars on FRAME to be removed at the next call
4297 to `*judge_scroll_bars_hook'. A scroll bar may be spared if
4298 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */
4299
4300 static void
4301 XTcondemn_scroll_bars (frame)
4302 FRAME_PTR frame;
4303 {
4304 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */
4305 while (! NILP (FRAME_SCROLL_BARS (frame)))
4306 {
4307 Lisp_Object bar;
4308 bar = FRAME_SCROLL_BARS (frame);
4309 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next;
4310 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame);
4311 XSCROLL_BAR (bar)->prev = Qnil;
4312 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame)))
4313 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar;
4314 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar;
4315 }
4316 }
4317
4318
4319 /* Un-mark WINDOW's scroll bar for deletion in this judgment cycle.
4320 Note that WINDOW isn't necessarily condemned at all. */
4321
4322 static void
4323 XTredeem_scroll_bar (window)
4324 struct window *window;
4325 {
4326 struct scroll_bar *bar;
4327
4328 /* We can't redeem this window's scroll bar if it doesn't have one. */
4329 if (NILP (window->vertical_scroll_bar))
4330 abort ();
4331
4332 bar = XSCROLL_BAR (window->vertical_scroll_bar);
4333
4334 /* Unlink it from the condemned list. */
4335 {
4336 FRAME_PTR f = XFRAME (WINDOW_FRAME (window));
4337
4338 if (NILP (bar->prev))
4339 {
4340 /* If the prev pointer is nil, it must be the first in one of
4341 the lists. */
4342 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar))
4343 /* It's not condemned. Everything's fine. */
4344 return;
4345 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f),
4346 window->vertical_scroll_bar))
4347 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next;
4348 else
4349 /* If its prev pointer is nil, it must be at the front of
4350 one or the other! */
4351 abort ();
4352 }
4353 else
4354 XSCROLL_BAR (bar->prev)->next = bar->next;
4355
4356 if (! NILP (bar->next))
4357 XSCROLL_BAR (bar->next)->prev = bar->prev;
4358
4359 bar->next = FRAME_SCROLL_BARS (f);
4360 bar->prev = Qnil;
4361 XSETVECTOR (FRAME_SCROLL_BARS (f), bar);
4362 if (! NILP (bar->next))
4363 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar);
4364 }
4365 }
4366
4367 /* Remove all scroll bars on FRAME that haven't been saved since the
4368 last call to `*condemn_scroll_bars_hook'. */
4369
4370 static void
4371 XTjudge_scroll_bars (f)
4372 FRAME_PTR f;
4373 {
4374 Lisp_Object bar, next;
4375
4376 bar = FRAME_CONDEMNED_SCROLL_BARS (f);
4377
4378 /* Clear out the condemned list now so we won't try to process any
4379 more events on the hapless scroll bars. */
4380 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil;
4381
4382 for (; ! NILP (bar); bar = next)
4383 {
4384 struct scroll_bar *b = XSCROLL_BAR (bar);
4385
4386 x_scroll_bar_remove (b);
4387
4388 next = b->next;
4389 b->next = b->prev = Qnil;
4390 }
4391
4392 /* Now there should be no references to the condemned scroll bars,
4393 and they should get garbage-collected. */
4394 }
4395
4396
4397 void
4398 activate_scroll_bars (frame)
4399 FRAME_PTR frame;
4400 {
4401 Lisp_Object bar;
4402 ControlHandle ch;
4403
4404 bar = FRAME_SCROLL_BARS (frame);
4405 while (! NILP (bar))
4406 {
4407 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
4408 #ifdef TARGET_API_MAC_CARBON
4409 ActivateControl (ch);
4410 #else
4411 SetControlMaximum (ch,
4412 VERTICAL_SCROLL_BAR_TOP_RANGE (frame,
4413 XINT (XSCROLL_BAR (bar)
4414 ->height)) - 1);
4415 #endif
4416 bar = XSCROLL_BAR (bar)->next;
4417 }
4418 }
4419
4420
4421 void
4422 deactivate_scroll_bars (frame)
4423 FRAME_PTR frame;
4424 {
4425 Lisp_Object bar;
4426 ControlHandle ch;
4427
4428 bar = FRAME_SCROLL_BARS (frame);
4429 while (! NILP (bar))
4430 {
4431 ch = SCROLL_BAR_CONTROL_HANDLE (XSCROLL_BAR (bar));
4432 #ifdef TARGET_API_MAC_CARBON
4433 DeactivateControl (ch);
4434 #else
4435 SetControlMaximum (ch, XINT (-1));
4436 #endif
4437 bar = XSCROLL_BAR (bar)->next;
4438 }
4439 }
4440
4441 /* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind
4442 is set to something other than NO_EVENT, it is enqueued.
4443
4444 This may be called from a signal handler, so we have to ignore GC
4445 mark bits. */
4446
4447 static void
4448 x_scroll_bar_handle_click (bar, part_code, er, bufp)
4449 struct scroll_bar *bar;
4450 int part_code;
4451 EventRecord *er;
4452 struct input_event *bufp;
4453 {
4454 int win_y, top_range;
4455
4456 if (! GC_WINDOWP (bar->window))
4457 abort ();
4458
4459 bufp->kind = SCROLL_BAR_CLICK_EVENT;
4460 bufp->frame_or_window = bar->window;
4461 bufp->arg = Qnil;
4462
4463 bar->dragging = Qnil;
4464
4465 switch (part_code)
4466 {
4467 case kControlUpButtonPart:
4468 bufp->part = scroll_bar_up_arrow;
4469 break;
4470 case kControlDownButtonPart:
4471 bufp->part = scroll_bar_down_arrow;
4472 break;
4473 case kControlPageUpPart:
4474 bufp->part = scroll_bar_above_handle;
4475 break;
4476 case kControlPageDownPart:
4477 bufp->part = scroll_bar_below_handle;
4478 break;
4479 #ifdef TARGET_API_MAC_CARBON
4480 default:
4481 #else
4482 case kControlIndicatorPart:
4483 #endif
4484 if (er->what == mouseDown)
4485 bar->dragging = make_number (0);
4486 XSETVECTOR (last_mouse_scroll_bar, bar);
4487 bufp->part = scroll_bar_handle;
4488 break;
4489 }
4490
4491 win_y = XINT (bufp->y) - XINT (bar->top);
4492 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar->height));
4493
4494 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
4495
4496 win_y -= 24;
4497
4498 if (! NILP (bar->dragging))
4499 win_y -= XINT (bar->dragging);
4500
4501 if (win_y < 0)
4502 win_y = 0;
4503 if (win_y > top_range)
4504 win_y = top_range;
4505
4506 XSETINT (bufp->x, win_y);
4507 XSETINT (bufp->y, top_range);
4508 }
4509
4510
4511 /* Handle some mouse motion while someone is dragging the scroll bar.
4512
4513 This may be called from a signal handler, so we have to ignore GC
4514 mark bits. */
4515
4516 static void
4517 x_scroll_bar_note_movement (bar, y_pos, t)
4518 struct scroll_bar *bar;
4519 int y_pos;
4520 Time t;
4521 {
4522 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame);
4523
4524 last_mouse_movement_time = t;
4525
4526 f->mouse_moved = 1;
4527 XSETVECTOR (last_mouse_scroll_bar, bar);
4528
4529 /* If we're dragging the bar, display it. */
4530 if (! GC_NILP (bar->dragging))
4531 {
4532 /* Where should the handle be now? */
4533 int new_start = y_pos - 24;
4534
4535 if (new_start != XINT (bar->start))
4536 {
4537 int new_end = new_start + (XINT (bar->end) - XINT (bar->start));
4538
4539 x_scroll_bar_set_handle (bar, new_start, new_end, 0);
4540 }
4541 }
4542 }
4543
4544
4545 /* Return information to the user about the current position of the
4546 mouse on the scroll bar. */
4547
4548 static void
4549 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time)
4550 FRAME_PTR *fp;
4551 Lisp_Object *bar_window;
4552 enum scroll_bar_part *part;
4553 Lisp_Object *x, *y;
4554 unsigned long *time;
4555 {
4556 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar);
4557 WindowPtr wp = front_emacs_window ();
4558 Point mouse_pos;
4559 struct frame *f = mac_window_to_frame (wp);
4560 int win_y, top_range;
4561
4562 SetPortWindowPort (wp);
4563
4564 GetMouse (&mouse_pos);
4565
4566 win_y = mouse_pos.v - XINT (bar->top);
4567 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height));
4568
4569 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER;
4570
4571 win_y -= 24;
4572
4573 if (! NILP (bar->dragging))
4574 win_y -= XINT (bar->dragging);
4575
4576 if (win_y < 0)
4577 win_y = 0;
4578 if (win_y > top_range)
4579 win_y = top_range;
4580
4581 *fp = f;
4582 *bar_window = bar->window;
4583
4584 if (! NILP (bar->dragging))
4585 *part = scroll_bar_handle;
4586 else if (win_y < XINT (bar->start))
4587 *part = scroll_bar_above_handle;
4588 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE)
4589 *part = scroll_bar_handle;
4590 else
4591 *part = scroll_bar_below_handle;
4592
4593 XSETINT (*x, win_y);
4594 XSETINT (*y, top_range);
4595
4596 f->mouse_moved = 0;
4597 last_mouse_scroll_bar = Qnil;
4598
4599 *time = last_mouse_movement_time;
4600 }
4601 \f
4602 /***********************************************************************
4603 Text Cursor
4604 ***********************************************************************/
4605
4606 /* Set clipping for output in glyph row ROW. W is the window in which
4607 we operate. GC is the graphics context to set clipping in.
4608
4609 ROW may be a text row or, e.g., a mode line. Text rows must be
4610 clipped to the interior of the window dedicated to text display,
4611 mode lines must be clipped to the whole window. */
4612
4613 static void
4614 x_clip_to_row (w, row, gc)
4615 struct window *w;
4616 struct glyph_row *row;
4617 GC gc;
4618 {
4619 struct frame *f = XFRAME (WINDOW_FRAME (w));
4620 Rect clip_rect;
4621 int window_y, window_width;
4622
4623 window_box (w, -1, 0, &window_y, &window_width, 0);
4624
4625 clip_rect.left = WINDOW_TO_FRAME_PIXEL_X (w, 0);
4626 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
4627 clip_rect.top = max (clip_rect.top, window_y);
4628 clip_rect.right = clip_rect.left + window_width;
4629 clip_rect.bottom = clip_rect.top + row->visible_height;
4630
4631 mac_set_clip_rectangle (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f), &clip_rect);
4632 }
4633
4634
4635 /* Draw a hollow box cursor on window W in glyph row ROW. */
4636
4637 static void
4638 x_draw_hollow_cursor (w, row)
4639 struct window *w;
4640 struct glyph_row *row;
4641 {
4642 struct frame *f = XFRAME (WINDOW_FRAME (w));
4643 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
4644 Display *dpy = FRAME_MAC_DISPLAY (f);
4645 int x, y, wd, h;
4646 XGCValues xgcv;
4647 struct glyph *cursor_glyph;
4648 GC gc;
4649
4650 /* Get the glyph the cursor is on. If we can't tell because
4651 the current matrix is invalid or such, give up. */
4652 cursor_glyph = get_phys_cursor_glyph (w);
4653 if (cursor_glyph == NULL)
4654 return;
4655
4656 /* Compute the width of the rectangle to draw. If on a stretch
4657 glyph, and `x-stretch-block-cursor' is nil, don't draw a
4658 rectangle as wide as the glyph, but use a canonical character
4659 width instead. */
4660 wd = cursor_glyph->pixel_width - 1;
4661 if (cursor_glyph->type == STRETCH_GLYPH
4662 && !x_stretch_cursor_p)
4663 wd = min (FRAME_COLUMN_WIDTH (f), wd);
4664 w->phys_cursor_width = wd;
4665
4666 /* Compute frame-relative coordinates from window-relative
4667 coordinates. */
4668 x = WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x);
4669 y = WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y);
4670
4671 /* Compute the proper height and ascent of the rectangle, based
4672 on the actual glyph. Using the full height of the row looks
4673 bad when there are tall images on that row. */
4674 h = max (min (FRAME_LINE_HEIGHT (f), row->height),
4675 cursor_glyph->ascent + cursor_glyph->descent);
4676 if (h < row->height)
4677 y += row->ascent /* - w->phys_cursor_ascent */ + cursor_glyph->descent - h;
4678 h--;
4679
4680 /* The foreground of cursor_gc is typically the same as the normal
4681 background color, which can cause the cursor box to be invisible. */
4682 xgcv.foreground = f->output_data.mac->cursor_pixel;
4683 if (dpyinfo->scratch_cursor_gc)
4684 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv);
4685 else
4686 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f),
4687 GCForeground, &xgcv);
4688 gc = dpyinfo->scratch_cursor_gc;
4689
4690 /* Set clipping, draw the rectangle, and reset clipping again. */
4691 x_clip_to_row (w, row, gc);
4692 mac_draw_rectangle (dpy, FRAME_MAC_WINDOW (f), gc, x, y, wd, h);
4693 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4694 }
4695
4696
4697 /* Draw a bar cursor on window W in glyph row ROW.
4698
4699 Implementation note: One would like to draw a bar cursor with an
4700 angle equal to the one given by the font property XA_ITALIC_ANGLE.
4701 Unfortunately, I didn't find a font yet that has this property set.
4702 --gerd. */
4703
4704 static void
4705 x_draw_bar_cursor (w, row, width, kind)
4706 struct window *w;
4707 struct glyph_row *row;
4708 int width;
4709 enum text_cursor_kinds kind;
4710 {
4711 struct frame *f = XFRAME (w->frame);
4712 struct glyph *cursor_glyph;
4713
4714 /* If cursor is out of bounds, don't draw garbage. This can happen
4715 in mini-buffer windows when switching between echo area glyphs
4716 and mini-buffer. */
4717 cursor_glyph = get_phys_cursor_glyph (w);
4718 if (cursor_glyph == NULL)
4719 return;
4720
4721 /* If on an image, draw like a normal cursor. That's usually better
4722 visible than drawing a bar, esp. if the image is large so that
4723 the bar might not be in the window. */
4724 if (cursor_glyph->type == IMAGE_GLYPH)
4725 {
4726 struct glyph_row *row;
4727 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos);
4728 draw_phys_cursor_glyph (w, row, DRAW_CURSOR);
4729 }
4730 else
4731 {
4732 Display *dpy = FRAME_MAC_DISPLAY (f);
4733 Window window = FRAME_MAC_WINDOW (f);
4734 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc;
4735 unsigned long mask = GCForeground | GCBackground;
4736 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id);
4737 XGCValues xgcv;
4738
4739 /* If the glyph's background equals the color we normally draw
4740 the bar cursor in, the bar cursor in its normal color is
4741 invisible. Use the glyph's foreground color instead in this
4742 case, on the assumption that the glyph's colors are chosen so
4743 that the glyph is legible. */
4744 if (face->background == f->output_data.mac->cursor_pixel)
4745 xgcv.background = xgcv.foreground = face->foreground;
4746 else
4747 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel;
4748
4749 if (gc)
4750 XChangeGC (dpy, gc, mask, &xgcv);
4751 else
4752 {
4753 gc = XCreateGC (dpy, window, mask, &xgcv);
4754 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc;
4755 }
4756
4757 if (width < 0)
4758 width = FRAME_CURSOR_WIDTH (f);
4759 width = min (cursor_glyph->pixel_width, width);
4760
4761 w->phys_cursor_width = width;
4762 x_clip_to_row (w, row, gc);
4763
4764 if (kind == BAR_CURSOR)
4765 XFillRectangle (dpy, window, gc,
4766 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
4767 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y),
4768 width, row->height);
4769 else
4770 XFillRectangle (dpy, window, gc,
4771 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x),
4772 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y +
4773 row->height - width),
4774 cursor_glyph->pixel_width,
4775 width);
4776
4777 mac_reset_clipping (dpy, FRAME_MAC_WINDOW (f));
4778 }
4779 }
4780
4781
4782 /* RIF: Define cursor CURSOR on frame F. */
4783
4784 static void
4785 mac_define_frame_cursor (f, cursor)
4786 struct frame *f;
4787 Cursor cursor;
4788 {
4789 #if TARGET_API_MAC_CARBON
4790 SetThemeCursor (cursor);
4791 #else
4792 SetCursor (*cursor);
4793 #endif
4794 }
4795
4796
4797 /* RIF: Clear area on frame F. */
4798
4799 static void
4800 mac_clear_frame_area (f, x, y, width, height)
4801 struct frame *f;
4802 int x, y, width, height;
4803 {
4804 XClearArea (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f),
4805 x, y, width, height, 0);
4806 }
4807
4808
4809 /* RIF: Draw cursor on window W. */
4810
4811 static void
4812 mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p)
4813 struct window *w;
4814 struct glyph_row *glyph_row;
4815 int x, y;
4816 int cursor_type, cursor_width;
4817 int on_p, active_p;
4818 {
4819 if (on_p)
4820 {
4821 w->phys_cursor_type = cursor_type;
4822 w->phys_cursor_on_p = 1;
4823
4824 if (glyph_row->exact_window_width_line_p
4825 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
4826 {
4827 glyph_row->cursor_in_fringe_p = 1;
4828 draw_fringe_bitmap (w, glyph_row, 0);
4829 }
4830 else
4831 switch (cursor_type)
4832 {
4833 case HOLLOW_BOX_CURSOR:
4834 x_draw_hollow_cursor (w, glyph_row);
4835 break;
4836
4837 case FILLED_BOX_CURSOR:
4838 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
4839 break;
4840
4841 case BAR_CURSOR:
4842 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR);
4843 break;
4844
4845 case HBAR_CURSOR:
4846 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR);
4847 break;
4848
4849 case NO_CURSOR:
4850 w->phys_cursor_width = 0;
4851 break;
4852
4853 default:
4854 abort ();
4855 }
4856 }
4857 }
4858
4859 \f
4860 /* Icons. */
4861
4862 #if 0 /* MAC_TODO: no icon support yet. */
4863 int
4864 x_bitmap_icon (f, icon)
4865 struct frame *f;
4866 Lisp_Object icon;
4867 {
4868 HANDLE hicon;
4869
4870 if (FRAME_W32_WINDOW (f) == 0)
4871 return 1;
4872
4873 if (NILP (icon))
4874 hicon = LoadIcon (hinst, EMACS_CLASS);
4875 else if (STRINGP (icon))
4876 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0,
4877 LR_DEFAULTSIZE | LR_LOADFROMFILE);
4878 else if (SYMBOLP (icon))
4879 {
4880 LPCTSTR name;
4881
4882 if (EQ (icon, intern ("application")))
4883 name = (LPCTSTR) IDI_APPLICATION;
4884 else if (EQ (icon, intern ("hand")))
4885 name = (LPCTSTR) IDI_HAND;
4886 else if (EQ (icon, intern ("question")))
4887 name = (LPCTSTR) IDI_QUESTION;
4888 else if (EQ (icon, intern ("exclamation")))
4889 name = (LPCTSTR) IDI_EXCLAMATION;
4890 else if (EQ (icon, intern ("asterisk")))
4891 name = (LPCTSTR) IDI_ASTERISK;
4892 else if (EQ (icon, intern ("winlogo")))
4893 name = (LPCTSTR) IDI_WINLOGO;
4894 else
4895 return 1;
4896
4897 hicon = LoadIcon (NULL, name);
4898 }
4899 else
4900 return 1;
4901
4902 if (hicon == NULL)
4903 return 1;
4904
4905 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG,
4906 (LPARAM) hicon);
4907
4908 return 0;
4909 }
4910 #endif /* MAC_TODO */
4911 \f
4912 /************************************************************************
4913 Handling X errors
4914 ************************************************************************/
4915
4916 /* Display Error Handling functions not used on W32. Listing them here
4917 helps diff stay in step when comparing w32term.c with xterm.c.
4918
4919 x_error_catcher (display, error)
4920 x_catch_errors (dpy)
4921 x_catch_errors_unwind (old_val)
4922 x_check_errors (dpy, format)
4923 x_had_errors_p (dpy)
4924 x_clear_errors (dpy)
4925 x_uncatch_errors (dpy, count)
4926 x_trace_wire ()
4927 x_connection_signal (signalnum)
4928 x_connection_closed (dpy, error_message)
4929 x_error_quitter (display, error)
4930 x_error_handler (display, error)
4931 x_io_error_quitter (display)
4932
4933 */
4934
4935 \f
4936 /* Changing the font of the frame. */
4937
4938 /* Give frame F the font named FONTNAME as its default font, and
4939 return the full name of that font. FONTNAME may be a wildcard
4940 pattern; in that case, we choose some font that fits the pattern.
4941 The return value shows which font we chose. */
4942
4943 Lisp_Object
4944 x_new_font (f, fontname)
4945 struct frame *f;
4946 register char *fontname;
4947 {
4948 struct font_info *fontp
4949 = FS_LOAD_FONT (f, 0, fontname, -1);
4950
4951 if (!fontp)
4952 return Qnil;
4953
4954 FRAME_FONT (f) = (XFontStruct *) (fontp->font);
4955 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset;
4956 FRAME_FONTSET (f) = -1;
4957
4958 FRAME_COLUMN_WIDTH (f) = FONT_WIDTH (FRAME_FONT (f));
4959 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f));
4960
4961 compute_fringe_widths (f, 1);
4962
4963 /* Compute the scroll bar width in character columns. */
4964 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
4965 {
4966 int wid = FRAME_COLUMN_WIDTH (f);
4967 FRAME_CONFIG_SCROLL_BAR_COLS (f)
4968 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid;
4969 }
4970 else
4971 {
4972 int wid = FRAME_COLUMN_WIDTH (f);
4973 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
4974 }
4975
4976 /* Now make the frame display the given font. */
4977 if (FRAME_MAC_WINDOW (f) != 0)
4978 {
4979 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc,
4980 FRAME_FONT (f));
4981 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc,
4982 FRAME_FONT (f));
4983 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc,
4984 FRAME_FONT (f));
4985
4986 if (NILP (tip_frame) || XFRAME (tip_frame) != f)
4987 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
4988 }
4989
4990 return build_string (fontp->full_name);
4991 }
4992 \f
4993 /* Give frame F the fontset named FONTSETNAME as its default font, and
4994 return the full name of that fontset. FONTSETNAME may be a wildcard
4995 pattern; in that case, we choose some fontset that fits the pattern.
4996 The return value shows which fontset we chose. */
4997
4998 Lisp_Object
4999 x_new_fontset (f, fontsetname)
5000 struct frame *f;
5001 char *fontsetname;
5002 {
5003 int fontset = fs_query_fontset (build_string (fontsetname), 0);
5004 Lisp_Object result;
5005
5006 if (fontset < 0)
5007 return Qnil;
5008
5009 if (FRAME_FONTSET (f) == fontset)
5010 /* This fontset is already set in frame F. There's nothing more
5011 to do. */
5012 return fontset_name (fontset);
5013
5014 result = x_new_font (f, (SDATA (fontset_ascii (fontset))));
5015
5016 if (!STRINGP (result))
5017 /* Can't load ASCII font. */
5018 return Qnil;
5019
5020 /* Since x_new_font doesn't update any fontset information, do it now. */
5021 FRAME_FONTSET(f) = fontset;
5022
5023 return build_string (fontsetname);
5024 }
5025
5026 \f
5027 /***********************************************************************
5028 TODO: W32 Input Methods
5029 ***********************************************************************/
5030 /* Listing missing functions from xterm.c helps diff stay in step.
5031
5032 xim_destroy_callback (xim, client_data, call_data)
5033 xim_open_dpy (dpyinfo, resource_name)
5034 struct xim_inst_t
5035 xim_instantiate_callback (display, client_data, call_data)
5036 xim_initialize (dpyinfo, resource_name)
5037 xim_close_dpy (dpyinfo)
5038
5039 */
5040
5041 \f
5042 void
5043 mac_get_window_bounds (f, inner, outer)
5044 struct frame *f;
5045 Rect *inner, *outer;
5046 {
5047 #if TARGET_API_MAC_CARBON
5048 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner);
5049 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer);
5050 #else /* not TARGET_API_MAC_CARBON */
5051 RgnHandle region = NewRgn ();
5052
5053 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region);
5054 *inner = (*region)->rgnBBox;
5055 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region);
5056 *outer = (*region)->rgnBBox;
5057 DisposeRgn (region);
5058 #endif /* not TARGET_API_MAC_CARBON */
5059 }
5060
5061
5062 /* Calculate the absolute position in frame F
5063 from its current recorded position values and gravity. */
5064
5065 void
5066 x_calc_absolute_position (f)
5067 struct frame *f;
5068 {
5069 int width_diff = 0, height_diff = 0;
5070 int flags = f->size_hint_flags;
5071 Rect inner, outer;
5072
5073 /* We have nothing to do if the current position
5074 is already for the top-left corner. */
5075 if (! ((flags & XNegative) || (flags & YNegative)))
5076 return;
5077
5078 /* Find the offsets of the outside upper-left corner of
5079 the inner window, with respect to the outer window. */
5080 mac_get_window_bounds (f, &inner, &outer);
5081
5082 width_diff = (outer.right - outer.left) - (inner.right - inner.left);
5083 height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top);
5084
5085 /* Treat negative positions as relative to the leftmost bottommost
5086 position that fits on the screen. */
5087 if (flags & XNegative)
5088 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width
5089 - width_diff
5090 - FRAME_PIXEL_WIDTH (f)
5091 + f->left_pos);
5092
5093 if (flags & YNegative)
5094 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height
5095 - height_diff
5096 - FRAME_PIXEL_HEIGHT (f)
5097 + f->top_pos);
5098
5099 /* The left_pos and top_pos
5100 are now relative to the top and left screen edges,
5101 so the flags should correspond. */
5102 f->size_hint_flags &= ~ (XNegative | YNegative);
5103 }
5104
5105 /* CHANGE_GRAVITY is 1 when calling from Fset_frame_position,
5106 to really change the position, and 0 when calling from
5107 x_make_frame_visible (in that case, XOFF and YOFF are the current
5108 position values). It is -1 when calling from x_set_frame_parameters,
5109 which means, do adjust for borders but don't change the gravity. */
5110
5111 void
5112 x_set_offset (f, xoff, yoff, change_gravity)
5113 struct frame *f;
5114 register int xoff, yoff;
5115 int change_gravity;
5116 {
5117 if (change_gravity > 0)
5118 {
5119 f->top_pos = yoff;
5120 f->left_pos = xoff;
5121 f->size_hint_flags &= ~ (XNegative | YNegative);
5122 if (xoff < 0)
5123 f->size_hint_flags |= XNegative;
5124 if (yoff < 0)
5125 f->size_hint_flags |= YNegative;
5126 f->win_gravity = NorthWestGravity;
5127 }
5128 x_calc_absolute_position (f);
5129
5130 BLOCK_INPUT;
5131 x_wm_set_size_hint (f, (long) 0, 0);
5132
5133 #if TARGET_API_MAC_CARBON
5134 MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos);
5135 /* If the title bar is completely outside the screen, adjust the
5136 position. */
5137 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn,
5138 kWindowConstrainMoveRegardlessOfFit
5139 | kWindowConstrainAllowPartial, NULL, NULL);
5140 x_real_positions (f, &f->left_pos, &f->top_pos);
5141 #else
5142 {
5143 Rect inner, outer, screen_rect, dummy;
5144 RgnHandle region = NewRgn ();
5145
5146 mac_get_window_bounds (f, &inner, &outer);
5147 f->x_pixels_diff = inner.left - outer.left;
5148 f->y_pixels_diff = inner.top - outer.top;
5149 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5150 f->top_pos + f->y_pixels_diff, false);
5151
5152 /* If the title bar is completely outside the screen, adjust the
5153 position. The variable `outer' holds the title bar rectangle.
5154 The variable `inner' holds slightly smaller one than `outer',
5155 so that the calculation of overlapping may not become too
5156 strict. */
5157 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region);
5158 outer = (*region)->rgnBBox;
5159 DisposeRgn (region);
5160 inner = outer;
5161 InsetRect (&inner, 8, 8);
5162 screen_rect = qd.screenBits.bounds;
5163 screen_rect.top += GetMBarHeight ();
5164
5165 if (!SectRect (&inner, &screen_rect, &dummy))
5166 {
5167 if (inner.right <= screen_rect.left)
5168 f->left_pos = screen_rect.left;
5169 else if (inner.left >= screen_rect.right)
5170 f->left_pos = screen_rect.right - (outer.right - outer.left);
5171
5172 if (inner.bottom <= screen_rect.top)
5173 f->top_pos = screen_rect.top;
5174 else if (inner.top >= screen_rect.bottom)
5175 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top);
5176
5177 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff,
5178 f->top_pos + f->y_pixels_diff, false);
5179 }
5180 }
5181 #endif
5182
5183 UNBLOCK_INPUT;
5184 }
5185
5186 /* Call this to change the size of frame F's x-window.
5187 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity
5188 for this size change and subsequent size changes.
5189 Otherwise we leave the window gravity unchanged. */
5190
5191 void
5192 x_set_window_size (f, change_gravity, cols, rows)
5193 struct frame *f;
5194 int change_gravity;
5195 int cols, rows;
5196 {
5197 int pixelwidth, pixelheight;
5198
5199 BLOCK_INPUT;
5200
5201 check_frame_size (f, &rows, &cols);
5202 f->scroll_bar_actual_width
5203 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f);
5204
5205 compute_fringe_widths (f, 0);
5206
5207 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
5208 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
5209
5210 f->win_gravity = NorthWestGravity;
5211 x_wm_set_size_hint (f, (long) 0, 0);
5212
5213 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0);
5214
5215 /* Now, strictly speaking, we can't be sure that this is accurate,
5216 but the window manager will get around to dealing with the size
5217 change request eventually, and we'll hear how it went when the
5218 ConfigureNotify event gets here.
5219
5220 We could just not bother storing any of this information here,
5221 and let the ConfigureNotify event set everything up, but that
5222 might be kind of confusing to the Lisp code, since size changes
5223 wouldn't be reported in the frame parameters until some random
5224 point in the future when the ConfigureNotify event arrives.
5225
5226 We pass 1 for DELAY since we can't run Lisp code inside of
5227 a BLOCK_INPUT. */
5228 change_frame_size (f, rows, cols, 0, 1, 0);
5229 FRAME_PIXEL_WIDTH (f) = pixelwidth;
5230 FRAME_PIXEL_HEIGHT (f) = pixelheight;
5231
5232 /* We've set {FRAME,PIXEL}_{WIDTH,HEIGHT} to the values we hope to
5233 receive in the ConfigureNotify event; if we get what we asked
5234 for, then the event won't cause the screen to become garbaged, so
5235 we have to make sure to do it here. */
5236 SET_FRAME_GARBAGED (f);
5237
5238 XFlush (FRAME_X_DISPLAY (f));
5239
5240 /* If cursor was outside the new size, mark it as off. */
5241 mark_window_cursors_off (XWINDOW (f->root_window));
5242
5243 /* Clear out any recollection of where the mouse highlighting was,
5244 since it might be in a place that's outside the new frame size.
5245 Actually checking whether it is outside is a pain in the neck,
5246 so don't try--just let the highlighting be done afresh with new size. */
5247 cancel_mouse_face (f);
5248
5249 UNBLOCK_INPUT;
5250 }
5251 \f
5252 /* Mouse warping. */
5253
5254 void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y);
5255
5256 void
5257 x_set_mouse_position (f, x, y)
5258 struct frame *f;
5259 int x, y;
5260 {
5261 int pix_x, pix_y;
5262
5263 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2;
5264 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2;
5265
5266 if (pix_x < 0) pix_x = 0;
5267 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
5268
5269 if (pix_y < 0) pix_y = 0;
5270 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
5271
5272 x_set_mouse_pixel_position (f, pix_x, pix_y);
5273 }
5274
5275 void
5276 x_set_mouse_pixel_position (f, pix_x, pix_y)
5277 struct frame *f;
5278 int pix_x, pix_y;
5279 {
5280 #if 0 /* MAC_TODO: CursorDeviceMoveTo is non-Carbon */
5281 BLOCK_INPUT;
5282
5283 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f),
5284 0, 0, 0, 0, pix_x, pix_y);
5285 UNBLOCK_INPUT;
5286 #endif
5287 }
5288
5289 \f
5290 /* focus shifting, raising and lowering. */
5291
5292 void
5293 x_focus_on_frame (f)
5294 struct frame *f;
5295 {
5296 #if 0 /* This proves to be unpleasant. */
5297 x_raise_frame (f);
5298 #endif
5299 #if 0
5300 /* I don't think that the ICCCM allows programs to do things like this
5301 without the interaction of the window manager. Whatever you end up
5302 doing with this code, do it to x_unfocus_frame too. */
5303 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f),
5304 RevertToPointerRoot, CurrentTime);
5305 #endif /* ! 0 */
5306 }
5307
5308 void
5309 x_unfocus_frame (f)
5310 struct frame *f;
5311 {
5312 }
5313
5314 /* Raise frame F. */
5315 void
5316 x_raise_frame (f)
5317 struct frame *f;
5318 {
5319 if (f->async_visible)
5320 {
5321 BLOCK_INPUT;
5322 SelectWindow (FRAME_MAC_WINDOW (f));
5323 UNBLOCK_INPUT;
5324 }
5325 }
5326
5327 /* Lower frame F. */
5328 void
5329 x_lower_frame (f)
5330 struct frame *f;
5331 {
5332 if (f->async_visible)
5333 {
5334 BLOCK_INPUT;
5335 SendBehind (FRAME_MAC_WINDOW (f), nil);
5336 UNBLOCK_INPUT;
5337 }
5338 }
5339
5340 static void
5341 XTframe_raise_lower (f, raise_flag)
5342 FRAME_PTR f;
5343 int raise_flag;
5344 {
5345 if (raise_flag)
5346 x_raise_frame (f);
5347 else
5348 x_lower_frame (f);
5349 }
5350 \f
5351 /* Change of visibility. */
5352
5353 /* This tries to wait until the frame is really visible.
5354 However, if the window manager asks the user where to position
5355 the frame, this will return before the user finishes doing that.
5356 The frame will not actually be visible at that time,
5357 but it will become visible later when the window manager
5358 finishes with it. */
5359
5360 void
5361 x_make_frame_visible (f)
5362 struct frame *f;
5363 {
5364 Lisp_Object type;
5365 int original_top, original_left;
5366
5367 BLOCK_INPUT;
5368
5369 if (! FRAME_VISIBLE_P (f))
5370 {
5371 /* We test FRAME_GARBAGED_P here to make sure we don't
5372 call x_set_offset a second time
5373 if we get to x_make_frame_visible a second time
5374 before the window gets really visible. */
5375 if (! FRAME_ICONIFIED_P (f)
5376 && ! f->output_data.mac->asked_for_visible)
5377 x_set_offset (f, f->left_pos, f->top_pos, 0);
5378
5379 f->output_data.mac->asked_for_visible = 1;
5380
5381 ShowWindow (FRAME_MAC_WINDOW (f));
5382 }
5383
5384 XFlush (FRAME_MAC_DISPLAY (f));
5385
5386 /* Synchronize to ensure Emacs knows the frame is visible
5387 before we do anything else. We do this loop with input not blocked
5388 so that incoming events are handled. */
5389 {
5390 Lisp_Object frame;
5391 int count;
5392
5393 /* This must come after we set COUNT. */
5394 UNBLOCK_INPUT;
5395
5396 XSETFRAME (frame, f);
5397
5398 /* Wait until the frame is visible. Process X events until a
5399 MapNotify event has been seen, or until we think we won't get a
5400 MapNotify at all.. */
5401 for (count = input_signal_count + 10;
5402 input_signal_count < count && !FRAME_VISIBLE_P (f);)
5403 {
5404 /* Force processing of queued events. */
5405 x_sync (f);
5406
5407 /* Machines that do polling rather than SIGIO have been
5408 observed to go into a busy-wait here. So we'll fake an
5409 alarm signal to let the handler know that there's something
5410 to be read. We used to raise a real alarm, but it seems
5411 that the handler isn't always enabled here. This is
5412 probably a bug. */
5413 if (input_polling_used ())
5414 {
5415 /* It could be confusing if a real alarm arrives while
5416 processing the fake one. Turn it off and let the
5417 handler reset it. */
5418 extern void poll_for_input_1 P_ ((void));
5419 int old_poll_suppress_count = poll_suppress_count;
5420 poll_suppress_count = 1;
5421 poll_for_input_1 ();
5422 poll_suppress_count = old_poll_suppress_count;
5423 }
5424
5425 /* See if a MapNotify event has been processed. */
5426 FRAME_SAMPLE_VISIBILITY (f);
5427 }
5428 }
5429 }
5430
5431 /* Change from mapped state to withdrawn state. */
5432
5433 /* Make the frame visible (mapped and not iconified). */
5434
5435 void
5436 x_make_frame_invisible (f)
5437 struct frame *f;
5438 {
5439 /* Don't keep the highlight on an invisible frame. */
5440 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5441 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5442
5443 BLOCK_INPUT;
5444
5445 HideWindow (FRAME_MAC_WINDOW (f));
5446
5447 /* We can't distinguish this from iconification
5448 just by the event that we get from the server.
5449 So we can't win using the usual strategy of letting
5450 FRAME_SAMPLE_VISIBILITY set this. So do it by hand,
5451 and synchronize with the server to make sure we agree. */
5452 f->visible = 0;
5453 FRAME_ICONIFIED_P (f) = 0;
5454 f->async_visible = 0;
5455 f->async_iconified = 0;
5456
5457 UNBLOCK_INPUT;
5458 }
5459
5460 /* Change window state from mapped to iconified. */
5461
5462 void
5463 x_iconify_frame (f)
5464 struct frame *f;
5465 {
5466 /* Don't keep the highlight on an invisible frame. */
5467 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f)
5468 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0;
5469
5470 #if 0
5471 /* Review: Since window is still visible in dock, still allow updates? */
5472 if (f->async_iconified)
5473 return;
5474 #endif
5475
5476 BLOCK_INPUT;
5477
5478 CollapseWindow (FRAME_MAC_WINDOW (f), true);
5479
5480 UNBLOCK_INPUT;
5481 }
5482
5483 \f
5484 /* Free X resources of frame F. */
5485
5486 void
5487 x_free_frame_resources (f)
5488 struct frame *f;
5489 {
5490 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5491 WindowPtr wp = FRAME_MAC_WINDOW (f);
5492
5493 BLOCK_INPUT;
5494
5495 DisposeWindow (wp);
5496 if (wp == tip_window)
5497 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window
5498 closed' event. So we reset tip_window here. */
5499 tip_window = NULL;
5500
5501 free_frame_menubar (f);
5502
5503 if (FRAME_FACE_CACHE (f))
5504 free_frame_faces (f);
5505
5506 x_free_gcs (f);
5507
5508 xfree (f->output_data.mac);
5509 f->output_data.mac = NULL;
5510
5511 if (f == dpyinfo->x_focus_frame)
5512 dpyinfo->x_focus_frame = 0;
5513 if (f == dpyinfo->x_focus_event_frame)
5514 dpyinfo->x_focus_event_frame = 0;
5515 if (f == dpyinfo->x_highlight_frame)
5516 dpyinfo->x_highlight_frame = 0;
5517
5518 if (f == dpyinfo->mouse_face_mouse_frame)
5519 {
5520 dpyinfo->mouse_face_beg_row
5521 = dpyinfo->mouse_face_beg_col = -1;
5522 dpyinfo->mouse_face_end_row
5523 = dpyinfo->mouse_face_end_col = -1;
5524 dpyinfo->mouse_face_window = Qnil;
5525 dpyinfo->mouse_face_deferred_gc = 0;
5526 dpyinfo->mouse_face_mouse_frame = 0;
5527 }
5528
5529 UNBLOCK_INPUT;
5530 }
5531
5532
5533 /* Destroy the X window of frame F. */
5534
5535 void
5536 x_destroy_window (f)
5537 struct frame *f;
5538 {
5539 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
5540
5541 x_free_frame_resources (f);
5542
5543 dpyinfo->reference_count--;
5544 }
5545
5546 \f
5547 /* Setting window manager hints. */
5548
5549 /* Set the normal size hints for the window manager, for frame F.
5550 FLAGS is the flags word to use--or 0 meaning preserve the flags
5551 that the window now has.
5552 If USER_POSITION is nonzero, we set the USPosition
5553 flag (this is useful when FLAGS is 0). */
5554 void
5555 x_wm_set_size_hint (f, flags, user_position)
5556 struct frame *f;
5557 long flags;
5558 int user_position;
5559 {
5560 #if 0 /* MAC_TODO: connect this to the Appearance Manager */
5561 XSizeHints size_hints;
5562
5563 #ifdef USE_X_TOOLKIT
5564 Arg al[2];
5565 int ac = 0;
5566 Dimension widget_width, widget_height;
5567 Window window = XtWindow (f->output_data.x->widget);
5568 #else /* not USE_X_TOOLKIT */
5569 Window window = FRAME_X_WINDOW (f);
5570 #endif /* not USE_X_TOOLKIT */
5571
5572 /* Setting PMaxSize caused various problems. */
5573 size_hints.flags = PResizeInc | PMinSize /* | PMaxSize */;
5574
5575 size_hints.x = f->left_pos;
5576 size_hints.y = f->top_pos;
5577
5578 #ifdef USE_X_TOOLKIT
5579 XtSetArg (al[ac], XtNwidth, &widget_width); ac++;
5580 XtSetArg (al[ac], XtNheight, &widget_height); ac++;
5581 XtGetValues (f->output_data.x->widget, al, ac);
5582 size_hints.height = widget_height;
5583 size_hints.width = widget_width;
5584 #else /* not USE_X_TOOLKIT */
5585 size_hints.height = FRAME_PIXEL_HEIGHT (f);
5586 size_hints.width = FRAME_PIXEL_WIDTH (f);
5587 #endif /* not USE_X_TOOLKIT */
5588
5589 size_hints.width_inc = FRAME_COLUMN_WIDTH (f);
5590 size_hints.height_inc = FRAME_LINE_HEIGHT (f);
5591 size_hints.max_width
5592 = FRAME_X_DISPLAY_INFO (f)->width - FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
5593 size_hints.max_height
5594 = FRAME_X_DISPLAY_INFO (f)->height - FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
5595
5596 /* Calculate the base and minimum sizes.
5597
5598 (When we use the X toolkit, we don't do it here.
5599 Instead we copy the values that the widgets are using, below.) */
5600 #ifndef USE_X_TOOLKIT
5601 {
5602 int base_width, base_height;
5603 int min_rows = 0, min_cols = 0;
5604
5605 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0);
5606 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0);
5607
5608 check_frame_size (f, &min_rows, &min_cols);
5609
5610 /* The window manager uses the base width hints to calculate the
5611 current number of rows and columns in the frame while
5612 resizing; min_width and min_height aren't useful for this
5613 purpose, since they might not give the dimensions for a
5614 zero-row, zero-column frame.
5615
5616 We use the base_width and base_height members if we have
5617 them; otherwise, we set the min_width and min_height members
5618 to the size for a zero x zero frame. */
5619
5620 #ifdef HAVE_X11R4
5621 size_hints.flags |= PBaseSize;
5622 size_hints.base_width = base_width;
5623 size_hints.base_height = base_height;
5624 size_hints.min_width = base_width + min_cols * size_hints.width_inc;
5625 size_hints.min_height = base_height + min_rows * size_hints.height_inc;
5626 #else
5627 size_hints.min_width = base_width;
5628 size_hints.min_height = base_height;
5629 #endif
5630 }
5631
5632 /* If we don't need the old flags, we don't need the old hint at all. */
5633 if (flags)
5634 {
5635 size_hints.flags |= flags;
5636 goto no_read;
5637 }
5638 #endif /* not USE_X_TOOLKIT */
5639
5640 {
5641 XSizeHints hints; /* Sometimes I hate X Windows... */
5642 long supplied_return;
5643 int value;
5644
5645 #ifdef HAVE_X11R4
5646 value = XGetWMNormalHints (FRAME_X_DISPLAY (f), window, &hints,
5647 &supplied_return);
5648 #else
5649 value = XGetNormalHints (FRAME_X_DISPLAY (f), window, &hints);
5650 #endif
5651
5652 #ifdef USE_X_TOOLKIT
5653 size_hints.base_height = hints.base_height;
5654 size_hints.base_width = hints.base_width;
5655 size_hints.min_height = hints.min_height;
5656 size_hints.min_width = hints.min_width;
5657 #endif
5658
5659 if (flags)
5660 size_hints.flags |= flags;
5661 else
5662 {
5663 if (value == 0)
5664 hints.flags = 0;
5665 if (hints.flags & PSize)
5666 size_hints.flags |= PSize;
5667 if (hints.flags & PPosition)
5668 size_hints.flags |= PPosition;
5669 if (hints.flags & USPosition)
5670 size_hints.flags |= USPosition;
5671 if (hints.flags & USSize)
5672 size_hints.flags |= USSize;
5673 }
5674 }
5675
5676 #ifndef USE_X_TOOLKIT
5677 no_read:
5678 #endif
5679
5680 #ifdef PWinGravity
5681 size_hints.win_gravity = f->win_gravity;
5682 size_hints.flags |= PWinGravity;
5683
5684 if (user_position)
5685 {
5686 size_hints.flags &= ~ PPosition;
5687 size_hints.flags |= USPosition;
5688 }
5689 #endif /* PWinGravity */
5690
5691 #ifdef HAVE_X11R4
5692 XSetWMNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
5693 #else
5694 XSetNormalHints (FRAME_X_DISPLAY (f), window, &size_hints);
5695 #endif
5696 #endif /* MAC_TODO */
5697 }
5698
5699 #if 0 /* MAC_TODO: hide application instead of iconify? */
5700 /* Used for IconicState or NormalState */
5701
5702 void
5703 x_wm_set_window_state (f, state)
5704 struct frame *f;
5705 int state;
5706 {
5707 #ifdef USE_X_TOOLKIT
5708 Arg al[1];
5709
5710 XtSetArg (al[0], XtNinitialState, state);
5711 XtSetValues (f->output_data.x->widget, al, 1);
5712 #else /* not USE_X_TOOLKIT */
5713 Window window = FRAME_X_WINDOW (f);
5714
5715 f->output_data.x->wm_hints.flags |= StateHint;
5716 f->output_data.x->wm_hints.initial_state = state;
5717
5718 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5719 #endif /* not USE_X_TOOLKIT */
5720 }
5721
5722 void
5723 x_wm_set_icon_pixmap (f, pixmap_id)
5724 struct frame *f;
5725 int pixmap_id;
5726 {
5727 Pixmap icon_pixmap;
5728
5729 #ifndef USE_X_TOOLKIT
5730 Window window = FRAME_X_WINDOW (f);
5731 #endif
5732
5733 if (pixmap_id > 0)
5734 {
5735 icon_pixmap = x_bitmap_pixmap (f, pixmap_id);
5736 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap;
5737 }
5738 else
5739 {
5740 /* It seems there is no way to turn off use of an icon pixmap.
5741 The following line does it, only if no icon has yet been created,
5742 for some window managers. But with mwm it crashes.
5743 Some people say it should clear the IconPixmapHint bit in this case,
5744 but that doesn't work, and the X consortium said it isn't the
5745 right thing at all. Since there is no way to win,
5746 best to explicitly give up. */
5747 #if 0
5748 f->output_data.x->wm_hints.icon_pixmap = None;
5749 #else
5750 return;
5751 #endif
5752 }
5753
5754 #ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */
5755
5756 {
5757 Arg al[1];
5758 XtSetArg (al[0], XtNiconPixmap, icon_pixmap);
5759 XtSetValues (f->output_data.x->widget, al, 1);
5760 }
5761
5762 #else /* not USE_X_TOOLKIT */
5763
5764 f->output_data.x->wm_hints.flags |= IconPixmapHint;
5765 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5766
5767 #endif /* not USE_X_TOOLKIT */
5768 }
5769
5770 #endif /* MAC_TODO */
5771
5772 void
5773 x_wm_set_icon_position (f, icon_x, icon_y)
5774 struct frame *f;
5775 int icon_x, icon_y;
5776 {
5777 #if 0 /* MAC_TODO: no icons on Mac */
5778 #ifdef USE_X_TOOLKIT
5779 Window window = XtWindow (f->output_data.x->widget);
5780 #else
5781 Window window = FRAME_X_WINDOW (f);
5782 #endif
5783
5784 f->output_data.x->wm_hints.flags |= IconPositionHint;
5785 f->output_data.x->wm_hints.icon_x = icon_x;
5786 f->output_data.x->wm_hints.icon_y = icon_y;
5787
5788 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints);
5789 #endif /* MAC_TODO */
5790 }
5791
5792 \f
5793 /***********************************************************************
5794 Fonts
5795 ***********************************************************************/
5796
5797 /* Return a pointer to struct font_info of font FONT_IDX of frame F. */
5798
5799 struct font_info *
5800 x_get_font_info (f, font_idx)
5801 FRAME_PTR f;
5802 int font_idx;
5803 {
5804 return (FRAME_MAC_FONT_TABLE (f) + font_idx);
5805 }
5806
5807 /* the global font name table */
5808 char **font_name_table = NULL;
5809 int font_name_table_size = 0;
5810 int font_name_count = 0;
5811
5812 #if 0
5813 /* compare two strings ignoring case */
5814 static int
5815 stricmp (const char *s, const char *t)
5816 {
5817 for ( ; tolower (*s) == tolower (*t); s++, t++)
5818 if (*s == '\0')
5819 return 0;
5820 return tolower (*s) - tolower (*t);
5821 }
5822
5823 /* compare two strings ignoring case and handling wildcard */
5824 static int
5825 wildstrieq (char *s1, char *s2)
5826 {
5827 if (strcmp (s1, "*") == 0 || strcmp (s2, "*") == 0)
5828 return true;
5829
5830 return stricmp (s1, s2) == 0;
5831 }
5832
5833 /* Assume parameter 1 is fully qualified, no wildcards. */
5834 static int
5835 mac_font_pattern_match (fontname, pattern)
5836 char * fontname;
5837 char * pattern;
5838 {
5839 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
5840 char *font_name_copy = (char *) alloca (strlen (fontname) + 1);
5841 char *ptr;
5842
5843 /* Copy fontname so we can modify it during comparison. */
5844 strcpy (font_name_copy, fontname);
5845
5846 ptr = regex;
5847 *ptr++ = '^';
5848
5849 /* Turn pattern into a regexp and do a regexp match. */
5850 for (; *pattern; pattern++)
5851 {
5852 if (*pattern == '?')
5853 *ptr++ = '.';
5854 else if (*pattern == '*')
5855 {
5856 *ptr++ = '.';
5857 *ptr++ = '*';
5858 }
5859 else
5860 *ptr++ = *pattern;
5861 }
5862 *ptr = '$';
5863 *(ptr + 1) = '\0';
5864
5865 return (fast_c_string_match_ignore_case (build_string (regex),
5866 font_name_copy) >= 0);
5867 }
5868
5869 /* Two font specs are considered to match if their foundry, family,
5870 weight, slant, and charset match. */
5871 static int
5872 mac_font_match (char *mf, char *xf)
5873 {
5874 char m_foundry[50], m_family[50], m_weight[20], m_slant[2], m_charset[20];
5875 char x_foundry[50], x_family[50], x_weight[20], x_slant[2], x_charset[20];
5876
5877 if (sscanf (mf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5878 m_foundry, m_family, m_weight, m_slant, m_charset) != 5)
5879 return mac_font_pattern_match (mf, xf);
5880
5881 if (sscanf (xf, "-%49[^-]-%49[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%19s",
5882 x_foundry, x_family, x_weight, x_slant, x_charset) != 5)
5883 return mac_font_pattern_match (mf, xf);
5884
5885 return (wildstrieq (m_foundry, x_foundry)
5886 && wildstrieq (m_family, x_family)
5887 && wildstrieq (m_weight, x_weight)
5888 && wildstrieq (m_slant, x_slant)
5889 && wildstrieq (m_charset, x_charset))
5890 || mac_font_pattern_match (mf, xf);
5891 }
5892 #endif
5893
5894 static Lisp_Object Qbig5, Qcn_gb, Qsjis, Qeuc_kr;
5895
5896 static void
5897 decode_mac_font_name (char *name, int size, short scriptcode)
5898 {
5899 Lisp_Object coding_system;
5900 struct coding_system coding;
5901 char *buf;
5902
5903 switch (scriptcode)
5904 {
5905 case smTradChinese:
5906 coding_system = Qbig5;
5907 break;
5908 case smSimpChinese:
5909 coding_system = Qcn_gb;
5910 break;
5911 case smJapanese:
5912 coding_system = Qsjis;
5913 break;
5914 case smKorean:
5915 coding_system = Qeuc_kr;
5916 break;
5917 default:
5918 return;
5919 }
5920
5921 setup_coding_system (coding_system, &coding);
5922 coding.src_multibyte = 0;
5923 coding.dst_multibyte = 1;
5924 coding.mode |= CODING_MODE_LAST_BLOCK;
5925 coding.composing = COMPOSITION_DISABLED;
5926 buf = (char *) alloca (size);
5927
5928 decode_coding (&coding, name, buf, strlen (name), size - 1);
5929 bcopy (buf, name, coding.produced);
5930 name[coding.produced] = '\0';
5931 }
5932
5933
5934 static char *
5935 mac_to_x_fontname (char *name, int size, Style style, short scriptcode)
5936 {
5937 char foundry[32], family[32], cs[32];
5938 char xf[256], *result, *p;
5939
5940 if (sscanf (name, "%31[^-]-%31[^-]-%31s", foundry, family, cs) != 3)
5941 {
5942 strcpy(foundry, "Apple");
5943 strcpy(family, name);
5944
5945 switch (scriptcode)
5946 {
5947 case smTradChinese:
5948 strcpy(cs, "big5-0");
5949 break;
5950 case smSimpChinese:
5951 strcpy(cs, "gb2312.1980-0");
5952 break;
5953 case smJapanese:
5954 strcpy(cs, "jisx0208.1983-sjis");
5955 break;
5956 case -smJapanese:
5957 /* Each Apple Japanese font is entered into the font table
5958 twice: once as a jisx0208.1983-sjis font and once as a
5959 jisx0201.1976-0 font. The latter can be used to display
5960 the ascii charset and katakana-jisx0201 charset. A
5961 negative script code signals that the name of this latter
5962 font is being built. */
5963 strcpy(cs, "jisx0201.1976-0");
5964 break;
5965 case smKorean:
5966 strcpy(cs, "ksc5601.1989-0");
5967 break;
5968 default:
5969 strcpy(cs, "mac-roman");
5970 break;
5971 }
5972 }
5973
5974 sprintf(xf, "-%s-%s-%s-%c-normal--%d-%d-75-75-m-%d-%s",
5975 foundry, family, style & bold ? "bold" : "medium",
5976 style & italic ? 'i' : 'r', size, size * 10, size * 10, cs);
5977
5978 result = (char *) xmalloc (strlen (xf) + 1);
5979 strcpy (result, xf);
5980 for (p = result; *p; p++)
5981 *p = tolower(*p);
5982 return result;
5983 }
5984
5985
5986 /* Convert an X font spec to the corresponding mac font name, which
5987 can then be passed to GetFNum after conversion to a Pascal string.
5988 For ordinary Mac fonts, this should just be their names, like
5989 "monaco", "Taipei", etc. Fonts converted from the GNU intlfonts
5990 collection contain their charset designation in their names, like
5991 "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both types of font
5992 names are handled accordingly. */
5993 static void
5994 x_font_name_to_mac_font_name (char *xf, char *mf)
5995 {
5996 char foundry[32], family[32], weight[20], slant[2], cs[32];
5997 Lisp_Object coding_system = Qnil;
5998 struct coding_system coding;
5999
6000 strcpy (mf, "");
6001
6002 if (sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6003 foundry, family, weight, slant, cs) != 5 &&
6004 sscanf (xf, "-%31[^-]-%31[^-]-%19[^-]-%1[^-]-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6005 foundry, family, weight, slant, cs) != 5)
6006 return;
6007
6008 if (strcmp (cs, "big5-0") == 0)
6009 coding_system = Qbig5;
6010 else if (strcmp (cs, "gb2312.1980-0") == 0)
6011 coding_system = Qcn_gb;
6012 else if (strcmp (cs, "jisx0208.1983-sjis") == 0
6013 || strcmp (cs, "jisx0201.1976-0") == 0)
6014 coding_system = Qsjis;
6015 else if (strcmp (cs, "ksc5601.1989-0") == 0)
6016 coding_system = Qeuc_kr;
6017 else if (strcmp (cs, "mac-roman") == 0)
6018 strcpy (mf, family);
6019 else
6020 sprintf (mf, "%s-%s-%s", foundry, family, cs);
6021
6022 if (!NILP (coding_system))
6023 {
6024 setup_coding_system (coding_system, &coding);
6025 coding.src_multibyte = 1;
6026 coding.dst_multibyte = 1;
6027 coding.mode |= CODING_MODE_LAST_BLOCK;
6028 encode_coding (&coding, family, mf, strlen (family), sizeof (Str32) - 1);
6029 mf[coding.produced] = '\0';
6030 }
6031 }
6032
6033
6034 static void
6035 add_font_name_table_entry (char *font_name)
6036 {
6037 if (font_name_table_size == 0)
6038 {
6039 font_name_table_size = 16;
6040 font_name_table = (char **)
6041 xmalloc (font_name_table_size * sizeof (char *));
6042 }
6043 else if (font_name_count + 1 >= font_name_table_size)
6044 {
6045 font_name_table_size += 16;
6046 font_name_table = (char **)
6047 xrealloc (font_name_table,
6048 font_name_table_size * sizeof (char *));
6049 }
6050
6051 font_name_table[font_name_count++] = font_name;
6052 }
6053
6054 /* Sets up the table font_name_table to contain the list of all fonts
6055 in the system the first time the table is used so that the Resource
6056 Manager need not be accessed every time this information is
6057 needed. */
6058
6059 static void
6060 init_font_name_table ()
6061 {
6062 #if TARGET_API_MAC_CARBON
6063 SInt32 sv;
6064
6065 if (Gestalt (gestaltSystemVersion, &sv) == noErr && sv >= 0x1000)
6066 {
6067 FMFontFamilyIterator ffi;
6068 FMFontFamilyInstanceIterator ffii;
6069 FMFontFamily ff;
6070
6071 /* Create a dummy instance iterator here to avoid creating and
6072 destroying it in the loop. */
6073 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr)
6074 return;
6075 /* Create an iterator to enumerate the font families. */
6076 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi)
6077 != noErr)
6078 {
6079 FMDisposeFontFamilyInstanceIterator (&ffii);
6080 return;
6081 }
6082
6083 while (FMGetNextFontFamily (&ffi, &ff) == noErr)
6084 {
6085 Str255 name;
6086 FMFont font;
6087 FMFontStyle style;
6088 FMFontSize size;
6089 SInt16 sc;
6090
6091 if (FMGetFontFamilyName (ff, name) != noErr)
6092 break;
6093 p2cstr (name);
6094 if (*name == '.')
6095 continue;
6096
6097 sc = FontToScript (ff);
6098 decode_mac_font_name (name, sizeof (name), sc);
6099
6100 /* Point the instance iterator at the current font family. */
6101 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr)
6102 break;
6103
6104 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size)
6105 == noErr)
6106 {
6107 /* Both jisx0208.1983-sjis and jisx0201.1976-0 parts are
6108 contained in Apple Japanese (SJIS) font. */
6109 again:
6110 if (size == 0)
6111 {
6112 add_font_name_table_entry (mac_to_x_fontname (name, size,
6113 style, sc));
6114 add_font_name_table_entry (mac_to_x_fontname (name, size,
6115 italic, sc));
6116 add_font_name_table_entry (mac_to_x_fontname (name, size,
6117 bold, sc));
6118 add_font_name_table_entry (mac_to_x_fontname (name, size,
6119 italic | bold,
6120 sc));
6121 }
6122 else
6123 add_font_name_table_entry (mac_to_x_fontname (name, size,
6124 style, sc));
6125 if (sc == smJapanese)
6126 {
6127 sc = -smJapanese;
6128 goto again;
6129 }
6130 else if (sc == -smJapanese)
6131 sc = smJapanese;
6132 }
6133 }
6134
6135 /* Dispose of the iterators. */
6136 FMDisposeFontFamilyIterator (&ffi);
6137 FMDisposeFontFamilyInstanceIterator (&ffii);
6138 }
6139 else
6140 {
6141 #endif /* TARGET_API_MAC_CARBON */
6142 GrafPtr port;
6143 SInt16 fontnum, old_fontnum;
6144 int num_mac_fonts = CountResources('FOND');
6145 int i, j;
6146 Handle font_handle, font_handle_2;
6147 short id, scriptcode;
6148 ResType type;
6149 Str32 name;
6150 struct FontAssoc *fat;
6151 struct AsscEntry *assc_entry;
6152
6153 GetPort (&port); /* save the current font number used */
6154 #if TARGET_API_MAC_CARBON
6155 old_fontnum = GetPortTextFont (port);
6156 #else
6157 old_fontnum = port->txFont;
6158 #endif
6159
6160 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */
6161 {
6162 font_handle = GetIndResource ('FOND', i);
6163 if (!font_handle)
6164 continue;
6165
6166 GetResInfo (font_handle, &id, &type, name);
6167 GetFNum (name, &fontnum);
6168 p2cstr (name);
6169 if (fontnum == 0)
6170 continue;
6171
6172 TextFont (fontnum);
6173 scriptcode = FontToScript (fontnum);
6174 decode_mac_font_name (name, sizeof (name), scriptcode);
6175 do
6176 {
6177 HLock (font_handle);
6178
6179 if (GetResourceSizeOnDisk (font_handle)
6180 >= sizeof (struct FamRec))
6181 {
6182 fat = (struct FontAssoc *) (*font_handle
6183 + sizeof (struct FamRec));
6184 assc_entry
6185 = (struct AsscEntry *) (*font_handle
6186 + sizeof (struct FamRec)
6187 + sizeof (struct FontAssoc));
6188
6189 for (j = 0; j <= fat->numAssoc; j++, assc_entry++)
6190 {
6191 if (font_name_table_size == 0)
6192 {
6193 font_name_table_size = 16;
6194 font_name_table = (char **)
6195 xmalloc (font_name_table_size * sizeof (char *));
6196 }
6197 else if (font_name_count >= font_name_table_size)
6198 {
6199 font_name_table_size += 16;
6200 font_name_table = (char **)
6201 xrealloc (font_name_table,
6202 font_name_table_size * sizeof (char *));
6203 }
6204 font_name_table[font_name_count++]
6205 = mac_to_x_fontname (name,
6206 assc_entry->fontSize,
6207 assc_entry->fontStyle,
6208 scriptcode);
6209 /* Both jisx0208.1983-sjis and jisx0201.1976-0
6210 parts are contained in Apple Japanese (SJIS)
6211 font. */
6212 if (smJapanese == scriptcode)
6213 {
6214 font_name_table[font_name_count++]
6215 = mac_to_x_fontname (name,
6216 assc_entry->fontSize,
6217 assc_entry->fontStyle,
6218 -smJapanese);
6219 }
6220 }
6221 }
6222
6223 HUnlock (font_handle);
6224 font_handle_2 = GetNextFOND (font_handle);
6225 ReleaseResource (font_handle);
6226 font_handle = font_handle_2;
6227 }
6228 while (ResError () == noErr && font_handle);
6229 }
6230
6231 TextFont (old_fontnum);
6232 #if TARGET_API_MAC_CARBON
6233 }
6234 #endif /* TARGET_API_MAC_CARBON */
6235 }
6236
6237
6238 enum xlfd_scalable_field_index
6239 {
6240 XLFD_SCL_PIXEL_SIZE,
6241 XLFD_SCL_POINT_SIZE,
6242 XLFD_SCL_AVGWIDTH,
6243 XLFD_SCL_LAST
6244 };
6245
6246 static int xlfd_scalable_fields[] =
6247 {
6248 6, /* PIXEL_SIZE */
6249 7, /* POINT_SIZE */
6250 11, /* AVGWIDTH */
6251 -1
6252 };
6253
6254 static Lisp_Object
6255 mac_do_list_fonts (pattern, maxnames)
6256 char *pattern;
6257 int maxnames;
6258 {
6259 int i, n_fonts = 0;
6260 Lisp_Object font_list = Qnil, pattern_regex, fontname;
6261 char *regex = (char *) alloca (strlen (pattern) * 2 + 3);
6262 char scaled[256];
6263 char *ptr;
6264 int scl_val[XLFD_SCL_LAST], *field, *val;
6265
6266 for (i = 0; i < XLFD_SCL_LAST; i++)
6267 scl_val[i] = -1;
6268
6269 /* If the pattern contains 14 dashes and one of PIXEL_SIZE,
6270 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable
6271 fonts are scaled according to the specified size. */
6272 ptr = pattern;
6273 i = 0;
6274 field = xlfd_scalable_fields;
6275 val = scl_val;
6276 if (*ptr == '-')
6277 do
6278 {
6279 ptr++;
6280 if (i == *field)
6281 {
6282 if ('1' <= *ptr && *ptr <= '9')
6283 {
6284 *val = *ptr++ - '0';
6285 while ('0' <= *ptr && *ptr <= '9' && *val < 10000)
6286 *val = *val * 10 + *ptr++ - '0';
6287 if (*ptr != '-')
6288 *val = -1;
6289 }
6290 field++;
6291 val++;
6292 }
6293 ptr = strchr (ptr, '-');
6294 i++;
6295 }
6296 while (ptr && i < 14);
6297
6298 if (i == 14 && ptr == NULL)
6299 {
6300 if (scl_val[XLFD_SCL_POINT_SIZE] > 0)
6301 {
6302 scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_POINT_SIZE] / 10;
6303 scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_POINT_SIZE];
6304 }
6305 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0)
6306 {
6307 scl_val[XLFD_SCL_POINT_SIZE] =
6308 scl_val[XLFD_SCL_AVGWIDTH] = scl_val[XLFD_SCL_PIXEL_SIZE] * 10;
6309 }
6310 else if (scl_val[XLFD_SCL_AVGWIDTH] > 0)
6311 {
6312 scl_val[XLFD_SCL_PIXEL_SIZE] = scl_val[XLFD_SCL_AVGWIDTH] / 10;
6313 scl_val[XLFD_SCL_POINT_SIZE] = scl_val[XLFD_SCL_AVGWIDTH];
6314 }
6315 }
6316 else
6317 scl_val[XLFD_SCL_PIXEL_SIZE] = -1;
6318
6319 ptr = regex;
6320 *ptr++ = '^';
6321
6322 /* Turn pattern into a regexp and do a regexp match. */
6323 for (; *pattern; pattern++)
6324 {
6325 if (*pattern == '?')
6326 *ptr++ = '.';
6327 else if (*pattern == '*')
6328 {
6329 *ptr++ = '.';
6330 *ptr++ = '*';
6331 }
6332 else
6333 *ptr++ = tolower (*pattern);
6334 }
6335 *ptr = '$';
6336 *(ptr + 1) = '\0';
6337
6338 pattern_regex = build_string (regex);
6339
6340 for (i = 0; i < font_name_count; i++)
6341 {
6342 fontname = build_string (font_name_table[i]);
6343 if (fast_string_match (pattern_regex, fontname) >= 0)
6344 {
6345 font_list = Fcons (fontname, font_list);
6346
6347 n_fonts++;
6348 if (maxnames > 0 && n_fonts >= maxnames)
6349 break;
6350 }
6351 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0
6352 && (ptr = strstr (font_name_table[i], "-0-0-75-75-m-0-")))
6353 {
6354 int former_len = ptr - font_name_table[i];
6355
6356 memcpy (scaled, font_name_table[i], former_len);
6357 sprintf (scaled + former_len,
6358 "-%d-%d-75-75-m-%d-%s",
6359 scl_val[XLFD_SCL_PIXEL_SIZE],
6360 scl_val[XLFD_SCL_POINT_SIZE],
6361 scl_val[XLFD_SCL_AVGWIDTH],
6362 ptr + sizeof ("-0-0-75-75-m-0-") - 1);
6363 fontname = build_string (scaled);
6364 if (fast_string_match (pattern_regex, fontname) >= 0)
6365 {
6366 font_list = Fcons (fontname, font_list);
6367
6368 n_fonts++;
6369 if (maxnames > 0 && n_fonts >= maxnames)
6370 break;
6371 }
6372 }
6373 }
6374 return font_list;
6375 }
6376
6377 /* Return a list of at most MAXNAMES font specs matching the one in
6378 PATTERN. Cache matching fonts for patterns in
6379 dpyinfo->name_list_element to avoid looking them up again by
6380 calling mac_font_pattern_match (slow). Return as many matching
6381 fonts as possible if MAXNAMES = -1. */
6382
6383 Lisp_Object
6384 x_list_fonts (struct frame *f,
6385 Lisp_Object pattern,
6386 int size,
6387 int maxnames)
6388 {
6389 Lisp_Object newlist = Qnil, tem, key;
6390 struct mac_display_info *dpyinfo = f ? FRAME_MAC_DISPLAY_INFO (f) : NULL;
6391
6392 if (font_name_table == NULL) /* Initialize when first used. */
6393 init_font_name_table ();
6394
6395 if (dpyinfo)
6396 {
6397 tem = XCDR (dpyinfo->name_list_element);
6398 key = Fcons (pattern, make_number (maxnames));
6399
6400 newlist = Fassoc (key, tem);
6401 if (!NILP (newlist))
6402 {
6403 newlist = Fcdr_safe (newlist);
6404 goto label_cached;
6405 }
6406 }
6407
6408 newlist = mac_do_list_fonts (SDATA (pattern), maxnames);
6409
6410 /* MAC_TODO: add code for matching outline fonts here */
6411
6412 if (dpyinfo)
6413 {
6414 XSETCDR (dpyinfo->name_list_element,
6415 Fcons (Fcons (key, newlist),
6416 XCDR (dpyinfo->name_list_element)));
6417 }
6418 label_cached:
6419
6420 return newlist;
6421 }
6422
6423
6424 #if GLYPH_DEBUG
6425
6426 /* Check that FONT is valid on frame F. It is if it can be found in F's
6427 font table. */
6428
6429 static void
6430 x_check_font (f, font)
6431 struct frame *f;
6432 XFontStruct *font;
6433 {
6434 int i;
6435 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
6436
6437 xassert (font != NULL);
6438
6439 for (i = 0; i < dpyinfo->n_fonts; i++)
6440 if (dpyinfo->font_table[i].name
6441 && font == dpyinfo->font_table[i].font)
6442 break;
6443
6444 xassert (i < dpyinfo->n_fonts);
6445 }
6446
6447 #endif /* GLYPH_DEBUG != 0 */
6448
6449 /* Set *W to the minimum width, *H to the minimum font height of FONT.
6450 Note: There are (broken) X fonts out there with invalid XFontStruct
6451 min_bounds contents. For example, handa@etl.go.jp reports that
6452 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts
6453 have font->min_bounds.width == 0. */
6454
6455 static INLINE void
6456 x_font_min_bounds (font, w, h)
6457 MacFontStruct *font;
6458 int *w, *h;
6459 {
6460 /*
6461 * TODO: Windows does not appear to offer min bound, only
6462 * average and maximum width, and maximum height.
6463 */
6464 *h = FONT_HEIGHT (font);
6465 *w = FONT_WIDTH (font);
6466 }
6467
6468
6469 /* Compute the smallest character width and smallest font height over
6470 all fonts available on frame F. Set the members smallest_char_width
6471 and smallest_font_height in F's x_display_info structure to
6472 the values computed. Value is non-zero if smallest_font_height or
6473 smallest_char_width become smaller than they were before. */
6474
6475 int
6476 x_compute_min_glyph_bounds (f)
6477 struct frame *f;
6478 {
6479 int i;
6480 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6481 MacFontStruct *font;
6482 int old_width = dpyinfo->smallest_char_width;
6483 int old_height = dpyinfo->smallest_font_height;
6484
6485 dpyinfo->smallest_font_height = 100000;
6486 dpyinfo->smallest_char_width = 100000;
6487
6488 for (i = 0; i < dpyinfo->n_fonts; ++i)
6489 if (dpyinfo->font_table[i].name)
6490 {
6491 struct font_info *fontp = dpyinfo->font_table + i;
6492 int w, h;
6493
6494 font = (MacFontStruct *) fontp->font;
6495 xassert (font != (MacFontStruct *) ~0);
6496 x_font_min_bounds (font, &w, &h);
6497
6498 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h);
6499 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w);
6500 }
6501
6502 xassert (dpyinfo->smallest_char_width > 0
6503 && dpyinfo->smallest_font_height > 0);
6504
6505 return (dpyinfo->n_fonts == 1
6506 || dpyinfo->smallest_char_width < old_width
6507 || dpyinfo->smallest_font_height < old_height);
6508 }
6509
6510
6511 /* Determine whether given string is a fully-specified XLFD: all 14
6512 fields are present, none is '*'. */
6513
6514 static int
6515 is_fully_specified_xlfd (char *p)
6516 {
6517 int i;
6518 char *q;
6519
6520 if (*p != '-')
6521 return 0;
6522
6523 for (i = 0; i < 13; i++)
6524 {
6525 q = strchr (p + 1, '-');
6526 if (q == NULL)
6527 return 0;
6528 if (q - p == 2 && *(p + 1) == '*')
6529 return 0;
6530 p = q;
6531 }
6532
6533 if (strchr (p + 1, '-') != NULL)
6534 return 0;
6535
6536 if (*(p + 1) == '*' && *(p + 2) == '\0')
6537 return 0;
6538
6539 return 1;
6540 }
6541
6542
6543 const int kDefaultFontSize = 9;
6544
6545
6546 /* XLoadQueryFont creates and returns an internal representation for a
6547 font in a MacFontStruct struct. There is really no concept
6548 corresponding to "loading" a font on the Mac. But we check its
6549 existence and find the font number and all other information for it
6550 and store them in the returned MacFontStruct. */
6551
6552 static MacFontStruct *
6553 XLoadQueryFont (Display *dpy, char *fontname)
6554 {
6555 int i, size, is_two_byte_font, char_width;
6556 char *name;
6557 GrafPtr port;
6558 SInt16 old_fontnum, old_fontsize;
6559 Style old_fontface;
6560 Str32 mfontname;
6561 SInt16 fontnum;
6562 Style fontface = normal;
6563 MacFontStruct *font;
6564 FontInfo the_fontinfo;
6565 char s_weight[7], c_slant;
6566
6567 if (is_fully_specified_xlfd (fontname))
6568 name = fontname;
6569 else
6570 {
6571 Lisp_Object matched_fonts;
6572
6573 matched_fonts = mac_do_list_fonts (fontname, 1);
6574 if (NILP (matched_fonts))
6575 return NULL;
6576 name = SDATA (XCAR (matched_fonts));
6577 }
6578
6579 GetPort (&port); /* save the current font number used */
6580 #if TARGET_API_MAC_CARBON
6581 old_fontnum = GetPortTextFont (port);
6582 old_fontsize = GetPortTextSize (port);
6583 old_fontface = GetPortTextFace (port);
6584 #else
6585 old_fontnum = port->txFont;
6586 old_fontsize = port->txSize;
6587 old_fontface = port->txFace;
6588 #endif
6589
6590 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%d-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &size) != 1)
6591 size = kDefaultFontSize;
6592
6593 if (sscanf (name, "-%*[^-]-%*[^-]-%6[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", s_weight) == 1)
6594 if (strcmp (s_weight, "bold") == 0)
6595 fontface |= bold;
6596
6597 if (sscanf (name, "-%*[^-]-%*[^-]-%*[^-]-%c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%*s", &c_slant) == 1)
6598 if (c_slant == 'i')
6599 fontface |= italic;
6600
6601 x_font_name_to_mac_font_name (name, mfontname);
6602 c2pstr (mfontname);
6603 GetFNum (mfontname, &fontnum);
6604 if (fontnum == 0)
6605 return NULL;
6606
6607 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct));
6608
6609 font->fontname = (char *) xmalloc (strlen (name) + 1);
6610 bcopy (name, font->fontname, strlen (name) + 1);
6611
6612 font->mac_fontnum = fontnum;
6613 font->mac_fontsize = size;
6614 font->mac_fontface = fontface;
6615 font->mac_scriptcode = FontToScript (fontnum);
6616
6617 /* Apple Japanese (SJIS) font is listed as both
6618 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0"
6619 (Roman script) in init_font_name_table (). The latter should be
6620 treated as a one-byte font. */
6621 {
6622 char cs[32];
6623
6624 if (sscanf (name,
6625 "-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]--%*[^-]-%*[^-]-%*[^-]-%*[^-]-%*c-%*[^-]-%31s",
6626 cs) == 1
6627 && 0 == strcmp (cs, "jisx0201.1976-0"))
6628 font->mac_scriptcode = smRoman;
6629 }
6630
6631 is_two_byte_font = font->mac_scriptcode == smJapanese ||
6632 font->mac_scriptcode == smTradChinese ||
6633 font->mac_scriptcode == smSimpChinese ||
6634 font->mac_scriptcode == smKorean;
6635
6636 TextFont (fontnum);
6637 TextSize (size);
6638 TextFace (fontface);
6639
6640 GetFontInfo (&the_fontinfo);
6641
6642 font->ascent = the_fontinfo.ascent;
6643 font->descent = the_fontinfo.descent;
6644
6645 font->min_byte1 = 0;
6646 if (is_two_byte_font)
6647 font->max_byte1 = 1;
6648 else
6649 font->max_byte1 = 0;
6650 font->min_char_or_byte2 = 0x20;
6651 font->max_char_or_byte2 = 0xff;
6652
6653 if (is_two_byte_font)
6654 {
6655 /* Use the width of an "ideographic space" of that font because
6656 the_fontinfo.widMax returns the wrong width for some fonts. */
6657 switch (font->mac_scriptcode)
6658 {
6659 case smJapanese:
6660 char_width = StringWidth("\p\x81\x40");
6661 break;
6662 case smTradChinese:
6663 char_width = StringWidth("\p\xa1\x40");
6664 break;
6665 case smSimpChinese:
6666 char_width = StringWidth("\p\xa1\xa1");
6667 break;
6668 case smKorean:
6669 char_width = StringWidth("\p\xa1\xa1");
6670 break;
6671 }
6672 }
6673 else
6674 /* Do this instead of use the_fontinfo.widMax, which incorrectly
6675 returns 15 for 12-point Monaco! */
6676 char_width = CharWidth ('m');
6677
6678 font->max_bounds.rbearing = char_width;
6679 font->max_bounds.lbearing = 0;
6680 font->max_bounds.width = char_width;
6681 font->max_bounds.ascent = the_fontinfo.ascent;
6682 font->max_bounds.descent = the_fontinfo.descent;
6683
6684 font->min_bounds = font->max_bounds;
6685
6686 if (is_two_byte_font || CharWidth ('m') == CharWidth ('i'))
6687 font->per_char = NULL;
6688 else
6689 {
6690 font->per_char = (XCharStruct *)
6691 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1));
6692 {
6693 int c;
6694
6695 for (c = 0x20; c <= 0xff; c++)
6696 {
6697 font->per_char[c - 0x20] = font->max_bounds;
6698 font->per_char[c - 0x20].width =
6699 font->per_char[c - 0x20].rbearing = CharWidth (c);
6700 }
6701 }
6702 }
6703
6704 TextFont (old_fontnum); /* restore previous font number, size and face */
6705 TextSize (old_fontsize);
6706 TextFace (old_fontface);
6707
6708 return font;
6709 }
6710
6711
6712 /* Load font named FONTNAME of the size SIZE for frame F, and return a
6713 pointer to the structure font_info while allocating it dynamically.
6714 If SIZE is 0, load any size of font.
6715 If loading is failed, return NULL. */
6716
6717 struct font_info *
6718 x_load_font (f, fontname, size)
6719 struct frame *f;
6720 register char *fontname;
6721 int size;
6722 {
6723 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6724 Lisp_Object font_names;
6725
6726 /* Get a list of all the fonts that match this name. Once we
6727 have a list of matching fonts, we compare them against the fonts
6728 we already have by comparing names. */
6729 font_names = x_list_fonts (f, build_string (fontname), size, 1);
6730
6731 if (!NILP (font_names))
6732 {
6733 Lisp_Object tail;
6734 int i;
6735
6736 for (i = 0; i < dpyinfo->n_fonts; i++)
6737 for (tail = font_names; CONSP (tail); tail = XCDR (tail))
6738 if (dpyinfo->font_table[i].name
6739 && (!strcmp (dpyinfo->font_table[i].name,
6740 SDATA (XCAR (tail)))
6741 || !strcmp (dpyinfo->font_table[i].full_name,
6742 SDATA (XCAR (tail)))))
6743 return (dpyinfo->font_table + i);
6744 }
6745
6746 /* Load the font and add it to the table. */
6747 {
6748 char *full_name;
6749 struct MacFontStruct *font;
6750 struct font_info *fontp;
6751 unsigned long value;
6752 int i;
6753
6754 /* If we have found fonts by x_list_font, load one of them. If
6755 not, we still try to load a font by the name given as FONTNAME
6756 because XListFonts (called in x_list_font) of some X server has
6757 a bug of not finding a font even if the font surely exists and
6758 is loadable by XLoadQueryFont. */
6759 if (size > 0 && !NILP (font_names))
6760 fontname = (char *) SDATA (XCAR (font_names));
6761
6762 font = (MacFontStruct *) XLoadQueryFont (FRAME_MAC_DISPLAY (f), fontname);
6763 if (!font)
6764 return NULL;
6765
6766 /* Find a free slot in the font table. */
6767 for (i = 0; i < dpyinfo->n_fonts; ++i)
6768 if (dpyinfo->font_table[i].name == NULL)
6769 break;
6770
6771 /* If no free slot found, maybe enlarge the font table. */
6772 if (i == dpyinfo->n_fonts
6773 && dpyinfo->n_fonts == dpyinfo->font_table_size)
6774 {
6775 int sz;
6776 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size);
6777 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table;
6778 dpyinfo->font_table
6779 = (struct font_info *) xrealloc (dpyinfo->font_table, sz);
6780 }
6781
6782 fontp = dpyinfo->font_table + i;
6783 if (i == dpyinfo->n_fonts)
6784 ++dpyinfo->n_fonts;
6785
6786 /* Now fill in the slots of *FONTP. */
6787 BLOCK_INPUT;
6788 bzero (fontp, sizeof (*fontp));
6789 fontp->font = font;
6790 fontp->font_idx = i;
6791 fontp->name = (char *) xmalloc (strlen (font->fontname) + 1);
6792 bcopy (font->fontname, fontp->name, strlen (font->fontname) + 1);
6793
6794 fontp->full_name = fontp->name;
6795
6796 fontp->size = font->max_bounds.width;
6797 fontp->height = FONT_HEIGHT (font);
6798 {
6799 /* For some font, ascent and descent in max_bounds field is
6800 larger than the above value. */
6801 int max_height = font->max_bounds.ascent + font->max_bounds.descent;
6802 if (max_height > fontp->height)
6803 fontp->height = max_height;
6804 }
6805
6806 /* The slot `encoding' specifies how to map a character
6807 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to
6808 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or
6809 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF,
6810 2:0xA020..0xFF7F). For the moment, we don't know which charset
6811 uses this font. So, we set information in fontp->encoding[1]
6812 which is never used by any charset. If mapping can't be
6813 decided, set FONT_ENCODING_NOT_DECIDED. */
6814 if (font->mac_scriptcode == smJapanese)
6815 fontp->encoding[1] = 4;
6816 else
6817 {
6818 fontp->encoding[1]
6819 = (font->max_byte1 == 0
6820 /* 1-byte font */
6821 ? (font->min_char_or_byte2 < 0x80
6822 ? (font->max_char_or_byte2 < 0x80
6823 ? 0 /* 0x20..0x7F */
6824 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */
6825 : 1) /* 0xA0..0xFF */
6826 /* 2-byte font */
6827 : (font->min_byte1 < 0x80
6828 ? (font->max_byte1 < 0x80
6829 ? (font->min_char_or_byte2 < 0x80
6830 ? (font->max_char_or_byte2 < 0x80
6831 ? 0 /* 0x2020..0x7F7F */
6832 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */
6833 : 3) /* 0x20A0..0x7FFF */
6834 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */
6835 : (font->min_char_or_byte2 < 0x80
6836 ? (font->max_char_or_byte2 < 0x80
6837 ? 2 /* 0xA020..0xFF7F */
6838 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */
6839 : 1))); /* 0xA0A0..0xFFFF */
6840 }
6841
6842 #if 0 /* MAC_TODO: fill these out with more reasonably values */
6843 fontp->baseline_offset
6844 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value)
6845 ? (long) value : 0);
6846 fontp->relative_compose
6847 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value)
6848 ? (long) value : 0);
6849 fontp->default_ascent
6850 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value)
6851 ? (long) value : 0);
6852 #else
6853 fontp->baseline_offset = 0;
6854 fontp->relative_compose = 0;
6855 fontp->default_ascent = 0;
6856 #endif
6857
6858 /* Set global flag fonts_changed_p to non-zero if the font loaded
6859 has a character with a smaller width than any other character
6860 before, or if the font loaded has a smalle>r height than any
6861 other font loaded before. If this happens, it will make a
6862 glyph matrix reallocation necessary. */
6863 fonts_changed_p = x_compute_min_glyph_bounds (f);
6864 UNBLOCK_INPUT;
6865 return fontp;
6866 }
6867 }
6868
6869
6870 /* Return a pointer to struct font_info of a font named FONTNAME for
6871 frame F. If no such font is loaded, return NULL. */
6872
6873 struct font_info *
6874 x_query_font (f, fontname)
6875 struct frame *f;
6876 register char *fontname;
6877 {
6878 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f);
6879 int i;
6880
6881 for (i = 0; i < dpyinfo->n_fonts; i++)
6882 if (dpyinfo->font_table[i].name
6883 && (!strcmp (dpyinfo->font_table[i].name, fontname)
6884 || !strcmp (dpyinfo->font_table[i].full_name, fontname)))
6885 return (dpyinfo->font_table + i);
6886 return NULL;
6887 }
6888
6889
6890 /* Find a CCL program for a font specified by FONTP, and set the member
6891 `encoder' of the structure. */
6892
6893 void
6894 x_find_ccl_program (fontp)
6895 struct font_info *fontp;
6896 {
6897 Lisp_Object list, elt;
6898
6899 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list))
6900 {
6901 elt = XCAR (list);
6902 if (CONSP (elt)
6903 && STRINGP (XCAR (elt))
6904 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name)
6905 >= 0))
6906 break;
6907 }
6908 if (! NILP (list))
6909 {
6910 struct ccl_program *ccl
6911 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program));
6912
6913 if (setup_ccl_program (ccl, XCDR (elt)) < 0)
6914 xfree (ccl);
6915 else
6916 fontp->font_encoder = ccl;
6917 }
6918 }
6919
6920
6921 \f
6922 /* The Mac Event loop code */
6923
6924 #ifndef MAC_OSX
6925 #include <Events.h>
6926 #include <Quickdraw.h>
6927 #include <Balloons.h>
6928 #include <Devices.h>
6929 #include <Fonts.h>
6930 #include <Gestalt.h>
6931 #include <Menus.h>
6932 #include <Processes.h>
6933 #include <Sound.h>
6934 #include <ToolUtils.h>
6935 #include <TextUtils.h>
6936 #include <Dialogs.h>
6937 #include <Script.h>
6938 #include <Types.h>
6939 #include <TextEncodingConverter.h>
6940 #include <Resources.h>
6941
6942 #if __MWERKS__
6943 #include <unix.h>
6944 #endif
6945 #endif /* ! MAC_OSX */
6946
6947 #define M_APPLE 128
6948 #define I_ABOUT 1
6949
6950 #define WINDOW_RESOURCE 128
6951 #define TERM_WINDOW_RESOURCE 129
6952
6953 #define DEFAULT_NUM_COLS 80
6954
6955 #define MIN_DOC_SIZE 64
6956 #define MAX_DOC_SIZE 32767
6957
6958 /* sleep time for WaitNextEvent */
6959 #define WNE_SLEEP_AT_SUSPEND 10
6960 #define WNE_SLEEP_AT_RESUME 1
6961
6962 /* true when cannot handle any Mac OS events */
6963 static int handling_window_update = 0;
6964
6965 #if 0
6966 /* the flag appl_is_suspended is used both for determining the sleep
6967 time to be passed to WaitNextEvent and whether the cursor should be
6968 drawn when updating the display. The cursor is turned off when
6969 Emacs is suspended. Redrawing it is unnecessary and what needs to
6970 be done depends on whether the cursor lies inside or outside the
6971 redraw region. So we might as well skip drawing it when Emacs is
6972 suspended. */
6973 static Boolean app_is_suspended = false;
6974 static long app_sleep_time = WNE_SLEEP_AT_RESUME;
6975 #endif
6976
6977 #define EXTRA_STACK_ALLOC (256 * 1024)
6978
6979 #define ARGV_STRING_LIST_ID 129
6980 #define ABOUT_ALERT_ID 128
6981 #define RAM_TOO_LARGE_ALERT_ID 129
6982
6983 Boolean terminate_flag = false;
6984
6985 /* Contains the string "reverse", which is a constant for mouse button emu.*/
6986 Lisp_Object Qreverse;
6987
6988 /* True if using command key as meta key. */
6989 Lisp_Object Vmac_command_key_is_meta;
6990
6991 /* True if the ctrl and meta keys should be reversed. */
6992 Lisp_Object Vmac_reverse_ctrl_meta;
6993
6994 /* True if the option and command modifiers should be used to emulate
6995 a three button mouse */
6996 Lisp_Object Vmac_emulate_three_button_mouse;
6997
6998 #if USE_CARBON_EVENTS
6999 /* True if the mouse wheel button (i.e. button 4) should map to
7000 mouse-2, instead of mouse-3. */
7001 Lisp_Object Vmac_wheel_button_is_mouse_2;
7002
7003 /* If Non-nil, the Mac "Command" key is passed on to the Mac Toolbox
7004 for processing before Emacs sees it. */
7005 Lisp_Object Vmac_pass_command_to_system;
7006
7007 /* If Non-nil, the Mac "Control" key is passed on to the Mac Toolbox
7008 for processing before Emacs sees it. */
7009 Lisp_Object Vmac_pass_control_to_system;
7010 #endif
7011
7012 /* convert input from Mac keyboard (assumed to be in Mac Roman coding)
7013 to this text encoding */
7014 int mac_keyboard_text_encoding;
7015 int current_mac_keyboard_text_encoding = kTextEncodingMacRoman;
7016
7017 /* Set in term/mac-win.el to indicate that event loop can now generate
7018 drag and drop events. */
7019 Lisp_Object Qmac_ready_for_drag_n_drop;
7020
7021 Lisp_Object drag_and_drop_file_list;
7022
7023 Point saved_menu_event_location;
7024
7025 #if !TARGET_API_MAC_CARBON
7026 /* Place holder for the default arrow cursor. */
7027 CursPtr arrow_cursor;
7028 #endif
7029
7030 /* Apple Events */
7031 static void init_required_apple_events (void);
7032 static pascal OSErr
7033 do_ae_open_application (const AppleEvent *, AppleEvent *, long);
7034 static pascal OSErr
7035 do_ae_print_documents (const AppleEvent *, AppleEvent *, long);
7036 static pascal OSErr do_ae_open_documents (AppleEvent *, AppleEvent *, long);
7037 static pascal OSErr do_ae_quit_application (AppleEvent *, AppleEvent *, long);
7038
7039 /* Drag and Drop */
7040 static OSErr init_mac_drag_n_drop ();
7041 static pascal OSErr mac_do_receive_drag (WindowPtr, void*, DragReference);
7042
7043 #if USE_CARBON_EVENTS
7044 /* Preliminary Support for the OSX Services Menu */
7045 static OSStatus mac_handle_service_event (EventHandlerCallRef,EventRef,void*);
7046 static void init_service_handler ();
7047 #endif
7048
7049 extern void init_emacs_passwd_dir ();
7050 extern int emacs_main (int, char **, char **);
7051 extern void check_alarm ();
7052
7053 extern void initialize_applescript();
7054 extern void terminate_applescript();
7055
7056 static unsigned int
7057 #if USE_CARBON_EVENTS
7058 mac_to_emacs_modifiers (UInt32 mods)
7059 #else
7060 mac_to_emacs_modifiers (EventModifiers mods)
7061 #endif
7062 {
7063 unsigned int result = 0;
7064 if (mods & macShiftKey)
7065 result |= shift_modifier;
7066 if (mods & macCtrlKey)
7067 result |= ctrl_modifier;
7068 if (mods & macMetaKey)
7069 result |= meta_modifier;
7070 if (NILP (Vmac_command_key_is_meta) && (mods & macAltKey))
7071 result |= alt_modifier;
7072 return result;
7073 }
7074
7075 static int
7076 mac_get_emulated_btn ( UInt32 modifiers )
7077 {
7078 int result = 0;
7079 if (!NILP (Vmac_emulate_three_button_mouse)) {
7080 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse);
7081 if (modifiers & cmdKey)
7082 result = cmdIs3 ? 2 : 1;
7083 else if (modifiers & optionKey)
7084 result = cmdIs3 ? 1 : 2;
7085 }
7086 return result;
7087 }
7088
7089 #if USE_CARBON_EVENTS
7090 /* Obtains the event modifiers from the event ref and then calls
7091 mac_to_emacs_modifiers. */
7092 static int
7093 mac_event_to_emacs_modifiers (EventRef eventRef)
7094 {
7095 UInt32 mods = 0;
7096 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL,
7097 sizeof (UInt32), NULL, &mods);
7098 if (!NILP (Vmac_emulate_three_button_mouse) &&
7099 GetEventClass(eventRef) == kEventClassMouse)
7100 {
7101 mods &= ~(optionKey | cmdKey);
7102 }
7103 return mac_to_emacs_modifiers (mods);
7104 }
7105
7106 /* Given an event ref, return the code to use for the mouse button
7107 code in the emacs input_event. */
7108 static int
7109 mac_get_mouse_btn (EventRef ref)
7110 {
7111 EventMouseButton result = kEventMouseButtonPrimary;
7112 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL,
7113 sizeof (EventMouseButton), NULL, &result);
7114 switch (result)
7115 {
7116 case kEventMouseButtonPrimary:
7117 if (NILP (Vmac_emulate_three_button_mouse))
7118 return 0;
7119 else {
7120 UInt32 mods = 0;
7121 GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL,
7122 sizeof (UInt32), NULL, &mods);
7123 return mac_get_emulated_btn(mods);
7124 }
7125 case kEventMouseButtonSecondary:
7126 return NILP (Vmac_wheel_button_is_mouse_2) ? 1 : 2;
7127 case kEventMouseButtonTertiary:
7128 case 4: /* 4 is the number for the mouse wheel button */
7129 return NILP (Vmac_wheel_button_is_mouse_2) ? 2 : 1;
7130 default:
7131 return 0;
7132 }
7133 }
7134
7135 /* Normally, ConvertEventRefToEventRecord will correctly handle all
7136 events. However the click of the mouse wheel is not converted to a
7137 mouseDown or mouseUp event. This calls ConvertEventRef, but then
7138 checks to see if it is a mouse up or down carbon event that has not
7139 been converted, and if so, converts it by hand (to be picked up in
7140 the XTread_socket loop). */
7141 static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec)
7142 {
7143 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec);
7144 /* Do special case for mouse wheel button. */
7145 if (!result && GetEventClass (eventRef) == kEventClassMouse)
7146 {
7147 UInt32 kind = GetEventKind (eventRef);
7148 if (kind == kEventMouseDown && !(eventRec->what == mouseDown))
7149 {
7150 eventRec->what = mouseDown;
7151 result=1;
7152 }
7153 if (kind == kEventMouseUp && !(eventRec->what == mouseUp))
7154 {
7155 eventRec->what = mouseUp;
7156 result=1;
7157 }
7158 if (result)
7159 {
7160 /* Need where and when. */
7161 UInt32 mods;
7162 GetEventParameter (eventRef, kEventParamMouseLocation,
7163 typeQDPoint, NULL, sizeof (Point),
7164 NULL, &eventRec->where);
7165 /* Use two step process because new event modifiers are
7166 32-bit and old are 16-bit. Currently, only loss is
7167 NumLock & Fn. */
7168 GetEventParameter (eventRef, kEventParamKeyModifiers,
7169 typeUInt32, NULL, sizeof (UInt32),
7170 NULL, &mods);
7171 eventRec->modifiers = mods;
7172
7173 eventRec->when = EventTimeToTicks (GetEventTime (eventRef));
7174 }
7175 }
7176 return result;
7177 }
7178
7179 #endif
7180
7181 static void
7182 do_get_menus (void)
7183 {
7184 Handle menubar_handle;
7185 MenuHandle menu_handle;
7186
7187 menubar_handle = GetNewMBar (128);
7188 if(menubar_handle == NULL)
7189 abort ();
7190 SetMenuBar (menubar_handle);
7191 DrawMenuBar ();
7192
7193 menu_handle = GetMenuHandle (M_APPLE);
7194 if(menu_handle != NULL)
7195 AppendResMenu (menu_handle,'DRVR');
7196 else
7197 abort ();
7198 }
7199
7200
7201 static void
7202 do_init_managers (void)
7203 {
7204 #if !TARGET_API_MAC_CARBON
7205 InitGraf (&qd.thePort);
7206 InitFonts ();
7207 FlushEvents (everyEvent, 0);
7208 InitWindows ();
7209 InitMenus ();
7210 TEInit ();
7211 InitDialogs (NULL);
7212 #endif /* !TARGET_API_MAC_CARBON */
7213 InitCursor ();
7214
7215 #if !TARGET_API_MAC_CARBON
7216 arrow_cursor = &qd.arrow;
7217
7218 /* set up some extra stack space for use by emacs */
7219 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC));
7220
7221 /* MaxApplZone must be called for AppleScript to execute more
7222 complicated scripts */
7223 MaxApplZone ();
7224 MoreMasters ();
7225 #endif /* !TARGET_API_MAC_CARBON */
7226 }
7227
7228 static void
7229 do_check_ram_size (void)
7230 {
7231 SInt32 physical_ram_size, logical_ram_size;
7232
7233 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr
7234 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr
7235 || physical_ram_size > (1 << VALBITS)
7236 || logical_ram_size > (1 << VALBITS))
7237 {
7238 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL);
7239 exit (1);
7240 }
7241 }
7242
7243 static void
7244 do_window_update (WindowPtr win)
7245 {
7246 struct frame *f = mac_window_to_frame (win);
7247
7248 if (win == tip_window)
7249 /* The tooltip has been drawn already. Avoid the
7250 SET_FRAME_GARBAGED below. */
7251 return;
7252
7253 if (f)
7254 {
7255 if (f->async_visible == 0)
7256 {
7257 f->async_visible = 1;
7258 f->async_iconified = 0;
7259 SET_FRAME_GARBAGED (f);
7260
7261 /* An update event is equivalent to MapNotify on X, so report
7262 visibility changes properly. */
7263 if (! NILP(Vframe_list) && ! NILP (XCDR (Vframe_list)))
7264 /* Force a redisplay sooner or later to update the
7265 frame titles in case this is the second frame. */
7266 record_asynch_buffer_change ();
7267 }
7268 else
7269 {
7270 BeginUpdate (win);
7271 handling_window_update = 1;
7272
7273 XClearWindow (FRAME_MAC_DISPLAY (f), FRAME_MAC_WINDOW (f));
7274
7275 expose_frame (f, 0, 0, 0, 0);
7276
7277 handling_window_update = 0;
7278 EndUpdate (win);
7279 }
7280 }
7281 }
7282
7283 static int
7284 is_emacs_window (WindowPtr win)
7285 {
7286 Lisp_Object tail, frame;
7287
7288 if (!win)
7289 return 0;
7290
7291 FOR_EACH_FRAME (tail, frame)
7292 if (FRAME_MAC_P (XFRAME (frame)))
7293 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win)
7294 return 1;
7295
7296 return 0;
7297 }
7298
7299 static void
7300 do_app_resume ()
7301 {
7302 /* Window-activate events will do the job. */
7303 #if 0
7304 WindowPtr wp;
7305 struct frame *f;
7306
7307 wp = front_emacs_window ();
7308 if (wp)
7309 {
7310 f = mac_window_to_frame (wp);
7311
7312 if (f)
7313 {
7314 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), f);
7315 activate_scroll_bars (f);
7316 }
7317 }
7318
7319 app_is_suspended = false;
7320 app_sleep_time = WNE_SLEEP_AT_RESUME;
7321 #endif
7322 }
7323
7324 static void
7325 do_app_suspend ()
7326 {
7327 /* Window-deactivate events will do the job. */
7328 #if 0
7329 WindowPtr wp;
7330 struct frame *f;
7331
7332 wp = front_emacs_window ();
7333 if (wp)
7334 {
7335 f = mac_window_to_frame (wp);
7336
7337 if (f == FRAME_MAC_DISPLAY_INFO (f)->x_focus_frame)
7338 {
7339 x_new_focus_frame (FRAME_MAC_DISPLAY_INFO (f), 0);
7340 deactivate_scroll_bars (f);
7341 }
7342 }
7343
7344 app_is_suspended = true;
7345 app_sleep_time = WNE_SLEEP_AT_SUSPEND;
7346 #endif
7347 }
7348
7349
7350 static void
7351 do_mouse_moved (mouse_pos, f)
7352 Point mouse_pos;
7353 FRAME_PTR *f;
7354 {
7355 WindowPtr wp = front_emacs_window ();
7356 struct x_display_info *dpyinfo;
7357
7358 if (wp)
7359 {
7360 *f = mac_window_to_frame (wp);
7361 dpyinfo = FRAME_MAC_DISPLAY_INFO (*f);
7362
7363 if (dpyinfo->mouse_face_hidden)
7364 {
7365 dpyinfo->mouse_face_hidden = 0;
7366 clear_mouse_face (dpyinfo);
7367 }
7368
7369 SetPortWindowPort (wp);
7370
7371 GlobalToLocal (&mouse_pos);
7372
7373 if (dpyinfo->grabbed && tracked_scroll_bar)
7374 x_scroll_bar_note_movement (tracked_scroll_bar,
7375 mouse_pos.v
7376 - XINT (tracked_scroll_bar->top),
7377 TickCount() * (1000 / 60));
7378 else
7379 note_mouse_movement (*f, &mouse_pos);
7380 }
7381 }
7382
7383
7384 static void
7385 do_apple_menu (SInt16 menu_item)
7386 {
7387 #if !TARGET_API_MAC_CARBON
7388 Str255 item_name;
7389 SInt16 da_driver_refnum;
7390
7391 if (menu_item == I_ABOUT)
7392 NoteAlert (ABOUT_ALERT_ID, NULL);
7393 else
7394 {
7395 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name);
7396 da_driver_refnum = OpenDeskAcc (item_name);
7397 }
7398 #endif /* !TARGET_API_MAC_CARBON */
7399 }
7400
7401 void
7402 do_menu_choice (SInt32 menu_choice)
7403 {
7404 SInt16 menu_id, menu_item;
7405
7406 menu_id = HiWord (menu_choice);
7407 menu_item = LoWord (menu_choice);
7408
7409 if (menu_id == 0)
7410 return;
7411
7412 switch (menu_id)
7413 {
7414 case M_APPLE:
7415 do_apple_menu (menu_item);
7416 break;
7417
7418 default:
7419 {
7420 struct frame *f = mac_window_to_frame (front_emacs_window ());
7421 MenuHandle menu = GetMenuHandle (menu_id);
7422 if (menu)
7423 {
7424 UInt32 refcon;
7425
7426 GetMenuItemRefCon (menu, menu_item, &refcon);
7427 menubar_selection_callback (f, refcon);
7428 }
7429 }
7430 }
7431
7432 HiliteMenu (0);
7433 }
7434
7435
7436 /* Handle drags in size box. Based on code contributed by Ben
7437 Mesander and IM - Window Manager A. */
7438
7439 static void
7440 do_grow_window (WindowPtr w, EventRecord *e)
7441 {
7442 long grow_size;
7443 Rect limit_rect;
7444 int rows, columns;
7445 struct frame *f = mac_window_to_frame (w);
7446
7447 SetRect(&limit_rect, MIN_DOC_SIZE, MIN_DOC_SIZE, MAX_DOC_SIZE, MAX_DOC_SIZE);
7448
7449 grow_size = GrowWindow (w, e->where, &limit_rect);
7450
7451 /* see if it really changed size */
7452 if (grow_size != 0)
7453 {
7454 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, HiWord (grow_size));
7455 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, LoWord (grow_size));
7456
7457 x_set_window_size (f, 0, columns, rows);
7458 }
7459 }
7460
7461
7462 /* Handle clicks in zoom box. Calculation of "standard state" based
7463 on code in IM - Window Manager A and code contributed by Ben
7464 Mesander. The standard state of an Emacs window is 80-characters
7465 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */
7466
7467 static void
7468 do_zoom_window (WindowPtr w, int zoom_in_or_out)
7469 {
7470 GrafPtr save_port;
7471 Rect zoom_rect, port_rect;
7472 Point top_left;
7473 int w_title_height, columns, rows;
7474 struct frame *f = mac_window_to_frame (w);
7475
7476 #if TARGET_API_MAC_CARBON
7477 {
7478 Point standard_size;
7479
7480 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7481 standard_size.v = FRAME_MAC_DISPLAY_INFO (f)->height;
7482
7483 if (IsWindowInStandardState (w, &standard_size, &zoom_rect))
7484 zoom_in_or_out = inZoomIn;
7485 else
7486 {
7487 /* Adjust the standard size according to character boundaries. */
7488
7489 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, zoom_rect.right - zoom_rect.left);
7490 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7491 standard_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns);
7492 standard_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7493 GetWindowBounds (w, kWindowContentRgn, &port_rect);
7494 if (IsWindowInStandardState (w, &standard_size, &zoom_rect)
7495 && port_rect.left == zoom_rect.left
7496 && port_rect.top == zoom_rect.top)
7497 zoom_in_or_out = inZoomIn;
7498 else
7499 zoom_in_or_out = inZoomOut;
7500 }
7501
7502 ZoomWindowIdeal (w, zoom_in_or_out, &standard_size);
7503 }
7504 #else /* not TARGET_API_MAC_CARBON */
7505 GetPort (&save_port);
7506
7507 SetPortWindowPort (w);
7508
7509 /* Clear window to avoid flicker. */
7510 EraseRect (&(w->portRect));
7511 if (zoom_in_or_out == inZoomOut)
7512 {
7513 SetPt (&top_left, w->portRect.left, w->portRect.top);
7514 LocalToGlobal (&top_left);
7515
7516 /* calculate height of window's title bar */
7517 w_title_height = top_left.v - 1
7518 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight ();
7519
7520 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */
7521 zoom_rect = qd.screenBits.bounds;
7522 zoom_rect.top += w_title_height;
7523 InsetRect (&zoom_rect, 8, 4); /* not too tight */
7524
7525 zoom_rect.right = zoom_rect.left
7526 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS);
7527
7528 /* Adjust the standard size according to character boundaries. */
7529 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top);
7530 zoom_rect.bottom =
7531 zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
7532
7533 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState
7534 = zoom_rect;
7535 }
7536
7537 ZoomWindow (w, zoom_in_or_out, w == front_emacs_window ());
7538
7539 SetPort (save_port);
7540 #endif /* not TARGET_API_MAC_CARBON */
7541
7542 /* retrieve window size and update application values */
7543 #if TARGET_API_MAC_CARBON
7544 GetWindowPortBounds (w, &port_rect);
7545 #else
7546 port_rect = w->portRect;
7547 #endif
7548 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, port_rect.bottom - port_rect.top);
7549 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, port_rect.right - port_rect.left);
7550 x_set_window_size (f, 0, columns, rows);
7551 x_real_positions (f, &f->left_pos, &f->top_pos);
7552 }
7553
7554 /* Initialize Drag And Drop to allow files to be dropped onto emacs frames */
7555 static OSErr
7556 init_mac_drag_n_drop ()
7557 {
7558 OSErr result = InstallReceiveHandler (mac_do_receive_drag, 0L, NULL);
7559 return result;
7560 }
7561
7562 /* Intialize AppleEvent dispatcher table for the required events. */
7563 void
7564 init_required_apple_events ()
7565 {
7566 OSErr err;
7567 long result;
7568
7569 /* Make sure we have apple events before starting. */
7570 err = Gestalt (gestaltAppleEventsAttr, &result);
7571 if (err != noErr)
7572 abort ();
7573
7574 if (!(result & (1 << gestaltAppleEventsPresent)))
7575 abort ();
7576
7577 #if TARGET_API_MAC_CARBON
7578 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7579 NewAEEventHandlerUPP
7580 ((AEEventHandlerProcPtr) do_ae_open_application),
7581 0L, false);
7582 #else
7583 err = AEInstallEventHandler(kCoreEventClass, kAEOpenApplication,
7584 NewAEEventHandlerProc
7585 ((AEEventHandlerProcPtr) do_ae_open_application),
7586 0L, false);
7587 #endif
7588 if (err != noErr)
7589 abort ();
7590
7591 #if TARGET_API_MAC_CARBON
7592 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7593 NewAEEventHandlerUPP
7594 ((AEEventHandlerProcPtr) do_ae_open_documents),
7595 0L, false);
7596 #else
7597 err = AEInstallEventHandler(kCoreEventClass, kAEOpenDocuments,
7598 NewAEEventHandlerProc
7599 ((AEEventHandlerProcPtr) do_ae_open_documents),
7600 0L, false);
7601 #endif
7602 if (err != noErr)
7603 abort ();
7604
7605 #if TARGET_API_MAC_CARBON
7606 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7607 NewAEEventHandlerUPP
7608 ((AEEventHandlerProcPtr) do_ae_print_documents),
7609 0L, false);
7610 #else
7611 err = AEInstallEventHandler(kCoreEventClass, kAEPrintDocuments,
7612 NewAEEventHandlerProc
7613 ((AEEventHandlerProcPtr) do_ae_print_documents),
7614 0L, false);
7615 #endif
7616 if (err != noErr)
7617 abort ();
7618
7619 #if TARGET_API_MAC_CARBON
7620 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7621 NewAEEventHandlerUPP
7622 ((AEEventHandlerProcPtr) do_ae_quit_application),
7623 0L, false);
7624 #else
7625 err = AEInstallEventHandler(kCoreEventClass, kAEQuitApplication,
7626 NewAEEventHandlerProc
7627 ((AEEventHandlerProcPtr) do_ae_quit_application),
7628 0L, false);
7629 #endif
7630 if (err != noErr)
7631 abort ();
7632 }
7633
7634 #if USE_CARBON_EVENTS
7635
7636 void
7637 init_service_handler ()
7638 {
7639 EventTypeSpec specs[] = {{kEventClassService, kEventServiceGetTypes},
7640 {kEventClassService, kEventServiceCopy},
7641 {kEventClassService, kEventServicePaste}};
7642 InstallApplicationEventHandler (NewEventHandlerUPP (mac_handle_service_event),
7643 3, specs, NULL, NULL);
7644 }
7645
7646 /*
7647 MAC_TODO: Check to see if this is called by AEProcessDesc...
7648 */
7649 OSStatus
7650 mac_handle_service_event (EventHandlerCallRef callRef,
7651 EventRef event, void *data)
7652 {
7653 OSStatus err = noErr;
7654 switch (GetEventKind (event))
7655 {
7656 case kEventServiceGetTypes:
7657 {
7658 CFMutableArrayRef copyTypes, pasteTypes;
7659 CFStringRef type;
7660 Boolean selection = true;
7661 /*
7662 GetEventParameter(event, kEventParamServicePasteTypes,
7663 typeCFMutableArrayRef, NULL,
7664 sizeof (CFMutableArrayRef), NULL, &pasteTypes);
7665 */
7666 GetEventParameter(event, kEventParamServiceCopyTypes,
7667 typeCFMutableArrayRef, NULL,
7668 sizeof (CFMutableArrayRef), NULL, &copyTypes);
7669 type = CreateTypeStringWithOSType (kScrapFlavorTypeText);
7670 if (type) {
7671 CFArrayAppendValue (copyTypes, type);
7672 //CFArrayAppendValue (pasteTypes, type);
7673 CFRelease (type);
7674 }
7675 }
7676 case kEventServiceCopy:
7677 {
7678 ScrapRef currentScrap, specificScrap;
7679 char * buf = "";
7680 Size byteCount = 0;
7681
7682 GetCurrentScrap (&currentScrap);
7683
7684 err = GetScrapFlavorSize (currentScrap, kScrapFlavorTypeText, &byteCount);
7685 if (err == noErr)
7686 {
7687 void *buffer = xmalloc (byteCount);
7688 if (buffer != NULL)
7689 {
7690 GetEventParameter (event, kEventParamScrapRef, typeScrapRef, NULL,
7691 sizeof (ScrapRef), NULL, &specificScrap);
7692
7693 err = GetScrapFlavorData (currentScrap, kScrapFlavorTypeText,
7694 &byteCount, buffer);
7695 if (err == noErr)
7696 PutScrapFlavor (specificScrap, kScrapFlavorTypeText,
7697 kScrapFlavorMaskNone, byteCount, buffer);
7698 xfree (buffer);
7699 }
7700 }
7701 err = noErr;
7702 }
7703 case kEventServicePaste:
7704 {
7705 /*
7706 // Get the current location
7707 Size byteCount;
7708 ScrapRef specificScrap;
7709 GetEventParameter(event, kEventParamScrapRef, typeScrapRef, NULL,
7710 sizeof(ScrapRef), NULL, &specificScrap);
7711 err = GetScrapFlavorSize(specificScrap, kScrapFlavorTypeText, &byteCount);
7712 if (err == noErr) {
7713 void * buffer = xmalloc(byteCount);
7714 if (buffer != NULL ) {
7715 err = GetScrapFlavorData(specificScrap, kScrapFlavorTypeText,
7716 &byteCount, buffer);
7717 if (err == noErr) {
7718 // Actually place in the buffer
7719 BLOCK_INPUT;
7720 // Get the current "selection" string here
7721 UNBLOCK_INPUT;
7722 }
7723 }
7724 xfree(buffer);
7725 }
7726 */
7727 }
7728 }
7729 return err;
7730 }
7731 #endif
7732
7733 /* Open Application Apple Event */
7734 static pascal OSErr
7735 do_ae_open_application(const AppleEvent *pae, AppleEvent *preply, long prefcon)
7736 {
7737 return noErr;
7738 }
7739
7740
7741 /* Defined in mac.c. */
7742 extern int
7743 path_from_vol_dir_name (char *, int, short, long, char *);
7744
7745
7746 /* Called when we receive an AppleEvent with an ID of
7747 "kAEOpenDocuments". This routine gets the direct parameter,
7748 extracts the FSSpecs in it, and puts their names on a list. */
7749 static pascal OSErr
7750 do_ae_open_documents(AppleEvent *message, AppleEvent *reply, long refcon)
7751 {
7752 OSErr err, err2;
7753 AEDesc the_desc;
7754 AEKeyword keyword;
7755 DescType actual_type;
7756 Size actual_size;
7757
7758 err = AEGetParamDesc (message, keyDirectObject, typeAEList, &the_desc);
7759 if (err != noErr)
7760 goto descriptor_error_exit;
7761
7762 /* Check to see that we got all of the required parameters from the
7763 event descriptor. For an 'odoc' event this should just be the
7764 file list. */
7765 err = AEGetAttributePtr(message, keyMissedKeywordAttr, typeWildCard,
7766 &actual_type, (Ptr) &keyword,
7767 sizeof (keyword), &actual_size);
7768 /* No error means that we found some unused parameters.
7769 errAEDescNotFound means that there are no more parameters. If we
7770 get an error code other than that, flag it. */
7771 if ((err == noErr) || (err != errAEDescNotFound))
7772 {
7773 err = errAEEventNotHandled;
7774 goto error_exit;
7775 }
7776 err = noErr;
7777
7778 /* Got all the parameters we need. Now, go through the direct
7779 object list and parse it up. */
7780 {
7781 long num_files_to_open;
7782
7783 err = AECountItems (&the_desc, &num_files_to_open);
7784 if (err == noErr)
7785 {
7786 int i;
7787
7788 /* AE file list is one based so just use that for indexing here. */
7789 for (i = 1; (err == noErr) && (i <= num_files_to_open); i++)
7790 {
7791 FSSpec fs;
7792 Str255 path_name, unix_path_name;
7793 #ifdef MAC_OSX
7794 FSRef fref;
7795 #endif
7796
7797 err = AEGetNthPtr(&the_desc, i, typeFSS, &keyword, &actual_type,
7798 (Ptr) &fs, sizeof (fs), &actual_size);
7799 if (err != noErr) break;
7800
7801 #ifdef MAC_OSX
7802 err = FSpMakeFSRef (&fs, &fref);
7803 if (err != noErr) break;
7804
7805 if (FSRefMakePath (&fref, unix_path_name, 255) == noErr)
7806 #else
7807 if (path_from_vol_dir_name (path_name, 255, fs.vRefNum, fs.parID,
7808 fs.name) &&
7809 mac_to_posix_pathname (path_name, unix_path_name, 255))
7810 #endif
7811 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
7812 drag_and_drop_file_list);
7813 }
7814 }
7815 }
7816
7817 error_exit:
7818 /* Nuke the coerced file list in any case */
7819 err2 = AEDisposeDesc(&the_desc);
7820
7821 descriptor_error_exit:
7822 /* InvalRect(&(gFrontMacWindowP->mWP->portRect)); */
7823 return err;
7824 }
7825
7826
7827 static pascal OSErr
7828 mac_do_receive_drag (WindowPtr window, void *handlerRefCon,
7829 DragReference theDrag)
7830 {
7831 short items;
7832 short index;
7833 FlavorFlags theFlags;
7834 Point mouse;
7835 OSErr result;
7836 ItemReference theItem;
7837 HFSFlavor data;
7838 FSRef fref;
7839 Size size = sizeof (HFSFlavor);
7840
7841 drag_and_drop_file_list = Qnil;
7842 GetDragMouse (theDrag, &mouse, 0L);
7843 CountDragItems (theDrag, &items);
7844 for (index = 1; index <= items; index++)
7845 {
7846 /* Only handle file references. */
7847 GetDragItemReferenceNumber (theDrag, index, &theItem);
7848 result = GetFlavorFlags (theDrag, theItem, flavorTypeHFS, &theFlags);
7849 if (result == noErr)
7850 {
7851 #ifdef MAC_OSX
7852 FSRef frref;
7853 #else
7854 Str255 path_name;
7855 #endif
7856 Str255 unix_path_name;
7857 GetFlavorData (theDrag, theItem, flavorTypeHFS, &data, &size, 0L);
7858 #ifdef MAC_OSX
7859 /* Use Carbon routines, otherwise it converts the file name
7860 to /Macintosh HD/..., which is not correct. */
7861 FSpMakeFSRef (&data.fileSpec, &fref);
7862 if (! FSRefMakePath (&fref, unix_path_name, sizeof (unix_path_name)));
7863 #else
7864 if (path_from_vol_dir_name (path_name, 255, data.fileSpec.vRefNum,
7865 data.fileSpec.parID, data.fileSpec.name) &&
7866 mac_to_posix_pathname (path_name, unix_path_name, 255))
7867 #endif
7868 drag_and_drop_file_list = Fcons (build_string (unix_path_name),
7869 drag_and_drop_file_list);
7870 }
7871 else
7872 return;
7873 }
7874 /* If there are items in the list, construct an event and post it to
7875 the queue like an interrupt using kbd_buffer_store_event. */
7876 if (!NILP (drag_and_drop_file_list))
7877 {
7878 struct input_event event;
7879 Lisp_Object frame;
7880 struct frame *f = mac_window_to_frame (window);
7881 SetPortWindowPort (window);
7882 GlobalToLocal (&mouse);
7883
7884 event.kind = DRAG_N_DROP_EVENT;
7885 event.code = 0;
7886 event.modifiers = 0;
7887 event.timestamp = TickCount () * (1000 / 60);
7888 XSETINT (event.x, mouse.h);
7889 XSETINT (event.y, mouse.v);
7890 XSETFRAME (frame, f);
7891 event.frame_or_window = Fcons (frame, drag_and_drop_file_list);
7892 event.arg = Qnil;
7893 /* Post to the interrupt queue */
7894 kbd_buffer_store_event (&event);
7895 /* MAC_TODO: Mimic behavior of windows by switching contexts to Emacs */
7896 {
7897 ProcessSerialNumber psn;
7898 GetCurrentProcess (&psn);
7899 SetFrontProcess (&psn);
7900 }
7901 }
7902 }
7903
7904
7905 /* Print Document Apple Event */
7906 static pascal OSErr
7907 do_ae_print_documents (const AppleEvent *pAE, AppleEvent *reply, long refcon)
7908 {
7909 return errAEEventNotHandled;
7910 }
7911
7912
7913 static pascal OSErr
7914 do_ae_quit_application (AppleEvent* message, AppleEvent *reply, long refcon)
7915 {
7916 /* FixMe: Do we need an unwind-protect or something here? And what
7917 do we do about unsaved files. Currently just forces quit rather
7918 than doing recursive callback to get user input. */
7919
7920 terminate_flag = true;
7921
7922 /* Fkill_emacs doesn't return. We have to return. (TI) */
7923 return noErr;
7924 }
7925
7926
7927 #if __profile__
7928 void
7929 profiler_exit_proc ()
7930 {
7931 ProfilerDump ("\pEmacs.prof");
7932 ProfilerTerm ();
7933 }
7934 #endif
7935
7936 /* These few functions implement Emacs as a normal Mac application
7937 (almost): set up the heap and the Toolbox, handle necessary
7938 system events plus a few simple menu events. They also set up
7939 Emacs's access to functions defined in the rest of this file.
7940 Emacs uses function hooks to perform all its terminal I/O. A
7941 complete list of these functions appear in termhooks.h. For what
7942 they do, read the comments there and see also w32term.c and
7943 xterm.c. What's noticeably missing here is the event loop, which
7944 is normally present in most Mac application. After performing the
7945 necessary Mac initializations, main passes off control to
7946 emacs_main (corresponding to main in emacs.c). Emacs_main calls
7947 mac_read_socket (defined further below) to read input. This is
7948 where WaitNextEvent is called to process Mac events. This is also
7949 where check_alarm in sysdep.c is called to simulate alarm signals.
7950 This makes the cursor jump back to its correct position after
7951 briefly jumping to that of the matching parenthesis, print useful
7952 hints and prompts in the minibuffer after the user stops typing for
7953 a wait, etc. */
7954
7955 #if !TARGET_API_MAC_CARBON
7956 #undef main
7957 int
7958 main (void)
7959 {
7960 #if __profile__ /* is the profiler on? */
7961 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200))
7962 exit(1);
7963 #endif
7964
7965 #if __MWERKS__
7966 /* set creator and type for files created by MSL */
7967 _fcreator = 'EMAx';
7968 _ftype = 'TEXT';
7969 #endif
7970
7971 do_init_managers ();
7972
7973 do_get_menus ();
7974
7975 #ifndef USE_LSB_TAG
7976 do_check_ram_size ();
7977 #endif
7978
7979 init_emacs_passwd_dir ();
7980
7981 init_environ ();
7982
7983 initialize_applescript ();
7984
7985 init_required_apple_events ();
7986
7987 {
7988 char **argv;
7989 int argc = 0;
7990
7991 /* set up argv array from STR# resource */
7992 get_string_list (&argv, ARGV_STRING_LIST_ID);
7993 while (argv[argc])
7994 argc++;
7995
7996 /* free up AppleScript resources on exit */
7997 atexit (terminate_applescript);
7998
7999 #if __profile__ /* is the profiler on? */
8000 atexit (profiler_exit_proc);
8001 #endif
8002
8003 /* 3rd param "envp" never used in emacs_main */
8004 (void) emacs_main (argc, argv, 0);
8005 }
8006
8007 /* Never reached - real exit in Fkill_emacs */
8008 return 0;
8009 }
8010 #endif
8011
8012 /* Table for translating Mac keycode to X keysym values. Contributed
8013 by Sudhir Shenoy. */
8014 static unsigned char keycode_to_xkeysym_table[] = {
8015 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8016 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8017 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
8018
8019 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/,
8020 /*0x34*/ 0, 0x1b /*escape*/, 0, 0,
8021 /*0x38*/ 0, 0, 0, 0,
8022 /*0x3C*/ 0, 0, 0, 0,
8023
8024 /*0x40*/ 0, 0xae /*kp-.*/, 0, 0xaa /*kp-**/,
8025 /*0x44*/ 0, 0xab /*kp-+*/, 0, 0x7f /*kp-clear*/,
8026 /*0x48*/ 0, 0, 0, 0xaf /*kp-/*/,
8027 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp--*/, 0,
8028
8029 /*0x50*/ 0, 0xbd /*kp-=*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/,
8030 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/,
8031 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/,
8032 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0,
8033
8034 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/,
8035 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/,
8036 /*0x68*/ 0, 0xca /*f13*/, 0, 0xcb /*f14*/,
8037 /*0x6C*/ 0, 0xc7 /*f10*/, 0, 0xc9 /*f12*/,
8038
8039 /*0x70*/ 0, 0xcc /*f15*/, 0x9e /*insert (or 0x6a==help)*/, 0x95 /*home*/,
8040 /*0x74*/ 0x9a /*pgup*/, 0x9f /*delete*/, 0xc1 /*f4*/, 0x9c /*end*/,
8041 /*0x78*/ 0xbf /*f2*/, 0x9b /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/,
8042 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0
8043 };
8044
8045 static int
8046 keycode_to_xkeysym (int keyCode, int *xKeySym)
8047 {
8048 *xKeySym = keycode_to_xkeysym_table [keyCode & 0x7f];
8049 return *xKeySym != 0;
8050 }
8051
8052 /* Emacs calls this whenever it wants to read an input event from the
8053 user. */
8054 int
8055 XTread_socket (sd, expected, hold_quit)
8056 int sd, expected;
8057 struct input_event *hold_quit;
8058 {
8059 struct input_event inev;
8060 int count = 0;
8061 #if USE_CARBON_EVENTS
8062 EventRef eventRef;
8063 EventTargetRef toolbox_dispatcher = GetEventDispatcherTarget ();
8064 #else
8065 EventMask event_mask;
8066 #endif
8067 EventRecord er;
8068 struct mac_display_info *dpyinfo = &one_mac_display_info;
8069
8070 if (interrupt_input_blocked)
8071 {
8072 interrupt_input_pending = 1;
8073 return -1;
8074 }
8075
8076 interrupt_input_pending = 0;
8077 BLOCK_INPUT;
8078
8079 /* So people can tell when we have read the available input. */
8080 input_signal_count++;
8081
8082 /* Don't poll for events to process (specifically updateEvt) if
8083 window update currently already in progress. A call to redisplay
8084 (in do_window_update) can be preempted by another call to
8085 redisplay, causing blank regions to be left on the screen and the
8086 cursor to be left at strange places. */
8087 if (handling_window_update)
8088 {
8089 UNBLOCK_INPUT;
8090 return 0;
8091 }
8092
8093 if (terminate_flag)
8094 Fkill_emacs (make_number (1));
8095
8096 #if !USE_CARBON_EVENTS
8097 event_mask = everyEvent;
8098 if (NILP (Fboundp (Qmac_ready_for_drag_n_drop)))
8099 event_mask -= highLevelEventMask;
8100
8101 while (WaitNextEvent (event_mask, &er, 0L, NULL))
8102 #else /* USE_CARBON_EVENTS */
8103 while (!ReceiveNextEvent (0, NULL, kEventDurationNoWait,
8104 kEventRemoveFromQueue, &eventRef))
8105 #endif /* USE_CARBON_EVENTS */
8106 {
8107 int do_help = 0;
8108 struct frame *f;
8109
8110 /* It is necessary to set this (additional) argument slot of an
8111 event to nil because keyboard.c protects incompletely
8112 processed event from being garbage collected by placing them
8113 in the kbd_buffer_gcpro vector. */
8114 EVENT_INIT (inev);
8115 inev.kind = NO_EVENT;
8116 inev.arg = Qnil;
8117
8118 #if USE_CARBON_EVENTS
8119 /* Handle new events */
8120 if (!mac_convert_event_ref (eventRef, &er))
8121 switch (GetEventClass (eventRef))
8122 {
8123 case kEventClassWindow:
8124 if (GetEventKind (eventRef) == kEventWindowBoundsChanged)
8125 {
8126 WindowPtr window_ptr;
8127 GetEventParameter(eventRef, kEventParamDirectObject,
8128 typeWindowRef, NULL, sizeof(WindowPtr),
8129 NULL, &window_ptr);
8130 f = mac_window_to_frame (window_ptr);
8131 if (f && !f->async_iconified)
8132 x_real_positions (f, &f->left_pos, &f->top_pos);
8133 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8134 }
8135 break;
8136 case kEventClassMouse:
8137 if (GetEventKind (eventRef) == kEventMouseWheelMoved)
8138 {
8139 SInt32 delta;
8140 Point point;
8141 WindowPtr window_ptr = front_emacs_window ();
8142
8143 if (!IsValidWindowPtr (window_ptr))
8144 {
8145 SysBeep(1);
8146 break;
8147 }
8148
8149 GetEventParameter(eventRef, kEventParamMouseWheelDelta,
8150 typeSInt32, NULL, sizeof (SInt32),
8151 NULL, &delta);
8152 GetEventParameter(eventRef, kEventParamMouseLocation,
8153 typeQDPoint, NULL, sizeof (Point),
8154 NULL, &point);
8155 inev.kind = WHEEL_EVENT;
8156 inev.code = 0;
8157 inev.modifiers = (mac_event_to_emacs_modifiers (eventRef)
8158 | ((delta < 0) ? down_modifier
8159 : up_modifier));
8160 SetPortWindowPort (window_ptr);
8161 GlobalToLocal (&point);
8162 XSETINT (inev.x, point.h);
8163 XSETINT (inev.y, point.v);
8164 XSETFRAME (inev.frame_or_window,
8165 mac_window_to_frame (window_ptr));
8166 inev.timestamp = EventTimeToTicks (GetEventTime (eventRef))*(1000/60);
8167 }
8168 else
8169 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8170
8171 break;
8172 default:
8173 /* Send the event to the appropriate receiver. */
8174 SendEventToEventTarget (eventRef, toolbox_dispatcher);
8175 }
8176 else
8177 #endif /* USE_CARBON_EVENTS */
8178 switch (er.what)
8179 {
8180 case mouseDown:
8181 case mouseUp:
8182 {
8183 WindowPtr window_ptr;
8184 SInt16 part_code;
8185 int tool_bar_p = 0;
8186
8187 #if USE_CARBON_EVENTS
8188 /* This is needed to send mouse events like aqua window
8189 buttons to the correct handler. */
8190 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8191 != eventNotHandledErr)
8192 break;
8193 #endif
8194
8195 if (dpyinfo->grabbed && last_mouse_frame
8196 && FRAME_LIVE_P (last_mouse_frame))
8197 {
8198 window_ptr = FRAME_MAC_WINDOW (last_mouse_frame);
8199 part_code = inContent;
8200 }
8201 else
8202 {
8203 part_code = FindWindow (er.where, &window_ptr);
8204 if (tip_window && window_ptr == tip_window)
8205 {
8206 HideWindow (tip_window);
8207 part_code = FindWindow (er.where, &window_ptr);
8208 }
8209 }
8210
8211 if (er.what != mouseDown && part_code != inContent)
8212 break;
8213
8214 switch (part_code)
8215 {
8216 case inMenuBar:
8217 f = mac_window_to_frame (front_emacs_window ());
8218 saved_menu_event_location = er.where;
8219 inev.kind = MENU_BAR_ACTIVATE_EVENT;
8220 XSETFRAME (inev.frame_or_window, f);
8221 break;
8222
8223 case inContent:
8224 if (window_ptr != front_emacs_window ())
8225 SelectWindow (window_ptr);
8226 else
8227 {
8228 SInt16 control_part_code;
8229 ControlHandle ch;
8230 Point mouse_loc = er.where;
8231
8232 f = mac_window_to_frame (window_ptr);
8233 /* convert to local coordinates of new window */
8234 SetPortWindowPort (window_ptr);
8235
8236 GlobalToLocal (&mouse_loc);
8237 #if TARGET_API_MAC_CARBON
8238 ch = FindControlUnderMouse (mouse_loc, window_ptr,
8239 &control_part_code);
8240 #else
8241 control_part_code = FindControl (mouse_loc, window_ptr,
8242 &ch);
8243 #endif
8244
8245 #if USE_CARBON_EVENTS
8246 inev.code = mac_get_mouse_btn (eventRef);
8247 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
8248 #else
8249 inev.code = mac_get_emulated_btn (er.modifiers);
8250 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
8251 #endif
8252 XSETINT (inev.x, mouse_loc.h);
8253 XSETINT (inev.y, mouse_loc.v);
8254 inev.timestamp = er.when * (1000 / 60);
8255 /* ticks to milliseconds */
8256
8257 if (dpyinfo->grabbed && tracked_scroll_bar
8258 #if TARGET_API_MAC_CARBON
8259 || ch != 0
8260 #else
8261 || control_part_code != 0
8262 #endif
8263 )
8264 {
8265 struct scroll_bar *bar;
8266
8267 if (dpyinfo->grabbed && tracked_scroll_bar)
8268 {
8269 bar = tracked_scroll_bar;
8270 control_part_code = kControlIndicatorPart;
8271 }
8272 else
8273 bar = (struct scroll_bar *) GetControlReference (ch);
8274 x_scroll_bar_handle_click (bar, control_part_code,
8275 &er, &inev);
8276 if (er.what == mouseDown
8277 && control_part_code == kControlIndicatorPart)
8278 tracked_scroll_bar = bar;
8279 else
8280 tracked_scroll_bar = NULL;
8281 }
8282 else
8283 {
8284 Lisp_Object window;
8285 int x = mouse_loc.h;
8286 int y = mouse_loc.v;
8287
8288 window = window_from_coordinates (f, x, y, 0, 0, 0, 1);
8289 if (EQ (window, f->tool_bar_window))
8290 {
8291 if (er.what == mouseDown)
8292 handle_tool_bar_click (f, x, y, 1, 0);
8293 else
8294 handle_tool_bar_click (f, x, y, 0,
8295 inev.modifiers);
8296 tool_bar_p = 1;
8297 }
8298 else
8299 {
8300 XSETFRAME (inev.frame_or_window, f);
8301 inev.kind = MOUSE_CLICK_EVENT;
8302 }
8303 }
8304
8305 if (er.what == mouseDown)
8306 {
8307 dpyinfo->grabbed |= (1 << inev.code);
8308 last_mouse_frame = f;
8309 /* Ignore any mouse motion that happened
8310 before this event; any subsequent
8311 mouse-movement Emacs events should reflect
8312 only motion after the ButtonPress. */
8313 if (f != 0)
8314 f->mouse_moved = 0;
8315
8316 if (!tool_bar_p)
8317 last_tool_bar_item = -1;
8318 }
8319 else
8320 {
8321 if ((dpyinfo->grabbed & (1 << inev.code)) == 0)
8322 /* If a button is released though it was not
8323 previously pressed, that would be because
8324 of multi-button emulation. */
8325 dpyinfo->grabbed = 0;
8326 else
8327 dpyinfo->grabbed &= ~(1 << inev.code);
8328 }
8329
8330 switch (er.what)
8331 {
8332 case mouseDown:
8333 inev.modifiers |= down_modifier;
8334 break;
8335 case mouseUp:
8336 inev.modifiers |= up_modifier;
8337 break;
8338 }
8339 }
8340 break;
8341
8342 case inDrag:
8343 #if TARGET_API_MAC_CARBON
8344 DragWindow (window_ptr, er.where, NULL);
8345 #else /* not TARGET_API_MAC_CARBON */
8346 DragWindow (window_ptr, er.where, &qd.screenBits.bounds);
8347 #endif /* not TARGET_API_MAC_CARBON */
8348 /* Update the frame parameters. */
8349 {
8350 struct frame *f = mac_window_to_frame (window_ptr);
8351
8352 if (f && !f->async_iconified)
8353 x_real_positions (f, &f->left_pos, &f->top_pos);
8354 }
8355 break;
8356
8357 case inGoAway:
8358 if (TrackGoAway (window_ptr, er.where))
8359 {
8360 inev.kind = DELETE_WINDOW_EVENT;
8361 XSETFRAME (inev.frame_or_window,
8362 mac_window_to_frame (window_ptr));
8363 }
8364 break;
8365
8366 /* window resize handling added --ben */
8367 case inGrow:
8368 do_grow_window (window_ptr, &er);
8369 break;
8370
8371 /* window zoom handling added --ben */
8372 case inZoomIn:
8373 case inZoomOut:
8374 if (TrackBox (window_ptr, er.where, part_code))
8375 do_zoom_window (window_ptr, part_code);
8376 break;
8377
8378 default:
8379 break;
8380 }
8381 }
8382 break;
8383
8384 case updateEvt:
8385 #if USE_CARBON_EVENTS
8386 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8387 != eventNotHandledErr)
8388 break;
8389 #endif
8390 do_window_update ((WindowPtr) er.message);
8391 break;
8392
8393 case osEvt:
8394 #if USE_CARBON_EVENTS
8395 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8396 != eventNotHandledErr)
8397 break;
8398 #endif
8399 switch ((er.message >> 24) & 0x000000FF)
8400 {
8401 case suspendResumeMessage:
8402 if ((er.message & resumeFlag) == 1)
8403 do_app_resume ();
8404 else
8405 do_app_suspend ();
8406 break;
8407
8408 case mouseMovedMessage:
8409 previous_help_echo_string = help_echo_string;
8410 help_echo_string = help_echo_object = help_echo_window = Qnil;
8411 help_echo_pos = -1;
8412
8413 do_mouse_moved (er.where, &f);
8414
8415 /* If the contents of the global variable
8416 help_echo_string has changed, generate a
8417 HELP_EVENT. */
8418 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
8419 do_help = 1;
8420 break;
8421 }
8422 break;
8423
8424 case activateEvt:
8425 {
8426 WindowPtr window_ptr = (WindowPtr) er.message;
8427
8428 #if USE_CARBON_EVENTS
8429 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8430 != eventNotHandledErr)
8431 break;
8432 #endif
8433 if (window_ptr == tip_window)
8434 {
8435 HideWindow (tip_window);
8436 break;
8437 }
8438
8439 if (!is_emacs_window (window_ptr))
8440 break;
8441
8442 f = mac_window_to_frame (window_ptr);
8443
8444 if ((er.modifiers & activeFlag) != 0)
8445 {
8446 /* A window has been activated */
8447 Point mouse_loc = er.where;
8448
8449 x_new_focus_frame (dpyinfo, f);
8450 activate_scroll_bars (f);
8451
8452 SetPortWindowPort (window_ptr);
8453 GlobalToLocal (&mouse_loc);
8454 /* Window-activated event counts as mouse movement,
8455 so update things that depend on mouse position. */
8456 note_mouse_movement (mac_window_to_frame (window_ptr),
8457 &mouse_loc);
8458 }
8459 else
8460 {
8461 /* A window has been deactivated */
8462 dpyinfo->grabbed = 0;
8463
8464 if (f == dpyinfo->x_focus_frame)
8465 {
8466 x_new_focus_frame (dpyinfo, 0);
8467 deactivate_scroll_bars (f);
8468 }
8469
8470
8471 if (f == dpyinfo->mouse_face_mouse_frame)
8472 {
8473 /* If we move outside the frame, then we're
8474 certainly no longer on any text in the
8475 frame. */
8476 clear_mouse_face (dpyinfo);
8477 dpyinfo->mouse_face_mouse_frame = 0;
8478 }
8479
8480 /* Generate a nil HELP_EVENT to cancel a help-echo.
8481 Do it only if there's something to cancel.
8482 Otherwise, the startup message is cleared when the
8483 mouse leaves the frame. */
8484 if (any_help_event_p)
8485 do_help = -1;
8486 }
8487 }
8488 break;
8489
8490 case keyDown:
8491 case autoKey:
8492 {
8493 int keycode = (er.message & keyCodeMask) >> 8;
8494 int xkeysym;
8495
8496 #if USE_CARBON_EVENTS
8497 /* When using Carbon Events, we need to pass raw keyboard
8498 events to the TSM ourselves. If TSM handles it, it
8499 will pass back noErr, otherwise it will pass back
8500 "eventNotHandledErr" and we can process it
8501 normally. */
8502 if ((!NILP (Vmac_pass_command_to_system)
8503 || !(er.modifiers & cmdKey))
8504 && (!NILP (Vmac_pass_control_to_system)
8505 || !(er.modifiers & controlKey)))
8506 if (SendEventToEventTarget (eventRef, toolbox_dispatcher)
8507 != eventNotHandledErr)
8508 break;
8509 #endif
8510
8511 #if TARGET_API_MAC_CARBON
8512 if (!IsValidWindowPtr (front_emacs_window ()))
8513 {
8514 SysBeep (1);
8515 break;
8516 }
8517 #endif
8518
8519 ObscureCursor ();
8520
8521 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
8522 {
8523 clear_mouse_face (dpyinfo);
8524 dpyinfo->mouse_face_hidden = 1;
8525 }
8526
8527 if (keycode_to_xkeysym (keycode, &xkeysym))
8528 {
8529 inev.code = 0xff00 | xkeysym;
8530 inev.kind = NON_ASCII_KEYSTROKE_EVENT;
8531 }
8532 else
8533 {
8534 if (er.modifiers & (controlKey |
8535 (NILP (Vmac_command_key_is_meta) ? optionKey
8536 : cmdKey)))
8537 {
8538 /* This code comes from Keyboard Resource,
8539 Appendix C of IM - Text. This is necessary
8540 since shift is ignored in KCHR table
8541 translation when option or command is pressed.
8542 It also does not translate correctly
8543 control-shift chars like C-% so mask off shift
8544 here also */
8545 int new_modifiers = er.modifiers & 0xe600;
8546 /* mask off option and command */
8547 int new_keycode = keycode | new_modifiers;
8548 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache);
8549 unsigned long some_state = 0;
8550 inev.code = KeyTranslate (kchr_ptr, new_keycode,
8551 &some_state) & 0xff;
8552 }
8553 else
8554 inev.code = er.message & charCodeMask;
8555 inev.kind = ASCII_KEYSTROKE_EVENT;
8556 }
8557 }
8558
8559 /* If variable mac-convert-keyboard-input-to-latin-1 is
8560 non-nil, convert non-ASCII characters typed at the Mac
8561 keyboard (presumed to be in the Mac Roman encoding) to
8562 iso-latin-1 encoding before they are passed to Emacs.
8563 This enables the Mac keyboard to be used to enter
8564 non-ASCII iso-latin-1 characters directly. */
8565 if (mac_keyboard_text_encoding != kTextEncodingMacRoman
8566 && inev.kind == ASCII_KEYSTROKE_EVENT && inev.code >= 128)
8567 {
8568 static TECObjectRef converter = NULL;
8569 OSStatus the_err = noErr;
8570 OSStatus convert_status = noErr;
8571
8572 if (converter == NULL)
8573 {
8574 the_err = TECCreateConverter (&converter,
8575 kTextEncodingMacRoman,
8576 mac_keyboard_text_encoding);
8577 current_mac_keyboard_text_encoding
8578 = mac_keyboard_text_encoding;
8579 }
8580 else if (mac_keyboard_text_encoding
8581 != current_mac_keyboard_text_encoding)
8582 {
8583 /* Free the converter for the current encoding
8584 before creating a new one. */
8585 TECDisposeConverter (converter);
8586 the_err = TECCreateConverter (&converter,
8587 kTextEncodingMacRoman,
8588 mac_keyboard_text_encoding);
8589 current_mac_keyboard_text_encoding
8590 = mac_keyboard_text_encoding;
8591 }
8592
8593 if (the_err == noErr)
8594 {
8595 unsigned char ch = inev.code;
8596 ByteCount actual_input_length, actual_output_length;
8597 unsigned char outch;
8598
8599 convert_status = TECConvertText (converter, &ch, 1,
8600 &actual_input_length,
8601 &outch, 1,
8602 &actual_output_length);
8603 if (convert_status == noErr
8604 && actual_input_length == 1
8605 && actual_output_length == 1)
8606 inev.code = outch;
8607 }
8608 }
8609
8610 #if USE_CARBON_EVENTS
8611 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
8612 #else
8613 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
8614 #endif
8615 XSETFRAME (inev.frame_or_window,
8616 mac_window_to_frame (front_emacs_window ()));
8617 inev.timestamp = er.when * (1000 / 60); /* ticks to milliseconds */
8618 break;
8619
8620 case kHighLevelEvent:
8621 drag_and_drop_file_list = Qnil;
8622
8623 AEProcessAppleEvent(&er);
8624
8625 /* Build a DRAG_N_DROP_EVENT type event as is done in
8626 constuct_drag_n_drop in w32term.c. */
8627 if (!NILP (drag_and_drop_file_list))
8628 {
8629 struct frame *f = NULL;
8630 WindowPtr wp;
8631 Lisp_Object frame;
8632
8633 wp = front_emacs_window ();
8634
8635 if (!wp)
8636 {
8637 struct frame *f = XFRAME (XCAR (Vframe_list));
8638 CollapseWindow (FRAME_MAC_WINDOW (f), false);
8639 wp = front_emacs_window ();
8640 }
8641
8642 if (wp)
8643 f = mac_window_to_frame (wp);
8644
8645 inev.kind = DRAG_N_DROP_EVENT;
8646 inev.code = 0;
8647 inev.timestamp = er.when * (1000 / 60);
8648 /* ticks to milliseconds */
8649 #if USE_CARBON_EVENTS
8650 inev.modifiers = mac_event_to_emacs_modifiers (eventRef);
8651 #else
8652 inev.modifiers = mac_to_emacs_modifiers (er.modifiers);
8653 #endif
8654
8655 XSETINT (inev.x, 0);
8656 XSETINT (inev.y, 0);
8657
8658 XSETFRAME (frame, f);
8659 inev.frame_or_window = Fcons (frame, drag_and_drop_file_list);
8660
8661 /* Regardless of whether Emacs was suspended or in the
8662 foreground, ask it to redraw its entire screen.
8663 Otherwise parts of the screen can be left in an
8664 inconsistent state. */
8665 if (wp)
8666 #if TARGET_API_MAC_CARBON
8667 {
8668 Rect r;
8669
8670 GetWindowPortBounds (wp, &r);
8671 InvalWindowRect (wp, &r);
8672 }
8673 #else /* not TARGET_API_MAC_CARBON */
8674 InvalRect (&(wp->portRect));
8675 #endif /* not TARGET_API_MAC_CARBON */
8676 }
8677 default:
8678 break;
8679 }
8680 #if USE_CARBON_EVENTS
8681 ReleaseEvent (eventRef);
8682 #endif
8683
8684 if (inev.kind != NO_EVENT)
8685 {
8686 kbd_buffer_store_event_hold (&inev, hold_quit);
8687 count++;
8688 }
8689
8690 if (do_help
8691 && !(hold_quit && hold_quit->kind != NO_EVENT))
8692 {
8693 Lisp_Object frame;
8694
8695 if (f)
8696 XSETFRAME (frame, f);
8697 else
8698 frame = Qnil;
8699
8700 if (do_help > 0)
8701 {
8702 any_help_event_p = 1;
8703 gen_help_event (help_echo_string, frame, help_echo_window,
8704 help_echo_object, help_echo_pos);
8705 }
8706 else
8707 {
8708 help_echo_string = Qnil;
8709 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
8710 }
8711 count++;
8712 }
8713
8714 }
8715
8716 /* If the focus was just given to an autoraising frame,
8717 raise it now. */
8718 /* ??? This ought to be able to handle more than one such frame. */
8719 if (pending_autoraise_frame)
8720 {
8721 x_raise_frame (pending_autoraise_frame);
8722 pending_autoraise_frame = 0;
8723 }
8724
8725 #if !TARGET_API_MAC_CARBON
8726 check_alarm (); /* simulate the handling of a SIGALRM */
8727 #endif
8728
8729 UNBLOCK_INPUT;
8730 return count;
8731 }
8732
8733
8734 /* Need to override CodeWarrior's input function so no conversion is
8735 done on newlines Otherwise compiled functions in .elc files will be
8736 read incorrectly. Defined in ...:MSL C:MSL
8737 Common:Source:buffer_io.c. */
8738 #ifdef __MWERKS__
8739 void
8740 __convert_to_newlines (unsigned char * p, size_t * n)
8741 {
8742 #pragma unused(p,n)
8743 }
8744
8745 void
8746 __convert_from_newlines (unsigned char * p, size_t * n)
8747 {
8748 #pragma unused(p,n)
8749 }
8750 #endif
8751
8752
8753 /* Initialize the struct pointed to by MW to represent a new COLS x
8754 ROWS Macintosh window, using font with name FONTNAME and size
8755 FONTSIZE. */
8756 void
8757 make_mac_frame (FRAME_PTR fp)
8758 {
8759 mac_output *mwp;
8760 #if TARGET_API_MAC_CARBON
8761 static int making_terminal_window = 0;
8762 #else
8763 static int making_terminal_window = 1;
8764 #endif
8765
8766 mwp = fp->output_data.mac;
8767
8768 BLOCK_INPUT;
8769 if (making_terminal_window)
8770 {
8771 if (!(mwp->mWP = GetNewCWindow (TERM_WINDOW_RESOURCE, NULL,
8772 (WindowPtr) -1)))
8773 abort ();
8774 making_terminal_window = 0;
8775 }
8776 else
8777 {
8778 #if TARGET_API_MAC_CARBON
8779 Rect r;
8780
8781 SetRect (&r, 0, 0, 1, 1);
8782 if (CreateNewWindow (kDocumentWindowClass,
8783 kWindowStandardDocumentAttributes
8784 /* | kWindowToolbarButtonAttribute */,
8785 &r, &mwp->mWP) != noErr)
8786 #else
8787 if (!(mwp->mWP = GetNewCWindow (WINDOW_RESOURCE, NULL, (WindowPtr) -1)))
8788 #endif
8789 abort ();
8790 }
8791
8792 SetWRefCon (mwp->mWP, (long) mwp);
8793 /* so that update events can find this mac_output struct */
8794 mwp->mFP = fp; /* point back to emacs frame */
8795
8796 SizeWindow (mwp->mWP, FRAME_PIXEL_WIDTH (fp), FRAME_PIXEL_HEIGHT (fp), false);
8797 UNBLOCK_INPUT;
8798 }
8799
8800
8801 void
8802 make_mac_terminal_frame (struct frame *f)
8803 {
8804 Lisp_Object frame;
8805
8806 XSETFRAME (frame, f);
8807
8808 f->output_method = output_mac;
8809 f->output_data.mac = (struct mac_output *)
8810 xmalloc (sizeof (struct mac_output));
8811 bzero (f->output_data.mac, sizeof (struct mac_output));
8812
8813 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f);
8814
8815 FRAME_COLS (f) = 96;
8816 FRAME_LINES (f) = 4;
8817
8818 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
8819 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right;
8820
8821 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR;
8822
8823 f->output_data.mac->cursor_pixel = 0;
8824 f->output_data.mac->border_pixel = 0x00ff00;
8825 f->output_data.mac->mouse_pixel = 0xff00ff;
8826 f->output_data.mac->cursor_foreground_pixel = 0x0000ff;
8827
8828 FRAME_FONTSET (f) = -1;
8829 f->output_data.mac->explicit_parent = 0;
8830 f->left_pos = 4;
8831 f->top_pos = 4;
8832 f->border_width = 0;
8833
8834 f->internal_border_width = 0;
8835
8836 f->auto_raise = 1;
8837 f->auto_lower = 1;
8838
8839 f->new_text_cols = 0;
8840 f->new_text_lines = 0;
8841
8842 make_mac_frame (f);
8843
8844 x_make_gc (f);
8845
8846 /* Need to be initialized for unshow_buffer in window.c. */
8847 selected_window = f->selected_window;
8848
8849 Fmodify_frame_parameters (frame,
8850 Fcons (Fcons (Qfont,
8851 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil));
8852 Fmodify_frame_parameters (frame,
8853 Fcons (Fcons (Qforeground_color,
8854 build_string ("black")), Qnil));
8855 Fmodify_frame_parameters (frame,
8856 Fcons (Fcons (Qbackground_color,
8857 build_string ("white")), Qnil));
8858
8859 ShowWindow (f->output_data.mac->mWP);
8860 }
8861
8862 \f
8863 /***********************************************************************
8864 Initialization
8865 ***********************************************************************/
8866
8867 int mac_initialized = 0;
8868
8869 void
8870 mac_initialize_display_info ()
8871 {
8872 struct mac_display_info *dpyinfo = &one_mac_display_info;
8873 GDHandle main_device_handle;
8874
8875 bzero (dpyinfo, sizeof (*dpyinfo));
8876
8877 /* Put it on x_display_name_list. */
8878 x_display_name_list = Fcons (Fcons (build_string ("Mac"), Qnil),
8879 x_display_name_list);
8880 dpyinfo->name_list_element = XCAR (x_display_name_list);
8881
8882 #if 0
8883 dpyinfo->mac_id_name
8884 = (char *) xmalloc (SCHARS (Vinvocation_name)
8885 + SCHARS (Vsystem_name)
8886 + 2);
8887 sprintf (dpyinfo->mac_id_name, "%s@%s",
8888 SDATA (Vinvocation_name), SDATA (Vsystem_name));
8889 #else
8890 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1);
8891 strcpy (dpyinfo->mac_id_name, "Mac Display");
8892 #endif
8893
8894 main_device_handle = LMGetMainDevice();
8895
8896 dpyinfo->reference_count = 0;
8897 dpyinfo->resx = 75.0;
8898 dpyinfo->resy = 75.0;
8899 dpyinfo->color_p = TestDeviceAttribute (main_device_handle, gdDevType);
8900 #ifdef MAC_OSX
8901 /* HasDepth returns true if it is possible to have a 32 bit display,
8902 but this may not be what is actually used. Mac OSX can do better.
8903 CGMainDisplayID is only available on OSX 10.2 and higher, but the
8904 header for CGGetActiveDisplayList says that the first display returned
8905 is the active one, so we use that. */
8906 {
8907 CGDirectDisplayID disp_id[1];
8908 CGDisplayCount disp_count;
8909 CGDisplayErr error_code;
8910
8911 error_code = CGGetActiveDisplayList (1, disp_id, &disp_count);
8912 if (error_code != 0)
8913 error ("No display found, CGGetActiveDisplayList error %d", error_code);
8914
8915 dpyinfo->n_planes = CGDisplayBitsPerPixel (disp_id[0]);
8916 }
8917 #else
8918 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1)
8919 if (HasDepth (main_device_handle, dpyinfo->n_planes,
8920 gdDevType, dpyinfo->color_p))
8921 break;
8922 #endif
8923 dpyinfo->height = (**main_device_handle).gdRect.bottom;
8924 dpyinfo->width = (**main_device_handle).gdRect.right;
8925 dpyinfo->grabbed = 0;
8926 dpyinfo->root_window = NULL;
8927 dpyinfo->image_cache = make_image_cache ();
8928
8929 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
8930 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
8931 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
8932 dpyinfo->mouse_face_window = Qnil;
8933 dpyinfo->mouse_face_overlay = Qnil;
8934 dpyinfo->mouse_face_hidden = 0;
8935 }
8936
8937 struct mac_display_info *
8938 mac_term_init (display_name, xrm_option, resource_name)
8939 Lisp_Object display_name;
8940 char *xrm_option;
8941 char *resource_name;
8942 {
8943 struct mac_display_info *dpyinfo;
8944 GDHandle main_device_handle;
8945
8946 if (!mac_initialized)
8947 {
8948 mac_initialize ();
8949 mac_initialized = 1;
8950 }
8951
8952 mac_initialize_display_info (display_name);
8953
8954 dpyinfo = &one_mac_display_info;
8955
8956 main_device_handle = LMGetMainDevice();
8957
8958 dpyinfo->height = (**main_device_handle).gdRect.bottom;
8959 dpyinfo->width = (**main_device_handle).gdRect.right;
8960
8961 return dpyinfo;
8962 }
8963 \f
8964 #ifdef MAC_OSX
8965 void
8966 mac_check_bundle()
8967 {
8968 extern int inhibit_window_system;
8969 extern int noninteractive;
8970 CFBundleRef appsBundle;
8971 pid_t child;
8972
8973 /* No need to test if already -nw*/
8974 if (inhibit_window_system || noninteractive)
8975 return;
8976
8977 appsBundle = CFBundleGetMainBundle();
8978 if (appsBundle != NULL)
8979 {
8980 CFStringRef cfBI = CFSTR("CFBundleIdentifier");
8981 CFTypeRef res = CFBundleGetValueForInfoDictionaryKey(appsBundle, cfBI);
8982 /* We found the bundle identifier, now we know we are valid. */
8983 if (res != NULL)
8984 {
8985 CFRelease(res);
8986 return;
8987 }
8988 }
8989 /* MAC_TODO: Have this start the bundled executable */
8990
8991 /* For now, prevent the fatal error by bringing it up in the terminal */
8992 inhibit_window_system = 1;
8993 }
8994
8995 void
8996 MakeMeTheFrontProcess ()
8997 {
8998 ProcessSerialNumber psn;
8999 OSErr err;
9000
9001 err = GetCurrentProcess (&psn);
9002 if (err == noErr)
9003 (void) SetFrontProcess (&psn);
9004 }
9005
9006 /***** Code to handle C-g testing *****/
9007
9008 /* Contains the Mac modifier formed from quit_char */
9009 static mac_quit_char_modifiers = 0;
9010 static mac_quit_char_keycode;
9011 extern int quit_char;
9012
9013 static void
9014 mac_determine_quit_char_modifiers()
9015 {
9016 /* Todo: Determine modifiers from quit_char. */
9017 UInt32 qc_modifiers = ctrl_modifier;
9018
9019 /* Map modifiers */
9020 mac_quit_char_modifiers = 0;
9021 if (qc_modifiers & ctrl_modifier) mac_quit_char_modifiers |= macCtrlKey;
9022 if (qc_modifiers & shift_modifier) mac_quit_char_modifiers |= macShiftKey;
9023 if (qc_modifiers & meta_modifier) mac_quit_char_modifiers |= macMetaKey;
9024 if (qc_modifiers & alt_modifier) mac_quit_char_modifiers |= macAltKey;
9025 }
9026
9027 static void
9028 init_quit_char_handler ()
9029 {
9030 /* TODO: Let this support keys other the 'g' */
9031 mac_quit_char_keycode = 5;
9032 /* Look at <architecture/adb_kb_map.h> for details */
9033 /* http://gemma.apple.com/techpubs/mac/Toolbox/Toolbox-40.html#MARKER-9-184*/
9034
9035 mac_determine_quit_char_modifiers();
9036 }
9037
9038 static Boolean
9039 quit_char_comp (EventRef inEvent, void *inCompData)
9040 {
9041 if (GetEventClass(inEvent) != kEventClassKeyboard)
9042 return false;
9043 if (GetEventKind(inEvent) != kEventRawKeyDown)
9044 return false;
9045 {
9046 UInt32 keyCode;
9047 UInt32 keyModifiers;
9048 GetEventParameter(inEvent, kEventParamKeyCode,
9049 typeUInt32, NULL, sizeof(UInt32), NULL, &keyCode);
9050 if (keyCode != mac_quit_char_keycode)
9051 return false;
9052 GetEventParameter(inEvent, kEventParamKeyModifiers,
9053 typeUInt32, NULL, sizeof(UInt32), NULL, &keyModifiers);
9054 if (keyModifiers != mac_quit_char_modifiers)
9055 return false;
9056 }
9057 return true;
9058 }
9059
9060 void
9061 mac_check_for_quit_char ()
9062 {
9063 EventRef event;
9064 static EMACS_TIME last_check_time = { 0, 0 };
9065 static EMACS_TIME one_second = { 1, 0 };
9066 EMACS_TIME now, t;
9067
9068 /* If windows are not initialized, return immediately (keep it bouncin'). */
9069 if (!mac_quit_char_modifiers)
9070 return;
9071
9072 /* Don't check if last check is less than a second ago. */
9073 EMACS_GET_TIME (now);
9074 EMACS_SUB_TIME (t, now, last_check_time);
9075 if (EMACS_TIME_LT (t, one_second))
9076 return;
9077 last_check_time = now;
9078
9079 /* Redetermine modifiers because they are based on lisp variables */
9080 mac_determine_quit_char_modifiers ();
9081
9082 /* Fill the queue with events */
9083 BLOCK_INPUT;
9084 ReceiveNextEvent (0, NULL, kEventDurationNoWait, false, &event);
9085 event = FindSpecificEventInQueue (GetMainEventQueue (), quit_char_comp,
9086 NULL);
9087 UNBLOCK_INPUT;
9088 if (event)
9089 {
9090 struct input_event e;
9091
9092 /* Use an input_event to emulate what the interrupt handler does. */
9093 EVENT_INIT (e);
9094 e.kind = ASCII_KEYSTROKE_EVENT;
9095 e.code = quit_char;
9096 e.arg = Qnil;
9097 e.modifiers = NULL;
9098 e.timestamp = EventTimeToTicks (GetEventTime (event)) * (1000/60);
9099 XSETFRAME (e.frame_or_window, mac_window_to_frame (front_emacs_window ()));
9100 /* Remove event from queue to prevent looping. */
9101 RemoveEventFromQueue (GetMainEventQueue (), event);
9102 ReleaseEvent (event);
9103 kbd_buffer_store_event (&e);
9104 }
9105 }
9106
9107 #endif /* MAC_OSX */
9108
9109 /* Set up use of X before we make the first connection. */
9110
9111 extern frame_parm_handler mac_frame_parm_handlers[];
9112
9113 static struct redisplay_interface x_redisplay_interface =
9114 {
9115 mac_frame_parm_handlers,
9116 x_produce_glyphs,
9117 x_write_glyphs,
9118 x_insert_glyphs,
9119 x_clear_end_of_line,
9120 x_scroll_run,
9121 x_after_update_window_line,
9122 x_update_window_begin,
9123 x_update_window_end,
9124 x_cursor_to,
9125 x_flush,
9126 x_flush,
9127 x_clear_window_mouse_face,
9128 x_get_glyph_overhangs,
9129 x_fix_overlapping_area,
9130 x_draw_fringe_bitmap,
9131 0, /* define_fringe_bitmap */
9132 0, /* destroy_fringe_bitmap */
9133 mac_per_char_metric,
9134 mac_encode_char,
9135 NULL, /* mac_compute_glyph_string_overhangs */
9136 x_draw_glyph_string,
9137 mac_define_frame_cursor,
9138 mac_clear_frame_area,
9139 mac_draw_window_cursor,
9140 mac_draw_vertical_window_border,
9141 mac_shift_glyphs_for_insert
9142 };
9143
9144 void
9145 mac_initialize ()
9146 {
9147 rif = &x_redisplay_interface;
9148
9149 clear_frame_hook = x_clear_frame;
9150 ins_del_lines_hook = x_ins_del_lines;
9151 delete_glyphs_hook = x_delete_glyphs;
9152 ring_bell_hook = XTring_bell;
9153 reset_terminal_modes_hook = XTreset_terminal_modes;
9154 set_terminal_modes_hook = XTset_terminal_modes;
9155 update_begin_hook = x_update_begin;
9156 update_end_hook = x_update_end;
9157 set_terminal_window_hook = XTset_terminal_window;
9158 read_socket_hook = XTread_socket;
9159 frame_up_to_date_hook = XTframe_up_to_date;
9160 mouse_position_hook = XTmouse_position;
9161 frame_rehighlight_hook = XTframe_rehighlight;
9162 frame_raise_lower_hook = XTframe_raise_lower;
9163
9164 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar;
9165 condemn_scroll_bars_hook = XTcondemn_scroll_bars;
9166 redeem_scroll_bar_hook = XTredeem_scroll_bar;
9167 judge_scroll_bars_hook = XTjudge_scroll_bars;
9168
9169 scroll_region_ok = 1; /* we'll scroll partial frames */
9170 char_ins_del_ok = 1;
9171 line_ins_del_ok = 1; /* we'll just blt 'em */
9172 fast_clear_end_of_line = 1; /* X does this well */
9173 memory_below_frame = 0; /* we don't remember what scrolls
9174 off the bottom */
9175 baud_rate = 19200;
9176
9177 x_noop_count = 0;
9178 last_tool_bar_item = -1;
9179 any_help_event_p = 0;
9180
9181 /* Try to use interrupt input; if we can't, then start polling. */
9182 Fset_input_mode (Qt, Qnil, Qt, Qnil);
9183
9184 #ifdef USE_X_TOOLKIT
9185 XtToolkitInitialize ();
9186 Xt_app_con = XtCreateApplicationContext ();
9187 XtAppSetFallbackResources (Xt_app_con, Xt_default_resources);
9188
9189 /* Install an asynchronous timer that processes Xt timeout events
9190 every 0.1s. This is necessary because some widget sets use
9191 timeouts internally, for example the LessTif menu bar, or the
9192 Xaw3d scroll bar. When Xt timouts aren't processed, these
9193 widgets don't behave normally. */
9194 {
9195 EMACS_TIME interval;
9196 EMACS_SET_SECS_USECS (interval, 0, 100000);
9197 start_atimer (ATIMER_CONTINUOUS, interval, x_process_timeouts, 0);
9198 }
9199 #endif
9200
9201 #if USE_TOOLKIT_SCROLL_BARS
9202 xaw3d_arrow_scroll = False;
9203 xaw3d_pick_top = True;
9204 #endif
9205
9206 #if 0
9207 /* Note that there is no real way portable across R3/R4 to get the
9208 original error handler. */
9209 XSetErrorHandler (x_error_handler);
9210 XSetIOErrorHandler (x_io_error_quitter);
9211
9212 /* Disable Window Change signals; they are handled by X events. */
9213 #ifdef SIGWINCH
9214 signal (SIGWINCH, SIG_DFL);
9215 #endif /* ! defined (SIGWINCH) */
9216
9217 signal (SIGPIPE, x_connection_signal);
9218 #endif
9219
9220 BLOCK_INPUT;
9221 mac_initialize_display_info ();
9222
9223 #if TARGET_API_MAC_CARBON
9224 init_required_apple_events ();
9225
9226 init_mac_drag_n_drop ();
9227
9228 #if USE_CARBON_EVENTS
9229 init_service_handler ();
9230
9231 init_quit_char_handler ();
9232 #endif
9233
9234 DisableMenuCommand (NULL, kHICommandQuit);
9235
9236 if (!inhibit_window_system)
9237 MakeMeTheFrontProcess ();
9238 #endif
9239 UNBLOCK_INPUT;
9240 }
9241
9242
9243 void
9244 syms_of_macterm ()
9245 {
9246 #if 0
9247 staticpro (&x_error_message_string);
9248 x_error_message_string = Qnil;
9249 #endif
9250
9251 Fprovide (intern ("mac-carbon"), Qnil);
9252
9253 staticpro (&Qreverse);
9254 Qreverse = intern ("reverse");
9255
9256 staticpro (&x_display_name_list);
9257 x_display_name_list = Qnil;
9258
9259 staticpro (&last_mouse_scroll_bar);
9260 last_mouse_scroll_bar = Qnil;
9261
9262 staticpro (&Qvendor_specific_keysyms);
9263 Qvendor_specific_keysyms = intern ("vendor-specific-keysyms");
9264
9265 staticpro (&last_mouse_press_frame);
9266 last_mouse_press_frame = Qnil;
9267
9268 Qmac_ready_for_drag_n_drop = intern ("mac-ready-for-drag-n-drop");
9269 staticpro (&Qmac_ready_for_drag_n_drop);
9270
9271 Qbig5 = intern ("big5");
9272 staticpro (&Qbig5);
9273
9274 Qcn_gb = intern ("cn-gb");
9275 staticpro (&Qcn_gb);
9276
9277 Qsjis = intern ("sjis");
9278 staticpro (&Qsjis);
9279
9280 Qeuc_kr = intern ("euc-kr");
9281 staticpro (&Qeuc_kr);
9282
9283 DEFVAR_BOOL ("x-autoselect-window", &x_autoselect_window_p,
9284 doc: /* *Non-nil means autoselect window with mouse pointer. */);
9285 x_autoselect_window_p = 0;
9286
9287 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
9288 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
9289 Vx_toolkit_scroll_bars = Qt;
9290
9291 DEFVAR_BOOL ("x-use-underline-position-properties",
9292 &x_use_underline_position_properties,
9293 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties.
9294 nil means ignore them. If you encounter fonts with bogus
9295 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
9296 to 4.1, set this to nil. */);
9297 x_use_underline_position_properties = 0;
9298
9299 staticpro (&last_mouse_motion_frame);
9300 last_mouse_motion_frame = Qnil;
9301
9302 DEFVAR_LISP ("mac-command-key-is-meta", &Vmac_command_key_is_meta,
9303 doc: /* Non-nil means that the command key is used as the Emacs meta key.
9304 Otherwise the option key is used. */);
9305 Vmac_command_key_is_meta = Qt;
9306
9307 DEFVAR_LISP ("mac-reverse-ctrl-meta", &Vmac_reverse_ctrl_meta,
9308 doc: /* Non-nil means that the control and meta keys are reversed. This is
9309 useful for non-standard keyboard layouts. */);
9310 Vmac_reverse_ctrl_meta = Qnil;
9311
9312 DEFVAR_LISP ("mac-emulate-three-button-mouse",
9313 &Vmac_emulate_three_button_mouse,
9314 doc: /* t means that when the option-key is held down while pressing the
9315 mouse button, the click will register as mouse-2 and while the
9316 command-key is held down, the click will register as mouse-3.
9317 'reverse means that the the option-key will register for mouse-3
9318 and the command-key will register for mouse-2. nil means that
9319 not emulation should be done and the modifiers should be placed
9320 on the mouse-1 event. */);
9321 Vmac_emulate_three_button_mouse = Qnil;
9322
9323 #if USE_CARBON_EVENTS
9324 DEFVAR_LISP ("mac-wheel-button-is-mouse-2", &Vmac_wheel_button_is_mouse_2,
9325 doc: /* Non-nil means that the wheel button will be treated as mouse-2 and
9326 the right click will be mouse-3.
9327 Otherwise, the right click will be mouse-2 and the wheel button mouse-3.*/);
9328 Vmac_wheel_button_is_mouse_2 = Qt;
9329
9330 DEFVAR_LISP ("mac-pass-command-to-system", &Vmac_pass_command_to_system,
9331 doc: /* If non-nil, the Mac \"Command\" key is passed on to the Mac
9332 Toolbox for processing before Emacs sees it. */);
9333 Vmac_pass_command_to_system = Qt;
9334
9335 DEFVAR_LISP ("mac-pass-control-to-system", &Vmac_pass_control_to_system,
9336 doc: /* If non-nil, the Mac \"Control\" key is passed on to the Mac
9337 Toolbox for processing before Emacs sees it. */);
9338 Vmac_pass_control_to_system = Qt;
9339 #endif
9340
9341 DEFVAR_INT ("mac-keyboard-text-encoding", &mac_keyboard_text_encoding,
9342 doc: /* One of the Text Encoding Base constant values defined in the
9343 Basic Text Constants section of Inside Macintosh - Text Encoding
9344 Conversion Manager. Its value determines the encoding characters
9345 typed at the Mac keyboard (presumed to be in the MacRoman encoding)
9346 will convert into. E.g., if it is set to kTextEncodingMacRoman (0),
9347 its default value, no conversion takes place. If it is set to
9348 kTextEncodingISOLatin1 (0x201) or kTextEncodingISOLatin2 (0x202),
9349 characters typed on Mac keyboard are first converted into the
9350 ISO Latin-1 or ISO Latin-2 encoding, respectively before being
9351 passed to Emacs. Together with Emacs's set-keyboard-coding-system
9352 command, this enables the Mac keyboard to be used to enter non-ASCII
9353 characters directly. */);
9354 mac_keyboard_text_encoding = kTextEncodingMacRoman;
9355 }
9356
9357 /* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b
9358 (do not change this comment) */