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