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