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