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