1/* Implementation of GUI terminal on the Mac OS. 2 Copyright (C) 2000, 2001, 2002, 2003, 2004, 3 2005, 2006, 2007 Free Software Foundation, Inc. 4 5This file is part of GNU Emacs. 6 7GNU Emacs is free software; you can redistribute it and/or modify 8it under the terms of the GNU General Public License as published by 9the Free Software Foundation; either version 2, or (at your option) 10any later version. 11 12GNU Emacs is distributed in the hope that it will be useful, 13but WITHOUT ANY WARRANTY; without even the implied warranty of 14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15GNU General Public License for more details. 16 17You should have received a copy of the GNU General Public License 18along with GNU Emacs; see the file COPYING. If not, write to 19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 20Boston, MA 02110-1301, USA. */ 21 22/* Contributed by Andrew Choi (akochoi@mac.com). */ 23 24#include <config.h> 25#include <signal.h> 26 27#include <stdio.h> 28 29#include "lisp.h" 30#include "blockinput.h" 31 32#include "macterm.h" 33 34#ifndef MAC_OSX 35#include <alloca.h> 36#endif 37 38#if TARGET_API_MAC_CARBON 39/* USE_CARBON_EVENTS determines if the Carbon Event Manager is used to 40 obtain events from the event queue. If set to 0, WaitNextEvent is 41 used instead. */ 42#define USE_CARBON_EVENTS 1 43#else /* not TARGET_API_MAC_CARBON */ 44#include <Quickdraw.h> 45#include <ToolUtils.h> 46#include <Sound.h> 47#include <Events.h> 48#include <Script.h> 49#include <Resources.h> 50#include <Fonts.h> 51#include <TextUtils.h> 52#include <LowMem.h> 53#include <Controls.h> 54#include <Windows.h> 55#include <Displays.h> 56#if defined (__MRC__) || (__MSL__ >= 0x6000) 57#include <ControlDefinitions.h> 58#endif 59 60#if __profile__ 61#include <profiler.h> 62#endif 63#endif /* not TARGET_API_MAC_CARBON */ 64 65#include "systty.h" 66#include "systime.h" 67 68#include <ctype.h> 69#include <errno.h> 70#include <setjmp.h> 71#include <sys/stat.h> 72 73#include "charset.h" 74#include "coding.h" 75#include "frame.h" 76#include "dispextern.h" 77#include "fontset.h" 78#include "termhooks.h" 79#include "termopts.h" 80#include "termchar.h" 81#include "disptab.h" 82#include "buffer.h" 83#include "window.h" 84#include "keyboard.h" 85#include "intervals.h" 86#include "atimer.h" 87#include "keymap.h" 88 89 90 91/* Non-nil means Emacs uses toolkit scroll bars. */ 92 93Lisp_Object Vx_toolkit_scroll_bars; 94 95/* If non-zero, the text will be rendered using Core Graphics text 96 rendering which may anti-alias the text. */ 97int mac_use_core_graphics; 98 99 100/* Non-zero means that a HELP_EVENT has been generated since Emacs 101 start. */ 102 103static int any_help_event_p; 104 105/* Last window where we saw the mouse. Used by mouse-autoselect-window. */ 106static Lisp_Object last_window; 107 108/* Non-zero means make use of UNDERLINE_POSITION font properties. 109 (Not yet supported.) */ 110int x_use_underline_position_properties; 111 112/* Non-zero means to draw the underline at the same place as the descent line. */ 113 114int x_underline_at_descent_line; 115 116/* This is a chain of structures for all the X displays currently in 117 use. */ 118 119struct x_display_info *x_display_list; 120 121/* This is a list of cons cells, each of the form (NAME 122 FONT-LIST-CACHE . RESOURCE-DATABASE), one for each element of 123 x_display_list and in the same order. NAME is the name of the 124 frame. FONT-LIST-CACHE records previous values returned by 125 x-list-fonts. RESOURCE-DATABASE preserves the X Resource Database 126 equivalent, which is implemented with a Lisp object, for the 127 display. */ 128 129Lisp_Object x_display_name_list; 130 131/* This is display since Mac does not support multiple ones. */ 132struct mac_display_info one_mac_display_info; 133 134/* Frame being updated by update_frame. This is declared in term.c. 135 This is set by update_begin and looked at by all the XT functions. 136 It is zero while not inside an update. In that case, the XT 137 functions assume that `selected_frame' is the frame to apply to. */ 138 139extern struct frame *updating_frame; 140 141/* This is a frame waiting to be auto-raised, within XTread_socket. */ 142 143struct frame *pending_autoraise_frame; 144 145/* Mouse movement. 146 147 Formerly, we used PointerMotionHintMask (in standard_event_mask) 148 so that we would have to call XQueryPointer after each MotionNotify 149 event to ask for another such event. However, this made mouse tracking 150 slow, and there was a bug that made it eventually stop. 151 152 Simply asking for MotionNotify all the time seems to work better. 153 154 In order to avoid asking for motion events and then throwing most 155 of them away or busy-polling the server for mouse positions, we ask 156 the server for pointer motion hints. This means that we get only 157 one event per group of mouse movements. "Groups" are delimited by 158 other kinds of events (focus changes and button clicks, for 159 example), or by XQueryPointer calls; when one of these happens, we 160 get another MotionNotify event the next time the mouse moves. This 161 is at least as efficient as getting motion events when mouse 162 tracking is on, and I suspect only negligibly worse when tracking 163 is off. */ 164 165/* Where the mouse was last time we reported a mouse event. */ 166 167static Rect last_mouse_glyph; 168static FRAME_PTR last_mouse_glyph_frame; 169 170/* The scroll bar in which the last X motion event occurred. 171 172 If the last X motion event occurred in a scroll bar, we set this so 173 XTmouse_position can know whether to report a scroll bar motion or 174 an ordinary motion. 175 176 If the last X motion event didn't occur in a scroll bar, we set 177 this to Qnil, to tell XTmouse_position to return an ordinary motion 178 event. */ 179 180static Lisp_Object last_mouse_scroll_bar; 181 182/* This is a hack. We would really prefer that XTmouse_position would 183 return the time associated with the position it returns, but there 184 doesn't seem to be any way to wrest the time-stamp from the server 185 along with the position query. So, we just keep track of the time 186 of the last movement we received, and return that in hopes that 187 it's somewhat accurate. */ 188 189static Time last_mouse_movement_time; 190 191struct scroll_bar *tracked_scroll_bar = NULL; 192 193/* Incremented by XTread_socket whenever it really tries to read 194 events. */ 195 196#ifdef __STDC__ 197static int volatile input_signal_count; 198#else 199static int input_signal_count; 200#endif 201 202extern Lisp_Object Vsystem_name; 203 204extern Lisp_Object Qeql; 205 206/* A mask of extra modifier bits to put into every keyboard char. */ 207 208extern EMACS_INT extra_keyboard_modifiers; 209 210/* The keysyms to use for the various modifiers. */ 211 212static Lisp_Object Qalt, Qhyper, Qsuper, Qcontrol, Qmeta, Qmodifier_value; 213 214extern int inhibit_window_system; 215 216#if __MRC__ && !TARGET_API_MAC_CARBON 217QDGlobals qd; /* QuickDraw global information structure. */ 218#endif 219 220#define mac_window_to_frame(wp) (((mac_output *) GetWRefCon (wp))->mFP) 221 222struct mac_display_info *mac_display_info_for_display (Display *); 223static void x_update_window_end P_ ((struct window *, int, int)); 224int x_catch_errors P_ ((Display *)); 225void x_uncatch_errors P_ ((Display *, int)); 226void x_lower_frame P_ ((struct frame *)); 227void x_scroll_bar_clear P_ ((struct frame *)); 228int x_had_errors_p P_ ((Display *)); 229void x_wm_set_size_hint P_ ((struct frame *, long, int)); 230void x_raise_frame P_ ((struct frame *)); 231void x_set_window_size P_ ((struct frame *, int, int, int)); 232void x_wm_set_window_state P_ ((struct frame *, int)); 233void x_wm_set_icon_pixmap P_ ((struct frame *, int)); 234void mac_initialize P_ ((void)); 235static void x_font_min_bounds P_ ((XFontStruct *, int *, int *)); 236static int x_compute_min_glyph_bounds P_ ((struct frame *)); 237static void x_update_end P_ ((struct frame *)); 238static void XTframe_up_to_date P_ ((struct frame *)); 239static void XTset_terminal_modes P_ ((void)); 240static void XTreset_terminal_modes P_ ((void)); 241static void x_clear_frame P_ ((void)); 242static void frame_highlight P_ ((struct frame *)); 243static void frame_unhighlight P_ ((struct frame *)); 244static void x_new_focus_frame P_ ((struct x_display_info *, struct frame *)); 245static void mac_focus_changed P_ ((int, struct mac_display_info *, 246 struct frame *, struct input_event *)); 247static void x_detect_focus_change P_ ((struct mac_display_info *, 248 const EventRecord *, 249 struct input_event *)); 250static void XTframe_rehighlight P_ ((struct frame *)); 251static void x_frame_rehighlight P_ ((struct x_display_info *)); 252static void x_draw_hollow_cursor P_ ((struct window *, struct glyph_row *)); 253static void x_draw_bar_cursor P_ ((struct window *, struct glyph_row *, int, 254 enum text_cursor_kinds)); 255 256static void x_clip_to_row P_ ((struct window *, struct glyph_row *, int, GC)); 257static void x_flush P_ ((struct frame *f)); 258static void x_update_begin P_ ((struct frame *)); 259static void x_update_window_begin P_ ((struct window *)); 260static void x_after_update_window_line P_ ((struct glyph_row *)); 261static void x_scroll_bar_report_motion P_ ((struct frame **, Lisp_Object *, 262 enum scroll_bar_part *, 263 Lisp_Object *, Lisp_Object *, 264 unsigned long *)); 265 266static int is_emacs_window P_ ((WindowPtr)); 267static XCharStruct *mac_per_char_metric P_ ((XFontStruct *, XChar2b *, int)); 268static void XSetFont P_ ((Display *, GC, XFontStruct *)); 269 270#define GC_FORE_COLOR(gc) (&(gc)->fore_color) 271#define GC_BACK_COLOR(gc) (&(gc)->back_color) 272#define GC_FONT(gc) ((gc)->xgcv.font) 273#define FRAME_NORMAL_GC(f) ((f)->output_data.mac->normal_gc) 274 275#define CG_SET_FILL_COLOR(context, color) \ 276 CGContextSetRGBFillColor (context, \ 277 RED_FROM_ULONG (color) / 255.0f, \ 278 GREEN_FROM_ULONG (color) / 255.0f, \ 279 BLUE_FROM_ULONG (color) / 255.0f, 1.0f) 280#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 281#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020 282#define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \ 283 do { \ 284 if (CGColorGetTypeID != NULL) \ 285 CGContextSetFillColorWithColor (context, cg_color); \ 286 else \ 287 CG_SET_FILL_COLOR (context, color); \ 288 } while (0) 289#else 290#define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \ 291 CGContextSetFillColorWithColor (context, cg_color) 292#endif 293#else 294#define CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \ 295 CG_SET_FILL_COLOR (context, color) 296#endif 297#define CG_SET_FILL_COLOR_WITH_GC_FOREGROUND(context, gc) \ 298 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \ 299 (gc)->cg_fore_color) 300#define CG_SET_FILL_COLOR_WITH_GC_BACKGROUND(context, gc) \ 301 CG_SET_FILL_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.background, \ 302 (gc)->cg_back_color) 303 304 305#define CG_SET_STROKE_COLOR(context, color) \ 306 CGContextSetRGBStrokeColor (context, \ 307 RED_FROM_ULONG (color) / 255.0f, \ 308 GREEN_FROM_ULONG (color) / 255.0f, \ 309 BLUE_FROM_ULONG (color) / 255.0f, 1.0f) 310#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 311#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020 312#define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \ 313 do { \ 314 if (CGColorGetTypeID != NULL) \ 315 CGContextSetStrokeColorWithColor (context, cg_color); \ 316 else \ 317 CG_SET_STROKE_COLOR (context, color); \ 318 } while (0) 319#else 320#define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \ 321 CGContextSetStrokeColorWithColor (context, cg_color) 322#endif 323#else 324#define CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR(context, color, cg_color) \ 325 CG_SET_STROKE_COLOR (context, color) 326#endif 327#define CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND(context, gc) \ 328 CG_SET_STROKE_COLOR_MAYBE_WITH_CGCOLOR (context, (gc)->xgcv.foreground, \ 329 (gc)->cg_fore_color) 330 331#if USE_CG_DRAWING 332#define FRAME_CG_CONTEXT(f) ((f)->output_data.mac->cg_context) 333 334/* Fringe bitmaps. */ 335 336static int max_fringe_bmp = 0; 337static CGImageRef *fringe_bmp = 0; 338 339static CGColorSpaceRef mac_cg_color_space_rgb; 340#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 341static CGColorRef mac_cg_color_black; 342#endif 343 344static void 345init_cg_color () 346{ 347 mac_cg_color_space_rgb = CGColorSpaceCreateDeviceRGB (); 348#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 349#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020 350 /* Don't check the availability of CGColorCreate; this symbol is 351 defined even in Mac OS X 10.1. */ 352 if (CGColorGetTypeID != NULL) 353#endif 354 { 355 float rgba[] = {0.0f, 0.0f, 0.0f, 1.0f}; 356 357 mac_cg_color_black = CGColorCreate (mac_cg_color_space_rgb, rgba); 358 } 359#endif 360} 361 362static CGContextRef 363mac_begin_cg_clip (f, gc) 364 struct frame *f; 365 GC gc; 366{ 367 CGContextRef context = FRAME_CG_CONTEXT (f); 368 369 if (!context) 370 { 371 QDBeginCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), &context); 372 FRAME_CG_CONTEXT (f) = context; 373 } 374 375 CGContextSaveGState (context); 376 CGContextTranslateCTM (context, 0, FRAME_PIXEL_HEIGHT (f)); 377 CGContextScaleCTM (context, 1, -1); 378 if (gc && gc->n_clip_rects) 379 CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects); 380 381 return context; 382} 383 384static void 385mac_end_cg_clip (f) 386 struct frame *f; 387{ 388 CGContextRestoreGState (FRAME_CG_CONTEXT (f)); 389} 390 391void 392mac_prepare_for_quickdraw (f) 393 struct frame *f; 394{ 395 if (f == NULL) 396 { 397 Lisp_Object rest, frame; 398 FOR_EACH_FRAME (rest, frame) 399 if (FRAME_MAC_P (XFRAME (frame))) 400 mac_prepare_for_quickdraw (XFRAME (frame)); 401 } 402 else 403 { 404 CGContextRef context = FRAME_CG_CONTEXT (f); 405 406 if (context) 407 { 408 CGContextSynchronize (context); 409 QDEndCGContext (GetWindowPort (FRAME_MAC_WINDOW (f)), 410 &FRAME_CG_CONTEXT (f)); 411 } 412 } 413} 414#endif 415 416static RgnHandle saved_port_clip_region = NULL; 417 418static void 419mac_begin_clip (gc) 420 GC gc; 421{ 422 static RgnHandle new_region = NULL; 423 424 if (saved_port_clip_region == NULL) 425 saved_port_clip_region = NewRgn (); 426 if (new_region == NULL) 427 new_region = NewRgn (); 428 429 if (gc->n_clip_rects) 430 { 431 GetClip (saved_port_clip_region); 432 SectRgn (saved_port_clip_region, gc->clip_region, new_region); 433 SetClip (new_region); 434 } 435} 436 437static void 438mac_end_clip (gc) 439 GC gc; 440{ 441 if (gc->n_clip_rects) 442 SetClip (saved_port_clip_region); 443} 444 445 446/* X display function emulation */ 447 448void 449XFreePixmap (display, pixmap) 450 Display *display; /* not used */ 451 Pixmap pixmap; 452{ 453 DisposeGWorld (pixmap); 454} 455 456 457/* Mac version of XDrawLine. */ 458 459static void 460mac_draw_line (f, gc, x1, y1, x2, y2) 461 struct frame *f; 462 GC gc; 463 int x1, y1, x2, y2; 464{ 465#if USE_CG_DRAWING 466 CGContextRef context; 467 float gx1 = x1, gy1 = y1, gx2 = x2, gy2 = y2; 468 469 if (y1 != y2) 470 gx1 += 0.5f, gx2 += 0.5f; 471 if (x1 != x2) 472 gy1 += 0.5f, gy2 += 0.5f; 473 474 context = mac_begin_cg_clip (f, gc); 475 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc); 476 CGContextBeginPath (context); 477 CGContextMoveToPoint (context, gx1, gy1); 478 CGContextAddLineToPoint (context, gx2, gy2); 479 CGContextClosePath (context); 480 CGContextStrokePath (context); 481 mac_end_cg_clip (f); 482#else 483 if (x1 == x2) 484 { 485 if (y1 > y2) 486 y1--; 487 else if (y2 > y1) 488 y2--; 489 } 490 else if (y1 == y2) 491 { 492 if (x1 > x2) 493 x1--; 494 else 495 x2--; 496 } 497 498 SetPortWindowPort (FRAME_MAC_WINDOW (f)); 499 500 RGBForeColor (GC_FORE_COLOR (gc)); 501 502 mac_begin_clip (gc); 503 MoveTo (x1, y1); 504 LineTo (x2, y2); 505 mac_end_clip (gc); 506#endif 507} 508 509/* Mac version of XDrawLine (to Pixmap). */ 510 511void 512XDrawLine (display, p, gc, x1, y1, x2, y2) 513 Display *display; 514 Pixmap p; 515 GC gc; 516 int x1, y1, x2, y2; 517{ 518 CGrafPtr old_port; 519 GDHandle old_gdh; 520 521 if (x1 == x2) 522 { 523 if (y1 > y2) 524 y1--; 525 else if (y2 > y1) 526 y2--; 527 } 528 else if (y1 == y2) 529 { 530 if (x1 > x2) 531 x1--; 532 else 533 x2--; 534 } 535 536 GetGWorld (&old_port, &old_gdh); 537 SetGWorld (p, NULL); 538 539 RGBForeColor (GC_FORE_COLOR (gc)); 540 541 LockPixels (GetGWorldPixMap (p)); 542 MoveTo (x1, y1); 543 LineTo (x2, y2); 544 UnlockPixels (GetGWorldPixMap (p)); 545 546 SetGWorld (old_port, old_gdh); 547} 548 549 550static void 551mac_erase_rectangle (f, gc, x, y, width, height) 552 struct frame *f; 553 GC gc; 554 int x, y; 555 unsigned int width, height; 556{ 557#if USE_CG_DRAWING 558 CGContextRef context; 559 560 context = mac_begin_cg_clip (f, gc); 561 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc); 562 CGContextFillRect (context, CGRectMake (x, y, width, height)); 563 mac_end_cg_clip (f); 564#else 565 Rect r; 566 567 SetPortWindowPort (FRAME_MAC_WINDOW (f)); 568 569 RGBBackColor (GC_BACK_COLOR (gc)); 570 SetRect (&r, x, y, x + width, y + height); 571 572 mac_begin_clip (gc); 573 EraseRect (&r); 574 mac_end_clip (gc); 575 576 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f))); 577#endif 578} 579 580 581/* Mac version of XClearArea. */ 582 583void 584mac_clear_area (f, x, y, width, height) 585 struct frame *f; 586 int x, y; 587 unsigned int width, height; 588{ 589 mac_erase_rectangle (f, FRAME_NORMAL_GC (f), x, y, width, height); 590} 591 592/* Mac version of XClearWindow. */ 593 594static void 595mac_clear_window (f) 596 struct frame *f; 597{ 598#if USE_CG_DRAWING 599 CGContextRef context; 600 GC gc = FRAME_NORMAL_GC (f); 601 602 context = mac_begin_cg_clip (f, NULL); 603 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc); 604 CGContextFillRect (context, CGRectMake (0, 0, FRAME_PIXEL_WIDTH (f), 605 FRAME_PIXEL_HEIGHT (f))); 606 mac_end_cg_clip (f); 607#else 608 SetPortWindowPort (FRAME_MAC_WINDOW (f)); 609 610 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f))); 611 612#if TARGET_API_MAC_CARBON 613 { 614 Rect r; 615 616 GetWindowPortBounds (FRAME_MAC_WINDOW (f), &r); 617 EraseRect (&r); 618 } 619#else /* not TARGET_API_MAC_CARBON */ 620 EraseRect (&(FRAME_MAC_WINDOW (f)->portRect)); 621#endif /* not TARGET_API_MAC_CARBON */ 622#endif 623} 624 625 626/* Mac replacement for XCopyArea. */ 627 628#if USE_CG_DRAWING 629static void 630mac_draw_cg_image (image, f, gc, src_x, src_y, width, height, 631 dest_x, dest_y, overlay_p) 632 CGImageRef image; 633 struct frame *f; 634 GC gc; 635 int src_x, src_y; 636 unsigned int width, height; 637 int dest_x, dest_y, overlay_p; 638{ 639 CGContextRef context; 640 float port_height = FRAME_PIXEL_HEIGHT (f); 641 CGRect dest_rect = CGRectMake (dest_x, dest_y, width, height); 642 643 context = mac_begin_cg_clip (f, gc); 644 if (!overlay_p) 645 { 646 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc); 647 CGContextFillRect (context, dest_rect); 648 } 649 CGContextClipToRect (context, dest_rect); 650 CGContextScaleCTM (context, 1, -1); 651 CGContextTranslateCTM (context, 0, -port_height); 652 if (CGImageIsMask (image)) 653 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc); 654 CGContextDrawImage (context, 655 CGRectMake (dest_x - src_x, 656 port_height - (dest_y - src_y 657 + CGImageGetHeight (image)), 658 CGImageGetWidth (image), 659 CGImageGetHeight (image)), 660 image); 661 mac_end_cg_clip (f); 662} 663 664#else /* !USE_CG_DRAWING */ 665 666static void 667mac_draw_bitmap (f, gc, x, y, width, height, bits, overlay_p) 668 struct frame *f; 669 GC gc; 670 int x, y, width, height; 671 unsigned short *bits; 672 int overlay_p; 673{ 674 BitMap bitmap; 675 Rect r; 676 677 bitmap.rowBytes = sizeof(unsigned short); 678 bitmap.baseAddr = (char *)bits; 679 SetRect (&(bitmap.bounds), 0, 0, width, height); 680 681 SetPortWindowPort (FRAME_MAC_WINDOW (f)); 682 683 RGBForeColor (GC_FORE_COLOR (gc)); 684 RGBBackColor (GC_BACK_COLOR (gc)); 685 SetRect (&r, x, y, x + width, y + height); 686 687 mac_begin_clip (gc); 688#if TARGET_API_MAC_CARBON 689 { 690 CGrafPtr port; 691 692 GetPort (&port); 693 LockPortBits (port); 694 CopyBits (&bitmap, GetPortBitMapForCopyBits (port), 695 &(bitmap.bounds), &r, overlay_p ? srcOr : srcCopy, 0); 696 UnlockPortBits (port); 697 } 698#else /* not TARGET_API_MAC_CARBON */ 699 CopyBits (&bitmap, &(FRAME_MAC_WINDOW (f)->portBits), &(bitmap.bounds), &r, 700 overlay_p ? srcOr : srcCopy, 0); 701#endif /* not TARGET_API_MAC_CARBON */ 702 mac_end_clip (gc); 703 704 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f))); 705} 706#endif /* !USE_CG_DRAWING */ 707 708 709/* Mac replacement for XCreateBitmapFromBitmapData. */ 710 711static void 712mac_create_bitmap_from_bitmap_data (bitmap, bits, w, h) 713 BitMap *bitmap; 714 char *bits; 715 int w, h; 716{ 717 static const unsigned char swap_nibble[16] 718 = { 0x0, 0x8, 0x4, 0xc, /* 0000 1000 0100 1100 */ 719 0x2, 0xa, 0x6, 0xe, /* 0010 1010 0110 1110 */ 720 0x1, 0x9, 0x5, 0xd, /* 0001 1001 0101 1101 */ 721 0x3, 0xb, 0x7, 0xf }; /* 0011 1011 0111 1111 */ 722 int i, j, w1; 723 char *p; 724 725 w1 = (w + 7) / 8; /* nb of 8bits elt in X bitmap */ 726 bitmap->rowBytes = ((w + 15) / 16) * 2; /* nb of 16bits elt in Mac bitmap */ 727 bitmap->baseAddr = xmalloc (bitmap->rowBytes * h); 728 bzero (bitmap->baseAddr, bitmap->rowBytes * h); 729 for (i = 0; i < h; i++) 730 { 731 p = bitmap->baseAddr + i * bitmap->rowBytes; 732 for (j = 0; j < w1; j++) 733 { 734 /* Bitswap XBM bytes to match how Mac does things. */ 735 unsigned char c = *bits++; 736 *p++ = (unsigned char)((swap_nibble[c & 0xf] << 4) 737 | (swap_nibble[(c>>4) & 0xf]));; 738 } 739 } 740 741 SetRect (&(bitmap->bounds), 0, 0, w, h); 742} 743 744 745static void 746mac_free_bitmap (bitmap) 747 BitMap *bitmap; 748{ 749 xfree (bitmap->baseAddr); 750} 751 752 753Pixmap 754XCreatePixmap (display, w, width, height, depth) 755 Display *display; /* not used */ 756 WindowPtr w; 757 unsigned int width, height; 758 unsigned int depth; 759{ 760 Pixmap pixmap; 761 Rect r; 762 QDErr err; 763 764 SetPortWindowPort (w); 765 766 SetRect (&r, 0, 0, width, height); 767#if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING 768 if (depth == 1) 769#endif 770 err = NewGWorld (&pixmap, depth, &r, NULL, NULL, 0); 771#if !defined (WORDS_BIG_ENDIAN) && USE_CG_DRAWING 772 else 773 /* CreateCGImageFromPixMaps requires ARGB format. */ 774 err = QTNewGWorld (&pixmap, k32ARGBPixelFormat, &r, NULL, NULL, 0); 775#endif 776 if (err != noErr) 777 return NULL; 778 return pixmap; 779} 780 781 782Pixmap 783XCreatePixmapFromBitmapData (display, w, data, width, height, fg, bg, depth) 784 Display *display; /* not used */ 785 WindowPtr w; 786 char *data; 787 unsigned int width, height; 788 unsigned long fg, bg; 789 unsigned int depth; 790{ 791 Pixmap pixmap; 792 BitMap bitmap; 793 CGrafPtr old_port; 794 GDHandle old_gdh; 795 static GC gc = NULL; /* not reentrant */ 796 797 if (gc == NULL) 798 gc = XCreateGC (display, w, 0, NULL); 799 800 pixmap = XCreatePixmap (display, w, width, height, depth); 801 if (pixmap == NULL) 802 return NULL; 803 804 GetGWorld (&old_port, &old_gdh); 805 SetGWorld (pixmap, NULL); 806 mac_create_bitmap_from_bitmap_data (&bitmap, data, width, height); 807 XSetForeground (display, gc, fg); 808 XSetBackground (display, gc, bg); 809 RGBForeColor (GC_FORE_COLOR (gc)); 810 RGBBackColor (GC_BACK_COLOR (gc)); 811 LockPixels (GetGWorldPixMap (pixmap)); 812#if TARGET_API_MAC_CARBON 813 CopyBits (&bitmap, GetPortBitMapForCopyBits (pixmap), 814 &bitmap.bounds, &bitmap.bounds, srcCopy, 0); 815#else /* not TARGET_API_MAC_CARBON */ 816 CopyBits (&bitmap, &(((GrafPtr)pixmap)->portBits), 817 &bitmap.bounds, &bitmap.bounds, srcCopy, 0); 818#endif /* not TARGET_API_MAC_CARBON */ 819 UnlockPixels (GetGWorldPixMap (pixmap)); 820 SetGWorld (old_port, old_gdh); 821 mac_free_bitmap (&bitmap); 822 823 return pixmap; 824} 825 826 827/* Mac replacement for XFillRectangle. */ 828 829static void 830mac_fill_rectangle (f, gc, x, y, width, height) 831 struct frame *f; 832 GC gc; 833 int x, y; 834 unsigned int width, height; 835{ 836#if USE_CG_DRAWING 837 CGContextRef context; 838 839 context = mac_begin_cg_clip (f, gc); 840 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc); 841 CGContextFillRect (context, CGRectMake (x, y, width, height)); 842 mac_end_cg_clip (f); 843#else 844 Rect r; 845 846 SetPortWindowPort (FRAME_MAC_WINDOW (f)); 847 848 RGBForeColor (GC_FORE_COLOR (gc)); 849 SetRect (&r, x, y, x + width, y + height); 850 851 mac_begin_clip (gc); 852 PaintRect (&r); /* using foreground color of gc */ 853 mac_end_clip (gc); 854#endif 855} 856 857 858/* Mac replacement for XDrawRectangle: dest is a window. */ 859 860static void 861mac_draw_rectangle (f, gc, x, y, width, height) 862 struct frame *f; 863 GC gc; 864 int x, y; 865 unsigned int width, height; 866{ 867#if USE_CG_DRAWING 868 CGContextRef context; 869 870 context = mac_begin_cg_clip (f, gc); 871 CG_SET_STROKE_COLOR_WITH_GC_FOREGROUND (context, gc); 872 CGContextStrokeRect (context, 873 CGRectMake (x + 0.5f, y + 0.5f, width, height)); 874 mac_end_cg_clip (f); 875#else 876 Rect r; 877 878 SetPortWindowPort (FRAME_MAC_WINDOW (f)); 879 880 RGBForeColor (GC_FORE_COLOR (gc)); 881 SetRect (&r, x, y, x + width + 1, y + height + 1); 882 883 mac_begin_clip (gc); 884 FrameRect (&r); /* using foreground color of gc */ 885 mac_end_clip (gc); 886#endif 887} 888 889 890#if USE_ATSUI 891static OSStatus 892atsu_get_text_layout_with_text_ptr (text, text_length, style, text_layout) 893 ConstUniCharArrayPtr text; 894 UniCharCount text_length; 895 ATSUStyle style; 896 ATSUTextLayout *text_layout; 897{ 898 OSStatus err; 899 static ATSUTextLayout saved_text_layout = NULL; /* not reentrant */ 900 901 if (saved_text_layout == NULL) 902 { 903 static const UniCharCount lengths[] = {kATSUToTextEnd}; 904 static const ATSUAttributeTag tags[] = {kATSULineLayoutOptionsTag}; 905 static const ByteCount sizes[] = {sizeof (ATSLineLayoutOptions)}; 906 static ATSLineLayoutOptions line_layout = 907#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 908 kATSLineDisableAllLayoutOperations | kATSLineUseDeviceMetrics 909 | kATSLineUseQDRendering 910#else 911 kATSLineIsDisplayOnly | kATSLineFractDisable 912#endif 913 ; 914 static const ATSUAttributeValuePtr values[] = {&line_layout}; 915 916 err = ATSUCreateTextLayoutWithTextPtr (text, 917 kATSUFromTextBeginning, 918 kATSUToTextEnd, 919 text_length, 920 1, lengths, &style, 921 &saved_text_layout); 922 if (err == noErr) 923 err = ATSUSetLayoutControls (saved_text_layout, 924 sizeof (tags) / sizeof (tags[0]), 925 tags, sizes, values); 926 /* XXX: Should we do this? */ 927 if (err == noErr) 928 err = ATSUSetTransientFontMatching (saved_text_layout, true); 929 } 930 else 931 { 932 err = ATSUSetRunStyle (saved_text_layout, style, 933 kATSUFromTextBeginning, kATSUToTextEnd); 934 if (err == noErr) 935 err = ATSUSetTextPointerLocation (saved_text_layout, text, 936 kATSUFromTextBeginning, 937 kATSUToTextEnd, 938 text_length); 939 } 940 941 if (err == noErr) 942 *text_layout = saved_text_layout; 943 return err; 944} 945#endif 946 947 948static void 949mac_invert_rectangle (f, x, y, width, height) 950 struct frame *f; 951 int x, y; 952 unsigned int width, height; 953{ 954 Rect r; 955 956#if USE_CG_DRAWING 957 mac_prepare_for_quickdraw (f); 958#endif 959 SetPortWindowPort (FRAME_MAC_WINDOW (f)); 960 961 SetRect (&r, x, y, x + width, y + height); 962 963 InvertRect (&r); 964} 965 966 967static void 968mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width, 969 overstrike_p, bytes_per_char) 970 struct frame *f; 971 GC gc; 972 int x, y; 973 char *buf; 974 int nchars, bg_width, overstrike_p, bytes_per_char; 975{ 976 SetPortWindowPort (FRAME_MAC_WINDOW (f)); 977 978#if USE_ATSUI 979 if (GC_FONT (gc)->mac_style) 980 { 981 OSStatus err; 982 ATSUTextLayout text_layout; 983 984 xassert (bytes_per_char == 2); 985 986#ifndef WORDS_BIG_ENDIAN 987 { 988 int i; 989 UniChar *text = (UniChar *)buf; 990 991 for (i = 0; i < nchars; i++) 992 text[i] = EndianU16_BtoN (text[i]); 993 } 994#endif 995 err = atsu_get_text_layout_with_text_ptr ((ConstUniCharArrayPtr)buf, 996 nchars, 997 GC_FONT (gc)->mac_style, 998 &text_layout); 999 if (err != noErr) 1000 return; 1001#ifdef MAC_OSX 1002 if (!mac_use_core_graphics) 1003 { 1004#endif 1005#if USE_CG_DRAWING 1006 mac_prepare_for_quickdraw (f); 1007#endif 1008 mac_begin_clip (gc); 1009 RGBForeColor (GC_FORE_COLOR (gc)); 1010 if (bg_width) 1011 { 1012 Rect r; 1013 1014 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)), 1015 x + bg_width, y + FONT_DESCENT (GC_FONT (gc))); 1016 RGBBackColor (GC_BACK_COLOR (gc)); 1017 EraseRect (&r); 1018 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f))); 1019 } 1020 MoveTo (x, y); 1021 ATSUDrawText (text_layout, 1022 kATSUFromTextBeginning, kATSUToTextEnd, 1023 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc); 1024 if (overstrike_p) 1025 { 1026 MoveTo (x + 1, y); 1027 ATSUDrawText (text_layout, 1028 kATSUFromTextBeginning, kATSUToTextEnd, 1029 kATSUUseGrafPortPenLoc, kATSUUseGrafPortPenLoc); 1030 } 1031 mac_end_clip (gc); 1032#ifdef MAC_OSX 1033 } 1034 else 1035 { 1036 CGrafPtr port; 1037 static CGContextRef context; 1038 float port_height = FRAME_PIXEL_HEIGHT (f); 1039 static const ATSUAttributeTag tags[] = {kATSUCGContextTag}; 1040 static const ByteCount sizes[] = {sizeof (CGContextRef)}; 1041 static const ATSUAttributeValuePtr values[] = {&context}; 1042 1043#if USE_CG_DRAWING 1044 context = mac_begin_cg_clip (f, gc); 1045#else 1046 GetPort (&port); 1047 QDBeginCGContext (port, &context); 1048 if (gc->n_clip_rects || bg_width) 1049 { 1050 CGContextTranslateCTM (context, 0, port_height); 1051 CGContextScaleCTM (context, 1, -1); 1052 if (gc->n_clip_rects) 1053 CGContextClipToRects (context, gc->clip_rects, 1054 gc->n_clip_rects); 1055#endif 1056 if (bg_width) 1057 { 1058 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc); 1059 CGContextFillRect 1060 (context, 1061 CGRectMake (x, y - FONT_BASE (GC_FONT (gc)), 1062 bg_width, FONT_HEIGHT (GC_FONT (gc)))); 1063 } 1064 CGContextScaleCTM (context, 1, -1); 1065 CGContextTranslateCTM (context, 0, -port_height); 1066#if !USE_CG_DRAWING 1067 } 1068#endif 1069 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc); 1070 err = ATSUSetLayoutControls (text_layout, 1071 sizeof (tags) / sizeof (tags[0]), 1072 tags, sizes, values); 1073 if (err == noErr) 1074 { 1075 ATSUDrawText (text_layout, 1076 kATSUFromTextBeginning, kATSUToTextEnd, 1077 Long2Fix (x), Long2Fix (port_height - y)); 1078 if (overstrike_p) 1079 ATSUDrawText (text_layout, 1080 kATSUFromTextBeginning, kATSUToTextEnd, 1081 Long2Fix (x + 1), Long2Fix (port_height - y)); 1082 } 1083#if USE_CG_DRAWING 1084 mac_end_cg_clip (f); 1085 context = NULL; 1086#else 1087 CGContextSynchronize (context); 1088 QDEndCGContext (port, &context); 1089#endif 1090#if 0 1091 /* This doesn't work on Mac OS X 10.1. */ 1092 ATSUClearLayoutControls (text_layout, 1093 sizeof (tags) / sizeof (tags[0]), tags); 1094#else 1095 ATSUSetLayoutControls (text_layout, 1096 sizeof (tags) / sizeof (tags[0]), 1097 tags, sizes, values); 1098#endif 1099 } 1100#endif /* MAC_OSX */ 1101 } 1102 else 1103#endif /* USE_ATSUI */ 1104 { 1105#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 1106 UInt32 savedFlags; 1107 1108 if (mac_use_core_graphics) 1109 savedFlags = SwapQDTextFlags (kQDUseCGTextRendering); 1110#endif 1111#if USE_CG_DRAWING 1112 mac_prepare_for_quickdraw (f); 1113#endif 1114 mac_begin_clip (gc); 1115 RGBForeColor (GC_FORE_COLOR (gc)); 1116#ifdef MAC_OS8 1117 if (bg_width) 1118 { 1119 RGBBackColor (GC_BACK_COLOR (gc)); 1120 TextMode (srcCopy); 1121 } 1122 else 1123 TextMode (srcOr); 1124#else 1125 /* We prefer not to use srcCopy text transfer mode on Mac OS X 1126 because: 1127 - Screen is double-buffered. (In srcCopy mode, a text is 1128 drawn into an offscreen graphics world first. So 1129 performance gain cannot be expected.) 1130 - It lowers rendering quality. 1131 - Some fonts leave garbage on cursor movement. */ 1132 if (bg_width) 1133 { 1134 Rect r; 1135 1136 RGBBackColor (GC_BACK_COLOR (gc)); 1137 SetRect (&r, x, y - FONT_BASE (GC_FONT (gc)), 1138 x + bg_width, y + FONT_DESCENT (GC_FONT (gc))); 1139 EraseRect (&r); 1140 } 1141 TextMode (srcOr); 1142#endif 1143 TextFont (GC_FONT (gc)->mac_fontnum); 1144 TextSize (GC_FONT (gc)->mac_fontsize); 1145 TextFace (GC_FONT (gc)->mac_fontface); 1146 MoveTo (x, y); 1147 DrawText (buf, 0, nchars * bytes_per_char); 1148 if (overstrike_p) 1149 { 1150 TextMode (srcOr); 1151 MoveTo (x + 1, y); 1152 DrawText (buf, 0, nchars * bytes_per_char); 1153 } 1154 if (bg_width) 1155 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f))); 1156 mac_end_clip (gc); 1157 1158#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 1159 if (mac_use_core_graphics) 1160 SwapQDTextFlags(savedFlags); 1161#endif 1162 } 1163} 1164 1165 1166/* Mac replacement for XDrawImageString. */ 1167 1168static void 1169mac_draw_image_string (f, gc, x, y, buf, nchars, bg_width, overstrike_p) 1170 struct frame *f; 1171 GC gc; 1172 int x, y; 1173 char *buf; 1174 int nchars, bg_width, overstrike_p; 1175{ 1176 mac_draw_string_common (f, gc, x, y, buf, nchars, bg_width, 1177 overstrike_p, 1); 1178} 1179 1180 1181/* Mac replacement for XDrawImageString16. */ 1182 1183static void 1184mac_draw_image_string_16 (f, gc, x, y, buf, nchars, bg_width, overstrike_p) 1185 struct frame *f; 1186 GC gc; 1187 int x, y; 1188 XChar2b *buf; 1189 int nchars, bg_width, overstrike_p; 1190{ 1191 mac_draw_string_common (f, gc, x, y, (char *) buf, nchars, bg_width, 1192 overstrike_p, 2); 1193} 1194 1195 1196/* Mac replacement for XQueryTextExtents, but takes a character. If 1197 STYLE is NULL, measurement is done by QuickDraw Text routines for 1198 the font of the current graphics port. If CG_GLYPH is not NULL, 1199 *CG_GLYPH is set to the glyph ID or 0 if it cannot be obtained. */ 1200 1201static OSStatus 1202mac_query_char_extents (style, c, 1203 font_ascent_return, font_descent_return, 1204 overall_return, cg_glyph) 1205#if USE_ATSUI 1206 ATSUStyle style; 1207#else 1208 void *style; 1209#endif 1210 int c; 1211 int *font_ascent_return, *font_descent_return; 1212 XCharStruct *overall_return; 1213#if USE_CG_TEXT_DRAWING 1214 CGGlyph *cg_glyph; 1215#else 1216 void *cg_glyph; 1217#endif 1218{ 1219 OSStatus err = noErr; 1220 int width; 1221 Rect char_bounds; 1222 1223#if USE_ATSUI 1224 if (style) 1225 { 1226 ATSUTextLayout text_layout; 1227 UniChar ch = c; 1228 1229 err = atsu_get_text_layout_with_text_ptr (&ch, 1, style, &text_layout); 1230 if (err == noErr 1231 && (font_ascent_return || font_descent_return || overall_return)) 1232 { 1233 ATSTrapezoid glyph_bounds; 1234 1235 err = ATSUGetGlyphBounds (text_layout, 0, 0, 1236 kATSUFromTextBeginning, kATSUToTextEnd, 1237#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 1238 kATSUseFractionalOrigins, 1239#else 1240 kATSUseDeviceOrigins, 1241#endif 1242 1, &glyph_bounds, NULL); 1243 if (err == noErr) 1244 { 1245 xassert (glyph_bounds.lowerRight.x - glyph_bounds.lowerLeft.x 1246 == glyph_bounds.upperRight.x - glyph_bounds.upperLeft.x); 1247 1248 width = Fix2Long (glyph_bounds.upperRight.x 1249 - glyph_bounds.upperLeft.x); 1250 if (font_ascent_return) 1251 *font_ascent_return = -Fix2Long (glyph_bounds.upperLeft.y); 1252 if (font_descent_return) 1253 *font_descent_return = Fix2Long (glyph_bounds.lowerLeft.y); 1254 } 1255 } 1256 if (err == noErr && overall_return) 1257 { 1258 err = ATSUMeasureTextImage (text_layout, 1259 kATSUFromTextBeginning, kATSUToTextEnd, 1260 0, 0, &char_bounds); 1261 if (err == noErr) 1262 STORE_XCHARSTRUCT (*overall_return, width, char_bounds); 1263#if USE_CG_TEXT_DRAWING 1264 if (err == noErr && cg_glyph) 1265 { 1266 OSStatus err1; 1267 ATSUGlyphInfoArray glyph_info_array; 1268 ByteCount count = sizeof (ATSUGlyphInfoArray); 1269 1270 err1 = ATSUMatchFontsToText (text_layout, kATSUFromTextBeginning, 1271 kATSUToTextEnd, NULL, NULL, NULL); 1272 if (err1 == noErr) 1273 err1 = ATSUGetGlyphInfo (text_layout, kATSUFromTextBeginning, 1274 kATSUToTextEnd, &count, 1275 &glyph_info_array); 1276 if (err1 == noErr 1277 /* Make sure that we don't have to make layout 1278 adjustments. */ 1279 && glyph_info_array.glyphs[0].deltaY == 0.0f 1280 && glyph_info_array.glyphs[0].idealX == 0.0f 1281 && glyph_info_array.glyphs[0].screenX == 0) 1282 { 1283 xassert (glyph_info_array.glyphs[0].glyphID); 1284 *cg_glyph = glyph_info_array.glyphs[0].glyphID; 1285 } 1286 else 1287 *cg_glyph = 0; 1288 } 1289#endif 1290 } 1291 } 1292 else 1293#endif 1294 { 1295 if (font_ascent_return || font_descent_return) 1296 { 1297 FontInfo font_info; 1298 1299 GetFontInfo (&font_info); 1300 if (font_ascent_return) 1301 *font_ascent_return = font_info.ascent; 1302 if (font_descent_return) 1303 *font_descent_return = font_info.descent; 1304 } 1305 if (overall_return) 1306 { 1307 char ch = c; 1308 1309 width = CharWidth (ch); 1310 QDTextBounds (1, &ch, &char_bounds); 1311 STORE_XCHARSTRUCT (*overall_return, width, char_bounds); 1312 } 1313 } 1314 1315 return err; 1316} 1317 1318 1319/* Mac replacement for XTextExtents16. Only sets horizontal metrics. */ 1320 1321static int 1322mac_text_extents_16 (font_struct, string, nchars, overall_return) 1323 XFontStruct *font_struct; 1324 XChar2b *string; 1325 int nchars; 1326 XCharStruct *overall_return; 1327{ 1328 int i; 1329 short width = 0, lbearing = 0, rbearing = 0; 1330 XCharStruct *pcm; 1331 1332 for (i = 0; i < nchars; i++) 1333 { 1334 pcm = mac_per_char_metric (font_struct, string, 0); 1335 if (pcm == NULL) 1336 width += FONT_WIDTH (font_struct); 1337 else 1338 { 1339 lbearing = min (lbearing, width + pcm->lbearing); 1340 rbearing = max (rbearing, width + pcm->rbearing); 1341 width += pcm->width; 1342 } 1343 string++; 1344 } 1345 1346 overall_return->lbearing = lbearing; 1347 overall_return->rbearing = rbearing; 1348 overall_return->width = width; 1349 1350 /* What's the meaning of the return value of XTextExtents16? */ 1351} 1352 1353 1354#if USE_CG_TEXT_DRAWING 1355static int cg_text_anti_aliasing_threshold = 8; 1356 1357static void 1358init_cg_text_anti_aliasing_threshold () 1359{ 1360 int threshold; 1361 Boolean valid_p; 1362 1363 threshold = 1364 CFPreferencesGetAppIntegerValue (CFSTR ("AppleAntiAliasingThreshold"), 1365 kCFPreferencesCurrentApplication, 1366 &valid_p); 1367 if (valid_p) 1368 cg_text_anti_aliasing_threshold = threshold; 1369} 1370 1371static int 1372mac_draw_image_string_cg (f, gc, x, y, buf, nchars, bg_width, overstrike_p) 1373 struct frame *f; 1374 GC gc; 1375 int x, y; 1376 XChar2b *buf; 1377 int nchars, bg_width, overstrike_p; 1378{ 1379 CGrafPtr port; 1380 float port_height, gx, gy; 1381 int i; 1382 CGContextRef context; 1383 CGGlyph *glyphs; 1384 CGSize *advances; 1385 1386 if (!mac_use_core_graphics || GC_FONT (gc)->cg_font == NULL) 1387 return 0; 1388 1389 port = GetWindowPort (FRAME_MAC_WINDOW (f)); 1390 port_height = FRAME_PIXEL_HEIGHT (f); 1391 gx = x; 1392 gy = port_height - y; 1393 glyphs = (CGGlyph *)buf; 1394 advances = alloca (sizeof (CGSize) * nchars); 1395 if (advances == NULL) 1396 return 0; 1397 for (i = 0; i < nchars; i++) 1398 { 1399 XCharStruct *pcm = mac_per_char_metric (GC_FONT (gc), buf, 0); 1400 1401 advances[i].width = pcm->width; 1402 advances[i].height = 0; 1403 glyphs[i] = GC_FONT (gc)->cg_glyphs[buf->byte2]; 1404 buf++; 1405 } 1406 1407#if USE_CG_DRAWING 1408 context = mac_begin_cg_clip (f, gc); 1409#else 1410 QDBeginCGContext (port, &context); 1411 if (gc->n_clip_rects || bg_width) 1412 { 1413 CGContextTranslateCTM (context, 0, port_height); 1414 CGContextScaleCTM (context, 1, -1); 1415 if (gc->n_clip_rects) 1416 CGContextClipToRects (context, gc->clip_rects, gc->n_clip_rects); 1417#endif 1418 if (bg_width) 1419 { 1420 CG_SET_FILL_COLOR_WITH_GC_BACKGROUND (context, gc); 1421 CGContextFillRect 1422 (context, 1423 CGRectMake (gx, y - FONT_BASE (GC_FONT (gc)), 1424 bg_width, FONT_HEIGHT (GC_FONT (gc)))); 1425 } 1426 CGContextScaleCTM (context, 1, -1); 1427 CGContextTranslateCTM (context, 0, -port_height); 1428#if !USE_CG_DRAWING 1429 } 1430#endif 1431 CG_SET_FILL_COLOR_WITH_GC_FOREGROUND (context, gc); 1432 CGContextSetFont (context, GC_FONT (gc)->cg_font); 1433 CGContextSetFontSize (context, GC_FONT (gc)->mac_fontsize); 1434 if (GC_FONT (gc)->mac_fontsize <= cg_text_anti_aliasing_threshold) 1435 CGContextSetShouldAntialias (context, false); 1436#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 1437#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020 1438 if (CGContextShowGlyphsWithAdvances != NULL) 1439#endif 1440 { 1441 CGContextSetTextPosition (context, gx, gy); 1442 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars); 1443 if (overstrike_p) 1444 { 1445 CGContextSetTextPosition (context, gx + 1.0f, gy); 1446 CGContextShowGlyphsWithAdvances (context, glyphs, advances, nchars); 1447 } 1448 } 1449#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020 1450 else 1451#endif 1452#endif /* MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 */ 1453#if MAC_OS_X_VERSION_MAX_ALLOWED < 1030 || MAC_OS_X_VERSION_MIN_REQUIRED == 1020 1454 { 1455 for (i = 0; i < nchars; i++) 1456 { 1457 CGContextShowGlyphsAtPoint (context, gx, gy, glyphs + i, 1); 1458 if (overstrike_p) 1459 CGContextShowGlyphsAtPoint (context, gx + 1.0f, gy, glyphs + i, 1); 1460 gx += advances[i].width; 1461 } 1462 } 1463#endif 1464#if USE_CG_DRAWING 1465 mac_end_cg_clip (f); 1466#else 1467 CGContextSynchronize (context); 1468 QDEndCGContext (port, &context); 1469#endif 1470 1471 return 1; 1472} 1473#endif 1474 1475 1476#if !USE_CG_DRAWING 1477/* Mac replacement for XCopyArea: dest must be window. */ 1478 1479static void 1480mac_copy_area (src, f, gc, src_x, src_y, width, height, dest_x, dest_y) 1481 Pixmap src; 1482 struct frame *f; 1483 GC gc; 1484 int src_x, src_y; 1485 unsigned int width, height; 1486 int dest_x, dest_y; 1487{ 1488 Rect src_r, dest_r; 1489 1490 SetPortWindowPort (FRAME_MAC_WINDOW (f)); 1491 1492 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height); 1493 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height); 1494 1495 ForeColor (blackColor); 1496 BackColor (whiteColor); 1497 1498 mac_begin_clip (gc); 1499 LockPixels (GetGWorldPixMap (src)); 1500#if TARGET_API_MAC_CARBON 1501 { 1502 CGrafPtr port; 1503 1504 GetPort (&port); 1505 LockPortBits (port); 1506 CopyBits (GetPortBitMapForCopyBits (src), 1507 GetPortBitMapForCopyBits (port), 1508 &src_r, &dest_r, srcCopy, 0); 1509 UnlockPortBits (port); 1510 } 1511#else /* not TARGET_API_MAC_CARBON */ 1512 CopyBits (&(((GrafPtr)src)->portBits), &(FRAME_MAC_WINDOW (f)->portBits), 1513 &src_r, &dest_r, srcCopy, 0); 1514#endif /* not TARGET_API_MAC_CARBON */ 1515 UnlockPixels (GetGWorldPixMap (src)); 1516 mac_end_clip (gc); 1517 1518 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f))); 1519} 1520 1521 1522static void 1523mac_copy_area_with_mask (src, mask, f, gc, src_x, src_y, 1524 width, height, dest_x, dest_y) 1525 Pixmap src, mask; 1526 struct frame *f; 1527 GC gc; 1528 int src_x, src_y; 1529 unsigned int width, height; 1530 int dest_x, dest_y; 1531{ 1532 Rect src_r, dest_r; 1533 1534 SetPortWindowPort (FRAME_MAC_WINDOW (f)); 1535 1536 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height); 1537 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height); 1538 1539 ForeColor (blackColor); 1540 BackColor (whiteColor); 1541 1542 mac_begin_clip (gc); 1543 LockPixels (GetGWorldPixMap (src)); 1544 LockPixels (GetGWorldPixMap (mask)); 1545#if TARGET_API_MAC_CARBON 1546 { 1547 CGrafPtr port; 1548 1549 GetPort (&port); 1550 LockPortBits (port); 1551 CopyMask (GetPortBitMapForCopyBits (src), GetPortBitMapForCopyBits (mask), 1552 GetPortBitMapForCopyBits (port), 1553 &src_r, &src_r, &dest_r); 1554 UnlockPortBits (port); 1555 } 1556#else /* not TARGET_API_MAC_CARBON */ 1557 CopyMask (&(((GrafPtr)src)->portBits), &(((GrafPtr)mask)->portBits), 1558 &(FRAME_MAC_WINDOW (f)->portBits), &src_r, &src_r, &dest_r); 1559#endif /* not TARGET_API_MAC_CARBON */ 1560 UnlockPixels (GetGWorldPixMap (mask)); 1561 UnlockPixels (GetGWorldPixMap (src)); 1562 mac_end_clip (gc); 1563 1564 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f))); 1565} 1566#endif /* !USE_CG_DRAWING */ 1567 1568 1569/* Mac replacement for XCopyArea: used only for scrolling. */ 1570 1571static void 1572mac_scroll_area (f, gc, src_x, src_y, width, height, dest_x, dest_y) 1573 struct frame *f; 1574 GC gc; 1575 int src_x, src_y; 1576 unsigned int width, height; 1577 int dest_x, dest_y; 1578{ 1579#if TARGET_API_MAC_CARBON 1580 Rect src_r; 1581 RgnHandle dummy = NewRgn (); /* For avoiding update events. */ 1582 1583 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height); 1584#if USE_CG_DRAWING 1585 mac_prepare_for_quickdraw (f); 1586#endif 1587 ScrollWindowRect (FRAME_MAC_WINDOW (f), 1588 &src_r, dest_x - src_x, dest_y - src_y, 1589 kScrollWindowNoOptions, dummy); 1590 DisposeRgn (dummy); 1591#else /* not TARGET_API_MAC_CARBON */ 1592 Rect src_r, dest_r; 1593 WindowPtr w = FRAME_MAC_WINDOW (f); 1594 1595 SetPort (w); 1596 1597 SetRect (&src_r, src_x, src_y, src_x + width, src_y + height); 1598 SetRect (&dest_r, dest_x, dest_y, dest_x + width, dest_y + height); 1599 1600 /* In Color QuickDraw, set ForeColor and BackColor as follows to avoid 1601 color mapping in CopyBits. Otherwise, it will be slow. */ 1602 ForeColor (blackColor); 1603 BackColor (whiteColor); 1604 mac_begin_clip (gc); 1605 CopyBits (&(w->portBits), &(w->portBits), &src_r, &dest_r, srcCopy, 0); 1606 mac_end_clip (gc); 1607 1608 RGBBackColor (GC_BACK_COLOR (FRAME_NORMAL_GC (f))); 1609#endif /* not TARGET_API_MAC_CARBON */ 1610} 1611 1612 1613/* Mac replacement for XChangeGC. */ 1614 1615static void 1616XChangeGC (display, gc, mask, xgcv) 1617 Display *display; 1618 GC gc; 1619 unsigned long mask; 1620 XGCValues *xgcv; 1621{ 1622 if (mask & GCForeground) 1623 XSetForeground (display, gc, xgcv->foreground); 1624 if (mask & GCBackground) 1625 XSetBackground (display, gc, xgcv->background); 1626 if (mask & GCFont) 1627 XSetFont (display, gc, xgcv->font); 1628} 1629 1630 1631/* Mac replacement for XCreateGC. */ 1632 1633GC 1634XCreateGC (display, d, mask, xgcv) 1635 Display *display; 1636 void *d; 1637 unsigned long mask; 1638 XGCValues *xgcv; 1639{ 1640 GC gc = xmalloc (sizeof (*gc)); 1641 1642 bzero (gc, sizeof (*gc)); 1643#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 1644#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020 1645 if (CGColorGetTypeID != NULL) 1646#endif 1647 { 1648 gc->cg_fore_color = gc->cg_back_color = mac_cg_color_black; 1649 CGColorRetain (gc->cg_fore_color); 1650 CGColorRetain (gc->cg_back_color); 1651 } 1652#endif 1653 XChangeGC (display, gc, mask, xgcv); 1654 1655 return gc; 1656} 1657 1658 1659/* Used in xfaces.c. */ 1660 1661void 1662XFreeGC (display, gc) 1663 Display *display; 1664 GC gc; 1665{ 1666 if (gc->clip_region) 1667 DisposeRgn (gc->clip_region); 1668#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 1669#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020 1670 if (CGColorGetTypeID != NULL) 1671#endif 1672 { 1673 CGColorRelease (gc->cg_fore_color); 1674 CGColorRelease (gc->cg_back_color); 1675 } 1676#endif 1677 xfree (gc); 1678} 1679 1680 1681/* Mac replacement for XGetGCValues. */ 1682 1683static void 1684XGetGCValues (display, gc, mask, xgcv) 1685 Display *display; 1686 GC gc; 1687 unsigned long mask; 1688 XGCValues *xgcv; 1689{ 1690 if (mask & GCForeground) 1691 xgcv->foreground = gc->xgcv.foreground; 1692 if (mask & GCBackground) 1693 xgcv->background = gc->xgcv.background; 1694 if (mask & GCFont) 1695 xgcv->font = gc->xgcv.font; 1696} 1697 1698 1699/* Mac replacement for XSetForeground. */ 1700 1701void 1702XSetForeground (display, gc, color) 1703 Display *display; 1704 GC gc; 1705 unsigned long color; 1706{ 1707 if (gc->xgcv.foreground != color) 1708 { 1709 gc->xgcv.foreground = color; 1710 gc->fore_color.red = RED16_FROM_ULONG (color); 1711 gc->fore_color.green = GREEN16_FROM_ULONG (color); 1712 gc->fore_color.blue = BLUE16_FROM_ULONG (color); 1713#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 1714#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020 1715 if (CGColorGetTypeID != NULL) 1716#endif 1717 { 1718 CGColorRelease (gc->cg_fore_color); 1719 if (color == 0) 1720 { 1721 gc->cg_fore_color = mac_cg_color_black; 1722 CGColorRetain (gc->cg_fore_color); 1723 } 1724 else 1725 { 1726 float rgba[4]; 1727 1728 rgba[0] = gc->fore_color.red / 65535.0f; 1729 rgba[1] = gc->fore_color.green / 65535.0f; 1730 rgba[2] = gc->fore_color.blue / 65535.0f; 1731 rgba[3] = 1.0f; 1732 gc->cg_fore_color = CGColorCreate (mac_cg_color_space_rgb, rgba); 1733 } 1734 } 1735#endif 1736 } 1737} 1738 1739 1740/* Mac replacement for XSetBackground. */ 1741 1742void 1743XSetBackground (display, gc, color) 1744 Display *display; 1745 GC gc; 1746 unsigned long color; 1747{ 1748 if (gc->xgcv.background != color) 1749 { 1750 gc->xgcv.background = color; 1751 gc->back_color.red = RED16_FROM_ULONG (color); 1752 gc->back_color.green = GREEN16_FROM_ULONG (color); 1753 gc->back_color.blue = BLUE16_FROM_ULONG (color); 1754#if USE_CG_DRAWING && MAC_OS_X_VERSION_MAX_ALLOWED >= 1030 1755#if MAC_OS_X_VERSION_MIN_REQUIRED == 1020 1756 if (CGColorGetTypeID != NULL) 1757#endif 1758 { 1759 CGColorRelease (gc->cg_back_color); 1760 if (color == 0) 1761 { 1762 gc->cg_back_color = mac_cg_color_black; 1763 CGColorRetain (gc->cg_back_color); 1764 } 1765 else 1766 { 1767 float rgba[4]; 1768 1769 rgba[0] = gc->back_color.red / 65535.0f; 1770 rgba[1] = gc->back_color.green / 65535.0f; 1771 rgba[2] = gc->back_color.blue / 65535.0f; 1772 rgba[3] = 1.0f; 1773 gc->cg_back_color = CGColorCreate (mac_cg_color_space_rgb, rgba); 1774 } 1775 } 1776#endif 1777 } 1778} 1779 1780 1781/* Mac replacement for XSetFont. */ 1782 1783static void 1784XSetFont (display, gc, font) 1785 Display *display; 1786 GC gc; 1787 XFontStruct *font; 1788{ 1789 gc->xgcv.font = font; 1790} 1791 1792 1793/* Mac replacement for XSetClipRectangles. */ 1794 1795static void 1796mac_set_clip_rectangles (display, gc, rectangles, n) 1797 Display *display; 1798 GC gc; 1799 Rect *rectangles; 1800 int n; 1801{ 1802 int i; 1803 1804 xassert (n >= 0 && n <= MAX_CLIP_RECTS); 1805 1806 gc->n_clip_rects = n; 1807 if (n > 0) 1808 { 1809 if (gc->clip_region == NULL) 1810 gc->clip_region = NewRgn (); 1811 RectRgn (gc->clip_region, rectangles); 1812 if (n > 1) 1813 { 1814 RgnHandle region = NewRgn (); 1815 1816 for (i = 1; i < n; i++) 1817 { 1818 RectRgn (region, rectangles + i); 1819 UnionRgn (gc->clip_region, region, gc->clip_region); 1820 } 1821 DisposeRgn (region); 1822 } 1823 } 1824#if defined (MAC_OSX) && (USE_ATSUI || USE_CG_DRAWING) 1825 for (i = 0; i < n; i++) 1826 { 1827 Rect *rect = rectangles + i; 1828 1829 gc->clip_rects[i] = CGRectMake (rect->left, rect->top, 1830 rect->right - rect->left, 1831 rect->bottom - rect->top); 1832 } 1833#endif 1834} 1835 1836 1837/* Mac replacement for XSetClipMask. */ 1838 1839static INLINE void 1840mac_reset_clip_rectangles (display, gc) 1841 Display *display; 1842 GC gc; 1843{ 1844 gc->n_clip_rects = 0; 1845} 1846 1847 1848/* Mac replacement for XSetWindowBackground. */ 1849 1850void 1851XSetWindowBackground (display, w, color) 1852 Display *display; 1853 WindowPtr w; 1854 unsigned long color; 1855{ 1856#if !TARGET_API_MAC_CARBON 1857 AuxWinHandle aw_handle; 1858 CTabHandle ctab_handle; 1859 ColorSpecPtr ct_table; 1860 short ct_size; 1861#endif 1862 RGBColor bg_color; 1863 1864 bg_color.red = RED16_FROM_ULONG (color); 1865 bg_color.green = GREEN16_FROM_ULONG (color); 1866 bg_color.blue = BLUE16_FROM_ULONG (color); 1867 1868#if TARGET_API_MAC_CARBON 1869 SetWindowContentColor (w, &bg_color); 1870#else 1871 if (GetAuxWin (w, &aw_handle)) 1872 { 1873 ctab_handle = (*aw_handle)->awCTable; 1874 HandToHand ((Handle *) &ctab_handle); 1875 ct_table = (*ctab_handle)->ctTable; 1876 ct_size = (*ctab_handle)->ctSize; 1877 while (ct_size > -1) 1878 { 1879 if (ct_table->value == 0) 1880 { 1881 ct_table->rgb = bg_color; 1882 CTabChanged (ctab_handle); 1883 SetWinColor (w, (WCTabHandle) ctab_handle); 1884 } 1885 ct_size--; 1886 } 1887 } 1888#endif 1889} 1890 1891/* Flush display of frame F, or of all frames if F is null. */ 1892 1893static void 1894x_flush (f) 1895 struct frame *f; 1896{ 1897#if TARGET_API_MAC_CARBON 1898 BLOCK_INPUT; 1899#if USE_CG_DRAWING 1900 mac_prepare_for_quickdraw (f); 1901#endif 1902 if (f) 1903 QDFlushPortBuffer (GetWindowPort (FRAME_MAC_WINDOW (f)), NULL); 1904 else 1905 QDFlushPortBuffer (GetQDGlobalsThePort (), NULL); 1906 UNBLOCK_INPUT; 1907#endif 1908} 1909 1910 1911/* Remove calls to XFlush by defining XFlush to an empty replacement. 1912 Calls to XFlush should be unnecessary because the X output buffer 1913 is flushed automatically as needed by calls to XPending, 1914 XNextEvent, or XWindowEvent according to the XFlush man page. 1915 XTread_socket calls XPending. Removing XFlush improves 1916 performance. */ 1917 1918#define XFlush(DISPLAY) (void) 0 1919 1920#if USE_CG_DRAWING 1921static void 1922mac_flush_display_optional (f) 1923 struct frame *f; 1924{ 1925 BLOCK_INPUT; 1926 mac_prepare_for_quickdraw (f); 1927 UNBLOCK_INPUT; 1928} 1929#endif 1930 1931/*********************************************************************** 1932 Starting and ending an update 1933 ***********************************************************************/ 1934 1935/* Start an update of frame F. This function is installed as a hook 1936 for update_begin, i.e. it is called when update_begin is called. 1937 This function is called prior to calls to x_update_window_begin for 1938 each window being updated. */ 1939 1940static void 1941x_update_begin (f) 1942 struct frame *f; 1943{ 1944#if TARGET_API_MAC_CARBON 1945 /* During update of a frame, availability of input events is 1946 periodically checked with ReceiveNextEvent if 1947 redisplay-dont-pause is nil. That normally flushes window buffer 1948 changes for every check, and thus screen update looks waving even 1949 if no input is available. So we disable screen updates during 1950 update of a frame. */ 1951 BLOCK_INPUT; 1952 DisableScreenUpdates (); 1953 UNBLOCK_INPUT; 1954#endif 1955} 1956 1957 1958/* Start update of window W. Set the global variable updated_window 1959 to the window being updated and set output_cursor to the cursor 1960 position of W. */ 1961 1962static void 1963x_update_window_begin (w) 1964 struct window *w; 1965{ 1966 struct frame *f = XFRAME (WINDOW_FRAME (w)); 1967 struct mac_display_info *display_info = FRAME_MAC_DISPLAY_INFO (f); 1968 1969 updated_window = w; 1970 set_output_cursor (&w->cursor); 1971 1972 BLOCK_INPUT; 1973 1974 if (f == display_info->mouse_face_mouse_frame) 1975 { 1976 /* Don't do highlighting for mouse motion during the update. */ 1977 display_info->mouse_face_defer = 1; 1978 1979 /* If F needs to be redrawn, simply forget about any prior mouse 1980 highlighting. */ 1981 if (FRAME_GARBAGED_P (f)) 1982 display_info->mouse_face_window = Qnil; 1983 1984#if 0 /* Rows in a current matrix containing glyphs in mouse-face have 1985 their mouse_face_p flag set, which means that they are always 1986 unequal to rows in a desired matrix which never have that 1987 flag set. So, rows containing mouse-face glyphs are never 1988 scrolled, and we don't have to switch the mouse highlight off 1989 here to prevent it from being scrolled. */ 1990 1991 /* Can we tell that this update does not affect the window 1992 where the mouse highlight is? If so, no need to turn off. 1993 Likewise, don't do anything if the frame is garbaged; 1994 in that case, the frame's current matrix that we would use 1995 is all wrong, and we will redisplay that line anyway. */ 1996 if (!NILP (display_info->mouse_face_window) 1997 && w == XWINDOW (display_info->mouse_face_window)) 1998 { 1999 int i; 2000 2001 for (i = 0; i < w->desired_matrix->nrows; ++i) 2002 if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i)) 2003 break; 2004 2005 if (i < w->desired_matrix->nrows) 2006 clear_mouse_face (display_info); 2007 } 2008#endif /* 0 */ 2009 } 2010 2011 UNBLOCK_INPUT; 2012} 2013 2014 2015/* Draw a vertical window border from (x,y0) to (x,y1) */ 2016 2017static void 2018mac_draw_vertical_window_border (w, x, y0, y1) 2019 struct window *w; 2020 int x, y0, y1; 2021{ 2022 struct frame *f = XFRAME (WINDOW_FRAME (w)); 2023 struct face *face; 2024 2025 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID); 2026 if (face) 2027 XSetForeground (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc, 2028 face->foreground); 2029 2030 mac_draw_line (f, f->output_data.mac->normal_gc, x, y0, x, y1); 2031} 2032 2033/* End update of window W (which is equal to updated_window). 2034 2035 Draw vertical borders between horizontally adjacent windows, and 2036 display W's cursor if CURSOR_ON_P is non-zero. 2037 2038 MOUSE_FACE_OVERWRITTEN_P non-zero means that some row containing 2039 glyphs in mouse-face were overwritten. In that case we have to 2040 make sure that the mouse-highlight is properly redrawn. 2041 2042 W may be a menu bar pseudo-window in case we don't have X toolkit 2043 support. Such windows don't have a cursor, so don't display it 2044 here. */ 2045 2046static void 2047x_update_window_end (w, cursor_on_p, mouse_face_overwritten_p) 2048 struct window *w; 2049 int cursor_on_p, mouse_face_overwritten_p; 2050{ 2051 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (XFRAME (w->frame)); 2052 2053 if (!w->pseudo_window_p) 2054 { 2055 BLOCK_INPUT; 2056 2057 if (cursor_on_p) 2058 display_and_set_cursor (w, 1, output_cursor.hpos, 2059 output_cursor.vpos, 2060 output_cursor.x, output_cursor.y); 2061 2062 if (draw_window_fringes (w, 1)) 2063 x_draw_vertical_border (w); 2064 2065 UNBLOCK_INPUT; 2066 } 2067 2068 /* If a row with mouse-face was overwritten, arrange for 2069 XTframe_up_to_date to redisplay the mouse highlight. */ 2070 if (mouse_face_overwritten_p) 2071 { 2072 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; 2073 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; 2074 dpyinfo->mouse_face_window = Qnil; 2075 } 2076 2077 updated_window = NULL; 2078} 2079 2080 2081/* End update of frame F. This function is installed as a hook in 2082 update_end. */ 2083 2084static void 2085x_update_end (f) 2086 struct frame *f; 2087{ 2088 /* Mouse highlight may be displayed again. */ 2089 FRAME_MAC_DISPLAY_INFO (f)->mouse_face_defer = 0; 2090 2091 BLOCK_INPUT; 2092#if TARGET_API_MAC_CARBON 2093 EnableScreenUpdates (); 2094#endif 2095 XFlush (FRAME_MAC_DISPLAY (f)); 2096 UNBLOCK_INPUT; 2097} 2098 2099 2100/* This function is called from various places in xdisp.c whenever a 2101 complete update has been performed. The global variable 2102 updated_window is not available here. */ 2103 2104static void 2105XTframe_up_to_date (f) 2106 struct frame *f; 2107{ 2108 if (FRAME_MAC_P (f)) 2109 { 2110 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f); 2111 2112 if (dpyinfo->mouse_face_deferred_gc 2113 || f == dpyinfo->mouse_face_mouse_frame) 2114 { 2115 BLOCK_INPUT; 2116 if (dpyinfo->mouse_face_mouse_frame) 2117 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame, 2118 dpyinfo->mouse_face_mouse_x, 2119 dpyinfo->mouse_face_mouse_y); 2120 dpyinfo->mouse_face_deferred_gc = 0; 2121 UNBLOCK_INPUT; 2122 } 2123 } 2124} 2125 2126 2127/* Draw truncation mark bitmaps, continuation mark bitmaps, overlay 2128 arrow bitmaps, or clear the fringes if no bitmaps are required 2129 before DESIRED_ROW is made current. The window being updated is 2130 found in updated_window. This function is called from 2131 update_window_line only if it is known that there are differences 2132 between bitmaps to be drawn between current row and DESIRED_ROW. */ 2133 2134static void 2135x_after_update_window_line (desired_row) 2136 struct glyph_row *desired_row; 2137{ 2138 struct window *w = updated_window; 2139 struct frame *f; 2140 int width, height; 2141 2142 xassert (w); 2143 2144 if (!desired_row->mode_line_p && !w->pseudo_window_p) 2145 desired_row->redraw_fringe_bitmaps_p = 1; 2146 2147 /* When a window has disappeared, make sure that no rest of 2148 full-width rows stays visible in the internal border. Could 2149 check here if updated_window is the leftmost/rightmost window, 2150 but I guess it's not worth doing since vertically split windows 2151 are almost never used, internal border is rarely set, and the 2152 overhead is very small. */ 2153 if (windows_or_buffers_changed 2154 && desired_row->full_width_p 2155 && (f = XFRAME (w->frame), 2156 width = FRAME_INTERNAL_BORDER_WIDTH (f), 2157 width != 0) 2158 && (height = desired_row->visible_height, 2159 height > 0)) 2160 { 2161 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y)); 2162 2163 /* Internal border is drawn below the tool bar. */ 2164 if (WINDOWP (f->tool_bar_window) 2165 && w == XWINDOW (f->tool_bar_window)) 2166 y -= width; 2167 2168 BLOCK_INPUT; 2169 mac_clear_area (f, 0, y, width, height); 2170 mac_clear_area (f, FRAME_PIXEL_WIDTH (f) - width, y, width, height); 2171 UNBLOCK_INPUT; 2172 } 2173} 2174 2175 2176/* Draw the bitmap WHICH in one of the left or right fringes of 2177 window W. ROW is the glyph row for which to display the bitmap; it 2178 determines the vertical position at which the bitmap has to be 2179 drawn. */ 2180 2181static void 2182x_draw_fringe_bitmap (w, row, p) 2183 struct window *w; 2184 struct glyph_row *row; 2185 struct draw_fringe_bitmap_params *p; 2186{ 2187 struct frame *f = XFRAME (WINDOW_FRAME (w)); 2188 Display *display = FRAME_MAC_DISPLAY (f); 2189 struct face *face = p->face; 2190 int rowY; 2191 2192 /* Must clip because of partially visible lines. */ 2193 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); 2194 if (p->y < rowY) 2195 { 2196 /* Adjust position of "bottom aligned" bitmap on partially 2197 visible last row. */ 2198 int oldY = row->y; 2199 int oldVH = row->visible_height; 2200 row->visible_height = p->h; 2201 row->y -= rowY - p->y; 2202 x_clip_to_row (w, row, -1, face->gc); 2203 row->y = oldY; 2204 row->visible_height = oldVH; 2205 } 2206 else 2207 x_clip_to_row (w, row, -1, face->gc); 2208 2209 if (p->bx >= 0 && !p->overlay_p) 2210 { 2211#if 0 /* MAC_TODO: stipple */ 2212 /* In case the same realized face is used for fringes and 2213 for something displayed in the text (e.g. face `region' on 2214 mono-displays, the fill style may have been changed to 2215 FillSolid in x_draw_glyph_string_background. */ 2216 if (face->stipple) 2217 XSetFillStyle (FRAME_X_DISPLAY (f), face->gc, FillOpaqueStippled); 2218 else 2219 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->background); 2220#endif 2221 2222 mac_erase_rectangle (f, face->gc, p->bx, p->by, p->nx, p->ny); 2223 2224#if 0 /* MAC_TODO: stipple */ 2225 if (!face->stipple) 2226 XSetForeground (FRAME_X_DISPLAY (f), face->gc, face->foreground); 2227#endif 2228 } 2229 2230 if (p->which 2231#if USE_CG_DRAWING 2232 && p->which < max_fringe_bmp 2233#endif 2234 ) 2235 { 2236 XGCValues gcv; 2237 2238 XGetGCValues (display, face->gc, GCForeground, &gcv); 2239 XSetForeground (display, face->gc, 2240 (p->cursor_p 2241 ? (p->overlay_p ? face->background 2242 : f->output_data.mac->cursor_pixel) 2243 : face->foreground)); 2244#if USE_CG_DRAWING 2245 mac_draw_cg_image (fringe_bmp[p->which], f, face->gc, 0, p->dh, 2246 p->wd, p->h, p->x, p->y, p->overlay_p); 2247#else 2248 mac_draw_bitmap (f, face->gc, p->x, p->y, 2249 p->wd, p->h, p->bits + p->dh, p->overlay_p); 2250#endif 2251 XSetForeground (display, face->gc, gcv.foreground); 2252 } 2253 2254 mac_reset_clip_rectangles (display, face->gc); 2255} 2256 2257#if USE_CG_DRAWING 2258static void 2259mac_define_fringe_bitmap (which, bits, h, wd) 2260 int which; 2261 unsigned short *bits; 2262 int h, wd; 2263{ 2264 int i; 2265 CGDataProviderRef provider; 2266 2267 if (which >= max_fringe_bmp) 2268 { 2269 i = max_fringe_bmp; 2270 max_fringe_bmp = which + 20; 2271 fringe_bmp = (CGImageRef *) xrealloc (fringe_bmp, max_fringe_bmp * sizeof (CGImageRef)); 2272 while (i < max_fringe_bmp) 2273 fringe_bmp[i++] = 0; 2274 } 2275 2276 for (i = 0; i < h; i++) 2277 bits[i] = ~bits[i]; 2278 provider = CGDataProviderCreateWithData (NULL, bits, 2279 sizeof (unsigned short) * h, NULL); 2280 if (provider) 2281 { 2282 fringe_bmp[which] = CGImageMaskCreate (wd, h, 1, 1, 2283 sizeof (unsigned short), 2284 provider, NULL, 0); 2285 CGDataProviderRelease (provider); 2286 } 2287} 2288 2289static void 2290mac_destroy_fringe_bitmap (which) 2291 int which; 2292{ 2293 if (which >= max_fringe_bmp) 2294 return; 2295 2296 if (fringe_bmp[which]) 2297 CGImageRelease (fringe_bmp[which]); 2298 fringe_bmp[which] = 0; 2299} 2300#endif 2301 2302 2303/* This is called when starting Emacs and when restarting after 2304 suspend. When starting Emacs, no window is mapped. And nothing 2305 must be done to Emacs's own window if it is suspended (though that 2306 rarely happens). */ 2307 2308static void 2309XTset_terminal_modes () 2310{ 2311} 2312 2313/* This is called when exiting or suspending Emacs. Exiting will make 2314 the windows go away, and suspending requires no action. */ 2315 2316static void 2317XTreset_terminal_modes () 2318{ 2319} 2320 2321 2322 2323/*********************************************************************** 2324 Display Iterator 2325 ***********************************************************************/ 2326 2327/* Function prototypes of this page. */ 2328 2329static XCharStruct *x_per_char_metric P_ ((XFontStruct *, XChar2b *)); 2330static int mac_encode_char P_ ((int, XChar2b *, struct font_info *, int *)); 2331 2332 2333static void 2334pcm_init (pcm, count) 2335 XCharStruct *pcm; 2336 int count; 2337{ 2338 bzero (pcm, sizeof (XCharStruct) * count); 2339 while (--count >= 0) 2340 { 2341 pcm->descent = PCM_INVALID; 2342 pcm++; 2343 } 2344} 2345 2346static enum pcm_status 2347pcm_get_status (pcm) 2348 const XCharStruct *pcm; 2349{ 2350 int height = pcm->ascent + pcm->descent; 2351 2352 /* Negative height means some special status. */ 2353 return height >= 0 ? PCM_VALID : height; 2354} 2355 2356/* Get metrics of character CHAR2B in FONT. Value is null if CHAR2B 2357 is not contained in the font. */ 2358 2359static INLINE XCharStruct * 2360x_per_char_metric (font, char2b) 2361 XFontStruct *font; 2362 XChar2b *char2b; 2363{ 2364 /* The result metric information. */ 2365 XCharStruct *pcm = NULL; 2366 2367 xassert (font && char2b); 2368 2369#if USE_ATSUI 2370 if (font->mac_style) 2371 { 2372 XCharStruct **row = font->bounds.rows + char2b->byte1; 2373 2374 if (*row == NULL) 2375 { 2376 *row = xmalloc (sizeof (XCharStruct) * 0x100); 2377 pcm_init (*row, 0x100); 2378 } 2379 pcm = *row + char2b->byte2; 2380 if (pcm_get_status (pcm) != PCM_VALID) 2381 { 2382 BLOCK_INPUT; 2383 mac_query_char_extents (font->mac_style, 2384 (char2b->byte1 << 8) + char2b->byte2, 2385 NULL, NULL, pcm, NULL); 2386 UNBLOCK_INPUT; 2387 } 2388 } 2389 else 2390 { 2391#endif 2392 if (font->bounds.per_char != NULL) 2393 { 2394 if (font->min_byte1 == 0 && font->max_byte1 == 0) 2395 { 2396 /* min_char_or_byte2 specifies the linear character index 2397 corresponding to the first element of the per_char array, 2398 max_char_or_byte2 is the index of the last character. A 2399 character with non-zero CHAR2B->byte1 is not in the font. 2400 A character with byte2 less than min_char_or_byte2 or 2401 greater max_char_or_byte2 is not in the font. */ 2402 if (char2b->byte1 == 0 2403 && char2b->byte2 >= font->min_char_or_byte2 2404 && char2b->byte2 <= font->max_char_or_byte2) 2405 pcm = font->bounds.per_char 2406 + (char2b->byte2 - font->min_char_or_byte2); 2407 } 2408 else 2409 { 2410 /* If either min_byte1 or max_byte1 are nonzero, both 2411 min_char_or_byte2 and max_char_or_byte2 are less than 2412 256, and the 2-byte character index values corresponding 2413 to the per_char array element N (counting from 0) are: 2414 2415 byte1 = N/D + min_byte1 2416 byte2 = N\D + min_char_or_byte2 2417 2418 where: 2419 2420 D = max_char_or_byte2 - min_char_or_byte2 + 1 2421 / = integer division 2422 \ = integer modulus */ 2423 if (char2b->byte1 >= font->min_byte1 2424 && char2b->byte1 <= font->max_byte1 2425 && char2b->byte2 >= font->min_char_or_byte2 2426 && char2b->byte2 <= font->max_char_or_byte2) 2427 { 2428 pcm = (font->bounds.per_char 2429 + ((font->max_char_or_byte2 - font->min_char_or_byte2 + 1) 2430 * (char2b->byte1 - font->min_byte1)) 2431 + (char2b->byte2 - font->min_char_or_byte2)); 2432 } 2433 } 2434 } 2435 else 2436 { 2437 /* If the per_char pointer is null, all glyphs between the first 2438 and last character indexes inclusive have the same 2439 information, as given by both min_bounds and max_bounds. */ 2440 if (char2b->byte2 >= font->min_char_or_byte2 2441 && char2b->byte2 <= font->max_char_or_byte2) 2442 pcm = &font->max_bounds; 2443 } 2444#if USE_ATSUI 2445 } 2446#endif 2447 2448 return ((pcm == NULL 2449 || (pcm->width == 0 2450#if 0 /* Show hollow boxes for zero-width glyphs such as combining diacritics. */ 2451 && (pcm->rbearing - pcm->lbearing) == 0 2452#endif 2453 )) 2454 ? NULL : pcm); 2455} 2456 2457/* RIF: 2458 */ 2459 2460static XCharStruct * 2461mac_per_char_metric (font, char2b, font_type) 2462 XFontStruct *font; 2463 XChar2b *char2b; 2464 int font_type; 2465{ 2466 return x_per_char_metric (font, char2b); 2467} 2468 2469/* RIF: 2470 Encode CHAR2B using encoding information from FONT_INFO. CHAR2B is 2471 the two-byte form of C. Encoding is returned in *CHAR2B. */ 2472 2473static int 2474mac_encode_char (c, char2b, font_info, two_byte_p) 2475 int c; 2476 XChar2b *char2b; 2477 struct font_info *font_info; 2478 int *two_byte_p; 2479{ 2480 int charset = CHAR_CHARSET (c); 2481 XFontStruct *font = font_info->font; 2482 2483 /* FONT_INFO may define a scheme by which to encode byte1 and byte2. 2484 This may be either a program in a special encoder language or a 2485 fixed encoding. */ 2486 if (font_info->font_encoder) 2487 { 2488 /* It's a program. */ 2489 struct ccl_program *ccl = font_info->font_encoder; 2490 2491 check_ccl_update (ccl); 2492 if (CHARSET_DIMENSION (charset) == 1) 2493 { 2494 ccl->reg[0] = charset; 2495 ccl->reg[1] = char2b->byte2; 2496 ccl->reg[2] = -1; 2497 } 2498 else 2499 { 2500 ccl->reg[0] = charset; 2501 ccl->reg[1] = char2b->byte1; 2502 ccl->reg[2] = char2b->byte2; 2503 } 2504 2505 ccl_driver (ccl, NULL, NULL, 0, 0, NULL); 2506 2507 /* We assume that MSBs are appropriately set/reset by CCL 2508 program. */ 2509 if (font->max_byte1 == 0) /* 1-byte font */ 2510 char2b->byte1 = 0, char2b->byte2 = ccl->reg[1]; 2511 else 2512 char2b->byte1 = ccl->reg[1], char2b->byte2 = ccl->reg[2]; 2513 } 2514 else if (font_info->encoding[charset]) 2515 { 2516 /* Fixed encoding scheme. See fontset.h for the meaning of the 2517 encoding numbers. */ 2518 int enc = font_info->encoding[charset]; 2519 2520 if ((enc == 1 || enc == 2) 2521 && CHARSET_DIMENSION (charset) == 2) 2522 char2b->byte1 |= 0x80; 2523 2524 if (enc == 1 || enc == 3) 2525 char2b->byte2 |= 0x80; 2526 2527 if (enc == 4) 2528 { 2529 int sjis1, sjis2; 2530 2531 ENCODE_SJIS (char2b->byte1, char2b->byte2, sjis1, sjis2); 2532 char2b->byte1 = sjis1; 2533 char2b->byte2 = sjis2; 2534 } 2535 } 2536 2537 if (two_byte_p) 2538 *two_byte_p = ((XFontStruct *) (font_info->font))->max_byte1 > 0; 2539 2540 return FONT_TYPE_UNKNOWN; 2541} 2542 2543 2544 2545/*********************************************************************** 2546 Glyph display 2547 ***********************************************************************/ 2548 2549 2550 2551static void x_set_glyph_string_clipping P_ ((struct glyph_string *)); 2552static void x_set_glyph_string_gc P_ ((struct glyph_string *)); 2553static void x_draw_glyph_string_background P_ ((struct glyph_string *, 2554 int)); 2555static void x_draw_glyph_string_foreground P_ ((struct glyph_string *)); 2556static void x_draw_composite_glyph_string_foreground P_ ((struct glyph_string *)); 2557static void x_draw_glyph_string_box P_ ((struct glyph_string *)); 2558static void x_draw_glyph_string P_ ((struct glyph_string *)); 2559static void mac_compute_glyph_string_overhangs P_ ((struct glyph_string *)); 2560static void x_set_cursor_gc P_ ((struct glyph_string *)); 2561static void x_set_mode_line_face_gc P_ ((struct glyph_string *)); 2562static void x_set_mouse_face_gc P_ ((struct glyph_string *)); 2563/*static int x_alloc_lighter_color P_ ((struct frame *, Display *, Colormap, 2564 unsigned long *, double, int));*/ 2565static void x_setup_relief_color P_ ((struct frame *, struct relief *, 2566 double, int, unsigned long)); 2567static void x_setup_relief_colors P_ ((struct glyph_string *)); 2568static void x_draw_image_glyph_string P_ ((struct glyph_string *)); 2569static void x_draw_image_relief P_ ((struct glyph_string *)); 2570static void x_draw_image_foreground P_ ((struct glyph_string *)); 2571static void x_clear_glyph_string_rect P_ ((struct glyph_string *, int, 2572 int, int, int)); 2573static void x_draw_relief_rect P_ ((struct frame *, int, int, int, int, 2574 int, int, int, int, int, int, 2575 Rect *)); 2576static void x_draw_box_rect P_ ((struct glyph_string *, int, int, int, int, 2577 int, int, int, Rect *)); 2578 2579#if GLYPH_DEBUG 2580static void x_check_font P_ ((struct frame *, XFontStruct *)); 2581#endif 2582 2583 2584/* Set S->gc to a suitable GC for drawing glyph string S in cursor 2585 face. */ 2586 2587static void 2588x_set_cursor_gc (s) 2589 struct glyph_string *s; 2590{ 2591 if (s->font == FRAME_FONT (s->f) 2592 && s->face->background == FRAME_BACKGROUND_PIXEL (s->f) 2593 && s->face->foreground == FRAME_FOREGROUND_PIXEL (s->f) 2594 && !s->cmp) 2595 s->gc = s->f->output_data.mac->cursor_gc; 2596 else 2597 { 2598 /* Cursor on non-default face: must merge. */ 2599 XGCValues xgcv; 2600 unsigned long mask; 2601 2602 xgcv.background = s->f->output_data.mac->cursor_pixel; 2603 xgcv.foreground = s->face->background; 2604 2605 /* If the glyph would be invisible, try a different foreground. */ 2606 if (xgcv.foreground == xgcv.background) 2607 xgcv.foreground = s->face->foreground; 2608 if (xgcv.foreground == xgcv.background) 2609 xgcv.foreground = s->f->output_data.mac->cursor_foreground_pixel; 2610 if (xgcv.foreground == xgcv.background) 2611 xgcv.foreground = s->face->foreground; 2612 2613 /* Make sure the cursor is distinct from text in this face. */ 2614 if (xgcv.background == s->face->background 2615 && xgcv.foreground == s->face->foreground) 2616 { 2617 xgcv.background = s->face->foreground; 2618 xgcv.foreground = s->face->background; 2619 } 2620 2621 IF_DEBUG (x_check_font (s->f, s->font)); 2622 xgcv.font = s->font; 2623 mask = GCForeground | GCBackground | GCFont; 2624 2625 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc) 2626 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc, 2627 mask, &xgcv); 2628 else 2629 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc 2630 = XCreateGC (s->display, s->window, mask, &xgcv); 2631 2632 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc; 2633 } 2634} 2635 2636 2637/* Set up S->gc of glyph string S for drawing text in mouse face. */ 2638 2639static void 2640x_set_mouse_face_gc (s) 2641 struct glyph_string *s; 2642{ 2643 int face_id; 2644 struct face *face; 2645 2646 /* What face has to be used last for the mouse face? */ 2647 face_id = FRAME_X_DISPLAY_INFO (s->f)->mouse_face_face_id; 2648 face = FACE_FROM_ID (s->f, face_id); 2649 if (face == NULL) 2650 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID); 2651 2652 if (s->first_glyph->type == CHAR_GLYPH) 2653 face_id = FACE_FOR_CHAR (s->f, face, s->first_glyph->u.ch); 2654 else 2655 face_id = FACE_FOR_CHAR (s->f, face, 0); 2656 s->face = FACE_FROM_ID (s->f, face_id); 2657 PREPARE_FACE_FOR_DISPLAY (s->f, s->face); 2658 2659 /* If font in this face is same as S->font, use it. */ 2660 if (s->font == s->face->font) 2661 s->gc = s->face->gc; 2662 else 2663 { 2664 /* Otherwise construct scratch_cursor_gc with values from FACE 2665 but font FONT. */ 2666 XGCValues xgcv; 2667 unsigned long mask; 2668 2669 xgcv.background = s->face->background; 2670 xgcv.foreground = s->face->foreground; 2671 IF_DEBUG (x_check_font (s->f, s->font)); 2672 xgcv.font = s->font; 2673 mask = GCForeground | GCBackground | GCFont; 2674 2675 if (FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc) 2676 XChangeGC (s->display, FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc, 2677 mask, &xgcv); 2678 else 2679 FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc 2680 = XCreateGC (s->display, s->window, mask, &xgcv); 2681 2682 s->gc = FRAME_MAC_DISPLAY_INFO (s->f)->scratch_cursor_gc; 2683 } 2684 2685 xassert (s->gc != 0); 2686} 2687 2688 2689/* Set S->gc of glyph string S to a GC suitable for drawing a mode line. 2690 Faces to use in the mode line have already been computed when the 2691 matrix was built, so there isn't much to do, here. */ 2692 2693static INLINE void 2694x_set_mode_line_face_gc (s) 2695 struct glyph_string *s; 2696{ 2697 s->gc = s->face->gc; 2698} 2699 2700 2701/* Set S->gc of glyph string S for drawing that glyph string. Set 2702 S->stippled_p to a non-zero value if the face of S has a stipple 2703 pattern. */ 2704 2705static INLINE void 2706x_set_glyph_string_gc (s) 2707 struct glyph_string *s; 2708{ 2709 PREPARE_FACE_FOR_DISPLAY (s->f, s->face); 2710 2711 if (s->hl == DRAW_NORMAL_TEXT) 2712 { 2713 s->gc = s->face->gc; 2714 s->stippled_p = s->face->stipple != 0; 2715 } 2716 else if (s->hl == DRAW_INVERSE_VIDEO) 2717 { 2718 x_set_mode_line_face_gc (s); 2719 s->stippled_p = s->face->stipple != 0; 2720 } 2721 else if (s->hl == DRAW_CURSOR) 2722 { 2723 x_set_cursor_gc (s); 2724 s->stippled_p = 0; 2725 } 2726 else if (s->hl == DRAW_MOUSE_FACE) 2727 { 2728 x_set_mouse_face_gc (s); 2729 s->stippled_p = s->face->stipple != 0; 2730 } 2731 else if (s->hl == DRAW_IMAGE_RAISED 2732 || s->hl == DRAW_IMAGE_SUNKEN) 2733 { 2734 s->gc = s->face->gc; 2735 s->stippled_p = s->face->stipple != 0; 2736 } 2737 else 2738 { 2739 s->gc = s->face->gc; 2740 s->stippled_p = s->face->stipple != 0; 2741 } 2742 2743 /* GC must have been set. */ 2744 xassert (s->gc != 0); 2745} 2746 2747 2748/* Set clipping for output of glyph string S. S may be part of a mode 2749 line or menu if we don't have X toolkit support. */ 2750 2751static INLINE void 2752x_set_glyph_string_clipping (s) 2753 struct glyph_string *s; 2754{ 2755 Rect rects[MAX_CLIP_RECTS]; 2756 int n; 2757 2758 n = get_glyph_string_clip_rects (s, rects, MAX_CLIP_RECTS); 2759 mac_set_clip_rectangles (s->display, s->gc, rects, n); 2760} 2761 2762 2763/* RIF: 2764 Compute left and right overhang of glyph string S. If S is a glyph 2765 string for a composition, assume overhangs don't exist. */ 2766 2767static void 2768mac_compute_glyph_string_overhangs (s) 2769 struct glyph_string *s; 2770{ 2771 if (!(s->cmp == NULL 2772 && s->first_glyph->type == CHAR_GLYPH)) 2773 return; 2774 2775 if (!s->two_byte_p 2776#if USE_ATSUI 2777 || s->font->mac_style 2778#endif 2779 ) 2780 { 2781 XCharStruct cs; 2782 2783 mac_text_extents_16 (s->font, s->char2b, s->nchars, &cs); 2784 s->right_overhang = cs.rbearing > cs.width ? cs.rbearing - cs.width : 0; 2785 s->left_overhang = cs.lbearing < 0 ? -cs.lbearing : 0; 2786 } 2787 else 2788 { 2789 Rect r; 2790 MacFontStruct *font = s->font; 2791 2792#if USE_CG_DRAWING 2793 mac_prepare_for_quickdraw (s->f); 2794#endif 2795 SetPortWindowPort (FRAME_MAC_WINDOW (s->f)); 2796 2797 TextFont (font->mac_fontnum); 2798 TextSize (font->mac_fontsize); 2799 TextFace (font->mac_fontface); 2800 2801 QDTextBounds (s->nchars * 2, (char *)s->char2b, &r); 2802 2803 s->right_overhang = r.right > s->width ? r.right - s->width : 0; 2804 s->left_overhang = r.left < 0 ? -r.left : 0; 2805 } 2806} 2807 2808 2809/* Fill rectangle X, Y, W, H with background color of glyph string S. */ 2810 2811static INLINE void 2812x_clear_glyph_string_rect (s, x, y, w, h) 2813 struct glyph_string *s; 2814 int x, y, w, h; 2815{ 2816 mac_erase_rectangle (s->f, s->gc, x, y, w, h); 2817} 2818 2819 2820/* Draw the background of glyph_string S. If S->background_filled_p 2821 is non-zero don't draw it. FORCE_P non-zero means draw the 2822 background even if it wouldn't be drawn normally. This is used 2823 when a string preceding S draws into the background of S, or S 2824 contains the first component of a composition. */ 2825 2826static void 2827x_draw_glyph_string_background (s, force_p) 2828 struct glyph_string *s; 2829 int force_p; 2830{ 2831 /* Nothing to do if background has already been drawn or if it 2832 shouldn't be drawn in the first place. */ 2833 if (!s->background_filled_p) 2834 { 2835 int box_line_width = max (s->face->box_line_width, 0); 2836 2837#if 0 /* MAC_TODO: stipple */ 2838 if (s->stippled_p) 2839 { 2840 /* Fill background with a stipple pattern. */ 2841 XSetFillStyle (s->display, s->gc, FillOpaqueStippled); 2842 XFillRectangle (s->display, s->window, s->gc, s->x, 2843 s->y + box_line_width, 2844 s->background_width, 2845 s->height - 2 * box_line_width); 2846 XSetFillStyle (s->display, s->gc, FillSolid); 2847 s->background_filled_p = 1; 2848 } 2849 else 2850#endif 2851 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width 2852 || s->font_not_found_p 2853 || s->extends_to_end_of_line_p 2854 || force_p) 2855 { 2856 x_clear_glyph_string_rect (s, s->x, s->y + box_line_width, 2857 s->background_width, 2858 s->height - 2 * box_line_width); 2859 s->background_filled_p = 1; 2860 } 2861 } 2862} 2863 2864 2865/* Draw the foreground of glyph string S. */ 2866 2867static void 2868x_draw_glyph_string_foreground (s) 2869 struct glyph_string *s; 2870{ 2871 int i, x, bg_width; 2872 2873 /* If first glyph of S has a left box line, start drawing the text 2874 of S to the right of that box line. */ 2875 if (s->face->box != FACE_NO_BOX 2876 && s->first_glyph->left_box_line_p) 2877 x = s->x + abs (s->face->box_line_width); 2878 else 2879 x = s->x; 2880 2881 /* Draw characters of S as rectangles if S's font could not be 2882 loaded. */ 2883 if (s->font_not_found_p) 2884 { 2885 for (i = 0; i < s->nchars; ++i) 2886 { 2887 struct glyph *g = s->first_glyph + i; 2888 mac_draw_rectangle (s->f, s->gc, x, s->y, 2889 g->pixel_width - 1, s->height - 1); 2890 x += g->pixel_width; 2891 } 2892 } 2893 else 2894 { 2895 char *char1b = (char *) s->char2b; 2896 int boff = s->font_info->baseline_offset; 2897 2898 if (s->font_info->vertical_centering) 2899 boff = VCENTER_BASELINE_OFFSET (s->font, s->f) - boff; 2900 2901 /* If we can use 8-bit functions, condense S->char2b. */ 2902 if (!s->two_byte_p 2903#if USE_ATSUI 2904 && GC_FONT (s->gc)->mac_style == NULL 2905#endif 2906 ) 2907 for (i = 0; i < s->nchars; ++i) 2908 char1b[i] = s->char2b[i].byte2; 2909 2910 /* Draw text with XDrawString if background has already been 2911 filled. Otherwise, use XDrawImageString. (Note that 2912 XDrawImageString is usually faster than XDrawString.) Always 2913 use XDrawImageString when drawing the cursor so that there is 2914 no chance that characters under a box cursor are invisible. */ 2915 if (s->for_overlaps 2916 || (s->background_filled_p && s->hl != DRAW_CURSOR)) 2917 bg_width = 0; /* Corresponds to XDrawString. */ 2918 else 2919 bg_width = s->background_width; /* Corresponds to XDrawImageString. */ 2920 2921 if (s->two_byte_p 2922#if USE_ATSUI 2923 || GC_FONT (s->gc)->mac_style 2924#endif 2925 ) 2926#if USE_CG_TEXT_DRAWING 2927 if (!s->two_byte_p 2928 && mac_draw_image_string_cg (s->f, s->gc, x, s->ybase - boff, 2929 s->char2b, s->nchars, bg_width, 2930 s->face->overstrike)) 2931 ; 2932 else 2933#endif 2934 mac_draw_image_string_16 (s->f, s->gc, x, s->ybase - boff, 2935 s->char2b, s->nchars, bg_width, 2936 s->face->overstrike); 2937 else 2938 mac_draw_image_string (s->f, s->gc, x, s->ybase - boff, 2939 char1b, s->nchars, bg_width, 2940 s->face->overstrike); 2941 } 2942} 2943 2944/* Draw the foreground of composite glyph string S. */ 2945 2946static void 2947x_draw_composite_glyph_string_foreground (s) 2948 struct glyph_string *s; 2949{ 2950 int i, x; 2951 2952 /* If first glyph of S has a left box line, start drawing the text 2953 of S to the right of that box line. */ 2954 if (s->face->box != FACE_NO_BOX 2955 && s->first_glyph->left_box_line_p) 2956 x = s->x + abs (s->face->box_line_width); 2957 else 2958 x = s->x; 2959 2960 /* S is a glyph string for a composition. S->gidx is the index of 2961 the first character drawn for glyphs of this composition. 2962 S->gidx == 0 means we are drawing the very first character of 2963 this composition. */ 2964 2965 /* Draw a rectangle for the composition if the font for the very 2966 first character of the composition could not be loaded. */ 2967 if (s->font_not_found_p) 2968 { 2969 if (s->gidx == 0) 2970 mac_draw_rectangle (s->f, s->gc, x, s->y, 2971 s->width - 1, s->height - 1); 2972 } 2973 else 2974 { 2975 for (i = 0; i < s->nchars; i++, ++s->gidx) 2976 mac_draw_image_string_16 (s->f, s->gc, 2977 x + s->cmp->offsets[s->gidx * 2], 2978 s->ybase - s->cmp->offsets[s->gidx * 2 + 1], 2979 s->char2b + i, 1, 0, s->face->overstrike); 2980 } 2981} 2982 2983 2984#ifdef USE_X_TOOLKIT 2985 2986static struct frame *x_frame_of_widget P_ ((Widget)); 2987 2988 2989/* Return the frame on which widget WIDGET is used.. Abort if frame 2990 cannot be determined. */ 2991 2992static struct frame * 2993x_frame_of_widget (widget) 2994 Widget widget; 2995{ 2996 struct x_display_info *dpyinfo; 2997 Lisp_Object tail; 2998 struct frame *f; 2999 3000 dpyinfo = x_display_info_for_display (XtDisplay (widget)); 3001 3002 /* Find the top-level shell of the widget. Note that this function 3003 can be called when the widget is not yet realized, so XtWindow 3004 (widget) == 0. That's the reason we can't simply use 3005 x_any_window_to_frame. */ 3006 while (!XtIsTopLevelShell (widget)) 3007 widget = XtParent (widget); 3008 3009 /* Look for a frame with that top-level widget. Allocate the color 3010 on that frame to get the right gamma correction value. */ 3011 for (tail = Vframe_list; GC_CONSP (tail); tail = XCDR (tail)) 3012 if (GC_FRAMEP (XCAR (tail)) 3013 && (f = XFRAME (XCAR (tail)), 3014 (f->output_data.nothing != 1 3015 && FRAME_X_DISPLAY_INFO (f) == dpyinfo)) 3016 && f->output_data.x->widget == widget) 3017 return f; 3018 3019 abort (); 3020} 3021 3022 3023/* Allocate the color COLOR->pixel on the screen and display of 3024 widget WIDGET in colormap CMAP. If an exact match cannot be 3025 allocated, try the nearest color available. Value is non-zero 3026 if successful. This is called from lwlib. */ 3027 3028int 3029x_alloc_nearest_color_for_widget (widget, cmap, color) 3030 Widget widget; 3031 Colormap cmap; 3032 XColor *color; 3033{ 3034 struct frame *f = x_frame_of_widget (widget); 3035 return x_alloc_nearest_color (f, cmap, color); 3036} 3037 3038 3039#endif /* USE_X_TOOLKIT */ 3040 3041#if 0 /* MAC_TODO */ 3042 3043/* Allocate the color COLOR->pixel on SCREEN of DISPLAY, colormap 3044 CMAP. If an exact match can't be allocated, try the nearest color 3045 available. Value is non-zero if successful. Set *COLOR to the 3046 color allocated. */ 3047 3048int 3049x_alloc_nearest_color (f, cmap, color) 3050 struct frame *f; 3051 Colormap cmap; 3052 XColor *color; 3053{ 3054 Display *display = FRAME_X_DISPLAY (f); 3055 Screen *screen = FRAME_X_SCREEN (f); 3056 int rc; 3057 3058 gamma_correct (f, color); 3059 rc = XAllocColor (display, cmap, color); 3060 if (rc == 0) 3061 { 3062 /* If we got to this point, the colormap is full, so we're going 3063 to try to get the next closest color. The algorithm used is 3064 a least-squares matching, which is what X uses for closest 3065 color matching with StaticColor visuals. */ 3066 int nearest, i; 3067 unsigned long nearest_delta = ~0; 3068 int ncells = XDisplayCells (display, XScreenNumberOfScreen (screen)); 3069 XColor *cells = (XColor *) alloca (ncells * sizeof *cells); 3070 3071 for (i = 0; i < ncells; ++i) 3072 cells[i].pixel = i; 3073 XQueryColors (display, cmap, cells, ncells); 3074 3075 for (nearest = i = 0; i < ncells; ++i) 3076 { 3077 long dred = (color->red >> 8) - (cells[i].red >> 8); 3078 long dgreen = (color->green >> 8) - (cells[i].green >> 8); 3079 long dblue = (color->blue >> 8) - (cells[i].blue >> 8); 3080 unsigned long delta = dred * dred + dgreen * dgreen + dblue * dblue; 3081 3082 if (delta < nearest_delta) 3083 { 3084 nearest = i; 3085 nearest_delta = delta; 3086 } 3087 } 3088 3089 color->red = cells[nearest].red; 3090 color->green = cells[nearest].green; 3091 color->blue = cells[nearest].blue; 3092 rc = XAllocColor (display, cmap, color); 3093 } 3094 3095#ifdef DEBUG_X_COLORS 3096 if (rc) 3097 register_color (color->pixel); 3098#endif /* DEBUG_X_COLORS */ 3099 3100 return rc; 3101} 3102 3103 3104/* Allocate color PIXEL on frame F. PIXEL must already be allocated. 3105 It's necessary to do this instead of just using PIXEL directly to 3106 get color reference counts right. */ 3107 3108unsigned long 3109x_copy_color (f, pixel) 3110 struct frame *f; 3111 unsigned long pixel; 3112{ 3113 XColor color; 3114 3115 color.pixel = pixel; 3116 BLOCK_INPUT; 3117 XQueryColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color); 3118 XAllocColor (FRAME_X_DISPLAY (f), FRAME_X_COLORMAP (f), &color); 3119 UNBLOCK_INPUT; 3120#ifdef DEBUG_X_COLORS 3121 register_color (pixel); 3122#endif 3123 return color.pixel; 3124} 3125 3126 3127/* Allocate color PIXEL on display DPY. PIXEL must already be allocated. 3128 It's necessary to do this instead of just using PIXEL directly to 3129 get color reference counts right. */ 3130 3131unsigned long 3132x_copy_dpy_color (dpy, cmap, pixel) 3133 Display *dpy; 3134 Colormap cmap; 3135 unsigned long pixel; 3136{ 3137 XColor color; 3138 3139 color.pixel = pixel; 3140 BLOCK_INPUT; 3141 XQueryColor (dpy, cmap, &color); 3142 XAllocColor (dpy, cmap, &color); 3143 UNBLOCK_INPUT; 3144#ifdef DEBUG_X_COLORS 3145 register_color (pixel); 3146#endif 3147 return color.pixel; 3148} 3149 3150#endif /* MAC_TODO */ 3151 3152 3153/* Brightness beyond which a color won't have its highlight brightness 3154 boosted. 3155 3156 Nominally, highlight colors for `3d' faces are calculated by 3157 brightening an object's color by a constant scale factor, but this 3158 doesn't yield good results for dark colors, so for colors who's 3159 brightness is less than this value (on a scale of 0-255) have to 3160 use an additional additive factor. 3161 3162 The value here is set so that the default menu-bar/mode-line color 3163 (grey75) will not have its highlights changed at all. */ 3164#define HIGHLIGHT_COLOR_DARK_BOOST_LIMIT 187 3165 3166 3167/* Allocate a color which is lighter or darker than *COLOR by FACTOR 3168 or DELTA. Try a color with RGB values multiplied by FACTOR first. 3169 If this produces the same color as COLOR, try a color where all RGB 3170 values have DELTA added. Return the allocated color in *COLOR. 3171 DISPLAY is the X display, CMAP is the colormap to operate on. 3172 Value is non-zero if successful. */ 3173 3174static int 3175mac_alloc_lighter_color (f, color, factor, delta) 3176 struct frame *f; 3177 unsigned long *color; 3178 double factor; 3179 int delta; 3180{ 3181 unsigned long new; 3182 long bright; 3183 3184 /* On Mac, RGB values are 0-255, not 0-65535, so scale delta. */ 3185 delta /= 256; 3186 3187 /* Change RGB values by specified FACTOR. Avoid overflow! */ 3188 xassert (factor >= 0); 3189 new = RGB_TO_ULONG (min (0xff, (int) (factor * RED_FROM_ULONG (*color))), 3190 min (0xff, (int) (factor * GREEN_FROM_ULONG (*color))), 3191 min (0xff, (int) (factor * BLUE_FROM_ULONG (*color)))); 3192 3193 /* Calculate brightness of COLOR. */ 3194 bright = (2 * RED_FROM_ULONG (*color) + 3 * GREEN_FROM_ULONG (*color) 3195 + BLUE_FROM_ULONG (*color)) / 6; 3196 3197 /* We only boost colors that are darker than 3198 HIGHLIGHT_COLOR_DARK_BOOST_LIMIT. */ 3199 if (bright < HIGHLIGHT_COLOR_DARK_BOOST_LIMIT) 3200 /* Make an additive adjustment to NEW, because it's dark enough so 3201 that scaling by FACTOR alone isn't enough. */ 3202 { 3203 /* How far below the limit this color is (0 - 1, 1 being darker). */ 3204 double dimness = 1 - (double)bright / HIGHLIGHT_COLOR_DARK_BOOST_LIMIT; 3205 /* The additive adjustment. */ 3206 int min_delta = delta * dimness * factor / 2; 3207 3208 if (factor < 1) 3209 new = RGB_TO_ULONG (max (0, min (0xff, (int) (RED_FROM_ULONG (*color)) - min_delta)), 3210 max (0, min (0xff, (int) (GREEN_FROM_ULONG (*color)) - min_delta)), 3211 max (0, min (0xff, (int) (BLUE_FROM_ULONG (*color)) - min_delta))); 3212 else 3213 new = RGB_TO_ULONG (max (0, min (0xff, (int) (min_delta + RED_FROM_ULONG (*color)))), 3214 max (0, min (0xff, (int) (min_delta + GREEN_FROM_ULONG (*color)))), 3215 max (0, min (0xff, (int) (min_delta + BLUE_FROM_ULONG (*color))))); 3216 } 3217 3218 if (new == *color) 3219 new = RGB_TO_ULONG (max (0, min (0xff, (int) (delta + RED_FROM_ULONG (*color)))), 3220 max (0, min (0xff, (int) (delta + GREEN_FROM_ULONG (*color)))), 3221 max (0, min (0xff, (int) (delta + BLUE_FROM_ULONG (*color))))); 3222 3223 /* MAC_TODO: Map to palette and retry with delta if same? */ 3224 /* MAC_TODO: Free colors (if using palette)? */ 3225 3226 if (new == *color) 3227 return 0; 3228 3229 *color = new; 3230 3231 return 1; 3232} 3233 3234 3235/* Set up the foreground color for drawing relief lines of glyph 3236 string S. RELIEF is a pointer to a struct relief containing the GC 3237 with which lines will be drawn. Use a color that is FACTOR or 3238 DELTA lighter or darker than the relief's background which is found 3239 in S->f->output_data.x->relief_background. If such a color cannot 3240 be allocated, use DEFAULT_PIXEL, instead. */ 3241 3242static void 3243x_setup_relief_color (f, relief, factor, delta, default_pixel) 3244 struct frame *f; 3245 struct relief *relief; 3246 double factor; 3247 int delta; 3248 unsigned long default_pixel; 3249{ 3250 XGCValues xgcv; 3251 struct mac_output *di = f->output_data.mac; 3252 unsigned long mask = GCForeground; 3253 unsigned long pixel; 3254 unsigned long background = di->relief_background; 3255 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f); 3256 3257 /* MAC_TODO: Free colors (if using palette)? */ 3258 3259 /* Allocate new color. */ 3260 xgcv.foreground = default_pixel; 3261 pixel = background; 3262 if (dpyinfo->n_planes != 1 3263 && mac_alloc_lighter_color (f, &pixel, factor, delta)) 3264 { 3265 relief->allocated_p = 1; 3266 xgcv.foreground = relief->pixel = pixel; 3267 } 3268 3269 if (relief->gc == 0) 3270 { 3271#if 0 /* MAC_TODO: stipple */ 3272 xgcv.stipple = dpyinfo->gray; 3273 mask |= GCStipple; 3274#endif 3275 relief->gc = XCreateGC (NULL, FRAME_MAC_WINDOW (f), mask, &xgcv); 3276 } 3277 else 3278 XChangeGC (NULL, relief->gc, mask, &xgcv); 3279} 3280 3281 3282/* Set up colors for the relief lines around glyph string S. */ 3283 3284static void 3285x_setup_relief_colors (s) 3286 struct glyph_string *s; 3287{ 3288 struct mac_output *di = s->f->output_data.mac; 3289 unsigned long color; 3290 3291 if (s->face->use_box_color_for_shadows_p) 3292 color = s->face->box_color; 3293 else if (s->first_glyph->type == IMAGE_GLYPH 3294 && s->img->pixmap 3295 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0)) 3296 color = IMAGE_BACKGROUND (s->img, s->f, 0); 3297 else 3298 { 3299 XGCValues xgcv; 3300 3301 /* Get the background color of the face. */ 3302 XGetGCValues (s->display, s->gc, GCBackground, &xgcv); 3303 color = xgcv.background; 3304 } 3305 3306 if (di->white_relief.gc == 0 3307 || color != di->relief_background) 3308 { 3309 di->relief_background = color; 3310 x_setup_relief_color (s->f, &di->white_relief, 1.2, 0x8000, 3311 WHITE_PIX_DEFAULT (s->f)); 3312 x_setup_relief_color (s->f, &di->black_relief, 0.6, 0x4000, 3313 BLACK_PIX_DEFAULT (s->f)); 3314 } 3315} 3316 3317 3318/* Draw a relief on frame F inside the rectangle given by LEFT_X, 3319 TOP_Y, RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the relief 3320 to draw, it must be >= 0. RAISED_P non-zero means draw a raised 3321 relief. LEFT_P non-zero means draw a relief on the left side of 3322 the rectangle. RIGHT_P non-zero means draw a relief on the right 3323 side of the rectangle. CLIP_RECT is the clipping rectangle to use 3324 when drawing. */ 3325 3326static void 3327x_draw_relief_rect (f, left_x, top_y, right_x, bottom_y, width, 3328 raised_p, top_p, bot_p, left_p, right_p, clip_rect) 3329 struct frame *f; 3330 int left_x, top_y, right_x, bottom_y, width; 3331 int top_p, bot_p, left_p, right_p, raised_p; 3332 Rect *clip_rect; 3333{ 3334 Display *dpy = FRAME_MAC_DISPLAY (f); 3335 int i; 3336 GC gc; 3337 3338 if (raised_p) 3339 gc = f->output_data.mac->white_relief.gc; 3340 else 3341 gc = f->output_data.mac->black_relief.gc; 3342 mac_set_clip_rectangles (dpy, gc, clip_rect, 1); 3343 3344 /* Top. */ 3345 if (top_p) 3346 for (i = 0; i < width; ++i) 3347 mac_draw_line (f, gc, 3348 left_x + i * left_p, top_y + i, 3349 right_x + 1 - i * right_p, top_y + i); 3350 3351 /* Left. */ 3352 if (left_p) 3353 for (i = 0; i < width; ++i) 3354 mac_draw_line (f, gc, 3355 left_x + i, top_y + i, left_x + i, bottom_y - i + 1); 3356 3357 mac_reset_clip_rectangles (dpy, gc); 3358 if (raised_p) 3359 gc = f->output_data.mac->black_relief.gc; 3360 else 3361 gc = f->output_data.mac->white_relief.gc; 3362 mac_set_clip_rectangles (dpy, gc, clip_rect, 1); 3363 3364 /* Bottom. */ 3365 if (bot_p) 3366 for (i = 0; i < width; ++i) 3367 mac_draw_line (f, gc, 3368 left_x + i * left_p, bottom_y - i, 3369 right_x + 1 - i * right_p, bottom_y - i); 3370 3371 /* Right. */ 3372 if (right_p) 3373 for (i = 0; i < width; ++i) 3374 mac_draw_line (f, gc, 3375 right_x - i, top_y + i + 1, right_x - i, bottom_y - i); 3376 3377 mac_reset_clip_rectangles (dpy, gc); 3378} 3379 3380 3381/* Draw a box on frame F inside the rectangle given by LEFT_X, TOP_Y, 3382 RIGHT_X, and BOTTOM_Y. WIDTH is the thickness of the lines to 3383 draw, it must be >= 0. LEFT_P non-zero means draw a line on the 3384 left side of the rectangle. RIGHT_P non-zero means draw a line 3385 on the right side of the rectangle. CLIP_RECT is the clipping 3386 rectangle to use when drawing. */ 3387 3388static void 3389x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width, 3390 left_p, right_p, clip_rect) 3391 struct glyph_string *s; 3392 int left_x, top_y, right_x, bottom_y, width, left_p, right_p; 3393 Rect *clip_rect; 3394{ 3395 XGCValues xgcv; 3396 3397 XGetGCValues (s->display, s->gc, GCForeground, &xgcv); 3398 XSetForeground (s->display, s->gc, s->face->box_color); 3399 mac_set_clip_rectangles (s->display, s->gc, clip_rect, 1); 3400 3401 /* Top. */ 3402 mac_fill_rectangle (s->f, s->gc, left_x, top_y, 3403 right_x - left_x + 1, width); 3404 3405 /* Left. */ 3406 if (left_p) 3407 mac_fill_rectangle (s->f, s->gc, left_x, top_y, 3408 width, bottom_y - top_y + 1); 3409 3410 /* Bottom. */ 3411 mac_fill_rectangle (s->f, s->gc, left_x, bottom_y - width + 1, 3412 right_x - left_x + 1, width); 3413 3414 /* Right. */ 3415 if (right_p) 3416 mac_fill_rectangle (s->f, s->gc, right_x - width + 1, 3417 top_y, width, bottom_y - top_y + 1); 3418 3419 XSetForeground (s->display, s->gc, xgcv.foreground); 3420 mac_reset_clip_rectangles (s->display, s->gc); 3421} 3422 3423 3424/* Draw a box around glyph string S. */ 3425 3426static void 3427x_draw_glyph_string_box (s) 3428 struct glyph_string *s; 3429{ 3430 int width, left_x, right_x, top_y, bottom_y, last_x, raised_p; 3431 int left_p, right_p; 3432 struct glyph *last_glyph; 3433 Rect clip_rect; 3434 3435 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p) 3436 ? WINDOW_RIGHT_EDGE_X (s->w) 3437 : window_box_right (s->w, s->area)); 3438 3439 /* The glyph that may have a right box line. */ 3440 last_glyph = (s->cmp || s->img 3441 ? s->first_glyph 3442 : s->first_glyph + s->nchars - 1); 3443 3444 width = abs (s->face->box_line_width); 3445 raised_p = s->face->box == FACE_RAISED_BOX; 3446 left_x = s->x; 3447 right_x = (s->row->full_width_p && s->extends_to_end_of_line_p 3448 ? last_x - 1 3449 : min (last_x, s->x + s->background_width) - 1); 3450 top_y = s->y; 3451 bottom_y = top_y + s->height - 1; 3452 3453 left_p = (s->first_glyph->left_box_line_p 3454 || (s->hl == DRAW_MOUSE_FACE 3455 && (s->prev == NULL 3456 || s->prev->hl != s->hl))); 3457 right_p = (last_glyph->right_box_line_p 3458 || (s->hl == DRAW_MOUSE_FACE 3459 && (s->next == NULL 3460 || s->next->hl != s->hl))); 3461 3462 get_glyph_string_clip_rect (s, &clip_rect); 3463 3464 if (s->face->box == FACE_SIMPLE_BOX) 3465 x_draw_box_rect (s, left_x, top_y, right_x, bottom_y, width, 3466 left_p, right_p, &clip_rect); 3467 else 3468 { 3469 x_setup_relief_colors (s); 3470 x_draw_relief_rect (s->f, left_x, top_y, right_x, bottom_y, 3471 width, raised_p, 1, 1, left_p, right_p, &clip_rect); 3472 } 3473} 3474 3475 3476/* Draw foreground of image glyph string S. */ 3477 3478static void 3479x_draw_image_foreground (s) 3480 struct glyph_string *s; 3481{ 3482 int x = s->x; 3483 int y = s->ybase - image_ascent (s->img, s->face, &s->slice); 3484 3485 /* If first glyph of S has a left box line, start drawing it to the 3486 right of that line. */ 3487 if (s->face->box != FACE_NO_BOX 3488 && s->first_glyph->left_box_line_p 3489 && s->slice.x == 0) 3490 x += abs (s->face->box_line_width); 3491 3492 /* If there is a margin around the image, adjust x- and y-position 3493 by that margin. */ 3494 if (s->slice.x == 0) 3495 x += s->img->hmargin; 3496 if (s->slice.y == 0) 3497 y += s->img->vmargin; 3498 3499 if (s->img->pixmap) 3500 { 3501 x_set_glyph_string_clipping (s); 3502 3503#if USE_CG_DRAWING 3504 mac_draw_cg_image (s->img->data.ptr_val, 3505 s->f, s->gc, s->slice.x, s->slice.y, 3506 s->slice.width, s->slice.height, x, y, 1); 3507#endif 3508 if (s->img->mask) 3509#if !USE_CG_DRAWING 3510 mac_copy_area_with_mask (s->img->pixmap, s->img->mask, 3511 s->f, s->gc, s->slice.x, s->slice.y, 3512 s->slice.width, s->slice.height, x, y); 3513#else 3514 ; 3515#endif 3516 else 3517 { 3518#if !USE_CG_DRAWING 3519 mac_copy_area (s->img->pixmap, 3520 s->f, s->gc, s->slice.x, s->slice.y, 3521 s->slice.width, s->slice.height, x, y); 3522#endif 3523 3524 /* When the image has a mask, we can expect that at 3525 least part of a mouse highlight or a block cursor will 3526 be visible. If the image doesn't have a mask, make 3527 a block cursor visible by drawing a rectangle around 3528 the image. I believe it's looking better if we do 3529 nothing here for mouse-face. */ 3530 if (s->hl == DRAW_CURSOR) 3531 { 3532 int r = s->img->relief; 3533 if (r < 0) r = -r; 3534 mac_draw_rectangle (s->f, s->gc, x - r, y - r, 3535 s->slice.width + r*2 - 1, 3536 s->slice.height + r*2 - 1); 3537 } 3538 } 3539 } 3540 else 3541 /* Draw a rectangle if image could not be loaded. */ 3542 mac_draw_rectangle (s->f, s->gc, x, y, 3543 s->slice.width - 1, s->slice.height - 1); 3544} 3545 3546 3547/* Draw a relief around the image glyph string S. */ 3548 3549static void 3550x_draw_image_relief (s) 3551 struct glyph_string *s; 3552{ 3553 int x0, y0, x1, y1, thick, raised_p; 3554 Rect r; 3555 int x = s->x; 3556 int y = s->ybase - image_ascent (s->img, s->face, &s->slice); 3557 3558 /* If first glyph of S has a left box line, start drawing it to the 3559 right of that line. */ 3560 if (s->face->box != FACE_NO_BOX 3561 && s->first_glyph->left_box_line_p 3562 && s->slice.x == 0) 3563 x += abs (s->face->box_line_width); 3564 3565 /* If there is a margin around the image, adjust x- and y-position 3566 by that margin. */ 3567 if (s->slice.x == 0) 3568 x += s->img->hmargin; 3569 if (s->slice.y == 0) 3570 y += s->img->vmargin; 3571 3572 if (s->hl == DRAW_IMAGE_SUNKEN 3573 || s->hl == DRAW_IMAGE_RAISED) 3574 { 3575 thick = tool_bar_button_relief >= 0 ? tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF; 3576 raised_p = s->hl == DRAW_IMAGE_RAISED; 3577 } 3578 else 3579 { 3580 thick = abs (s->img->relief); 3581 raised_p = s->img->relief > 0; 3582 } 3583 3584 x0 = x - thick; 3585 y0 = y - thick; 3586 x1 = x + s->slice.width + thick - 1; 3587 y1 = y + s->slice.height + thick - 1; 3588 3589 x_setup_relief_colors (s); 3590 get_glyph_string_clip_rect (s, &r); 3591 x_draw_relief_rect (s->f, x0, y0, x1, y1, thick, raised_p, 3592 s->slice.y == 0, 3593 s->slice.y + s->slice.height == s->img->height, 3594 s->slice.x == 0, 3595 s->slice.x + s->slice.width == s->img->width, 3596 &r); 3597} 3598 3599 3600/* Draw part of the background of glyph string S. X, Y, W, and H 3601 give the rectangle to draw. */ 3602 3603static void 3604x_draw_glyph_string_bg_rect (s, x, y, w, h) 3605 struct glyph_string *s; 3606 int x, y, w, h; 3607{ 3608#if 0 /* MAC_TODO: stipple */ 3609 if (s->stippled_p) 3610 { 3611 /* Fill background with a stipple pattern. */ 3612 XSetFillStyle (s->display, s->gc, FillOpaqueStippled); 3613 XFillRectangle (s->display, s->window, s->gc, x, y, w, h); 3614 XSetFillStyle (s->display, s->gc, FillSolid); 3615 } 3616 else 3617#endif /* MAC_TODO */ 3618 x_clear_glyph_string_rect (s, x, y, w, h); 3619} 3620 3621 3622/* Draw image glyph string S. 3623 3624 s->y 3625 s->x +------------------------- 3626 | s->face->box 3627 | 3628 | +------------------------- 3629 | | s->img->margin 3630 | | 3631 | | +------------------- 3632 | | | the image 3633 3634 */ 3635 3636static void 3637x_draw_image_glyph_string (s) 3638 struct glyph_string *s; 3639{ 3640 int x, y; 3641 int box_line_hwidth = abs (s->face->box_line_width); 3642 int box_line_vwidth = max (s->face->box_line_width, 0); 3643 int height; 3644 3645 height = s->height - 2 * box_line_vwidth; 3646 3647 3648 /* Fill background with face under the image. Do it only if row is 3649 taller than image or if image has a clip mask to reduce 3650 flickering. */ 3651 s->stippled_p = s->face->stipple != 0; 3652 if (height > s->slice.height 3653 || s->img->hmargin 3654 || s->img->vmargin 3655 || s->img->mask 3656 || s->img->pixmap == 0 3657 || s->width != s->background_width) 3658 { 3659 x = s->x; 3660 if (s->first_glyph->left_box_line_p 3661 && s->slice.x == 0) 3662 x += box_line_hwidth; 3663 3664 y = s->y; 3665 if (s->slice.y == 0) 3666 y += box_line_vwidth; 3667 3668 x_draw_glyph_string_bg_rect (s, x, y, s->background_width, height); 3669 3670 s->background_filled_p = 1; 3671 } 3672 3673 /* Draw the foreground. */ 3674 x_draw_image_foreground (s); 3675 3676 /* If we must draw a relief around the image, do it. */ 3677 if (s->img->relief 3678 || s->hl == DRAW_IMAGE_RAISED 3679 || s->hl == DRAW_IMAGE_SUNKEN) 3680 x_draw_image_relief (s); 3681} 3682 3683 3684/* Draw stretch glyph string S. */ 3685 3686static void 3687x_draw_stretch_glyph_string (s) 3688 struct glyph_string *s; 3689{ 3690 xassert (s->first_glyph->type == STRETCH_GLYPH); 3691 s->stippled_p = s->face->stipple != 0; 3692 3693 if (s->hl == DRAW_CURSOR 3694 && !x_stretch_cursor_p) 3695 { 3696 /* If `x-stretch-block-cursor' is nil, don't draw a block cursor 3697 as wide as the stretch glyph. */ 3698 int width, background_width = s->background_width; 3699 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA); 3700 3701 if (x < left_x) 3702 { 3703 background_width -= left_x - x; 3704 x = left_x; 3705 } 3706 width = min (FRAME_COLUMN_WIDTH (s->f), background_width); 3707 3708 /* Draw cursor. */ 3709 x_draw_glyph_string_bg_rect (s, x, s->y, width, s->height); 3710 3711 /* Clear rest using the GC of the original non-cursor face. */ 3712 if (width < background_width) 3713 { 3714 int y = s->y; 3715 int w = background_width - width, h = s->height; 3716 Rect r; 3717 GC gc; 3718 3719 x += width; 3720 if (s->row->mouse_face_p 3721 && cursor_in_mouse_face_p (s->w)) 3722 { 3723 x_set_mouse_face_gc (s); 3724 gc = s->gc; 3725 } 3726 else 3727 gc = s->face->gc; 3728 3729 get_glyph_string_clip_rect (s, &r); 3730 mac_set_clip_rectangles (s->display, gc, &r, 1); 3731 3732#if 0 /* MAC_TODO: stipple */ 3733 if (s->face->stipple) 3734 { 3735 /* Fill background with a stipple pattern. */ 3736 XSetFillStyle (s->display, gc, FillOpaqueStippled); 3737 XFillRectangle (s->display, s->window, gc, x, y, w, h); 3738 XSetFillStyle (s->display, gc, FillSolid); 3739 } 3740 else 3741#endif /* MAC_TODO */ 3742 mac_erase_rectangle (s->f, gc, x, y, w, h); 3743 } 3744 } 3745 else if (!s->background_filled_p) 3746 { 3747 int background_width = s->background_width; 3748 int x = s->x, left_x = window_box_left_offset (s->w, TEXT_AREA); 3749 3750 /* Don't draw into left margin, fringe or scrollbar area 3751 except for header line and mode line. */ 3752 if (x < left_x && !s->row->mode_line_p) 3753 { 3754 background_width -= left_x - x; 3755 x = left_x; 3756 } 3757 if (background_width > 0) 3758 x_draw_glyph_string_bg_rect (s, x, s->y, background_width, s->height); 3759 } 3760 3761 s->background_filled_p = 1; 3762} 3763 3764 3765/* Draw glyph string S. */ 3766 3767static void 3768x_draw_glyph_string (s) 3769 struct glyph_string *s; 3770{ 3771 int relief_drawn_p = 0; 3772 3773 /* If S draws into the background of its successor that does not 3774 draw a cursor, draw the background of the successor first so that 3775 S can draw into it. This makes S->next use XDrawString instead 3776 of XDrawImageString. */ 3777 if (s->next && s->right_overhang && !s->for_overlaps 3778 && s->next->hl != DRAW_CURSOR) 3779 { 3780 xassert (s->next->img == NULL); 3781 x_set_glyph_string_gc (s->next); 3782 x_set_glyph_string_clipping (s->next); 3783 x_draw_glyph_string_background (s->next, 1); 3784 } 3785 3786 /* Set up S->gc, set clipping and draw S. */ 3787 x_set_glyph_string_gc (s); 3788 3789 /* Draw relief (if any) in advance for char/composition so that the 3790 glyph string can be drawn over it. */ 3791 if (!s->for_overlaps 3792 && s->face->box != FACE_NO_BOX 3793 && (s->first_glyph->type == CHAR_GLYPH 3794 || s->first_glyph->type == COMPOSITE_GLYPH)) 3795 3796 { 3797 x_set_glyph_string_clipping (s); 3798 x_draw_glyph_string_background (s, 1); 3799 x_draw_glyph_string_box (s); 3800 x_set_glyph_string_clipping (s); 3801 relief_drawn_p = 1; 3802 } 3803 else 3804 x_set_glyph_string_clipping (s); 3805 3806 switch (s->first_glyph->type) 3807 { 3808 case IMAGE_GLYPH: 3809 x_draw_image_glyph_string (s); 3810 break; 3811 3812 case STRETCH_GLYPH: 3813 x_draw_stretch_glyph_string (s); 3814 break; 3815 3816 case CHAR_GLYPH: 3817 if (s->for_overlaps) 3818 s->background_filled_p = 1; 3819 else 3820 x_draw_glyph_string_background (s, 0); 3821 x_draw_glyph_string_foreground (s); 3822 break; 3823 3824 case COMPOSITE_GLYPH: 3825 if (s->for_overlaps || s->gidx > 0) 3826 s->background_filled_p = 1; 3827 else 3828 x_draw_glyph_string_background (s, 1); 3829 x_draw_composite_glyph_string_foreground (s); 3830 break; 3831 3832 default: 3833 abort (); 3834 } 3835 3836 if (!s->for_overlaps) 3837 { 3838 /* Draw underline. */ 3839 if (s->face->underline_p) 3840 { 3841 unsigned long tem, h; 3842 int y; 3843 3844#if 0 3845 /* Get the underline thickness. Default is 1 pixel. */ 3846 if (!XGetFontProperty (s->font, XA_UNDERLINE_THICKNESS, &h)) 3847#endif 3848 h = 1; 3849 3850 y = s->y + s->height - h; 3851 if (!x_underline_at_descent_line) 3852 { 3853 /* Get the underline position. This is the recommended 3854 vertical offset in pixels from the baseline to the top of 3855 the underline. This is a signed value according to the 3856 specs, and its default is 3857 3858 ROUND ((maximum descent) / 2), with 3859 ROUND(x) = floor (x + 0.5) */ 3860 3861#if 0 3862 if (x_use_underline_position_properties 3863 && XGetFontProperty (s->font, XA_UNDERLINE_POSITION, &tem)) 3864 y = s->ybase + (long) tem; 3865 else 3866#endif 3867 if (s->face->font) 3868 y = s->ybase + (s->face->font->max_bounds.descent + 1) / 2; 3869 } 3870 3871 if (s->face->underline_defaulted_p) 3872 mac_fill_rectangle (s->f, s->gc, s->x, y, 3873 s->background_width, h); 3874 else 3875 { 3876 XGCValues xgcv; 3877 XGetGCValues (s->display, s->gc, GCForeground, &xgcv); 3878 XSetForeground (s->display, s->gc, s->face->underline_color); 3879 mac_fill_rectangle (s->f, s->gc, s->x, y, 3880 s->background_width, h); 3881 XSetForeground (s->display, s->gc, xgcv.foreground); 3882 } 3883 } 3884 3885 /* Draw overline. */ 3886 if (s->face->overline_p) 3887 { 3888 unsigned long dy = 0, h = 1; 3889 3890 if (s->face->overline_color_defaulted_p) 3891 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy, 3892 s->background_width, h); 3893 else 3894 { 3895 XGCValues xgcv; 3896 XGetGCValues (s->display, s->gc, GCForeground, &xgcv); 3897 XSetForeground (s->display, s->gc, s->face->overline_color); 3898 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy, 3899 s->background_width, h); 3900 XSetForeground (s->display, s->gc, xgcv.foreground); 3901 } 3902 } 3903 3904 /* Draw strike-through. */ 3905 if (s->face->strike_through_p) 3906 { 3907 unsigned long h = 1; 3908 unsigned long dy = (s->height - h) / 2; 3909 3910 if (s->face->strike_through_color_defaulted_p) 3911 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy, 3912 s->width, h); 3913 else 3914 { 3915 XGCValues xgcv; 3916 XGetGCValues (s->display, s->gc, GCForeground, &xgcv); 3917 XSetForeground (s->display, s->gc, s->face->strike_through_color); 3918 mac_fill_rectangle (s->f, s->gc, s->x, s->y + dy, 3919 s->width, h); 3920 XSetForeground (s->display, s->gc, xgcv.foreground); 3921 } 3922 } 3923 3924 /* Draw relief if not yet drawn. */ 3925 if (!relief_drawn_p && s->face->box != FACE_NO_BOX) 3926 x_draw_glyph_string_box (s); 3927 } 3928 3929 /* Reset clipping. */ 3930 mac_reset_clip_rectangles (s->display, s->gc); 3931} 3932 3933/* Shift display to make room for inserted glyphs. */ 3934 3935void 3936mac_shift_glyphs_for_insert (f, x, y, width, height, shift_by) 3937 struct frame *f; 3938 int x, y, width, height, shift_by; 3939{ 3940 mac_scroll_area (f, f->output_data.mac->normal_gc, 3941 x, y, width, height, 3942 x + shift_by, y); 3943} 3944 3945/* Delete N glyphs at the nominal cursor position. Not implemented 3946 for X frames. */ 3947 3948static void 3949x_delete_glyphs (n) 3950 register int n; 3951{ 3952 abort (); 3953} 3954 3955 3956/* Clear entire frame. If updating_frame is non-null, clear that 3957 frame. Otherwise clear the selected frame. */ 3958 3959static void 3960x_clear_frame () 3961{ 3962 struct frame *f; 3963 3964 if (updating_frame) 3965 f = updating_frame; 3966 else 3967 f = SELECTED_FRAME (); 3968 3969 /* Clearing the frame will erase any cursor, so mark them all as no 3970 longer visible. */ 3971 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f))); 3972 output_cursor.hpos = output_cursor.vpos = 0; 3973 output_cursor.x = -1; 3974 3975 /* We don't set the output cursor here because there will always 3976 follow an explicit cursor_to. */ 3977 BLOCK_INPUT; 3978 mac_clear_window (f); 3979 3980 /* We have to clear the scroll bars, too. If we have changed 3981 colors or something like that, then they should be notified. */ 3982 x_scroll_bar_clear (f); 3983 3984 XFlush (FRAME_MAC_DISPLAY (f)); 3985 UNBLOCK_INPUT; 3986} 3987 3988 3989 3990/* Invert the middle quarter of the frame for .15 sec. */ 3991 3992/* We use the select system call to do the waiting, so we have to make 3993 sure it's available. If it isn't, we just won't do visual bells. */ 3994 3995#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) 3996 3997 3998/* Subtract the `struct timeval' values X and Y, storing the result in 3999 *RESULT. Return 1 if the difference is negative, otherwise 0. */ 4000 4001static int 4002timeval_subtract (result, x, y) 4003 struct timeval *result, x, y; 4004{ 4005 /* Perform the carry for the later subtraction by updating y. This 4006 is safer because on some systems the tv_sec member is unsigned. */ 4007 if (x.tv_usec < y.tv_usec) 4008 { 4009 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1; 4010 y.tv_usec -= 1000000 * nsec; 4011 y.tv_sec += nsec; 4012 } 4013 4014 if (x.tv_usec - y.tv_usec > 1000000) 4015 { 4016 int nsec = (y.tv_usec - x.tv_usec) / 1000000; 4017 y.tv_usec += 1000000 * nsec; 4018 y.tv_sec -= nsec; 4019 } 4020 4021 /* Compute the time remaining to wait. tv_usec is certainly 4022 positive. */ 4023 result->tv_sec = x.tv_sec - y.tv_sec; 4024 result->tv_usec = x.tv_usec - y.tv_usec; 4025 4026 /* Return indication of whether the result should be considered 4027 negative. */ 4028 return x.tv_sec < y.tv_sec; 4029} 4030 4031void 4032XTflash (f) 4033 struct frame *f; 4034{ 4035 /* Get the height not including a menu bar widget. */ 4036 int height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, FRAME_LINES (f)); 4037 /* Height of each line to flash. */ 4038 int flash_height = FRAME_LINE_HEIGHT (f); 4039 /* These will be the left and right margins of the rectangles. */ 4040 int flash_left = FRAME_INTERNAL_BORDER_WIDTH (f); 4041 int flash_right = FRAME_PIXEL_WIDTH (f) - FRAME_INTERNAL_BORDER_WIDTH (f); 4042 4043 int width; 4044 4045 /* Don't flash the area between a scroll bar and the frame 4046 edge it is next to. */ 4047 switch (FRAME_VERTICAL_SCROLL_BAR_TYPE (f)) 4048 { 4049 case vertical_scroll_bar_left: 4050 flash_left += VERTICAL_SCROLL_BAR_WIDTH_TRIM; 4051 break; 4052 4053 case vertical_scroll_bar_right: 4054 flash_right -= VERTICAL_SCROLL_BAR_WIDTH_TRIM; 4055 break; 4056 4057 default: 4058 break; 4059 } 4060 4061 width = flash_right - flash_left; 4062 4063 BLOCK_INPUT; 4064 4065 /* If window is tall, flash top and bottom line. */ 4066 if (height > 3 * FRAME_LINE_HEIGHT (f)) 4067 { 4068 mac_invert_rectangle (f, flash_left, 4069 (FRAME_INTERNAL_BORDER_WIDTH (f) 4070 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)), 4071 width, flash_height); 4072 mac_invert_rectangle (f, flash_left, 4073 (height - flash_height 4074 - FRAME_INTERNAL_BORDER_WIDTH (f)), 4075 width, flash_height); 4076 } 4077 else 4078 /* If it is short, flash it all. */ 4079 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f), 4080 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); 4081 4082 x_flush (f); 4083 4084 { 4085 struct timeval wakeup; 4086 4087 EMACS_GET_TIME (wakeup); 4088 4089 /* Compute time to wait until, propagating carry from usecs. */ 4090 wakeup.tv_usec += 150000; 4091 wakeup.tv_sec += (wakeup.tv_usec / 1000000); 4092 wakeup.tv_usec %= 1000000; 4093 4094 /* Keep waiting until past the time wakeup or any input gets 4095 available. */ 4096 while (! detect_input_pending ()) 4097 { 4098 struct timeval current; 4099 struct timeval timeout; 4100 4101 EMACS_GET_TIME (current); 4102 4103 /* Break if result would be negative. */ 4104 if (timeval_subtract (¤t, wakeup, current)) 4105 break; 4106 4107 /* How long `select' should wait. */ 4108 timeout.tv_sec = 0; 4109 timeout.tv_usec = 10000; 4110 4111 /* Try to wait that long--but we might wake up sooner. */ 4112 select (0, NULL, NULL, NULL, &timeout); 4113 } 4114 } 4115 4116 /* If window is tall, flash top and bottom line. */ 4117 if (height > 3 * FRAME_LINE_HEIGHT (f)) 4118 { 4119 mac_invert_rectangle (f, flash_left, 4120 (FRAME_INTERNAL_BORDER_WIDTH (f) 4121 + FRAME_TOOL_BAR_LINES (f) * FRAME_LINE_HEIGHT (f)), 4122 width, flash_height); 4123 mac_invert_rectangle (f, flash_left, 4124 (height - flash_height 4125 - FRAME_INTERNAL_BORDER_WIDTH (f)), 4126 width, flash_height); 4127 } 4128 else 4129 /* If it is short, flash it all. */ 4130 mac_invert_rectangle (f, flash_left, FRAME_INTERNAL_BORDER_WIDTH (f), 4131 width, height - 2 * FRAME_INTERNAL_BORDER_WIDTH (f)); 4132 4133 x_flush (f); 4134 4135 UNBLOCK_INPUT; 4136} 4137 4138#endif /* defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) */ 4139 4140 4141/* Make audible bell. */ 4142 4143void 4144XTring_bell () 4145{ 4146 struct frame *f = SELECTED_FRAME (); 4147 4148#if defined (HAVE_TIMEVAL) && defined (HAVE_SELECT) 4149 if (visible_bell) 4150 XTflash (f); 4151 else 4152#endif 4153 { 4154 BLOCK_INPUT; 4155 SysBeep (1); 4156 XFlush (FRAME_MAC_DISPLAY (f)); 4157 UNBLOCK_INPUT; 4158 } 4159} 4160 4161 4162/* Specify how many text lines, from the top of the window, 4163 should be affected by insert-lines and delete-lines operations. 4164 This, and those operations, are used only within an update 4165 that is bounded by calls to x_update_begin and x_update_end. */ 4166 4167static void 4168XTset_terminal_window (n) 4169 register int n; 4170{ 4171 /* This function intentionally left blank. */ 4172} 4173 4174 4175 4176/*********************************************************************** 4177 Line Dance 4178 ***********************************************************************/ 4179 4180/* Perform an insert-lines or delete-lines operation, inserting N 4181 lines or deleting -N lines at vertical position VPOS. */ 4182 4183static void 4184x_ins_del_lines (vpos, n) 4185 int vpos, n; 4186{ 4187 abort (); 4188} 4189 4190 4191/* Scroll part of the display as described by RUN. */ 4192 4193static void 4194x_scroll_run (w, run) 4195 struct window *w; 4196 struct run *run; 4197{ 4198 struct frame *f = XFRAME (w->frame); 4199 int x, y, width, height, from_y, to_y, bottom_y; 4200 4201 /* Get frame-relative bounding box of the text display area of W, 4202 without mode lines. Include in this box the left and right 4203 fringe of W. */ 4204 window_box (w, -1, &x, &y, &width, &height); 4205 4206 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y); 4207 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y); 4208 bottom_y = y + height; 4209 4210 if (to_y < from_y) 4211 { 4212 /* Scrolling up. Make sure we don't copy part of the mode 4213 line at the bottom. */ 4214 if (from_y + run->height > bottom_y) 4215 height = bottom_y - from_y; 4216 else 4217 height = run->height; 4218 } 4219 else 4220 { 4221 /* Scolling down. Make sure we don't copy over the mode line. 4222 at the bottom. */ 4223 if (to_y + run->height > bottom_y) 4224 height = bottom_y - to_y; 4225 else 4226 height = run->height; 4227 } 4228 4229 BLOCK_INPUT; 4230 4231 /* Cursor off. Will be switched on again in x_update_window_end. */ 4232 updated_window = w; 4233 x_clear_cursor (w); 4234 4235 mac_scroll_area (f, f->output_data.mac->normal_gc, 4236 x, from_y, 4237 width, height, 4238 x, to_y); 4239 4240 UNBLOCK_INPUT; 4241} 4242 4243 4244 4245/*********************************************************************** 4246 Exposure Events 4247 ***********************************************************************/ 4248 4249 4250static void 4251frame_highlight (f) 4252 struct frame *f; 4253{ 4254 OSErr err; 4255 ControlRef root_control; 4256 4257 BLOCK_INPUT; 4258 err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control); 4259 if (err == noErr) 4260 ActivateControl (root_control); 4261 UNBLOCK_INPUT; 4262 x_update_cursor (f, 1); 4263} 4264 4265static void 4266frame_unhighlight (f) 4267 struct frame *f; 4268{ 4269 OSErr err; 4270 ControlRef root_control; 4271 4272 BLOCK_INPUT; 4273 err = GetRootControl (FRAME_MAC_WINDOW (f), &root_control); 4274 if (err == noErr) 4275 DeactivateControl (root_control); 4276 UNBLOCK_INPUT; 4277 x_update_cursor (f, 1); 4278} 4279 4280/* The focus has changed. Update the frames as necessary to reflect 4281 the new situation. Note that we can't change the selected frame 4282 here, because the Lisp code we are interrupting might become confused. 4283 Each event gets marked with the frame in which it occurred, so the 4284 Lisp code can tell when the switch took place by examining the events. */ 4285 4286static void 4287x_new_focus_frame (dpyinfo, frame) 4288 struct x_display_info *dpyinfo; 4289 struct frame *frame; 4290{ 4291 struct frame *old_focus = dpyinfo->x_focus_frame; 4292 4293 if (frame != dpyinfo->x_focus_frame) 4294 { 4295 /* Set this before calling other routines, so that they see 4296 the correct value of x_focus_frame. */ 4297 dpyinfo->x_focus_frame = frame; 4298 4299 if (old_focus && old_focus->auto_lower) 4300 x_lower_frame (old_focus); 4301 4302#if 0 4303 selected_frame = frame; 4304 XSETFRAME (XWINDOW (selected_frame->selected_window)->frame, 4305 selected_frame); 4306 Fselect_window (selected_frame->selected_window, Qnil); 4307 choose_minibuf_frame (); 4308#endif /* ! 0 */ 4309 4310 if (dpyinfo->x_focus_frame && dpyinfo->x_focus_frame->auto_raise) 4311 pending_autoraise_frame = dpyinfo->x_focus_frame; 4312 else 4313 pending_autoraise_frame = 0; 4314 4315#if USE_MAC_FONT_PANEL 4316 if (frame) 4317 mac_set_font_info_for_selection (frame, DEFAULT_FACE_ID, 0); 4318#endif 4319 } 4320 4321 x_frame_rehighlight (dpyinfo); 4322} 4323 4324/* Handle FocusIn and FocusOut state changes for FRAME. 4325 If FRAME has focus and there exists more than one frame, puts 4326 a FOCUS_IN_EVENT into *BUFP. */ 4327 4328static void 4329mac_focus_changed (type, dpyinfo, frame, bufp) 4330 int type; 4331 struct mac_display_info *dpyinfo; 4332 struct frame *frame; 4333 struct input_event *bufp; 4334{ 4335 if (type == activeFlag) 4336 { 4337 if (dpyinfo->x_focus_event_frame != frame) 4338 { 4339 x_new_focus_frame (dpyinfo, frame); 4340 dpyinfo->x_focus_event_frame = frame; 4341 4342 /* Don't stop displaying the initial startup message 4343 for a switch-frame event we don't need. */ 4344 if (GC_NILP (Vterminal_frame) 4345 && GC_CONSP (Vframe_list) 4346 && !GC_NILP (XCDR (Vframe_list))) 4347 { 4348 bufp->kind = FOCUS_IN_EVENT; 4349 XSETFRAME (bufp->frame_or_window, frame); 4350 } 4351 } 4352 } 4353 else 4354 { 4355 if (dpyinfo->x_focus_event_frame == frame) 4356 { 4357 dpyinfo->x_focus_event_frame = 0; 4358 x_new_focus_frame (dpyinfo, 0); 4359 } 4360 } 4361} 4362 4363/* The focus may have changed. Figure out if it is a real focus change, 4364 by checking both FocusIn/Out and Enter/LeaveNotify events. 4365 4366 Returns FOCUS_IN_EVENT event in *BUFP. */ 4367 4368static void 4369x_detect_focus_change (dpyinfo, event, bufp) 4370 struct mac_display_info *dpyinfo; 4371 const EventRecord *event; 4372 struct input_event *bufp; 4373{ 4374 struct frame *frame; 4375 4376 frame = mac_window_to_frame ((WindowPtr) event->message); 4377 if (! frame) 4378 return; 4379 4380 /* On Mac, this is only called from focus events, so no switch needed. */ 4381 mac_focus_changed ((event->modifiers & activeFlag), 4382 dpyinfo, frame, bufp); 4383} 4384 4385 4386/* Handle an event saying the mouse has moved out of an Emacs frame. */ 4387 4388void 4389x_mouse_leave (dpyinfo) 4390 struct x_display_info *dpyinfo; 4391{ 4392 x_new_focus_frame (dpyinfo, dpyinfo->x_focus_event_frame); 4393} 4394 4395/* The focus has changed, or we have redirected a frame's focus to 4396 another frame (this happens when a frame uses a surrogate 4397 mini-buffer frame). Shift the highlight as appropriate. 4398 4399 The FRAME argument doesn't necessarily have anything to do with which 4400 frame is being highlighted or un-highlighted; we only use it to find 4401 the appropriate X display info. */ 4402 4403static void 4404XTframe_rehighlight (frame) 4405 struct frame *frame; 4406{ 4407 x_frame_rehighlight (FRAME_X_DISPLAY_INFO (frame)); 4408} 4409 4410static void 4411x_frame_rehighlight (dpyinfo) 4412 struct x_display_info *dpyinfo; 4413{ 4414 struct frame *old_highlight = dpyinfo->x_highlight_frame; 4415 4416 if (dpyinfo->x_focus_frame) 4417 { 4418 dpyinfo->x_highlight_frame 4419 = ((GC_FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))) 4420 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame)) 4421 : dpyinfo->x_focus_frame); 4422 if (! FRAME_LIVE_P (dpyinfo->x_highlight_frame)) 4423 { 4424 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil; 4425 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame; 4426 } 4427 } 4428 else 4429 dpyinfo->x_highlight_frame = 0; 4430 4431 if (dpyinfo->x_highlight_frame != old_highlight) 4432 { 4433 if (old_highlight) 4434 frame_unhighlight (old_highlight); 4435 if (dpyinfo->x_highlight_frame) 4436 frame_highlight (dpyinfo->x_highlight_frame); 4437 } 4438} 4439 4440 4441 4442/* Convert a keysym to its name. */ 4443 4444char * 4445x_get_keysym_name (keysym) 4446 int keysym; 4447{ 4448 char *value; 4449 4450 BLOCK_INPUT; 4451#if 0 4452 value = XKeysymToString (keysym); 4453#else 4454 value = 0; 4455#endif 4456 UNBLOCK_INPUT; 4457 4458 return value; 4459} 4460 4461 4462 4463/* Function to report a mouse movement to the mainstream Emacs code. 4464 The input handler calls this. 4465 4466 We have received a mouse movement event, which is given in *event. 4467 If the mouse is over a different glyph than it was last time, tell 4468 the mainstream emacs code by setting mouse_moved. If not, ask for 4469 another motion event, so we can check again the next time it moves. */ 4470 4471static Point last_mouse_motion_position; 4472static Lisp_Object last_mouse_motion_frame; 4473 4474static int 4475note_mouse_movement (frame, pos) 4476 FRAME_PTR frame; 4477 Point *pos; 4478{ 4479 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (frame); 4480#if TARGET_API_MAC_CARBON 4481 Rect r; 4482#endif 4483 4484 last_mouse_movement_time = TickCount () * (1000 / 60); /* to milliseconds */ 4485 last_mouse_motion_position = *pos; 4486 XSETFRAME (last_mouse_motion_frame, frame); 4487 4488 if (frame == dpyinfo->mouse_face_mouse_frame 4489#if TARGET_API_MAC_CARBON 4490 && !PtInRect (*pos, GetWindowPortBounds (FRAME_MAC_WINDOW (frame), &r)) 4491#else 4492 && !PtInRect (*pos, &FRAME_MAC_WINDOW (frame)->portRect) 4493#endif 4494 ) 4495 { 4496 /* This case corresponds to LeaveNotify in X11. If we move 4497 outside the frame, then we're certainly no longer on any text 4498 in the frame. */ 4499 clear_mouse_face (dpyinfo); 4500 dpyinfo->mouse_face_mouse_frame = 0; 4501 if (!dpyinfo->grabbed) 4502 rif->define_frame_cursor (frame, 4503 frame->output_data.mac->nontext_cursor); 4504 } 4505 4506 /* Has the mouse moved off the glyph it was on at the last sighting? */ 4507 if (frame != last_mouse_glyph_frame 4508 || !PtInRect (*pos, &last_mouse_glyph)) 4509 { 4510 frame->mouse_moved = 1; 4511 last_mouse_scroll_bar = Qnil; 4512 note_mouse_highlight (frame, pos->h, pos->v); 4513 /* Remember which glyph we're now on. */ 4514 remember_mouse_glyph (frame, pos->h, pos->v, &last_mouse_glyph); 4515 last_mouse_glyph_frame = frame; 4516 return 1; 4517 } 4518 4519 return 0; 4520} 4521 4522 4523/************************************************************************ 4524 Mouse Face 4525 ************************************************************************/ 4526 4527/* MAC TODO: This should be called from somewhere (or removed) ++KFS */ 4528 4529static void 4530redo_mouse_highlight () 4531{ 4532 if (!NILP (last_mouse_motion_frame) 4533 && FRAME_LIVE_P (XFRAME (last_mouse_motion_frame))) 4534 note_mouse_highlight (XFRAME (last_mouse_motion_frame), 4535 last_mouse_motion_position.h, 4536 last_mouse_motion_position.v); 4537} 4538 4539 4540static struct frame * 4541mac_focus_frame (dpyinfo) 4542 struct mac_display_info *dpyinfo; 4543{ 4544 if (dpyinfo->x_focus_frame) 4545 return dpyinfo->x_focus_frame; 4546 else 4547 /* Mac version may get events, such as a menu bar click, even when 4548 all the frames are invisible. In this case, we regard the 4549 event came to the selected frame. */ 4550 return SELECTED_FRAME (); 4551} 4552 4553 4554/* Return the current position of the mouse. 4555 *FP should be a frame which indicates which display to ask about. 4556 4557 If the mouse movement started in a scroll bar, set *FP, *BAR_WINDOW, 4558 and *PART to the frame, window, and scroll bar part that the mouse 4559 is over. Set *X and *Y to the portion and whole of the mouse's 4560 position on the scroll bar. 4561 4562 If the mouse movement started elsewhere, set *FP to the frame the 4563 mouse is on, *BAR_WINDOW to nil, and *X and *Y to the character cell 4564 the mouse is over. 4565 4566 Set *TIME to the server time-stamp for the time at which the mouse 4567 was at this position. 4568 4569 Don't store anything if we don't have a valid set of values to report. 4570 4571 This clears the mouse_moved flag, so we can wait for the next mouse 4572 movement. */ 4573 4574static void 4575XTmouse_position (fp, insist, bar_window, part, x, y, time) 4576 FRAME_PTR *fp; 4577 int insist; 4578 Lisp_Object *bar_window; 4579 enum scroll_bar_part *part; 4580 Lisp_Object *x, *y; 4581 unsigned long *time; 4582{ 4583 FRAME_PTR f1; 4584 4585 BLOCK_INPUT; 4586 4587 if (! NILP (last_mouse_scroll_bar) && insist == 0) 4588 x_scroll_bar_report_motion (fp, bar_window, part, x, y, time); 4589 else 4590 { 4591 Lisp_Object frame, tail; 4592 4593 /* Clear the mouse-moved flag for every frame on this display. */ 4594 FOR_EACH_FRAME (tail, frame) 4595 XFRAME (frame)->mouse_moved = 0; 4596 4597 last_mouse_scroll_bar = Qnil; 4598 4599 if (FRAME_MAC_DISPLAY_INFO (*fp)->grabbed && last_mouse_frame 4600 && FRAME_LIVE_P (last_mouse_frame)) 4601 f1 = last_mouse_frame; 4602 else 4603 f1 = mac_focus_frame (FRAME_MAC_DISPLAY_INFO (*fp)); 4604 4605 if (f1) 4606 { 4607 /* Ok, we found a frame. Store all the values. 4608 last_mouse_glyph is a rectangle used to reduce the 4609 generation of mouse events. To not miss any motion 4610 events, we must divide the frame into rectangles of the 4611 size of the smallest character that could be displayed 4612 on it, i.e. into the same rectangles that matrices on 4613 the frame are divided into. */ 4614 Point mouse_pos; 4615 4616 SetPortWindowPort (FRAME_MAC_WINDOW (f1)); 4617 GetMouse (&mouse_pos); 4618 remember_mouse_glyph (f1, mouse_pos.h, mouse_pos.v, 4619 &last_mouse_glyph); 4620 last_mouse_glyph_frame = f1; 4621 4622 *bar_window = Qnil; 4623 *part = 0; 4624 *fp = f1; 4625 XSETINT (*x, mouse_pos.h); 4626 XSETINT (*y, mouse_pos.v); 4627 *time = last_mouse_movement_time; 4628 } 4629 } 4630 4631 UNBLOCK_INPUT; 4632} 4633 4634 4635/************************************************************************ 4636 Toolkit scroll bars 4637 ************************************************************************/ 4638 4639#ifdef USE_TOOLKIT_SCROLL_BARS 4640 4641static pascal void scroll_bar_timer_callback P_ ((EventLoopTimerRef, void *)); 4642static OSStatus install_scroll_bar_timer P_ ((void)); 4643static OSStatus set_scroll_bar_timer P_ ((EventTimerInterval)); 4644static int control_part_code_to_scroll_bar_part P_ ((ControlPartCode)); 4645static void construct_scroll_bar_click P_ ((struct scroll_bar *, int, 4646 struct input_event *)); 4647static OSStatus get_control_part_bounds P_ ((ControlHandle, ControlPartCode, 4648 Rect *)); 4649static void x_scroll_bar_handle_press P_ ((struct scroll_bar *, 4650 ControlPartCode, Point, 4651 struct input_event *)); 4652static void x_scroll_bar_handle_release P_ ((struct scroll_bar *, 4653 struct input_event *)); 4654static void x_scroll_bar_handle_drag P_ ((WindowPtr, struct scroll_bar *, 4655 Point, struct input_event *)); 4656static void x_set_toolkit_scroll_bar_thumb P_ ((struct scroll_bar *, 4657 int, int, int)); 4658 4659/* Last scroll bar part sent in x_scroll_bar_handle_*. */ 4660 4661static int last_scroll_bar_part; 4662 4663static EventLoopTimerRef scroll_bar_timer; 4664 4665static int scroll_bar_timer_event_posted_p; 4666 4667#define SCROLL_BAR_FIRST_DELAY 0.5 4668#define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15) 4669 4670static pascal void 4671scroll_bar_timer_callback (timer, data) 4672 EventLoopTimerRef timer; 4673 void *data; 4674{ 4675 OSStatus err; 4676 4677 err = mac_post_mouse_moved_event (); 4678 if (err == noErr) 4679 scroll_bar_timer_event_posted_p = 1; 4680} 4681 4682static OSStatus 4683install_scroll_bar_timer () 4684{ 4685 static EventLoopTimerUPP scroll_bar_timer_callbackUPP = NULL; 4686 4687 if (scroll_bar_timer_callbackUPP == NULL) 4688 scroll_bar_timer_callbackUPP = 4689 NewEventLoopTimerUPP (scroll_bar_timer_callback); 4690 4691 if (scroll_bar_timer == NULL) 4692 /* Mac OS X and CarbonLib 1.5 and later allow us to specify 4693 kEventDurationForever as delays. */ 4694 return 4695 InstallEventLoopTimer (GetCurrentEventLoop (), 4696 kEventDurationForever, kEventDurationForever, 4697 scroll_bar_timer_callbackUPP, NULL, 4698 &scroll_bar_timer); 4699} 4700 4701static OSStatus 4702set_scroll_bar_timer (delay) 4703 EventTimerInterval delay; 4704{ 4705 if (scroll_bar_timer == NULL) 4706 install_scroll_bar_timer (); 4707 4708 scroll_bar_timer_event_posted_p = 0; 4709 4710 return SetEventLoopTimerNextFireTime (scroll_bar_timer, delay); 4711} 4712 4713static int 4714control_part_code_to_scroll_bar_part (part_code) 4715 ControlPartCode part_code; 4716{ 4717 switch (part_code) 4718 { 4719 case kControlUpButtonPart: return scroll_bar_up_arrow; 4720 case kControlDownButtonPart: return scroll_bar_down_arrow; 4721 case kControlPageUpPart: return scroll_bar_above_handle; 4722 case kControlPageDownPart: return scroll_bar_below_handle; 4723 case kControlIndicatorPart: return scroll_bar_handle; 4724 } 4725 4726 return -1; 4727} 4728 4729static void 4730construct_scroll_bar_click (bar, part, bufp) 4731 struct scroll_bar *bar; 4732 int part; 4733 struct input_event *bufp; 4734{ 4735 bufp->kind = SCROLL_BAR_CLICK_EVENT; 4736 bufp->frame_or_window = bar->window; 4737 bufp->arg = Qnil; 4738 bufp->part = part; 4739 bufp->code = 0; 4740 XSETINT (bufp->x, 0); 4741 XSETINT (bufp->y, 0); 4742 bufp->modifiers = 0; 4743} 4744 4745static OSStatus 4746get_control_part_bounds (ch, part_code, rect) 4747 ControlHandle ch; 4748 ControlPartCode part_code; 4749 Rect *rect; 4750{ 4751 RgnHandle region = NewRgn (); 4752 OSStatus err; 4753 4754 err = GetControlRegion (ch, part_code, region); 4755 if (err == noErr) 4756 GetRegionBounds (region, rect); 4757 DisposeRgn (region); 4758 4759 return err; 4760} 4761 4762static void 4763x_scroll_bar_handle_press (bar, part_code, mouse_pos, bufp) 4764 struct scroll_bar *bar; 4765 ControlPartCode part_code; 4766 Point mouse_pos; 4767 struct input_event *bufp; 4768{ 4769 int part = control_part_code_to_scroll_bar_part (part_code); 4770 4771 if (part < 0) 4772 return; 4773 4774 if (part != scroll_bar_handle) 4775 { 4776 construct_scroll_bar_click (bar, part, bufp); 4777 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), part_code); 4778 set_scroll_bar_timer (SCROLL_BAR_FIRST_DELAY); 4779 bar->dragging = Qnil; 4780 } 4781 else 4782 { 4783 Rect r; 4784 4785 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar), 4786 kControlIndicatorPart, &r); 4787 XSETINT (bar->dragging, - (mouse_pos.v - r.top) - 1); 4788 } 4789 4790 last_scroll_bar_part = part; 4791 tracked_scroll_bar = bar; 4792} 4793 4794static void 4795x_scroll_bar_handle_release (bar, bufp) 4796 struct scroll_bar *bar; 4797 struct input_event *bufp; 4798{ 4799 if (last_scroll_bar_part != scroll_bar_handle 4800 || (INTEGERP (bar->dragging) && XINT (bar->dragging) >= 0)) 4801 construct_scroll_bar_click (bar, scroll_bar_end_scroll, bufp); 4802 4803 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), 0); 4804 set_scroll_bar_timer (kEventDurationForever); 4805 4806 last_scroll_bar_part = -1; 4807 bar->dragging = Qnil; 4808 tracked_scroll_bar = NULL; 4809} 4810 4811static void 4812x_scroll_bar_handle_drag (win, bar, mouse_pos, bufp) 4813 WindowPtr win; 4814 struct scroll_bar *bar; 4815 Point mouse_pos; 4816 struct input_event *bufp; 4817{ 4818 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar); 4819 4820 if (last_scroll_bar_part == scroll_bar_handle) 4821 { 4822 int top, top_range; 4823 Rect r; 4824 4825 get_control_part_bounds (SCROLL_BAR_CONTROL_HANDLE (bar), 4826 kControlIndicatorPart, &r); 4827 4828 if (INTEGERP (bar->dragging) && XINT (bar->dragging) < 0) 4829 XSETINT (bar->dragging, - (XINT (bar->dragging) + 1)); 4830 4831 top = mouse_pos.v - XINT (bar->dragging) - XINT (bar->track_top); 4832 top_range = XINT (bar->track_height) - XINT (bar->min_handle); 4833 4834 if (top < 0) 4835 top = 0; 4836 if (top > top_range) 4837 top = top_range; 4838 4839 construct_scroll_bar_click (bar, scroll_bar_handle, bufp); 4840 XSETINT (bufp->x, top); 4841 XSETINT (bufp->y, top_range); 4842 } 4843 else 4844 { 4845 ControlPartCode part_code; 4846 int unhilite_p = 0, part; 4847 4848 if (ch != FindControlUnderMouse (mouse_pos, win, &part_code)) 4849 unhilite_p = 1; 4850 else 4851 { 4852 part = control_part_code_to_scroll_bar_part (part_code); 4853 4854 switch (last_scroll_bar_part) 4855 { 4856 case scroll_bar_above_handle: 4857 case scroll_bar_below_handle: 4858 if (part != scroll_bar_above_handle 4859 && part != scroll_bar_below_handle) 4860 unhilite_p = 1; 4861 break; 4862 4863 case scroll_bar_up_arrow: 4864 case scroll_bar_down_arrow: 4865 if (part != scroll_bar_up_arrow 4866 && part != scroll_bar_down_arrow) 4867 unhilite_p = 1; 4868 break; 4869 } 4870 } 4871 4872 if (unhilite_p) 4873 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), 0); 4874 else if (part != last_scroll_bar_part 4875 || scroll_bar_timer_event_posted_p) 4876 { 4877 construct_scroll_bar_click (bar, part, bufp); 4878 last_scroll_bar_part = part; 4879 HiliteControl (SCROLL_BAR_CONTROL_HANDLE (bar), part_code); 4880 set_scroll_bar_timer (SCROLL_BAR_CONTINUOUS_DELAY); 4881 } 4882 } 4883} 4884 4885/* Set the thumb size and position of scroll bar BAR. We are currently 4886 displaying PORTION out of a whole WHOLE, and our position POSITION. */ 4887 4888static void 4889x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole) 4890 struct scroll_bar *bar; 4891 int portion, position, whole; 4892{ 4893 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar); 4894 int value, viewsize, maximum; 4895 4896 if (XINT (bar->track_height) == 0) 4897 return; 4898 4899 if (whole <= portion) 4900 value = 0, viewsize = 1, maximum = 0; 4901 else 4902 { 4903 float scale; 4904 4905 maximum = XINT (bar->track_height) - XINT (bar->min_handle); 4906 scale = (float) maximum / (whole - portion); 4907 value = position * scale + 0.5f; 4908 viewsize = (int) (portion * scale + 0.5f) + XINT (bar->min_handle); 4909 } 4910 4911 BLOCK_INPUT; 4912 4913 if (GetControlViewSize (ch) != viewsize 4914 || GetControl32BitValue (ch) != value 4915 || GetControl32BitMaximum (ch) != maximum) 4916 { 4917 /* Temporarily hide the scroll bar to avoid multiple redraws. */ 4918 SetControlVisibility (ch, false, false); 4919 4920 SetControl32BitMaximum (ch, maximum); 4921 SetControl32BitValue (ch, value); 4922 SetControlViewSize (ch, viewsize); 4923 4924 SetControlVisibility (ch, true, true); 4925 } 4926 4927 UNBLOCK_INPUT; 4928} 4929 4930#endif /* USE_TOOLKIT_SCROLL_BARS */ 4931 4932 4933 4934/************************************************************************ 4935 Scroll bars, general 4936 ************************************************************************/ 4937 4938/* Create a scroll bar and return the scroll bar vector for it. W is 4939 the Emacs window on which to create the scroll bar. TOP, LEFT, 4940 WIDTH and HEIGHT are the pixel coordinates and dimensions of the 4941 scroll bar. */ 4942 4943static struct scroll_bar * 4944x_scroll_bar_create (w, top, left, width, height, disp_top, disp_height) 4945 struct window *w; 4946 int top, left, width, height, disp_top, disp_height; 4947{ 4948 struct frame *f = XFRAME (w->frame); 4949 struct scroll_bar *bar 4950 = XSCROLL_BAR (Fmake_vector (make_number (SCROLL_BAR_VEC_SIZE), Qnil)); 4951 Rect r; 4952 ControlHandle ch; 4953 4954 BLOCK_INPUT; 4955 4956 r.left = left; 4957 r.top = disp_top; 4958 r.right = left + width; 4959 r.bottom = disp_top + disp_height; 4960 4961#if USE_CG_DRAWING 4962 mac_prepare_for_quickdraw (f); 4963#endif 4964#if TARGET_API_MAC_CARBON 4965 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", 4966#ifdef USE_TOOLKIT_SCROLL_BARS 4967 false, 4968#else 4969 width < disp_height, 4970#endif 4971 0, 0, 0, kControlScrollBarProc, (long) bar); 4972#else 4973 ch = NewControl (FRAME_MAC_WINDOW (f), &r, "\p", width < disp_height, 4974 0, 0, 0, scrollBarProc, (long) bar); 4975#endif 4976 SET_SCROLL_BAR_CONTROL_HANDLE (bar, ch); 4977 4978 XSETWINDOW (bar->window, w); 4979 XSETINT (bar->top, top); 4980 XSETINT (bar->left, left); 4981 XSETINT (bar->width, width); 4982 XSETINT (bar->height, height); 4983 XSETINT (bar->start, 0); 4984 XSETINT (bar->end, 0); 4985 bar->dragging = Qnil; 4986#ifdef USE_TOOLKIT_SCROLL_BARS 4987 bar->track_top = Qnil; 4988 bar->track_height = Qnil; 4989 bar->min_handle = Qnil; 4990#endif 4991 4992 /* Add bar to its frame's list of scroll bars. */ 4993 bar->next = FRAME_SCROLL_BARS (f); 4994 bar->prev = Qnil; 4995 XSETVECTOR (FRAME_SCROLL_BARS (f), bar); 4996 if (!NILP (bar->next)) 4997 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar); 4998 4999 UNBLOCK_INPUT; 5000 return bar; 5001} 5002 5003 5004/* Draw BAR's handle in the proper position. 5005 5006 If the handle is already drawn from START to END, don't bother 5007 redrawing it, unless REBUILD is non-zero; in that case, always 5008 redraw it. (REBUILD is handy for drawing the handle after expose 5009 events.) 5010 5011 Normally, we want to constrain the start and end of the handle to 5012 fit inside its rectangle, but if the user is dragging the scroll 5013 bar handle, we want to let them drag it down all the way, so that 5014 the bar's top is as far down as it goes; otherwise, there's no way 5015 to move to the very end of the buffer. */ 5016 5017#ifndef USE_TOOLKIT_SCROLL_BARS 5018 5019static void 5020x_scroll_bar_set_handle (bar, start, end, rebuild) 5021 struct scroll_bar *bar; 5022 int start, end; 5023 int rebuild; 5024{ 5025 int dragging = ! NILP (bar->dragging); 5026 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar); 5027 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); 5028 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)); 5029 int length = end - start; 5030 5031 /* If the display is already accurate, do nothing. */ 5032 if (! rebuild 5033 && start == XINT (bar->start) 5034 && end == XINT (bar->end)) 5035 return; 5036 5037 BLOCK_INPUT; 5038 5039 /* Make sure the values are reasonable, and try to preserve the 5040 distance between start and end. */ 5041 if (start < 0) 5042 start = 0; 5043 else if (start > top_range) 5044 start = top_range; 5045 end = start + length; 5046 5047 if (end < start) 5048 end = start; 5049 else if (end > top_range && ! dragging) 5050 end = top_range; 5051 5052 /* Store the adjusted setting in the scroll bar. */ 5053 XSETINT (bar->start, start); 5054 XSETINT (bar->end, end); 5055 5056 /* Clip the end position, just for display. */ 5057 if (end > top_range) 5058 end = top_range; 5059 5060 /* Draw bottom positions VERTICAL_SCROLL_BAR_MIN_HANDLE pixels below 5061 top positions, to make sure the handle is always at least that 5062 many pixels tall. */ 5063 end += VERTICAL_SCROLL_BAR_MIN_HANDLE; 5064 5065 SetControlMinimum (ch, 0); 5066 /* Don't inadvertently activate deactivated scroll bars */ 5067 if (GetControlMaximum (ch) != -1) 5068 SetControlMaximum (ch, top_range + VERTICAL_SCROLL_BAR_MIN_HANDLE 5069 - (end - start)); 5070 SetControlValue (ch, start); 5071#if TARGET_API_MAC_CARBON 5072 SetControlViewSize (ch, end - start); 5073#endif 5074 5075 UNBLOCK_INPUT; 5076} 5077 5078#endif /* !USE_TOOLKIT_SCROLL_BARS */ 5079 5080/* Destroy scroll bar BAR, and set its Emacs window's scroll bar to 5081 nil. */ 5082 5083static void 5084x_scroll_bar_remove (bar) 5085 struct scroll_bar *bar; 5086{ 5087 FRAME_PTR f = XFRAME (WINDOW_FRAME (XWINDOW (bar->window))); 5088 5089 BLOCK_INPUT; 5090 5091#if USE_CG_DRAWING 5092 mac_prepare_for_quickdraw (f); 5093#endif 5094 /* Destroy the Mac scroll bar control */ 5095 DisposeControl (SCROLL_BAR_CONTROL_HANDLE (bar)); 5096 5097 /* Disassociate this scroll bar from its window. */ 5098 XWINDOW (bar->window)->vertical_scroll_bar = Qnil; 5099 5100 UNBLOCK_INPUT; 5101} 5102 5103 5104/* Set the handle of the vertical scroll bar for WINDOW to indicate 5105 that we are displaying PORTION characters out of a total of WHOLE 5106 characters, starting at POSITION. If WINDOW has no scroll bar, 5107 create one. */ 5108 5109static void 5110XTset_vertical_scroll_bar (w, portion, whole, position) 5111 struct window *w; 5112 int portion, whole, position; 5113{ 5114 struct frame *f = XFRAME (w->frame); 5115 struct scroll_bar *bar; 5116 int top, height, left, sb_left, width, sb_width, disp_top, disp_height; 5117 int window_y, window_height; 5118 5119 /* Get window dimensions. */ 5120 window_box (w, -1, 0, &window_y, 0, &window_height); 5121 top = window_y; 5122 width = WINDOW_CONFIG_SCROLL_BAR_COLS (w) * FRAME_COLUMN_WIDTH (f); 5123 height = window_height; 5124 5125 /* Compute the left edge of the scroll bar area. */ 5126 left = WINDOW_SCROLL_BAR_AREA_X (w); 5127 5128 /* Compute the width of the scroll bar which might be less than 5129 the width of the area reserved for the scroll bar. */ 5130 if (WINDOW_CONFIG_SCROLL_BAR_WIDTH (w) > 0) 5131 sb_width = WINDOW_CONFIG_SCROLL_BAR_WIDTH (w); 5132 else 5133 sb_width = width; 5134 5135 /* Compute the left edge of the scroll bar. */ 5136 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT (w)) 5137 sb_left = left; 5138 else 5139 sb_left = left + width - sb_width; 5140 5141 /* Adjustments according to Inside Macintosh to make it look nice */ 5142 disp_top = top; 5143 disp_height = height; 5144#ifdef MAC_OS8 5145 if (disp_top == 0) 5146 { 5147 disp_top = -1; 5148 disp_height++; 5149 } 5150 else if (disp_top == FRAME_PIXEL_HEIGHT (f) - 16) 5151 { 5152 disp_top++; 5153 disp_height--; 5154 } 5155 5156 if (sb_left + sb_width == FRAME_PIXEL_WIDTH (f)) 5157 sb_left++; 5158#endif 5159 5160 /* Does the scroll bar exist yet? */ 5161 if (NILP (w->vertical_scroll_bar)) 5162 { 5163 BLOCK_INPUT; 5164 mac_clear_area (f, left, top, width, height); 5165 UNBLOCK_INPUT; 5166 bar = x_scroll_bar_create (w, top, sb_left, sb_width, height, disp_top, 5167 disp_height); 5168 XSETVECTOR (w->vertical_scroll_bar, bar); 5169 } 5170 else 5171 { 5172 /* It may just need to be moved and resized. */ 5173 ControlHandle ch; 5174 5175 bar = XSCROLL_BAR (w->vertical_scroll_bar); 5176 ch = SCROLL_BAR_CONTROL_HANDLE (bar); 5177 5178 BLOCK_INPUT; 5179 5180 /* If already correctly positioned, do nothing. */ 5181 if (!(XINT (bar->left) == sb_left 5182 && XINT (bar->top) == top 5183 && XINT (bar->width) == sb_width 5184 && XINT (bar->height) == height)) 5185 { 5186 /* Since toolkit scroll bars are smaller than the space reserved 5187 for them on the frame, we have to clear "under" them. */ 5188 mac_clear_area (f, left, top, width, height); 5189 5190#if USE_CG_DRAWING 5191 mac_prepare_for_quickdraw (f); 5192#endif 5193 HideControl (ch); 5194 MoveControl (ch, sb_left + VERTICAL_SCROLL_BAR_WIDTH_TRIM, disp_top); 5195 SizeControl (ch, sb_width - VERTICAL_SCROLL_BAR_WIDTH_TRIM * 2, 5196 disp_height); 5197#ifndef USE_TOOLKIT_SCROLL_BARS 5198 if (sb_width < disp_height) 5199 ShowControl (ch); 5200#endif 5201 5202 /* Remember new settings. */ 5203 XSETINT (bar->left, sb_left); 5204 XSETINT (bar->top, top); 5205 XSETINT (bar->width, sb_width); 5206 XSETINT (bar->height, height); 5207#ifdef USE_TOOLKIT_SCROLL_BARS 5208 bar->track_top = Qnil; 5209 bar->track_height = Qnil; 5210 bar->min_handle = Qnil; 5211#endif 5212 } 5213 5214 UNBLOCK_INPUT; 5215 } 5216 5217#ifdef USE_TOOLKIT_SCROLL_BARS 5218 if (NILP (bar->track_top)) 5219 { 5220 if (sb_width >= disp_height 5221#ifdef MAC_OSX 5222 || sb_width < MAC_AQUA_SMALL_VERTICAL_SCROLL_BAR_WIDTH 5223#endif 5224 ) 5225 { 5226 XSETINT (bar->track_top, 0); 5227 XSETINT (bar->track_height, 0); 5228 XSETINT (bar->min_handle, 0); 5229 } 5230 else 5231 { 5232 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar); 5233 Rect r0, r1; 5234 5235 BLOCK_INPUT; 5236 5237 SetControl32BitMinimum (ch, 0); 5238 SetControl32BitMaximum (ch, 1 << 30); 5239 SetControlViewSize (ch, 1); 5240 5241 /* Move the scroll bar thumb to the top. */ 5242 SetControl32BitValue (ch, 0); 5243 get_control_part_bounds (ch, kControlIndicatorPart, &r0); 5244 5245 /* Move the scroll bar thumb to the bottom. */ 5246 SetControl32BitValue (ch, 1 << 30); 5247 get_control_part_bounds (ch, kControlIndicatorPart, &r1); 5248 5249 UnionRect (&r0, &r1, &r0); 5250 XSETINT (bar->track_top, r0.top); 5251 XSETINT (bar->track_height, r0.bottom - r0.top); 5252 XSETINT (bar->min_handle, r1.bottom - r1.top); 5253 5254 /* Don't show the scroll bar if its height is not enough to 5255 display the scroll bar thumb. */ 5256 if (r0.bottom - r0.top > 0) 5257 ShowControl (ch); 5258 5259 UNBLOCK_INPUT; 5260 } 5261 } 5262 5263 x_set_toolkit_scroll_bar_thumb (bar, portion, position, whole); 5264#else /* not USE_TOOLKIT_SCROLL_BARS */ 5265 /* Set the scroll bar's current state, unless we're currently being 5266 dragged. */ 5267 if (NILP (bar->dragging)) 5268 { 5269 int top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, height); 5270 5271 if (whole == 0) 5272 x_scroll_bar_set_handle (bar, 0, top_range, 0); 5273 else 5274 { 5275 int start = ((double) position * top_range) / whole; 5276 int end = ((double) (position + portion) * top_range) / whole; 5277 x_scroll_bar_set_handle (bar, start, end, 0); 5278 } 5279 } 5280#endif /* not USE_TOOLKIT_SCROLL_BARS */ 5281} 5282 5283 5284/* The following three hooks are used when we're doing a thorough 5285 redisplay of the frame. We don't explicitly know which scroll bars 5286 are going to be deleted, because keeping track of when windows go 5287 away is a real pain - "Can you say set-window-configuration, boys 5288 and girls?" Instead, we just assert at the beginning of redisplay 5289 that *all* scroll bars are to be removed, and then save a scroll bar 5290 from the fiery pit when we actually redisplay its window. */ 5291 5292/* Arrange for all scroll bars on FRAME to be removed at the next call 5293 to `*judge_scroll_bars_hook'. A scroll bar may be spared if 5294 `*redeem_scroll_bar_hook' is applied to its window before the judgment. */ 5295 5296static void 5297XTcondemn_scroll_bars (frame) 5298 FRAME_PTR frame; 5299{ 5300 /* Transfer all the scroll bars to FRAME_CONDEMNED_SCROLL_BARS. */ 5301 while (! NILP (FRAME_SCROLL_BARS (frame))) 5302 { 5303 Lisp_Object bar; 5304 bar = FRAME_SCROLL_BARS (frame); 5305 FRAME_SCROLL_BARS (frame) = XSCROLL_BAR (bar)->next; 5306 XSCROLL_BAR (bar)->next = FRAME_CONDEMNED_SCROLL_BARS (frame); 5307 XSCROLL_BAR (bar)->prev = Qnil; 5308 if (! NILP (FRAME_CONDEMNED_SCROLL_BARS (frame))) 5309 XSCROLL_BAR (FRAME_CONDEMNED_SCROLL_BARS (frame))->prev = bar; 5310 FRAME_CONDEMNED_SCROLL_BARS (frame) = bar; 5311 } 5312} 5313 5314 5315/* Un-mark WINDOW's scroll bar for deletion in this judgment cycle. 5316 Note that WINDOW isn't necessarily condemned at all. */ 5317 5318static void 5319XTredeem_scroll_bar (window) 5320 struct window *window; 5321{ 5322 struct scroll_bar *bar; 5323 struct frame *f; 5324 5325 /* We can't redeem this window's scroll bar if it doesn't have one. */ 5326 if (NILP (window->vertical_scroll_bar)) 5327 abort (); 5328 5329 bar = XSCROLL_BAR (window->vertical_scroll_bar); 5330 5331 /* Unlink it from the condemned list. */ 5332 f = XFRAME (WINDOW_FRAME (window)); 5333 if (NILP (bar->prev)) 5334 { 5335 /* If the prev pointer is nil, it must be the first in one of 5336 the lists. */ 5337 if (EQ (FRAME_SCROLL_BARS (f), window->vertical_scroll_bar)) 5338 /* It's not condemned. Everything's fine. */ 5339 return; 5340 else if (EQ (FRAME_CONDEMNED_SCROLL_BARS (f), 5341 window->vertical_scroll_bar)) 5342 FRAME_CONDEMNED_SCROLL_BARS (f) = bar->next; 5343 else 5344 /* If its prev pointer is nil, it must be at the front of 5345 one or the other! */ 5346 abort (); 5347 } 5348 else 5349 XSCROLL_BAR (bar->prev)->next = bar->next; 5350 5351 if (! NILP (bar->next)) 5352 XSCROLL_BAR (bar->next)->prev = bar->prev; 5353 5354 bar->next = FRAME_SCROLL_BARS (f); 5355 bar->prev = Qnil; 5356 XSETVECTOR (FRAME_SCROLL_BARS (f), bar); 5357 if (! NILP (bar->next)) 5358 XSETVECTOR (XSCROLL_BAR (bar->next)->prev, bar); 5359} 5360 5361/* Remove all scroll bars on FRAME that haven't been saved since the 5362 last call to `*condemn_scroll_bars_hook'. */ 5363 5364static void 5365XTjudge_scroll_bars (f) 5366 FRAME_PTR f; 5367{ 5368 Lisp_Object bar, next; 5369 5370 bar = FRAME_CONDEMNED_SCROLL_BARS (f); 5371 5372 /* Clear out the condemned list now so we won't try to process any 5373 more events on the hapless scroll bars. */ 5374 FRAME_CONDEMNED_SCROLL_BARS (f) = Qnil; 5375 5376 for (; ! NILP (bar); bar = next) 5377 { 5378 struct scroll_bar *b = XSCROLL_BAR (bar); 5379 5380 x_scroll_bar_remove (b); 5381 5382 next = b->next; 5383 b->next = b->prev = Qnil; 5384 } 5385 5386 /* Now there should be no references to the condemned scroll bars, 5387 and they should get garbage-collected. */ 5388} 5389 5390 5391/* Handle a mouse click on the scroll bar BAR. If *EMACS_EVENT's kind 5392 is set to something other than NO_EVENT, it is enqueued. 5393 5394 This may be called from a signal handler, so we have to ignore GC 5395 mark bits. */ 5396 5397static void 5398x_scroll_bar_handle_click (bar, part_code, er, bufp) 5399 struct scroll_bar *bar; 5400 ControlPartCode part_code; 5401 const EventRecord *er; 5402 struct input_event *bufp; 5403{ 5404 int win_y, top_range; 5405 5406 if (! GC_WINDOWP (bar->window)) 5407 abort (); 5408 5409 bufp->kind = SCROLL_BAR_CLICK_EVENT; 5410 bufp->frame_or_window = bar->window; 5411 bufp->arg = Qnil; 5412 5413 bar->dragging = Qnil; 5414 5415 switch (part_code) 5416 { 5417 case kControlUpButtonPart: 5418 bufp->part = scroll_bar_up_arrow; 5419 break; 5420 case kControlDownButtonPart: 5421 bufp->part = scroll_bar_down_arrow; 5422 break; 5423 case kControlPageUpPart: 5424 bufp->part = scroll_bar_above_handle; 5425 break; 5426 case kControlPageDownPart: 5427 bufp->part = scroll_bar_below_handle; 5428 break; 5429#if TARGET_API_MAC_CARBON 5430 default: 5431#else 5432 case kControlIndicatorPart: 5433#endif 5434 if (er->what == mouseDown) 5435 bar->dragging = make_number (0); 5436 XSETVECTOR (last_mouse_scroll_bar, bar); 5437 bufp->part = scroll_bar_handle; 5438 break; 5439 } 5440 5441 win_y = XINT (bufp->y) - XINT (bar->top); 5442 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (0/*dummy*/, XINT (bar->height)); 5443 5444 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER; 5445 5446 win_y -= 24; 5447 5448 if (! NILP (bar->dragging)) 5449 win_y -= XINT (bar->dragging); 5450 5451 if (win_y < 0) 5452 win_y = 0; 5453 if (win_y > top_range) 5454 win_y = top_range; 5455 5456 XSETINT (bufp->x, win_y); 5457 XSETINT (bufp->y, top_range); 5458} 5459 5460#ifndef USE_TOOLKIT_SCROLL_BARS 5461 5462/* Handle some mouse motion while someone is dragging the scroll bar. 5463 5464 This may be called from a signal handler, so we have to ignore GC 5465 mark bits. */ 5466 5467static void 5468x_scroll_bar_note_movement (bar, y_pos, t) 5469 struct scroll_bar *bar; 5470 int y_pos; 5471 Time t; 5472{ 5473 FRAME_PTR f = XFRAME (XWINDOW (bar->window)->frame); 5474 5475 last_mouse_movement_time = t; 5476 5477 f->mouse_moved = 1; 5478 XSETVECTOR (last_mouse_scroll_bar, bar); 5479 5480 /* If we're dragging the bar, display it. */ 5481 if (! GC_NILP (bar->dragging)) 5482 { 5483 /* Where should the handle be now? */ 5484 int new_start = y_pos - 24; 5485 5486 if (new_start != XINT (bar->start)) 5487 { 5488 int new_end = new_start + (XINT (bar->end) - XINT (bar->start)); 5489 5490 x_scroll_bar_set_handle (bar, new_start, new_end, 0); 5491 } 5492 } 5493} 5494 5495#endif /* !USE_TOOLKIT_SCROLL_BARS */ 5496 5497/* Return information to the user about the current position of the mouse 5498 on the scroll bar. */ 5499 5500static void 5501x_scroll_bar_report_motion (fp, bar_window, part, x, y, time) 5502 FRAME_PTR *fp; 5503 Lisp_Object *bar_window; 5504 enum scroll_bar_part *part; 5505 Lisp_Object *x, *y; 5506 unsigned long *time; 5507{ 5508 struct scroll_bar *bar = XSCROLL_BAR (last_mouse_scroll_bar); 5509 ControlHandle ch = SCROLL_BAR_CONTROL_HANDLE (bar); 5510#if TARGET_API_MAC_CARBON 5511 WindowPtr wp = GetControlOwner (ch); 5512#else 5513 WindowPtr wp = (*ch)->contrlOwner; 5514#endif 5515 Point mouse_pos; 5516 struct frame *f = mac_window_to_frame (wp); 5517 int win_y, top_range; 5518 5519 SetPortWindowPort (wp); 5520 5521 GetMouse (&mouse_pos); 5522 5523 win_y = mouse_pos.v - XINT (bar->top); 5524 top_range = VERTICAL_SCROLL_BAR_TOP_RANGE (f, XINT (bar->height)); 5525 5526 win_y -= VERTICAL_SCROLL_BAR_TOP_BORDER; 5527 5528 win_y -= 24; 5529 5530 if (! NILP (bar->dragging)) 5531 win_y -= XINT (bar->dragging); 5532 5533 if (win_y < 0) 5534 win_y = 0; 5535 if (win_y > top_range) 5536 win_y = top_range; 5537 5538 *fp = f; 5539 *bar_window = bar->window; 5540 5541 if (! NILP (bar->dragging)) 5542 *part = scroll_bar_handle; 5543 else if (win_y < XINT (bar->start)) 5544 *part = scroll_bar_above_handle; 5545 else if (win_y < XINT (bar->end) + VERTICAL_SCROLL_BAR_MIN_HANDLE) 5546 *part = scroll_bar_handle; 5547 else 5548 *part = scroll_bar_below_handle; 5549 5550 XSETINT (*x, win_y); 5551 XSETINT (*y, top_range); 5552 5553 f->mouse_moved = 0; 5554 last_mouse_scroll_bar = Qnil; 5555 5556 *time = last_mouse_movement_time; 5557} 5558 5559 5560/* The screen has been cleared so we may have changed foreground or 5561 background colors, and the scroll bars may need to be redrawn. 5562 Clear out the scroll bars, and ask for expose events, so we can 5563 redraw them. */ 5564 5565void 5566x_scroll_bar_clear (f) 5567 FRAME_PTR f; 5568{ 5569 XTcondemn_scroll_bars (f); 5570 XTjudge_scroll_bars (f); 5571} 5572 5573 5574/*********************************************************************** 5575 Text Cursor 5576 ***********************************************************************/ 5577 5578/* Set clipping for output in glyph row ROW. W is the window in which 5579 we operate. GC is the graphics context to set clipping in. 5580 5581 ROW may be a text row or, e.g., a mode line. Text rows must be 5582 clipped to the interior of the window dedicated to text display, 5583 mode lines must be clipped to the whole window. */ 5584 5585static void 5586x_clip_to_row (w, row, area, gc) 5587 struct window *w; 5588 struct glyph_row *row; 5589 int area; 5590 GC gc; 5591{ 5592 struct frame *f = XFRAME (WINDOW_FRAME (w)); 5593 Rect clip_rect; 5594 int window_x, window_y, window_width; 5595 5596 window_box (w, area, &window_x, &window_y, &window_width, 0); 5597 5598 clip_rect.left = window_x; 5599 clip_rect.top = WINDOW_TO_FRAME_PIXEL_Y (w, row->y); 5600 clip_rect.top = max (clip_rect.top, window_y); 5601 clip_rect.right = clip_rect.left + window_width; 5602 clip_rect.bottom = clip_rect.top + row->visible_height; 5603 5604 mac_set_clip_rectangles (FRAME_MAC_DISPLAY (f), gc, &clip_rect, 1); 5605} 5606 5607 5608/* Draw a hollow box cursor on window W in glyph row ROW. */ 5609 5610static void 5611x_draw_hollow_cursor (w, row) 5612 struct window *w; 5613 struct glyph_row *row; 5614{ 5615 struct frame *f = XFRAME (WINDOW_FRAME (w)); 5616 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f); 5617 Display *dpy = FRAME_MAC_DISPLAY (f); 5618 int x, y, wd, h; 5619 XGCValues xgcv; 5620 struct glyph *cursor_glyph; 5621 GC gc; 5622 5623 /* Get the glyph the cursor is on. If we can't tell because 5624 the current matrix is invalid or such, give up. */ 5625 cursor_glyph = get_phys_cursor_glyph (w); 5626 if (cursor_glyph == NULL) 5627 return; 5628 5629 /* Compute frame-relative coordinates for phys cursor. */ 5630 get_phys_cursor_geometry (w, row, cursor_glyph, &x, &y, &h); 5631 wd = w->phys_cursor_width; 5632 5633 /* The foreground of cursor_gc is typically the same as the normal 5634 background color, which can cause the cursor box to be invisible. */ 5635 xgcv.foreground = f->output_data.mac->cursor_pixel; 5636 if (dpyinfo->scratch_cursor_gc) 5637 XChangeGC (dpy, dpyinfo->scratch_cursor_gc, GCForeground, &xgcv); 5638 else 5639 dpyinfo->scratch_cursor_gc = XCreateGC (dpy, FRAME_MAC_WINDOW (f), 5640 GCForeground, &xgcv); 5641 gc = dpyinfo->scratch_cursor_gc; 5642 5643 /* Set clipping, draw the rectangle, and reset clipping again. */ 5644 x_clip_to_row (w, row, TEXT_AREA, gc); 5645 mac_draw_rectangle (f, gc, x, y, wd, h - 1); 5646 mac_reset_clip_rectangles (dpy, gc); 5647} 5648 5649 5650/* Draw a bar cursor on window W in glyph row ROW. 5651 5652 Implementation note: One would like to draw a bar cursor with an 5653 angle equal to the one given by the font property XA_ITALIC_ANGLE. 5654 Unfortunately, I didn't find a font yet that has this property set. 5655 --gerd. */ 5656 5657static void 5658x_draw_bar_cursor (w, row, width, kind) 5659 struct window *w; 5660 struct glyph_row *row; 5661 int width; 5662 enum text_cursor_kinds kind; 5663{ 5664 struct frame *f = XFRAME (w->frame); 5665 struct glyph *cursor_glyph; 5666 5667 /* If cursor is out of bounds, don't draw garbage. This can happen 5668 in mini-buffer windows when switching between echo area glyphs 5669 and mini-buffer. */ 5670 cursor_glyph = get_phys_cursor_glyph (w); 5671 if (cursor_glyph == NULL) 5672 return; 5673 5674 /* If on an image, draw like a normal cursor. That's usually better 5675 visible than drawing a bar, esp. if the image is large so that 5676 the bar might not be in the window. */ 5677 if (cursor_glyph->type == IMAGE_GLYPH) 5678 { 5679 struct glyph_row *row; 5680 row = MATRIX_ROW (w->current_matrix, w->phys_cursor.vpos); 5681 draw_phys_cursor_glyph (w, row, DRAW_CURSOR); 5682 } 5683 else 5684 { 5685 Display *dpy = FRAME_MAC_DISPLAY (f); 5686 Window window = FRAME_MAC_WINDOW (f); 5687 GC gc = FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc; 5688 unsigned long mask = GCForeground | GCBackground; 5689 struct face *face = FACE_FROM_ID (f, cursor_glyph->face_id); 5690 XGCValues xgcv; 5691 5692 /* If the glyph's background equals the color we normally draw 5693 the bar cursor in, the bar cursor in its normal color is 5694 invisible. Use the glyph's foreground color instead in this 5695 case, on the assumption that the glyph's colors are chosen so 5696 that the glyph is legible. */ 5697 if (face->background == f->output_data.mac->cursor_pixel) 5698 xgcv.background = xgcv.foreground = face->foreground; 5699 else 5700 xgcv.background = xgcv.foreground = f->output_data.mac->cursor_pixel; 5701 5702 if (gc) 5703 XChangeGC (dpy, gc, mask, &xgcv); 5704 else 5705 { 5706 gc = XCreateGC (dpy, window, mask, &xgcv); 5707 FRAME_MAC_DISPLAY_INFO (f)->scratch_cursor_gc = gc; 5708 } 5709 5710 if (width < 0) 5711 width = FRAME_CURSOR_WIDTH (f); 5712 width = min (cursor_glyph->pixel_width, width); 5713 5714 w->phys_cursor_width = width; 5715 x_clip_to_row (w, row, TEXT_AREA, gc); 5716 5717 if (kind == BAR_CURSOR) 5718 mac_fill_rectangle (f, gc, 5719 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x), 5720 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y), 5721 width, row->height); 5722 else 5723 mac_fill_rectangle (f, gc, 5724 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, w->phys_cursor.x), 5725 WINDOW_TO_FRAME_PIXEL_Y (w, w->phys_cursor.y + 5726 row->height - width), 5727 cursor_glyph->pixel_width, 5728 width); 5729 5730 mac_reset_clip_rectangles (dpy, gc); 5731 } 5732} 5733 5734 5735/* RIF: Define cursor CURSOR on frame F. */ 5736 5737static void 5738mac_define_frame_cursor (f, cursor) 5739 struct frame *f; 5740 Cursor cursor; 5741{ 5742 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f); 5743 5744 if (dpyinfo->x_focus_frame == f) 5745 SetThemeCursor (cursor); 5746} 5747 5748 5749/* RIF: Clear area on frame F. */ 5750 5751static void 5752mac_clear_frame_area (f, x, y, width, height) 5753 struct frame *f; 5754 int x, y, width, height; 5755{ 5756 mac_clear_area (f, x, y, width, height); 5757} 5758 5759 5760/* RIF: Draw cursor on window W. */ 5761 5762static void 5763mac_draw_window_cursor (w, glyph_row, x, y, cursor_type, cursor_width, on_p, active_p) 5764 struct window *w; 5765 struct glyph_row *glyph_row; 5766 int x, y; 5767 int cursor_type, cursor_width; 5768 int on_p, active_p; 5769{ 5770 if (on_p) 5771 { 5772 w->phys_cursor_type = cursor_type; 5773 w->phys_cursor_on_p = 1; 5774 5775 if (glyph_row->exact_window_width_line_p 5776 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA]) 5777 { 5778 glyph_row->cursor_in_fringe_p = 1; 5779 draw_fringe_bitmap (w, glyph_row, 0); 5780 } 5781 else 5782 switch (cursor_type) 5783 { 5784 case HOLLOW_BOX_CURSOR: 5785 x_draw_hollow_cursor (w, glyph_row); 5786 break; 5787 5788 case FILLED_BOX_CURSOR: 5789 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR); 5790 break; 5791 5792 case BAR_CURSOR: 5793 x_draw_bar_cursor (w, glyph_row, cursor_width, BAR_CURSOR); 5794 break; 5795 5796 case HBAR_CURSOR: 5797 x_draw_bar_cursor (w, glyph_row, cursor_width, HBAR_CURSOR); 5798 break; 5799 5800 case NO_CURSOR: 5801 w->phys_cursor_width = 0; 5802 break; 5803 5804 default: 5805 abort (); 5806 } 5807 } 5808} 5809 5810 5811/* Icons. */ 5812 5813#if 0 /* MAC_TODO: no icon support yet. */ 5814int 5815x_bitmap_icon (f, icon) 5816 struct frame *f; 5817 Lisp_Object icon; 5818{ 5819 HANDLE hicon; 5820 5821 if (FRAME_W32_WINDOW (f) == 0) 5822 return 1; 5823 5824 if (NILP (icon)) 5825 hicon = LoadIcon (hinst, EMACS_CLASS); 5826 else if (STRINGP (icon)) 5827 hicon = LoadImage (NULL, (LPCTSTR) SDATA (icon), IMAGE_ICON, 0, 0, 5828 LR_DEFAULTSIZE | LR_LOADFROMFILE); 5829 else if (SYMBOLP (icon)) 5830 { 5831 LPCTSTR name; 5832 5833 if (EQ (icon, intern ("application"))) 5834 name = (LPCTSTR) IDI_APPLICATION; 5835 else if (EQ (icon, intern ("hand"))) 5836 name = (LPCTSTR) IDI_HAND; 5837 else if (EQ (icon, intern ("question"))) 5838 name = (LPCTSTR) IDI_QUESTION; 5839 else if (EQ (icon, intern ("exclamation"))) 5840 name = (LPCTSTR) IDI_EXCLAMATION; 5841 else if (EQ (icon, intern ("asterisk"))) 5842 name = (LPCTSTR) IDI_ASTERISK; 5843 else if (EQ (icon, intern ("winlogo"))) 5844 name = (LPCTSTR) IDI_WINLOGO; 5845 else 5846 return 1; 5847 5848 hicon = LoadIcon (NULL, name); 5849 } 5850 else 5851 return 1; 5852 5853 if (hicon == NULL) 5854 return 1; 5855 5856 PostMessage (FRAME_W32_WINDOW (f), WM_SETICON, (WPARAM) ICON_BIG, 5857 (LPARAM) hicon); 5858 5859 return 0; 5860} 5861#endif /* MAC_TODO */ 5862 5863/************************************************************************ 5864 Handling X errors 5865 ************************************************************************/ 5866 5867/* Display Error Handling functions not used on W32. Listing them here 5868 helps diff stay in step when comparing w32term.c with xterm.c. 5869 5870x_error_catcher (display, error) 5871x_catch_errors (dpy) 5872x_catch_errors_unwind (old_val) 5873x_check_errors (dpy, format) 5874x_had_errors_p (dpy) 5875x_clear_errors (dpy) 5876x_uncatch_errors (dpy, count) 5877x_trace_wire () 5878x_connection_signal (signalnum) 5879x_connection_closed (dpy, error_message) 5880x_error_quitter (display, error) 5881x_error_handler (display, error) 5882x_io_error_quitter (display) 5883 5884 */ 5885 5886 5887/* Changing the font of the frame. */ 5888 5889/* Give frame F the font named FONTNAME as its default font, and 5890 return the full name of that font. FONTNAME may be a wildcard 5891 pattern; in that case, we choose some font that fits the pattern. 5892 The return value shows which font we chose. */ 5893 5894Lisp_Object 5895x_new_font (f, fontname) 5896 struct frame *f; 5897 register char *fontname; 5898{ 5899 struct font_info *fontp 5900 = FS_LOAD_FONT (f, 0, fontname, -1); 5901 5902 if (!fontp) 5903 return Qnil; 5904 5905 FRAME_FONT (f) = (XFontStruct *) (fontp->font); 5906 FRAME_BASELINE_OFFSET (f) = fontp->baseline_offset; 5907 FRAME_FONTSET (f) = -1; 5908 5909 FRAME_COLUMN_WIDTH (f) = fontp->average_width; 5910 FRAME_SPACE_WIDTH (f) = fontp->space_width; 5911 FRAME_LINE_HEIGHT (f) = FONT_HEIGHT (FRAME_FONT (f)); 5912 5913 compute_fringe_widths (f, 1); 5914 5915 /* Compute the scroll bar width in character columns. */ 5916 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0) 5917 { 5918 int wid = FRAME_COLUMN_WIDTH (f); 5919 FRAME_CONFIG_SCROLL_BAR_COLS (f) 5920 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid-1) / wid; 5921 } 5922 else 5923 { 5924 int wid = FRAME_COLUMN_WIDTH (f); 5925 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid; 5926 } 5927 5928 /* Now make the frame display the given font. */ 5929 if (FRAME_MAC_WINDOW (f) != 0) 5930 { 5931 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->normal_gc, 5932 FRAME_FONT (f)); 5933 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->reverse_gc, 5934 FRAME_FONT (f)); 5935 XSetFont (FRAME_MAC_DISPLAY (f), f->output_data.mac->cursor_gc, 5936 FRAME_FONT (f)); 5937 5938 /* Don't change the size of a tip frame; there's no point in 5939 doing it because it's done in Fx_show_tip, and it leads to 5940 problems because the tip frame has no widget. */ 5941 if (NILP (tip_frame) || XFRAME (tip_frame) != f) 5942 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f)); 5943 } 5944 5945 return build_string (fontp->full_name); 5946} 5947 5948/* Give frame F the fontset named FONTSETNAME as its default font, and 5949 return the full name of that fontset. FONTSETNAME may be a wildcard 5950 pattern; in that case, we choose some fontset that fits the pattern. 5951 The return value shows which fontset we chose. */ 5952 5953Lisp_Object 5954x_new_fontset (f, fontsetname) 5955 struct frame *f; 5956 char *fontsetname; 5957{ 5958 int fontset = fs_query_fontset (build_string (fontsetname), 0); 5959 Lisp_Object result; 5960 5961 if (fontset < 0) 5962 return Qnil; 5963 5964 if (FRAME_FONTSET (f) == fontset) 5965 /* This fontset is already set in frame F. There's nothing more 5966 to do. */ 5967 return fontset_name (fontset); 5968 5969 result = x_new_font (f, (SDATA (fontset_ascii (fontset)))); 5970 5971 if (!STRINGP (result)) 5972 /* Can't load ASCII font. */ 5973 return Qnil; 5974 5975 /* Since x_new_font doesn't update any fontset information, do it now. */ 5976 FRAME_FONTSET (f) = fontset; 5977 5978 return build_string (fontsetname); 5979} 5980 5981 5982/*********************************************************************** 5983 TODO: W32 Input Methods 5984 ***********************************************************************/ 5985/* Listing missing functions from xterm.c helps diff stay in step. 5986 5987xim_destroy_callback (xim, client_data, call_data) 5988xim_open_dpy (dpyinfo, resource_name) 5989struct xim_inst_t 5990xim_instantiate_callback (display, client_data, call_data) 5991xim_initialize (dpyinfo, resource_name) 5992xim_close_dpy (dpyinfo) 5993 5994 */ 5995 5996 5997void 5998mac_get_window_bounds (f, inner, outer) 5999 struct frame *f; 6000 Rect *inner, *outer; 6001{ 6002#if TARGET_API_MAC_CARBON 6003 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowContentRgn, inner); 6004 GetWindowBounds (FRAME_MAC_WINDOW (f), kWindowStructureRgn, outer); 6005#else /* not TARGET_API_MAC_CARBON */ 6006 RgnHandle region = NewRgn (); 6007 6008 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowContentRgn, region); 6009 *inner = (*region)->rgnBBox; 6010 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowStructureRgn, region); 6011 *outer = (*region)->rgnBBox; 6012 DisposeRgn (region); 6013#endif /* not TARGET_API_MAC_CARBON */ 6014} 6015 6016static void 6017mac_handle_origin_change (f) 6018 struct frame *f; 6019{ 6020 x_real_positions (f, &f->left_pos, &f->top_pos); 6021} 6022 6023static void 6024mac_handle_size_change (f, pixelwidth, pixelheight) 6025 struct frame *f; 6026 int pixelwidth, pixelheight; 6027{ 6028 int cols, rows; 6029 6030 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, pixelwidth); 6031 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, pixelheight); 6032 6033 if (cols != FRAME_COLS (f) 6034 || rows != FRAME_LINES (f) 6035 || pixelwidth != FRAME_PIXEL_WIDTH (f) 6036 || pixelheight != FRAME_PIXEL_HEIGHT (f)) 6037 { 6038 /* We pass 1 for DELAY since we can't run Lisp code inside of 6039 a BLOCK_INPUT. */ 6040 change_frame_size (f, rows, cols, 0, 1, 0); 6041 FRAME_PIXEL_WIDTH (f) = pixelwidth; 6042 FRAME_PIXEL_HEIGHT (f) = pixelheight; 6043 SET_FRAME_GARBAGED (f); 6044 6045 /* If cursor was outside the new size, mark it as off. */ 6046 mark_window_cursors_off (XWINDOW (f->root_window)); 6047 6048 /* Clear out any recollection of where the mouse highlighting 6049 was, since it might be in a place that's outside the new 6050 frame size. Actually checking whether it is outside is a 6051 pain in the neck, so don't try--just let the highlighting be 6052 done afresh with new size. */ 6053 cancel_mouse_face (f); 6054 6055#if TARGET_API_MAC_CARBON 6056 if (f->output_data.mac->hourglass_control) 6057 { 6058#if USE_CG_DRAWING 6059 mac_prepare_for_quickdraw (f); 6060#endif 6061 MoveControl (f->output_data.mac->hourglass_control, 6062 pixelwidth - HOURGLASS_WIDTH, 0); 6063 } 6064#endif 6065 } 6066} 6067 6068 6069/* Calculate the absolute position in frame F 6070 from its current recorded position values and gravity. */ 6071 6072void 6073x_calc_absolute_position (f) 6074 struct frame *f; 6075{ 6076 int width_diff = 0, height_diff = 0; 6077 int flags = f->size_hint_flags; 6078 Rect inner, outer; 6079 6080 /* We have nothing to do if the current position 6081 is already for the top-left corner. */ 6082 if (! ((flags & XNegative) || (flags & YNegative))) 6083 return; 6084 6085 /* Find the offsets of the outside upper-left corner of 6086 the inner window, with respect to the outer window. */ 6087 BLOCK_INPUT; 6088 mac_get_window_bounds (f, &inner, &outer); 6089 UNBLOCK_INPUT; 6090 6091 width_diff = (outer.right - outer.left) - (inner.right - inner.left); 6092 height_diff = (outer.bottom - outer.top) - (inner.bottom - inner.top); 6093 6094 /* Treat negative positions as relative to the leftmost bottommost 6095 position that fits on the screen. */ 6096 if (flags & XNegative) 6097 f->left_pos = (FRAME_MAC_DISPLAY_INFO (f)->width 6098 - width_diff 6099 - FRAME_PIXEL_WIDTH (f) 6100 + f->left_pos); 6101 6102 if (flags & YNegative) 6103 f->top_pos = (FRAME_MAC_DISPLAY_INFO (f)->height 6104 - height_diff 6105 - FRAME_PIXEL_HEIGHT (f) 6106 + f->top_pos); 6107 6108 /* The left_pos and top_pos 6109 are now relative to the top and left screen edges, 6110 so the flags should correspond. */ 6111 f->size_hint_flags &= ~ (XNegative | YNegative); 6112} 6113 6114/* CHANGE_GRAVITY is 1 when calling from Fset_frame_position, 6115 to really change the position, and 0 when calling from 6116 x_make_frame_visible (in that case, XOFF and YOFF are the current 6117 position values). It is -1 when calling from x_set_frame_parameters, 6118 which means, do adjust for borders but don't change the gravity. */ 6119 6120void 6121x_set_offset (f, xoff, yoff, change_gravity) 6122 struct frame *f; 6123 register int xoff, yoff; 6124 int change_gravity; 6125{ 6126 if (change_gravity > 0) 6127 { 6128 f->top_pos = yoff; 6129 f->left_pos = xoff; 6130 f->size_hint_flags &= ~ (XNegative | YNegative); 6131 if (xoff < 0) 6132 f->size_hint_flags |= XNegative; 6133 if (yoff < 0) 6134 f->size_hint_flags |= YNegative; 6135 f->win_gravity = NorthWestGravity; 6136 } 6137 x_calc_absolute_position (f); 6138 6139 BLOCK_INPUT; 6140 x_wm_set_size_hint (f, (long) 0, 0); 6141 6142#if TARGET_API_MAC_CARBON 6143 MoveWindowStructure (FRAME_MAC_WINDOW (f), f->left_pos, f->top_pos); 6144 /* If the title bar is completely outside the screen, adjust the 6145 position. */ 6146 ConstrainWindowToScreen (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, 6147 kWindowConstrainMoveRegardlessOfFit 6148 | kWindowConstrainAllowPartial, NULL, NULL); 6149#if USE_CARBON_EVENTS 6150 if (!NILP (tip_frame) && XFRAME (tip_frame) == f) 6151#endif 6152 mac_handle_origin_change (f); 6153#else 6154 { 6155 Rect inner, outer, screen_rect, dummy; 6156 RgnHandle region = NewRgn (); 6157 6158 mac_get_window_bounds (f, &inner, &outer); 6159 f->x_pixels_diff = inner.left - outer.left; 6160 f->y_pixels_diff = inner.top - outer.top; 6161 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff, 6162 f->top_pos + f->y_pixels_diff, false); 6163 6164 /* If the title bar is completely outside the screen, adjust the 6165 position. The variable `outer' holds the title bar rectangle. 6166 The variable `inner' holds slightly smaller one than `outer', 6167 so that the calculation of overlapping may not become too 6168 strict. */ 6169 GetWindowRegion (FRAME_MAC_WINDOW (f), kWindowTitleBarRgn, region); 6170 outer = (*region)->rgnBBox; 6171 DisposeRgn (region); 6172 inner = outer; 6173 InsetRect (&inner, 8, 8); 6174 screen_rect = qd.screenBits.bounds; 6175 screen_rect.top += GetMBarHeight (); 6176 6177 if (!SectRect (&inner, &screen_rect, &dummy)) 6178 { 6179 if (inner.right <= screen_rect.left) 6180 f->left_pos = screen_rect.left; 6181 else if (inner.left >= screen_rect.right) 6182 f->left_pos = screen_rect.right - (outer.right - outer.left); 6183 6184 if (inner.bottom <= screen_rect.top) 6185 f->top_pos = screen_rect.top; 6186 else if (inner.top >= screen_rect.bottom) 6187 f->top_pos = screen_rect.bottom - (outer.bottom - outer.top); 6188 6189 MoveWindow (FRAME_MAC_WINDOW (f), f->left_pos + f->x_pixels_diff, 6190 f->top_pos + f->y_pixels_diff, false); 6191 } 6192 } 6193#endif 6194 6195 UNBLOCK_INPUT; 6196} 6197 6198/* Call this to change the size of frame F's x-window. 6199 If CHANGE_GRAVITY is 1, we change to top-left-corner window gravity 6200 for this size change and subsequent size changes. 6201 Otherwise we leave the window gravity unchanged. */ 6202 6203void 6204x_set_window_size (f, change_gravity, cols, rows) 6205 struct frame *f; 6206 int change_gravity; 6207 int cols, rows; 6208{ 6209 int pixelwidth, pixelheight; 6210 6211 BLOCK_INPUT; 6212 6213 check_frame_size (f, &rows, &cols); 6214 f->scroll_bar_actual_width 6215 = FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f); 6216 6217 compute_fringe_widths (f, 0); 6218 6219 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols); 6220 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows); 6221 6222 f->win_gravity = NorthWestGravity; 6223 x_wm_set_size_hint (f, (long) 0, 0); 6224 6225 SizeWindow (FRAME_MAC_WINDOW (f), pixelwidth, pixelheight, 0); 6226 6227#if USE_CARBON_EVENTS 6228 if (!NILP (tip_frame) && f == XFRAME (tip_frame)) 6229#endif 6230 mac_handle_size_change (f, pixelwidth, pixelheight); 6231 6232 if (f->output_data.mac->internal_border_width 6233 != FRAME_INTERNAL_BORDER_WIDTH (f)) 6234 { 6235 mac_clear_window (f); 6236 f->output_data.mac->internal_border_width 6237 = FRAME_INTERNAL_BORDER_WIDTH (f); 6238 } 6239 6240 SET_FRAME_GARBAGED (f); 6241 6242 UNBLOCK_INPUT; 6243} 6244 6245/* Mouse warping. */ 6246 6247void x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y); 6248 6249void 6250x_set_mouse_position (f, x, y) 6251 struct frame *f; 6252 int x, y; 6253{ 6254 int pix_x, pix_y; 6255 6256 pix_x = FRAME_COL_TO_PIXEL_X (f, x) + FRAME_COLUMN_WIDTH (f) / 2; 6257 pix_y = FRAME_LINE_TO_PIXEL_Y (f, y) + FRAME_LINE_HEIGHT (f) / 2; 6258 6259 if (pix_x < 0) pix_x = 0; 6260 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f); 6261 6262 if (pix_y < 0) pix_y = 0; 6263 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f); 6264 6265 x_set_mouse_pixel_position (f, pix_x, pix_y); 6266} 6267 6268void 6269x_set_mouse_pixel_position (f, pix_x, pix_y) 6270 struct frame *f; 6271 int pix_x, pix_y; 6272{ 6273#ifdef MAC_OSX 6274 Point p; 6275 CGPoint point; 6276 6277 BLOCK_INPUT; 6278 SetPortWindowPort (FRAME_MAC_WINDOW (f)); 6279 p.h = pix_x; 6280 p.v = pix_y; 6281 LocalToGlobal (&p); 6282 point.x = p.h; 6283 point.y = p.v; 6284 CGWarpMouseCursorPosition (point); 6285 UNBLOCK_INPUT; 6286#else 6287#if 0 /* MAC_TODO: LMSetMouseLocation and CursorDeviceMoveTo are non-Carbon */ 6288 BLOCK_INPUT; 6289 6290 XWarpPointer (FRAME_X_DISPLAY (f), None, FRAME_X_WINDOW (f), 6291 0, 0, 0, 0, pix_x, pix_y); 6292 UNBLOCK_INPUT; 6293#endif 6294#endif 6295} 6296 6297/* focus shifting, raising and lowering. */ 6298 6299void 6300x_focus_on_frame (f) 6301 struct frame *f; 6302{ 6303#if 0 /* This proves to be unpleasant. */ 6304 x_raise_frame (f); 6305#endif 6306#if 0 6307 /* I don't think that the ICCCM allows programs to do things like this 6308 without the interaction of the window manager. Whatever you end up 6309 doing with this code, do it to x_unfocus_frame too. */ 6310 XSetInputFocus (FRAME_X_DISPLAY (f), FRAME_X_WINDOW (f), 6311 RevertToPointerRoot, CurrentTime); 6312#endif /* ! 0 */ 6313} 6314 6315void 6316x_unfocus_frame (f) 6317 struct frame *f; 6318{ 6319} 6320 6321/* Raise frame F. */ 6322 6323void 6324x_raise_frame (f) 6325 struct frame *f; 6326{ 6327 if (f->async_visible) 6328 { 6329 BLOCK_INPUT; 6330 BringToFront (FRAME_MAC_WINDOW (f)); 6331 UNBLOCK_INPUT; 6332 } 6333} 6334 6335/* Lower frame F. */ 6336 6337void 6338x_lower_frame (f) 6339 struct frame *f; 6340{ 6341 if (f->async_visible) 6342 { 6343 BLOCK_INPUT; 6344 SendBehind (FRAME_MAC_WINDOW (f), NULL); 6345 UNBLOCK_INPUT; 6346 } 6347} 6348 6349static void 6350XTframe_raise_lower (f, raise_flag) 6351 FRAME_PTR f; 6352 int raise_flag; 6353{ 6354 if (raise_flag) 6355 x_raise_frame (f); 6356 else 6357 x_lower_frame (f); 6358} 6359 6360/* Change of visibility. */ 6361 6362static void 6363mac_handle_visibility_change (f) 6364 struct frame *f; 6365{ 6366 WindowPtr wp = FRAME_MAC_WINDOW (f); 6367 int visible = 0, iconified = 0; 6368 struct input_event buf; 6369 6370 if (IsWindowVisible (wp)) 6371 { 6372 if (IsWindowCollapsed (wp)) 6373 iconified = 1; 6374 else 6375 visible = 1; 6376 } 6377 6378 if (!f->async_visible && visible) 6379 { 6380 if (f->iconified) 6381 { 6382 /* wait_reading_process_output will notice this and update 6383 the frame's display structures. If we were made 6384 invisible, we should not set garbaged, because that stops 6385 redrawing on Update events. */ 6386 SET_FRAME_GARBAGED (f); 6387 6388 EVENT_INIT (buf); 6389 buf.kind = DEICONIFY_EVENT; 6390 XSETFRAME (buf.frame_or_window, f); 6391 buf.arg = Qnil; 6392 kbd_buffer_store_event (&buf); 6393 } 6394 else if (! NILP (Vframe_list) && ! NILP (XCDR (Vframe_list))) 6395 /* Force a redisplay sooner or later to update the 6396 frame titles in case this is the second frame. */ 6397 record_asynch_buffer_change (); 6398 } 6399 else if (f->async_visible && !visible) 6400 if (iconified) 6401 { 6402 EVENT_INIT (buf); 6403 buf.kind = ICONIFY_EVENT; 6404 XSETFRAME (buf.frame_or_window, f); 6405 buf.arg = Qnil; 6406 kbd_buffer_store_event (&buf); 6407 } 6408 6409 f->async_visible = visible; 6410 f->async_iconified = iconified; 6411} 6412 6413/* This tries to wait until the frame is really visible. 6414 However, if the window manager asks the user where to position 6415 the frame, this will return before the user finishes doing that. 6416 The frame will not actually be visible at that time, 6417 but it will become visible later when the window manager 6418 finishes with it. */ 6419 6420void 6421x_make_frame_visible (f) 6422 struct frame *f; 6423{ 6424 BLOCK_INPUT; 6425 6426 if (! FRAME_VISIBLE_P (f)) 6427 { 6428 /* We test FRAME_GARBAGED_P here to make sure we don't 6429 call x_set_offset a second time 6430 if we get to x_make_frame_visible a second time 6431 before the window gets really visible. */ 6432 if (! FRAME_ICONIFIED_P (f) 6433 && ! f->output_data.mac->asked_for_visible) 6434 { 6435#if TARGET_API_MAC_CARBON 6436 if (!(FRAME_SIZE_HINTS (f)->flags & (USPosition | PPosition))) 6437 { 6438 struct frame *sf = SELECTED_FRAME (); 6439 if (!FRAME_MAC_P (sf)) 6440 RepositionWindow (FRAME_MAC_WINDOW (f), NULL, 6441 kWindowCenterOnMainScreen); 6442 else 6443 RepositionWindow (FRAME_MAC_WINDOW (f), 6444 FRAME_MAC_WINDOW (sf), 6445#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 6446 kWindowCascadeStartAtParentWindowScreen 6447#else 6448 kWindowCascadeOnParentWindowScreen 6449#endif 6450 ); 6451#if USE_CARBON_EVENTS 6452 if (!NILP (tip_frame) && f == XFRAME (tip_frame)) 6453#endif 6454 mac_handle_origin_change (f); 6455 } 6456 else 6457#endif 6458 x_set_offset (f, f->left_pos, f->top_pos, 0); 6459 } 6460 6461 f->output_data.mac->asked_for_visible = 1; 6462 6463 CollapseWindow (FRAME_MAC_WINDOW (f), false); 6464 ShowWindow (FRAME_MAC_WINDOW (f)); 6465 } 6466 6467 XFlush (FRAME_MAC_DISPLAY (f)); 6468 6469 /* Synchronize to ensure Emacs knows the frame is visible 6470 before we do anything else. We do this loop with input not blocked 6471 so that incoming events are handled. */ 6472 { 6473 Lisp_Object frame; 6474 int count; 6475 6476 /* This must come after we set COUNT. */ 6477 UNBLOCK_INPUT; 6478 6479 XSETFRAME (frame, f); 6480 6481 /* Wait until the frame is visible. Process X events until a 6482 MapNotify event has been seen, or until we think we won't get a 6483 MapNotify at all.. */ 6484 for (count = input_signal_count + 10; 6485 input_signal_count < count && !FRAME_VISIBLE_P (f);) 6486 { 6487 /* Force processing of queued events. */ 6488 x_sync (f); 6489 6490 /* Machines that do polling rather than SIGIO have been 6491 observed to go into a busy-wait here. So we'll fake an 6492 alarm signal to let the handler know that there's something 6493 to be read. We used to raise a real alarm, but it seems 6494 that the handler isn't always enabled here. This is 6495 probably a bug. */ 6496 if (input_polling_used ()) 6497 { 6498 /* It could be confusing if a real alarm arrives while 6499 processing the fake one. Turn it off and let the 6500 handler reset it. */ 6501 extern void poll_for_input_1 P_ ((void)); 6502 int old_poll_suppress_count = poll_suppress_count; 6503 poll_suppress_count = 1; 6504 poll_for_input_1 (); 6505 poll_suppress_count = old_poll_suppress_count; 6506 } 6507 6508 /* See if a MapNotify event has been processed. */ 6509 FRAME_SAMPLE_VISIBILITY (f); 6510 } 6511 } 6512} 6513 6514/* Change from mapped state to withdrawn state. */ 6515 6516/* Make the frame visible (mapped and not iconified). */ 6517 6518void 6519x_make_frame_invisible (f) 6520 struct frame *f; 6521{ 6522 /* A deactivate event does not occur when the last visible frame is 6523 made invisible. So if we clear the highlight here, it will not 6524 be rehighlighted when it is made visible. */ 6525#if 0 6526 /* Don't keep the highlight on an invisible frame. */ 6527 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f) 6528 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0; 6529#endif 6530 6531 BLOCK_INPUT; 6532 6533 /* Before unmapping the window, update the WM_SIZE_HINTS property to claim 6534 that the current position of the window is user-specified, rather than 6535 program-specified, so that when the window is mapped again, it will be 6536 placed at the same location, without forcing the user to position it 6537 by hand again (they have already done that once for this window.) */ 6538 x_wm_set_size_hint (f, (long) 0, 1); 6539 6540 HideWindow (FRAME_MAC_WINDOW (f)); 6541 6542 UNBLOCK_INPUT; 6543 6544#if !USE_CARBON_EVENTS 6545 mac_handle_visibility_change (f); 6546#endif 6547} 6548 6549/* Change window state from mapped to iconified. */ 6550 6551void 6552x_iconify_frame (f) 6553 struct frame *f; 6554{ 6555 OSStatus err; 6556 6557 /* A deactivate event does not occur when the last visible frame is 6558 iconified. So if we clear the highlight here, it will not be 6559 rehighlighted when it is deiconified. */ 6560#if 0 6561 /* Don't keep the highlight on an invisible frame. */ 6562 if (FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame == f) 6563 FRAME_MAC_DISPLAY_INFO (f)->x_highlight_frame = 0; 6564#endif 6565 6566 if (f->async_iconified) 6567 return; 6568 6569 BLOCK_INPUT; 6570 6571 FRAME_SAMPLE_VISIBILITY (f); 6572 6573 if (! FRAME_VISIBLE_P (f)) 6574 ShowWindow (FRAME_MAC_WINDOW (f)); 6575 6576 err = CollapseWindow (FRAME_MAC_WINDOW (f), true); 6577 6578 UNBLOCK_INPUT; 6579 6580 if (err != noErr) 6581 error ("Can't notify window manager of iconification"); 6582 6583#if !USE_CARBON_EVENTS 6584 mac_handle_visibility_change (f); 6585#endif 6586} 6587 6588 6589/* Free X resources of frame F. */ 6590 6591void 6592x_free_frame_resources (f) 6593 struct frame *f; 6594{ 6595 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f); 6596 WindowPtr wp = FRAME_MAC_WINDOW (f); 6597 6598 BLOCK_INPUT; 6599 6600 if (wp != tip_window) 6601 remove_window_handler (wp); 6602 6603#if USE_CG_DRAWING 6604 mac_prepare_for_quickdraw (f); 6605#endif 6606 DisposeWindow (wp); 6607 if (wp == tip_window) 6608 /* Neither WaitNextEvent nor ReceiveNextEvent receives `window 6609 closed' event. So we reset tip_window here. */ 6610 tip_window = NULL; 6611 6612 free_frame_menubar (f); 6613 6614 if (FRAME_FACE_CACHE (f)) 6615 free_frame_faces (f); 6616 6617 x_free_gcs (f); 6618 6619 if (FRAME_SIZE_HINTS (f)) 6620 xfree (FRAME_SIZE_HINTS (f)); 6621 6622 xfree (f->output_data.mac); 6623 f->output_data.mac = NULL; 6624 6625 if (f == dpyinfo->x_focus_frame) 6626 { 6627 dpyinfo->x_focus_frame = 0; 6628#if USE_MAC_FONT_PANEL 6629 mac_set_font_info_for_selection (NULL, DEFAULT_FACE_ID, 0); 6630#endif 6631 } 6632 if (f == dpyinfo->x_focus_event_frame) 6633 dpyinfo->x_focus_event_frame = 0; 6634 if (f == dpyinfo->x_highlight_frame) 6635 dpyinfo->x_highlight_frame = 0; 6636 6637 if (f == dpyinfo->mouse_face_mouse_frame) 6638 { 6639 dpyinfo->mouse_face_beg_row 6640 = dpyinfo->mouse_face_beg_col = -1; 6641 dpyinfo->mouse_face_end_row 6642 = dpyinfo->mouse_face_end_col = -1; 6643 dpyinfo->mouse_face_window = Qnil; 6644 dpyinfo->mouse_face_deferred_gc = 0; 6645 dpyinfo->mouse_face_mouse_frame = 0; 6646 } 6647 6648 UNBLOCK_INPUT; 6649} 6650 6651 6652/* Destroy the X window of frame F. */ 6653 6654void 6655x_destroy_window (f) 6656 struct frame *f; 6657{ 6658 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f); 6659 6660 x_free_frame_resources (f); 6661 6662 dpyinfo->reference_count--; 6663} 6664 6665 6666/* Setting window manager hints. */ 6667 6668/* Set the normal size hints for the window manager, for frame F. 6669 FLAGS is the flags word to use--or 0 meaning preserve the flags 6670 that the window now has. 6671 If USER_POSITION is nonzero, we set the USPosition 6672 flag (this is useful when FLAGS is 0). */ 6673void 6674x_wm_set_size_hint (f, flags, user_position) 6675 struct frame *f; 6676 long flags; 6677 int user_position; 6678{ 6679 int base_width, base_height, width_inc, height_inc; 6680 int min_rows = 0, min_cols = 0; 6681 XSizeHints *size_hints; 6682 6683 base_width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, 0); 6684 base_height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, 0); 6685 width_inc = FRAME_COLUMN_WIDTH (f); 6686 height_inc = FRAME_LINE_HEIGHT (f); 6687 6688 check_frame_size (f, &min_rows, &min_cols); 6689 6690 size_hints = FRAME_SIZE_HINTS (f); 6691 if (size_hints == NULL) 6692 { 6693 size_hints = FRAME_SIZE_HINTS (f) = xmalloc (sizeof (XSizeHints)); 6694 bzero (size_hints, sizeof (XSizeHints)); 6695 } 6696 6697 size_hints->flags |= PResizeInc | PMinSize | PBaseSize ; 6698 size_hints->width_inc = width_inc; 6699 size_hints->height_inc = height_inc; 6700 size_hints->min_width = base_width + min_cols * width_inc; 6701 size_hints->min_height = base_height + min_rows * height_inc; 6702 size_hints->base_width = base_width; 6703 size_hints->base_height = base_height; 6704 6705 if (flags) 6706 size_hints->flags = flags; 6707 else if (user_position) 6708 { 6709 size_hints->flags &= ~ PPosition; 6710 size_hints->flags |= USPosition; 6711 } 6712} 6713 6714#if 0 /* MAC_TODO: hide application instead of iconify? */ 6715/* Used for IconicState or NormalState */ 6716 6717void 6718x_wm_set_window_state (f, state) 6719 struct frame *f; 6720 int state; 6721{ 6722#ifdef USE_X_TOOLKIT 6723 Arg al[1]; 6724 6725 XtSetArg (al[0], XtNinitialState, state); 6726 XtSetValues (f->output_data.x->widget, al, 1); 6727#else /* not USE_X_TOOLKIT */ 6728 Window window = FRAME_X_WINDOW (f); 6729 6730 f->output_data.x->wm_hints.flags |= StateHint; 6731 f->output_data.x->wm_hints.initial_state = state; 6732 6733 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints); 6734#endif /* not USE_X_TOOLKIT */ 6735} 6736 6737void 6738x_wm_set_icon_pixmap (f, pixmap_id) 6739 struct frame *f; 6740 int pixmap_id; 6741{ 6742 Pixmap icon_pixmap; 6743 6744#ifndef USE_X_TOOLKIT 6745 Window window = FRAME_X_WINDOW (f); 6746#endif 6747 6748 if (pixmap_id > 0) 6749 { 6750 icon_pixmap = x_bitmap_pixmap (f, pixmap_id); 6751 f->output_data.x->wm_hints.icon_pixmap = icon_pixmap; 6752 } 6753 else 6754 { 6755 /* It seems there is no way to turn off use of an icon pixmap. 6756 The following line does it, only if no icon has yet been created, 6757 for some window managers. But with mwm it crashes. 6758 Some people say it should clear the IconPixmapHint bit in this case, 6759 but that doesn't work, and the X consortium said it isn't the 6760 right thing at all. Since there is no way to win, 6761 best to explicitly give up. */ 6762#if 0 6763 f->output_data.x->wm_hints.icon_pixmap = None; 6764#else 6765 return; 6766#endif 6767 } 6768 6769#ifdef USE_X_TOOLKIT /* same as in x_wm_set_window_state. */ 6770 6771 { 6772 Arg al[1]; 6773 XtSetArg (al[0], XtNiconPixmap, icon_pixmap); 6774 XtSetValues (f->output_data.x->widget, al, 1); 6775 } 6776 6777#else /* not USE_X_TOOLKIT */ 6778 6779 f->output_data.x->wm_hints.flags |= IconPixmapHint; 6780 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints); 6781 6782#endif /* not USE_X_TOOLKIT */ 6783} 6784 6785#endif /* MAC_TODO */ 6786 6787void 6788x_wm_set_icon_position (f, icon_x, icon_y) 6789 struct frame *f; 6790 int icon_x, icon_y; 6791{ 6792#if 0 /* MAC_TODO: no icons on Mac */ 6793#ifdef USE_X_TOOLKIT 6794 Window window = XtWindow (f->output_data.x->widget); 6795#else 6796 Window window = FRAME_X_WINDOW (f); 6797#endif 6798 6799 f->output_data.x->wm_hints.flags |= IconPositionHint; 6800 f->output_data.x->wm_hints.icon_x = icon_x; 6801 f->output_data.x->wm_hints.icon_y = icon_y; 6802 6803 XSetWMHints (FRAME_X_DISPLAY (f), window, &f->output_data.x->wm_hints); 6804#endif /* MAC_TODO */ 6805} 6806 6807 6808/*********************************************************************** 6809 XLFD Pattern Match 6810 ***********************************************************************/ 6811 6812/* An XLFD pattern is divided into blocks delimited by '*'. This 6813 structure holds information for each block. */ 6814struct xlfdpat_block 6815{ 6816 /* Length of the pattern string in this block. Non-zero except for 6817 the first and the last blocks. */ 6818 int len; 6819 6820 /* Pattern string except the last character in this block. The last 6821 character is replaced with NUL in order to use it as a 6822 sentinel. */ 6823 unsigned char *pattern; 6824 6825 /* Last character of the pattern string. Must not be '?'. */ 6826 unsigned char last_char; 6827 6828 /* One of the tables for the Boyer-Moore string search. It 6829 specifies the number of positions to proceed for each character 6830 with which the match fails. */ 6831 int skip[256]; 6832 6833 /* The skip value for the last character in the above `skip' is 6834 assigned to `infinity' in order to simplify a loop condition. 6835 The original value is saved here. */ 6836 int last_char_skip; 6837}; 6838 6839struct xlfdpat 6840{ 6841 /* Normalized pattern string. "Normalized" means that capital 6842 letters are lowered, blocks are not empty except the first and 6843 the last ones, and trailing '?'s in a block that is not the last 6844 one are moved to the next one. The last character in each block 6845 is replaced with NUL. */ 6846 unsigned char *buf; 6847 6848 /* Number of characters except '*'s and trailing '?'s in the 6849 normalized pattern string. */ 6850 int nchars; 6851 6852 /* Number of trailing '?'s in the normalized pattern string. */ 6853 int trailing_anychars; 6854 6855 /* Number of blocks and information for each block. The latter is 6856 NULL if the pattern is exact (no '*' or '?' in it). */ 6857 int nblocks; 6858 struct xlfdpat_block *blocks; 6859}; 6860 6861static void 6862xlfdpat_destroy (pat) 6863 struct xlfdpat *pat; 6864{ 6865 if (pat) 6866 { 6867 if (pat->buf) 6868 { 6869 if (pat->blocks) 6870 xfree (pat->blocks); 6871 xfree (pat->buf); 6872 } 6873 xfree (pat); 6874 } 6875} 6876 6877static struct xlfdpat * 6878xlfdpat_create (pattern) 6879 const char *pattern; 6880{ 6881 struct xlfdpat *pat; 6882 int nblocks, i, skip; 6883 unsigned char last_char, *p, *q, *anychar_head; 6884 const unsigned char *ptr; 6885 struct xlfdpat_block *blk; 6886 6887 pat = xmalloc (sizeof (struct xlfdpat)); 6888 pat->buf = xmalloc (strlen (pattern) + 1); 6889 6890 /* Normalize the pattern string and store it to `pat->buf'. */ 6891 nblocks = 0; 6892 anychar_head = NULL; 6893 q = pat->buf; 6894 last_char = '\0'; 6895 for (ptr = pattern; *ptr; ptr++) 6896 { 6897 unsigned char c = *ptr; 6898 6899 if (c == '*') 6900 if (last_char == '*') 6901 /* ...a** -> ...a* */ 6902 continue; 6903 else 6904 { 6905 if (last_char == '?') 6906 { 6907 if (anychar_head > pat->buf && *(anychar_head - 1) == '*') 6908 /* ...*??* -> ...*?? */ 6909 continue; 6910 else 6911 /* ...a??* -> ...a*?? */ 6912 { 6913 *anychar_head++ = '*'; 6914 c = '?'; 6915 } 6916 } 6917 nblocks++; 6918 } 6919 else if (c == '?') 6920 { 6921 if (last_char != '?') 6922 anychar_head = q; 6923 } 6924 else 6925 /* On Mac OS X 10.3, tolower also converts non-ASCII 6926 characters for some locales. */ 6927 if (isascii (c)) 6928 c = tolower (c); 6929 6930 *q++ = last_char = c; 6931 } 6932 *q = '\0'; 6933 nblocks++; 6934 pat->nblocks = nblocks; 6935 if (last_char != '?') 6936 pat->trailing_anychars = 0; 6937 else 6938 { 6939 pat->trailing_anychars = q - anychar_head; 6940 q = anychar_head; 6941 } 6942 pat->nchars = q - pat->buf - (nblocks - 1); 6943 6944 if (anychar_head == NULL && nblocks == 1) 6945 { 6946 /* The pattern is exact. */ 6947 pat->blocks = NULL; 6948 return pat; 6949 } 6950 6951 pat->blocks = xmalloc (sizeof (struct xlfdpat_block) * nblocks); 6952 6953 /* Divide the normalized pattern into blocks. */ 6954 p = pat->buf; 6955 for (blk = pat->blocks; blk < pat->blocks + nblocks - 1; blk++) 6956 { 6957 blk->pattern = p; 6958 while (*p != '*') 6959 p++; 6960 blk->len = p - blk->pattern; 6961 p++; 6962 } 6963 blk->pattern = p; 6964 blk->len = q - blk->pattern; 6965 6966 /* Setup a table for the Boyer-Moore string search. */ 6967 for (blk = pat->blocks; blk < pat->blocks + nblocks; blk++) 6968 if (blk->len != 0) 6969 { 6970 blk->last_char = blk->pattern[blk->len - 1]; 6971 blk->pattern[blk->len - 1] = '\0'; 6972 6973 for (skip = 1; skip < blk->len; skip++) 6974 if (blk->pattern[blk->len - skip - 1] == '?') 6975 break; 6976 6977 for (i = 0; i < 256; i++) 6978 blk->skip[i] = skip; 6979 6980 p = blk->pattern + (blk->len - skip); 6981 while (--skip > 0) 6982 blk->skip[*p++] = skip; 6983 6984 blk->last_char_skip = blk->skip[blk->last_char]; 6985 } 6986 6987 return pat; 6988} 6989 6990static INLINE int 6991xlfdpat_exact_p (pat) 6992 struct xlfdpat *pat; 6993{ 6994 return pat->blocks == NULL; 6995} 6996 6997/* Return the first string in STRING + 0, ..., STRING + START_MAX such 6998 that the pattern in *BLK matches with its prefix. Return NULL 6999 there is no such strings. STRING must be lowered in advance. */ 7000 7001static const char * 7002xlfdpat_block_match_1 (blk, string, start_max) 7003 struct xlfdpat_block *blk; 7004 const unsigned char *string; 7005 int start_max; 7006{ 7007 int start, infinity; 7008 unsigned char *p; 7009 const unsigned char *s; 7010 7011 xassert (blk->len > 0); 7012 xassert (start_max + blk->len <= strlen (string)); 7013 xassert (blk->last_char != '?'); 7014 7015 /* See the comments in the function `boyer_moore' (search.c) for the 7016 use of `infinity'. */ 7017 infinity = start_max + blk->len + 1; 7018 blk->skip[blk->last_char] = infinity; 7019 7020 start = 0; 7021 do 7022 { 7023 /* Check the last character of the pattern. */ 7024 s = string + blk->len - 1; 7025 do 7026 { 7027 start += blk->skip[*(s + start)]; 7028 } 7029 while (start <= start_max); 7030 7031 if (start < infinity) 7032 /* Couldn't find the last character. */ 7033 return NULL; 7034 7035 /* No less than `infinity' means we could find the last 7036 character at `s[start - infinity]'. */ 7037 start -= infinity; 7038 7039 /* Check the remaining characters. We prefer making no-'?' 7040 cases faster because the use of '?' is really rare. */ 7041 p = blk->pattern; 7042 s = string + start; 7043 do 7044 { 7045 while (*p++ == *s++) 7046 ; 7047 } 7048 while (*(p - 1) == '?'); 7049 7050 if (*(p - 1) == '\0') 7051 /* Matched. */ 7052 return string + start; 7053 7054 /* Didn't match. */ 7055 start += blk->last_char_skip; 7056 } 7057 while (start <= start_max); 7058 7059 return NULL; 7060} 7061 7062#define xlfdpat_block_match(b, s, m) \ 7063 ((b)->len == 1 ? memchr ((s), (b)->last_char, (m) + 1) \ 7064 : xlfdpat_block_match_1 (b, s, m)) 7065 7066/* Check if XLFD pattern PAT, which is generated by `xlfdpat_create', 7067 matches with STRING. STRING must be lowered in advance. */ 7068 7069static int 7070xlfdpat_match (pat, string) 7071 struct xlfdpat *pat; 7072 const unsigned char *string; 7073{ 7074 int str_len, nblocks, i, start_max; 7075 struct xlfdpat_block *blk; 7076 const unsigned char *s; 7077 7078 xassert (pat->nblocks > 0); 7079 7080 if (xlfdpat_exact_p (pat)) 7081 return strcmp (pat->buf, string) == 0; 7082 7083 /* The number of the characters in the string must not be smaller 7084 than that in the pattern. */ 7085 str_len = strlen (string); 7086 if (str_len < pat->nchars + pat->trailing_anychars) 7087 return 0; 7088 7089 /* Chop off the trailing '?'s. */ 7090 str_len -= pat->trailing_anychars; 7091 7092 /* The last block. When it is non-empty, it must match at the end 7093 of the string. */ 7094 nblocks = pat->nblocks; 7095 blk = pat->blocks + (nblocks - 1); 7096 if (nblocks == 1) 7097 /* The last block is also the first one. */ 7098 return (str_len == blk->len 7099 && (blk->len == 0 || xlfdpat_block_match (blk, string, 0))); 7100 else if (blk->len != 0) 7101 if (!xlfdpat_block_match (blk, string + (str_len - blk->len), 0)) 7102 return 0; 7103 7104 /* The first block. When it is non-empty, it must match at the 7105 beginning of the string. */ 7106 blk = pat->blocks; 7107 if (blk->len != 0) 7108 { 7109 s = xlfdpat_block_match (blk, string, 0); 7110 if (s == NULL) 7111 return 0; 7112 string = s + blk->len; 7113 } 7114 7115 /* The rest of the blocks. */ 7116 start_max = str_len - pat->nchars; 7117 for (i = 1, blk++; i < nblocks - 1; i++, blk++) 7118 { 7119 s = xlfdpat_block_match (blk, string, start_max); 7120 if (s == NULL) 7121 return 0; 7122 start_max -= s - string; 7123 string = s + blk->len; 7124 } 7125 7126 return 1; 7127} 7128 7129 7130/*********************************************************************** 7131 Fonts 7132 ***********************************************************************/ 7133 7134/* Return a pointer to struct font_info of font FONT_IDX of frame F. */ 7135 7136struct font_info * 7137x_get_font_info (f, font_idx) 7138 FRAME_PTR f; 7139 int font_idx; 7140{ 7141 return (FRAME_MAC_FONT_TABLE (f) + font_idx); 7142} 7143 7144/* the global font name table */ 7145static char **font_name_table = NULL; 7146static int font_name_table_size = 0; 7147static int font_name_count = 0; 7148 7149/* Alist linking font family names to Font Manager font family 7150 references (which can also be used as QuickDraw font IDs). We use 7151 an alist because hash tables are not ready when the terminal frame 7152 for Mac OS Classic is created. */ 7153static Lisp_Object fm_font_family_alist; 7154#if USE_ATSUI 7155/* Hash table linking font family names to ATSU font IDs. */ 7156static Lisp_Object atsu_font_id_hash; 7157/* Alist linking Font Manager style to face attributes. */ 7158static Lisp_Object fm_style_face_attributes_alist; 7159extern Lisp_Object QCfamily, QCweight, QCslant, Qnormal, Qbold, Qitalic; 7160#endif 7161 7162/* Alist linking character set strings to Mac text encoding and Emacs 7163 coding system. */ 7164static Lisp_Object Vmac_charset_info_alist; 7165 7166static Lisp_Object 7167create_text_encoding_info_alist () 7168{ 7169 Lisp_Object result = Qnil, rest; 7170 7171 for (rest = Vmac_charset_info_alist; CONSP (rest); rest = XCDR (rest)) 7172 { 7173 Lisp_Object charset_info = XCAR (rest); 7174 Lisp_Object charset, coding_system, text_encoding; 7175 Lisp_Object existing_info; 7176 7177 if (!(CONSP (charset_info) 7178 && (charset = XCAR (charset_info), 7179 STRINGP (charset)) 7180 && CONSP (XCDR (charset_info)) 7181 && (text_encoding = XCAR (XCDR (charset_info)), 7182 INTEGERP (text_encoding)) 7183 && CONSP (XCDR (XCDR (charset_info))) 7184 && (coding_system = XCAR (XCDR (XCDR (charset_info))), 7185 SYMBOLP (coding_system)))) 7186 continue; 7187 7188 existing_info = assq_no_quit (text_encoding, result); 7189 if (NILP (existing_info)) 7190 result = Fcons (list3 (text_encoding, coding_system, charset), 7191 result); 7192 else 7193 if (NILP (Fmember (charset, XCDR (XCDR (existing_info))))) 7194 XSETCDR (XCDR (existing_info), 7195 Fcons (charset, XCDR (XCDR (existing_info)))); 7196 } 7197 7198 return result; 7199} 7200 7201 7202static void 7203decode_mac_font_name (name, size, coding_system) 7204 char *name; 7205 int size; 7206 Lisp_Object coding_system; 7207{ 7208 struct coding_system coding; 7209 char *buf, *p; 7210 7211 if (!NILP (coding_system) && !NILP (Fcoding_system_p (coding_system))) 7212 { 7213 for (p = name; *p; p++) 7214 if (!isascii (*p) || iscntrl (*p)) 7215 break; 7216 7217 if (*p) 7218 { 7219 setup_coding_system (coding_system, &coding); 7220 coding.src_multibyte = 0; 7221 coding.dst_multibyte = 1; 7222 coding.mode |= CODING_MODE_LAST_BLOCK; 7223 coding.composing = COMPOSITION_DISABLED; 7224 buf = (char *) alloca (size); 7225 7226 decode_coding (&coding, name, buf, strlen (name), size - 1); 7227 bcopy (buf, name, coding.produced); 7228 name[coding.produced] = '\0'; 7229 } 7230 } 7231 7232 /* If there's just one occurrence of '-' in the family name, it is 7233 replaced with '_'. (More than one occurrence of '-' means a 7234 "FOUNDRY-FAMILY-CHARSET"-style name.) */ 7235 p = strchr (name, '-'); 7236 if (p && strchr (p + 1, '-') == NULL) 7237 *p = '_'; 7238 7239 for (p = name; *p; p++) 7240 /* On Mac OS X 10.3, tolower also converts non-ASCII characters 7241 for some locales. */ 7242 if (isascii (*p)) 7243 *p = tolower (*p); 7244} 7245 7246 7247static char * 7248mac_to_x_fontname (name, size, style, charset) 7249 const char *name; 7250 int size; 7251 Style style; 7252 char *charset; 7253{ 7254 Str31 foundry, cs; 7255 Str255 family; 7256 char xf[256], *result; 7257 unsigned char *p; 7258 7259 if (sscanf (name, "%31[^-]-%255[^-]-%31s", foundry, family, cs) == 3) 7260 charset = cs; 7261 else 7262 { 7263 strcpy(foundry, "Apple"); 7264 strcpy(family, name); 7265 } 7266 7267 sprintf (xf, "%s-%c-normal--%d-%d-%d-%d-m-%d-%s", 7268 style & bold ? "bold" : "medium", style & italic ? 'i' : 'r', 7269 size, size * 10, size ? 72 : 0, size ? 72 : 0, size * 10, charset); 7270 7271 result = xmalloc (strlen (foundry) + strlen (family) + strlen (xf) + 3 + 1); 7272 sprintf (result, "-%s-%s-%s", foundry, family, xf); 7273 for (p = result; *p; p++) 7274 /* On Mac OS X 10.3, tolower also converts non-ASCII characters 7275 for some locales. */ 7276 if (isascii (*p)) 7277 *p = tolower (*p); 7278 return result; 7279} 7280 7281 7282/* Parse fully-specified and instantiated X11 font spec XF, and store 7283 the results to FAMILY, *SIZE, *STYLE, and CHARSET. Return 1 if the 7284 parsing succeeded, and 0 otherwise. For FAMILY and CHARSET, the 7285 caller must allocate at least 256 and 32 bytes respectively. For 7286 ordinary Mac fonts, the value stored to FAMILY should just be their 7287 names, like "monaco", "Taipei", etc. Fonts converted from the GNU 7288 intlfonts collection contain their charset designation in their 7289 names, like "ETL-Fixed-iso8859-1", "ETL-Fixed-koi8-r", etc. Both 7290 types of font names are handled accordingly. */ 7291 7292const int kDefaultFontSize = 12; 7293 7294static int 7295parse_x_font_name (xf, family, size, style, charset) 7296 const char *xf; 7297 char *family; 7298 int *size; 7299 Style *style; 7300 char *charset; 7301{ 7302 Str31 foundry, weight; 7303 int point_size, avgwidth; 7304 char slant[2], *p; 7305 7306 if (sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]-%*[^-]-%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s", 7307 foundry, family, weight, slant, size, 7308 &point_size, &avgwidth, charset) != 8 7309 && sscanf (xf, "-%31[^-]-%255[^-]-%31[^-]-%1[^-]-%*[^-]--%d-%d-%*[^-]-%*[^-]-%*c-%d-%31s", 7310 foundry, family, weight, slant, size, 7311 &point_size, &avgwidth, charset) != 8) 7312 return 0; 7313 7314 if (*size == 0) 7315 { 7316 if (point_size > 0) 7317 *size = point_size / 10; 7318 else if (avgwidth > 0) 7319 *size = avgwidth / 10; 7320 } 7321 if (*size == 0) 7322 *size = kDefaultFontSize; 7323 7324 *style = normal; 7325 if (strcmp (weight, "bold") == 0) 7326 *style |= bold; 7327 if (*slant == 'i') 7328 *style |= italic; 7329 7330 if (NILP (Fassoc (build_string (charset), Vmac_charset_info_alist))) 7331 { 7332 int foundry_len = strlen (foundry), family_len = strlen (family); 7333 7334 if (foundry_len + family_len + strlen (charset) + 2 < sizeof (Str255)) 7335 { 7336 /* Like sprintf (family, "%s-%s-%s", foundry, family, charset), 7337 but take overlap into account. */ 7338 memmove (family + foundry_len + 1, family, family_len); 7339 memcpy (family, foundry, foundry_len); 7340 family[foundry_len] = '-'; 7341 family[foundry_len + 1 + family_len] = '-'; 7342 strcpy (family + foundry_len + 1 + family_len + 1, charset); 7343 } 7344 else 7345 return 0; 7346 } 7347 7348 for (p = family; *p; p++) 7349 /* On Mac OS X 10.3, tolower also converts non-ASCII characters 7350 for some locales. */ 7351 if (isascii (*p)) 7352 *p = tolower (*p); 7353 7354 return 1; 7355} 7356 7357 7358static void 7359add_font_name_table_entry (char *font_name) 7360{ 7361 if (font_name_table_size == 0) 7362 { 7363 font_name_table_size = 256; 7364 font_name_table = (char **) 7365 xmalloc (font_name_table_size * sizeof (char *)); 7366 } 7367 else if (font_name_count + 1 >= font_name_table_size) 7368 { 7369 font_name_table_size *= 2; 7370 font_name_table = (char **) 7371 xrealloc (font_name_table, 7372 font_name_table_size * sizeof (char *)); 7373 } 7374 7375 font_name_table[font_name_count++] = font_name; 7376} 7377 7378static void 7379add_mac_font_name (name, size, style, charset) 7380 const char *name; 7381 int size; 7382 Style style; 7383 const char *charset; 7384{ 7385 if (size > 0) 7386 add_font_name_table_entry (mac_to_x_fontname (name, size, style, charset)); 7387 else 7388 { 7389 add_font_name_table_entry (mac_to_x_fontname (name, 0, style, charset)); 7390 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic, charset)); 7391 add_font_name_table_entry (mac_to_x_fontname (name, 0, bold, charset)); 7392 add_font_name_table_entry (mac_to_x_fontname (name, 0, italic | bold, 7393 charset)); 7394 } 7395} 7396 7397#if USE_ATSUI 7398static FMFontStyle 7399fm_get_style_from_font (font) 7400 FMFont font; 7401{ 7402 OSStatus err; 7403 FMFontStyle style = normal; 7404 ByteCount len; 7405 UInt16 mac_style; 7406 FMFontFamily font_family; 7407#define FONT_HEADER_MAC_STYLE_OFFSET (4*4 + 2*2 + 8*2 + 2*4) 7408 7409 /* FMGetFontFamilyInstanceFromFont returns `normal' as the style of 7410 some font (e.g., Optima) even if it is `bold'. */ 7411 err = FMGetFontTable (font, 'head', FONT_HEADER_MAC_STYLE_OFFSET, 7412 sizeof (mac_style), &mac_style, &len); 7413 if (err == noErr 7414 && len >= FONT_HEADER_MAC_STYLE_OFFSET + sizeof (mac_style)) 7415 style = EndianU16_BtoN (mac_style); 7416 else 7417 FMGetFontFamilyInstanceFromFont (font, &font_family, &style); 7418 7419 return style; 7420} 7421 7422static ATSUFontID 7423atsu_find_font_from_family_name (family) 7424 const char *family; 7425{ 7426 struct Lisp_Hash_Table *h = XHASH_TABLE (atsu_font_id_hash); 7427 unsigned hash_code; 7428 int i; 7429 Lisp_Object rest, best; 7430 FMFontStyle min_style, style; 7431 7432 i = hash_lookup (h, make_unibyte_string (family, strlen (family)), 7433 &hash_code); 7434 if (i < 0) 7435 return kATSUInvalidFontID; 7436 7437 rest = HASH_VALUE (h, i); 7438 if (INTEGERP (rest) || (CONSP (rest) && INTEGERP (XCDR (rest)))) 7439 return cons_to_long (rest); 7440 7441 rest = Fnreverse (rest); 7442 best = XCAR (rest); 7443 rest = XCDR (rest); 7444 if (!NILP (rest) 7445 && (min_style = fm_get_style_from_font (cons_to_long (best))) != normal) 7446 do 7447 { 7448 style = fm_get_style_from_font (cons_to_long (XCAR (rest))); 7449 if (style < min_style) 7450 { 7451 best = XCAR (rest); 7452 if (style == normal) 7453 break; 7454 else 7455 min_style = style; 7456 } 7457 rest = XCDR (rest); 7458 } 7459 while (!NILP (rest)); 7460 7461 HASH_VALUE (h, i) = best; 7462 return cons_to_long (best); 7463} 7464 7465static Lisp_Object 7466fm_style_to_face_attributes (fm_style) 7467 FMFontStyle fm_style; 7468{ 7469 Lisp_Object tem; 7470 7471 fm_style &= (bold | italic); 7472 tem = assq_no_quit (make_number (fm_style), 7473 fm_style_face_attributes_alist); 7474 if (!NILP (tem)) 7475 return XCDR (tem); 7476 7477 tem = list4 (QCweight, fm_style & bold ? Qbold : Qnormal, 7478 QCslant, fm_style & italic ? Qitalic : Qnormal); 7479 fm_style_face_attributes_alist = 7480 Fcons (Fcons (make_number (fm_style), tem), 7481 fm_style_face_attributes_alist); 7482 7483 return tem; 7484} 7485 7486static Lisp_Object 7487atsu_find_font_family_name (font_id) 7488 ATSUFontID font_id; 7489{ 7490 OSStatus err; 7491 ByteCount len; 7492 Lisp_Object family = Qnil; 7493 7494 err = ATSUFindFontName (font_id, kFontFamilyName, 7495 kFontMacintoshPlatform, kFontNoScript, 7496 kFontNoLanguage, 0, NULL, &len, NULL); 7497 if (err == noErr) 7498 { 7499 family = make_uninit_string (len); 7500 err = ATSUFindFontName (font_id, kFontFamilyName, 7501 kFontMacintoshPlatform, kFontNoScript, 7502 kFontNoLanguage, len, SDATA (family), 7503 NULL, NULL); 7504 } 7505 if (err == noErr) 7506 decode_mac_font_name (SDATA (family), len + 1, Qnil); 7507 7508 return family; 7509} 7510 7511Lisp_Object 7512mac_atsu_font_face_attributes (font_id) 7513 ATSUFontID font_id; 7514{ 7515 Lisp_Object family, style_attrs; 7516 7517 family = atsu_find_font_family_name (font_id); 7518 if (NILP (family)) 7519 return Qnil; 7520 style_attrs = fm_style_to_face_attributes (fm_get_style_from_font (font_id)); 7521 return Fcons (QCfamily, Fcons (family, style_attrs)); 7522} 7523#endif 7524 7525/* Sets up the table font_name_table to contain the list of all fonts 7526 in the system the first time the table is used so that the Resource 7527 Manager need not be accessed every time this information is 7528 needed. */ 7529 7530static void 7531init_font_name_table () 7532{ 7533#if TARGET_API_MAC_CARBON 7534 FMFontFamilyIterator ffi; 7535 FMFontFamilyInstanceIterator ffii; 7536 FMFontFamily ff; 7537 Lisp_Object text_encoding_info_alist; 7538 struct gcpro gcpro1; 7539 7540 text_encoding_info_alist = create_text_encoding_info_alist (); 7541 7542#if USE_ATSUI 7543#if USE_CG_TEXT_DRAWING 7544 init_cg_text_anti_aliasing_threshold (); 7545#endif 7546 if (!NILP (assq_no_quit (make_number (kTextEncodingMacUnicode), 7547 text_encoding_info_alist))) 7548 { 7549 OSStatus err; 7550 struct Lisp_Hash_Table *h; 7551 unsigned hash_code; 7552 ItemCount nfonts, i; 7553 ATSUFontID *font_ids = NULL; 7554 Lisp_Object prev_family = Qnil; 7555 int j; 7556 7557 atsu_font_id_hash = 7558 make_hash_table (Qequal, make_number (DEFAULT_HASH_SIZE), 7559 make_float (DEFAULT_REHASH_SIZE), 7560 make_float (DEFAULT_REHASH_THRESHOLD), 7561 Qnil, Qnil, Qnil);; 7562 h = XHASH_TABLE (atsu_font_id_hash); 7563 7564 err = ATSUFontCount (&nfonts); 7565 if (err == noErr) 7566 { 7567 font_ids = xmalloc (sizeof (ATSUFontID) * nfonts); 7568 err = ATSUGetFontIDs (font_ids, nfonts, NULL); 7569 } 7570 if (err == noErr) 7571 for (i = 0; i < nfonts; i++) 7572 { 7573 Lisp_Object family; 7574 7575 family = atsu_find_font_family_name (font_ids[i]); 7576 if (NILP (family) || SREF (family, 0) == '.') 7577 continue; 7578 if (!NILP (Fequal (prev_family, family))) 7579 family = prev_family; 7580 else 7581 j = hash_lookup (h, family, &hash_code); 7582 if (j < 0) 7583 { 7584 add_mac_font_name (SDATA (family), 0, normal, "iso10646-1"); 7585 j = hash_put (h, family, Fcons (long_to_cons (font_ids[i]), 7586 Qnil), hash_code); 7587 } 7588 else if (EQ (prev_family, family)) 7589 HASH_VALUE (h, j) = Fcons (long_to_cons (font_ids[i]), 7590 HASH_VALUE (h, j)); 7591 prev_family = family; 7592 } 7593 if (font_ids) 7594 xfree (font_ids); 7595 } 7596#endif 7597 7598 /* Create a dummy instance iterator here to avoid creating and 7599 destroying it in the loop. */ 7600 if (FMCreateFontFamilyInstanceIterator (0, &ffii) != noErr) 7601 return; 7602 /* Create an iterator to enumerate the font families. */ 7603 if (FMCreateFontFamilyIterator (NULL, NULL, kFMDefaultOptions, &ffi) 7604 != noErr) 7605 { 7606 FMDisposeFontFamilyInstanceIterator (&ffii); 7607 return; 7608 } 7609 7610 GCPRO1 (text_encoding_info_alist); 7611 7612 while (FMGetNextFontFamily (&ffi, &ff) == noErr) 7613 { 7614 Str255 name; 7615 FMFont font; 7616 FMFontStyle style; 7617 FMFontSize size; 7618 TextEncoding encoding; 7619 TextEncodingBase sc; 7620 Lisp_Object text_encoding_info, family; 7621 7622 if (FMGetFontFamilyName (ff, name) != noErr) 7623 continue; 7624 p2cstr (name); 7625 if (*name == '.') 7626 continue; 7627 7628 if (FMGetFontFamilyTextEncoding (ff, &encoding) != noErr) 7629 continue; 7630 sc = GetTextEncodingBase (encoding); 7631 text_encoding_info = assq_no_quit (make_number (sc), 7632 text_encoding_info_alist); 7633 if (NILP (text_encoding_info)) 7634 text_encoding_info = assq_no_quit (make_number (kTextEncodingMacRoman), 7635 text_encoding_info_alist); 7636 decode_mac_font_name (name, sizeof (name), 7637 XCAR (XCDR (text_encoding_info))); 7638 family = build_string (name); 7639 if (!NILP (Fassoc (family, fm_font_family_alist))) 7640 continue; 7641 fm_font_family_alist = Fcons (Fcons (family, make_number (ff)), 7642 fm_font_family_alist); 7643 7644 /* Point the instance iterator at the current font family. */ 7645 if (FMResetFontFamilyInstanceIterator (ff, &ffii) != noErr) 7646 continue; 7647 7648 while (FMGetNextFontFamilyInstance (&ffii, &font, &style, &size) 7649 == noErr) 7650 { 7651 Lisp_Object rest = XCDR (XCDR (text_encoding_info)); 7652 7653 if (size > 0 || style == normal) 7654 for (; !NILP (rest); rest = XCDR (rest)) 7655 add_mac_font_name (name, size, style, SDATA (XCAR (rest))); 7656 } 7657 } 7658 7659 UNGCPRO; 7660 7661 /* Dispose of the iterators. */ 7662 FMDisposeFontFamilyIterator (&ffi); 7663 FMDisposeFontFamilyInstanceIterator (&ffii); 7664#else /* !TARGET_API_MAC_CARBON */ 7665 GrafPtr port; 7666 SInt16 fontnum, old_fontnum; 7667 int num_mac_fonts = CountResources('FOND'); 7668 int i, j; 7669 Handle font_handle, font_handle_2; 7670 short id, scriptcode; 7671 ResType type; 7672 Str255 name; 7673 struct FontAssoc *fat; 7674 struct AsscEntry *assc_entry; 7675 Lisp_Object text_encoding_info_alist, text_encoding_info, family; 7676 struct gcpro gcpro1; 7677 7678 GetPort (&port); /* save the current font number used */ 7679 old_fontnum = port->txFont; 7680 7681 text_encoding_info_alist = create_text_encoding_info_alist (); 7682 7683 GCPRO1 (text_encoding_info_alist); 7684 7685 for (i = 1; i <= num_mac_fonts; i++) /* get all available fonts */ 7686 { 7687 font_handle = GetIndResource ('FOND', i); 7688 if (!font_handle) 7689 continue; 7690 7691 GetResInfo (font_handle, &id, &type, name); 7692 GetFNum (name, &fontnum); 7693 p2cstr (name); 7694 if (fontnum == 0 || *name == '.') 7695 continue; 7696 7697 TextFont (fontnum); 7698 scriptcode = FontToScript (fontnum); 7699 text_encoding_info = assq_no_quit (make_number (scriptcode), 7700 text_encoding_info_alist); 7701 if (NILP (text_encoding_info)) 7702 text_encoding_info = assq_no_quit (make_number (smRoman), 7703 text_encoding_info_alist); 7704 decode_mac_font_name (name, sizeof (name), 7705 XCAR (XCDR (text_encoding_info))); 7706 family = build_string (name); 7707 if (!NILP (Fassoc (family, fm_font_family_alist))) 7708 continue; 7709 fm_font_family_alist = Fcons (Fcons (family, make_number (fontnum)), 7710 fm_font_family_alist); 7711 do 7712 { 7713 HLock (font_handle); 7714 7715 if (GetResourceSizeOnDisk (font_handle) 7716 >= sizeof (struct FamRec)) 7717 { 7718 fat = (struct FontAssoc *) (*font_handle 7719 + sizeof (struct FamRec)); 7720 assc_entry 7721 = (struct AsscEntry *) (*font_handle 7722 + sizeof (struct FamRec) 7723 + sizeof (struct FontAssoc)); 7724 7725 for (j = 0; j <= fat->numAssoc; j++, assc_entry++) 7726 { 7727 Lisp_Object rest = XCDR (XCDR (text_encoding_info)); 7728 7729 for (; !NILP (rest); rest = XCDR (rest)) 7730 add_mac_font_name (name, assc_entry->fontSize, 7731 assc_entry->fontStyle, 7732 SDATA (XCAR (rest))); 7733 } 7734 } 7735 7736 HUnlock (font_handle); 7737 font_handle_2 = GetNextFOND (font_handle); 7738 ReleaseResource (font_handle); 7739 font_handle = font_handle_2; 7740 } 7741 while (ResError () == noErr && font_handle); 7742 } 7743 7744 UNGCPRO; 7745 7746 TextFont (old_fontnum); 7747#endif /* !TARGET_API_MAC_CARBON */ 7748} 7749 7750 7751void 7752mac_clear_font_name_table () 7753{ 7754 int i; 7755 7756 for (i = 0; i < font_name_count; i++) 7757 xfree (font_name_table[i]); 7758 xfree (font_name_table); 7759 font_name_table = NULL; 7760 font_name_table_size = font_name_count = 0; 7761 fm_font_family_alist = Qnil; 7762} 7763 7764 7765enum xlfd_scalable_field_index 7766 { 7767 XLFD_SCL_PIXEL_SIZE, 7768 XLFD_SCL_POINT_SIZE, 7769 XLFD_SCL_AVGWIDTH, 7770 XLFD_SCL_LAST 7771 }; 7772 7773static const int xlfd_scalable_fields[] = 7774 { 7775 6, /* PIXEL_SIZE */ 7776 7, /* POINT_SIZE */ 7777 11, /* AVGWIDTH */ 7778 -1 7779 }; 7780 7781static Lisp_Object 7782mac_do_list_fonts (pattern, maxnames) 7783 const char *pattern; 7784 int maxnames; 7785{ 7786 int i, n_fonts = 0; 7787 Lisp_Object font_list = Qnil; 7788 struct xlfdpat *pat; 7789 char *scaled; 7790 const char *ptr; 7791 int scl_val[XLFD_SCL_LAST], *val; 7792 const int *field; 7793 int exact; 7794 7795 if (font_name_table == NULL) /* Initialize when first used. */ 7796 init_font_name_table (); 7797 7798 for (i = 0; i < XLFD_SCL_LAST; i++) 7799 scl_val[i] = -1; 7800 7801 /* If the pattern contains 14 dashes and one of PIXEL_SIZE, 7802 POINT_SIZE, and AVGWIDTH fields is explicitly specified, scalable 7803 fonts are scaled according to the specified size. */ 7804 ptr = pattern; 7805 i = 0; 7806 field = xlfd_scalable_fields; 7807 val = scl_val; 7808 if (*ptr == '-') 7809 do 7810 { 7811 ptr++; 7812 if (i == *field) 7813 { 7814 if ('0' <= *ptr && *ptr <= '9') 7815 { 7816 *val = *ptr++ - '0'; 7817 while ('0' <= *ptr && *ptr <= '9' && *val < 10000) 7818 *val = *val * 10 + *ptr++ - '0'; 7819 if (*ptr != '-') 7820 *val = -1; 7821 } 7822 field++; 7823 val++; 7824 } 7825 ptr = strchr (ptr, '-'); 7826 i++; 7827 } 7828 while (ptr && i < 14); 7829 7830 if (i == 14 && ptr == NULL) 7831 { 7832 if (scl_val[XLFD_SCL_PIXEL_SIZE] < 0) 7833 scl_val[XLFD_SCL_PIXEL_SIZE] = 7834 (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE] / 10 7835 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH] / 10 7836 : -1)); 7837 if (scl_val[XLFD_SCL_POINT_SIZE] < 0) 7838 scl_val[XLFD_SCL_POINT_SIZE] = 7839 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10 7840 : (scl_val[XLFD_SCL_AVGWIDTH] > 0 ? scl_val[XLFD_SCL_AVGWIDTH] 7841 : -1)); 7842 if (scl_val[XLFD_SCL_AVGWIDTH] < 0) 7843 scl_val[XLFD_SCL_AVGWIDTH] = 7844 (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 ? scl_val[XLFD_SCL_PIXEL_SIZE] * 10 7845 : (scl_val[XLFD_SCL_POINT_SIZE] > 0 ? scl_val[XLFD_SCL_POINT_SIZE] 7846 : -1)); 7847 } 7848 else 7849 scl_val[XLFD_SCL_PIXEL_SIZE] = -1; 7850 7851 pat = xlfdpat_create (pattern); 7852 if (pat == NULL) 7853 return Qnil; 7854 7855 exact = xlfdpat_exact_p (pat); 7856 7857 for (i = 0; i < font_name_count; i++) 7858 { 7859 if (xlfdpat_match (pat, font_name_table[i])) 7860 { 7861 font_list = Fcons (build_string (font_name_table[i]), font_list); 7862 if (exact || (maxnames > 0 && ++n_fonts >= maxnames)) 7863 break; 7864 } 7865 else if (scl_val[XLFD_SCL_PIXEL_SIZE] > 0 7866 && (ptr = strstr (font_name_table[i], "-0-0-0-0-m-0-"))) 7867 { 7868 int former_len = ptr - font_name_table[i]; 7869 7870 scaled = xmalloc (strlen (font_name_table[i]) + 20 + 1); 7871 memcpy (scaled, font_name_table[i], former_len); 7872 sprintf (scaled + former_len, 7873 "-%d-%d-72-72-m-%d-%s", 7874 scl_val[XLFD_SCL_PIXEL_SIZE], 7875 scl_val[XLFD_SCL_POINT_SIZE], 7876 scl_val[XLFD_SCL_AVGWIDTH], 7877 ptr + sizeof ("-0-0-0-0-m-0-") - 1); 7878 7879 if (xlfdpat_match (pat, scaled)) 7880 { 7881 font_list = Fcons (build_string (scaled), font_list); 7882 xfree (scaled); 7883 if (exact || (maxnames > 0 && ++n_fonts >= maxnames)) 7884 break; 7885 } 7886 else 7887 xfree (scaled); 7888 } 7889 } 7890 7891 xlfdpat_destroy (pat); 7892 7893 return font_list; 7894} 7895 7896/* Return a list of names of available fonts matching PATTERN on frame F. 7897 7898 Frame F null means we have not yet created any frame on Mac, and 7899 consult the first display in x_display_list. MAXNAMES sets a limit 7900 on how many fonts to match. */ 7901 7902Lisp_Object 7903x_list_fonts (f, pattern, size, maxnames) 7904 struct frame *f; 7905 Lisp_Object pattern; 7906 int size, maxnames; 7907{ 7908 Lisp_Object list = Qnil, patterns, tem, key; 7909 struct mac_display_info *dpyinfo 7910 = f ? FRAME_MAC_DISPLAY_INFO (f) : x_display_list; 7911 7912 xassert (size <= 0); 7913 7914 patterns = Fassoc (pattern, Valternate_fontname_alist); 7915 if (NILP (patterns)) 7916 patterns = Fcons (pattern, Qnil); 7917 7918 for (; CONSP (patterns); patterns = XCDR (patterns)) 7919 { 7920 pattern = XCAR (patterns); 7921 7922 if (!STRINGP (pattern)) 7923 continue; 7924 7925 tem = XCAR (XCDR (dpyinfo->name_list_element)); 7926 key = Fcons (pattern, make_number (maxnames)); 7927 7928 list = Fassoc (key, tem); 7929 if (!NILP (list)) 7930 { 7931 list = Fcdr_safe (list); 7932 /* We have a cashed list. Don't have to get the list again. */ 7933 goto label_cached; 7934 } 7935 7936 BLOCK_INPUT; 7937 list = mac_do_list_fonts (SDATA (pattern), maxnames); 7938 UNBLOCK_INPUT; 7939 7940 /* MAC_TODO: add code for matching outline fonts here */ 7941 7942 /* Now store the result in the cache. */ 7943 XSETCAR (XCDR (dpyinfo->name_list_element), 7944 Fcons (Fcons (key, list), 7945 XCAR (XCDR (dpyinfo->name_list_element)))); 7946 7947 label_cached: 7948 if (NILP (list)) continue; /* Try the remaining alternatives. */ 7949 } 7950 7951 return list; 7952} 7953 7954 7955#if GLYPH_DEBUG 7956 7957/* Check that FONT is valid on frame F. It is if it can be found in F's 7958 font table. */ 7959 7960static void 7961x_check_font (f, font) 7962 struct frame *f; 7963 XFontStruct *font; 7964{ 7965 int i; 7966 struct x_display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f); 7967 7968 xassert (font != NULL); 7969 7970 for (i = 0; i < dpyinfo->n_fonts; i++) 7971 if (dpyinfo->font_table[i].name 7972 && font == dpyinfo->font_table[i].font) 7973 break; 7974 7975 xassert (i < dpyinfo->n_fonts); 7976} 7977 7978#endif /* GLYPH_DEBUG != 0 */ 7979 7980/* Set *W to the minimum width, *H to the minimum font height of FONT. 7981 Note: There are (broken) X fonts out there with invalid XFontStruct 7982 min_bounds contents. For example, handa@etl.go.jp reports that 7983 "-adobe-courier-medium-r-normal--*-180-*-*-m-*-iso8859-1" fonts 7984 have font->min_bounds.width == 0. */ 7985 7986static INLINE void 7987x_font_min_bounds (font, w, h) 7988 MacFontStruct *font; 7989 int *w, *h; 7990{ 7991 *h = FONT_HEIGHT (font); 7992 *w = font->min_bounds.width; 7993} 7994 7995 7996/* Compute the smallest character width and smallest font height over 7997 all fonts available on frame F. Set the members smallest_char_width 7998 and smallest_font_height in F's x_display_info structure to 7999 the values computed. Value is non-zero if smallest_font_height or 8000 smallest_char_width become smaller than they were before. */ 8001 8002static int 8003x_compute_min_glyph_bounds (f) 8004 struct frame *f; 8005{ 8006 int i; 8007 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f); 8008 MacFontStruct *font; 8009 int old_width = dpyinfo->smallest_char_width; 8010 int old_height = dpyinfo->smallest_font_height; 8011 8012 dpyinfo->smallest_font_height = 100000; 8013 dpyinfo->smallest_char_width = 100000; 8014 8015 for (i = 0; i < dpyinfo->n_fonts; ++i) 8016 if (dpyinfo->font_table[i].name) 8017 { 8018 struct font_info *fontp = dpyinfo->font_table + i; 8019 int w, h; 8020 8021 font = (MacFontStruct *) fontp->font; 8022 xassert (font != (MacFontStruct *) ~0); 8023 x_font_min_bounds (font, &w, &h); 8024 8025 dpyinfo->smallest_font_height = min (dpyinfo->smallest_font_height, h); 8026 dpyinfo->smallest_char_width = min (dpyinfo->smallest_char_width, w); 8027 } 8028 8029 xassert (dpyinfo->smallest_char_width > 0 8030 && dpyinfo->smallest_font_height > 0); 8031 8032 return (dpyinfo->n_fonts == 1 8033 || dpyinfo->smallest_char_width < old_width 8034 || dpyinfo->smallest_font_height < old_height); 8035} 8036 8037 8038/* Determine whether given string is a fully-specified XLFD: all 14 8039 fields are present, none is '*'. */ 8040 8041static int 8042is_fully_specified_xlfd (p) 8043 const char *p; 8044{ 8045 int i; 8046 char *q; 8047 8048 if (*p != '-') 8049 return 0; 8050 8051 for (i = 0; i < 13; i++) 8052 { 8053 q = strchr (p + 1, '-'); 8054 if (q == NULL) 8055 return 0; 8056 if (q - p == 2 && *(p + 1) == '*') 8057 return 0; 8058 p = q; 8059 } 8060 8061 if (strchr (p + 1, '-') != NULL) 8062 return 0; 8063 8064 if (*(p + 1) == '*' && *(p + 2) == '\0') 8065 return 0; 8066 8067 return 1; 8068} 8069 8070 8071/* mac_load_query_font creates and returns an internal representation 8072 for a font in a MacFontStruct struct. There is really no concept 8073 corresponding to "loading" a font on the Mac. But we check its 8074 existence and find the font number and all other information for it 8075 and store them in the returned MacFontStruct. */ 8076 8077static MacFontStruct * 8078mac_load_query_font (f, fontname) 8079 struct frame *f; 8080 char *fontname; 8081{ 8082 int size; 8083 char *name; 8084 Str255 family; 8085 Str31 charset; 8086 SInt16 fontnum; 8087#if USE_ATSUI 8088 static ATSUFontID font_id; 8089 ATSUStyle mac_style = NULL; 8090#endif 8091 Style fontface; 8092#if TARGET_API_MAC_CARBON 8093 TextEncoding encoding; 8094 int scriptcode; 8095#else 8096 short scriptcode; 8097#endif 8098 MacFontStruct *font; 8099 XCharStruct *space_bounds = NULL, *pcm; 8100 8101 if (is_fully_specified_xlfd (fontname)) 8102 name = fontname; 8103 else 8104 { 8105 Lisp_Object matched_fonts; 8106 8107 matched_fonts = mac_do_list_fonts (fontname, 1); 8108 if (NILP (matched_fonts)) 8109 return NULL; 8110 name = SDATA (XCAR (matched_fonts)); 8111 } 8112 8113 if (parse_x_font_name (name, family, &size, &fontface, charset) == 0) 8114 return NULL; 8115 8116#if USE_ATSUI 8117 if (strcmp (charset, "iso10646-1") == 0) /* XXX */ 8118 { 8119 OSStatus err; 8120 static const ATSUAttributeTag tags[] = 8121 {kATSUFontTag, kATSUSizeTag, 8122 kATSUQDBoldfaceTag, kATSUQDItalicTag}; 8123 static const ByteCount sizes[] = 8124 {sizeof (ATSUFontID), sizeof (Fixed), 8125 sizeof (Boolean), sizeof (Boolean)}; 8126 static Fixed size_fixed; 8127 static Boolean bold_p, italic_p; 8128 static const ATSUAttributeValuePtr values[] = 8129 {&font_id, &size_fixed, 8130 &bold_p, &italic_p}; 8131 static const ATSUFontFeatureType types[] = 8132 {kAllTypographicFeaturesType, kDiacriticsType}; 8133 static const ATSUFontFeatureSelector selectors[] = 8134 {kAllTypeFeaturesOffSelector, kDecomposeDiacriticsSelector}; 8135 FMFontStyle style; 8136 8137 font_id = atsu_find_font_from_family_name (family); 8138 if (font_id == kATSUInvalidFontID) 8139 return; 8140 size_fixed = Long2Fix (size); 8141 bold_p = (fontface & bold) != 0; 8142 italic_p = (fontface & italic) != 0; 8143 err = ATSUCreateStyle (&mac_style); 8144 if (err != noErr) 8145 return NULL; 8146 err = ATSUSetFontFeatures (mac_style, sizeof (types) / sizeof (types[0]), 8147 types, selectors); 8148 if (err != noErr) 8149 return NULL; 8150 err = ATSUSetAttributes (mac_style, sizeof (tags) / sizeof (tags[0]), 8151 tags, sizes, values); 8152 if (err != noErr) 8153 return NULL; 8154 err = FMGetFontFamilyInstanceFromFont (font_id, &fontnum, &style); 8155 if (err != noErr) 8156 fontnum = -1; 8157 scriptcode = kTextEncodingMacUnicode; 8158 } 8159 else 8160#endif 8161 { 8162 Lisp_Object tmp = Fassoc (build_string (family), fm_font_family_alist); 8163 8164 if (NILP (tmp)) 8165 return NULL; 8166 fontnum = XINT (XCDR (tmp)); 8167#if TARGET_API_MAC_CARBON 8168 if (FMGetFontFamilyTextEncoding (fontnum, &encoding) != noErr) 8169 return NULL; 8170 scriptcode = GetTextEncodingBase (encoding); 8171#else 8172 scriptcode = FontToScript (fontnum); 8173#endif 8174 } 8175 8176 font = (MacFontStruct *) xmalloc (sizeof (struct MacFontStruct)); 8177 8178 font->mac_fontnum = fontnum; 8179 font->mac_fontsize = size; 8180 font->mac_fontface = fontface; 8181 font->mac_scriptcode = scriptcode; 8182#if USE_ATSUI 8183 font->mac_style = mac_style; 8184#if USE_CG_TEXT_DRAWING 8185 font->cg_font = NULL; 8186 font->cg_glyphs = NULL; 8187#endif 8188#endif 8189 8190 /* Apple Japanese (SJIS) font is listed as both 8191 "*-jisx0208.1983-sjis" (Japanese script) and "*-jisx0201.1976-0" 8192 (Roman script) in init_font_name_table (). The latter should be 8193 treated as a one-byte font. */ 8194 if (scriptcode == smJapanese && strcmp (charset, "jisx0201.1976-0") == 0) 8195 font->mac_scriptcode = smRoman; 8196 8197 font->full_name = mac_to_x_fontname (family, size, fontface, charset); 8198 8199#if USE_ATSUI 8200 if (font->mac_style) 8201 { 8202 OSStatus err; 8203 UniChar c; 8204 8205 font->min_byte1 = 0; 8206 font->max_byte1 = 0xff; 8207 font->min_char_or_byte2 = 0; 8208 font->max_char_or_byte2 = 0xff; 8209 8210 font->bounds.rows = xmalloc (sizeof (XCharStruct *) * 0x100); 8211 bzero (font->bounds.rows, sizeof (XCharStruct *) * 0x100); 8212 font->bounds.rows[0] = xmalloc (sizeof (XCharStruct) * 0x100); 8213 pcm_init (font->bounds.rows[0], 0x100); 8214 8215#if USE_CG_TEXT_DRAWING 8216 if (fontnum != -1) 8217 { 8218 FMFontStyle style; 8219 ATSFontRef ats_font; 8220 8221 err = FMGetFontFromFontFamilyInstance (fontnum, fontface, 8222 &font_id, &style); 8223 /* Use CG text drawing if italic/bold is not synthesized. */ 8224 if (err == noErr && style == fontface) 8225 { 8226 ats_font = FMGetATSFontRefFromFont (font_id); 8227 font->cg_font = CGFontCreateWithPlatformFont (&ats_font); 8228 } 8229 } 8230 8231 if (font->cg_font) 8232 { 8233 font->cg_glyphs = xmalloc (sizeof (CGGlyph) * 0x100); 8234 bzero (font->cg_glyphs, sizeof (CGGlyph) * 0x100); 8235 } 8236#endif 8237 space_bounds = font->bounds.rows[0] + 0x20; 8238 err = mac_query_char_extents (font->mac_style, 0x20, 8239 &font->ascent, &font->descent, 8240 space_bounds, 8241#if USE_CG_TEXT_DRAWING 8242 (font->cg_glyphs ? font->cg_glyphs + 0x20 8243 : NULL) 8244#else 8245 NULL 8246#endif 8247 ); 8248 if (err != noErr 8249 || space_bounds->width <= 0 || FONT_HEIGHT (font) <= 0) 8250 { 8251 mac_unload_font (&one_mac_display_info, font); 8252 return NULL; 8253 } 8254 8255 pcm = font->bounds.rows[0]; 8256 for (c = 0x21; c <= 0xff; c++) 8257 { 8258 if (c == 0xad) 8259 /* Soft hyphen is not supported in ATSUI. */ 8260 continue; 8261 else if (c == 0x7f) 8262 { 8263#if USE_CG_TEXT_DRAWING 8264 if (font->cg_glyphs) 8265 { 8266 c = 0x9f; 8267 pcm = NULL; 8268 continue; 8269 } 8270#endif 8271 break; 8272 } 8273 8274 mac_query_char_extents (font->mac_style, c, NULL, NULL, 8275 pcm ? pcm + c : NULL, 8276#if USE_CG_TEXT_DRAWING 8277 (font->cg_glyphs ? font->cg_glyphs + c 8278 : NULL) 8279#else 8280 NULL 8281#endif 8282 ); 8283 8284#if USE_CG_TEXT_DRAWING 8285 if (font->cg_glyphs && font->cg_glyphs[c] == 0) 8286 { 8287 /* Don't use CG text drawing if font substitution occurs in 8288 ASCII or Latin-1 characters. */ 8289 CGFontRelease (font->cg_font); 8290 font->cg_font = NULL; 8291 xfree (font->cg_glyphs); 8292 font->cg_glyphs = NULL; 8293 if (pcm == NULL) 8294 break; 8295 } 8296#endif 8297 } 8298 } 8299 else 8300#endif 8301 { 8302 OSStatus err; 8303 FontInfo the_fontinfo; 8304 int is_two_byte_font; 8305 8306#if USE_CG_DRAWING 8307 mac_prepare_for_quickdraw (f); 8308#endif 8309 SetPortWindowPort (FRAME_MAC_WINDOW (f)); 8310 8311 TextFont (fontnum); 8312 TextSize (size); 8313 TextFace (fontface); 8314 8315 GetFontInfo (&the_fontinfo); 8316 8317 font->ascent = the_fontinfo.ascent; 8318 font->descent = the_fontinfo.descent; 8319 8320 is_two_byte_font = (font->mac_scriptcode == smJapanese 8321 || font->mac_scriptcode == smTradChinese 8322 || font->mac_scriptcode == smSimpChinese 8323 || font->mac_scriptcode == smKorean); 8324 8325 if (is_two_byte_font) 8326 { 8327 int char_width; 8328 8329 font->min_byte1 = 0xa1; 8330 font->max_byte1 = 0xfe; 8331 font->min_char_or_byte2 = 0xa1; 8332 font->max_char_or_byte2 = 0xfe; 8333 8334 /* Use the width of an "ideographic space" of that font 8335 because the_fontinfo.widMax returns the wrong width for 8336 some fonts. */ 8337 switch (font->mac_scriptcode) 8338 { 8339 case smJapanese: 8340 font->min_byte1 = 0x81; 8341 font->max_byte1 = 0xfc; 8342 font->min_char_or_byte2 = 0x40; 8343 font->max_char_or_byte2 = 0xfc; 8344 char_width = StringWidth("\p\x81\x40"); 8345 break; 8346 case smTradChinese: 8347 font->min_char_or_byte2 = 0x40; 8348 char_width = StringWidth("\p\xa1\x40"); 8349 break; 8350 case smSimpChinese: 8351 char_width = StringWidth("\p\xa1\xa1"); 8352 break; 8353 case smKorean: 8354 char_width = StringWidth("\p\xa1\xa1"); 8355 break; 8356 } 8357 8358 font->bounds.per_char = NULL; 8359 8360 if (fontface & italic) 8361 font->max_bounds.rbearing = char_width + 1; 8362 else 8363 font->max_bounds.rbearing = char_width; 8364 font->max_bounds.lbearing = 0; 8365 font->max_bounds.width = char_width; 8366 font->max_bounds.ascent = the_fontinfo.ascent; 8367 font->max_bounds.descent = the_fontinfo.descent; 8368 8369 font->min_bounds = font->max_bounds; 8370 } 8371 else 8372 { 8373 int c; 8374 8375 font->min_byte1 = font->max_byte1 = 0; 8376 font->min_char_or_byte2 = 0x20; 8377 font->max_char_or_byte2 = 0xff; 8378 8379 font->bounds.per_char = 8380 xmalloc (sizeof (XCharStruct) * (0xff - 0x20 + 1)); 8381 bzero (font->bounds.per_char, 8382 sizeof (XCharStruct) * (0xff - 0x20 + 1)); 8383 8384 space_bounds = font->bounds.per_char; 8385 err = mac_query_char_extents (NULL, 0x20, &font->ascent, 8386 &font->descent, space_bounds, NULL); 8387 if (err != noErr || space_bounds->width <= 0) 8388 { 8389 mac_unload_font (&one_mac_display_info, font); 8390 return NULL; 8391 } 8392 8393 for (c = 0x21, pcm = space_bounds + 1; c <= 0xff; c++, pcm++) 8394 mac_query_char_extents (NULL, c, NULL, NULL, pcm, NULL); 8395 } 8396 } 8397 8398 if (space_bounds) 8399 { 8400 int c; 8401 8402 font->min_bounds = font->max_bounds = *space_bounds; 8403 for (c = 0x21, pcm = space_bounds + 1; c <= 0x7f; c++, pcm++) 8404 if (pcm->width > 0) 8405 { 8406 font->min_bounds.lbearing = min (font->min_bounds.lbearing, 8407 pcm->lbearing); 8408 font->min_bounds.rbearing = min (font->min_bounds.rbearing, 8409 pcm->rbearing); 8410 font->min_bounds.width = min (font->min_bounds.width, 8411 pcm->width); 8412 font->min_bounds.ascent = min (font->min_bounds.ascent, 8413 pcm->ascent); 8414 font->min_bounds.descent = min (font->min_bounds.descent, 8415 pcm->descent); 8416 8417 font->max_bounds.lbearing = max (font->max_bounds.lbearing, 8418 pcm->lbearing); 8419 font->max_bounds.rbearing = max (font->max_bounds.rbearing, 8420 pcm->rbearing); 8421 font->max_bounds.width = max (font->max_bounds.width, 8422 pcm->width); 8423 font->max_bounds.ascent = max (font->max_bounds.ascent, 8424 pcm->ascent); 8425 font->max_bounds.descent = max (font->max_bounds.descent, 8426 pcm->descent); 8427 } 8428 if ( 8429#if USE_ATSUI 8430 font->mac_style == NULL && 8431#endif 8432 font->max_bounds.width == font->min_bounds.width 8433 && font->min_bounds.lbearing >= 0 8434 && font->max_bounds.rbearing <= font->max_bounds.width) 8435 { 8436 /* Fixed width and no overhangs. */ 8437 xfree (font->bounds.per_char); 8438 font->bounds.per_char = NULL; 8439 } 8440 } 8441 8442#if !defined (MAC_OS8) || USE_ATSUI 8443 /* AppKit and WebKit do some adjustment to the heights of Courier, 8444 Helvetica, and Times. This only works on the environments where 8445 srcCopy text transfer mode is never used. */ 8446 if ( 8447#ifdef MAC_OS8 /* implies USE_ATSUI */ 8448 font->mac_style && 8449#endif 8450 (strcmp (family, "courier") == 0 || strcmp (family, "helvetica") == 0 8451 || strcmp (family, "times") == 0)) 8452 font->ascent += (font->ascent + font->descent) * .15 + 0.5; 8453#endif 8454 8455 return font; 8456} 8457 8458 8459void 8460mac_unload_font (dpyinfo, font) 8461 struct mac_display_info *dpyinfo; 8462 XFontStruct *font; 8463{ 8464 xfree (font->full_name); 8465#if USE_ATSUI 8466 if (font->mac_style) 8467 { 8468 int i; 8469 8470 for (i = font->min_byte1; i <= font->max_byte1; i++) 8471 if (font->bounds.rows[i]) 8472 xfree (font->bounds.rows[i]); 8473 xfree (font->bounds.rows); 8474 ATSUDisposeStyle (font->mac_style); 8475 } 8476 else 8477#endif 8478 if (font->bounds.per_char) 8479 xfree (font->bounds.per_char); 8480#if USE_CG_TEXT_DRAWING 8481 if (font->cg_font) 8482 CGFontRelease (font->cg_font); 8483 if (font->cg_glyphs) 8484 xfree (font->cg_glyphs); 8485#endif 8486 xfree (font); 8487} 8488 8489 8490/* Load font named FONTNAME of the size SIZE for frame F, and return a 8491 pointer to the structure font_info while allocating it dynamically. 8492 If SIZE is 0, load any size of font. 8493 If loading is failed, return NULL. */ 8494 8495struct font_info * 8496x_load_font (f, fontname, size) 8497 struct frame *f; 8498 register char *fontname; 8499 int size; 8500{ 8501 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f); 8502 Lisp_Object font_names; 8503 8504 /* Get a list of all the fonts that match this name. Once we 8505 have a list of matching fonts, we compare them against the fonts 8506 we already have by comparing names. */ 8507 font_names = x_list_fonts (f, build_string (fontname), size, 1); 8508 8509 if (!NILP (font_names)) 8510 { 8511 Lisp_Object tail; 8512 int i; 8513 8514 for (i = 0; i < dpyinfo->n_fonts; i++) 8515 for (tail = font_names; CONSP (tail); tail = XCDR (tail)) 8516 if (dpyinfo->font_table[i].name 8517 && (!strcmp (dpyinfo->font_table[i].name, 8518 SDATA (XCAR (tail))) 8519 || !strcmp (dpyinfo->font_table[i].full_name, 8520 SDATA (XCAR (tail))))) 8521 return (dpyinfo->font_table + i); 8522 } 8523 else 8524 return NULL; 8525 8526 /* Load the font and add it to the table. */ 8527 { 8528 struct MacFontStruct *font; 8529 struct font_info *fontp; 8530 int i; 8531 8532 fontname = (char *) SDATA (XCAR (font_names)); 8533 8534 BLOCK_INPUT; 8535 font = mac_load_query_font (f, fontname); 8536 UNBLOCK_INPUT; 8537 if (!font) 8538 return NULL; 8539 8540 /* Find a free slot in the font table. */ 8541 for (i = 0; i < dpyinfo->n_fonts; ++i) 8542 if (dpyinfo->font_table[i].name == NULL) 8543 break; 8544 8545 /* If no free slot found, maybe enlarge the font table. */ 8546 if (i == dpyinfo->n_fonts 8547 && dpyinfo->n_fonts == dpyinfo->font_table_size) 8548 { 8549 int sz; 8550 dpyinfo->font_table_size = max (16, 2 * dpyinfo->font_table_size); 8551 sz = dpyinfo->font_table_size * sizeof *dpyinfo->font_table; 8552 dpyinfo->font_table 8553 = (struct font_info *) xrealloc (dpyinfo->font_table, sz); 8554 } 8555 8556 fontp = dpyinfo->font_table + i; 8557 if (i == dpyinfo->n_fonts) 8558 ++dpyinfo->n_fonts; 8559 8560 /* Now fill in the slots of *FONTP. */ 8561 BLOCK_INPUT; 8562 bzero (fontp, sizeof (*fontp)); 8563 fontp->font = font; 8564 fontp->font_idx = i; 8565 fontp->name = (char *) xmalloc (strlen (fontname) + 1); 8566 bcopy (fontname, fontp->name, strlen (fontname) + 1); 8567 8568 if (font->min_bounds.width == font->max_bounds.width) 8569 { 8570 /* Fixed width font. */ 8571 fontp->average_width = fontp->space_width = font->min_bounds.width; 8572 } 8573 else 8574 { 8575 XChar2b char2b; 8576 XCharStruct *pcm; 8577 8578 char2b.byte1 = 0x00, char2b.byte2 = 0x20; 8579 pcm = mac_per_char_metric (font, &char2b, 0); 8580 if (pcm) 8581 fontp->space_width = pcm->width; 8582 else 8583 fontp->space_width = FONT_WIDTH (font); 8584 8585 if (pcm) 8586 { 8587 int width = pcm->width; 8588 for (char2b.byte2 = 33; char2b.byte2 <= 126; char2b.byte2++) 8589 if ((pcm = mac_per_char_metric (font, &char2b, 0)) != NULL) 8590 width += pcm->width; 8591 fontp->average_width = width / 95; 8592 } 8593 else 8594 fontp->average_width = FONT_WIDTH (font); 8595 } 8596 8597 fontp->full_name = (char *) xmalloc (strlen (font->full_name) + 1); 8598 bcopy (font->full_name, fontp->full_name, strlen (font->full_name) + 1); 8599 8600 fontp->size = font->max_bounds.width; 8601 fontp->height = FONT_HEIGHT (font); 8602 { 8603 /* For some font, ascent and descent in max_bounds field is 8604 larger than the above value. */ 8605 int max_height = font->max_bounds.ascent + font->max_bounds.descent; 8606 if (max_height > fontp->height) 8607 fontp->height = max_height; 8608 } 8609 8610 /* The slot `encoding' specifies how to map a character 8611 code-points (0x20..0x7F or 0x2020..0x7F7F) of each charset to 8612 the font code-points (0:0x20..0x7F, 1:0xA0..0xFF), or 8613 (0:0x2020..0x7F7F, 1:0xA0A0..0xFFFF, 3:0x20A0..0x7FFF, 8614 2:0xA020..0xFF7F). For the moment, we don't know which charset 8615 uses this font. So, we set information in fontp->encoding[1] 8616 which is never used by any charset. If mapping can't be 8617 decided, set FONT_ENCODING_NOT_DECIDED. */ 8618 if (font->mac_scriptcode == smJapanese) 8619 fontp->encoding[1] = 4; 8620 else 8621 { 8622 fontp->encoding[1] 8623 = (font->max_byte1 == 0 8624 /* 1-byte font */ 8625 ? (font->min_char_or_byte2 < 0x80 8626 ? (font->max_char_or_byte2 < 0x80 8627 ? 0 /* 0x20..0x7F */ 8628 : FONT_ENCODING_NOT_DECIDED) /* 0x20..0xFF */ 8629 : 1) /* 0xA0..0xFF */ 8630 /* 2-byte font */ 8631 : (font->min_byte1 < 0x80 8632 ? (font->max_byte1 < 0x80 8633 ? (font->min_char_or_byte2 < 0x80 8634 ? (font->max_char_or_byte2 < 0x80 8635 ? 0 /* 0x2020..0x7F7F */ 8636 : FONT_ENCODING_NOT_DECIDED) /* 0x2020..0x7FFF */ 8637 : 3) /* 0x20A0..0x7FFF */ 8638 : FONT_ENCODING_NOT_DECIDED) /* 0x20??..0xA0?? */ 8639 : (font->min_char_or_byte2 < 0x80 8640 ? (font->max_char_or_byte2 < 0x80 8641 ? 2 /* 0xA020..0xFF7F */ 8642 : FONT_ENCODING_NOT_DECIDED) /* 0xA020..0xFFFF */ 8643 : 1))); /* 0xA0A0..0xFFFF */ 8644 } 8645 8646#if 0 /* MAC_TODO: fill these out with more reasonably values */ 8647 fontp->baseline_offset 8648 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_BASELINE_OFFSET, &value) 8649 ? (long) value : 0); 8650 fontp->relative_compose 8651 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_RELATIVE_COMPOSE, &value) 8652 ? (long) value : 0); 8653 fontp->default_ascent 8654 = (XGetFontProperty (font, dpyinfo->Xatom_MULE_DEFAULT_ASCENT, &value) 8655 ? (long) value : 0); 8656#else 8657 fontp->baseline_offset = 0; 8658 fontp->relative_compose = 0; 8659 fontp->default_ascent = 0; 8660#endif 8661 8662 /* Set global flag fonts_changed_p to non-zero if the font loaded 8663 has a character with a smaller width than any other character 8664 before, or if the font loaded has a smaller height than any 8665 other font loaded before. If this happens, it will make a 8666 glyph matrix reallocation necessary. */ 8667 fonts_changed_p |= x_compute_min_glyph_bounds (f); 8668 UNBLOCK_INPUT; 8669 return fontp; 8670 } 8671} 8672 8673 8674/* Return a pointer to struct font_info of a font named FONTNAME for 8675 frame F. If no such font is loaded, return NULL. */ 8676 8677struct font_info * 8678x_query_font (f, fontname) 8679 struct frame *f; 8680 register char *fontname; 8681{ 8682 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f); 8683 int i; 8684 8685 for (i = 0; i < dpyinfo->n_fonts; i++) 8686 if (dpyinfo->font_table[i].name 8687 && (!xstricmp (dpyinfo->font_table[i].name, fontname) 8688 || !xstricmp (dpyinfo->font_table[i].full_name, fontname))) 8689 return (dpyinfo->font_table + i); 8690 return NULL; 8691} 8692 8693 8694/* Find a CCL program for a font specified by FONTP, and set the member 8695 `encoder' of the structure. */ 8696 8697void 8698x_find_ccl_program (fontp) 8699 struct font_info *fontp; 8700{ 8701 Lisp_Object list, elt; 8702 8703 for (list = Vfont_ccl_encoder_alist; CONSP (list); list = XCDR (list)) 8704 { 8705 elt = XCAR (list); 8706 if (CONSP (elt) 8707 && STRINGP (XCAR (elt)) 8708 && (fast_c_string_match_ignore_case (XCAR (elt), fontp->name) 8709 >= 0)) 8710 break; 8711 } 8712 if (! NILP (list)) 8713 { 8714 struct ccl_program *ccl 8715 = (struct ccl_program *) xmalloc (sizeof (struct ccl_program)); 8716 8717 if (setup_ccl_program (ccl, XCDR (elt)) < 0) 8718 xfree (ccl); 8719 else 8720 fontp->font_encoder = ccl; 8721 } 8722} 8723 8724#if USE_MAC_FONT_PANEL 8725/* Whether Font Panel has been shown before. The first call to font 8726 panel functions (FPIsFontPanelVisible, SetFontInfoForSelection) is 8727 slow. This variable is used for deferring such a call as much as 8728 possible. */ 8729static int font_panel_shown_p = 0; 8730 8731int 8732mac_font_panel_visible_p () 8733{ 8734 return font_panel_shown_p && FPIsFontPanelVisible (); 8735} 8736 8737OSStatus 8738mac_show_hide_font_panel () 8739{ 8740 font_panel_shown_p = 1; 8741 8742 return FPShowHideFontPanel (); 8743} 8744 8745OSStatus 8746mac_set_font_info_for_selection (f, face_id, c) 8747 struct frame *f; 8748 int face_id, c; 8749{ 8750 OSStatus err; 8751 EventTargetRef target = NULL; 8752 XFontStruct *font = NULL; 8753 8754 if (!mac_font_panel_visible_p ()) 8755 return noErr; 8756 8757 if (f) 8758 { 8759 target = GetWindowEventTarget (FRAME_MAC_WINDOW (f)); 8760 8761 if (FRAME_FACE_CACHE (f) && CHAR_VALID_P (c, 0)) 8762 { 8763 struct face *face; 8764 8765 face_id = FACE_FOR_CHAR (f, FACE_FROM_ID (f, face_id), c); 8766 face = FACE_FROM_ID (f, face_id); 8767 font = face->font; 8768 } 8769 } 8770 8771 if (font == NULL) 8772 err = SetFontInfoForSelection (kFontSelectionATSUIType, 0, NULL, target); 8773 else 8774 { 8775 if (font->mac_fontnum != -1) 8776 { 8777 FontSelectionQDStyle qd_style; 8778 8779 qd_style.version = kFontSelectionQDStyleVersionZero; 8780 qd_style.instance.fontFamily = font->mac_fontnum; 8781 qd_style.instance.fontStyle = font->mac_fontface; 8782 qd_style.size = font->mac_fontsize; 8783 qd_style.hasColor = false; 8784 8785 err = SetFontInfoForSelection (kFontSelectionQDType, 8786 1, &qd_style, target); 8787 } 8788 else 8789 err = SetFontInfoForSelection (kFontSelectionATSUIType, 8790 1, &font->mac_style, target); 8791 } 8792 8793 return err; 8794} 8795#endif 8796 8797 8798/* The Mac Event loop code */ 8799 8800#if !TARGET_API_MAC_CARBON 8801#include <Events.h> 8802#include <Quickdraw.h> 8803#include <Balloons.h> 8804#include <Devices.h> 8805#include <Fonts.h> 8806#include <Gestalt.h> 8807#include <Menus.h> 8808#include <Processes.h> 8809#include <Sound.h> 8810#include <ToolUtils.h> 8811#include <TextUtils.h> 8812#include <Dialogs.h> 8813#include <Script.h> 8814#include <Types.h> 8815#include <Resources.h> 8816 8817#if __MWERKS__ 8818#include <unix.h> 8819#endif 8820#endif /* ! TARGET_API_MAC_CARBON */ 8821 8822#define M_APPLE 234 8823#define I_ABOUT 1 8824 8825#define DEFAULT_NUM_COLS 80 8826 8827#define MIN_DOC_SIZE 64 8828#define MAX_DOC_SIZE 32767 8829 8830#define EXTRA_STACK_ALLOC (256 * 1024) 8831 8832#define ARGV_STRING_LIST_ID 129 8833#define ABOUT_ALERT_ID 128 8834#define RAM_TOO_LARGE_ALERT_ID 129 8835 8836/* Contains the string "reverse", which is a constant for mouse button emu.*/ 8837Lisp_Object Qreverse; 8838 8839 8840/* Modifier associated with the control key, or nil to ignore. */ 8841Lisp_Object Vmac_control_modifier; 8842 8843/* Modifier associated with the option key, or nil to ignore. */ 8844Lisp_Object Vmac_option_modifier; 8845 8846/* Modifier associated with the command key, or nil to ignore. */ 8847Lisp_Object Vmac_command_modifier; 8848 8849/* Modifier associated with the function key, or nil to ignore. */ 8850Lisp_Object Vmac_function_modifier; 8851 8852/* True if the option and command modifiers should be used to emulate 8853 a three button mouse */ 8854Lisp_Object Vmac_emulate_three_button_mouse; 8855 8856#if USE_CARBON_EVENTS 8857/* Non-zero if the mouse wheel button (i.e. button 4) should map to 8858 mouse-2, instead of mouse-3. */ 8859int mac_wheel_button_is_mouse_2; 8860 8861/* If non-zero, the Mac "Command" key is passed on to the Mac Toolbox 8862 for processing before Emacs sees it. */ 8863int mac_pass_command_to_system; 8864 8865/* If non-zero, the Mac "Control" key is passed on to the Mac Toolbox 8866 for processing before Emacs sees it. */ 8867int mac_pass_control_to_system; 8868#endif 8869 8870/* Points to the variable `inev' in the function XTread_socket. It is 8871 used for passing an input event to the function back from 8872 Carbon/Apple event handlers. */ 8873static struct input_event *read_socket_inev = NULL; 8874 8875/* Whether or not the screen configuration has changed. */ 8876static int mac_screen_config_changed = 0; 8877 8878Point saved_menu_event_location; 8879 8880/* Apple Events */ 8881#if USE_CARBON_EVENTS 8882static Lisp_Object Qhi_command; 8883#ifdef MAC_OSX 8884extern Lisp_Object Qwindow; 8885static Lisp_Object Qtoolbar_switch_mode; 8886#endif 8887#if USE_MAC_FONT_PANEL 8888extern Lisp_Object Qfont; 8889static Lisp_Object Qpanel_closed, Qselection; 8890#endif 8891#if USE_MAC_TSM 8892static TSMDocumentID tsm_document_id; 8893static Lisp_Object Qtext_input; 8894static Lisp_Object Qupdate_active_input_area, Qunicode_for_key_event; 8895static Lisp_Object Vmac_ts_active_input_overlay; 8896extern Lisp_Object Qbefore_string; 8897static Lisp_Object Vmac_ts_script_language_on_focus; 8898static Lisp_Object saved_ts_script_language_on_focus; 8899static ScriptLanguageRecord saved_ts_language; 8900static Component saved_ts_component; 8901#endif 8902#endif 8903extern int mac_ready_for_apple_events; 8904extern Lisp_Object Qundefined; 8905extern void init_apple_event_handler P_ ((void)); 8906extern void mac_find_apple_event_spec P_ ((AEEventClass, AEEventID, 8907 Lisp_Object *, Lisp_Object *, 8908 Lisp_Object *)); 8909extern OSErr init_coercion_handler P_ ((void)); 8910 8911/* Drag and Drop */ 8912extern OSErr install_drag_handler P_ ((WindowRef)); 8913extern void remove_drag_handler P_ ((WindowRef)); 8914 8915/* Showing help echo string during menu tracking */ 8916extern OSStatus install_menu_target_item_handler P_ ((WindowPtr)); 8917 8918#if USE_CARBON_EVENTS 8919#ifdef MAC_OSX 8920extern void init_service_handler (); 8921static Lisp_Object Qservice, Qpaste, Qperform; 8922#endif 8923 8924/* Window Event Handler */ 8925static pascal OSStatus mac_handle_window_event (EventHandlerCallRef, 8926 EventRef, void *); 8927#endif 8928OSStatus install_window_handler (WindowPtr); 8929 8930extern void init_emacs_passwd_dir (); 8931extern int emacs_main (int, char **, char **); 8932 8933extern void initialize_applescript(); 8934extern void terminate_applescript(); 8935 8936/* Table for translating Mac keycode to X keysym values. Contributed 8937 by Sudhir Shenoy. 8938 Mapping for special keys is now identical to that in Apple X11 8939 except `clear' (-> <clear>) on the KeyPad, `enter' (-> <kp-enter>) 8940 on the right of the Cmd key on laptops, and fn + `enter' (-> 8941 <linefeed>). */ 8942static const unsigned char keycode_to_xkeysym_table[] = { 8943 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8944 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8945 /*0x20*/ 0, 0, 0, 0, 0x0d /*return*/, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8946 8947 /*0x30*/ 0x09 /*tab*/, 0 /*0x0020 space*/, 0, 0x08 /*backspace*/, 8948 /*0x34*/ 0x8d /*enter on laptops*/, 0x1b /*escape*/, 0, 0, 8949 /*0x38*/ 0, 0, 0, 0, 8950 /*0x3C*/ 0, 0, 0, 0, 8951 8952 /*0x40*/ 0, 0xae /*kp-decimal*/, 0, 0xaa /*kp-multiply*/, 8953 /*0x44*/ 0, 0xab /*kp-add*/, 0, 0x0b /*clear*/, 8954 /*0x48*/ 0, 0, 0, 0xaf /*kp-divide*/, 8955 /*0x4C*/ 0x8d /*kp-enter*/, 0, 0xad /*kp-subtract*/, 0, 8956 8957 /*0x50*/ 0, 0xbd /*kp-equal*/, 0xb0 /*kp-0*/, 0xb1 /*kp-1*/, 8958 /*0x54*/ 0xb2 /*kp-2*/, 0xb3 /*kp-3*/, 0xb4 /*kp-4*/, 0xb5 /*kp-5*/, 8959 /*0x58*/ 0xb6 /*kp-6*/, 0xb7 /*kp-7*/, 0, 0xb8 /*kp-8*/, 8960 /*0x5C*/ 0xb9 /*kp-9*/, 0, 0, 0, 8961 8962 /*0x60*/ 0xc2 /*f5*/, 0xc3 /*f6*/, 0xc4 /*f7*/, 0xc0 /*f3*/, 8963 /*0x64*/ 0xc5 /*f8*/, 0xc6 /*f9*/, 0, 0xc8 /*f11*/, 8964 /*0x68*/ 0, 0xca /*f13*/, 0xcd /*f16*/, 0xcb /*f14*/, 8965 /*0x6C*/ 0, 0xc7 /*f10*/, 0x0a /*fn+enter on laptops*/, 0xc9 /*f12*/, 8966 8967 /*0x70*/ 0, 0xcc /*f15*/, 0x6a /*help*/, 0x50 /*home*/, 8968 /*0x74*/ 0x55 /*pgup*/, 0xff /*delete*/, 0xc1 /*f4*/, 0x57 /*end*/, 8969 /*0x78*/ 0xbf /*f2*/, 0x56 /*pgdown*/, 0xbe /*f1*/, 0x51 /*left*/, 8970 /*0x7C*/ 0x53 /*right*/, 0x54 /*down*/, 0x52 /*up*/, 0 8971}; 8972 8973#ifdef MAC_OSX 8974/* Table for translating Mac keycode with the laptop `fn' key to that 8975 without it. Destination symbols in comments are keys on US 8976 keyboard, and they may not be the same on other types of keyboards. 8977 If the destination is identical to the source (f1 ... f12), it 8978 doesn't map `fn' key to a modifier. */ 8979static const unsigned char fn_keycode_to_keycode_table[] = { 8980 /*0x00*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8981 /*0x10*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8982 /*0x20*/ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8983 8984 /*0x30*/ 0, 0, 0, 0, 8985 /*0x34*/ 0, 0, 0, 0, 8986 /*0x38*/ 0, 0, 0, 0, 8987 /*0x3C*/ 0, 0, 0, 0, 8988 8989 /*0x40*/ 0, 0x2f /*kp-decimal -> '.'*/, 0, 0x23 /*kp-multiply -> 'p'*/, 8990 /*0x44*/ 0, 0x2c /*kp-add -> '/'*/, 0, 0x16 /*clear -> '6'*/, 8991 /*0x48*/ 0, 0, 0, 0x1d /*kp-/ -> '0'*/, 8992 /*0x4C*/ 0x24 /*kp-enter -> return*/, 0, 0x29 /*kp-subtract -> ';'*/, 0, 8993 8994 /*0x50*/ 0, 0x1b /*kp-equal -> '-'*/, 0x2e /*kp-0 -> 'm'*/, 0x26 /*kp-1 -> 'j'*/, 8995 /*0x54*/ 0x28 /*kp-2 -> 'k'*/, 0x25 /*kp-3 -> 'l'*/, 0x20 /*kp-4 -> 'u'*/, 0x22 /*kp-5 ->'i'*/, 8996 /*0x58*/ 0x1f /*kp-6 -> 'o'*/, 0x1a /*kp-7 -> '7'*/, 0, 0x1c /*kp-8 -> '8'*/, 8997 /*0x5C*/ 0x19 /*kp-9 -> '9'*/, 0, 0, 0, 8998 8999 /*0x60*/ 0x60 /*f5 = f5*/, 0x61 /*f6 = f6*/, 0x62 /*f7 = f7*/, 0x63 /*f3 = f3*/, 9000 /*0x64*/ 0x64 /*f8 = f8*/, 0x65 /*f9 = f9*/, 0, 0x67 /*f11 = f11*/, 9001 /*0x68*/ 0, 0, 0, 0, 9002 /*0x6C*/ 0, 0x6d /*f10 = f10*/, 0, 0x6f /*f12 = f12*/, 9003 9004 /*0x70*/ 0, 0, 0, 0x7b /*home -> left*/, 9005 /*0x74*/ 0x7e /*pgup -> up*/, 0x33 /*delete -> backspace*/, 0x76 /*f4 = f4*/, 0x7c /*end -> right*/, 9006 /*0x78*/ 0x78 /*f2 = f2*/, 0x7d /*pgdown -> down*/, 0x7a /*f1 = f1*/, 0, 9007 /*0x7C*/ 0, 0, 0, 0 9008}; 9009#endif /* MAC_OSX */ 9010 9011static int 9012#if USE_CARBON_EVENTS 9013mac_to_emacs_modifiers (UInt32 mods) 9014#else 9015mac_to_emacs_modifiers (EventModifiers mods) 9016#endif 9017{ 9018 unsigned int result = 0; 9019 if (mods & shiftKey) 9020 result |= shift_modifier; 9021 9022 /* Deactivated to simplify configuration: 9023 if Vmac_option_modifier is non-NIL, we fully process the Option 9024 key. Otherwise, we only process it if an additional Ctrl or Command 9025 is pressed. That way the system may convert the character to a 9026 composed one. 9027 if ((mods & optionKey) && 9028 (( !NILP(Vmac_option_modifier) || 9029 ((mods & cmdKey) || (mods & controlKey))))) */ 9030 9031 if (!NILP (Vmac_option_modifier) && (mods & optionKey)) { 9032 Lisp_Object val = Fget(Vmac_option_modifier, Qmodifier_value); 9033 if (INTEGERP(val)) 9034 result |= XUINT(val); 9035 } 9036 if (!NILP (Vmac_command_modifier) && (mods & cmdKey)) { 9037 Lisp_Object val = Fget(Vmac_command_modifier, Qmodifier_value); 9038 if (INTEGERP(val)) 9039 result |= XUINT(val); 9040 } 9041 if (!NILP (Vmac_control_modifier) && (mods & controlKey)) { 9042 Lisp_Object val = Fget(Vmac_control_modifier, Qmodifier_value); 9043 if (INTEGERP(val)) 9044 result |= XUINT(val); 9045 } 9046 9047#ifdef MAC_OSX 9048 if (!NILP (Vmac_function_modifier) && (mods & kEventKeyModifierFnMask)) { 9049 Lisp_Object val = Fget(Vmac_function_modifier, Qmodifier_value); 9050 if (INTEGERP(val)) 9051 result |= XUINT(val); 9052 } 9053#endif 9054 9055 return result; 9056} 9057 9058static UInt32 9059mac_mapped_modifiers (modifiers) 9060 UInt32 modifiers; 9061{ 9062 UInt32 mapped_modifiers_all = 9063 (NILP (Vmac_control_modifier) ? 0 : controlKey) 9064 | (NILP (Vmac_option_modifier) ? 0 : optionKey) 9065 | (NILP (Vmac_command_modifier) ? 0 : cmdKey); 9066 9067#ifdef MAC_OSX 9068 mapped_modifiers_all |= 9069 (NILP (Vmac_function_modifier) ? 0 : kEventKeyModifierFnMask); 9070#endif 9071 9072 return mapped_modifiers_all & modifiers; 9073} 9074 9075static int 9076mac_get_emulated_btn ( UInt32 modifiers ) 9077{ 9078 int result = 0; 9079 if (!NILP (Vmac_emulate_three_button_mouse)) { 9080 int cmdIs3 = !EQ (Vmac_emulate_three_button_mouse, Qreverse); 9081 if (modifiers & cmdKey) 9082 result = cmdIs3 ? 2 : 1; 9083 else if (modifiers & optionKey) 9084 result = cmdIs3 ? 1 : 2; 9085 } 9086 return result; 9087} 9088 9089#if TARGET_API_MAC_CARBON 9090/***** Code to handle C-g testing *****/ 9091extern int quit_char; 9092extern int make_ctrl_char P_ ((int)); 9093 9094int 9095mac_quit_char_key_p (modifiers, key_code) 9096 UInt32 modifiers, key_code; 9097{ 9098 UInt32 char_code; 9099 unsigned long some_state = 0; 9100 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache); 9101 int c, emacs_modifiers; 9102 9103 /* Mask off modifier keys that are mapped to some Emacs modifiers. */ 9104 key_code |= (modifiers & ~(mac_mapped_modifiers (modifiers))); 9105 char_code = KeyTranslate (kchr_ptr, key_code, &some_state); 9106 if (char_code & ~0xff) 9107 return 0; 9108 9109 emacs_modifiers = mac_to_emacs_modifiers (modifiers); 9110 if (emacs_modifiers & ctrl_modifier) 9111 c = make_ctrl_char (char_code); 9112 9113 c |= (emacs_modifiers 9114 & (meta_modifier | alt_modifier 9115 | hyper_modifier | super_modifier)); 9116 9117 return c == quit_char; 9118} 9119#endif 9120 9121#if USE_CARBON_EVENTS 9122/* Obtains the event modifiers from the event ref and then calls 9123 mac_to_emacs_modifiers. */ 9124static int 9125mac_event_to_emacs_modifiers (EventRef eventRef) 9126{ 9127 UInt32 mods = 0; 9128 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, NULL, 9129 sizeof (UInt32), NULL, &mods); 9130 if (!NILP (Vmac_emulate_three_button_mouse) && 9131 GetEventClass(eventRef) == kEventClassMouse) 9132 { 9133 mods &= ~(optionKey | cmdKey); 9134 } 9135 return mac_to_emacs_modifiers (mods); 9136} 9137 9138/* Given an event ref, return the code to use for the mouse button 9139 code in the emacs input_event. */ 9140static int 9141mac_get_mouse_btn (EventRef ref) 9142{ 9143 EventMouseButton result = kEventMouseButtonPrimary; 9144 GetEventParameter (ref, kEventParamMouseButton, typeMouseButton, NULL, 9145 sizeof (EventMouseButton), NULL, &result); 9146 switch (result) 9147 { 9148 case kEventMouseButtonPrimary: 9149 if (NILP (Vmac_emulate_three_button_mouse)) 9150 return 0; 9151 else { 9152 UInt32 mods = 0; 9153 GetEventParameter (ref, kEventParamKeyModifiers, typeUInt32, NULL, 9154 sizeof (UInt32), NULL, &mods); 9155 return mac_get_emulated_btn(mods); 9156 } 9157 case kEventMouseButtonSecondary: 9158 return mac_wheel_button_is_mouse_2 ? 2 : 1; 9159 case kEventMouseButtonTertiary: 9160 case 4: /* 4 is the number for the mouse wheel button */ 9161 return mac_wheel_button_is_mouse_2 ? 1 : 2; 9162 default: 9163 return 0; 9164 } 9165} 9166 9167/* Normally, ConvertEventRefToEventRecord will correctly handle all 9168 events. However the click of the mouse wheel is not converted to a 9169 mouseDown or mouseUp event. Likewise for dead key events. This 9170 calls ConvertEventRefToEventRecord, but then checks to see if it is 9171 a mouse up/down, or a dead key Carbon event that has not been 9172 converted, and if so, converts it by hand (to be picked up in the 9173 XTread_socket loop). */ 9174static Boolean mac_convert_event_ref (EventRef eventRef, EventRecord *eventRec) 9175{ 9176 OSStatus err; 9177 Boolean result = ConvertEventRefToEventRecord (eventRef, eventRec); 9178 EventKind action; 9179 9180 if (result) 9181 return result; 9182 9183 switch (GetEventClass (eventRef)) 9184 { 9185 case kEventClassMouse: 9186 switch (GetEventKind (eventRef)) 9187 { 9188 case kEventMouseDown: 9189 eventRec->what = mouseDown; 9190 result = 1; 9191 break; 9192 9193 case kEventMouseUp: 9194 eventRec->what = mouseUp; 9195 result = 1; 9196 break; 9197 9198 default: 9199 break; 9200 } 9201 break; 9202 9203 case kEventClassKeyboard: 9204 switch (GetEventKind (eventRef)) 9205 { 9206 case kEventRawKeyDown: 9207 action = keyDown; 9208 goto keystroke_common; 9209 case kEventRawKeyRepeat: 9210 action = autoKey; 9211 goto keystroke_common; 9212 case kEventRawKeyUp: 9213 action = keyUp; 9214 keystroke_common: 9215 { 9216 unsigned char char_codes; 9217 UInt32 key_code; 9218 9219 err = GetEventParameter (eventRef, kEventParamKeyMacCharCodes, 9220 typeChar, NULL, sizeof (char), 9221 NULL, &char_codes); 9222 if (err == noErr) 9223 err = GetEventParameter (eventRef, kEventParamKeyCode, 9224 typeUInt32, NULL, sizeof (UInt32), 9225 NULL, &key_code); 9226 if (err == noErr) 9227 { 9228 eventRec->what = action; 9229 eventRec->message = char_codes | ((key_code & 0xff) << 8); 9230 result = 1; 9231 } 9232 } 9233 break; 9234 9235 default: 9236 break; 9237 } 9238 break; 9239 9240 default: 9241 break; 9242 } 9243 9244 if (result) 9245 { 9246 /* Need where and when. */ 9247 UInt32 mods = 0; 9248 9249 GetEventParameter (eventRef, kEventParamMouseLocation, typeQDPoint, 9250 NULL, sizeof (Point), NULL, &eventRec->where); 9251 /* Use two step process because new event modifiers are 32-bit 9252 and old are 16-bit. Currently, only loss is NumLock & Fn. */ 9253 GetEventParameter (eventRef, kEventParamKeyModifiers, typeUInt32, 9254 NULL, sizeof (UInt32), NULL, &mods); 9255 eventRec->modifiers = mods; 9256 9257 eventRec->when = EventTimeToTicks (GetEventTime (eventRef)); 9258 } 9259 9260 return result; 9261} 9262 9263#endif 9264 9265#ifdef MAC_OS8 9266static void 9267do_get_menus (void) 9268{ 9269 Handle menubar_handle; 9270 MenuHandle menu_handle; 9271 9272 menubar_handle = GetNewMBar (128); 9273 if(menubar_handle == NULL) 9274 abort (); 9275 SetMenuBar (menubar_handle); 9276 DrawMenuBar (); 9277 9278#if !TARGET_API_MAC_CARBON 9279 menu_handle = GetMenuHandle (M_APPLE); 9280 if(menu_handle != NULL) 9281 AppendResMenu (menu_handle,'DRVR'); 9282 else 9283 abort (); 9284#endif 9285} 9286 9287 9288static void 9289do_init_managers (void) 9290{ 9291#if !TARGET_API_MAC_CARBON 9292 InitGraf (&qd.thePort); 9293 InitFonts (); 9294 FlushEvents (everyEvent, 0); 9295 InitWindows (); 9296 InitMenus (); 9297 TEInit (); 9298 InitDialogs (NULL); 9299#endif /* !TARGET_API_MAC_CARBON */ 9300 InitCursor (); 9301 9302#if !TARGET_API_MAC_CARBON 9303 /* set up some extra stack space for use by emacs */ 9304 SetApplLimit ((Ptr) ((long) GetApplLimit () - EXTRA_STACK_ALLOC)); 9305 9306 /* MaxApplZone must be called for AppleScript to execute more 9307 complicated scripts */ 9308 MaxApplZone (); 9309 MoreMasters (); 9310#endif /* !TARGET_API_MAC_CARBON */ 9311} 9312 9313static void 9314do_check_ram_size (void) 9315{ 9316 SInt32 physical_ram_size, logical_ram_size; 9317 9318 if (Gestalt (gestaltPhysicalRAMSize, &physical_ram_size) != noErr 9319 || Gestalt (gestaltLogicalRAMSize, &logical_ram_size) != noErr 9320 || physical_ram_size > (1 << VALBITS) 9321 || logical_ram_size > (1 << VALBITS)) 9322 { 9323 StopAlert (RAM_TOO_LARGE_ALERT_ID, NULL); 9324 exit (1); 9325 } 9326} 9327#endif /* MAC_OS8 */ 9328 9329static void 9330do_window_update (WindowPtr win) 9331{ 9332 struct frame *f = mac_window_to_frame (win); 9333 9334 BeginUpdate (win); 9335 9336 /* The tooltip has been drawn already. Avoid the SET_FRAME_GARBAGED 9337 below. */ 9338 if (win != tip_window) 9339 { 9340 if (f->async_visible == 0) 9341 { 9342 /* Update events may occur when a frame gets iconified. */ 9343#if 0 9344 f->async_visible = 1; 9345 f->async_iconified = 0; 9346 SET_FRAME_GARBAGED (f); 9347#endif 9348 } 9349 else 9350 { 9351 Rect r; 9352#if TARGET_API_MAC_CARBON 9353 RgnHandle region = NewRgn (); 9354 9355 GetPortVisibleRegion (GetWindowPort (win), region); 9356 GetRegionBounds (region, &r); 9357 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top); 9358#if USE_CG_DRAWING 9359 mac_prepare_for_quickdraw (f); 9360#endif 9361 UpdateControls (win, region); 9362 DisposeRgn (region); 9363#else 9364 r = (*win->visRgn)->rgnBBox; 9365 expose_frame (f, r.left, r.top, r.right - r.left, r.bottom - r.top); 9366 UpdateControls (win, win->visRgn); 9367#endif 9368 } 9369 } 9370 9371 EndUpdate (win); 9372} 9373 9374static int 9375is_emacs_window (WindowPtr win) 9376{ 9377 Lisp_Object tail, frame; 9378 9379 if (!win) 9380 return 0; 9381 9382 FOR_EACH_FRAME (tail, frame) 9383 if (FRAME_MAC_P (XFRAME (frame))) 9384 if (FRAME_MAC_WINDOW (XFRAME (frame)) == win) 9385 return 1; 9386 9387 return 0; 9388} 9389 9390#if USE_MAC_TSM 9391static OSStatus 9392mac_tsm_resume () 9393{ 9394 OSStatus err; 9395 ScriptLanguageRecord slrec, *slptr = NULL; 9396 9397 err = ActivateTSMDocument (tsm_document_id); 9398 9399 if (err == noErr) 9400 { 9401 if (EQ (Vmac_ts_script_language_on_focus, Qt) 9402 && EQ (saved_ts_script_language_on_focus, Qt)) 9403 slptr = &saved_ts_language; 9404 else if (CONSP (Vmac_ts_script_language_on_focus) 9405 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus)) 9406 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus)) 9407 && CONSP (saved_ts_script_language_on_focus) 9408 && EQ (XCAR (saved_ts_script_language_on_focus), 9409 XCAR (Vmac_ts_script_language_on_focus)) 9410 && EQ (XCDR (saved_ts_script_language_on_focus), 9411 XCDR (Vmac_ts_script_language_on_focus))) 9412 { 9413 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus)); 9414 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus)); 9415 slptr = &slrec; 9416 } 9417 } 9418 9419 if (slptr) 9420 { 9421#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 9422 err = SetDefaultInputMethodOfClass (saved_ts_component, slptr, 9423 kKeyboardInputMethodClass); 9424#else 9425 err = SetDefaultInputMethod (saved_ts_component, slptr); 9426#endif 9427 if (err == noErr) 9428 err = SetTextServiceLanguage (slptr); 9429 9430 /* Seems to be needed on Mac OS X 10.2. */ 9431 if (err == noErr) 9432 KeyScript (slptr->fScript | smKeyForceKeyScriptMask); 9433 } 9434 9435 return err; 9436} 9437 9438static OSStatus 9439mac_tsm_suspend () 9440{ 9441 OSStatus err; 9442 ScriptLanguageRecord slrec, *slptr = NULL; 9443 9444 saved_ts_script_language_on_focus = Vmac_ts_script_language_on_focus; 9445 9446 if (EQ (Vmac_ts_script_language_on_focus, Qt)) 9447 { 9448 err = GetTextServiceLanguage (&saved_ts_language); 9449 if (err == noErr) 9450 slptr = &saved_ts_language; 9451 } 9452 else if (CONSP (Vmac_ts_script_language_on_focus) 9453 && INTEGERP (XCAR (Vmac_ts_script_language_on_focus)) 9454 && INTEGERP (XCDR (Vmac_ts_script_language_on_focus))) 9455 { 9456 slrec.fScript = XINT (XCAR (Vmac_ts_script_language_on_focus)); 9457 slrec.fLanguage = XINT (XCDR (Vmac_ts_script_language_on_focus)); 9458 slptr = &slrec; 9459 } 9460 9461 if (slptr) 9462 { 9463#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 9464 GetDefaultInputMethodOfClass (&saved_ts_component, slptr, 9465 kKeyboardInputMethodClass); 9466#else 9467 GetDefaultInputMethod (&saved_ts_component, slptr); 9468#endif 9469 } 9470 9471 err = DeactivateTSMDocument (tsm_document_id); 9472 9473 return err; 9474} 9475#endif 9476 9477#if !TARGET_API_MAC_CARBON 9478void 9479do_apple_menu (SInt16 menu_item) 9480{ 9481 Str255 item_name; 9482 SInt16 da_driver_refnum; 9483 9484 if (menu_item == I_ABOUT) 9485 NoteAlert (ABOUT_ALERT_ID, NULL); 9486 else 9487 { 9488 GetMenuItemText (GetMenuHandle (M_APPLE), menu_item, item_name); 9489 da_driver_refnum = OpenDeskAcc (item_name); 9490 } 9491} 9492#endif /* !TARGET_API_MAC_CARBON */ 9493 9494/* Handle drags in size box. Based on code contributed by Ben 9495 Mesander and IM - Window Manager A. */ 9496 9497static void 9498do_grow_window (w, e) 9499 WindowPtr w; 9500 const EventRecord *e; 9501{ 9502 Rect limit_rect; 9503 int rows, columns, width, height; 9504 struct frame *f = mac_window_to_frame (w); 9505 XSizeHints *size_hints = FRAME_SIZE_HINTS (f); 9506 int min_width = MIN_DOC_SIZE, min_height = MIN_DOC_SIZE; 9507#if TARGET_API_MAC_CARBON 9508 Rect new_rect; 9509#else 9510 long grow_size; 9511#endif 9512 9513 if (size_hints->flags & PMinSize) 9514 { 9515 min_width = size_hints->min_width; 9516 min_height = size_hints->min_height; 9517 } 9518 SetRect (&limit_rect, min_width, min_height, MAX_DOC_SIZE, MAX_DOC_SIZE); 9519 9520#if TARGET_API_MAC_CARBON 9521 if (!ResizeWindow (w, e->where, &limit_rect, &new_rect)) 9522 return; 9523 height = new_rect.bottom - new_rect.top; 9524 width = new_rect.right - new_rect.left; 9525#else 9526 grow_size = GrowWindow (w, e->where, &limit_rect); 9527 /* see if it really changed size */ 9528 if (grow_size == 0) 9529 return; 9530 height = HiWord (grow_size); 9531 width = LoWord (grow_size); 9532#endif 9533 9534 if (width != FRAME_PIXEL_WIDTH (f) 9535 || height != FRAME_PIXEL_HEIGHT (f)) 9536 { 9537 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height); 9538 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width); 9539 9540 x_set_window_size (f, 0, columns, rows); 9541 } 9542} 9543 9544 9545#if TARGET_API_MAC_CARBON 9546static Point 9547mac_get_ideal_size (f) 9548 struct frame *f; 9549{ 9550 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f); 9551 WindowPtr w = FRAME_MAC_WINDOW (f); 9552 Point ideal_size; 9553 Rect standard_rect; 9554 int height, width, columns, rows; 9555 9556 ideal_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS); 9557 ideal_size.v = dpyinfo->height; 9558 IsWindowInStandardState (w, &ideal_size, &standard_rect); 9559 /* Adjust the standard size according to character boundaries. */ 9560 width = standard_rect.right - standard_rect.left; 9561 height = standard_rect.bottom - standard_rect.top; 9562 columns = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (f, width); 9563 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, height); 9564 ideal_size.h = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, columns); 9565 ideal_size.v = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows); 9566 9567 return ideal_size; 9568} 9569#endif 9570 9571/* Handle clicks in zoom box. Calculation of "standard state" based 9572 on code in IM - Window Manager A and code contributed by Ben 9573 Mesander. The standard state of an Emacs window is 80-characters 9574 wide (DEFAULT_NUM_COLS) and as tall as will fit on the screen. */ 9575 9576static void 9577do_zoom_window (WindowPtr w, int zoom_in_or_out) 9578{ 9579 Rect zoom_rect, port_rect; 9580 int width, height; 9581 struct frame *f = mac_window_to_frame (w); 9582#if TARGET_API_MAC_CARBON 9583 Point ideal_size = mac_get_ideal_size (f); 9584 9585 GetWindowBounds (w, kWindowContentRgn, &port_rect); 9586 if (IsWindowInStandardState (w, &ideal_size, &zoom_rect) 9587 && port_rect.left == zoom_rect.left 9588 && port_rect.top == zoom_rect.top) 9589 zoom_in_or_out = inZoomIn; 9590 else 9591 zoom_in_or_out = inZoomOut; 9592 9593#ifdef MAC_OS8 9594 mac_clear_window (f); 9595#endif 9596 ZoomWindowIdeal (w, zoom_in_or_out, &ideal_size); 9597#else /* not TARGET_API_MAC_CARBON */ 9598 GrafPtr save_port; 9599 Point top_left; 9600 int w_title_height, rows; 9601 struct mac_display_info *dpyinfo = FRAME_MAC_DISPLAY_INFO (f); 9602 9603 GetPort (&save_port); 9604 9605 SetPortWindowPort (w); 9606 9607 /* Clear window to avoid flicker. */ 9608 EraseRect (&(w->portRect)); 9609 if (zoom_in_or_out == inZoomOut) 9610 { 9611 SetPt (&top_left, w->portRect.left, w->portRect.top); 9612 LocalToGlobal (&top_left); 9613 9614 /* calculate height of window's title bar */ 9615 w_title_height = top_left.v - 1 9616 - (**((WindowPeek) w)->strucRgn).rgnBBox.top + GetMBarHeight (); 9617 9618 /* get maximum height of window into zoom_rect.bottom - zoom_rect.top */ 9619 zoom_rect = qd.screenBits.bounds; 9620 zoom_rect.top += w_title_height; 9621 InsetRect (&zoom_rect, 8, 4); /* not too tight */ 9622 9623 zoom_rect.right = zoom_rect.left 9624 + FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, DEFAULT_NUM_COLS); 9625 9626 /* Adjust the standard size according to character boundaries. */ 9627 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (f, zoom_rect.bottom - zoom_rect.top); 9628 zoom_rect.bottom = 9629 zoom_rect.top + FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows); 9630 9631 (**((WStateDataHandle) ((WindowPeek) w)->dataHandle)).stdState 9632 = zoom_rect; 9633 } 9634 9635 ZoomWindow (w, zoom_in_or_out, f == mac_focus_frame (dpyinfo)); 9636 9637 SetPort (save_port); 9638#endif /* not TARGET_API_MAC_CARBON */ 9639 9640#if !USE_CARBON_EVENTS 9641 /* retrieve window size and update application values */ 9642#if TARGET_API_MAC_CARBON 9643 GetWindowPortBounds (w, &port_rect); 9644#else 9645 port_rect = w->portRect; 9646#endif 9647 height = port_rect.bottom - port_rect.top; 9648 width = port_rect.right - port_rect.left; 9649 9650 mac_handle_size_change (f, width, height); 9651 mac_handle_origin_change (f); 9652#endif 9653} 9654 9655void 9656mac_store_apple_event (class, id, desc) 9657 Lisp_Object class, id; 9658 const AEDesc *desc; 9659{ 9660 struct input_event buf; 9661 9662 EVENT_INIT (buf); 9663 9664 buf.kind = MAC_APPLE_EVENT; 9665 buf.x = class; 9666 buf.y = id; 9667 XSETFRAME (buf.frame_or_window, 9668 mac_focus_frame (&one_mac_display_info)); 9669 /* Now that Lisp object allocations are protected by BLOCK_INPUT, it 9670 is safe to use them during read_socket_hook. */ 9671 buf.arg = mac_aedesc_to_lisp (desc); 9672 kbd_buffer_store_event (&buf); 9673} 9674 9675#if TARGET_API_MAC_CARBON 9676static OSStatus 9677mac_store_event_ref_as_apple_event (class, id, class_key, id_key, 9678 event, num_params, names, types) 9679 AEEventClass class; 9680 AEEventID id; 9681 Lisp_Object class_key, id_key; 9682 EventRef event; 9683 UInt32 num_params; 9684 const EventParamName *names; 9685 const EventParamType *types; 9686{ 9687 OSStatus err = eventNotHandledErr; 9688 Lisp_Object binding; 9689 9690 mac_find_apple_event_spec (class, id, &class_key, &id_key, &binding); 9691 if (!NILP (binding) && !EQ (binding, Qundefined)) 9692 { 9693 if (INTEGERP (binding)) 9694 err = XINT (binding); 9695 else 9696 { 9697 AppleEvent apple_event; 9698 err = create_apple_event_from_event_ref (event, num_params, 9699 names, types, 9700 &apple_event); 9701 if (err == noErr) 9702 { 9703 mac_store_apple_event (class_key, id_key, &apple_event); 9704 AEDisposeDesc (&apple_event); 9705 mac_wakeup_from_rne (); 9706 } 9707 } 9708 } 9709 9710 return err; 9711} 9712 9713void 9714mac_store_drag_event (window, mouse_pos, modifiers, desc) 9715 WindowRef window; 9716 Point mouse_pos; 9717 SInt16 modifiers; 9718 const AEDesc *desc; 9719{ 9720 struct input_event buf; 9721 9722 EVENT_INIT (buf); 9723 9724 buf.kind = DRAG_N_DROP_EVENT; 9725 buf.modifiers = mac_to_emacs_modifiers (modifiers); 9726 buf.timestamp = TickCount () * (1000 / 60); 9727 XSETINT (buf.x, mouse_pos.h); 9728 XSETINT (buf.y, mouse_pos.v); 9729 XSETFRAME (buf.frame_or_window, mac_window_to_frame (window)); 9730 buf.arg = mac_aedesc_to_lisp (desc); 9731 kbd_buffer_store_event (&buf); 9732} 9733#endif 9734 9735#if USE_CARBON_EVENTS 9736static pascal OSStatus 9737mac_handle_command_event (next_handler, event, data) 9738 EventHandlerCallRef next_handler; 9739 EventRef event; 9740 void *data; 9741{ 9742 OSStatus result, err; 9743 HICommand command; 9744 static const EventParamName names[] = 9745 {kEventParamDirectObject, kEventParamKeyModifiers}; 9746 static const EventParamType types[] = 9747 {typeHICommand, typeUInt32}; 9748 int num_params = sizeof (names) / sizeof (names[0]); 9749 9750 result = CallNextEventHandler (next_handler, event); 9751 if (result != eventNotHandledErr) 9752 return result; 9753 9754 err = GetEventParameter (event, kEventParamDirectObject, typeHICommand, 9755 NULL, sizeof (HICommand), NULL, &command); 9756 9757 if (err != noErr || command.commandID == 0) 9758 return eventNotHandledErr; 9759 9760 /* A HI command event is mapped to an Apple event whose event class 9761 symbol is `hi-command' and event ID is its command ID. */ 9762 err = mac_store_event_ref_as_apple_event (0, command.commandID, 9763 Qhi_command, Qnil, 9764 event, num_params, names, types); 9765 return err == noErr ? noErr : eventNotHandledErr; 9766} 9767 9768static OSStatus 9769init_command_handler () 9770{ 9771 static const EventTypeSpec specs[] = 9772 {{kEventClassCommand, kEventCommandProcess}}; 9773 static EventHandlerUPP handle_command_eventUPP = NULL; 9774 9775 if (handle_command_eventUPP == NULL) 9776 handle_command_eventUPP = NewEventHandlerUPP (mac_handle_command_event); 9777 return InstallApplicationEventHandler (handle_command_eventUPP, 9778 GetEventTypeCount (specs), specs, 9779 NULL, NULL); 9780} 9781 9782static pascal OSStatus 9783mac_handle_window_event (next_handler, event, data) 9784 EventHandlerCallRef next_handler; 9785 EventRef event; 9786 void *data; 9787{ 9788 WindowPtr wp; 9789 OSStatus result, err; 9790 struct frame *f; 9791 UInt32 attributes; 9792 XSizeHints *size_hints; 9793 9794 err = GetEventParameter (event, kEventParamDirectObject, typeWindowRef, 9795 NULL, sizeof (WindowPtr), NULL, &wp); 9796 if (err != noErr) 9797 return eventNotHandledErr; 9798 9799 f = mac_window_to_frame (wp); 9800 switch (GetEventKind (event)) 9801 { 9802 case kEventWindowUpdate: 9803 result = CallNextEventHandler (next_handler, event); 9804 if (result != eventNotHandledErr) 9805 return result; 9806 9807 do_window_update (wp); 9808 return noErr; 9809 9810 case kEventWindowGetIdealSize: 9811 result = CallNextEventHandler (next_handler, event); 9812 if (result != eventNotHandledErr) 9813 return result; 9814 9815 { 9816 Point ideal_size = mac_get_ideal_size (f); 9817 9818 err = SetEventParameter (event, kEventParamDimensions, 9819 typeQDPoint, sizeof (Point), &ideal_size); 9820 if (err == noErr) 9821 return noErr; 9822 } 9823 break; 9824 9825 case kEventWindowBoundsChanging: 9826 result = CallNextEventHandler (next_handler, event); 9827 if (result != eventNotHandledErr) 9828 return result; 9829 9830 err = GetEventParameter (event, kEventParamAttributes, typeUInt32, 9831 NULL, sizeof (UInt32), NULL, &attributes); 9832 if (err != noErr) 9833 break; 9834 9835 size_hints = FRAME_SIZE_HINTS (f); 9836 if ((attributes & kWindowBoundsChangeUserResize) 9837 && ((size_hints->flags & (PResizeInc | PBaseSize | PMinSize)) 9838 == (PResizeInc | PBaseSize | PMinSize))) 9839 { 9840 Rect bounds; 9841 int width, height; 9842 9843 err = GetEventParameter (event, kEventParamCurrentBounds, 9844 typeQDRectangle, NULL, sizeof (Rect), 9845 NULL, &bounds); 9846 if (err != noErr) 9847 break; 9848 9849 width = bounds.right - bounds.left; 9850 height = bounds.bottom - bounds.top; 9851 9852 if (width < size_hints->min_width) 9853 width = size_hints->min_width; 9854 else 9855 width = size_hints->base_width 9856 + (int) ((width - size_hints->base_width) 9857 / (float) size_hints->width_inc + .5) 9858 * size_hints->width_inc; 9859 9860 if (height < size_hints->min_height) 9861 height = size_hints->min_height; 9862 else 9863 height = size_hints->base_height 9864 + (int) ((height - size_hints->base_height) 9865 / (float) size_hints->height_inc + .5) 9866 * size_hints->height_inc; 9867 9868 bounds.right = bounds.left + width; 9869 bounds.bottom = bounds.top + height; 9870 SetEventParameter (event, kEventParamCurrentBounds, 9871 typeQDRectangle, sizeof (Rect), &bounds); 9872 return noErr; 9873 } 9874 break; 9875 9876 case kEventWindowBoundsChanged: 9877 err = GetEventParameter (event, kEventParamAttributes, typeUInt32, 9878 NULL, sizeof (UInt32), NULL, &attributes); 9879 if (err != noErr) 9880 break; 9881 9882 if (attributes & kWindowBoundsChangeSizeChanged) 9883 { 9884 Rect bounds; 9885 9886 err = GetEventParameter (event, kEventParamCurrentBounds, 9887 typeQDRectangle, NULL, sizeof (Rect), 9888 NULL, &bounds); 9889 if (err == noErr) 9890 { 9891 int width, height; 9892 9893 width = bounds.right - bounds.left; 9894 height = bounds.bottom - bounds.top; 9895 mac_handle_size_change (f, width, height); 9896 mac_wakeup_from_rne (); 9897 } 9898 } 9899 9900 if (attributes & kWindowBoundsChangeOriginChanged) 9901 mac_handle_origin_change (f); 9902 9903 return noErr; 9904 9905 case kEventWindowShown: 9906 case kEventWindowHidden: 9907 case kEventWindowExpanded: 9908 case kEventWindowCollapsed: 9909 result = CallNextEventHandler (next_handler, event); 9910 9911 mac_handle_visibility_change (f); 9912 return noErr; 9913 9914 break; 9915 9916 case kEventWindowClose: 9917 result = CallNextEventHandler (next_handler, event); 9918 { 9919 struct input_event buf; 9920 9921 EVENT_INIT (buf); 9922 buf.kind = DELETE_WINDOW_EVENT; 9923 XSETFRAME (buf.frame_or_window, f); 9924 buf.arg = Qnil; 9925 kbd_buffer_store_event (&buf); 9926 } 9927 return noErr; 9928 9929#ifdef MAC_OSX 9930 case kEventWindowToolbarSwitchMode: 9931 result = CallNextEventHandler (next_handler, event); 9932 { 9933 static const EventParamName names[] = {kEventParamDirectObject, 9934 kEventParamWindowMouseLocation, 9935 kEventParamKeyModifiers, 9936 kEventParamMouseButton, 9937 kEventParamClickCount, 9938 kEventParamMouseChord}; 9939 static const EventParamType types[] = {typeWindowRef, 9940 typeQDPoint, 9941 typeUInt32, 9942 typeMouseButton, 9943 typeUInt32, 9944 typeUInt32}; 9945 int num_params = sizeof (names) / sizeof (names[0]); 9946 9947 err = mac_store_event_ref_as_apple_event (0, 0, 9948 Qwindow, 9949 Qtoolbar_switch_mode, 9950 event, num_params, 9951 names, types); 9952 } 9953 return err == noErr ? noErr : result; 9954#endif 9955 9956#if USE_MAC_TSM 9957 case kEventWindowFocusAcquired: 9958 result = CallNextEventHandler (next_handler, event); 9959 err = mac_tsm_resume (); 9960 return err == noErr ? noErr : result; 9961 9962 case kEventWindowFocusRelinquish: 9963 result = CallNextEventHandler (next_handler, event); 9964 err = mac_tsm_suspend (); 9965 return err == noErr ? noErr : result; 9966#endif 9967 } 9968 9969 return eventNotHandledErr; 9970} 9971 9972static pascal OSStatus 9973mac_handle_mouse_event (next_handler, event, data) 9974 EventHandlerCallRef next_handler; 9975 EventRef event; 9976 void *data; 9977{ 9978 OSStatus result, err; 9979 9980 switch (GetEventKind (event)) 9981 { 9982 case kEventMouseWheelMoved: 9983 { 9984 WindowPtr wp; 9985 struct frame *f; 9986 EventMouseWheelAxis axis; 9987 SInt32 delta; 9988 Point point; 9989 9990 result = CallNextEventHandler (next_handler, event); 9991 if (result != eventNotHandledErr || read_socket_inev == NULL) 9992 return result; 9993 9994 err = GetEventParameter (event, kEventParamWindowRef, typeWindowRef, 9995 NULL, sizeof (WindowRef), NULL, &wp); 9996 if (err != noErr) 9997 break; 9998 9999 f = mac_window_to_frame (wp); 10000 if (f != mac_focus_frame (&one_mac_display_info)) 10001 break; 10002 10003 err = GetEventParameter (event, kEventParamMouseWheelAxis, 10004 typeMouseWheelAxis, NULL, 10005 sizeof (EventMouseWheelAxis), NULL, &axis); 10006 if (err != noErr || axis != kEventMouseWheelAxisY) 10007 break; 10008 10009 err = GetEventParameter (event, kEventParamMouseLocation, 10010 typeQDPoint, NULL, sizeof (Point), 10011 NULL, &point); 10012 if (err != noErr) 10013 break; 10014 10015 SetPortWindowPort (wp); 10016 GlobalToLocal (&point); 10017 if (point.h < 0 || point.v < 0 10018 || EQ (window_from_coordinates (f, point.h, point.v, 0, 0, 0, 1), 10019 f->tool_bar_window)) 10020 break; 10021 10022 err = GetEventParameter (event, kEventParamMouseWheelDelta, 10023 typeSInt32, NULL, sizeof (SInt32), 10024 NULL, &delta); 10025 if (err != noErr) 10026 break; 10027 10028 read_socket_inev->kind = WHEEL_EVENT; 10029 read_socket_inev->code = 0; 10030 read_socket_inev->modifiers = 10031 (mac_event_to_emacs_modifiers (event) 10032 | ((delta < 0) ? down_modifier : up_modifier)); 10033 XSETINT (read_socket_inev->x, point.h); 10034 XSETINT (read_socket_inev->y, point.v); 10035 XSETFRAME (read_socket_inev->frame_or_window, f); 10036 10037 return noErr; 10038 } 10039 break; 10040 10041 default: 10042 break; 10043 } 10044 10045 return eventNotHandledErr; 10046} 10047 10048#if USE_MAC_FONT_PANEL 10049static pascal OSStatus 10050mac_handle_font_event (next_handler, event, data) 10051 EventHandlerCallRef next_handler; 10052 EventRef event; 10053 void *data; 10054{ 10055 OSStatus result, err; 10056 Lisp_Object id_key; 10057 int num_params; 10058 const EventParamName *names; 10059 const EventParamType *types; 10060 static const EventParamName names_sel[] = {kEventParamATSUFontID, 10061 kEventParamATSUFontSize, 10062 kEventParamFMFontFamily, 10063 kEventParamFMFontSize, 10064 kEventParamFontColor}; 10065 static const EventParamType types_sel[] = {typeATSUFontID, 10066 typeATSUSize, 10067 typeFMFontFamily, 10068 typeFMFontSize, 10069 typeFontColor}; 10070 10071 result = CallNextEventHandler (next_handler, event); 10072 if (result != eventNotHandledErr) 10073 return result; 10074 10075 switch (GetEventKind (event)) 10076 { 10077 case kEventFontPanelClosed: 10078 id_key = Qpanel_closed; 10079 num_params = 0; 10080 names = NULL; 10081 types = NULL; 10082 break; 10083 10084 case kEventFontSelection: 10085 id_key = Qselection; 10086 num_params = sizeof (names_sel) / sizeof (names_sel[0]); 10087 names = names_sel; 10088 types = types_sel; 10089 break; 10090 } 10091 10092 err = mac_store_event_ref_as_apple_event (0, 0, Qfont, id_key, 10093 event, num_params, 10094 names, types); 10095 10096 return err == noErr ? noErr : eventNotHandledErr; 10097} 10098#endif 10099 10100#if USE_MAC_TSM 10101static pascal OSStatus 10102mac_handle_text_input_event (next_handler, event, data) 10103 EventHandlerCallRef next_handler; 10104 EventRef event; 10105 void *data; 10106{ 10107 OSStatus result, err = noErr; 10108 Lisp_Object id_key = Qnil; 10109 int num_params; 10110 const EventParamName *names; 10111 const EventParamType *types; 10112 static UInt32 seqno_uaia = 0; 10113 static const EventParamName names_uaia[] = 10114 {kEventParamTextInputSendComponentInstance, 10115 kEventParamTextInputSendRefCon, 10116 kEventParamTextInputSendSLRec, 10117 kEventParamTextInputSendFixLen, 10118 kEventParamTextInputSendText, 10119 kEventParamTextInputSendUpdateRng, 10120 kEventParamTextInputSendHiliteRng, 10121 kEventParamTextInputSendClauseRng, 10122 kEventParamTextInputSendPinRng, 10123 kEventParamTextInputSendTextServiceEncoding, 10124 kEventParamTextInputSendTextServiceMacEncoding, 10125 EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER}; 10126 static const EventParamType types_uaia[] = 10127 {typeComponentInstance, 10128 typeLongInteger, 10129 typeIntlWritingCode, 10130 typeLongInteger, 10131#ifdef MAC_OSX 10132 typeUnicodeText, 10133#else 10134 typeChar, 10135#endif 10136 typeTextRangeArray, 10137 typeTextRangeArray, 10138 typeOffsetArray, 10139 typeTextRange, 10140 typeUInt32, 10141 typeUInt32, 10142 typeUInt32}; 10143 static const EventParamName names_ufke[] = 10144 {kEventParamTextInputSendComponentInstance, 10145 kEventParamTextInputSendRefCon, 10146 kEventParamTextInputSendSLRec, 10147 kEventParamTextInputSendText}; 10148 static const EventParamType types_ufke[] = 10149 {typeComponentInstance, 10150 typeLongInteger, 10151 typeIntlWritingCode, 10152 typeUnicodeText}; 10153 10154 result = CallNextEventHandler (next_handler, event); 10155 10156 switch (GetEventKind (event)) 10157 { 10158 case kEventTextInputUpdateActiveInputArea: 10159 id_key = Qupdate_active_input_area; 10160 num_params = sizeof (names_uaia) / sizeof (names_uaia[0]); 10161 names = names_uaia; 10162 types = types_uaia; 10163 SetEventParameter (event, EVENT_PARAM_TEXT_INPUT_SEQUENCE_NUMBER, 10164 typeUInt32, sizeof (UInt32), &seqno_uaia); 10165 seqno_uaia++; 10166 break; 10167 10168 case kEventTextInputUnicodeForKeyEvent: 10169 { 10170 EventRef kbd_event; 10171 UInt32 actual_size, modifiers; 10172 10173 err = GetEventParameter (event, kEventParamTextInputSendKeyboardEvent, 10174 typeEventRef, NULL, sizeof (EventRef), NULL, 10175 &kbd_event); 10176 if (err == noErr) 10177 err = GetEventParameter (kbd_event, kEventParamKeyModifiers, 10178 typeUInt32, NULL, 10179 sizeof (UInt32), NULL, &modifiers); 10180 if (err == noErr && mac_mapped_modifiers (modifiers)) 10181 /* There're mapped modifier keys. Process it in 10182 XTread_socket. */ 10183 return eventNotHandledErr; 10184 if (err == noErr) 10185 err = GetEventParameter (kbd_event, kEventParamKeyUnicodes, 10186 typeUnicodeText, NULL, 0, &actual_size, 10187 NULL); 10188 if (err == noErr && actual_size == sizeof (UniChar)) 10189 { 10190 UniChar code; 10191 10192 err = GetEventParameter (kbd_event, kEventParamKeyUnicodes, 10193 typeUnicodeText, NULL, 10194 sizeof (UniChar), NULL, &code); 10195 if (err == noErr && code < 0x80) 10196 { 10197 /* ASCII character. Process it in XTread_socket. */ 10198 if (read_socket_inev && code >= 0x20 && code <= 0x7e) 10199 { 10200 UInt32 key_code; 10201 10202 err = GetEventParameter (kbd_event, kEventParamKeyCode, 10203 typeUInt32, NULL, sizeof (UInt32), 10204 NULL, &key_code); 10205 if (!(err == noErr && key_code <= 0x7f 10206 && keycode_to_xkeysym_table [key_code])) 10207 { 10208 struct frame *f = 10209 mac_focus_frame (&one_mac_display_info); 10210 10211 read_socket_inev->kind = ASCII_KEYSTROKE_EVENT; 10212 read_socket_inev->code = code; 10213 read_socket_inev->modifiers = 10214 mac_to_emacs_modifiers (modifiers); 10215 read_socket_inev->modifiers |= 10216 (extra_keyboard_modifiers 10217 & (meta_modifier | alt_modifier 10218 | hyper_modifier | super_modifier)); 10219 XSETFRAME (read_socket_inev->frame_or_window, f); 10220 } 10221 } 10222 return eventNotHandledErr; 10223 } 10224 } 10225 } 10226 /* Non-ASCII keystrokes without mapped modifiers are processed 10227 at the Lisp level. */ 10228 id_key = Qunicode_for_key_event; 10229 num_params = sizeof (names_ufke) / sizeof (names_ufke[0]); 10230 names = names_ufke; 10231 types = types_ufke; 10232 break; 10233 10234 case kEventTextInputOffsetToPos: 10235 { 10236 struct frame *f; 10237 struct window *w; 10238 Point p; 10239 10240 if (!OVERLAYP (Vmac_ts_active_input_overlay)) 10241 return eventNotHandledErr; 10242 10243 /* Strictly speaking, this is not always correct because 10244 previous events may change some states about display. */ 10245 if (NILP (Foverlay_get (Vmac_ts_active_input_overlay, Qbefore_string))) 10246 { 10247 /* Active input area is displayed in the echo area. */ 10248 w = XWINDOW (echo_area_window); 10249 f = WINDOW_XFRAME (w); 10250 } 10251 else 10252 { 10253 /* Active input area is displayed around the current point. */ 10254 f = SELECTED_FRAME (); 10255 w = XWINDOW (f->selected_window); 10256 } 10257 10258 p.h = (WINDOW_TO_FRAME_PIXEL_X (w, w->cursor.x) 10259 + WINDOW_LEFT_FRINGE_WIDTH (w)); 10260 p.v = (WINDOW_TO_FRAME_PIXEL_Y (w, w->cursor.y) 10261 + FONT_BASE (FRAME_FONT (f))); 10262 SetPortWindowPort (FRAME_MAC_WINDOW (f)); 10263 LocalToGlobal (&p); 10264 err = SetEventParameter (event, kEventParamTextInputReplyPoint, 10265 typeQDPoint, sizeof (typeQDPoint), &p); 10266 } 10267 break; 10268 10269 default: 10270 abort (); 10271 } 10272 10273 if (!NILP (id_key)) 10274 err = mac_store_event_ref_as_apple_event (0, 0, Qtext_input, id_key, 10275 event, num_params, 10276 names, types); 10277 10278 return err == noErr ? noErr : result; 10279} 10280#endif 10281 10282#ifdef MAC_OSX 10283OSStatus 10284mac_store_service_event (event) 10285 EventRef event; 10286{ 10287 OSStatus err; 10288 Lisp_Object id_key; 10289 int num_params; 10290 const EventParamName *names; 10291 const EventParamType *types; 10292 static const EventParamName names_pfm[] = 10293 {kEventParamServiceMessageName, kEventParamServiceUserData}; 10294 static const EventParamType types_pfm[] = 10295 {typeCFStringRef, typeCFStringRef}; 10296 10297 switch (GetEventKind (event)) 10298 { 10299 case kEventServicePaste: 10300 id_key = Qpaste; 10301 num_params = 0; 10302 names = NULL; 10303 types = NULL; 10304 break; 10305 10306 case kEventServicePerform: 10307 id_key = Qperform; 10308 num_params = sizeof (names_pfm) / sizeof (names_pfm[0]); 10309 names = names_pfm; 10310 types = types_pfm; 10311 break; 10312 10313 default: 10314 abort (); 10315 } 10316 10317 err = mac_store_event_ref_as_apple_event (0, 0, Qservice, id_key, 10318 event, num_params, 10319 names, types); 10320 10321 return err; 10322} 10323#endif /* MAC_OSX */ 10324#endif /* USE_CARBON_EVENTS */ 10325 10326 10327OSStatus 10328install_window_handler (window) 10329 WindowPtr window; 10330{ 10331 OSStatus err = noErr; 10332#if USE_CARBON_EVENTS 10333 static const EventTypeSpec specs_window[] = 10334 {{kEventClassWindow, kEventWindowUpdate}, 10335 {kEventClassWindow, kEventWindowGetIdealSize}, 10336 {kEventClassWindow, kEventWindowBoundsChanging}, 10337 {kEventClassWindow, kEventWindowBoundsChanged}, 10338 {kEventClassWindow, kEventWindowShown}, 10339 {kEventClassWindow, kEventWindowHidden}, 10340 {kEventClassWindow, kEventWindowExpanded}, 10341 {kEventClassWindow, kEventWindowCollapsed}, 10342 {kEventClassWindow, kEventWindowClose}, 10343#ifdef MAC_OSX 10344 {kEventClassWindow, kEventWindowToolbarSwitchMode}, 10345#endif 10346#if USE_MAC_TSM 10347 {kEventClassWindow, kEventWindowFocusAcquired}, 10348 {kEventClassWindow, kEventWindowFocusRelinquish}, 10349#endif 10350 }; 10351 static const EventTypeSpec specs_mouse[] = 10352 {{kEventClassMouse, kEventMouseWheelMoved}}; 10353 static EventHandlerUPP handle_window_eventUPP = NULL; 10354 static EventHandlerUPP handle_mouse_eventUPP = NULL; 10355#if USE_MAC_FONT_PANEL 10356 static const EventTypeSpec specs_font[] = 10357 {{kEventClassFont, kEventFontPanelClosed}, 10358 {kEventClassFont, kEventFontSelection}}; 10359 static EventHandlerUPP handle_font_eventUPP = NULL; 10360#endif 10361#if USE_MAC_TSM 10362 static const EventTypeSpec specs_text_input[] = 10363 {{kEventClassTextInput, kEventTextInputUpdateActiveInputArea}, 10364 {kEventClassTextInput, kEventTextInputUnicodeForKeyEvent}, 10365 {kEventClassTextInput, kEventTextInputOffsetToPos}}; 10366 static EventHandlerUPP handle_text_input_eventUPP = NULL; 10367#endif 10368 10369 if (handle_window_eventUPP == NULL) 10370 handle_window_eventUPP = NewEventHandlerUPP (mac_handle_window_event); 10371 if (handle_mouse_eventUPP == NULL) 10372 handle_mouse_eventUPP = NewEventHandlerUPP (mac_handle_mouse_event); 10373#if USE_MAC_FONT_PANEL 10374 if (handle_font_eventUPP == NULL) 10375 handle_font_eventUPP = NewEventHandlerUPP (mac_handle_font_event); 10376#endif 10377#if USE_MAC_TSM 10378 if (handle_text_input_eventUPP == NULL) 10379 handle_text_input_eventUPP = 10380 NewEventHandlerUPP (mac_handle_text_input_event); 10381#endif 10382 err = InstallWindowEventHandler (window, handle_window_eventUPP, 10383 GetEventTypeCount (specs_window), 10384 specs_window, NULL, NULL); 10385 if (err == noErr) 10386 err = InstallWindowEventHandler (window, handle_mouse_eventUPP, 10387 GetEventTypeCount (specs_mouse), 10388 specs_mouse, NULL, NULL); 10389#if USE_MAC_FONT_PANEL 10390 if (err == noErr) 10391 err = InstallWindowEventHandler (window, handle_font_eventUPP, 10392 GetEventTypeCount (specs_font), 10393 specs_font, NULL, NULL); 10394#endif 10395#if USE_MAC_TSM 10396 if (err == noErr) 10397 err = InstallWindowEventHandler (window, handle_text_input_eventUPP, 10398 GetEventTypeCount (specs_text_input), 10399 specs_text_input, window, NULL); 10400#endif 10401#endif 10402 if (err == noErr) 10403 err = install_drag_handler (window); 10404 if (err == noErr) 10405 err = install_menu_target_item_handler (window); 10406 10407 return err; 10408} 10409 10410void 10411remove_window_handler (window) 10412 WindowPtr window; 10413{ 10414 remove_drag_handler (window); 10415} 10416 10417 10418static pascal void 10419mac_handle_dm_notification (event) 10420 AppleEvent *event; 10421{ 10422 mac_screen_config_changed = 1; 10423} 10424 10425static OSErr 10426init_dm_notification_handler () 10427{ 10428 OSErr err; 10429 static DMNotificationUPP handle_dm_notificationUPP = NULL; 10430 ProcessSerialNumber psn; 10431 10432 if (handle_dm_notificationUPP == NULL) 10433 handle_dm_notificationUPP = 10434 NewDMNotificationUPP (mac_handle_dm_notification); 10435 10436 err = GetCurrentProcess (&psn); 10437 if (err == noErr) 10438 err = DMRegisterNotifyProc (handle_dm_notificationUPP, &psn); 10439 10440 return err; 10441} 10442 10443static void 10444mac_get_screen_info (dpyinfo) 10445 struct mac_display_info *dpyinfo; 10446{ 10447#ifdef MAC_OSX 10448 /* HasDepth returns true if it is possible to have a 32 bit display, 10449 but this may not be what is actually used. Mac OSX can do better. */ 10450 dpyinfo->color_p = CGDisplaySamplesPerPixel (kCGDirectMainDisplay) > 1; 10451 dpyinfo->n_planes = CGDisplayBitsPerPixel (kCGDirectMainDisplay); 10452 { 10453 CGDisplayErr err; 10454 CGDisplayCount ndisps; 10455 CGDirectDisplayID *displays; 10456 10457 err = CGGetActiveDisplayList (0, NULL, &ndisps); 10458 if (err == noErr) 10459 { 10460 displays = alloca (sizeof (CGDirectDisplayID) * ndisps); 10461 err = CGGetActiveDisplayList (ndisps, displays, &ndisps); 10462 } 10463 if (err == noErr) 10464 { 10465 CGRect bounds = CGRectZero; 10466 10467 while (ndisps-- > 0) 10468 bounds = CGRectUnion (bounds, CGDisplayBounds (displays[ndisps])); 10469 dpyinfo->height = CGRectGetHeight (bounds); 10470 dpyinfo->width = CGRectGetWidth (bounds); 10471 } 10472 else 10473 { 10474 dpyinfo->height = CGDisplayPixelsHigh (kCGDirectMainDisplay); 10475 dpyinfo->width = CGDisplayPixelsWide (kCGDirectMainDisplay); 10476 } 10477 } 10478#else /* !MAC_OSX */ 10479 { 10480 GDHandle gdh = GetMainDevice (); 10481 Rect rect = (**gdh).gdRect; 10482 10483 dpyinfo->color_p = TestDeviceAttribute (gdh, gdDevType); 10484 for (dpyinfo->n_planes = 32; dpyinfo->n_planes > 0; dpyinfo->n_planes >>= 1) 10485 if (HasDepth (gdh, dpyinfo->n_planes, gdDevType, dpyinfo->color_p)) 10486 break; 10487 10488 for (gdh = DMGetFirstScreenDevice (dmOnlyActiveDisplays); gdh; 10489 gdh = DMGetNextScreenDevice (gdh, dmOnlyActiveDisplays)) 10490 UnionRect (&rect, &(**gdh).gdRect, &rect); 10491 10492 dpyinfo->height = rect.bottom - rect.top; 10493 dpyinfo->width = rect.right - rect.left; 10494 } 10495#endif /* !MAC_OSX */ 10496} 10497 10498 10499#if __profile__ 10500void 10501profiler_exit_proc () 10502{ 10503 ProfilerDump ("\pEmacs.prof"); 10504 ProfilerTerm (); 10505} 10506#endif 10507 10508/* These few functions implement Emacs as a normal Mac application 10509 (almost): set up the heap and the Toolbox, handle necessary system 10510 events plus a few simple menu events. They also set up Emacs's 10511 access to functions defined in the rest of this file. Emacs uses 10512 function hooks to perform all its terminal I/O. A complete list of 10513 these functions appear in termhooks.h. For what they do, read the 10514 comments there and see also w32term.c and xterm.c. What's 10515 noticeably missing here is the event loop, which is normally 10516 present in most Mac application. After performing the necessary 10517 Mac initializations, main passes off control to emacs_main 10518 (corresponding to main in emacs.c). Emacs_main calls XTread_socket 10519 (defined further below) to read input. This is where 10520 WaitNextEvent/ReceiveNextEvent is called to process Mac events. */ 10521 10522#ifdef MAC_OS8 10523#undef main 10524int 10525main (void) 10526{ 10527#if __profile__ /* is the profiler on? */ 10528 if (ProfilerInit(collectDetailed, bestTimeBase, 5000, 200)) 10529 exit(1); 10530#endif 10531 10532#if __MWERKS__ 10533 /* set creator and type for files created by MSL */ 10534 _fcreator = MAC_EMACS_CREATOR_CODE; 10535 _ftype = 'TEXT'; 10536#endif 10537 10538 do_init_managers (); 10539 10540 do_get_menus (); 10541 10542#ifndef USE_LSB_TAG 10543 do_check_ram_size (); 10544#endif 10545 10546 init_emacs_passwd_dir (); 10547 10548 init_environ (); 10549 10550 init_coercion_handler (); 10551 10552 initialize_applescript (); 10553 10554 init_apple_event_handler (); 10555 10556 init_dm_notification_handler (); 10557 10558 { 10559 char **argv; 10560 int argc = 0; 10561 10562 /* set up argv array from STR# resource */ 10563 get_string_list (&argv, ARGV_STRING_LIST_ID); 10564 while (argv[argc]) 10565 argc++; 10566 10567 /* free up AppleScript resources on exit */ 10568 atexit (terminate_applescript); 10569 10570#if __profile__ /* is the profiler on? */ 10571 atexit (profiler_exit_proc); 10572#endif 10573 10574 /* 3rd param "envp" never used in emacs_main */ 10575 (void) emacs_main (argc, argv, 0); 10576 } 10577 10578 /* Never reached - real exit in Fkill_emacs */ 10579 return 0; 10580} 10581#endif 10582 10583#if !USE_CARBON_EVENTS 10584static RgnHandle mouse_region = NULL; 10585 10586Boolean 10587mac_wait_next_event (er, sleep_time, dequeue) 10588 EventRecord *er; 10589 UInt32 sleep_time; 10590 Boolean dequeue; 10591{ 10592 static EventRecord er_buf = {nullEvent}; 10593 UInt32 target_tick, current_tick; 10594 EventMask event_mask; 10595 10596 if (mouse_region == NULL) 10597 mouse_region = NewRgn (); 10598 10599 event_mask = everyEvent; 10600 if (!mac_ready_for_apple_events) 10601 event_mask -= highLevelEventMask; 10602 10603 current_tick = TickCount (); 10604 target_tick = current_tick + sleep_time; 10605 10606 if (er_buf.what == nullEvent) 10607 while (!WaitNextEvent (event_mask, &er_buf, 10608 target_tick - current_tick, mouse_region)) 10609 { 10610 current_tick = TickCount (); 10611 if (target_tick <= current_tick) 10612 return false; 10613 } 10614 10615 *er = er_buf; 10616 if (dequeue) 10617 er_buf.what = nullEvent; 10618 return true; 10619} 10620#endif /* not USE_CARBON_EVENTS */ 10621 10622#if TARGET_API_MAC_CARBON 10623OSStatus 10624mac_post_mouse_moved_event () 10625{ 10626 EventRef event = NULL; 10627 OSStatus err; 10628 10629 err = CreateEvent (NULL, kEventClassMouse, kEventMouseMoved, 0, 10630 kEventAttributeNone, &event); 10631 if (err == noErr) 10632 { 10633 Point mouse_pos; 10634 10635 GetGlobalMouse (&mouse_pos); 10636 err = SetEventParameter (event, kEventParamMouseLocation, typeQDPoint, 10637 sizeof (Point), &mouse_pos); 10638 } 10639 if (err == noErr) 10640 { 10641 UInt32 modifiers = GetCurrentKeyModifiers (); 10642 10643 err = SetEventParameter (event, kEventParamKeyModifiers, typeUInt32, 10644 sizeof (UInt32), &modifiers); 10645 } 10646 if (err == noErr) 10647 err = PostEventToQueue (GetCurrentEventQueue (), event, 10648 kEventPriorityStandard); 10649 if (event) 10650 ReleaseEvent (event); 10651 10652 return err; 10653} 10654 10655static void 10656mac_set_unicode_keystroke_event (code, buf) 10657 UniChar code; 10658 struct input_event *buf; 10659{ 10660 int charset_id, c1, c2; 10661 10662 if (code < 0x80) 10663 { 10664 buf->kind = ASCII_KEYSTROKE_EVENT; 10665 buf->code = code; 10666 } 10667 else if (code < 0x100) 10668 { 10669 if (code < 0xA0) 10670 charset_id = CHARSET_8_BIT_CONTROL; 10671 else 10672 charset_id = charset_latin_iso8859_1; 10673 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; 10674 buf->code = MAKE_CHAR (charset_id, code, 0); 10675 } 10676 else 10677 { 10678 if (code < 0x2500) 10679 charset_id = charset_mule_unicode_0100_24ff, 10680 code -= 0x100; 10681 else if (code < 0x33FF) 10682 charset_id = charset_mule_unicode_2500_33ff, 10683 code -= 0x2500; 10684 else if (code >= 0xE000) 10685 charset_id = charset_mule_unicode_e000_ffff, 10686 code -= 0xE000; 10687 c1 = (code / 96) + 32, c2 = (code % 96) + 32; 10688 buf->kind = MULTIBYTE_CHAR_KEYSTROKE_EVENT; 10689 buf->code = MAKE_CHAR (charset_id, c1, c2); 10690 } 10691} 10692#endif 10693 10694/* Emacs calls this whenever it wants to read an input event from the 10695 user. */ 10696int 10697XTread_socket (sd, expected, hold_quit) 10698 int sd, expected; 10699 struct input_event *hold_quit; 10700{ 10701 struct input_event inev; 10702 int count = 0; 10703#if USE_CARBON_EVENTS 10704 EventRef eventRef; 10705 EventTargetRef toolbox_dispatcher; 10706#endif 10707 EventRecord er; 10708 struct mac_display_info *dpyinfo = &one_mac_display_info; 10709 10710 if (interrupt_input_blocked) 10711 { 10712 interrupt_input_pending = 1; 10713 return -1; 10714 } 10715 10716 interrupt_input_pending = 0; 10717 BLOCK_INPUT; 10718 10719 /* So people can tell when we have read the available input. */ 10720 input_signal_count++; 10721 10722 ++handling_signal; 10723 10724#if USE_CARBON_EVENTS 10725 toolbox_dispatcher = GetEventDispatcherTarget (); 10726 10727 while ( 10728#if USE_CG_DRAWING 10729 mac_prepare_for_quickdraw (NULL), 10730#endif 10731 !ReceiveNextEvent (0, NULL, kEventDurationNoWait, 10732 kEventRemoveFromQueue, &eventRef)) 10733#else /* !USE_CARBON_EVENTS */ 10734 while (mac_wait_next_event (&er, 0, true)) 10735#endif /* !USE_CARBON_EVENTS */ 10736 { 10737 int do_help = 0; 10738 struct frame *f; 10739 unsigned long timestamp; 10740 10741 EVENT_INIT (inev); 10742 inev.kind = NO_EVENT; 10743 inev.arg = Qnil; 10744 10745#if USE_CARBON_EVENTS 10746 timestamp = GetEventTime (eventRef) / kEventDurationMillisecond; 10747#else 10748 timestamp = er.when * (1000 / 60); /* ticks to milliseconds */ 10749#endif 10750 10751#if USE_CARBON_EVENTS 10752 /* Handle new events */ 10753 if (!mac_convert_event_ref (eventRef, &er)) 10754 { 10755 /* There used to be a handler for the kEventMouseWheelMoved 10756 event here. But as of Mac OS X 10.4, this kind of event 10757 is not directly posted to the main event queue by 10758 two-finger scrolling on the trackpad. Instead, some 10759 private event is posted and it is converted to a wheel 10760 event by the default handler for the application target. 10761 The converted one can be received by a Carbon event 10762 handler installed on a window target. */ 10763 read_socket_inev = &inev; 10764 SendEventToEventTarget (eventRef, toolbox_dispatcher); 10765 read_socket_inev = NULL; 10766 } 10767 else 10768#endif /* USE_CARBON_EVENTS */ 10769 switch (er.what) 10770 { 10771 case mouseDown: 10772 case mouseUp: 10773 { 10774 WindowPtr window_ptr; 10775 ControlPartCode part_code; 10776 int tool_bar_p = 0; 10777 10778#if USE_CARBON_EVENTS 10779 /* This is needed to send mouse events like aqua window 10780 buttons to the correct handler. */ 10781 if (SendEventToEventTarget (eventRef, toolbox_dispatcher) 10782 != eventNotHandledErr) 10783 break; 10784#endif 10785 last_mouse_glyph_frame = 0; 10786 10787 if (dpyinfo->grabbed && last_mouse_frame 10788 && FRAME_LIVE_P (last_mouse_frame)) 10789 { 10790 window_ptr = FRAME_MAC_WINDOW (last_mouse_frame); 10791 part_code = inContent; 10792 } 10793 else 10794 { 10795 part_code = FindWindow (er.where, &window_ptr); 10796 if (tip_window && window_ptr == tip_window) 10797 { 10798 HideWindow (tip_window); 10799 part_code = FindWindow (er.where, &window_ptr); 10800 } 10801 } 10802 10803 if (er.what != mouseDown && 10804 (part_code != inContent || dpyinfo->grabbed == 0)) 10805 break; 10806 10807 switch (part_code) 10808 { 10809 case inMenuBar: 10810 f = mac_focus_frame (dpyinfo); 10811 saved_menu_event_location = er.where; 10812 inev.kind = MENU_BAR_ACTIVATE_EVENT; 10813 XSETFRAME (inev.frame_or_window, f); 10814 break; 10815 10816 case inContent: 10817 if ( 10818#if TARGET_API_MAC_CARBON 10819 FrontNonFloatingWindow () 10820#else 10821 FrontWindow () 10822#endif 10823 != window_ptr 10824 || (mac_window_to_frame (window_ptr) 10825 != dpyinfo->x_focus_frame)) 10826 SelectWindow (window_ptr); 10827 else 10828 { 10829 ControlPartCode control_part_code; 10830 ControlHandle ch; 10831 Point mouse_loc = er.where; 10832#ifdef MAC_OSX 10833 ControlKind control_kind; 10834#endif 10835 10836 f = mac_window_to_frame (window_ptr); 10837 /* convert to local coordinates of new window */ 10838 SetPortWindowPort (window_ptr); 10839 10840 GlobalToLocal (&mouse_loc); 10841#if TARGET_API_MAC_CARBON 10842 ch = FindControlUnderMouse (mouse_loc, window_ptr, 10843 &control_part_code); 10844#ifdef MAC_OSX 10845 if (ch) 10846 GetControlKind (ch, &control_kind); 10847#endif 10848#else 10849 control_part_code = FindControl (mouse_loc, window_ptr, 10850 &ch); 10851#endif 10852 10853#if USE_CARBON_EVENTS 10854 inev.code = mac_get_mouse_btn (eventRef); 10855 inev.modifiers = mac_event_to_emacs_modifiers (eventRef); 10856#else 10857 inev.code = mac_get_emulated_btn (er.modifiers); 10858 inev.modifiers = mac_to_emacs_modifiers (er.modifiers); 10859#endif 10860 XSETINT (inev.x, mouse_loc.h); 10861 XSETINT (inev.y, mouse_loc.v); 10862 10863 if ((dpyinfo->grabbed && tracked_scroll_bar) 10864 || (ch != 0 10865#ifndef USE_TOOLKIT_SCROLL_BARS 10866 /* control_part_code becomes kControlNoPart if 10867 a progress indicator is clicked. */ 10868 && control_part_code != kControlNoPart 10869#else /* USE_TOOLKIT_SCROLL_BARS */ 10870#ifdef MAC_OSX 10871 && control_kind.kind == kControlKindScrollBar 10872#endif /* MAC_OSX */ 10873#endif /* USE_TOOLKIT_SCROLL_BARS */ 10874 )) 10875 { 10876 struct scroll_bar *bar; 10877 10878 if (dpyinfo->grabbed && tracked_scroll_bar) 10879 { 10880 bar = tracked_scroll_bar; 10881#ifndef USE_TOOLKIT_SCROLL_BARS 10882 control_part_code = kControlIndicatorPart; 10883#endif 10884 } 10885 else 10886 bar = (struct scroll_bar *) GetControlReference (ch); 10887#ifdef USE_TOOLKIT_SCROLL_BARS 10888 /* Make the "Ctrl-Mouse-2 splits window" work 10889 for toolkit scroll bars. */ 10890 if (inev.modifiers & ctrl_modifier) 10891 x_scroll_bar_handle_click (bar, control_part_code, 10892 &er, &inev); 10893 else if (er.what == mouseDown) 10894 x_scroll_bar_handle_press (bar, control_part_code, 10895 mouse_loc, &inev); 10896 else 10897 x_scroll_bar_handle_release (bar, &inev); 10898#else /* not USE_TOOLKIT_SCROLL_BARS */ 10899 x_scroll_bar_handle_click (bar, control_part_code, 10900 &er, &inev); 10901 if (er.what == mouseDown 10902 && control_part_code == kControlIndicatorPart) 10903 tracked_scroll_bar = bar; 10904 else 10905 tracked_scroll_bar = NULL; 10906#endif /* not USE_TOOLKIT_SCROLL_BARS */ 10907 } 10908 else 10909 { 10910 Lisp_Object window; 10911 int x = mouse_loc.h; 10912 int y = mouse_loc.v; 10913 10914 window = window_from_coordinates (f, x, y, 0, 0, 0, 1); 10915 if (EQ (window, f->tool_bar_window)) 10916 { 10917 if (er.what == mouseDown) 10918 handle_tool_bar_click (f, x, y, 1, 0); 10919 else 10920 handle_tool_bar_click (f, x, y, 0, 10921 inev.modifiers); 10922 tool_bar_p = 1; 10923 } 10924 else 10925 { 10926 XSETFRAME (inev.frame_or_window, f); 10927 inev.kind = MOUSE_CLICK_EVENT; 10928 } 10929 } 10930 10931 if (er.what == mouseDown) 10932 { 10933 dpyinfo->grabbed |= (1 << inev.code); 10934 last_mouse_frame = f; 10935 10936 if (!tool_bar_p) 10937 last_tool_bar_item = -1; 10938 } 10939 else 10940 { 10941 if ((dpyinfo->grabbed & (1 << inev.code)) == 0) 10942 /* If a button is released though it was not 10943 previously pressed, that would be because 10944 of multi-button emulation. */ 10945 dpyinfo->grabbed = 0; 10946 else 10947 dpyinfo->grabbed &= ~(1 << inev.code); 10948 } 10949 10950 /* Ignore any mouse motion that happened before 10951 this event; any subsequent mouse-movement Emacs 10952 events should reflect only motion after the 10953 ButtonPress. */ 10954 if (f != 0) 10955 f->mouse_moved = 0; 10956 10957#ifdef USE_TOOLKIT_SCROLL_BARS 10958 if (inev.kind == MOUSE_CLICK_EVENT 10959 || (inev.kind == SCROLL_BAR_CLICK_EVENT 10960 && (inev.modifiers & ctrl_modifier))) 10961#endif 10962 switch (er.what) 10963 { 10964 case mouseDown: 10965 inev.modifiers |= down_modifier; 10966 break; 10967 case mouseUp: 10968 inev.modifiers |= up_modifier; 10969 break; 10970 } 10971 } 10972 break; 10973 10974 case inDrag: 10975#if TARGET_API_MAC_CARBON 10976 case inProxyIcon: 10977 if (IsWindowPathSelectClick (window_ptr, &er)) 10978 { 10979 WindowPathSelect (window_ptr, NULL, NULL); 10980 break; 10981 } 10982 if (part_code == inProxyIcon 10983 && (TrackWindowProxyDrag (window_ptr, er.where) 10984 != errUserWantsToDragWindow)) 10985 break; 10986 DragWindow (window_ptr, er.where, NULL); 10987#else /* not TARGET_API_MAC_CARBON */ 10988 DragWindow (window_ptr, er.where, &qd.screenBits.bounds); 10989#endif /* not TARGET_API_MAC_CARBON */ 10990 /* Update the frame parameters. */ 10991#if !USE_CARBON_EVENTS 10992 { 10993 struct frame *f = mac_window_to_frame (window_ptr); 10994 10995 if (f && !f->async_iconified) 10996 mac_handle_origin_change (f); 10997 } 10998#endif 10999 break; 11000 11001 case inGoAway: 11002 if (TrackGoAway (window_ptr, er.where)) 11003 { 11004 inev.kind = DELETE_WINDOW_EVENT; 11005 XSETFRAME (inev.frame_or_window, 11006 mac_window_to_frame (window_ptr)); 11007 } 11008 break; 11009 11010 /* window resize handling added --ben */ 11011 case inGrow: 11012 do_grow_window (window_ptr, &er); 11013 break; 11014 11015 /* window zoom handling added --ben */ 11016 case inZoomIn: 11017 case inZoomOut: 11018 if (TrackBox (window_ptr, er.where, part_code)) 11019 do_zoom_window (window_ptr, part_code); 11020 break; 11021 11022 default: 11023 break; 11024 } 11025 } 11026 break; 11027 11028 case updateEvt: 11029#if USE_CARBON_EVENTS 11030 if (SendEventToEventTarget (eventRef, toolbox_dispatcher) 11031 != eventNotHandledErr) 11032 break; 11033#else 11034 do_window_update ((WindowPtr) er.message); 11035#endif 11036 break; 11037 11038 case osEvt: 11039#if USE_CARBON_EVENTS 11040 if (SendEventToEventTarget (eventRef, toolbox_dispatcher) 11041 != eventNotHandledErr) 11042 break; 11043#endif 11044 switch ((er.message >> 24) & 0x000000FF) 11045 { 11046 case suspendResumeMessage: 11047#if USE_MAC_TSM 11048 if (er.message & resumeFlag) 11049 mac_tsm_resume (); 11050 else 11051 mac_tsm_suspend (); 11052#endif 11053 break; 11054 11055 case mouseMovedMessage: 11056#if !USE_CARBON_EVENTS 11057 SetRectRgn (mouse_region, er.where.h, er.where.v, 11058 er.where.h + 1, er.where.v + 1); 11059#endif 11060 previous_help_echo_string = help_echo_string; 11061 help_echo_string = Qnil; 11062 11063 if (dpyinfo->grabbed && last_mouse_frame 11064 && FRAME_LIVE_P (last_mouse_frame)) 11065 f = last_mouse_frame; 11066 else 11067 f = dpyinfo->x_focus_frame; 11068 11069 if (dpyinfo->mouse_face_hidden) 11070 { 11071 dpyinfo->mouse_face_hidden = 0; 11072 clear_mouse_face (dpyinfo); 11073 } 11074 11075 if (f) 11076 { 11077 WindowPtr wp = FRAME_MAC_WINDOW (f); 11078 Point mouse_pos = er.where; 11079 11080 SetPortWindowPort (wp); 11081 11082 GlobalToLocal (&mouse_pos); 11083 11084 if (dpyinfo->grabbed && tracked_scroll_bar) 11085#ifdef USE_TOOLKIT_SCROLL_BARS 11086 x_scroll_bar_handle_drag (wp, tracked_scroll_bar, 11087 mouse_pos, &inev); 11088#else /* not USE_TOOLKIT_SCROLL_BARS */ 11089 x_scroll_bar_note_movement (tracked_scroll_bar, 11090 mouse_pos.v 11091 - XINT (tracked_scroll_bar->top), 11092 er.when * (1000 / 60)); 11093#endif /* not USE_TOOLKIT_SCROLL_BARS */ 11094 else 11095 { 11096 /* Generate SELECT_WINDOW_EVENTs when needed. */ 11097 if (!NILP (Vmouse_autoselect_window)) 11098 { 11099 Lisp_Object window; 11100 11101 window = window_from_coordinates (f, 11102 mouse_pos.h, 11103 mouse_pos.v, 11104 0, 0, 0, 0); 11105 11106 /* Window will be selected only when it is 11107 not selected now and last mouse movement 11108 event was not in it. Minibuffer window 11109 will be selected iff it is active. */ 11110 if (WINDOWP (window) 11111 && !EQ (window, last_window) 11112 && !EQ (window, selected_window)) 11113 { 11114 inev.kind = SELECT_WINDOW_EVENT; 11115 inev.frame_or_window = window; 11116 } 11117 11118 last_window=window; 11119 } 11120 if (!note_mouse_movement (f, &mouse_pos)) 11121 help_echo_string = previous_help_echo_string; 11122 } 11123 } 11124 11125 /* If the contents of the global variable 11126 help_echo_string has changed, generate a 11127 HELP_EVENT. */ 11128 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string)) 11129 do_help = 1; 11130 break; 11131 } 11132 break; 11133 11134 case activateEvt: 11135 { 11136 WindowPtr window_ptr = (WindowPtr) er.message; 11137 11138#if USE_CARBON_EVENTS 11139 if (SendEventToEventTarget (eventRef, toolbox_dispatcher) 11140 != eventNotHandledErr) 11141 break; 11142#endif 11143 if (window_ptr == tip_window) 11144 { 11145 HideWindow (tip_window); 11146 break; 11147 } 11148 11149 if (!is_emacs_window (window_ptr)) 11150 break; 11151 11152 if ((er.modifiers & activeFlag) != 0) 11153 { 11154 /* A window has been activated */ 11155 Point mouse_loc = er.where; 11156 11157 x_detect_focus_change (dpyinfo, &er, &inev); 11158 11159 SetPortWindowPort (window_ptr); 11160 GlobalToLocal (&mouse_loc); 11161 /* Window-activated event counts as mouse movement, 11162 so update things that depend on mouse position. */ 11163 note_mouse_movement (mac_window_to_frame (window_ptr), 11164 &mouse_loc); 11165 } 11166 else 11167 { 11168 /* A window has been deactivated */ 11169#ifdef USE_TOOLKIT_SCROLL_BARS 11170 if (dpyinfo->grabbed && tracked_scroll_bar) 11171 { 11172 struct input_event event; 11173 11174 EVENT_INIT (event); 11175 event.kind = NO_EVENT; 11176 x_scroll_bar_handle_release (tracked_scroll_bar, &event); 11177 if (event.kind != NO_EVENT) 11178 { 11179 event.timestamp = timestamp; 11180 kbd_buffer_store_event_hold (&event, hold_quit); 11181 count++; 11182 } 11183 } 11184#endif 11185 dpyinfo->grabbed = 0; 11186 11187 x_detect_focus_change (dpyinfo, &er, &inev); 11188 11189 f = mac_window_to_frame (window_ptr); 11190 if (f == dpyinfo->mouse_face_mouse_frame) 11191 { 11192 /* If we move outside the frame, then we're 11193 certainly no longer on any text in the 11194 frame. */ 11195 clear_mouse_face (dpyinfo); 11196 dpyinfo->mouse_face_mouse_frame = 0; 11197 } 11198 11199 /* Generate a nil HELP_EVENT to cancel a help-echo. 11200 Do it only if there's something to cancel. 11201 Otherwise, the startup message is cleared when the 11202 mouse leaves the frame. */ 11203 if (any_help_event_p) 11204 do_help = -1; 11205 } 11206 } 11207 break; 11208 11209 case keyDown: 11210 case keyUp: 11211 case autoKey: 11212 { 11213 int keycode = (er.message & keyCodeMask) >> 8; 11214 static SInt16 last_key_script = -1; 11215 SInt16 current_key_script; 11216 UInt32 modifiers = er.modifiers, mapped_modifiers; 11217 11218#if USE_CARBON_EVENTS && defined (MAC_OSX) 11219 GetEventParameter (eventRef, kEventParamKeyModifiers, 11220 typeUInt32, NULL, 11221 sizeof (UInt32), NULL, &modifiers); 11222#endif 11223 mapped_modifiers = mac_mapped_modifiers (modifiers); 11224 11225#if USE_CARBON_EVENTS && (defined (MAC_OSX) || USE_MAC_TSM) 11226 /* When using Carbon Events, we need to pass raw keyboard 11227 events to the TSM ourselves. If TSM handles it, it 11228 will pass back noErr, otherwise it will pass back 11229 "eventNotHandledErr" and we can process it 11230 normally. */ 11231 if (!(mapped_modifiers 11232 & ~(mac_pass_command_to_system ? cmdKey : 0) 11233 & ~(mac_pass_control_to_system ? controlKey : 0))) 11234 { 11235 OSStatus err; 11236 11237 read_socket_inev = &inev; 11238 err = SendEventToEventTarget (eventRef, toolbox_dispatcher); 11239 read_socket_inev = NULL; 11240 if (err != eventNotHandledErr) 11241 break; 11242 } 11243#endif 11244 if (er.what == keyUp) 11245 break; 11246 11247 ObscureCursor (); 11248 11249 f = mac_focus_frame (dpyinfo); 11250 11251 if (!dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight) 11252 && !EQ (f->tool_bar_window, dpyinfo->mouse_face_window)) 11253 { 11254 clear_mouse_face (dpyinfo); 11255 dpyinfo->mouse_face_hidden = 1; 11256 } 11257 11258 current_key_script = GetScriptManagerVariable (smKeyScript); 11259 if (last_key_script != current_key_script) 11260 { 11261 struct input_event event; 11262 11263 EVENT_INIT (event); 11264 event.kind = LANGUAGE_CHANGE_EVENT; 11265 event.arg = Qnil; 11266 event.code = current_key_script; 11267 event.timestamp = timestamp; 11268 kbd_buffer_store_event (&event); 11269 count++; 11270 last_key_script = current_key_script; 11271 } 11272 11273#if USE_MAC_TSM 11274 if (inev.kind != NO_EVENT) 11275 break; 11276#endif 11277 11278#ifdef MAC_OSX 11279 if (mapped_modifiers & kEventKeyModifierFnMask 11280 && keycode <= 0x7f 11281 && fn_keycode_to_keycode_table[keycode]) 11282 keycode = fn_keycode_to_keycode_table[keycode]; 11283#endif 11284 if (keycode <= 0x7f && keycode_to_xkeysym_table [keycode]) 11285 { 11286 inev.kind = NON_ASCII_KEYSTROKE_EVENT; 11287 inev.code = 0xff00 | keycode_to_xkeysym_table [keycode]; 11288#ifdef MAC_OSX 11289 if (modifiers & kEventKeyModifierFnMask 11290 && keycode <= 0x7f 11291 && fn_keycode_to_keycode_table[keycode] == keycode) 11292 modifiers &= ~kEventKeyModifierFnMask; 11293#endif 11294 } 11295 else if (mapped_modifiers) 11296 { 11297 /* translate the keycode back to determine the 11298 original key */ 11299#ifdef MAC_OSX 11300 UCKeyboardLayout *uchr_ptr = NULL; 11301#if MAC_OS_X_VERSION_MAX_ALLOWED >= 1020 11302 OSStatus err; 11303 KeyboardLayoutRef layout; 11304 11305 err = KLGetCurrentKeyboardLayout (&layout); 11306 if (err == noErr) 11307 KLGetKeyboardLayoutProperty (layout, kKLuchrData, 11308 (const void **) &uchr_ptr); 11309#else 11310 static SInt16 last_key_layout_id = 0; 11311 static Handle uchr_handle = (Handle)-1; 11312 SInt16 current_key_layout_id = 11313 GetScriptVariable (current_key_script, smScriptKeys); 11314 11315 if (uchr_handle == (Handle)-1 11316 || last_key_layout_id != current_key_layout_id) 11317 { 11318 uchr_handle = GetResource ('uchr', current_key_layout_id); 11319 last_key_layout_id = current_key_layout_id; 11320 } 11321 if (uchr_handle) 11322 uchr_ptr = (UCKeyboardLayout *)*uchr_handle; 11323#endif 11324 11325 if (uchr_ptr) 11326 { 11327 OSStatus status; 11328 UInt16 key_action = er.what - keyDown; 11329 UInt32 modifier_key_state = 11330 (modifiers & ~mapped_modifiers) >> 8; 11331 UInt32 keyboard_type = LMGetKbdType (); 11332 SInt32 dead_key_state = 0; 11333 UniChar code; 11334 UniCharCount actual_length; 11335 11336 status = UCKeyTranslate (uchr_ptr, 11337 keycode, key_action, 11338 modifier_key_state, 11339 keyboard_type, 11340 kUCKeyTranslateNoDeadKeysMask, 11341 &dead_key_state, 11342 1, &actual_length, &code); 11343 if (status == noErr && actual_length == 1) 11344 mac_set_unicode_keystroke_event (code, &inev); 11345 } 11346#endif /* MAC_OSX */ 11347 11348 if (inev.kind == NO_EVENT) 11349 { 11350 /* This code comes from Keyboard Resource, 11351 Appendix C of IM - Text. This is necessary 11352 since shift is ignored in KCHR table 11353 translation when option or command is pressed. 11354 It also does not translate correctly 11355 control-shift chars like C-% so mask off shift 11356 here also. */ 11357 /* Mask off modifier keys that are mapped to some 11358 Emacs modifiers. */ 11359 int new_modifiers = er.modifiers & ~mapped_modifiers; 11360 /* set high byte of keycode to modifier high byte*/ 11361 int new_keycode = keycode | new_modifiers; 11362 Ptr kchr_ptr = (Ptr) GetScriptManagerVariable (smKCHRCache); 11363 unsigned long some_state = 0; 11364 UInt32 new_char_code; 11365 11366 new_char_code = KeyTranslate (kchr_ptr, new_keycode, 11367 &some_state); 11368 if (new_char_code == 0) 11369 /* Seems like a dead key. Append up-stroke. */ 11370 new_char_code = KeyTranslate (kchr_ptr, 11371 new_keycode | 0x80, 11372 &some_state); 11373 if (new_char_code) 11374 { 11375 inev.kind = ASCII_KEYSTROKE_EVENT; 11376 inev.code = new_char_code & 0xff; 11377 } 11378 } 11379 } 11380 11381 if (inev.kind == NO_EVENT) 11382 { 11383 inev.kind = ASCII_KEYSTROKE_EVENT; 11384 inev.code = er.message & charCodeMask; 11385 } 11386 11387 inev.modifiers = mac_to_emacs_modifiers (modifiers); 11388 inev.modifiers |= (extra_keyboard_modifiers 11389 & (meta_modifier | alt_modifier 11390 | hyper_modifier | super_modifier)); 11391 XSETFRAME (inev.frame_or_window, f); 11392 11393#if TARGET_API_MAC_CARBON 11394 if (inev.kind == ASCII_KEYSTROKE_EVENT 11395 && inev.code >= 0x80 && inev.modifiers) 11396 { 11397 OSStatus err; 11398 TextEncoding encoding = kTextEncodingMacRoman; 11399 TextToUnicodeInfo ttu_info; 11400 11401 UpgradeScriptInfoToTextEncoding (current_key_script, 11402 kTextLanguageDontCare, 11403 kTextRegionDontCare, 11404 NULL, &encoding); 11405 err = CreateTextToUnicodeInfoByEncoding (encoding, &ttu_info); 11406 if (err == noErr) 11407 { 11408 UniChar code; 11409 Str255 pstr; 11410 ByteCount unicode_len; 11411 11412 pstr[0] = 1; 11413 pstr[1] = inev.code; 11414 err = ConvertFromPStringToUnicode (ttu_info, pstr, 11415 sizeof (UniChar), 11416 &unicode_len, &code); 11417 if (err == noErr && unicode_len == sizeof (UniChar)) 11418 mac_set_unicode_keystroke_event (code, &inev); 11419 DisposeTextToUnicodeInfo (&ttu_info); 11420 } 11421 } 11422#endif 11423 } 11424 break; 11425 11426 case kHighLevelEvent: 11427 AEProcessAppleEvent (&er); 11428 break; 11429 11430 default: 11431 break; 11432 } 11433#if USE_CARBON_EVENTS 11434 ReleaseEvent (eventRef); 11435#endif 11436 11437 if (inev.kind != NO_EVENT) 11438 { 11439 inev.timestamp = timestamp; 11440 kbd_buffer_store_event_hold (&inev, hold_quit); 11441 count++; 11442 } 11443 11444 if (do_help 11445 && !(hold_quit && hold_quit->kind != NO_EVENT)) 11446 { 11447 Lisp_Object frame; 11448 11449 if (f) 11450 XSETFRAME (frame, f); 11451 else 11452 frame = Qnil; 11453 11454 if (do_help > 0) 11455 { 11456 any_help_event_p = 1; 11457 gen_help_event (help_echo_string, frame, help_echo_window, 11458 help_echo_object, help_echo_pos); 11459 } 11460 else 11461 { 11462 help_echo_string = Qnil; 11463 gen_help_event (Qnil, frame, Qnil, Qnil, 0); 11464 } 11465 count++; 11466 } 11467 11468 } 11469 11470 /* If the focus was just given to an autoraising frame, 11471 raise it now. */ 11472 /* ??? This ought to be able to handle more than one such frame. */ 11473 if (pending_autoraise_frame) 11474 { 11475 x_raise_frame (pending_autoraise_frame); 11476 pending_autoraise_frame = 0; 11477 } 11478 11479 if (mac_screen_config_changed) 11480 { 11481 mac_get_screen_info (dpyinfo); 11482 mac_screen_config_changed = 0; 11483 } 11484 11485#if !USE_CARBON_EVENTS 11486 /* Check which frames are still visible. We do this here because 11487 there doesn't seem to be any direct notification from the Window 11488 Manager that the visibility of a window has changed (at least, 11489 not in all cases). */ 11490 { 11491 Lisp_Object tail, frame; 11492 11493 FOR_EACH_FRAME (tail, frame) 11494 { 11495 struct frame *f = XFRAME (frame); 11496 11497 /* The tooltip has been drawn already. Avoid the 11498 SET_FRAME_GARBAGED in mac_handle_visibility_change. */ 11499 if (EQ (frame, tip_frame)) 11500 continue; 11501 11502 if (FRAME_MAC_P (f)) 11503 mac_handle_visibility_change (f); 11504 } 11505 } 11506#endif 11507 11508 --handling_signal; 11509 UNBLOCK_INPUT; 11510 return count; 11511} 11512 11513 11514/* Need to override CodeWarrior's input function so no conversion is 11515 done on newlines Otherwise compiled functions in .elc files will be 11516 read incorrectly. Defined in ...:MSL C:MSL 11517 Common:Source:buffer_io.c. */ 11518#ifdef __MWERKS__ 11519void 11520__convert_to_newlines (unsigned char * p, size_t * n) 11521{ 11522#pragma unused(p,n) 11523} 11524 11525void 11526__convert_from_newlines (unsigned char * p, size_t * n) 11527{ 11528#pragma unused(p,n) 11529} 11530#endif 11531 11532#ifdef MAC_OS8 11533void 11534make_mac_terminal_frame (struct frame *f) 11535{ 11536 Lisp_Object frame; 11537 Rect r; 11538 11539 XSETFRAME (frame, f); 11540 11541 f->output_method = output_mac; 11542 f->output_data.mac = (struct mac_output *) 11543 xmalloc (sizeof (struct mac_output)); 11544 bzero (f->output_data.mac, sizeof (struct mac_output)); 11545 11546 XSETFRAME (FRAME_KBOARD (f)->Vdefault_minibuffer_frame, f); 11547 11548 FRAME_COLS (f) = 96; 11549 FRAME_LINES (f) = 4; 11550 11551 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1; 11552 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_right; 11553 11554 FRAME_DESIRED_CURSOR (f) = FILLED_BOX_CURSOR; 11555 11556 f->output_data.mac->cursor_pixel = 0; 11557 f->output_data.mac->border_pixel = 0x00ff00; 11558 f->output_data.mac->mouse_pixel = 0xff00ff; 11559 f->output_data.mac->cursor_foreground_pixel = 0x0000ff; 11560 11561 f->output_data.mac->text_cursor = kThemeIBeamCursor; 11562 f->output_data.mac->nontext_cursor = kThemeArrowCursor; 11563 f->output_data.mac->modeline_cursor = kThemeArrowCursor; 11564 f->output_data.mac->hand_cursor = kThemePointingHandCursor; 11565 f->output_data.mac->hourglass_cursor = kThemeWatchCursor; 11566 f->output_data.mac->horizontal_drag_cursor = kThemeResizeLeftRightCursor; 11567 11568 FRAME_FONTSET (f) = -1; 11569 f->output_data.mac->explicit_parent = 0; 11570 f->left_pos = 8; 11571 f->top_pos = 32; 11572 f->border_width = 0; 11573 11574 f->internal_border_width = 0; 11575 11576 f->auto_raise = 1; 11577 f->auto_lower = 1; 11578 11579 f->new_text_cols = 0; 11580 f->new_text_lines = 0; 11581 11582 SetRect (&r, f->left_pos, f->top_pos, 11583 f->left_pos + FRAME_PIXEL_WIDTH (f), 11584 f->top_pos + FRAME_PIXEL_HEIGHT (f)); 11585 11586 BLOCK_INPUT; 11587 11588 if (!(FRAME_MAC_WINDOW (f) = 11589 NewCWindow (NULL, &r, "\p", true, dBoxProc, 11590 (WindowPtr) -1, 1, (long) f->output_data.mac))) 11591 abort (); 11592 /* so that update events can find this mac_output struct */ 11593 f->output_data.mac->mFP = f; /* point back to emacs frame */ 11594 11595 UNBLOCK_INPUT; 11596 11597 x_make_gc (f); 11598 11599 /* Need to be initialized for unshow_buffer in window.c. */ 11600 selected_window = f->selected_window; 11601 11602 Fmodify_frame_parameters (frame, 11603 Fcons (Fcons (Qfont, 11604 build_string ("-*-monaco-medium-r-*--*-90-*-*-*-*-mac-roman")), Qnil)); 11605 Fmodify_frame_parameters (frame, 11606 Fcons (Fcons (Qforeground_color, 11607 build_string ("black")), Qnil)); 11608 Fmodify_frame_parameters (frame, 11609 Fcons (Fcons (Qbackground_color, 11610 build_string ("white")), Qnil)); 11611} 11612#endif 11613 11614 11615/*********************************************************************** 11616 Initialization 11617 ***********************************************************************/ 11618 11619static int mac_initialized = 0; 11620 11621static XrmDatabase 11622mac_make_rdb (xrm_option) 11623 const char *xrm_option; 11624{ 11625 XrmDatabase database; 11626 11627 database = xrm_get_preference_database (NULL); 11628 if (xrm_option) 11629 xrm_merge_string_database (database, xrm_option); 11630 11631 return database; 11632} 11633 11634struct mac_display_info * 11635mac_term_init (display_name, xrm_option, resource_name) 11636 Lisp_Object display_name; 11637 char *xrm_option; 11638 char *resource_name; 11639{ 11640 struct mac_display_info *dpyinfo; 11641 11642 BLOCK_INPUT; 11643 11644 if (!mac_initialized) 11645 { 11646 mac_initialize (); 11647 mac_initialized = 1; 11648 } 11649 11650 if (x_display_list) 11651 error ("Sorry, this version can only handle one display"); 11652 11653 dpyinfo = &one_mac_display_info; 11654 bzero (dpyinfo, sizeof (*dpyinfo)); 11655 11656#ifdef MAC_OSX 11657 dpyinfo->mac_id_name 11658 = (char *) xmalloc (SCHARS (Vinvocation_name) 11659 + SCHARS (Vsystem_name) 11660 + 2); 11661 sprintf (dpyinfo->mac_id_name, "%s@%s", 11662 SDATA (Vinvocation_name), SDATA (Vsystem_name)); 11663#else 11664 dpyinfo->mac_id_name = (char *) xmalloc (strlen ("Mac Display") + 1); 11665 strcpy (dpyinfo->mac_id_name, "Mac Display"); 11666#endif 11667 11668 dpyinfo->reference_count = 0; 11669 dpyinfo->resx = 72.0; 11670 dpyinfo->resy = 72.0; 11671 11672 mac_get_screen_info (dpyinfo); 11673 11674 dpyinfo->grabbed = 0; 11675 dpyinfo->root_window = NULL; 11676 dpyinfo->image_cache = make_image_cache (); 11677 11678 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1; 11679 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1; 11680 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID; 11681 dpyinfo->mouse_face_window = Qnil; 11682 dpyinfo->mouse_face_overlay = Qnil; 11683 dpyinfo->mouse_face_hidden = 0; 11684 11685 dpyinfo->xrdb = mac_make_rdb (xrm_option); 11686 11687 /* Put this display on the chain. */ 11688 dpyinfo->next = x_display_list; 11689 x_display_list = dpyinfo; 11690 11691 /* Put it on x_display_name_list. */ 11692 x_display_name_list = Fcons (Fcons (display_name, 11693 Fcons (Qnil, dpyinfo->xrdb)), 11694 x_display_name_list); 11695 dpyinfo->name_list_element = XCAR (x_display_name_list); 11696 11697 UNBLOCK_INPUT; 11698 11699 return dpyinfo; 11700} 11701 11702/* Get rid of display DPYINFO, assuming all frames are already gone. */ 11703 11704void 11705x_delete_display (dpyinfo) 11706 struct mac_display_info *dpyinfo; 11707{ 11708 int i; 11709 11710 /* Discard this display from x_display_name_list and x_display_list. 11711 We can't use Fdelq because that can quit. */ 11712 if (! NILP (x_display_name_list) 11713 && EQ (XCAR (x_display_name_list), dpyinfo->name_list_element)) 11714 x_display_name_list = XCDR (x_display_name_list); 11715 else 11716 { 11717 Lisp_Object tail; 11718 11719 tail = x_display_name_list; 11720 while (CONSP (tail) && CONSP (XCDR (tail))) 11721 { 11722 if (EQ (XCAR (XCDR (tail)), dpyinfo->name_list_element)) 11723 { 11724 XSETCDR (tail, XCDR (XCDR (tail))); 11725 break; 11726 } 11727 tail = XCDR (tail); 11728 } 11729 } 11730 11731 if (x_display_list == dpyinfo) 11732 x_display_list = dpyinfo->next; 11733 else 11734 { 11735 struct x_display_info *tail; 11736 11737 for (tail = x_display_list; tail; tail = tail->next) 11738 if (tail->next == dpyinfo) 11739 tail->next = tail->next->next; 11740 } 11741 11742 /* Free the font names in the font table. */ 11743 for (i = 0; i < dpyinfo->n_fonts; i++) 11744 if (dpyinfo->font_table[i].name) 11745 { 11746 if (dpyinfo->font_table[i].name != dpyinfo->font_table[i].full_name) 11747 xfree (dpyinfo->font_table[i].full_name); 11748 xfree (dpyinfo->font_table[i].name); 11749 } 11750 11751 if (dpyinfo->font_table) 11752 { 11753 if (dpyinfo->font_table->font_encoder) 11754 xfree (dpyinfo->font_table->font_encoder); 11755 xfree (dpyinfo->font_table); 11756 } 11757 if (dpyinfo->mac_id_name) 11758 xfree (dpyinfo->mac_id_name); 11759 11760 if (x_display_list == 0) 11761 { 11762 mac_clear_font_name_table (); 11763 bzero (dpyinfo, sizeof (*dpyinfo)); 11764 } 11765} 11766 11767 11768static void 11769init_menu_bar () 11770{ 11771#ifdef MAC_OSX 11772 OSStatus err; 11773 MenuRef menu; 11774 MenuItemIndex menu_index; 11775 11776 err = GetIndMenuItemWithCommandID (NULL, kHICommandQuit, 1, 11777 &menu, &menu_index); 11778 if (err == noErr) 11779 SetMenuItemCommandKey (menu, menu_index, false, 0); 11780#if USE_CARBON_EVENTS 11781 EnableMenuCommand (NULL, kHICommandPreferences); 11782 err = GetIndMenuItemWithCommandID (NULL, kHICommandPreferences, 1, 11783 &menu, &menu_index); 11784 if (err == noErr) 11785 { 11786 SetMenuItemCommandKey (menu, menu_index, false, 0); 11787 InsertMenuItemTextWithCFString (menu, NULL, 11788 0, kMenuItemAttrSeparator, 0); 11789 InsertMenuItemTextWithCFString (menu, CFSTR ("About Emacs"), 11790 0, 0, kHICommandAbout); 11791 } 11792#endif /* USE_CARBON_EVENTS */ 11793#else /* !MAC_OSX */ 11794#if USE_CARBON_EVENTS 11795 SetMenuItemCommandID (GetMenuHandle (M_APPLE), I_ABOUT, kHICommandAbout); 11796#endif 11797#endif 11798} 11799 11800#if USE_MAC_TSM 11801static void 11802init_tsm () 11803{ 11804#ifdef MAC_OSX 11805 static InterfaceTypeList types = {kUnicodeDocument}; 11806#else 11807 static InterfaceTypeList types = {kTextService}; 11808#endif 11809 11810 NewTSMDocument (sizeof (types) / sizeof (types[0]), types, 11811 &tsm_document_id, 0); 11812} 11813#endif 11814 11815/* Set up use of X before we make the first connection. */ 11816 11817extern frame_parm_handler mac_frame_parm_handlers[]; 11818 11819static struct redisplay_interface x_redisplay_interface = 11820{ 11821 mac_frame_parm_handlers, 11822 x_produce_glyphs, 11823 x_write_glyphs, 11824 x_insert_glyphs, 11825 x_clear_end_of_line, 11826 x_scroll_run, 11827 x_after_update_window_line, 11828 x_update_window_begin, 11829 x_update_window_end, 11830 x_cursor_to, 11831 x_flush, 11832#if USE_CG_DRAWING 11833 mac_flush_display_optional, 11834#else 11835 0, /* flush_display_optional */ 11836#endif 11837 x_clear_window_mouse_face, 11838 x_get_glyph_overhangs, 11839 x_fix_overlapping_area, 11840 x_draw_fringe_bitmap, 11841#if USE_CG_DRAWING 11842 mac_define_fringe_bitmap, 11843 mac_destroy_fringe_bitmap, 11844#else 11845 0, /* define_fringe_bitmap */ 11846 0, /* destroy_fringe_bitmap */ 11847#endif 11848 mac_per_char_metric, 11849 mac_encode_char, 11850 mac_compute_glyph_string_overhangs, 11851 x_draw_glyph_string, 11852 mac_define_frame_cursor, 11853 mac_clear_frame_area, 11854 mac_draw_window_cursor, 11855 mac_draw_vertical_window_border, 11856 mac_shift_glyphs_for_insert 11857}; 11858 11859void 11860mac_initialize () 11861{ 11862 rif = &x_redisplay_interface; 11863 11864 clear_frame_hook = x_clear_frame; 11865 ins_del_lines_hook = x_ins_del_lines; 11866 delete_glyphs_hook = x_delete_glyphs; 11867 ring_bell_hook = XTring_bell; 11868 reset_terminal_modes_hook = XTreset_terminal_modes; 11869 set_terminal_modes_hook = XTset_terminal_modes; 11870 update_begin_hook = x_update_begin; 11871 update_end_hook = x_update_end; 11872 set_terminal_window_hook = XTset_terminal_window; 11873 read_socket_hook = XTread_socket; 11874 frame_up_to_date_hook = XTframe_up_to_date; 11875 mouse_position_hook = XTmouse_position; 11876 frame_rehighlight_hook = XTframe_rehighlight; 11877 frame_raise_lower_hook = XTframe_raise_lower; 11878 11879 set_vertical_scroll_bar_hook = XTset_vertical_scroll_bar; 11880 condemn_scroll_bars_hook = XTcondemn_scroll_bars; 11881 redeem_scroll_bar_hook = XTredeem_scroll_bar; 11882 judge_scroll_bars_hook = XTjudge_scroll_bars; 11883 11884 scroll_region_ok = 1; /* we'll scroll partial frames */ 11885 char_ins_del_ok = 1; 11886 line_ins_del_ok = 1; /* we'll just blt 'em */ 11887 fast_clear_end_of_line = 1; /* X does this well */ 11888 memory_below_frame = 0; /* we don't remember what scrolls 11889 off the bottom */ 11890 baud_rate = 19200; 11891 11892 last_tool_bar_item = -1; 11893 any_help_event_p = 0; 11894 11895 /* Try to use interrupt input; if we can't, then start polling. */ 11896 Fset_input_mode (Qt, Qnil, Qt, Qnil); 11897 11898 BLOCK_INPUT; 11899 11900#if TARGET_API_MAC_CARBON 11901 11902#if USE_CARBON_EVENTS 11903#ifdef MAC_OSX 11904 init_service_handler (); 11905#endif /* MAC_OSX */ 11906 11907 init_command_handler (); 11908 11909 init_menu_bar (); 11910 11911#if USE_MAC_TSM 11912 init_tsm (); 11913#endif 11914#endif /* USE_CARBON_EVENTS */ 11915 11916#ifdef MAC_OSX 11917 init_coercion_handler (); 11918 11919 init_apple_event_handler (); 11920 11921 init_dm_notification_handler (); 11922 11923 if (!inhibit_window_system) 11924 { 11925 static const ProcessSerialNumber psn = {0, kCurrentProcess}; 11926 11927 SetFrontProcess (&psn); 11928 } 11929#endif 11930#endif 11931 11932#if USE_CG_DRAWING 11933 init_cg_color (); 11934 11935 mac_init_fringe (); 11936#endif 11937 11938 UNBLOCK_INPUT; 11939} 11940 11941 11942void 11943syms_of_macterm () 11944{ 11945#if 0 11946 staticpro (&x_error_message_string); 11947 x_error_message_string = Qnil; 11948#endif 11949 11950 Qcontrol = intern ("control"); staticpro (&Qcontrol); 11951 Qmeta = intern ("meta"); staticpro (&Qmeta); 11952 Qalt = intern ("alt"); staticpro (&Qalt); 11953 Qhyper = intern ("hyper"); staticpro (&Qhyper); 11954 Qsuper = intern ("super"); staticpro (&Qsuper); 11955 Qmodifier_value = intern ("modifier-value"); 11956 staticpro (&Qmodifier_value); 11957 11958 Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier)); 11959 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier)); 11960 Fput (Qalt, Qmodifier_value, make_number (alt_modifier)); 11961 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier)); 11962 Fput (Qsuper, Qmodifier_value, make_number (super_modifier)); 11963 11964#if USE_CARBON_EVENTS 11965 Qhi_command = intern ("hi-command"); staticpro (&Qhi_command); 11966#ifdef MAC_OSX 11967 Qtoolbar_switch_mode = intern ("toolbar-switch-mode"); 11968 staticpro (&Qtoolbar_switch_mode); 11969#if USE_MAC_FONT_PANEL 11970 Qpanel_closed = intern ("panel-closed"); staticpro (&Qpanel_closed); 11971 Qselection = intern ("selection"); staticpro (&Qselection); 11972#endif 11973 11974 Qservice = intern ("service"); staticpro (&Qservice); 11975 Qpaste = intern ("paste"); staticpro (&Qpaste); 11976 Qperform = intern ("perform"); staticpro (&Qperform); 11977#endif 11978#if USE_MAC_TSM 11979 Qtext_input = intern ("text-input"); staticpro (&Qtext_input); 11980 Qupdate_active_input_area = intern ("update-active-input-area"); 11981 staticpro (&Qupdate_active_input_area); 11982 Qunicode_for_key_event = intern ("unicode-for-key-event"); 11983 staticpro (&Qunicode_for_key_event); 11984#endif 11985#endif 11986 11987#ifdef MAC_OSX 11988 Fprovide (intern ("mac-carbon"), Qnil); 11989#endif 11990 11991 staticpro (&Qreverse); 11992 Qreverse = intern ("reverse"); 11993 11994 staticpro (&x_display_name_list); 11995 x_display_name_list = Qnil; 11996 11997 staticpro (&last_mouse_scroll_bar); 11998 last_mouse_scroll_bar = Qnil; 11999 12000 staticpro (&fm_font_family_alist); 12001 fm_font_family_alist = Qnil; 12002 12003#if USE_ATSUI 12004 staticpro (&atsu_font_id_hash); 12005 atsu_font_id_hash = Qnil; 12006 12007 staticpro (&fm_style_face_attributes_alist); 12008 fm_style_face_attributes_alist = Qnil; 12009#endif 12010 12011#if USE_MAC_TSM 12012 staticpro (&saved_ts_script_language_on_focus); 12013 saved_ts_script_language_on_focus = Qnil; 12014#endif 12015 12016 /* We don't yet support this, but defining this here avoids whining 12017 from cus-start.el and other places, like "M-x set-variable". */ 12018 DEFVAR_BOOL ("x-use-underline-position-properties", 12019 &x_use_underline_position_properties, 12020 doc: /* *Non-nil means make use of UNDERLINE_POSITION font properties. 12021A value of nil means ignore them. If you encounter fonts with bogus 12022UNDERLINE_POSITION font properties, for example 7x13 on XFree prior 12023to 4.1, set this to nil. 12024 12025NOTE: Not supported on Mac yet. */); 12026 x_use_underline_position_properties = 0; 12027 12028 DEFVAR_BOOL ("x-underline-at-descent-line", 12029 &x_underline_at_descent_line, 12030 doc: /* *Non-nil means to draw the underline at the same place as the descent line. 12031A value of nil means to draw the underline according to the value of the 12032variable `x-use-underline-position-properties', which is usually at the 12033baseline level. The default value is nil. */); 12034 x_underline_at_descent_line = 0; 12035 12036 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars, 12037 doc: /* If not nil, Emacs uses toolkit scroll bars. */); 12038#ifdef USE_TOOLKIT_SCROLL_BARS 12039 Vx_toolkit_scroll_bars = Qt; 12040#else 12041 Vx_toolkit_scroll_bars = Qnil; 12042#endif 12043 12044 staticpro (&last_mouse_motion_frame); 12045 last_mouse_motion_frame = Qnil; 12046 12047/* Variables to configure modifier key assignment. */ 12048 12049 DEFVAR_LISP ("mac-control-modifier", &Vmac_control_modifier, 12050 doc: /* *Modifier key assumed when the Mac control key is pressed. 12051The value can be `control', `meta', `alt', `hyper', or `super' for the 12052respective modifier. The default is `control'. */); 12053 Vmac_control_modifier = Qcontrol; 12054 12055 DEFVAR_LISP ("mac-option-modifier", &Vmac_option_modifier, 12056 doc: /* *Modifier key assumed when the Mac alt/option key is pressed. 12057The value can be `control', `meta', `alt', `hyper', or `super' for the 12058respective modifier. If the value is nil then the key will act as the 12059normal Mac control modifier, and the option key can be used to compose 12060characters depending on the chosen Mac keyboard setting. */); 12061 Vmac_option_modifier = Qnil; 12062 12063 DEFVAR_LISP ("mac-command-modifier", &Vmac_command_modifier, 12064 doc: /* *Modifier key assumed when the Mac command key is pressed. 12065The value can be `control', `meta', `alt', `hyper', or `super' for the 12066respective modifier. The default is `meta'. */); 12067 Vmac_command_modifier = Qmeta; 12068 12069 DEFVAR_LISP ("mac-function-modifier", &Vmac_function_modifier, 12070 doc: /* *Modifier key assumed when the Mac function key is pressed. 12071The value can be `control', `meta', `alt', `hyper', or `super' for the 12072respective modifier. Note that remapping the function key may lead to 12073unexpected results for some keys on non-US/GB keyboards. */); 12074 Vmac_function_modifier = Qnil; 12075 12076 DEFVAR_LISP ("mac-emulate-three-button-mouse", 12077 &Vmac_emulate_three_button_mouse, 12078 doc: /* *Specify a way of three button mouse emulation. 12079The value can be nil, t, or the symbol `reverse'. 12080A value of nil means that no emulation should be done and the modifiers 12081should be placed on the mouse-1 event. 12082t means that when the option-key is held down while pressing the mouse 12083button, the click will register as mouse-2 and while the command-key 12084is held down, the click will register as mouse-3. 12085The symbol `reverse' means that the option-key will register for 12086mouse-3 and the command-key will register for mouse-2. */); 12087 Vmac_emulate_three_button_mouse = Qnil; 12088 12089#if USE_CARBON_EVENTS 12090 DEFVAR_BOOL ("mac-wheel-button-is-mouse-2", &mac_wheel_button_is_mouse_2, 12091 doc: /* *Non-nil if the wheel button is mouse-2 and the right click mouse-3. 12092Otherwise, the right click will be treated as mouse-2 and the wheel 12093button will be mouse-3. */); 12094 mac_wheel_button_is_mouse_2 = 1; 12095 12096 DEFVAR_BOOL ("mac-pass-command-to-system", &mac_pass_command_to_system, 12097 doc: /* *Non-nil if command key presses are passed on to the Mac Toolbox. */); 12098 mac_pass_command_to_system = 1; 12099 12100 DEFVAR_BOOL ("mac-pass-control-to-system", &mac_pass_control_to_system, 12101 doc: /* *Non-nil if control key presses are passed on to the Mac Toolbox. */); 12102 mac_pass_control_to_system = 1; 12103 12104#endif 12105 12106 DEFVAR_BOOL ("mac-allow-anti-aliasing", &mac_use_core_graphics, 12107 doc: /* *If non-nil, allow anti-aliasing. 12108The text will be rendered using Core Graphics text rendering which 12109may anti-alias the text. */); 12110#if USE_CG_DRAWING 12111 mac_use_core_graphics = 1; 12112#else 12113 mac_use_core_graphics = 0; 12114#endif 12115 12116 /* Register an entry for `mac-roman' so that it can be used when 12117 creating the terminal frame on Mac OS 9 before loading 12118 term/mac-win.elc. */ 12119 DEFVAR_LISP ("mac-charset-info-alist", &Vmac_charset_info_alist, 12120 doc: /* Alist of Emacs character sets vs text encodings and coding systems. 12121Each entry should be of the form: 12122 12123 (CHARSET-NAME TEXT-ENCODING CODING-SYSTEM) 12124 12125where CHARSET-NAME is a string used in font names to identify the 12126charset, TEXT-ENCODING is a TextEncodingBase value in Mac, and 12127CODING_SYSTEM is a coding system corresponding to TEXT-ENCODING. */); 12128 Vmac_charset_info_alist = 12129 Fcons (list3 (build_string ("mac-roman"), 12130 make_number (smRoman), Qnil), Qnil); 12131 12132#if USE_MAC_TSM 12133 DEFVAR_LISP ("mac-ts-active-input-overlay", &Vmac_ts_active_input_overlay, 12134 doc: /* Overlay used to display Mac TSM active input area. */); 12135 Vmac_ts_active_input_overlay = Qnil; 12136 12137 DEFVAR_LISP ("mac-ts-script-language-on-focus", &Vmac_ts_script_language_on_focus, 12138 doc: /* *How to change Mac TSM script/language when a frame gets focus. 12139If the value is t, the input script and language are restored to those 12140used in the last focus frame. If the value is a pair of integers, the 12141input script and language codes, which are defined in the Script 12142Manager, are set to its car and cdr parts, respectively. Otherwise, 12143Emacs doesn't set them and thus follows the system default behavior. */); 12144 Vmac_ts_script_language_on_focus = Qnil; 12145#endif 12146} 12147 12148/* arch-tag: f2259165-4454-4c04-a029-a133c8af7b5b 12149 (do not change this comment) */ 12150