1 /* NeXT/Open/GNUstep / MacOSX communication module.
2 Copyright (C) 1989, 1993, 1994, 2005, 2006, 2008
3 Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21 Originally by Carl Edman
22 Updated by Christian Limpach (chris@nice.ch)
23 OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com)
24 MacOSX/Aqua port by Christophe de Dinechin (descubes@earthlink.net)
25 GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
28 /* This should be the first include, as it may set up #defines affecting
29 interpretation of even the system includes. */
33 #include <sys/types.h>
38 #include "blockinput.h"
39 #include "sysselect.h"
42 #include "character.h"
44 #include "composite.h"
47 #include "termhooks.h"
58 int term_trace_num = 0;
59 #define NSTRACE(x) fprintf (stderr, "%s:%d: [%d] " #x "\n", \
60 __FILE__, __LINE__, ++term_trace_num)
66 /* ==========================================================================
70 ========================================================================== */
72 /* Special keycodes that we pass down the event chain */
73 #define KEY_NS_POWER_OFF ((1<<28)|(0<<16)|1)
74 #define KEY_NS_OPEN_FILE ((1<<28)|(0<<16)|2)
75 #define KEY_NS_OPEN_TEMP_FILE ((1<<28)|(0<<16)|3)
76 #define KEY_NS_DRAG_FILE ((1<<28)|(0<<16)|4)
77 #define KEY_NS_DRAG_COLOR ((1<<28)|(0<<16)|5)
78 #define KEY_NS_DRAG_TEXT ((1<<28)|(0<<16)|6)
79 #define KEY_NS_CHANGE_FONT ((1<<28)|(0<<16)|7)
80 #define KEY_NS_OPEN_FILE_LINE ((1<<28)|(0<<16)|8)
81 #define KEY_NS_INSERT_WORKING_TEXT ((1<<28)|(0<<16)|9)
82 #define KEY_NS_DELETE_WORKING_TEXT ((1<<28)|(0<<16)|10)
83 #define KEY_NS_SPI_SERVICE_CALL ((1<<28)|(0<<16)|11)
84 #define KEY_NS_NEW_FRAME ((1<<28)|(0<<16)|12)
86 /* Convert a symbol indexed with an NSxxx value to a value as defined
87 in keyboard.c (lispy_function_key). I hope this is a correct way
89 static unsigned convert_ns_to_X_keysym[] =
91 NSHomeFunctionKey, 0x50,
92 NSLeftArrowFunctionKey, 0x51,
93 NSUpArrowFunctionKey, 0x52,
94 NSRightArrowFunctionKey, 0x53,
95 NSDownArrowFunctionKey, 0x54,
96 NSPageUpFunctionKey, 0x55,
97 NSPageDownFunctionKey, 0x56,
98 NSEndFunctionKey, 0x57,
99 NSBeginFunctionKey, 0x58,
100 NSSelectFunctionKey, 0x60,
101 NSPrintFunctionKey, 0x61,
102 NSExecuteFunctionKey, 0x62,
103 NSInsertFunctionKey, 0x63,
104 NSUndoFunctionKey, 0x65,
105 NSRedoFunctionKey, 0x66,
106 NSMenuFunctionKey, 0x67,
107 NSFindFunctionKey, 0x68,
108 NSHelpFunctionKey, 0x6A,
109 NSBreakFunctionKey, 0x6B,
111 NSF1FunctionKey, 0xBE,
112 NSF2FunctionKey, 0xBF,
113 NSF3FunctionKey, 0xC0,
114 NSF4FunctionKey, 0xC1,
115 NSF5FunctionKey, 0xC2,
116 NSF6FunctionKey, 0xC3,
117 NSF7FunctionKey, 0xC4,
118 NSF8FunctionKey, 0xC5,
119 NSF9FunctionKey, 0xC6,
120 NSF10FunctionKey, 0xC7,
121 NSF11FunctionKey, 0xC8,
122 NSF12FunctionKey, 0xC9,
123 NSF13FunctionKey, 0xCA,
124 NSF14FunctionKey, 0xCB,
125 NSF15FunctionKey, 0xCC,
127 NSBackspaceCharacter, 0x08, /* 8: Not on some KBs. */
128 NSDeleteCharacter, 0xFF, /* 127: Big 'delete' key upper right. */
129 NSDeleteFunctionKey, 0x9F, /* 63272: Del forw key off main array. */
131 NSTabCharacter, 0x09,
132 0x19, 0x09, /* left tab->regular since pass shift */
133 NSCarriageReturnCharacter, 0x0D,
134 NSNewlineCharacter, 0x0D,
135 NSEnterCharacter, 0x8D,
137 0x1B, 0x1B /* escape */
141 /* Lisp communications */
142 Lisp_Object ns_input_file, ns_input_font, ns_input_fontsize, ns_input_line;
143 Lisp_Object ns_input_color, ns_input_text, ns_working_text;
144 Lisp_Object ns_input_spi_name, ns_input_spi_arg;
145 Lisp_Object Vx_toolkit_scroll_bars;
146 static Lisp_Object Qmodifier_value;
147 /* TODO: unsure why these defined in term files, anyway we need in keymap.c */
148 Lisp_Object Qalt, Qcontrol, Qhyper, Qmeta, Qsuper;
149 extern Lisp_Object Qcursor_color, Qcursor_type, Qns;
152 EmacsPrefsController *prefsController;
154 /* Defaults managed through the OpenStep defaults system. These pertain to
155 the NS interface specifically. Although a customization group could be
156 created, it's more natural to manage them via defaults. */
158 /* Specifies which emacs modifier should be generated when NS receives
159 the Alternate modifer. May be Qnone or any of the modifier lisp symbols. */
160 Lisp_Object ns_alternate_modifier;
162 /* Specifies which emacs modifier should be generated when NS receives
163 the Command modifer. May be any of the modifier lisp symbols. */
164 Lisp_Object ns_command_modifier;
166 /* Specifies which emacs modifier should be generated when NS receives
167 the Control modifer. May be any of the modifier lisp symbols. */
168 Lisp_Object ns_control_modifier;
170 /* Specifies which emacs modifier should be generated when NS receives
171 the Function modifer (laptops). May be any of the modifier lisp symbols. */
172 Lisp_Object ns_function_modifier;
174 /* A floating point value specifying vertical stretch (positive) or shrink
175 (negative) of text line spacing. Zero means default spacing.
176 YES indicates 0.5, NO indicates 0.0. */
177 Lisp_Object ns_expand_space;
179 /* Control via default 'GSFontAntiAlias' on OS X and GNUstep. */
180 Lisp_Object ns_antialias_text;
182 /* On OS X picks up the default NSGlobalDomain AppleAntiAliasingThreshold,
183 the maximum font size to NOT antialias. On GNUstep there is currently
184 no way to control this behavior. */
185 float ns_antialias_threshold;
187 /* Controls use of an undocumented CG function to do Quickdraw-style font
188 smoothing (less heavy) instead of regular Quartz smoothing. */
189 Lisp_Object ns_use_qd_smoothing;
191 /* Used to pick up AppleHighlightColor on OS X */
192 Lisp_Object ns_use_system_highlight_color;
193 NSString *ns_selection_color;
196 NSArray *ns_send_types =0, *ns_return_types =0, *ns_drag_types =0;
198 /* Display variables */
199 struct ns_display_info *x_display_list; /* Chain of existing displays */
200 Lisp_Object ns_display_name_list;
201 long context_menu_value = 0;
204 NSPoint last_mouse_motion_position;
205 static NSRect last_mouse_glyph;
206 static unsigned long last_mouse_movement_time = 0;
207 static Lisp_Object last_mouse_motion_frame;
208 static EmacsScroller *last_mouse_scroll_bar = nil;
209 static struct frame *ns_updating_frame;
210 static NSView *focus_view = NULL;
211 static int ns_window_num =0;
213 static BOOL gsaved = NO;
214 BOOL ns_in_resize = NO;
215 int ns_tmp_flags; /* FIXME */
216 struct nsfont_info *ns_tmp_font; /* FIXME */
217 /*static int debug_lock = 0; */
220 /* This undocumented Quartz function controls how fonts are anti-aliased.
221 (Found from code in Mac wxWindows impl, discovered by running `nm' on
223 Mode 0 is normal anti-aliasing, mode 1 is no anti-aliasing, and mode 2 is
224 4-bit pixel-aligned anti-aliasing (the old QuickDraw standard). */
225 extern void CGContextSetFontRenderingMode (CGContextRef cg, int v);
230 static BOOL send_appdefined = YES;
231 static NSEvent *last_appdefined_event = 0;
232 static NSTimer *timed_entry = 0;
233 static NSTimer *fd_entry = nil;
234 static NSTimer *scroll_repeat_entry = nil;
235 static fd_set select_readfds, t_readfds;
236 static struct timeval select_timeout;
237 static int select_nfds;
238 static NSAutoreleasePool *outerpool;
239 static BOOL ns_shutdown_properly = NO;
240 static struct input_event *emacs_event = NULL;
241 static struct input_event *q_event_ptr = NULL;
242 static int n_emacs_events_pending = 0;
243 static NSMutableArray *ns_pending_files, *ns_pending_service_names,
244 *ns_pending_service_args;
245 static BOOL inNsSelect = 0;
247 /* Convert modifiers in a NeXTSTEP event to emacs style modifiers. */
248 #define NS_FUNCTION_KEY_MASK 0x800000
249 #define EV_MODIFIERS(e) \
250 ((([e modifierFlags] & NSHelpKeyMask) ? \
251 hyper_modifier : 0) \
252 | (([e modifierFlags] & NSAlternateKeyMask) ? \
253 parse_solitary_modifier (ns_alternate_modifier) : 0) \
254 | (([e modifierFlags] & NSShiftKeyMask) ? \
255 shift_modifier : 0) \
256 | (([e modifierFlags] & NSControlKeyMask) ? \
257 parse_solitary_modifier (ns_control_modifier) : 0) \
258 | (([e modifierFlags] & NS_FUNCTION_KEY_MASK) ? \
259 parse_solitary_modifier (ns_function_modifier) : 0) \
260 | (([e modifierFlags] & NSCommandKeyMask) ? \
261 parse_solitary_modifier (ns_command_modifier):0))
263 #define EV_UDMODIFIERS(e) \
264 ((([e type] == NSLeftMouseDown) ? down_modifier : 0) \
265 | (([e type] == NSRightMouseDown) ? down_modifier : 0) \
266 | (([e type] == NSOtherMouseDown) ? down_modifier : 0) \
267 | (([e type] == NSLeftMouseDragged) ? down_modifier : 0) \
268 | (([e type] == NSRightMouseDragged) ? down_modifier : 0) \
269 | (([e type] == NSOtherMouseDragged) ? down_modifier : 0) \
270 | (([e type] == NSLeftMouseUp) ? up_modifier : 0) \
271 | (([e type] == NSRightMouseUp) ? up_modifier : 0) \
272 | (([e type] == NSOtherMouseUp) ? up_modifier : 0))
274 #define EV_BUTTON(e) \
275 ((([e type] == NSLeftMouseDown) || ([e type] == NSLeftMouseUp)) ? 0 : \
276 (([e type] == NSRightMouseDown) || ([e type] == NSRightMouseUp)) ? 2 : \
277 [e buttonNumber] - 1)
279 /* Convert the time field to a timestamp in milliseconds. */
280 #ifdef NS_IMPL_GNUSTEP
281 /* Apple says timestamp is in seconds, but GNUstep seems to be returning msec */
282 #define EV_TIMESTAMP(e) ([e timestamp])
284 #define EV_TIMESTAMP(e) ([e timestamp] * 1000)
285 #endif /* not gnustep */
287 /* This is a piece of code which is common to all the event handling
288 methods. Maybe it should even be a function. */
289 #define EV_TRAILER(e) \
291 XSETFRAME (emacs_event->frame_or_window, [NSApp isActive] ? \
292 emacsframe : SELECTED_FRAME ()); \
293 if (e) emacs_event->timestamp = EV_TIMESTAMP (e); \
294 n_emacs_events_pending++; \
295 kbd_buffer_store_event_hold (emacs_event, q_event_ptr); \
296 EVENT_INIT (*emacs_event); \
297 ns_send_appdefined (-1); \
300 /* TODO: get rid of need for these forward declarations */
301 static void ns_condemn_scroll_bars (struct frame *f),
302 ns_judge_scroll_bars (struct frame *f);
304 /* unused variables needed for compatibility reasons */
305 int x_use_underline_position_properties, x_underline_at_descent_line;
306 /* FIXME: figure out what to do with underline_minimum_offset. */
309 /* ==========================================================================
313 ========================================================================== */
317 append2 (Lisp_Object list, Lisp_Object item)
318 /* --------------------------------------------------------------------------
319 Utility to append to a list
320 -------------------------------------------------------------------------- */
322 Lisp_Object array[2];
324 array[1] = Fcons (item, Qnil);
325 return Fnconc (2, &array[0]);
331 /* --------------------------------------------------------------------------
332 Used to allow emacs to find its resources under Emacs.app
333 Called from emacs.c at startup.
334 -------------------------------------------------------------------------- */
336 NSBundle *bundle = [NSBundle mainBundle];
337 NSString *binDir = [bundle bundlePath], *resourceDir = [bundle resourcePath];
338 NSString *resourcePath, *resourcePaths;
340 BOOL onWindows = NO; /* how do I determine this? */
341 NSString *pathSeparator = onWindows ? @";" : @":";
342 NSFileManager *fileManager = [NSFileManager defaultManager];
344 /*NSLog (@"ns_init_paths: '%@'\n%@\n", [[NSBundle mainBundle] bundlePath], [[NSBundle mainBundle] resourcePath]); */
346 /* get bindir from base */
347 range = [resourceDir rangeOfString: @"Contents"];
348 if (range.location != NSNotFound)
350 binDir = [binDir stringByAppendingPathComponent: @"Contents"];
352 binDir = [binDir stringByAppendingPathComponent: @"MacOS"];
356 /* the following based on Andrew Choi's init_mac_osx_environment () */
357 if (!getenv ("EMACSLOADPATH"))
359 NSArray *paths = [resourceDir stringsByAppendingPaths:
360 [NSArray arrayWithObjects:
361 @"site-lisp", @"lisp", @"leim", nil]];
362 NSEnumerator *pathEnum = [paths objectEnumerator];
364 while (resourcePath = [pathEnum nextObject])
366 if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir])
369 if ([resourcePaths length] > 0)
371 = [resourcePaths stringByAppendingString: pathSeparator];
373 = [resourcePaths stringByAppendingString: resourcePath];
376 if ([resourcePaths length] > 0)
377 setenv ("EMACSLOADPATH", [resourcePaths UTF8String], 1);
378 /*NSLog (@"loadPath: '%s'\n", resourcePaths); */
381 if (!getenv ("EMACSPATH"))
383 NSArray *paths = [binDir stringsByAppendingPaths:
384 [NSArray arrayWithObjects: @"bin",
386 NSEnumerator *pathEnum = [paths objectEnumerator];
388 while (resourcePath = [pathEnum nextObject])
390 if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir])
393 if ([resourcePaths length] > 0)
395 = [resourcePaths stringByAppendingString: pathSeparator];
397 = [resourcePaths stringByAppendingString: resourcePath];
400 if ([resourcePaths length] > 0)
401 setenv ("EMACSPATH", [resourcePaths UTF8String], 1);
404 resourcePath = [resourceDir stringByAppendingPathComponent: @"etc"];
405 if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir])
409 if (!getenv ("EMACSDATA"))
410 setenv ("EMACSDATA", [resourcePath UTF8String], 1);
411 if (!getenv ("EMACSDOC"))
412 setenv ("EMACSDOC", [resourcePath UTF8String], 1);
416 if (!getenv ("INFOPATH"))
418 resourcePath = [resourceDir stringByAppendingPathComponent: @"info"];
419 if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir])
421 setenv ("INFOPATH", [resourcePath UTF8String], 1);
427 timeval_subtract (struct timeval *result, struct timeval x, struct timeval y)
428 /* --------------------------------------------------------------------------
429 Subtract the `struct timeval' values X and Y, storing the result in RESULT.
430 Return 1 if the difference is negative, otherwise 0.
431 -------------------------------------------------------------------------- */
433 /* Perform the carry for the later subtraction by updating y.
434 This is safer because on some systems
435 the tv_sec member is unsigned. */
436 if (x.tv_usec < y.tv_usec)
438 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
439 y.tv_usec -= 1000000 * nsec;
442 if (x.tv_usec - y.tv_usec > 1000000)
444 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
445 y.tv_usec += 1000000 * nsec;
449 /* Compute the time remaining to wait. tv_usec is certainly positive. */
450 result->tv_sec = x.tv_sec - y.tv_sec;
451 result->tv_usec = x.tv_usec - y.tv_usec;
453 /* Return indication of whether the result should be considered negative. */
454 return x.tv_sec < y.tv_sec;
458 ns_timeout (int usecs)
459 /* --------------------------------------------------------------------------
460 Blocking timer utility used by ns_ring_bell
461 -------------------------------------------------------------------------- */
463 struct timeval wakeup;
465 EMACS_GET_TIME (wakeup);
467 /* Compute time to wait until, propagating carry from usecs. */
468 wakeup.tv_usec += usecs;
469 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
470 wakeup.tv_usec %= 1000000;
472 /* Keep waiting until past the time wakeup. */
475 struct timeval timeout;
477 EMACS_GET_TIME (timeout);
479 /* In effect, timeout = wakeup - timeout.
480 Break if result would be negative. */
481 if (timeval_subtract (&timeout, wakeup, timeout))
484 /* Try to wait that long--but we might wake up sooner. */
485 select (0, NULL, NULL, NULL, &timeout);
491 ns_release_object (void *obj)
492 /* --------------------------------------------------------------------------
493 Release an object (callable from C)
494 -------------------------------------------------------------------------- */
501 ns_retain_object (void *obj)
502 /* --------------------------------------------------------------------------
503 Retain an object (callable from C)
504 -------------------------------------------------------------------------- */
511 ns_alloc_autorelease_pool ()
512 /* --------------------------------------------------------------------------
513 Allocate a pool for temporary objects (callable from C)
514 -------------------------------------------------------------------------- */
516 return [[NSAutoreleasePool alloc] init];
521 ns_release_autorelease_pool (void *pool)
522 /* --------------------------------------------------------------------------
523 Free a pool and temporary objects it refers to (callable from C)
524 -------------------------------------------------------------------------- */
526 ns_release_object (pool);
531 /* ==========================================================================
533 Focus (clipping) and screen update
535 ========================================================================== */
538 ns_resize_handle_rect (NSWindow *window)
540 NSRect r = [window frame];
541 r.origin.x = r.size.width - RESIZE_HANDLE_SIZE;
543 r.size.width = r.size.height = RESIZE_HANDLE_SIZE;
549 ns_update_begin (struct frame *f)
550 /* --------------------------------------------------------------------------
551 Prepare for a grouped sequence of drawing calls
552 23: external (RIF) call; now split w/ and called before update_window_begin
553 -------------------------------------------------------------------------- */
555 NSView *view = FRAME_NS_VIEW (f);
556 NSTRACE (ns_update_begin);
558 ns_updating_frame = f;
561 #ifdef NS_IMPL_GNUSTEP
562 uRect = NSMakeRect (0, 0, 0, 0);
568 ns_update_window_begin (struct window *w)
569 /* --------------------------------------------------------------------------
570 Prepare for a grouped sequence of drawing calls
571 23: external (RIF) call; now split with and called after update_begin
572 -------------------------------------------------------------------------- */
574 struct frame *f = XFRAME (WINDOW_FRAME (w));
575 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f);
576 NSTRACE (ns_update_window_begin);
579 set_output_cursor (&w->cursor);
583 if (f == dpyinfo->mouse_face_mouse_frame)
585 /* Don't do highlighting for mouse motion during the update. */
586 dpyinfo->mouse_face_defer = 1;
588 /* If the frame needs to be redrawn,
589 simply forget about any prior mouse highlighting. */
590 if (FRAME_GARBAGED_P (f))
591 dpyinfo->mouse_face_window = Qnil;
593 /* (further code for mouse faces ifdef'd out in other terms elided) */
601 ns_update_window_end (struct window *w, int cursor_on_p,
602 int mouse_face_overwritten_p)
603 /* --------------------------------------------------------------------------
604 Finished a grouped sequence of drawing calls
605 23: external (RIF) call; now split with and called before update_window_end
606 -------------------------------------------------------------------------- */
608 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (XFRAME (w->frame));
610 /* note: this fn is nearly identical in all terms */
611 if (!w->pseudo_window_p)
616 display_and_set_cursor (w, 1,
617 output_cursor.hpos, output_cursor.vpos,
618 output_cursor.x, output_cursor.y);
620 if (draw_window_fringes (w, 1))
621 x_draw_vertical_border (w);
626 /* If a row with mouse-face was overwritten, arrange for
627 frame_up_to_date to redisplay the mouse highlight. */
628 if (mouse_face_overwritten_p)
630 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
631 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
632 dpyinfo->mouse_face_window = Qnil;
635 updated_window = NULL;
636 NSTRACE (update_window_end);
641 ns_update_end (struct frame *f)
642 /* --------------------------------------------------------------------------
643 Finished a grouped sequence of drawing calls
644 23: external (RIF) call; now split with and called after update_window_end
645 -------------------------------------------------------------------------- */
647 NSView *view = FRAME_NS_VIEW (f);
649 /* if (f == FRAME_NS_DISPLAY_INFO (f)->mouse_face_mouse_frame) */
650 FRAME_NS_DISPLAY_INFO (f)->mouse_face_defer = 0;
654 #ifdef NS_IMPL_GNUSTEP
655 /* trigger flush only in the rectangle we tracked as being drawn */
656 [view unlockFocusNeedsFlush: NO];
657 /*fprintf (stderr, " (%.0f, %.0f : %.0f x %.0f)", uRect.origin.x, uRect.origin.y, uRect.size.width, uRect.size.height); */
658 [view lockFocusInRect: uRect];
662 [[view window] flushWindow];
665 ns_updating_frame = NULL;
666 NSTRACE (ns_update_end);
671 ns_flush (struct frame *f)
672 /* --------------------------------------------------------------------------
673 23: external (RIF) call
674 NS impl is no-op since currently we flush in ns_update_end and elsewhere
675 -------------------------------------------------------------------------- */
682 ns_focus (struct frame *f, NSRect *r, int n)
683 /* --------------------------------------------------------------------------
684 Internal: Focus on given frame. During small local updates this is used to
685 draw, however during large updates, ns_update_begin and ns_update_end are
686 called to wrap the whole thing, in which case these calls are stubbed out.
687 Except, on GNUstep, we accumulate the rectangle being drawn into, because
688 the back end won't do this automatically, and will just end up flushing
690 -------------------------------------------------------------------------- */
692 // NSTRACE (ns_focus);
693 #ifdef NS_IMPL_GNUSTEP
696 u = NSUnionRect (r[0], r[1]);
701 fprintf (stderr, "focus: %d", c++);
702 if (r) fprintf (stderr, " (%.0f, %.0f : %.0f x %.0f)", r->origin.x, r->origin.y, r->size.width, r->size.height);
703 fprintf (stderr, "\n"); */
705 if (f != ns_updating_frame)
707 NSView *view = FRAME_NS_VIEW (f);
708 if (view != focus_view)
710 if (focus_view != NULL)
712 [focus_view unlockFocus];
713 [[focus_view window] flushWindow];
718 #ifdef NS_IMPL_GNUSTEP
719 r ? [view lockFocusInRect: u] : [view lockFocus];
724 /*if (view) debug_lock++; */
726 #ifdef NS_IMPL_GNUSTEP
729 /* more than one rect being drawn into */
732 [view unlockFocus]; /* add prev rect to redraw list */
733 [view lockFocusInRect: u]; /* focus for draw in new rect */
738 #ifdef NS_IMPL_GNUSTEP
741 /* in batch mode, but in GNUstep must still track rectangles explicitly */
742 uRect = (r ? NSUnionRect (uRect, u) : [FRAME_NS_VIEW (f) visibleRect]);
749 [[NSGraphicsContext currentContext] saveGraphicsState];
751 NSRectClipList (r, 2);
760 ns_unfocus (struct frame *f)
761 /* --------------------------------------------------------------------------
762 Internal: Remove focus on given frame
763 -------------------------------------------------------------------------- */
765 // NSTRACE (ns_unfocus);
769 [[NSGraphicsContext currentContext] restoreGraphicsState];
773 if (f != ns_updating_frame)
775 if (focus_view != NULL)
777 [focus_view unlockFocus];
778 [[focus_view window] flushWindow];
787 ns_clip_to_row (struct window *w, struct glyph_row *row, int area, BOOL gc)
788 /* --------------------------------------------------------------------------
789 23: Internal (but parallels other terms): Focus drawing on given row
790 -------------------------------------------------------------------------- */
792 struct frame *f = XFRAME (WINDOW_FRAME (w));
794 int window_x, window_y, window_width;
796 window_box (w, area, &window_x, &window_y, &window_width, 0);
798 clip_rect.origin.x = window_x - FRAME_INTERNAL_BORDER_WIDTH (f);
799 clip_rect.origin.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
800 clip_rect.origin.y = max (clip_rect.origin.y, window_y);
801 clip_rect.size.width = window_width + 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
802 clip_rect.size.height = row->visible_height;
804 /* allow a full-height row at the top when requested
805 (used to draw fringe all the way through internal border area) */
806 if (gc && clip_rect.origin.y < 5)
808 clip_rect.origin.y -= FRAME_INTERNAL_BORDER_WIDTH (f);
809 clip_rect.size.height += FRAME_INTERNAL_BORDER_WIDTH (f);
812 /* likewise at bottom */
814 FRAME_PIXEL_HEIGHT (f) - (clip_rect.origin.y + clip_rect.size.height) < 5)
815 clip_rect.size.height += FRAME_INTERNAL_BORDER_WIDTH (f);
817 ns_focus (f, &clip_rect, 1);
823 /* --------------------------------------------------------------------------
825 -------------------------------------------------------------------------- */
827 NSTRACE (ns_ring_bell);
830 NSAutoreleasePool *pool;
831 struct frame *frame = SELECTED_FRAME ();
835 pool = [[NSAutoreleasePool alloc] init];
837 view = FRAME_NS_VIEW (frame);
841 NSPoint dim = NSMakePoint (128, 128);
844 r.origin.x += (r.size.width - dim.x) / 2;
845 r.origin.y += (r.size.height - dim.y) / 2;
846 r.size.width = dim.x;
847 r.size.height = dim.y;
848 /* XXX: cacheImageInRect under GNUstep does not account for
849 offset in x_set_window_size, so overestimate (4 fine on Cocoa) */
850 surr = NSInsetRect (r, -10, -10);
851 ns_focus (frame, &surr, 1);
852 [[view window] cacheImageInRect: surr];
853 [ns_lookup_indexed_color (NS_FACE_FOREGROUND
854 (FRAME_DEFAULT_FACE (frame)), frame) set];
856 [[view window] flushWindow];
858 [[view window] restoreCachedImage];
859 [[view window] flushWindow];
873 ns_reset_terminal_modes (struct terminal *terminal)
874 /* Externally called as hook */
876 NSTRACE (ns_reset_terminal_modes);
880 ns_set_terminal_modes (struct terminal *terminal)
881 /* Externally called as hook */
883 NSTRACE (ns_set_terminal_modes);
888 /* ==========================================================================
890 Frame / window manager related functions
892 ========================================================================== */
896 ns_raise_frame (struct frame *f)
897 /* --------------------------------------------------------------------------
898 Bring window to foreground and make it active
899 -------------------------------------------------------------------------- */
901 NSView *view = FRAME_NS_VIEW (f);
904 [[view window] makeKeyAndOrderFront: NSApp];
910 ns_lower_frame (struct frame *f)
911 /* --------------------------------------------------------------------------
913 -------------------------------------------------------------------------- */
915 NSView *view = FRAME_NS_VIEW (f);
918 [[view window] orderBack: NSApp];
924 ns_frame_raise_lower (struct frame *f, int raise)
925 /* --------------------------------------------------------------------------
927 -------------------------------------------------------------------------- */
929 NSTRACE (ns_frame_raise_lower);
939 ns_frame_rehighlight (struct frame *frame)
940 /* --------------------------------------------------------------------------
941 External (hook): called on things like window switching within frame
942 -------------------------------------------------------------------------- */
944 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (frame);
945 struct frame *old_highlight = dpyinfo->x_highlight_frame;
947 NSTRACE (ns_frame_rehighlight);
948 if (dpyinfo->x_focus_frame)
950 dpyinfo->x_highlight_frame
951 = (FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
952 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame))
953 : dpyinfo->x_focus_frame);
954 if (!FRAME_LIVE_P (dpyinfo->x_highlight_frame))
956 FRAME_FOCUS_FRAME (dpyinfo->x_focus_frame) = Qnil;
957 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame;
961 dpyinfo->x_highlight_frame = 0;
963 if (dpyinfo->x_highlight_frame &&
964 dpyinfo->x_highlight_frame != old_highlight)
968 x_update_cursor (old_highlight, 1);
969 x_set_frame_alpha (old_highlight);
971 if (dpyinfo->x_highlight_frame)
973 x_update_cursor (dpyinfo->x_highlight_frame, 1);
974 x_set_frame_alpha (dpyinfo->x_highlight_frame);
981 x_make_frame_visible (struct frame *f)
982 /* --------------------------------------------------------------------------
983 External: Show the window (X11 semantics)
984 -------------------------------------------------------------------------- */
986 NSTRACE (x_make_frame_visible);
987 /* XXX: at some points in past this was not needed, as the only place that
988 called this (frame.c:Fraise_frame ()) also called raise_lower;
989 if this ends up the case again, comment this out again. */
990 if (!FRAME_VISIBLE_P (f))
996 x_make_frame_invisible (struct frame *f)
997 /* --------------------------------------------------------------------------
998 External: Hide the window (X11 semantics)
999 -------------------------------------------------------------------------- */
1001 NSView * view = FRAME_NS_VIEW (f);
1002 NSTRACE (x_make_frame_invisible);
1004 [[view window] orderOut: NSApp];
1009 x_iconify_frame (struct frame *f)
1010 /* --------------------------------------------------------------------------
1011 External: Iconify window
1012 -------------------------------------------------------------------------- */
1014 NSView * view = FRAME_NS_VIEW (f);
1015 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f);
1016 NSTRACE (x_iconify_frame);
1019 if (dpyinfo->x_highlight_frame == f)
1020 dpyinfo->x_highlight_frame = 0;
1022 if ([[view window] windowNumber] <= 0)
1024 /* the window is still deferred. Make it very small, bring it
1025 on screen and order it out. */
1026 NSRect s = { { 100, 100}, {0, 0} };
1028 t = [[view window] frame];
1029 [[view window] setFrame: s display: NO];
1030 [[view window] orderBack: NSApp];
1031 [[view window] orderOut: NSApp];
1032 [[view window] setFrame: t display: NO];
1034 [[view window] miniaturize: NSApp];
1039 x_destroy_window (struct frame *f)
1040 /* --------------------------------------------------------------------------
1041 External: Delete the window
1042 -------------------------------------------------------------------------- */
1044 NSView *view = FRAME_NS_VIEW (f);
1045 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f);
1046 NSTRACE (x_destroy_window);
1049 [(EmacsView *)view setWindowClosing: YES]; /* may not have been informed */
1053 free_frame_menubar (f);
1055 if (FRAME_FACE_CACHE (f))
1056 free_frame_faces (f);
1058 if (f == dpyinfo->x_focus_frame)
1059 dpyinfo->x_focus_frame = 0;
1060 if (f == dpyinfo->x_highlight_frame)
1061 dpyinfo->x_highlight_frame = 0;
1062 if (f == dpyinfo->mouse_face_mouse_frame)
1064 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1065 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1066 dpyinfo->mouse_face_window = Qnil;
1067 dpyinfo->mouse_face_deferred_gc = 0;
1068 dpyinfo->mouse_face_mouse_frame = 0;
1071 xfree (f->output_data.ns);
1073 [[view window] close];
1082 x_set_offset (struct frame *f, int xoff, int yoff, int change_grav)
1083 /* --------------------------------------------------------------------------
1084 External: Position the window
1085 -------------------------------------------------------------------------- */
1088 NSView *view = FRAME_NS_VIEW (f);
1090 NSTRACE (x_set_offset);
1096 #ifdef NS_IMPL_GNUSTEP
1098 f->left_pos = 100; /* don't overlap menu */
1100 if (view != nil && (screen = [[view window] screen]))
1101 [[view window] setFrameTopLeftPoint:
1102 NSMakePoint (SCREENMAXBOUND (f->left_pos),
1103 SCREENMAXBOUND ([screen frame].size.height
1104 - NS_TOP_POS (f)))];
1110 x_set_window_size (struct frame *f, int change_grav, int cols, int rows)
1111 /* --------------------------------------------------------------------------
1112 Adjust window pixel size based on given character grid size
1113 Impl is a bit more complex than other terms, need to do some
1114 internal clipping and also pay attention to screen constraints.
1115 -------------------------------------------------------------------------- */
1117 EmacsView *view = FRAME_NS_VIEW (f);
1118 EmacsToolbar *toolbar = [view toolbar];
1119 NSWindow *window = [view window];
1120 NSScreen *screen = [window screen];
1121 NSRect wr = [window frame];
1122 int tb = FRAME_EXTERNAL_TOOL_BAR (f);
1123 int pixelwidth, pixelheight;
1124 static int oldRows, oldCols, oldFontWidth, oldFontHeight;
1126 static struct frame *oldF;
1128 NSTRACE (x_set_window_size);
1132 && rows == oldRows && cols == oldCols
1133 && oldFontWidth == FRAME_COLUMN_WIDTH (f)
1134 && oldFontHeight == FRAME_LINE_HEIGHT (f)
1138 /*fprintf (stderr, "\tsetWindowSize: %d x %d, font size %d x %d\n", cols, rows, FRAME_COLUMN_WIDTH (f), FRAME_LINE_HEIGHT (f)); */
1142 check_frame_size (f, &rows, &cols);
1146 oldFontWidth = FRAME_COLUMN_WIDTH (f);
1147 oldFontHeight = FRAME_LINE_HEIGHT (f);
1150 f->scroll_bar_actual_width = NS_SCROLL_BAR_WIDTH (f);
1151 compute_fringe_widths (f, 0);
1153 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
1154 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
1156 /* If we have a change in toolbar display, calculate height */
1158 /* XXX: GNUstep has not yet implemented the first method below, added
1159 in Panther, however the second is incorrect under Cocoa. */
1160 #ifdef NS_IMPL_GNUSTEP
1161 FRAME_NS_TOOLBAR_HEIGHT (f)
1162 = NSHeight ([NSWindow frameRectForContentRect: NSMakeRect (0, 0, 0, 0)
1163 styleMask: [window styleMask]])
1164 - FRAME_NS_TITLEBAR_HEIGHT (f);
1166 FRAME_NS_TOOLBAR_HEIGHT (f) = 32;
1167 /* actually get wrong result here if toolbar not yet displayed
1168 NSHeight ([window frameRectForContentRect: NSMakeRect (0, 0, 0, 0)])
1169 - FRAME_NS_TITLEBAR_HEIGHT (f); */
1172 FRAME_NS_TOOLBAR_HEIGHT (f) = 0;
1174 wr.size.width = pixelwidth + f->border_width;
1175 wr.size.height = pixelheight + FRAME_NS_TITLEBAR_HEIGHT (f)
1176 + FRAME_NS_TOOLBAR_HEIGHT (f);
1178 /* constrain to screen if we can */
1181 NSSize sz = [screen visibleFrame].size;
1182 NSSize ez = { wr.size.width - sz.width, wr.size.height - sz.height };
1185 int cr = ez.width / FRAME_COLUMN_WIDTH (f) + 1;
1188 wr.size.width -= cr * FRAME_COLUMN_WIDTH (f);
1189 pixelwidth -= cr * FRAME_COLUMN_WIDTH (f);
1193 int rr = ez.height / FRAME_LINE_HEIGHT (f) + 1;
1196 wr.size.height -= rr * FRAME_LINE_HEIGHT (f);
1197 pixelheight -= rr * FRAME_LINE_HEIGHT (f);
1199 wr.origin.x = f->left_pos;
1200 wr.origin.y = [screen frame].size.height - NS_TOP_POS (f)
1204 [view setRows: rows andColumns: cols];
1205 [window setFrame: wr display: YES];
1207 /*fprintf (stderr, "\tx_set_window_size %d, %d\t%d, %d\n", cols, rows, pixelwidth, pixelheight); */
1209 /* This is a trick to compensate for Emacs' managing the scrollbar area
1210 as a fixed number of standard character columns. Instead of leaving
1211 blank space for the extra, we chopped it off above. Now for
1212 left-hand scrollbars, we shift all rendering to the left by the
1213 difference between the real width and Emacs' imagined one. For
1214 right-hand bars, don't worry about it since the extra is never used.
1215 (Obviously doesn't work for vertically split windows tho..) */
1216 NSPoint origin = FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)
1217 ? NSMakePoint (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f)
1218 - NS_SCROLL_BAR_WIDTH (f), 0)
1219 : NSMakePoint (0, 0);
1220 [view setFrame: NSMakeRect (0, 0, pixelwidth, pixelheight)];
1221 [view setBoundsOrigin: origin];
1223 change_frame_size (f, rows, cols, 0, 1, 0); /* pretend, delay, safe */
1224 FRAME_PIXEL_WIDTH (f) = pixelwidth;
1225 FRAME_PIXEL_HEIGHT (f) = pixelheight;
1226 /* SET_FRAME_GARBAGED (f); // this short-circuits expose call in drawRect */
1228 mark_window_cursors_off (XWINDOW (f->root_window));
1229 cancel_mouse_face (f);
1236 /* ==========================================================================
1240 ========================================================================== */
1244 ns_lookup_indexed_color (unsigned long idx, struct frame *f)
1246 struct ns_color_table *color_table = FRAME_NS_DISPLAY_INFO (f)->color_table;
1247 return color_table->colors[idx];
1252 ns_index_color (NSColor *color, struct frame *f)
1254 struct ns_color_table *color_table = FRAME_NS_DISPLAY_INFO (f)->color_table;
1258 if (!color_table->colors)
1260 color_table->size = NS_COLOR_CAPACITY;
1261 color_table->avail = 1; /* skip idx=0 as marker */
1263 = (NSColor **)xmalloc (color_table->size * sizeof (NSColor *));
1264 color_table->empty_indices = [[NSMutableSet alloc] init];
1267 /* do we already have this color ? */
1270 for (i = 1; i < color_table->avail; i++)
1272 if (color_table->colors[i] && [color_table->colors[i] isEqual: color])
1274 [color_table->colors[i] retain];
1280 if ([color_table->empty_indices count] > 0)
1282 index = [color_table->empty_indices anyObject];
1283 [color_table->empty_indices removeObject: index];
1284 idx = [index unsignedIntValue];
1288 if (color_table->avail == color_table->size)
1290 color_table->size += NS_COLOR_CAPACITY;
1292 = (NSColor **)xrealloc (color_table->colors,
1293 color_table->size * sizeof (NSColor *));
1295 idx = color_table->avail++;
1298 color_table->colors[idx] = color;
1300 /*fprintf(stderr, "color_table: allocated %d\n",idx);*/
1306 ns_free_indexed_color (unsigned long idx, struct frame *f)
1308 struct ns_color_table *color_table;
1315 color_table = FRAME_NS_DISPLAY_INFO (f)->color_table;
1317 if (idx <= 0 || idx >= color_table->size) {
1318 message1("ns_free_indexed_color: Color index out of range.\n");
1322 index = [NSNumber numberWithUnsignedInt: idx];
1323 if ([color_table->empty_indices containsObject: index]) {
1324 message1("ns_free_indexed_color: attempt to free already freed color.\n");
1328 color = color_table->colors[idx];
1330 color_table->colors[idx] = nil;
1331 [color_table->empty_indices addObject: [NSNumber numberWithUnsignedInt: idx]];
1332 /*fprintf(stderr, "color_table: FREED %d\n",idx);*/
1337 ns_get_color (const char *name, NSColor **col)
1338 /* --------------------------------------------------------------------------
1340 /* --------------------------------------------------------------------------
1341 /* On *Step, we recognize several color formats, in addition to a catalog
1342 of colors found in the file Emacs.clr. Color formats include:
1343 - #rrggbb or RGBrrggbb where rr, gg, bb specify red, green and blue in hex
1344 - ARGBaarrggbb is similar, with aa being the alpha channel (FF = opaque)
1345 - HSVhhssvv and AHSVaahhssvv (or HSB/AHSB) are similar for hue, saturation,
1347 - CMYKccmmyykk is similar for cyan, magenta, yellow, black. */
1349 NSColor * new = nil;
1350 const char *hex = NULL;
1351 enum { rgb, argb, hsv, ahsv, cmyk, gray } color_space;
1352 NSString *nsname = [NSString stringWithUTF8String: name];
1354 /*fprintf (stderr, "ns_get_color: '%s'\n", name); */
1357 if ([nsname isEqualToString: @"ns_selection_color"])
1359 nsname = ns_selection_color;
1360 name = [ns_selection_color UTF8String];
1363 if (name[0] == '0' || name[0] == '1' || name[0] == '.')
1366 NSScanner *scanner = [NSScanner scannerWithString: nsname];
1368 [scanner scanFloat: &r];
1369 [scanner scanFloat: &g];
1370 [scanner scanFloat: &b];
1371 *col = [NSColor colorWithCalibratedRed: r green: g blue: b alpha: 1.0];
1376 /* 23: FIXME: emacs seems to downcase everything before passing it here,
1377 which we can work around, except for GRAY, since gray##, where ## is
1378 decimal between 0 and 99, is also an X11 colorname. */
1379 if (name[0] == '#') /* X11 format */
1384 else if (!memcmp (name, "RGB", 3) || !memcmp (name, "rgb", 3))
1389 else if (!memcmp (name, "ARGB", 4) || !memcmp (name, "argb", 4))
1394 else if (!memcmp (name, "HSV", 3) || !memcmp (name, "hsv", 3) ||
1395 !memcmp (name, "HSB", 3) || !memcmp (name, "hsb", 3))
1400 else if (!memcmp (name, "AHSV", 4) || !memcmp (name, "ahsv", 4) ||
1401 !memcmp (name, "AHSB", 4) || !memcmp (name, "ahsb", 4))
1406 else if (!memcmp (name, "CMYK", 4) || !memcmp (name, "cmyk", 4))
1411 else if (!memcmp (name, "GRAY", 4) /*|| !memcmp (name, "gray", 4)*/)
1417 /* Direct colors (hex values) */
1420 unsigned long color = 0;
1421 if (sscanf (hex, "%x", &color))
1423 float f1, f2, f3, f4;
1424 /* Assume it's either 1 byte or 2 per channel... */
1425 if (strlen(hex) > 8) {
1426 f1 = ((color >> 48) & 0xffff) / 65535.0;
1427 f2 = ((color >> 32) & 0xffff) / 65535.0;
1428 f3 = ((color >> 16) & 0xffff) / 65535.0;
1429 f4 = ((color ) & 0xffff) / 65535.0;
1431 f1 = ((color >> 24) & 0xff) / 255.0;
1432 f2 = ((color >> 16) & 0xff) / 255.0;
1433 f3 = ((color >> 8) & 0xff) / 255.0;
1434 f4 = ((color ) & 0xff) / 255.0;
1437 switch (color_space)
1440 *col = [NSColor colorWithCalibratedRed: f2
1446 *col = [NSColor colorWithCalibratedRed: f2
1452 *col = [NSColor colorWithCalibratedHue: f2
1458 *col = [NSColor colorWithCalibratedHue: f2
1464 *col = [NSColor colorWithCalibratedWhite: f3 alpha: f4];
1467 *col = [NSColor colorWithDeviceCyan: f1
1474 *col = [*col colorUsingColorSpaceName: NSCalibratedRGBColorSpace];
1480 /* Otherwise, color is expected to be from a list */
1482 NSEnumerator *lenum, *cenum;
1486 #ifdef NS_IMPL_GNUSTEP
1487 /* XXX: who is wrong, the requestor or the implementation? */
1488 if ([nsname compare: @"Highlight" options: NSCaseInsensitiveSearch]
1490 nsname = @"highlightColor";
1493 lenum = [[NSColorList availableColorLists] objectEnumerator];
1494 while ( (clist = [lenum nextObject]) && new == nil)
1496 cenum = [[clist allKeys] objectEnumerator];
1497 while ( (name = [cenum nextObject]) && new == nil )
1499 if ([name compare: nsname
1500 options: NSCaseInsensitiveSearch] == NSOrderedSame )
1501 new = [clist colorWithKey: name];
1507 *col = [new colorUsingColorSpaceName: NSCalibratedRGBColorSpace];
1509 NSLog (@"Failed to find color '%@'", nsname); */
1516 ns_get_color_default (const char *name, NSColor *dflt)
1517 /* --------------------------------------------------------------------------
1518 Parse a color or use a default value
1519 -------------------------------------------------------------------------- */
1523 if (ns_get_color (name, &col))
1531 ns_lisp_to_color (Lisp_Object color, NSColor **col)
1532 /* --------------------------------------------------------------------------
1533 Convert a Lisp string object to a NS color
1534 -------------------------------------------------------------------------- */
1536 NSTRACE (ns_lisp_to_color);
1537 if (STRINGP (color))
1538 return ns_get_color (SDATA (color), col);
1539 else if (SYMBOLP (color))
1540 return ns_get_color (SDATA (SYMBOL_NAME (color)), col);
1546 ns_color_to_lisp (NSColor *col)
1547 /* --------------------------------------------------------------------------
1548 Convert a color to a lisp string with the RGB equivalent
1549 -------------------------------------------------------------------------- */
1551 float red, green, blue, alpha, gray;
1554 NSTRACE (ns_color_to_lisp);
1557 if ([[col colorSpaceName] isEqualToString: NSNamedColorSpace])
1559 if ((str =[[col colorNameComponent] UTF8String]))
1562 return build_string ((char *)str);
1565 [[col colorUsingColorSpaceName: NSCalibratedRGBColorSpace]
1566 getRed: &red green: &green blue: &blue alpha: &alpha];
1567 if (red ==green && red ==blue)
1569 [[col colorUsingColorSpaceName: NSCalibratedWhiteColorSpace]
1570 getWhite: &gray alpha: &alpha];
1571 snprintf (buf, sizeof (buf), "GRAY%02.2lx%02.2lx",
1572 lrint (gray * 0xff), lrint (alpha * 0xff));
1574 return build_string (buf);
1577 snprintf (buf, sizeof (buf), "ARGB%02.2lx%02.2lx%02.2lx%02.2lx",
1579 lrint (red*0xff), lrint (green*0xff), lrint (blue*0xff));
1582 return build_string (buf);
1587 ns_defined_color (struct frame *f, char *name, XColor *color_def, int alloc,
1589 /* --------------------------------------------------------------------------
1590 23: Return 1 if named color found, and set color_def rgb accordingly.
1591 If makeIndex and alloc are nonzero put the color in the color_table,
1592 and set color_def pixel to the resulting index.
1593 If makeIndex is zero, set color_def pixel to ARGB.
1594 Return 0 if not found
1595 -------------------------------------------------------------------------- */
1599 int notFound = ns_get_color (name, &temp);
1601 NSTRACE (ns_defined_color);
1606 if (makeIndex && alloc)
1607 color_def->pixel = ns_index_color(temp, f); /* [temp retain]; */
1609 [temp getRed: &r green: &g blue: &b alpha: &a];
1610 color_def->red = r * 256;
1611 color_def->green = g * 256;
1612 color_def->blue = b * 256;
1616 = ARGB_TO_ULONG((int)(a*256),
1617 color_def->red, color_def->green, color_def->blue);
1624 ns_get_rgb_color (struct frame *f, float r, float g, float b, float a)
1625 /* --------------------------------------------------------------------------
1626 return an autoreleased RGB color
1627 -------------------------------------------------------------------------- */
1629 /*static int c = 1; fprintf (stderr, "color request %d\n", c++); */
1630 if (r < 0.0) r = 0.0;
1631 else if (r > 1.0) r = 1.0;
1632 if (g < 0.0) g = 0.0;
1633 else if (g > 1.0) g = 1.0;
1634 if (b < 0.0) b = 0.0;
1635 else if (b > 1.0) b = 1.0;
1636 if (a < 0.0) a = 0.0;
1637 else if (a > 1.0) a = 1.0;
1638 return (unsigned long) ns_index_color(
1639 [NSColor colorWithCalibratedRed: r green: g blue: b alpha: a], f);
1644 x_set_frame_alpha (struct frame *f)
1645 /* --------------------------------------------------------------------------
1646 change the entire-frame transparency
1647 -------------------------------------------------------------------------- */
1649 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f);
1650 EmacsView *view = FRAME_NS_VIEW (f);
1652 double alpha_min = 1.0;
1654 if (dpyinfo->x_highlight_frame == f)
1655 alpha = f->alpha[0];
1657 alpha = f->alpha[1];
1659 if (FLOATP (Vframe_alpha_lower_limit))
1660 alpha_min = XFLOAT_DATA (Vframe_alpha_lower_limit);
1661 else if (INTEGERP (Vframe_alpha_lower_limit))
1662 alpha_min = (XINT (Vframe_alpha_lower_limit)) / 100.0;
1666 else if (1.0 < alpha)
1668 else if (0.0 <= alpha && alpha < alpha_min && alpha_min <= 1.0)
1671 #ifdef NS_IMPL_COCOA
1672 [[view window] setAlphaValue: alpha];
1677 /* ==========================================================================
1681 ========================================================================== */
1685 x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
1686 /* --------------------------------------------------------------------------
1687 Programmatically reposition mouse pointer in pixel coordinates
1688 -------------------------------------------------------------------------- */
1690 NSTRACE (x_set_mouse_pixel_position);
1693 /* FIXME: this does not work, and what about GNUstep? */
1694 #ifdef NS_IMPL_COCOA
1695 [FRAME_NS_VIEW (f) lockFocus];
1696 PSsetmouse ((float)pix_x, (float)pix_y);
1697 [FRAME_NS_VIEW (f) unlockFocus];
1704 x_set_mouse_position (struct frame *f, int h, int v)
1705 /* --------------------------------------------------------------------------
1706 Programmatically reposition mouse pointer in character coordinates
1707 -------------------------------------------------------------------------- */
1711 pix_x = FRAME_COL_TO_PIXEL_X (f, h) + FRAME_COLUMN_WIDTH (f) / 2;
1712 pix_y = FRAME_LINE_TO_PIXEL_Y (f, v) + FRAME_LINE_HEIGHT (f) / 2;
1714 if (pix_x < 0) pix_x = 0;
1715 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
1717 if (pix_y < 0) pix_y = 0;
1718 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
1720 x_set_mouse_pixel_position (f, pix_x, pix_y);
1725 note_mouse_movement (struct frame *frame, float x, float y)
1726 /* ------------------------------------------------------------------------
1727 Called by EmacsView on mouseMovement events. Passes on
1728 to emacs mainstream code if we moved off of a rect of interest
1729 known as last_mouse_glyph.
1730 ------------------------------------------------------------------------ */
1732 // NSTRACE (note_mouse_movement);
1734 XSETFRAME (last_mouse_motion_frame, frame);
1736 /* Note, this doesn't get called for enter/leave, since we don't have a
1737 position. Those are taken care of in the corresponding NSView methods. */
1739 /* has movement gone beyond last rect we were tracking? */
1740 if (x < last_mouse_glyph.origin.x ||
1741 x >= (last_mouse_glyph.origin.x + last_mouse_glyph.size.width) ||
1742 y < last_mouse_glyph.origin.y ||
1743 y >= (last_mouse_glyph.origin.y + last_mouse_glyph.size.height))
1745 frame->mouse_moved = 1;
1746 note_mouse_highlight (frame, x, y);
1747 remember_mouse_glyph (frame, x, y, &last_mouse_glyph);
1756 ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
1757 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
1758 unsigned long *time)
1759 /* --------------------------------------------------------------------------
1760 External (hook): inform emacs about mouse position and hit parts.
1761 If a scrollbar is being dragged, set bar_window, part, x, y, time.
1762 x & y should be position in the scrollbar (the whole bar, not the handle)
1763 and length of scrollbar respectively
1764 -------------------------------------------------------------------------- */
1769 Lisp_Object frame, tail;
1771 struct ns_display_info *dpyinfo;
1773 NSTRACE (ns_mouse_position);
1777 fprintf (stderr, "Warning: ns_mouse_position () called with null *fp.\n");
1781 dpyinfo = FRAME_NS_DISPLAY_INFO (*fp);
1785 if (last_mouse_scroll_bar != nil && insist == 0)
1787 /* TODO: we do not use this path at the moment because drag events will
1788 go directly to the EmacsScroller. Leaving code in for now. */
1789 [last_mouse_scroll_bar getMouseMotionPart: (int *)part window: bar_window
1791 if (time) *time = last_mouse_movement_time;
1792 last_mouse_scroll_bar = nil;
1796 /* Clear the mouse-moved flag for every frame on this display. */
1797 FOR_EACH_FRAME (tail, frame)
1798 if (FRAME_NS_P (XFRAME (frame))
1799 && FRAME_NS_DISPLAY (XFRAME (frame)) == FRAME_NS_DISPLAY (*fp))
1800 XFRAME (frame)->mouse_moved = 0;
1802 last_mouse_scroll_bar = nil;
1803 if (last_mouse_frame && FRAME_LIVE_P (last_mouse_frame))
1804 f = last_mouse_frame;
1806 f = dpyinfo->x_focus_frame ? dpyinfo->x_focus_frame
1807 : SELECTED_FRAME ();
1809 if (f && f->output_data.ns) /* TODO: 2nd check no longer needed? */
1811 view = FRAME_NS_VIEW (*fp);
1813 position = [[view window] mouseLocationOutsideOfEventStream];
1814 position = [view convertPoint: position fromView: nil];
1815 remember_mouse_glyph (f, position.x, position.y, &last_mouse_glyph);
1816 /*fprintf (stderr, "ns_mouse_position: %.0f, %.0f\n", position.x, position.y); */
1818 if (bar_window) *bar_window = Qnil;
1819 if (part) *part = 0; /*scroll_bar_handle; */
1821 if (x) XSETINT (*x, lrint (position.x));
1822 if (y) XSETINT (*y, lrint (position.y));
1823 if (time) *time = last_mouse_movement_time;
1833 ns_frame_up_to_date (struct frame *f)
1834 /* --------------------------------------------------------------------------
1835 External (hook): Fix up mouse highlighting right after a full update.
1836 Some highlighting was deferred if GC was happening during
1837 note_mouse_highlight (), while other highlighting was deferred for update.
1838 -------------------------------------------------------------------------- */
1840 NSTRACE (ns_frame_up_to_date);
1844 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f);
1845 if ((dpyinfo->mouse_face_deferred_gc||f ==dpyinfo->mouse_face_mouse_frame)
1846 /*&& dpyinfo->mouse_face_mouse_frame*/)
1849 if (dpyinfo->mouse_face_mouse_frame)
1850 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1851 dpyinfo->mouse_face_mouse_x,
1852 dpyinfo->mouse_face_mouse_y);
1853 dpyinfo->mouse_face_deferred_gc = 0;
1861 ns_define_frame_cursor (struct frame *f, Cursor cursor)
1862 /* --------------------------------------------------------------------------
1863 External (RIF): set frame mouse pointer type.
1864 -------------------------------------------------------------------------- */
1866 NSTRACE (ns_define_frame_cursor);
1867 if (FRAME_POINTER_TYPE (f) != cursor)
1869 EmacsView *view = FRAME_NS_VIEW (f);
1870 FRAME_POINTER_TYPE (f) = cursor;
1871 [[view window] invalidateCursorRectsForView: view];
1877 /* ==========================================================================
1881 ========================================================================== */
1885 ns_convert_key (unsigned code)
1886 /* --------------------------------------------------------------------------
1887 Internal call used by NSView-keyDown.
1888 -------------------------------------------------------------------------- */
1890 const unsigned last_keysym = (sizeof (convert_ns_to_X_keysym)
1891 / sizeof (convert_ns_to_X_keysym[0]));
1893 /* An array would be faster, but less easy to read. */
1894 for (keysym = 0; keysym < last_keysym; keysym += 2)
1895 if (code == convert_ns_to_X_keysym[keysym])
1896 return 0xFF00 | convert_ns_to_X_keysym[keysym+1];
1898 /* if decide to use keyCode and Carbon table, use this line:
1899 return code > 0xff ? 0 : 0xFF00 | ns_keycode_to_xkeysym_table[code]; */
1904 x_get_keysym_name (int keysym)
1905 /* --------------------------------------------------------------------------
1906 Called by keyboard.c. Not sure if the return val is important, except
1908 -------------------------------------------------------------------------- */
1910 static char value[16];
1911 NSTRACE (x_get_keysym_name);
1912 sprintf (value, "%d", keysym);
1918 /* ==========================================================================
1920 Block drawing operations
1922 ========================================================================== */
1926 ns_redraw_scroll_bars (struct frame *f)
1930 NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews];
1931 NSTRACE (ns_judge_scroll_bars);
1932 for (i =[subviews count]-1; i >= 0; i--)
1934 view = [subviews objectAtIndex: i];
1935 if (![view isKindOfClass: [EmacsScroller class]]) continue;
1942 ns_clear_frame (struct frame *f)
1943 /* --------------------------------------------------------------------------
1944 External (hook): Erase the entire frame
1945 -------------------------------------------------------------------------- */
1947 NSView *view = FRAME_NS_VIEW (f);
1950 NSTRACE (ns_clear_frame);
1954 /* comes on initial frame because we have
1955 after-make-frame-functions = select-frame */
1956 if (!FRAME_DEFAULT_FACE (f))
1959 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
1961 output_cursor.hpos = output_cursor.vpos = 0;
1962 output_cursor.x = -1;
1967 ns_focus (f, &r, 1);
1968 [ns_lookup_indexed_color (NS_FACE_BACKGROUND (FRAME_DEFAULT_FACE (f)), f) set];
1972 #ifdef NS_IMPL_COCOA
1973 [[view window] display]; /* redraw resize handle */
1976 /* as of 2006/11 or so this is now needed */
1977 ns_redraw_scroll_bars (f);
1983 ns_clear_frame_area (struct frame *f, int x, int y, int width, int height)
1984 /* --------------------------------------------------------------------------
1985 23: External (RIF): Clear section of frame
1986 -------------------------------------------------------------------------- */
1988 NSRect r = NSMakeRect (x, y, width, height);
1989 NSView *view = FRAME_NS_VIEW (f);
1990 struct face *face = FRAME_DEFAULT_FACE (f);
1995 NSTRACE (ns_clear_frame_area);
1997 r = NSIntersectionRect (r, [view frame]);
1998 ns_focus (f, &r, 1);
1999 [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set];
2001 #ifdef NS_IMPL_COCOA
2003 /* clip out the resize handle */
2004 NSWindow *window = [FRAME_NS_VIEW (f) window];
2006 = [view convertRect: ns_resize_handle_rect (window) fromView: nil];
2008 ir = NSIntersectionRect (r, ir);
2009 if (NSIsEmptyRect (ir))
2015 #ifdef NS_IMPL_COCOA
2019 NSRect r1 = r, r2 = r; /* upper and lower non-intersecting */
2020 r1.size.height -= ir.size.height;
2021 r2.origin.y += r1.size.height;
2022 r2.size.width -= ir.size.width;
2023 r2.size.height = ir.size.height;
2036 ns_scroll_run (struct window *w, struct run *run)
2037 /* --------------------------------------------------------------------------
2038 23: External (RIF): Insert or delete n lines at line vpos
2039 -------------------------------------------------------------------------- */
2041 struct frame *f = XFRAME (w->frame);
2042 int x, y, width, height, from_y, to_y, bottom_y;
2044 NSTRACE (ns_scroll_run);
2046 /* begin copy from other terms */
2047 /* Get frame-relative bounding box of the text display area of W,
2048 without mode lines. Include in this box the left and right
2050 window_box (w, -1, &x, &y, &width, &height);
2052 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
2053 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
2054 bottom_y = y + height;
2058 /* Scrolling up. Make sure we don't copy part of the mode
2059 line at the bottom. */
2060 if (from_y + run->height > bottom_y)
2061 height = bottom_y - from_y;
2063 height = run->height;
2067 /* Scolling down. Make sure we don't copy over the mode line.
2069 if (to_y + run->height > bottom_y)
2070 height = bottom_y - to_y;
2072 height = run->height;
2074 /* end copy from other terms */
2085 NSRect srcRect = NSMakeRect (x, from_y, width, height);
2086 NSRect dstRect = NSMakeRect (x, to_y, width, height);
2087 NSPoint dstOrigin = NSMakePoint (x, to_y);
2089 ns_focus (f, &dstRect, 1);
2090 NSCopyBits (0, srcRect , dstOrigin);
2099 ns_after_update_window_line (struct glyph_row *desired_row)
2100 /* --------------------------------------------------------------------------
2101 23: External (RIF): preparatory to fringe update after text was updated
2102 -------------------------------------------------------------------------- */
2104 struct window *w = updated_window;
2108 NSTRACE (ns_after_update_window_line);
2110 /* begin copy from other terms */
2113 if (!desired_row->mode_line_p && !w->pseudo_window_p)
2114 desired_row->redraw_fringe_bitmaps_p = 1;
2116 /* When a window has disappeared, make sure that no rest of
2117 full-width rows stays visible in the internal border.
2118 Under NS this is drawn inside the fringes. */
2119 if (windows_or_buffers_changed
2120 && (f = XFRAME (w->frame),
2121 width = FRAME_INTERNAL_BORDER_WIDTH (f),
2123 && (height = desired_row->visible_height,
2126 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
2128 /* Internal border is drawn below the tool bar. */
2129 if (WINDOWP (f->tool_bar_window)
2130 && w == XWINDOW (f->tool_bar_window))
2132 /* end copy from other terms */
2135 if (!desired_row->full_width_p)
2137 int x1 = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w)
2138 + WINDOW_LEFT_FRINGE_WIDTH (w);
2139 int x2 = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w)
2140 + FRAME_PIXEL_WIDTH (f) - NS_SCROLL_BAR_WIDTH (f)
2141 - WINDOW_RIGHT_FRINGE_WIDTH (w)
2142 - FRAME_INTERNAL_BORDER_WIDTH (f);
2143 ns_clear_frame_area (f, x1, y, width, height);
2144 ns_clear_frame_area (f, x2, y, width, height);
2152 ns_shift_glyphs_for_insert (struct frame *f,
2153 int x, int y, int width, int height,
2155 /* --------------------------------------------------------------------------
2156 23: External (RIF): copy an area horizontally, don't worry about clearing src
2157 -------------------------------------------------------------------------- */
2159 NSRect srcRect = NSMakeRect (x, y, width, height);
2160 NSRect dstRect = NSMakeRect (x+shift_by, y, width, height);
2161 NSPoint dstOrigin = dstRect.origin;
2163 NSTRACE (ns_shift_glyphs_for_insert);
2165 ns_focus (f, &dstRect, 1);
2166 NSCopyBits (0, srcRect, dstOrigin);
2172 /* ==========================================================================
2174 Character encoding and metrics
2176 ========================================================================== */
2180 ns_compute_glyph_string_overhangs (struct glyph_string *s)
2181 /* --------------------------------------------------------------------------
2182 23: External (RIF); compute left/right overhang of whole string and set in s
2183 -------------------------------------------------------------------------- */
2185 struct face *face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
2186 struct font *font = s->font; /*face->font; */
2190 struct font_metrics metrics;
2191 unsigned int codes[2];
2192 codes[0] = *(s->char2b);
2193 codes[1] = *(s->char2b + s->nchars - 1);
2195 font->driver->text_extents (font, codes, 2, &metrics);
2196 s->left_overhang = -metrics.lbearing;
2198 = metrics.rbearing > metrics.width
2199 ? metrics.rbearing - metrics.width : 0;
2203 s->left_overhang = 0;
2204 s->right_overhang = ((struct nsfont_info *)font)->ital ?
2205 FONT_HEIGHT (font) * 0.2 : 0;
2211 /* ==========================================================================
2213 Fringe and cursor drawing
2215 ========================================================================== */
2218 extern int max_used_fringe_bitmap;
2220 ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
2221 struct draw_fringe_bitmap_params *p)
2222 /* --------------------------------------------------------------------------
2223 23: External (RIF); fringe-related
2224 -------------------------------------------------------------------------- */
2226 struct frame *f = XFRAME (WINDOW_FRAME (w));
2227 struct face *face = p->face;
2229 static EmacsImage **bimgs = NULL;
2230 static int nBimgs = 0;
2231 /* NS-specific: move internal border inside fringe */
2232 int x = p->bx < 0 ? p->x : p->bx;
2233 int wd = p->bx < 0 ? p->wd : p->nx;
2234 BOOL fringeOnVeryLeft
2235 = x - WINDOW_LEFT_SCROLL_BAR_COLS (w) * WINDOW_FRAME_COLUMN_WIDTH (w)
2236 - FRAME_INTERNAL_BORDER_WIDTH (f) < 10;
2237 BOOL fringeOnVeryRight
2238 = FRAME_PIXEL_WIDTH (f) - x - wd - FRAME_INTERNAL_BORDER_WIDTH (f)
2239 - WINDOW_RIGHT_SCROLL_BAR_COLS (w) * WINDOW_FRAME_COLUMN_WIDTH (w) < 10;
2240 int xAdjust = FRAME_INTERNAL_BORDER_WIDTH (f) *
2241 (fringeOnVeryLeft ? -1 : (fringeOnVeryRight ? 1 : 0));
2243 /* grow bimgs if needed */
2244 if (nBimgs < max_used_fringe_bitmap)
2246 EmacsImage **newBimgs
2247 = xmalloc (max_used_fringe_bitmap * sizeof (EmacsImage *));
2248 bzero (newBimgs, max_used_fringe_bitmap * sizeof (EmacsImage *));
2252 bcopy (bimgs, newBimgs, nBimgs * sizeof (EmacsImage *));
2257 nBimgs = max_used_fringe_bitmap;
2260 /* Must clip because of partially visible lines. */
2261 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
2264 /* Adjust position of "bottom aligned" bitmap on partially
2265 visible last row. */
2267 int oldVH = row->visible_height;
2268 row->visible_height = p->h;
2269 row->y -= rowY - p->y;
2270 ns_clip_to_row (w, row, -1, NO);
2272 row->visible_height = oldVH;
2275 ns_clip_to_row (w, row, -1, YES);
2277 if (p->bx >= 0 && !p->overlay_p)
2279 int yAdjust = rowY - FRAME_INTERNAL_BORDER_WIDTH (f) < 5 ?
2280 -FRAME_INTERNAL_BORDER_WIDTH (f) : 0;
2281 int yIncr = FRAME_PIXEL_HEIGHT (f) - (p->by+yAdjust + p->ny) < 5 ?
2282 FRAME_INTERNAL_BORDER_WIDTH (f) : 0;
2284 yIncr += FRAME_INTERNAL_BORDER_WIDTH (f);
2285 NSRect r = NSMakeRect (p->bx+xAdjust, p->by+yAdjust, p->nx, p->ny+yIncr);
2287 [ns_lookup_indexed_color(face->background, f) set];
2293 NSRect r = NSMakeRect (p->x+xAdjust, p->y, p->wd, p->h);
2294 NSPoint pt = r.origin;
2295 EmacsImage *img = bimgs[p->which - 1];
2299 unsigned short *bits = p->bits + p->dh;
2300 int len = 8 * p->h/8;
2302 unsigned char *cbits = xmalloc (len);
2304 for (i =0; i<len; i++)
2305 cbits[i] = ~(bits[i] & 0xff);
2306 img = [[EmacsImage alloc] initFromXBM: cbits width: 8 height: p->h
2308 bimgs[p->which - 1] = img;
2313 /* Since we composite the bitmap instead of just blitting it, we need
2314 to erase the whole background. */
2315 [ns_lookup_indexed_color(face->background, f) set];
2318 [img setXBMColor: ns_lookup_indexed_color(face->foreground, f)];
2319 [img compositeToPoint: pt operation: NSCompositeSourceOver];
2326 ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
2327 int x, int y, int cursor_type, int cursor_width,
2328 int on_p, int active_p)
2329 /* --------------------------------------------------------------------------
2330 External call (RIF): draw cursor
2331 (modeled after x_draw_window_cursor
2332 FIXME: cursor_width is effectively bogus -- it sometimes gets set
2333 in xdisp.c set_frame_cursor_types, sometimes left uninitialized;
2334 DON'T USE IT (no other terms do)
2335 -------------------------------------------------------------------------- */
2339 struct frame *f = WINDOW_XFRAME (w);
2340 struct glyph *phys_cursor_glyph;
2341 int overspill, cursorToDraw;
2343 NSTRACE (dumpcursor);
2344 //fprintf(stderr, "drawcursor (%d,%d) activep = %d\tonp = %d\tc_type = %d\twidth = %d\n",x,y, active_p,on_p,cursor_type,cursor_width);
2349 w->phys_cursor_type = cursor_type;
2350 w->phys_cursor_on_p = on_p;
2352 if (cursor_type == NO_CURSOR)
2354 w->phys_cursor_width = 0;
2358 if ((phys_cursor_glyph = get_phys_cursor_glyph (w)) == NULL)
2360 if (glyph_row->exact_window_width_line_p
2361 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
2363 glyph_row->cursor_in_fringe_p = 1;
2364 draw_fringe_bitmap (w, glyph_row, 0);
2369 get_phys_cursor_geometry (w, glyph_row, phys_cursor_glyph, &fx, &fy, &h);
2371 r.origin.x = fx, r.origin.y = fy;
2373 r.size.width = w->phys_cursor_width;
2375 /* FIXME: if we overwrite the internal border area, it does not get erased;
2376 fix by truncating cursor, but better would be to erase properly */
2377 overspill = r.origin.x + r.size.width -
2378 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, WINDOW_BOX_RIGHT_EDGE_X (w)
2379 - WINDOW_TOTAL_FRINGE_WIDTH (w) - FRAME_INTERNAL_BORDER_WIDTH (f));
2381 r.size.width -= overspill;
2383 /* TODO: only needed in rare cases with last-resort font in HELLO..
2384 should we do this more efficiently? */
2385 ns_clip_to_row (w, glyph_row, -1, NO); /* do ns_focus(f, &r, 1); if remove */
2386 [FRAME_CURSOR_COLOR (f) set];
2388 #ifdef NS_IMPL_COCOA
2389 /* TODO: This makes drawing of cursor plus that of phys_cursor_glyph
2390 atomic. Cleaner ways of doing this should be investigated.
2391 One way would be to set a global variable DRAWING_CURSOR
2392 when making the call to draw_phys..(), don't focus in that
2393 case, then move the ns_unfocus() here after that call. */
2394 NSDisableScreenUpdates ();
2397 cursorToDraw = active_p ? cursor_type : HOLLOW_BOX_CURSOR;
2398 switch (cursorToDraw)
2402 case FILLED_BOX_CURSOR:
2405 case HOLLOW_BOX_CURSOR:
2407 [FRAME_BACKGROUND_COLOR (f) set];
2408 NSRectFill (NSInsetRect (r, 1, 1));
2409 [FRAME_CURSOR_COLOR (f) set];
2413 s.origin.y += lrint (0.75 * s.size.height);
2414 s.size.width = min (FRAME_COLUMN_WIDTH (f), s.size.width);
2415 s.size.height = lrint (s.size.height * 0.25);
2420 s.size.width = min (cursor_width, 2); //FIXME(see above)
2426 /* draw the character under the cursor */
2427 if (cursorToDraw != NO_CURSOR)
2428 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
2430 #ifdef NS_IMPL_COCOA
2431 NSEnableScreenUpdates ();
2438 ns_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
2439 /* --------------------------------------------------------------------------
2440 External (RIF): Draw a vertical line.
2441 -------------------------------------------------------------------------- */
2443 struct frame *f = XFRAME (WINDOW_FRAME (w));
2445 NSRect r = NSMakeRect (x, y0, 2, y1-y0);
2447 NSTRACE (ns_draw_vertical_window_border);
2449 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
2451 [ns_lookup_indexed_color(face->foreground, f) set];
2453 ns_focus (f, &r, 1);
2454 NSDrawGroove (r, r);
2460 show_hourglass (struct atimer *timer)
2462 if (hourglass_shown_p)
2467 /* TODO: add NSProgressIndicator to selected frame (see macfns.c) */
2469 hourglass_shown_p = 1;
2477 if (!hourglass_shown_p)
2482 /* TODO: remove NSProgressIndicator from all frames */
2484 hourglass_shown_p = 0;
2490 /* ==========================================================================
2492 Glyph drawing operations
2494 ========================================================================== */
2497 static inline NSRect
2498 ns_fix_rect_ibw (NSRect r, int fibw, int frame_pixel_width)
2499 /* --------------------------------------------------------------------------
2500 Under NS we draw internal borders inside fringes, and want full-width
2501 rendering to go all the way to edge. This function makes that correction.
2502 -------------------------------------------------------------------------- */
2504 if (r.origin.y <= fibw+1)
2506 r.size.height += r.origin.y;
2509 if (r.origin.x <= fibw+1)
2511 r.size.width += r.origin.x;
2514 if (frame_pixel_width - (r.origin.x+r.size.width) <= fibw+1)
2515 r.size.width += fibw;
2522 ns_get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr)
2523 /* --------------------------------------------------------------------------
2524 Wrapper utility to account for internal border width on full-width lines,
2525 and allow top full-width rows to hit the frame top. nr should be pointer
2526 to two successive NSRects. Number of rects actually used is returned.
2527 -------------------------------------------------------------------------- */
2529 int n = get_glyph_string_clip_rects (s, nr, 2);
2530 if (s->row->full_width_p)
2532 *nr = ns_fix_rect_ibw (*nr, FRAME_INTERNAL_BORDER_WIDTH (s->f),
2533 FRAME_PIXEL_WIDTH (s->f));
2535 *nr = ns_fix_rect_ibw (*(nr+1), FRAME_INTERNAL_BORDER_WIDTH (s->f),
2536 FRAME_PIXEL_WIDTH (s->f));
2543 ns_draw_box (NSRect r, float thickness, NSColor *col, char left_p, char right_p)
2544 /* --------------------------------------------------------------------------
2545 Draw an unfilled rect inside r, optionally leaving left and/or right open.
2546 Note we can't just use an NSDrawRect command, because of the possibility
2547 of some sides not being drawn, and because the rect will be filled.
2548 -------------------------------------------------------------------------- */
2554 s.size.height = thickness;
2556 s.origin.y += r.size.height - thickness;
2559 s.size.height = r.size.height;
2560 s.origin.y = r.origin.y;
2562 /* left, right (optional) */
2563 s.size.width = thickness;
2568 s.origin.x += r.size.width - thickness;
2575 ns_draw_relief (NSRect r, int thickness, char raised_p,
2576 char top_p, char bottom_p, char left_p, char right_p,
2577 struct glyph_string *s)
2578 /* --------------------------------------------------------------------------
2579 Draw a relief rect inside r, optionally leaving some sides open.
2580 Note we can't just use an NSDrawBezel command, because of the possibility
2581 of some sides not being drawn, and because the rect will be filled.
2582 -------------------------------------------------------------------------- */
2584 static NSColor *baseCol = nil, *lightCol = nil, *darkCol = nil;
2585 NSColor *newBaseCol = nil;
2588 NSTRACE (ns_draw_relief);
2592 if (s->face->use_box_color_for_shadows_p)
2594 newBaseCol = ns_lookup_indexed_color (s->face->box_color, s->f);
2596 /* else if (s->first_glyph->type == IMAGE_GLYPH
2598 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
2600 newBaseCol = IMAGE_BACKGROUND (s->img, s->f, 0);
2604 newBaseCol = ns_lookup_indexed_color (s->face->background, s->f);
2607 if (newBaseCol == nil)
2608 newBaseCol = [NSColor grayColor];
2610 if (newBaseCol != baseCol) /* TODO: better check */
2613 baseCol = [newBaseCol retain];
2615 lightCol = [[baseCol highlightWithLevel: 0.2] retain];
2617 darkCol = [[baseCol shadowWithLevel: 0.3] retain];
2620 [(raised_p ? lightCol : darkCol) set];
2622 /* TODO: mitering. Using NSBezierPath doesn't work because of color switch. */
2625 sr.size.height = thickness;
2626 if (top_p) NSRectFill (sr);
2629 sr.size.height = r.size.height;
2630 sr.size.width = thickness;
2631 if (left_p) NSRectFill (sr);
2633 [(raised_p ? darkCol : lightCol) set];
2636 sr.size.width = r.size.width;
2637 sr.size.height = thickness;
2638 sr.origin.y += r.size.height - thickness;
2639 if (bottom_p) NSRectFill (sr);
2642 sr.size.height = r.size.height;
2643 sr.origin.y = r.origin.y;
2644 sr.size.width = thickness;
2645 sr.origin.x += r.size.width - thickness;
2646 if (right_p) NSRectFill (sr);
2651 ns_dumpglyphs_box_or_relief (struct glyph_string *s)
2652 /* --------------------------------------------------------------------------
2653 Function modeled after x_draw_glyph_string_box ().
2654 Sets up parameters for drawing.
2655 -------------------------------------------------------------------------- */
2657 int right_x, last_x;
2658 char left_p, right_p;
2659 struct glyph *last_glyph;
2664 if (s->hl == DRAW_MOUSE_FACE)
2667 (s->f, FRAME_NS_DISPLAY_INFO (s->f)->mouse_face_face_id);
2669 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2674 thickness = face->box_line_width;
2676 NSTRACE (ns_dumpglyphs_box_or_relief);
2678 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
2679 ? WINDOW_RIGHT_EDGE_X (s->w)
2680 : window_box_right (s->w, s->area));
2681 last_glyph = (s->cmp || s->img
2682 ? s->first_glyph : s->first_glyph + s->nchars-1);
2684 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
2685 ? last_x - 1 : min (last_x, s->x + s->background_width) - 1));
2687 left_p = (s->first_glyph->left_box_line_p
2688 || (s->hl == DRAW_MOUSE_FACE
2689 && (s->prev == NULL || s->prev->hl != s->hl)));
2690 right_p = (last_glyph->right_box_line_p
2691 || (s->hl == DRAW_MOUSE_FACE
2692 && (s->next == NULL || s->next->hl != s->hl)));
2694 r = NSMakeRect (s->x, s->y, right_x - s->x + 1, s->height);
2696 /* expand full-width row over internal borders */
2697 if (s->row->full_width_p)
2698 r = ns_fix_rect_ibw (r, FRAME_INTERNAL_BORDER_WIDTH (s->f),
2699 FRAME_PIXEL_WIDTH (s->f));
2701 if (s->face->box == FACE_SIMPLE_BOX)
2703 xassert (s->face->box_color != nil);
2704 ns_draw_box (r, abs (thickness),
2705 ns_lookup_indexed_color (face->box_color, s->f),
2710 ns_draw_relief (r, abs (thickness), s->face->box == FACE_RAISED_BOX,
2711 1, 1, left_p, right_p, s);
2717 ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p)
2718 /* --------------------------------------------------------------------------
2719 Modeled after x_draw_glyph_string_background, which draws BG in
2720 certain cases. Others are left to the text rendering routine.
2721 -------------------------------------------------------------------------- */
2723 NSTRACE (ns_maybe_dumpglyphs_background);
2725 if (!s->background_filled_p/* || s->hl == DRAW_MOUSE_FACE*/)
2727 int box_line_width = max (s->face->box_line_width, 0);
2728 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2729 || s->font_not_found_p || s->extends_to_end_of_line_p || force_p)
2732 if (s->hl == DRAW_MOUSE_FACE)
2735 (s->f, FRAME_NS_DISPLAY_INFO (s->f)->mouse_face_face_id);
2737 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2740 face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
2742 [(NS_FACE_BACKGROUND (face) != 0
2743 ? ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f)
2744 : FRAME_BACKGROUND_COLOR (s->f)) set];
2747 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (s->f);
2748 [[dpyinfo->bitmaps[face->stipple-1].img stippleMask] set];
2751 if (s->hl != DRAW_CURSOR)
2753 NSRect r = NSMakeRect (s->x, s->y + box_line_width,
2754 s->background_width,
2755 s->height-2*box_line_width);
2757 /* expand full-width row over internal borders */
2758 if (s->row->full_width_p)
2760 int fibw = FRAME_INTERNAL_BORDER_WIDTH (s->f);
2761 if (r.origin.y <= fibw+1 + box_line_width)
2763 r.size.height += r.origin.y;
2766 if (r.origin.x <= fibw+1)
2768 r.size.width += 2*r.origin.x;
2771 if (FRAME_PIXEL_WIDTH (s->f) - (r.origin.x + r.size.width)
2773 r.size.width += fibw;
2779 s->background_filled_p = 1;
2786 ns_dumpglyphs_image (struct glyph_string *s, NSRect r)
2787 /* --------------------------------------------------------------------------
2788 Renders an image and associated borders.
2789 -------------------------------------------------------------------------- */
2791 EmacsImage *img = s->img->pixmap;
2792 int box_line_vwidth = max (s->face->box_line_width, 0);
2793 int x = s->x, y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2794 int bg_x, bg_y, bg_height;
2799 NSTRACE (ns_dumpglyphs_image);
2801 if (s->face->box != FACE_NO_BOX
2802 && s->first_glyph->left_box_line_p && s->slice.x == 0)
2803 x += abs (s->face->box_line_width);
2806 bg_y = s->slice.y == 0 ? s->y : s->y + box_line_vwidth;
2807 bg_height = s->height;
2808 /* other terms have this, but was causing problems w/tabbar mode */
2809 /* - 2 * box_line_vwidth; */
2811 if (s->slice.x == 0) x += s->img->hmargin;
2812 if (s->slice.y == 0) y += s->img->vmargin;
2814 /* Draw BG: if we need larger area than image itself cleared, do that,
2815 otherwise, since we composite the image under NS (instead of mucking
2816 with its background color), we must clear just the image area. */
2817 [ns_lookup_indexed_color (NS_FACE_BACKGROUND
2818 (FACE_FROM_ID (s->f, s->first_glyph->face_id)), s->f) set];
2820 if (bg_height > s->slice.height || s->img->hmargin || s->img->vmargin
2821 || s->img->mask || s->img->pixmap == 0 || s->width != s->background_width)
2823 br = NSMakeRect (bg_x, bg_y, s->background_width, bg_height);
2824 s->background_filled_p = 1;
2828 br = NSMakeRect (x, y, s->slice.width, s->slice.height);
2831 /* expand full-width row over internal borders */
2832 if (s->row->full_width_p)
2834 int fibw = FRAME_INTERNAL_BORDER_WIDTH (s->f);
2835 if (br.origin.y <= fibw+1 + box_line_vwidth)
2837 br.size.height += br.origin.y;
2840 if (br.origin.x <= fibw+1 + box_line_vwidth)
2842 br.size.width += br.origin.x;
2845 if (FRAME_PIXEL_WIDTH (s->f) - (br.origin.x + br.size.width) <= fibw+1)
2846 br.size.width += fibw;
2851 /* Draw the image.. do we need to draw placeholder if img ==nil? */
2853 [img compositeToPoint: NSMakePoint (x, y + s->slice.height)
2854 operation: NSCompositeSourceOver];
2856 /* Draw relief, if requested */
2857 if (s->img->relief || s->hl ==DRAW_IMAGE_RAISED || s->hl ==DRAW_IMAGE_SUNKEN)
2859 if (s->hl == DRAW_IMAGE_SUNKEN || s->hl == DRAW_IMAGE_RAISED)
2861 th = tool_bar_button_relief >= 0 ?
2862 tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
2863 raised_p = (s->hl == DRAW_IMAGE_RAISED);
2867 th = abs (s->img->relief);
2868 raised_p = (s->img->relief > 0);
2871 r.origin.x = x - th;
2872 r.origin.y = y - th;
2873 r.size.width = s->slice.width + 2*th-1;
2874 r.size.height = s->slice.height + 2*th-1;
2875 ns_draw_relief (r, th, raised_p,
2877 s->slice.y + s->slice.height == s->img->height,
2879 s->slice.x + s->slice.width == s->img->width, s);
2885 ns_draw_glyph_string (struct glyph_string *s)
2886 /* --------------------------------------------------------------------------
2887 External (RIF): Main draw-text call.
2888 -------------------------------------------------------------------------- */
2890 /* TODO (optimize): focus for box and contents draw */
2893 char box_drawn_p = 0;
2895 NSTRACE (ns_draw_glyph_string);
2897 if (s->next && s->right_overhang && !s->for_overlaps/*&&s->hl!=DRAW_CURSOR*/)
2900 struct glyph_string *next;
2902 for (width = 0, next = s->next;
2903 next && width < s->right_overhang;
2904 width += next->width, next = next->next)
2905 if (next->first_glyph->type != IMAGE_GLYPH)
2907 n = ns_get_glyph_string_clip_rect (s->next, r);
2908 ns_focus (s->f, r, n);
2909 ns_maybe_dumpglyphs_background (s->next, 1);
2911 next->num_clips = 0;
2915 if (!s->for_overlaps && s->face->box != FACE_NO_BOX
2916 && (s->first_glyph->type == CHAR_GLYPH
2917 || s->first_glyph->type == COMPOSITE_GLYPH))
2919 n = ns_get_glyph_string_clip_rect (s, r);
2920 ns_focus (s->f, r, n);
2921 ns_maybe_dumpglyphs_background (s, 1);
2922 ns_dumpglyphs_box_or_relief (s);
2927 switch (s->first_glyph->type)
2931 n = ns_get_glyph_string_clip_rect (s, r);
2932 ns_focus (s->f, r, n);
2933 ns_dumpglyphs_image (s, r[0]);
2938 if (!s->background_filled_p)
2940 *r = NSMakeRect (s->x, s->y, s->background_width, s->height);
2942 if (!s->row->full_width_p)
2944 /* truncate to avoid overwriting fringe and/or scrollbar */
2945 int overrun = max (0, (s->x + s->background_width)
2946 - (WINDOW_BOX_RIGHT_EDGE_X (s->w)
2947 - WINDOW_RIGHT_FRINGE_WIDTH (s->w)));
2948 r[0].size.width -= overrun;
2950 /* XXX: Try to work between problem where a stretch glyph on
2951 a partially-visible bottom row will clear part of the
2952 modeline, and another where list-buffers headers and similar
2953 rows erroneously have visible_height set to 0. Not sure
2954 where this is coming from as other terms seem not to show. */
2955 r[0].size.height = min (s->height, s->row->visible_height);
2958 /* expand full-width rows over internal borders */
2961 r[0] = ns_fix_rect_ibw (r[0], FRAME_INTERNAL_BORDER_WIDTH (s->f),
2962 FRAME_PIXEL_WIDTH (s->f));
2965 /* NOTE: under NS this is NOT used to draw cursors, but we must avoid
2966 overwriting cursor (usually when cursor on a tab) */
2967 if (s->hl == DRAW_CURSOR)
2969 r[0].origin.x += s->width;
2970 r[0].size.width -= s->width;
2973 ns_focus (s->f, r, 1);
2974 [ns_lookup_indexed_color (NS_FACE_BACKGROUND
2975 (FACE_FROM_ID (s->f, s->first_glyph->face_id)), s->f) set];
2978 s->background_filled_p = 1;
2983 case COMPOSITE_GLYPH:
2984 n = ns_get_glyph_string_clip_rect (s, r);
2985 ns_focus (s->f, r, n);
2987 if (s->for_overlaps || (s->cmp_from > 0
2988 && ! s->first_glyph->u.cmp.automatic))
2989 s->background_filled_p = 1;
2991 ns_maybe_dumpglyphs_background
2992 (s, s->first_glyph->type == COMPOSITE_GLYPH);
2994 ns_tmp_flags = s->hl == DRAW_CURSOR ? NS_DUMPGLYPH_CURSOR :
2995 (s->hl == DRAW_MOUSE_FACE ? NS_DUMPGLYPH_MOUSEFACE :
2996 (s->for_overlaps ? NS_DUMPGLYPH_FOREGROUND :
2997 NS_DUMPGLYPH_NORMAL));
2998 ns_tmp_font = (struct nsfont_info *)s->face->font;
2999 if (ns_tmp_font == NULL)
3000 ns_tmp_font = (struct nsfont_info *)FRAME_FONT (s->f);
3002 ns_tmp_font->font.driver->draw
3003 (s, 0, s->nchars, s->x, s->y,
3004 (ns_tmp_flags == NS_DUMPGLYPH_NORMAL && !s->background_filled_p)
3005 || ns_tmp_flags == NS_DUMPGLYPH_MOUSEFACE);
3014 /* Draw box if not done already. */
3015 if (!s->for_overlaps && !box_drawn_p && s->face->box != FACE_NO_BOX)
3017 n = ns_get_glyph_string_clip_rect (s, r);
3018 ns_focus (s->f, r, n);
3019 ns_dumpglyphs_box_or_relief (s);
3028 /* ==========================================================================
3032 ========================================================================== */
3036 ns_send_appdefined (int value)
3037 /* --------------------------------------------------------------------------
3038 Internal: post an appdefined event which EmacsApp-sendEvent will
3039 recognize and take as a command to halt the event loop.
3040 -------------------------------------------------------------------------- */
3042 /*NSTRACE (ns_send_appdefined); */
3044 /* Only post this event if we haven't already posted one. This will end
3045 the [NXApp run] main loop after having processed all events queued at
3047 if (send_appdefined)
3051 /* We only need one NX_APPDEFINED event to stop NXApp from running. */
3052 send_appdefined = NO;
3054 /* Don't need wakeup timer any more */
3057 [timed_entry invalidate];
3058 [timed_entry release];
3062 /* Ditto for file descriptor poller */
3065 [fd_entry invalidate];
3070 nxev = [NSEvent otherEventWithType: NSApplicationDefined
3071 location: NSMakePoint (0, 0)
3074 windowNumber: [[NSApp mainWindow] windowNumber]
3075 context: [NSApp context]
3080 /* Post an application defined event on the event queue. When this is
3081 received the [NXApp run] will return, thus having processed all
3082 events which are currently queued. */
3083 [NSApp postEvent: nxev atStart: NO];
3089 ns_read_socket (struct terminal *terminal, int expected,
3090 struct input_event *hold_quit)
3091 /* --------------------------------------------------------------------------
3092 External (hook): Post an event to ourself and keep reading events until
3093 we read it back again. In effect process all events which were waiting.
3094 23: Now we have to manage the event buffer ourselves.
3095 -------------------------------------------------------------------------- */
3097 struct input_event ev;
3099 static NSDate *lastCheck = nil;
3100 /* NSTRACE (ns_read_socket); */
3102 if (interrupt_input_blocked)
3104 interrupt_input_pending = 1;
3108 interrupt_input_pending = 0;
3111 #ifdef COCOA_EXPERIMENTAL_CTRL_G
3112 /* causes Feval to abort; unclear on why this isn't in calling code */
3116 n_emacs_events_pending = 0;
3119 q_event_ptr = hold_quit;
3121 /* we manage autorelease pools by allocate/reallocate each time around
3122 the loop; strict nesting is occasionally violated but seems not to
3123 matter.. earlier methods using full nesting caused major memory leaks */
3124 [outerpool release];
3125 outerpool = [[NSAutoreleasePool alloc] init];
3127 /* If have pending open-file requests, attend to the next one of those. */
3128 if (ns_pending_files && [ns_pending_files count] != 0
3129 && [(EmacsApp *)NSApp openFile: [ns_pending_files objectAtIndex: 0]])
3131 [ns_pending_files removeObjectAtIndex: 0];
3133 /* Deal with pending service requests. */
3134 else if (ns_pending_service_names && [ns_pending_service_names count] != 0
3136 NSApp fulfillService: [ns_pending_service_names objectAtIndex: 0]
3137 withArg: [ns_pending_service_args objectAtIndex: 0]])
3139 [ns_pending_service_names removeObjectAtIndex: 0];
3140 [ns_pending_service_args removeObjectAtIndex: 0];
3144 /* Run and wait for events. We must always send one NX_APPDEFINED event
3145 to ourself, otherwise [NXApp run] will never exit. */
3146 send_appdefined = YES;
3148 /* TODO: from termhooks.h: */
3149 /* XXX Please note that a non-zero value of EXPECTED only means that
3150 there is available input on at least one of the currently opened
3151 terminal devices -- but not necessarily on this device.
3152 Therefore, in most cases EXPECTED should be simply ignored. */
3153 /* However, if in ns_select, this is called from gobble_input, which
3154 appears to set it correctly for our purposes, and always assuming
3155 !expected causes 100% CPU usage. */
3156 if (!inNsSelect || !expected)
3158 /* Post an application defined event on the event queue. When this is
3159 received the [NXApp run] will return, thus having processed all
3160 events which are currently queued, if any. */
3161 ns_send_appdefined (-1);
3167 nevents = n_emacs_events_pending;
3168 n_emacs_events_pending = 0;
3169 emacs_event = q_event_ptr = NULL;
3171 #ifdef COCOA_EXPERIMENTAL_CTRL_G
3180 ns_select (int nfds, fd_set *readfds, fd_set *writefds,
3181 fd_set *exceptfds, struct timeval *timeout)
3182 /* --------------------------------------------------------------------------
3183 Replacement for select, checking for events
3184 -------------------------------------------------------------------------- */
3189 /* NSTRACE (ns_select); */
3191 if (NSApp == nil /* || ([NSApp isActive] == NO &&
3192 [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:nil
3193 inMode:NSDefaultRunLoopMode dequeue:NO] == nil) */)
3194 return select (nfds, readfds, writefds, exceptfds, timeout);
3196 /* Save file descriptor set, which gets overwritten in calls to select ()
3197 Note, this is called from process.c, and only readfds is ever set */
3200 memcpy (&select_readfds, readfds, sizeof (fd_set));
3206 /* Try an initial select for pending data on input files */
3207 select_timeout.tv_sec = select_timeout.tv_usec = 0;
3208 result = select (nfds, readfds, writefds, exceptfds, &select_timeout);
3212 /* if (!timeout || timed_entry || fd_entry)
3213 fprintf (stderr, "assertion failed: timeout null or timed_entry/fd_entry non-null in ns_select\n"); */
3215 /* set a timeout and run the main AppKit event loop while continuing
3216 to monitor the files */
3217 time = ((double) timeout->tv_sec) + ((double) timeout->tv_usec)/1000000.0;
3218 timed_entry = [[NSTimer scheduledTimerWithTimeInterval: time
3220 selector: @selector (timeout_handler:)
3222 repeats: YES] /* for safe removal */
3225 /* set a periodic task to try the select () again */
3226 fd_entry = [[NSTimer scheduledTimerWithTimeInterval: 0.1
3228 selector: @selector (fd_handler:)
3233 /* Let Application dispatch events until it receives an event of the type
3234 NX_APPDEFINED, which should only be sent by timeout_handler. */
3236 gobble_input (timeout ? 1 : 0);
3237 ev = last_appdefined_event;
3243 if ([ev type] != NSApplicationDefined)
3247 last_appdefined_event = 0;
3251 /* The NX_APPDEFINED event we received was a timeout. */
3256 /* The NX_APPDEFINED event we received was the result of
3257 at least one real input event arriving. */
3263 /* Received back from select () in fd_handler; copy the results */
3265 memcpy (readfds, &select_readfds, sizeof (fd_set));
3269 /* never reached, shut compiler up */
3275 /* ==========================================================================
3279 ========================================================================== */
3283 ns_set_vertical_scroll_bar (struct window *window,
3284 int portion, int whole, int position)
3285 /* --------------------------------------------------------------------------
3286 External (hook): Update or add scrollbar
3287 -------------------------------------------------------------------------- */
3291 struct frame *f = XFRAME (WINDOW_FRAME (window));
3292 EmacsView *view = FRAME_NS_VIEW (f);
3293 int window_y, window_height;
3294 BOOL barOnVeryLeft, barOnVeryRight;
3295 int top, left, height, width, sb_width, sb_left;
3297 static int count = 0;
3299 /* optimization; display engine sends WAY too many of these.. */
3300 if (!NILP (window->vertical_scroll_bar))
3302 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
3303 if ([bar checkSamePosition: position portion: portion whole: whole])
3305 if (view->scrollbarsNeedingUpdate == 0)
3307 if (!windows_or_buffers_changed)
3311 view->scrollbarsNeedingUpdate--;
3315 NSTRACE (ns_set_vertical_scroll_bar);
3317 /* Get dimensions. */
3318 window_box (window, -1, 0, &window_y, 0, &window_height);
3320 height = window_height;
3321 width = WINDOW_CONFIG_SCROLL_BAR_COLS (window) * FRAME_COLUMN_WIDTH (f);
3322 left = WINDOW_SCROLL_BAR_AREA_X (window);
3324 if (top < 5) /* top scrollbar adjustment */
3326 top -= FRAME_INTERNAL_BORDER_WIDTH (f);
3327 height += FRAME_INTERNAL_BORDER_WIDTH (f);
3330 /* allow for displaying a skinnier scrollbar than char area allotted */
3331 sb_width = (WINDOW_CONFIG_SCROLL_BAR_WIDTH (window) > 0) ?
3332 WINDOW_CONFIG_SCROLL_BAR_WIDTH (window) : width;
3334 barOnVeryLeft = left < 5;
3335 barOnVeryRight = FRAME_PIXEL_WIDTH (f) - left - width < 5;
3336 sb_left = left + FRAME_INTERNAL_BORDER_WIDTH (f)
3337 * (barOnVeryLeft ? -1 : (barOnVeryRight ? 1 : 0));
3339 r = NSMakeRect (sb_left, top, sb_width, height);
3340 /* the parent view is flipped, so we need to flip y value */
3342 r.origin.y = (v.size.height - r.size.height - r.origin.y);
3344 XSETWINDOW (win, window);
3347 /* we want at least 5 lines to display a scrollbar */
3348 if (WINDOW_TOTAL_LINES (window) < 5)
3350 if (!NILP (window->vertical_scroll_bar))
3352 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
3353 [bar removeFromSuperview];
3354 window->vertical_scroll_bar = Qnil;
3356 ns_clear_frame_area (f, sb_left, top, width, height);
3361 if (NILP (window->vertical_scroll_bar))
3363 ns_clear_frame_area (f, sb_left, top, width, height);
3364 bar = [[EmacsScroller alloc] initFrame: r window: win];
3365 window->vertical_scroll_bar = make_save_value (bar, 0);
3370 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
3371 oldRect = [bar frame];
3372 r.size.width = oldRect.size.width;
3373 if (FRAME_LIVE_P (f) && !NSEqualRects (oldRect, r))
3375 if (oldRect.origin.x != r.origin.x)
3376 ns_clear_frame_area (f, sb_left, top, width, height);
3381 [bar setPosition: position portion: portion whole: whole];
3387 ns_condemn_scroll_bars (struct frame *f)
3388 /* --------------------------------------------------------------------------
3389 External (hook): arrange for all frame's scrollbars to be removed
3390 at next call to judge_scroll_bars, except for those redeemed.
3391 -------------------------------------------------------------------------- */
3395 NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews];
3397 NSTRACE (ns_condemn_scroll_bars);
3399 for (i =[subviews count]-1; i >= 0; i--)
3401 view = [subviews objectAtIndex: i];
3402 if ([view isKindOfClass: [EmacsScroller class]])
3409 ns_redeem_scroll_bar (struct window *window)
3410 /* --------------------------------------------------------------------------
3411 External (hook): arrange to spare this window's scrollbar
3412 at next call to judge_scroll_bars.
3413 -------------------------------------------------------------------------- */
3416 NSTRACE (ns_redeem_scroll_bar);
3417 if (!NILP (window->vertical_scroll_bar))
3419 bar =XNS_SCROLL_BAR (window->vertical_scroll_bar);
3426 ns_judge_scroll_bars (struct frame *f)
3427 /* --------------------------------------------------------------------------
3428 External (hook): destroy all scrollbars on frame that weren't
3429 redeemed after call to condemn_scroll_bars.
3430 -------------------------------------------------------------------------- */
3434 NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews];
3435 NSTRACE (ns_judge_scroll_bars);
3436 for (i =[subviews count]-1; i >= 0; i--)
3438 view = [subviews objectAtIndex: i];
3439 if (![view isKindOfClass: [EmacsScroller class]]) continue;
3446 /* ==========================================================================
3448 Miscellaneous, mainly stubbed-out functions added in 23
3450 ========================================================================== */
3454 x_wm_set_icon_position (struct frame *f, int icon_x, int icon_y)
3460 /* ==========================================================================
3464 ========================================================================== */
3467 x_display_pixel_height (dpyinfo)
3468 struct ns_display_info *dpyinfo;
3470 NSScreen *screen = [NSScreen mainScreen];
3471 return [screen frame].size.height;
3475 x_display_pixel_width (dpyinfo)
3476 struct ns_display_info *dpyinfo;
3478 NSScreen *screen = [NSScreen mainScreen];
3479 return [screen frame].size.width;
3483 static Lisp_Object ns_string_to_lispmod (const char *s)
3484 /* --------------------------------------------------------------------------
3485 Convert modifier name to lisp symbol
3486 -------------------------------------------------------------------------- */
3488 if (!strncmp (SDATA (SYMBOL_NAME (Qmeta)), s, 10))
3490 else if (!strncmp (SDATA (SYMBOL_NAME (Qsuper)), s, 10))
3492 else if (!strncmp (SDATA (SYMBOL_NAME (Qcontrol)), s, 10))
3494 else if (!strncmp (SDATA (SYMBOL_NAME (Qalt)), s, 10))
3496 else if (!strncmp (SDATA (SYMBOL_NAME (Qhyper)), s, 10))
3498 else if (!strncmp (SDATA (SYMBOL_NAME (Qnone)), s, 10))
3505 static Lisp_Object ns_mod_to_lisp (int m)
3506 /* --------------------------------------------------------------------------
3507 Convert modifier code (see lisp.h) to lisp symbol
3508 -------------------------------------------------------------------------- */
3512 else if (m == CHAR_SUPER)
3514 else if (m == CHAR_CTL)
3516 else if (m == CHAR_ALT)
3518 else if (m == CHAR_HYPER)
3520 else /* if (m == 0) */
3526 ns_set_default_prefs ()
3527 /* --------------------------------------------------------------------------
3528 Initialize preference variables to defaults
3529 -------------------------------------------------------------------------- */
3531 ns_alternate_modifier = Qmeta;
3532 ns_command_modifier = Qsuper;
3533 ns_control_modifier = Qcontrol;
3534 ns_function_modifier = Qnone;
3535 ns_expand_space = make_float (0.0);
3536 ns_antialias_text = Qt;
3537 ns_antialias_threshold = 10.0; /* not exposed to lisp side */
3538 ns_use_qd_smoothing = Qnil;
3539 ns_use_system_highlight_color = Qt;
3544 ns_default (const char *parameter, Lisp_Object *result,
3545 Lisp_Object yesval, Lisp_Object noval,
3546 BOOL is_float, BOOL is_modstring)
3547 /* --------------------------------------------------------------------------
3548 Check a parameter value in user's preferences
3549 -------------------------------------------------------------------------- */
3553 if ( (value =[[[NSUserDefaults standardUserDefaults]
3554 stringForKey: [NSString stringWithUTF8String: parameter]]
3559 if (strcasecmp (value, "YES") == 0)
3561 else if (strcasecmp (value, "NO") == 0)
3563 else if (is_float && (f = strtod (value, &pos), pos != value))
3564 *result = make_float (f);
3565 else if (is_modstring && value)
3566 *result = ns_string_to_lispmod (value);
3567 else fprintf (stderr,
3568 "Bad value for default \"%s\": \"%s\"\n", parameter, value);
3574 ns_initialize_display_info (struct ns_display_info *dpyinfo)
3575 /* --------------------------------------------------------------------------
3576 Initialize global info and storage for display.
3577 -------------------------------------------------------------------------- */
3579 NSScreen *screen = [NSScreen mainScreen];
3580 NSWindowDepth depth = [screen depth];
3582 dpyinfo->resx = 72.27; /* used 75.0, but this makes pt == pixel, expected */
3583 dpyinfo->resy = 72.27;
3584 dpyinfo->color_p = ![NSDeviceWhiteColorSpace isEqualToString:
3585 NSColorSpaceFromDepth (depth)]
3586 && ![NSCalibratedWhiteColorSpace isEqualToString:
3587 NSColorSpaceFromDepth (depth)];
3588 dpyinfo->n_planes = NSBitsPerPixelFromDepth (depth);
3589 dpyinfo->image_cache = make_image_cache ();
3590 dpyinfo->color_table
3591 = (struct ns_color_table *)xmalloc (sizeof (struct ns_color_table));
3592 dpyinfo->color_table->colors = NULL;
3593 dpyinfo->root_window = 42; /* a placeholder.. */
3595 dpyinfo->mouse_face_mouse_frame = NULL;
3596 dpyinfo->mouse_face_deferred_gc = 0;
3597 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
3598 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
3599 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
3600 dpyinfo->mouse_face_window = dpyinfo->mouse_face_overlay = Qnil;
3601 dpyinfo->mouse_face_hidden = 0;
3603 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
3604 dpyinfo->mouse_face_defer = 0;
3606 dpyinfo->x_highlight_frame = dpyinfo->x_focus_frame = NULL;
3608 dpyinfo->n_fonts = 0;
3609 dpyinfo->smallest_font_height = 1;
3610 dpyinfo->smallest_char_width = 1;
3614 /* 23: Needed as new part of display engine; this and next define public
3615 functions in this file (well, many of them, anyway). */
3616 /* x_... are generic versions in xdisp.c that we, and other terms, get away
3617 with using despite presence in the "system dependent" redisplay
3618 interface. In addition, many of the ns_ methods have code that is
3619 shared with all terms, indicating need for further refactoring. */
3620 extern frame_parm_handler ns_frame_parm_handlers[];
3621 static struct redisplay_interface ns_redisplay_interface =
3623 ns_frame_parm_handlers,
3624 x_produce_glyphs, /*generic OK */
3625 x_write_glyphs, /*generic OK */
3626 x_insert_glyphs, /*generic OK */
3627 x_clear_end_of_line, /*generic OK */
3628 ns_scroll_run, /*23 */
3629 ns_after_update_window_line, /*23: added */
3630 ns_update_window_begin, /*23: split from update_begin */
3631 ns_update_window_end, /*23: split from update_end */
3632 x_cursor_to, /*generic OK */
3634 0, /* flush_display_optional */
3635 x_clear_window_mouse_face, /*generic OK */
3636 x_get_glyph_overhangs, /*23: generic OK */
3637 x_fix_overlapping_area, /*generic OK */
3638 ns_draw_fringe_bitmap, /*23 */
3639 0, /* define_fringe_bitmap */ /* FIXME: simplify ns_draw_fringe_bitmap */
3640 0, /* destroy_fringe_bitmap */
3641 ns_compute_glyph_string_overhangs, /*23 */
3642 ns_draw_glyph_string, /*23: interface to nsfont.m */
3643 ns_define_frame_cursor, /*23 */
3644 ns_clear_frame_area, /*23 */
3645 ns_draw_window_cursor, /*23: revamped ns_dumpcursor */
3646 ns_draw_vertical_window_border,
3647 ns_shift_glyphs_for_insert
3652 ns_delete_display (struct ns_display_info *dpyinfo)
3658 /* This function is called when the last frame on a display is deleted. */
3660 ns_delete_terminal (struct terminal *terminal)
3662 struct ns_display_info *dpyinfo = terminal->display_info.ns;
3665 /* Protect against recursive calls. Fdelete_frame in
3666 delete_terminal calls us back when it deletes our last frame. */
3667 if (!terminal->name)
3672 x_destroy_all_bitmaps (dpyinfo);
3673 ns_delete_display (dpyinfo);
3678 static struct terminal *
3679 ns_create_terminal (struct ns_display_info *dpyinfo)
3680 /* --------------------------------------------------------------------------
3681 Set up use of NS before we make the first connection.
3682 -------------------------------------------------------------------------- */
3684 struct terminal *terminal;
3686 NSTRACE (ns_create_terminal);
3688 terminal = create_terminal ();
3690 terminal->type = output_ns;
3691 terminal->display_info.ns = dpyinfo;
3692 dpyinfo->terminal = terminal;
3694 terminal->rif = &ns_redisplay_interface;
3696 terminal->clear_frame_hook = ns_clear_frame;
3697 terminal->ins_del_lines_hook = 0; /* 23: vestigial? */
3698 terminal->delete_glyphs_hook = 0; /* 23: vestigial? */
3699 terminal->ring_bell_hook = ns_ring_bell;
3700 terminal->reset_terminal_modes_hook = ns_reset_terminal_modes;
3701 terminal->set_terminal_modes_hook = ns_set_terminal_modes;
3702 terminal->update_begin_hook = ns_update_begin;
3703 terminal->update_end_hook = ns_update_end;
3704 terminal->set_terminal_window_hook = NULL; /* 23: vestigial? */
3705 terminal->read_socket_hook = ns_read_socket;
3706 terminal->frame_up_to_date_hook = ns_frame_up_to_date;
3707 terminal->mouse_position_hook = ns_mouse_position;
3708 terminal->frame_rehighlight_hook = ns_frame_rehighlight;
3709 terminal->frame_raise_lower_hook = ns_frame_raise_lower;
3711 terminal->fullscreen_hook = 0; /*XTfullscreen_hook;//23.50 */
3713 terminal->set_vertical_scroll_bar_hook = ns_set_vertical_scroll_bar;
3714 terminal->condemn_scroll_bars_hook = ns_condemn_scroll_bars;
3715 terminal->redeem_scroll_bar_hook = ns_redeem_scroll_bar;
3716 terminal->judge_scroll_bars_hook = ns_judge_scroll_bars;
3718 terminal->delete_frame_hook = x_destroy_window;
3719 terminal->delete_terminal_hook = ns_delete_terminal;
3721 terminal->scroll_region_ok = 1;
3722 terminal->char_ins_del_ok = 1;
3723 terminal->line_ins_del_ok = 1;
3724 terminal->fast_clear_end_of_line = 1;
3725 terminal->memory_below_frame = 0;
3733 /* --------------------------------------------------------------------------
3734 Mainly vestigial under NS now that ns_create_terminal () does most things.
3735 -------------------------------------------------------------------------- */
3738 Fset_input_interrupt_mode (Qt);
3742 struct ns_display_info *
3743 ns_term_init (Lisp_Object display_name)
3744 /* --------------------------------------------------------------------------
3745 Start the Application and get things rolling.
3746 -------------------------------------------------------------------------- */
3748 extern Lisp_Object Fset_input_mode (Lisp_Object, Lisp_Object,
3749 Lisp_Object, Lisp_Object);
3750 struct terminal *terminal;
3751 struct ns_display_info *dpyinfo;
3752 static int ns_initialized = 0;
3755 NSTRACE (ns_term_init);
3757 /* count object allocs (About, click icon); on OS X use ObjectAlloc tool */
3758 /*GSDebugAllocationActive (YES); */
3760 handling_signal = 0;
3762 if (!ns_initialized)
3768 ns_pending_files = [[NSMutableArray alloc] init];
3769 ns_pending_service_names = [[NSMutableArray alloc] init];
3770 ns_pending_service_args = [[NSMutableArray alloc] init];
3772 /* Start app and create the main menu, window, view.
3773 Needs to be here because ns_initialize_display_info () uses AppKit classes.
3774 The view will then ask the NSApp to stop and return to Emacs. */
3775 [EmacsApp sharedApplication];
3778 [NSApp setDelegate: NSApp];
3780 /* debugging: log all notifications */
3781 /* [[NSNotificationCenter defaultCenter] addObserver: NSApp
3782 selector: @selector (logNotification:)
3783 name: nil object: nil]; */
3785 dpyinfo = (struct ns_display_info *)xmalloc (sizeof (struct ns_display_info));
3786 bzero (dpyinfo, sizeof (struct ns_display_info));
3788 ns_initialize_display_info (dpyinfo);
3789 terminal = ns_create_terminal (dpyinfo);
3791 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
3792 init_kboard (terminal->kboard);
3793 terminal->kboard->Vwindow_system = Qns;
3794 terminal->kboard->next_kboard = all_kboards;
3795 all_kboards = terminal->kboard;
3796 /* Don't let the initial kboard remain current longer than necessary.
3797 That would cause problems if a file loaded on startup tries to
3798 prompt in the mini-buffer. */
3799 if (current_kboard == initial_kboard)
3800 current_kboard = terminal->kboard;
3801 terminal->kboard->reference_count++;
3803 dpyinfo->next = x_display_list;
3804 x_display_list = dpyinfo;
3806 /* Put it on ns_display_name_list */
3807 ns_display_name_list = Fcons (Fcons (display_name, Qnil),
3808 ns_display_name_list);
3809 /* ns_display_name_list = Fcons (Fcons (display_name,
3810 Fcons (Qnil, dpyinfo->xrdb)),
3811 ns_display_name_list); */
3812 dpyinfo->name_list_element = XCAR (ns_display_name_list);
3814 /* Set the name of the terminal. */
3815 terminal->name = (char *) xmalloc (SBYTES (display_name) + 1);
3816 strncpy (terminal->name, SDATA (display_name), SBYTES (display_name));
3817 terminal->name[SBYTES (display_name)] = 0;
3821 /* Read various user defaults. */
3822 ns_set_default_prefs ();
3823 ns_default ("AlternateModifier", &ns_alternate_modifier,
3824 Qnil, Qnil, NO, YES);
3825 if (NILP (ns_alternate_modifier))
3826 ns_alternate_modifier = Qmeta;
3827 ns_default ("CommandModifier", &ns_command_modifier,
3828 Qnil, Qnil, NO, YES);
3829 if (NILP (ns_command_modifier))
3830 ns_command_modifier = Qsuper;
3831 ns_default ("ControlModifier", &ns_control_modifier,
3832 Qnil, Qnil, NO, YES);
3833 if (NILP (ns_control_modifier))
3834 ns_control_modifier = Qcontrol;
3835 ns_default ("FunctionModifier", &ns_function_modifier,
3836 Qnil, Qnil, NO, YES);
3837 if (NILP (ns_function_modifier))
3838 ns_function_modifier = Qnone;
3839 ns_default ("ExpandSpace", &ns_expand_space,
3840 make_float (0.5), make_float (0.0), YES, NO);
3841 ns_default ("GSFontAntiAlias", &ns_antialias_text,
3844 ns_default ("AppleAntiAliasingThreshold", &tmp,
3845 make_float (10.0), make_float (6.0), YES, NO);
3846 ns_antialias_threshold = NILP (tmp) ? 10.0 : XFLOATINT (tmp);
3847 ns_default ("UseQuickdrawSmoothing", &ns_use_qd_smoothing,
3849 ns_default ("UseSystemHighlightColor", &ns_use_system_highlight_color,
3851 if (EQ (ns_use_system_highlight_color, Qt))
3853 ns_selection_color = [[NSUserDefaults standardUserDefaults]
3854 stringForKey: @"AppleHighlightColor"];
3855 if (ns_selection_color == nil)
3856 ns_selection_color = NS_SELECTION_COLOR_DEFAULT;
3859 ns_selection_color = NS_SELECTION_COLOR_DEFAULT;
3862 NSColorList *cl = [NSColorList colorListNamed: @"Emacs"];
3866 Lisp_Object color_file, color_map, color;
3871 color_file = Fexpand_file_name (build_string ("rgb.txt"),
3872 Fsymbol_value (intern ("data-directory")));
3873 if (NILP (Ffile_readable_p (color_file)))
3874 fatal ("Could not find %s.\n", SDATA (color_file));
3876 color_map = Fx_load_color_file (color_file);
3877 if (NILP (color_map))
3878 fatal ("Could not read %s.\n", SDATA (color_file));
3880 cl = [[NSColorList alloc] initWithName: @"Emacs"];
3881 for ( ; CONSP (color_map); color_map = XCDR (color_map))
3883 color = XCAR (color_map);
3884 name = SDATA (XCAR (color));
3885 c = XINT (XCDR (color));
3887 [NSColor colorWithCalibratedRed: RED_FROM_ULONG (c) / 255.0
3888 green: GREEN_FROM_ULONG (c) / 255.0
3889 blue: BLUE_FROM_ULONG (c) / 255.0
3891 forKey: [NSString stringWithUTF8String: name]];
3893 [cl writeToFile: nil];
3899 #ifdef NS_IMPL_GNUSTEP
3900 strncpy (c, gnustep_base_version, sizeof (c));
3902 /*PSnextrelease (128, c); */
3903 snprintf (c, sizeof (c), "%g", NSAppKitVersionNumber);
3905 Vwindow_system_version = build_string (c);
3908 delete_keyboard_wait_descriptor (0);
3910 /* Set up OS X app menu */
3911 #ifdef NS_IMPL_COCOA
3915 /* set up the application menu */
3916 svcsMenu = [[EmacsMenu alloc] initWithTitle: @"Services"];
3917 [svcsMenu setAutoenablesItems: NO];
3918 appMenu = [[EmacsMenu alloc] initWithTitle: @"Emacs"];
3919 [appMenu setAutoenablesItems: NO];
3920 mainMenu = [[EmacsMenu alloc] initWithTitle: @""];
3921 dockMenu = [[EmacsMenu alloc] initWithTitle: @""];
3923 [appMenu insertItemWithTitle: @"About Emacs"
3924 action: @selector (orderFrontStandardAboutPanel:)
3927 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 1];
3928 [appMenu insertItemWithTitle: @"Preferences..."
3929 action: @selector (showPreferencesWindow:)
3932 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 3];
3933 item = [appMenu insertItemWithTitle: @"Services"
3934 action: @selector (menuDown:)
3937 [appMenu setSubmenu: svcsMenu forItem: item];
3938 /* [svcsMenu setSupercell: item]; */
3939 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 5];
3940 [appMenu insertItemWithTitle: @"Hide Emacs"
3941 action: @selector (hide:)
3944 item = [appMenu insertItemWithTitle: @"Hide Others"
3945 action: @selector (hideOtherApplications:)
3948 [item setKeyEquivalentModifierMask: NSCommandKeyMask | NSAlternateKeyMask];
3949 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 8];
3950 [appMenu insertItemWithTitle: @"Quit Emacs"
3951 action: @selector (terminate:)
3955 item = [mainMenu insertItemWithTitle: @"Emacs"
3956 action: @selector (menuDown:)
3959 [mainMenu setSubmenu: appMenu forItem: item];
3960 [dockMenu insertItemWithTitle: @"New Frame"
3961 action: @selector (newFrame:)
3965 [NSApp setMainMenu: mainMenu];
3966 [NSApp setAppleMenu: appMenu];
3967 [NSApp setServicesMenu: svcsMenu];
3968 /* Needed at least on Cocoa, to get dock menu to show windows */
3969 [NSApp setWindowsMenu: [[NSMenu alloc] init]];
3971 #endif /* MAC OS X menu setup */
3979 extern Lisp_Object Vauto_save_list_file_name;
3981 ns_term_shutdown (int sig)
3983 /* code not reached in emacs.c after this is called by shut_down_emacs: */
3984 if (STRINGP (Vauto_save_list_file_name))
3985 unlink (SDATA (Vauto_save_list_file_name));
3987 ns_shutdown_properly = YES;
3988 [NSApp terminate: NSApp];
3992 /* ==========================================================================
3994 EmacsApp implementation
3996 ========================================================================== */
3999 @implementation EmacsApp
4001 - (void)logNotification: (NSNotification *)notification
4003 const char *name = [[notification name] UTF8String];
4004 if (!strstr (name, "Update") && !strstr (name, "NSMenu")
4005 && !strstr (name, "WindowNumber"))
4006 NSLog (@"notification: '%@'", [notification name]);
4010 - (void)sendEvent: (NSEvent *)theEvent
4011 /* --------------------------------------------------------------------------
4012 Events posted by ns_send_appdefined interrupt the run loop here
4013 -------------------------------------------------------------------------- */
4015 int type = [theEvent type];
4016 NSWindow *window = [theEvent window];
4017 /* NSTRACE (sendEvent); */
4018 /*fprintf (stderr, "received event of type %d\n", [theEvent type]); */
4020 if (type == NSCursorUpdate && window == nil)
4022 fprintf (stderr, "Dropping external cursor update event.\n");
4026 #ifdef NS_IMPL_COCOA
4027 /* pass mouse down in resize handle and subsequent drags directly to
4028 EmacsWindow so we can generate continuous redisplays */
4031 if (type == NSLeftMouseDragged)
4033 [window mouseDragged: theEvent];
4036 else if (type == NSLeftMouseUp)
4038 [window mouseUp: theEvent];
4042 else if (type == NSLeftMouseDown)
4044 NSRect r = ns_resize_handle_rect (window);
4045 if (NSPointInRect ([theEvent locationInWindow], r))
4048 [window mouseDown: theEvent];
4054 if (type == NSApplicationDefined)
4056 last_appdefined_event = theEvent;
4060 [super sendEvent: theEvent];
4064 - (void)showPreferencesWindow: (id)sender
4066 if (prefsController == nil)
4067 prefsController = [[EmacsPrefsController alloc] init];
4068 [prefsController showForFrame: SELECTED_FRAME ()];
4072 - (void)newFrame: (id)sender
4074 struct frame *emacsframe = SELECTED_FRAME ();
4075 NSEvent *theEvent = [NSApp currentEvent];
4079 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
4080 emacs_event->code = KEY_NS_NEW_FRAME;
4081 emacs_event->modifiers = 0;
4082 EV_TRAILER (theEvent);
4086 /* Open a file (used by below, after going into queue read by ns_read_socket) */
4087 - (BOOL) openFile: (NSString *)fileName
4089 struct frame *emacsframe = SELECTED_FRAME ();
4090 NSEvent *theEvent = [NSApp currentEvent];
4095 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
4096 emacs_event->code = KEY_NS_OPEN_FILE_LINE;
4097 ns_input_file = append2 (ns_input_file, build_string ([fileName UTF8String]));
4098 ns_input_line = Qnil; /* can be start or cons start,end */
4099 emacs_event->modifiers =0;
4100 EV_TRAILER (theEvent);
4106 /* **************************************************************************
4108 EmacsApp delegate implementation
4110 ************************************************************************** */
4112 - (void)applicationDidFinishLaunching: (NSNotification *)notification
4113 /* --------------------------------------------------------------------------
4114 When application is loaded, terminate event loop in ns_term_init
4115 -------------------------------------------------------------------------- */
4117 NSTRACE (applicationDidFinishLaunching);
4118 [NSApp setServicesProvider: NSApp];
4119 ns_send_appdefined (-2);
4123 - (void) terminate: (id)sender
4126 if (ns_shutdown_properly)
4127 [super terminate: sender];
4130 /* Fkill_emacs (Qnil); */
4131 ns_shutdown_properly = YES;
4132 Feval (Fcons (intern ("save-buffers-kill-emacs"), Qnil));
4138 - (NSApplicationTerminateReply)applicationShouldTerminate: (id)sender
4140 if (ns_shutdown_properly)
4141 return NSTerminateNow;
4143 Lisp_Object contents = list3 (build_string ("Exit requested. Would you like to Save Buffers and Exit, or Cancel the request?"),
4144 Fcons (build_string ("Cancel"), Qnil),
4145 Fcons (build_string ("Save and Exit"), Qt));
4146 Lisp_Object res = ns_popup_dialog (Qt, contents, Qnil);
4147 fprintf (stderr, "res = %d\n", EQ (res, Qt)); /* FIXME */
4150 Feval (Fcons (intern ("save-buffers-kill-emacs"), Qnil));
4151 return NSTerminateNow;
4153 return NSTerminateCancel;
4157 /* Notification from the Workspace to open a file */
4158 - (BOOL)application: sender openFile: (NSString *)file
4160 [ns_pending_files addObject: file];
4165 /* Open a file as a temporary file */
4166 - (BOOL)application: sender openTempFile: (NSString *)file
4168 [ns_pending_files addObject: file];
4173 /* Notification from the Workspace to open a file noninteractively (?) */
4174 - (BOOL)application: sender openFileWithoutUI: (NSString *)file
4176 [ns_pending_files addObject: file];
4181 /* Notification from the Workspace to open multiple files */
4182 - (void)application: sender openFiles: (NSArray *)fileList
4184 NSEnumerator *files = [fileList objectEnumerator];
4186 while ((file = [files nextObject]) != nil)
4187 [ns_pending_files addObject: file];
4189 /* TODO: when GNUstep implements this (and we require that version of
4190 GNUstep), remove. */
4191 #ifndef NS_IMPL_GNUSTEP
4192 [self replyToOpenOrPrint: NSApplicationDelegateReplySuccess];
4193 #endif /* !NS_IMPL_GNUSTEP */
4198 /* Handle dock menu requests. */
4199 - (NSMenu *)applicationDockMenu: (NSApplication *) sender
4205 /* TODO: these may help w/IO switching btwn terminal and NSApp */
4206 - (void)applicationDidBecomeActive: (NSNotification *)notification
4209 - (void)applicationDidResignActive: (NSNotification *)notification
4211 ns_send_appdefined (-1);
4216 /* ==========================================================================
4218 EmacsApp aux handlers for managing event loop
4220 ========================================================================== */
4223 - (void)timeout_handler: (NSTimer *)timedEntry
4224 /* --------------------------------------------------------------------------
4225 The timeout specified to ns_select has passed.
4226 -------------------------------------------------------------------------- */
4228 /*NSTRACE (timeout_handler); */
4229 ns_send_appdefined (-2);
4232 extern void update_window_cursor (struct window *w, int on);
4234 - (void)fd_handler: (NSTimer *) fdEntry
4235 /* --------------------------------------------------------------------------
4236 Check data waiting on file descriptors and terminate if so
4237 -------------------------------------------------------------------------- */
4240 /* NSTRACE (fd_handler); */
4242 if (select_nfds == 0)
4245 memcpy (&t_readfds, &select_readfds, sizeof (fd_set));
4247 select_timeout.tv_sec = select_timeout.tv_usec = 0;
4248 result = select (select_nfds, &t_readfds, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
4252 memcpy (&select_readfds, &t_readfds, sizeof (fd_set));
4253 ns_send_appdefined (result);
4259 /* ==========================================================================
4263 ========================================================================== */
4265 /* called from system: queue for next pass through event loop */
4266 - (void)requestService: (NSPasteboard *)pboard
4267 userData: (NSString *)userData
4268 error: (NSString **)error
4270 [ns_pending_service_names addObject: userData];
4271 [ns_pending_service_args addObject: [NSString stringWithUTF8String:
4272 SDATA (ns_string_from_pasteboard (pboard))]];
4276 /* called from ns_read_socket to clear queue */
4277 - (BOOL)fulfillService: (NSString *)name withArg: (NSString *)arg
4279 struct frame *emacsframe = SELECTED_FRAME ();
4280 NSEvent *theEvent = [NSApp currentEvent];
4285 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
4286 emacs_event->code = KEY_NS_SPI_SERVICE_CALL;
4287 ns_input_spi_name = build_string ([name UTF8String]);
4288 ns_input_spi_arg = build_string ([arg UTF8String]);
4289 emacs_event->modifiers = EV_MODIFIERS (theEvent);
4290 EV_TRAILER (theEvent);
4300 /* ==========================================================================
4302 EmacsView implementation
4304 ========================================================================== */
4307 @implementation EmacsView
4309 /* needed to inform when window closed from LISP */
4310 - (void) setWindowClosing: (BOOL)closing
4312 windowClosing = closing;
4318 NSTRACE (EmacsView_dealloc);
4324 /* called on font panel selection */
4325 - (void)changeFont: (id)sender
4327 NSEvent *e =[[self window] currentEvent];
4328 struct face *face =FRAME_DEFAULT_FACE (emacsframe);
4332 NSTRACE (changeFont);
4336 if (newFont = [sender convertFont:
4337 ((struct nsfont_info *)face->font)->nsfont])
4339 SET_FRAME_GARBAGED (emacsframe); /* now needed as of 2008/10 */
4341 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
4342 emacs_event->modifiers = 0;
4343 emacs_event->code = KEY_NS_CHANGE_FONT;
4345 size = [newFont pointSize];
4346 ns_input_fontsize = make_number (lrint (size));
4347 ns_input_font = build_string ([[newFont familyName] UTF8String]);
4353 - (BOOL)acceptsFirstResponder
4355 NSTRACE (acceptsFirstResponder);
4360 - (void)resetCursorRects
4362 NSRect visible = [self visibleRect];
4363 NSCursor *currentCursor = FRAME_POINTER_TYPE (emacsframe);
4364 NSTRACE (resetCursorRects);
4366 if (currentCursor == nil)
4367 currentCursor = [NSCursor arrowCursor];
4369 if (!NSIsEmptyRect (visible))
4370 [self addCursorRect: visible cursor: currentCursor];
4371 [currentCursor setOnMouseEntered: YES];
4375 /*****************************************************************************/
4376 /* Keyboard handling. */
4379 - (void)keyDown: (NSEvent *)theEvent
4381 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe);
4383 unsigned fnKeysym = 0;
4385 static NSMutableArray *nsEvArray;
4386 static BOOL firstTime = YES;
4390 /* Rhapsody and OS X give up and down events for the arrow keys */
4391 if ([theEvent type] != NSKeyDown)
4397 if (![[self window] isKeyWindow])
4399 /* XXX: Using NO_SOCK_SIGIO like Carbon causes a condition in which,
4400 when Emacs display updates a different frame from the current one,
4401 and temporarily selects it, then processes some interrupt-driven
4402 input (dispnew.c:3878), OS will send the event to the correct NSWindow,
4403 but for some reason that window has its first responder set to the
4404 NSView most recently updated (I guess), which is not the correct one.
4405 UPDATE: After multi-TTY merge this happens even w/o NO_SOCK_SIGIO */
4406 if ([[theEvent window] isKindOfClass: [EmacsWindow class]])
4407 [(EmacsView *)[[theEvent window] delegate] keyDown: theEvent];
4411 if (nsEvArray == nil)
4412 nsEvArray = [[NSMutableArray alloc] initWithCapacity: 1];
4414 [NSCursor setHiddenUntilMouseMoves: YES];
4416 if (dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
4418 clear_mouse_face (dpyinfo);
4419 dpyinfo->mouse_face_hidden = 1;
4422 if (!processingCompose)
4424 code = ([[theEvent charactersIgnoringModifiers] length] == 0) ?
4425 0 : [[theEvent charactersIgnoringModifiers] characterAtIndex: 0];
4426 /* (Carbon way: [theEvent keyCode]) */
4428 /* is it a "function key"? */
4429 fnKeysym = ns_convert_key (code);
4432 /* COUNTERHACK: map 'Delete' on upper-right main KB to 'Backspace',
4433 because Emacs treats Delete and KP-Delete same (in simple.el). */
4434 if (fnKeysym == 0xFFFF && [theEvent keyCode] == 0x33)
4435 code = 0xFF08; /* backspace */
4440 /* are there modifiers? */
4441 emacs_event->modifiers = 0;
4442 flags = [theEvent modifierFlags];
4444 if (flags & NSHelpKeyMask)
4445 emacs_event->modifiers |= hyper_modifier;
4447 if (flags & NSShiftKeyMask)
4448 emacs_event->modifiers |= shift_modifier;
4450 if (flags & NSCommandKeyMask)
4452 emacs_event->modifiers |= parse_solitary_modifier (ns_command_modifier);
4453 /* if super (default), take input manager's word so things like
4454 dvorak / qwerty layout work */
4455 if (EQ (ns_command_modifier, Qsuper)
4457 && [[theEvent characters] length] != 0)
4459 /* XXX: the code we get will be unshifted, so if we have
4460 a shift modifier, must convert ourselves */
4461 if (!(flags & NSShiftKeyMask))
4462 code = [[theEvent characters] characterAtIndex: 0];
4464 /* this is ugly and also requires linking w/Carbon framework
4465 (for LMGetKbdType) so for now leave this rare (?) case
4466 undealt with.. in future look into CGEvent methods */
4469 long smv = GetScriptManagerVariable (smKeyScript);
4470 Handle uchrHandle = GetResource
4471 ('uchr', GetScriptVariable (smv, smScriptKeys));
4473 UCKeyTranslate ((UCKeyboardLayout*)*uchrHandle,
4474 [[theEvent characters] characterAtIndex: 0],
4475 kUCKeyActionDisplay,
4476 (flags & ~NSCommandKeyMask) >> 8,
4477 LMGetKbdType (), kUCKeyTranslateNoDeadKeysMask,
4478 &dummy, 1, &dummy, &code);
4485 if (flags & NSControlKeyMask)
4486 emacs_event->modifiers |= parse_solitary_modifier (ns_control_modifier);
4488 if (flags & NS_FUNCTION_KEY_MASK && !fnKeysym)
4489 emacs_event->modifiers |= parse_solitary_modifier (ns_function_modifier);
4491 if (flags & NSAlternateKeyMask) /* default = meta */
4493 if (EQ (ns_alternate_modifier, Qnone) && !fnKeysym)
4494 { /* accept pre-interp alt comb */
4495 if ([[theEvent characters] length] > 0)
4496 code = [[theEvent characters] characterAtIndex: 0];
4497 /*HACK: clear lone shift modifier to stop next if from firing */
4498 if (emacs_event->modifiers == shift_modifier)
4499 emacs_event->modifiers = 0;
4502 emacs_event->modifiers |= parse_solitary_modifier (ns_alternate_modifier);
4505 /*fprintf (stderr,"code =%x\tfnKey =%x\tflags = %x\tmods = %x\n",code,fnKeysym,flags,emacs_event->modifiers); */
4507 /* if it was a function key or had modifiers, pass it directly to emacs */
4508 if (fnKeysym || (emacs_event->modifiers
4509 && [[theEvent charactersIgnoringModifiers] length] > 0))
4510 /*[[theEvent characters] length] */
4512 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
4514 code |= (1<<28)|(3<<16);
4515 else if (code == 0x7f)
4516 code |= (1<<28)|(3<<16);
4518 emacs_event->kind = code > 0xFF
4519 ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT;
4521 emacs_event->code = code;
4522 EV_TRAILER (theEvent);
4527 /* if we get here we should send the key for input manager processing */
4528 if (firstTime && [[NSInputManager currentInputManager]
4529 wantsToDelayTextChangeNotifications] == NO)
4531 "Emacs: WARNING: TextInput mgr wants marked text to be permanent!\n");
4534 if (NS_KEYLOG && !processingCompose)
4535 fprintf (stderr, "Begin compose sequence.\n");
4537 processingCompose = YES;
4538 [nsEvArray addObject: theEvent];
4539 [self interpretKeyEvents: nsEvArray];
4540 [nsEvArray removeObject: theEvent];
4544 /* <NSTextInput> implementation (called through super interpretKeyEvents:]). */
4547 /* <NSTextInput>: called through when done composing */
4548 - (void)insertText: (id)aString
4551 int len = [(NSString *)aString length];
4554 if (NS_KEYLOG) NSLog (@"insertText '%@'\tlen = %d", aString, len);
4555 processingCompose = NO;
4560 /* first, clear any working text */
4561 if (workingText != nil)
4562 [self deleteWorkingText];
4564 /* now insert the string as keystrokes */
4565 for (i =0; i<len; i++)
4567 code = [aString characterAtIndex: i];
4568 /* TODO: still need this? */
4570 code = '~'; /* 0x7E */
4571 emacs_event->modifiers = 0;
4573 = code > 0xFF ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT;
4574 emacs_event->code = code;
4575 EV_TRAILER ((id)nil);
4580 /* <NSTextInput>: inserts display of composing characters */
4581 - (void)setMarkedText: (id)aString selectedRange: (NSRange)selRange
4583 NSString *str = [aString respondsToSelector: @selector (string)] ?
4584 [aString string] : aString;
4586 NSLog (@"setMarkedText '%@' len =%d range %d from %d", str, [str length],
4587 selRange.length, selRange.location);
4589 if (workingText != nil)
4590 [self deleteWorkingText];
4591 if ([str length] == 0)
4597 processingCompose = YES;
4598 workingText = [str copy];
4599 ns_working_text = build_string ([workingText UTF8String]);
4601 /* if in "echo area", not true minibuffer, can't show chars in interactive
4602 mode, so call using eval; otherwise we send a key event, which was the
4603 original way this was done */
4604 if (!EQ (Feval (Fcons (intern ("ns-in-echo-area"), Qnil)), Qnil))
4606 Feval (Fcons (intern ("ns-echo-working-text"), Qnil));
4607 ns_send_appdefined (-1);
4611 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
4612 emacs_event->code = KEY_NS_INSERT_WORKING_TEXT;
4613 EV_TRAILER ((id)nil);
4618 /* delete display of composing characters [not in <NSTextInput>] */
4619 - (void)deleteWorkingText
4621 if (workingText == nil)
4624 fprintf (stderr, "deleteWorkingText len =%d\n", [workingText length]);
4625 [workingText release];
4627 processingCompose = NO;
4632 if (!EQ (Feval (Fcons (intern ("ns-in-echo-area"), Qnil)), Qnil))
4634 Feval (Fcons (intern ("ns-unecho-working-text"), Qnil));
4635 ns_send_appdefined (-1);
4639 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
4640 emacs_event->code = KEY_NS_DELETE_WORKING_TEXT;
4641 EV_TRAILER ((id)nil);
4646 - (BOOL)hasMarkedText
4648 return workingText != nil;
4651 - (NSRange)markedRange
4653 NSRange rng = workingText != nil
4654 ? NSMakeRange (0, [workingText length]) : NSMakeRange (NSNotFound, 0);
4655 if (NS_KEYLOG) NSLog (@"markedRange request");
4661 if (NS_KEYLOG) NSLog (@"unmark (accept) text");
4662 [self deleteWorkingText];
4663 processingCompose = NO;
4666 /* used to position char selection windows, etc. */
4667 - (NSRect)firstRectForCharacterRange: (NSRange)theRange
4671 struct window *win = XWINDOW (FRAME_SELECTED_WINDOW (emacsframe));
4672 if (NS_KEYLOG) NSLog (@"firstRectForCharRange request");
4674 rect.size.width = theRange.length * FRAME_COLUMN_WIDTH (emacsframe);
4675 rect.size.height = FRAME_LINE_HEIGHT (emacsframe);
4676 pt.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (win, win->phys_cursor.x);
4677 pt.y = WINDOW_TO_FRAME_PIXEL_Y (win, win->phys_cursor.y
4678 +FRAME_LINE_HEIGHT (emacsframe));
4680 pt = [self convertPoint: pt toView: nil];
4681 pt = [[self window] convertBaseToScreen: pt];
4686 - (NSInteger)conversationIdentifier
4688 return (NSInteger)self;
4691 /* TODO: below here not yet implemented correctly, but may not be needed */
4693 - (void)doCommandBySelector: (SEL)aSelector
4695 if (NS_KEYLOG) NSLog (@"Do command by selector: %@",
4696 NSStringFromSelector (aSelector));
4698 if (aSelector == @selector (deleteBackward:))
4700 /* happens when user backspaces over an ongoing composition:
4701 throw a 'delete' into the event queue */
4704 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
4705 emacs_event->code = 0xFF08;
4706 EV_TRAILER ((id)nil);
4710 - (NSArray *)validAttributesForMarkedText
4712 static NSArray *arr = nil;
4713 if (arr == nil) arr = [NSArray new];
4714 /* [[NSArray arrayWithObject: NSUnderlineStyleAttributeName] retain]; */
4718 - (NSRange)selectedRange
4720 if (NS_KEYLOG) NSLog (@"selectedRange request");
4721 return NSMakeRange (NSNotFound, 0);
4724 - (unsigned int)characterIndexForPoint: (NSPoint)thePoint
4726 if (NS_KEYLOG) NSLog (@"characterIndexForPoint request");
4730 - (NSAttributedString *)attributedSubstringFromRange: (NSRange)theRange
4732 static NSAttributedString *str = nil;
4733 if (str == nil) str = [NSAttributedString new];
4734 if (NS_KEYLOG) NSLog (@"attributedSubstringFromRange request");
4738 /* End <NSTextInput> impl. */
4739 /*****************************************************************************/
4742 /* This is what happens when the user presses a mouse button. */
4743 - (void)mouseDown: (NSEvent *)theEvent
4745 NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil];
4748 NSTRACE (mouseDown);
4750 [self deleteWorkingText];
4755 last_mouse_frame = emacsframe;
4756 /* appears to be needed to prevent spurious movement events generated on
4758 last_mouse_frame->mouse_moved = 0;
4760 if ([theEvent type] == NSScrollWheel)
4762 float delta = [theEvent deltaY];
4763 /* Mac notebooks send wheel events w/delta =0 when trackpad scrolling */
4766 emacs_event->kind = WHEEL_EVENT;
4767 emacs_event->code = 0;
4768 emacs_event->modifiers = EV_MODIFIERS (theEvent) |
4769 ((delta > 0) ? up_modifier : down_modifier);
4773 emacs_event->kind = MOUSE_CLICK_EVENT;
4774 emacs_event->code = EV_BUTTON (theEvent);
4775 emacs_event->modifiers = EV_MODIFIERS (theEvent)
4776 | EV_UDMODIFIERS (theEvent);
4778 XSETINT (emacs_event->x, lrint (p.x));
4779 XSETINT (emacs_event->y, lrint (p.y));
4780 EV_TRAILER (theEvent);
4784 - (void)rightMouseDown: (NSEvent *)theEvent
4786 NSTRACE (rightMouseDown);
4787 [self mouseDown: theEvent];
4791 - (void)otherMouseDown: (NSEvent *)theEvent
4793 NSTRACE (otherMouseDown);
4794 [self mouseDown: theEvent];
4798 - (void)mouseUp: (NSEvent *)theEvent
4801 [self mouseDown: theEvent];
4805 - (void)rightMouseUp: (NSEvent *)theEvent
4807 NSTRACE (rightMouseUp);
4808 [self mouseDown: theEvent];
4812 - (void)otherMouseUp: (NSEvent *)theEvent
4814 NSTRACE (otherMouseUp);
4815 [self mouseDown: theEvent];
4819 - (void) scrollWheel: (NSEvent *)theEvent
4821 NSTRACE (scrollWheel);
4822 [self mouseDown: theEvent];
4826 /* Tell emacs the mouse has moved. */
4827 - (void)mouseMoved: (NSEvent *)e
4829 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe);
4832 // NSTRACE (mouseMoved);
4834 last_mouse_movement_time = EV_TIMESTAMP (e);
4835 last_mouse_motion_position
4836 = [self convertPoint: [e locationInWindow] fromView: nil];
4838 /* update any mouse face */
4839 if (dpyinfo->mouse_face_hidden)
4841 dpyinfo->mouse_face_hidden = 0;
4842 clear_mouse_face (dpyinfo);
4845 /* tooltip handling */
4846 previous_help_echo_string = help_echo_string;
4847 help_echo_string = Qnil;
4849 if (!note_mouse_movement (emacsframe, last_mouse_motion_position.x,
4850 last_mouse_motion_position.y))
4851 help_echo_string = previous_help_echo_string;
4853 XSETFRAME (frame, emacsframe);
4854 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
4856 /* NOTE: help_echo_{window,pos,object} are set in xdisp.c
4857 (note_mouse_highlight), which is called through the
4858 note_mouse_movement () call above */
4859 gen_help_event (help_echo_string, frame, help_echo_window,
4860 help_echo_object, help_echo_pos);
4864 help_echo_string = Qnil;
4865 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
4868 if (emacsframe->mouse_moved && send_appdefined)
4869 ns_send_appdefined (-1);
4873 - (void)mouseDragged: (NSEvent *)e
4875 NSTRACE (mouseDragged);
4876 [self mouseMoved: e];
4880 - (void)rightMouseDragged: (NSEvent *)e
4882 NSTRACE (rightMouseDragged);
4883 [self mouseMoved: e];
4887 - (void)otherMouseDragged: (NSEvent *)e
4889 NSTRACE (otherMouseDragged);
4890 [self mouseMoved: e];
4894 - (BOOL)windowShouldClose: (id)sender
4896 NSEvent *e =[[self window] currentEvent];
4898 NSTRACE (windowShouldClose);
4899 windowClosing = YES;
4902 emacs_event->kind = DELETE_WINDOW_EVENT;
4903 emacs_event->modifiers = 0;
4904 emacs_event->code = 0;
4906 /* Don't close this window, let this be done from lisp code. */
4911 - (NSSize)windowWillResize: (NSWindow *)sender toSize: (NSSize)frameSize
4912 /* normalize frame to gridded text size */
4914 NSTRACE (windowWillResize);
4915 /*fprintf (stderr,"Window will resize: %.0f x %.0f\n",frameSize.width,frameSize.height); */
4917 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe,
4918 #ifdef NS_IMPL_GNUSTEP
4919 frameSize.width + 3);
4923 if (cols < MINWIDTH)
4925 frameSize.width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (emacsframe, cols);
4927 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe, frameSize.height
4928 #ifdef NS_IMPL_GNUSTEP
4929 - FRAME_NS_TITLEBAR_HEIGHT (emacsframe) + 3
4930 - FRAME_NS_TOOLBAR_HEIGHT (emacsframe));
4932 - FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
4933 - FRAME_NS_TOOLBAR_HEIGHT (emacsframe));
4935 if (rows < MINHEIGHT)
4937 frameSize.height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (emacsframe, rows)
4938 + FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
4939 + FRAME_NS_TOOLBAR_HEIGHT (emacsframe);
4940 #ifdef NS_IMPL_COCOA
4942 /* this sets window title to have size in it; the wm does this under GS */
4943 NSRect r = [[self window] frame];
4944 if (r.size.height == frameSize.height && r.size.width == frameSize.width)
4955 NSWindow *window = [self window];
4958 const char *t = [[[self window] title] UTF8String];
4959 char *pos = strstr (t, " — ");
4962 old_title = (char *) xmalloc (strlen (t) + 1);
4963 strcpy (old_title, t);
4965 size_title = xmalloc (strlen (old_title) + 40);
4966 sprintf (size_title, "%s — (%d x %d)", old_title, cols, rows);
4967 [window setTitle: [NSString stringWithUTF8String: size_title]];
4972 #endif /* NS_IMPL_COCOA */
4973 /*fprintf (stderr," ...size became %.0f x %.0f (%d x %d)\n",frameSize.width,frameSize.height,cols,rows); */
4979 - (void)windowDidResize: (NSNotification *)notification
4981 NSWindow *theWindow = [notification object];
4983 #ifdef NS_IMPL_GNUSTEP
4984 /* in GNUstep, at least currently, it's possible to get a didResize
4985 without getting a willResize.. therefore we need to act as if we got
4986 the willResize now */
4987 NSSize sz = [theWindow frame].size;
4988 sz = [self windowWillResize: theWindow toSize: sz];
4989 #endif /* NS_IMPL_GNUSTEP */
4991 NSTRACE (windowDidResize);
4992 /*fprintf (stderr,"windowDidResize: %.0f\n",[theWindow frame].size.height); */
4994 #ifdef NS_IMPL_COCOA
5000 #endif /* NS_IMPL_COCOA */
5002 if (cols > 0 && rows > 0)
5003 x_set_window_size (emacsframe, 0, cols, rows);
5005 ns_send_appdefined (-1);
5007 /* The following line causes a crash on GNUstep. Adrian Robert
5008 says he doesn't remember why he added this line, but removing it
5009 doesn't seem to cause problems on OSX, either. */
5016 - (void)windowDidBecomeKey: (NSNotification *)notification
5017 /* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
5019 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe);
5020 struct frame *old_focus = dpyinfo->x_focus_frame;
5022 NSTRACE (windowDidBecomeKey);
5024 if (emacsframe != old_focus)
5025 dpyinfo->x_focus_frame = emacsframe;
5027 ns_frame_rehighlight (emacsframe);
5031 emacs_event->kind = FOCUS_IN_EVENT;
5032 EV_TRAILER ((id)nil);
5037 - (void)windowDidResignKey: (NSNotification *)notification
5038 /* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
5040 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe);
5041 NSTRACE (windowDidResignKey);
5043 if (dpyinfo->x_focus_frame == emacsframe)
5044 dpyinfo->x_focus_frame = 0;
5046 ns_frame_rehighlight (emacsframe);
5048 /* FIXME: for some reason needed on second and subsequent clicks away
5049 from sole-frame Emacs to get hollow box to show */
5050 if (!windowClosing && [[self window] isVisible] == YES)
5052 x_update_cursor (emacsframe, 1);
5053 x_set_frame_alpha (emacsframe);
5058 [self deleteWorkingText];
5059 emacs_event->kind = FOCUS_IN_EVENT;
5060 EV_TRAILER ((id)nil);
5065 - (void)windowWillMiniaturize: sender
5067 NSTRACE (windowWillMiniaturize);
5083 - initFrameFromEmacs: (struct frame *)f
5088 NSButton *toggleButton;
5089 int vbextra = NS_SCROLL_BAR_WIDTH (f);
5094 NSTRACE (initFrameFromEmacs);
5097 processingCompose = NO;
5098 scrollbarsNeedingUpdate = 0;
5100 /*fprintf (stderr,"init with %d, %d\n",f->text_cols, f->text_lines); */
5102 r = NSMakeRect (0, 0, FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, f->text_cols),
5103 FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, f->text_lines));
5104 [self initWithFrame: r];
5106 FRAME_NS_VIEW (f) = self;
5110 win = [[EmacsWindow alloc]
5111 initWithContentRect: r
5112 styleMask: (NSResizableWindowMask |
5113 NSMiniaturizableWindowMask |
5114 NSClosableWindowMask)
5115 backing: NSBackingStoreBuffered
5119 f->border_width = wr.size.width - r.size.width;
5120 FRAME_NS_TITLEBAR_HEIGHT (f) = wr.size.height - r.size.height;
5122 [win setAcceptsMouseMovedEvents: YES];
5123 [win setDelegate: self];
5124 [win useOptimizedDrawing: YES];
5126 sz.width = FRAME_COLUMN_WIDTH (f);
5127 sz.height = FRAME_LINE_HEIGHT (f);
5128 [win setResizeIncrements: sz];
5130 [[win contentView] addSubview: self];
5133 [self registerForDraggedTypes: ns_drag_types];
5136 name = [NSString stringWithUTF8String:
5137 NILP (tem) ? (unsigned char *)"Emacs" : SDATA (tem)];
5138 [win setTitle: name];
5140 /* toolbar support */
5141 toolbar = [[EmacsToolbar alloc] initForView: self withIdentifier:
5142 [NSString stringWithFormat: @"Emacs Frame %d",
5144 [win setToolbar: toolbar];
5145 [toolbar setVisible: NO];
5146 #ifdef NS_IMPL_COCOA
5147 toggleButton = [win standardWindowButton: NSWindowToolbarButton];
5148 [toggleButton setTarget: self];
5149 [toggleButton setAction: @selector (toggleToolbar: )];
5151 FRAME_NS_TOOLBAR_HEIGHT (f) = 0;
5155 [win setMiniwindowTitle:
5156 [NSString stringWithUTF8String: SDATA (tem)]];
5159 NSScreen *screen = [win screen];
5162 [win setFrameTopLeftPoint: NSMakePoint
5163 (IN_BOUND (-SCREENMAX, f->left_pos, SCREENMAX),
5164 IN_BOUND (-SCREENMAX,
5165 [screen frame].size.height - NS_TOP_POS (f), SCREENMAX))];
5168 [win makeFirstResponder: self];
5170 col = ns_lookup_indexed_color (NS_FACE_BACKGROUND
5171 (FRAME_DEFAULT_FACE (emacsframe)), emacsframe);
5172 [win setBackgroundColor: col];
5173 if ([col alphaComponent] != 1.0)
5174 [win setOpaque: NO];
5176 [self allocateGState];
5183 - (void)windowDidMove: sender
5185 NSWindow *win = [self window];
5186 NSRect r = [win frame];
5187 NSScreen *screen = [win screen];
5188 NSRect sr = [screen frame];
5190 NSTRACE (windowDidMove);
5192 if (!emacsframe->output_data.ns)
5196 emacsframe->left_pos = r.origin.x; /* - sr.origin.x; */
5197 emacsframe->top_pos = sr.size.height -
5198 (r.origin.y + r.size.height); /* + sr.origin.y; */
5202 #ifdef NS_IMPL_COCOA
5203 /* if we don't do this manually, the window will resize but not move */
5204 - (BOOL)windowShouldZoom: (NSWindow *)sender toFrame: (NSRect)newFrame
5206 [[self window] setFrame: newFrame display: NO];
5211 /* Implement this to control size of frame on zoom.
5212 - (NSRect)windowWillUseStandardFrame:(NSWindow *)sender
5213 defaultFrame:(NSRect)defaultFrame; */
5216 - (void)windowDidDeminiaturize: sender
5218 NSTRACE (windowDidDeminiaturize);
5219 if (!emacsframe->output_data.ns)
5221 emacsframe->async_visible = 1;
5222 emacsframe->async_iconified = 0;
5223 windows_or_buffers_changed++;
5227 emacs_event->kind = ICONIFY_EVENT;
5228 EV_TRAILER ((id)nil);
5233 - (void)windowDidExpose: sender
5235 NSTRACE (windowDidExpose);
5236 if (!emacsframe->output_data.ns)
5238 emacsframe->async_visible = 1;
5239 SET_FRAME_GARBAGED (emacsframe);
5241 if (send_appdefined)
5242 ns_send_appdefined (-1);
5246 - (void)windowDidMiniaturize: sender
5248 NSTRACE (windowDidMiniaturize);
5249 if (!emacsframe->output_data.ns)
5252 emacsframe->async_iconified = 1;
5256 emacs_event->kind = ICONIFY_EVENT;
5257 EV_TRAILER ((id)nil);
5262 - (void)mouseEntered: (NSEvent *)theEvent
5264 NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil];
5265 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe);
5266 NSTRACE (mouseEntered);
5268 last_mouse_movement_time = EV_TIMESTAMP (theEvent);
5272 - (void)mouseExited: (NSEvent *)theEvent
5274 NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil];
5276 struct ns_display_info *dpyinfo
5277 = emacsframe ? FRAME_NS_DISPLAY_INFO (emacsframe) : NULL;
5279 NSTRACE (mouseExited);
5281 if (dpyinfo || !emacsframe)
5284 last_mouse_movement_time = EV_TIMESTAMP (theEvent);
5286 if (emacsframe == dpyinfo->mouse_face_mouse_frame)
5288 clear_mouse_face (dpyinfo);
5289 dpyinfo->mouse_face_mouse_frame = 0;
5297 if (context_menu_value == -1)
5298 context_menu_value = [sender tag];
5300 find_and_call_menu_selection (emacsframe, emacsframe->menu_bar_items_used,
5301 emacsframe->menu_bar_vector,
5302 (void *)[sender tag]);
5303 ns_send_appdefined (-1);
5308 - (EmacsToolbar *)toolbar
5314 /* this gets called on toolbar button click */
5315 - toolbarClicked: (id)item
5318 int idx = [item tag] * TOOL_BAR_ITEM_NSLOTS;
5320 NSTRACE (toolbarClicked);
5325 /* send first event (for some reason two needed) */
5326 theEvent =[[self window] currentEvent];
5327 emacs_event->kind = TOOL_BAR_EVENT;
5328 XSETFRAME (emacs_event->arg, emacsframe);
5329 EV_TRAILER (theEvent);
5331 emacs_event->kind = TOOL_BAR_EVENT;
5332 /* XSETINT (emacs_event->code, 0); */
5333 emacs_event->arg = AREF (emacsframe->tool_bar_items,
5334 idx + TOOL_BAR_ITEM_KEY);
5335 emacs_event->modifiers = EV_MODIFIERS (theEvent);
5336 EV_TRAILER (theEvent);
5341 - toggleToolbar: (id)sender
5343 Lisp_Object lispFrame;
5344 XSETFRAME (lispFrame, emacsframe);
5345 Feval (Fcons (intern ("ns-toggle-toolbar"), Fcons (lispFrame, Qnil)));
5346 SET_FRAME_GARBAGED (emacsframe);
5347 ns_send_appdefined (-1);
5351 - (void)drawRect: (NSRect)rect
5353 int x = NSMinX (rect), y = NSMinY (rect);
5354 int width = NSWidth (rect), height = NSHeight (rect);
5358 if (!emacsframe || !emacsframe->output_data.ns)
5362 ns_clear_frame_area (emacsframe, x, y, width, height);
5363 expose_frame (emacsframe, x, y, width, height);
5365 emacsframe->async_visible = 1;
5366 emacsframe->async_iconified = 0;
5368 /* SET_FRAME_GARBAGED (emacsframe);
5369 ns_send_appdefined (-1); */
5373 /* NSDraggingDestination protocol methods. Actually this is not really a
5374 protocol, but a category of Object. O well... */
5376 -(unsigned int) draggingEntered: (id <NSDraggingInfo>) sender
5378 NSTRACE (draggingEntered);
5379 return NSDragOperationGeneric;
5383 -(BOOL)prepareForDragOperation: (id <NSDraggingInfo>) sender
5389 -(BOOL)performDragOperation: (id <NSDraggingInfo>) sender
5394 NSEvent *theEvent = [[self window] currentEvent];
5397 NSTRACE (performDragOperation);
5402 position = [self convertPoint: [sender draggingLocation] fromView: nil];
5403 x = lrint (position.x); y = lrint (position.y);
5405 pb = [sender draggingPasteboard];
5406 type = [pb availableTypeFromArray: ns_drag_types];
5411 else if ([type isEqualToString: NSFilenamesPboardType])
5414 NSEnumerator *fenum;
5417 if (!(files = [pb propertyListForType: type]))
5420 fenum = [files objectEnumerator];
5421 while ( (file = [fenum nextObject]) )
5423 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
5424 emacs_event->code = KEY_NS_DRAG_FILE;
5425 XSETINT (emacs_event->x, x);
5426 XSETINT (emacs_event->y, y);
5427 ns_input_file = append2 (ns_input_file,
5428 build_string ([file UTF8String]));
5429 emacs_event->modifiers = EV_MODIFIERS (theEvent);
5430 EV_TRAILER (theEvent);
5434 else if ([type isEqualToString: NSURLPboardType])
5439 if (!(fileURL = [NSURL URLFromPasteboard: pb]) ||
5440 [fileURL isFileURL] == NO)
5443 file = [fileURL path];
5444 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
5445 emacs_event->code = KEY_NS_DRAG_FILE;
5446 XSETINT (emacs_event->x, x);
5447 XSETINT (emacs_event->y, y);
5448 ns_input_file = append2 (ns_input_file, build_string ([file UTF8String]));
5449 emacs_event->modifiers = EV_MODIFIERS (theEvent);
5450 EV_TRAILER (theEvent);
5453 else if ([type isEqualToString: NSStringPboardType]
5454 || [type isEqualToString: NSTabularTextPboardType])
5458 if (! (data = [pb stringForType: type]))
5461 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
5462 emacs_event->code = KEY_NS_DRAG_TEXT;
5463 XSETINT (emacs_event->x, x);
5464 XSETINT (emacs_event->y, y);
5465 ns_input_text = build_string ([data UTF8String]);
5466 emacs_event->modifiers = EV_MODIFIERS (theEvent);
5467 EV_TRAILER (theEvent);
5470 else if ([type isEqualToString: NSColorPboardType])
5472 NSColor *c = [NSColor colorFromPasteboard: pb];
5473 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
5474 emacs_event->code = KEY_NS_DRAG_COLOR;
5475 XSETINT (emacs_event->x, x);
5476 XSETINT (emacs_event->y, y);
5477 ns_input_color = ns_color_to_lisp (c);
5478 emacs_event->modifiers = EV_MODIFIERS (theEvent);
5479 EV_TRAILER (theEvent);
5482 else if ([type isEqualToString: NSFontPboardType])
5484 /* impl based on GNUstep NSTextView.m */
5485 NSData *data = [pb dataForType: NSFontPboardType];
5486 NSDictionary *dict = [NSUnarchiver unarchiveObjectWithData: data];
5487 NSFont *font = [dict objectForKey: NSFontAttributeName];
5493 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
5494 emacs_event->code = KEY_NS_CHANGE_FONT;
5495 XSETINT (emacs_event->x, x);
5496 XSETINT (emacs_event->y, y);
5497 ns_input_font = build_string ([[font fontName] UTF8String]);
5498 snprintf (fontSize, 10, "%f", [font pointSize]);
5499 ns_input_fontsize = build_string (fontSize);
5500 emacs_event->modifiers = EV_MODIFIERS (theEvent);
5501 EV_TRAILER (theEvent);
5506 error ("Invalid data type in dragging pasteboard.");
5512 - validRequestorForSendType: (NSString *)typeSent
5513 returnType: (NSString *)typeReturned
5515 NSTRACE (validRequestorForSendType);
5516 if ([ns_send_types indexOfObjectIdenticalTo: typeSent] != NSNotFound &&
5517 [ns_return_types indexOfObjectIdenticalTo: typeSent] != NSNotFound)
5520 return [super validRequestorForSendType: typeSent
5521 returnType: typeReturned];
5525 /* setMini =YES means set from internal (gives a finder icon), NO means set nil
5526 (gives a miniaturized version of the window); currently we use the latter for
5527 frames whose active buffer doesn't correspond to any file
5528 (e.g., '*scratch*') */
5529 - setMiniwindowImage: (BOOL) setMini
5531 id image = [[self window] miniwindowImage];
5532 NSTRACE (setMiniwindowImage);
5534 /* NOTE: under Cocoa miniwindowImage always returns nil, documentation
5535 about "AppleDockIconEnabled" notwithstanding, however the set message
5536 below has its effect nonetheless. */
5537 if (image != emacsframe->output_data.ns->miniimage)
5539 if (image && [image isKindOfClass: [EmacsImage class]])
5541 [[self window] setMiniwindowImage:
5542 setMini ? emacsframe->output_data.ns->miniimage : nil];
5549 - (void) setRows: (int) r andColumns: (int) c
5555 @end /* EmacsView */
5559 /* ==========================================================================
5561 EmacsWindow implementation
5563 ========================================================================== */
5565 @implementation EmacsWindow
5567 /* called only on resize clicks by special case in EmacsApp-sendEvent */
5568 - (void)mouseDown: (NSEvent *)theEvent
5572 NSSize size = [[theEvent window] frame].size;
5573 grabOffset = [theEvent locationInWindow];
5574 grabOffset.x = size.width - grabOffset.x;
5577 [super mouseDown: theEvent];
5582 - (void)mouseUp: (NSEvent *)theEvent
5586 struct frame *f = ((EmacsView *)[self delegate])->emacsframe;
5588 ns_set_name_as_filename (f);
5590 ns_send_appdefined (-1);
5593 [super mouseUp: theEvent];
5597 /* send resize events */
5598 - (void)mouseDragged: (NSEvent *)theEvent
5602 NSPoint p = [theEvent locationInWindow];
5603 NSSize size, vettedSize, origSize = [self frame].size;
5605 size.width = p.x + grabOffset.x;
5606 size.height = origSize.height - p.y + grabOffset.y;
5608 if (size.width == origSize.width && size.height == origSize.height)
5611 vettedSize = [[self delegate] windowWillResize: self toSize: size];
5612 if (vettedSize.width != size.width || vettedSize.height != size.height)
5614 [[NSNotificationCenter defaultCenter]
5615 postNotificationName: NSWindowDidResizeNotification
5620 [super mouseDragged: theEvent];
5623 @end /* EmacsWindow */
5626 /* ==========================================================================
5628 EmacsScroller implementation
5630 ========================================================================== */
5633 @implementation EmacsScroller
5635 /* for repeat button push */
5636 #define SCROLL_BAR_FIRST_DELAY 0.5
5637 #define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
5639 + (float) scrollerWidth
5641 /* TODO: if we want to allow variable widths, this is the place to do it,
5642 however neither GNUstep nor Cocoa support it very well */
5643 return [NSScroller scrollerWidth];
5647 - initFrame: (NSRect )r window: (Lisp_Object)nwin
5649 NSTRACE (EmacsScroller_initFrame);
5651 r.size.width = [EmacsScroller scrollerWidth];
5652 [super initWithFrame: r/*NSMakeRect (0, 0, 0, 0)*/];
5653 [self setContinuous: YES];
5654 [self setEnabled: YES];
5656 /* Ensure auto resizing of scrollbars occurs within the emacs frame's view
5657 locked against the right, top and bottom edges. */
5658 [self setAutoresizingMask: NSViewMinXMargin | NSViewHeightSizable];
5662 pixel_height = NSHeight (r);
5663 min_portion = 20 / pixel_height;
5665 frame = XFRAME (XWINDOW (win)->frame);
5666 if (FRAME_LIVE_P (frame))
5669 EmacsView *view = FRAME_NS_VIEW (frame);
5670 NSView *sview = [[view window] contentView];
5671 NSArray *subs = [sview subviews];
5673 /* disable optimization stopping redraw of other scrollbars */
5674 view->scrollbarsNeedingUpdate = 0;
5675 for (i =[subs count]-1; i >= 0; i--)
5676 if ([[subs objectAtIndex: i] isKindOfClass: [EmacsScroller class]])
5677 view->scrollbarsNeedingUpdate++;
5678 [sview addSubview: self];
5681 /* [self setFrame: r]; */
5687 - (void)setFrame: (NSRect)newRect
5689 NSTRACE (EmacsScroller_setFrame);
5691 pixel_height = NSHeight (newRect);
5692 min_portion = 20 / pixel_height;
5693 [super setFrame: newRect];
5695 /* UNBLOCK_INPUT; */
5701 NSTRACE (EmacsScroller_dealloc);
5703 XWINDOW (win)->vertical_scroll_bar = Qnil;
5730 /* ensure other scrollbar updates after deletion */
5731 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (frame);
5733 view->scrollbarsNeedingUpdate++;
5734 [self removeFromSuperview];
5742 - (void)resetCursorRects
5744 NSRect visible = [self visibleRect];
5745 NSTRACE (resetCursorRects);
5747 if (!NSIsEmptyRect (visible))
5748 [self addCursorRect: visible cursor: [NSCursor arrowCursor]];
5749 [[NSCursor arrowCursor] setOnMouseEntered: YES];
5753 - (int) checkSamePosition: (int) position portion: (int) portion
5756 return em_position ==position && em_portion ==portion && em_whole ==whole
5757 && portion != whole; /* needed for resize empty buf */
5761 - setPosition: (int)position portion: (int)portion whole: (int)whole
5763 NSTRACE (setPosition);
5765 em_position = position;
5766 em_portion = portion;
5769 if (portion >= whole)
5770 [self setFloatValue: 0.0 knobProportion: 1.0];
5774 portion = max ((float)whole*min_portion/pixel_height, portion);
5775 pos = (float)position / (whole - portion);
5776 por = (float)portion/whole;
5777 [self setFloatValue: pos knobProportion: por];
5779 #ifdef NS_IMPL_GNUSTEP
5785 /* FIXME: unused at moment (see ns_mouse_position) at the moment because
5786 drag events will go directly to the EmacsScroller. Leaving in for now. */
5787 -(void)getMouseMotionPart: (int *)part window: (Lisp_Object *)window
5788 x: (Lisp_Object *)x y: ( Lisp_Object *)y
5790 *part = last_hit_part;
5792 XSETINT (*y, pixel_height);
5793 if ([self floatValue] > 0.999)
5794 XSETINT (*x, pixel_height);
5796 XSETINT (*x, pixel_height * [self floatValue]);
5800 /* set up emacs_event */
5801 - (void) sendScrollEventAtLoc: (float)loc fromEvent: (NSEvent *)e
5806 emacs_event->part = last_hit_part;
5807 emacs_event->code = 0;
5808 emacs_event->modifiers = EV_MODIFIERS (e) | down_modifier;
5809 emacs_event->frame_or_window = win;
5810 emacs_event->timestamp = EV_TIMESTAMP (e);
5811 emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
5812 emacs_event->arg = Qnil;
5813 XSETINT (emacs_event->x, loc * pixel_height);
5814 XSETINT (emacs_event->y, pixel_height-20);
5816 n_emacs_events_pending++;
5817 kbd_buffer_store_event_hold (emacs_event, q_event_ptr);
5818 EVENT_INIT (*emacs_event);
5819 ns_send_appdefined (-1);
5823 /* called manually thru timer to implement repeated button action w/hold-down */
5824 - repeatScroll: (NSTimer *)scrollEntry
5826 NSEvent *e = [[self window] currentEvent];
5827 NSPoint p = [[self window] mouseLocationOutsideOfEventStream];
5828 BOOL inKnob = [self testPart: p] == NSScrollerKnob;
5830 /* clear timer if need be */
5831 if (inKnob || [scroll_repeat_entry timeInterval] == SCROLL_BAR_FIRST_DELAY)
5833 [scroll_repeat_entry invalidate];
5834 [scroll_repeat_entry release];
5835 scroll_repeat_entry = nil;
5841 = [[NSTimer scheduledTimerWithTimeInterval:
5842 SCROLL_BAR_CONTINUOUS_DELAY
5844 selector: @selector (repeatScroll:)
5850 [self sendScrollEventAtLoc: 0 fromEvent: e];
5855 /* Asynchronous mouse tracking for scroller. This allows us to dispatch
5856 mouseDragged events without going into a modal loop. */
5857 - (void)mouseDown: (NSEvent *)e
5860 /* hitPart is only updated AFTER event is passed on */
5861 NSScrollerPart part = [self testPart: [e locationInWindow]];
5862 double inc = 0.0, loc, kloc, pos;
5865 NSTRACE (EmacsScroller_mouseDown);
5869 case NSScrollerDecrementPage:
5870 last_hit_part = scroll_bar_above_handle; inc = -1.0; break;
5871 case NSScrollerIncrementPage:
5872 last_hit_part = scroll_bar_below_handle; inc = 1.0; break;
5873 case NSScrollerDecrementLine:
5874 last_hit_part = scroll_bar_up_arrow; inc = -0.1; break;
5875 case NSScrollerIncrementLine:
5876 last_hit_part = scroll_bar_down_arrow; inc = 0.1; break;
5877 case NSScrollerKnob:
5878 last_hit_part = scroll_bar_handle; break;
5879 case NSScrollerKnobSlot: /* GNUstep-only */
5880 last_hit_part = scroll_bar_move_ratio; break;
5881 default: /* NSScrollerNoPart? */
5882 fprintf (stderr, "EmacsScoller-mouseDown: unexpected part %d\n", part);
5888 pos = 0; /* ignored */
5890 /* set a timer to repeat, as we can't let superclass do this modally */
5892 = [[NSTimer scheduledTimerWithTimeInterval: 0.5
5894 selector: @selector (repeatScroll:)
5901 /* handle, or on GNUstep possibly slot */
5902 NSEvent *fake_event;
5904 /* compute float loc in slot and mouse offset on knob */
5905 sr = [self convertRect: [self rectForPart: NSScrollerKnobSlot]
5907 loc = NSHeight (sr) - ([e locationInWindow].y - NSMinY (sr));
5913 else if (loc >= NSHeight (sr))
5915 loc = NSHeight (sr);
5923 kr = [self convertRect: [self rectForPart: NSScrollerKnob]
5925 kloc = NSHeight (kr) - ([e locationInWindow].y - NSMinY (kr));
5927 last_mouse_offset = kloc;
5929 /* if knob, tell emacs a location offset by knob pos
5930 (to indicate top of handle) */
5931 if (part == NSScrollerKnob)
5932 pos = (loc - last_mouse_offset) / NSHeight (sr);
5934 /* else this is a slot click on GNUstep: go straight there */
5935 pos = loc / NSHeight (sr);
5937 /* send a fake mouse-up to super to preempt modal -trackKnob: mode */
5938 fake_event = [NSEvent mouseEventWithType: NSLeftMouseUp
5939 location: [e locationInWindow]
5940 modifierFlags: [e modifierFlags]
5941 timestamp: [e timestamp]
5942 windowNumber: [e windowNumber]
5943 context: [e context]
5944 eventNumber: [e eventNumber]
5945 clickCount: [e clickCount]
5946 pressure: [e pressure]];
5947 [super mouseUp: fake_event];
5950 if (part != NSScrollerKnob)
5951 [self sendScrollEventAtLoc: pos fromEvent: e];
5955 /* Called as we manually track scroller drags, rather than superclass. */
5956 - (void)mouseDragged: (NSEvent *)e
5962 NSTRACE (EmacsScroller_mouseDragged);
5964 sr = [self convertRect: [self rectForPart: NSScrollerKnobSlot]
5966 loc = NSHeight (sr) - ([e locationInWindow].y - NSMinY (sr));
5973 else if (loc >= NSHeight (sr) + last_mouse_offset)
5975 loc = NSHeight (sr) + last_mouse_offset;
5979 pos = /*(edge ? loc :*/ (loc - last_mouse_offset) / NSHeight (sr);
5980 [self sendScrollEventAtLoc: pos fromEvent: e];
5984 - (void)mouseUp: (NSEvent *)e
5986 if (scroll_repeat_entry)
5988 [scroll_repeat_entry invalidate];
5989 [scroll_repeat_entry release];
5990 scroll_repeat_entry = nil;
5996 /* treat scrollwheel events in the bar as though they were in the main window */
5997 - (void) scrollWheel: (NSEvent *)theEvent
5999 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (frame);
6000 [view mouseDown: theEvent];
6003 @end /* EmacsScroller */
6007 /* ==========================================================================
6009 EmacsPrefsController implementation
6011 ========================================================================== */
6014 @implementation EmacsPrefsController
6016 /* in Tiger+, can just do [popup selectItemWithTag: tag]; */
6017 static void selectItemWithTag (NSPopUpButton *popup, int tag)
6019 NSEnumerator *items = [[popup itemArray] objectEnumerator];
6021 while (item = [items nextObject])
6023 if ([item tag] == tag)
6025 [popup selectItem: item];
6033 [NSBundle loadNibNamed: @"preferences" owner: self];
6038 - (void) showForFrame: (struct frame *)f
6041 [self setPanelFromValues];
6042 [prefsWindow makeKeyAndOrderFront: self];
6043 [prefsWindow display];
6047 - (void) setPanelFromValues
6050 = ns_lisp_to_cursor_type (get_frame_param (frame, Qcursor_type));
6051 prevExpandSpace = XFLOATINT (ns_expand_space);
6053 #ifdef NS_IMPL_COCOA
6054 prevUseHighlightColor = ns_use_system_highlight_color;
6057 [expandSpaceSlider setFloatValue: prevExpandSpace];
6058 [cursorTypeMatrix selectCellWithTag: (cursorType == FILLED_BOX_CURSOR ? 1 :
6059 (cursorType == BAR_CURSOR ? 2 :
6060 (cursorType == HBAR_CURSOR ? 3 : 4)))];
6061 selectItemWithTag (alternateModMenu,
6062 parse_solitary_modifier (ns_alternate_modifier));
6063 selectItemWithTag (commandModMenu,
6064 parse_solitary_modifier (ns_command_modifier));
6065 #ifdef NS_IMPL_COCOA
6066 selectItemWithTag (controlModMenu,
6067 parse_solitary_modifier (ns_control_modifier));
6068 selectItemWithTag (functionModMenu,
6069 parse_solitary_modifier (ns_function_modifier));
6070 [smoothFontsCheck setState: (NILP (ns_antialias_text) ? NO : YES)];
6071 [useQuickdrawCheck setState: (NILP (ns_use_qd_smoothing) ? NO : YES)];
6072 [useSysHiliteCheck setState: (NILP (prevUseHighlightColor) ? NO : YES)];
6077 - (void) setValuesFromPanel
6079 int altTag = [[alternateModMenu selectedItem] tag];
6080 int cmdTag = [[commandModMenu selectedItem] tag];
6081 #ifdef NS_IMPL_COCOA
6082 int ctrlTag = [[controlModMenu selectedItem] tag];
6083 int fnTag = [[functionModMenu selectedItem] tag];
6085 float expandSpace = [expandSpaceSlider floatValue];
6086 int cursorTag = [[cursorTypeMatrix selectedCell] tag];
6087 Lisp_Object cursor_type = ns_cursor_type_to_lisp
6088 ( cursorTag == 1 ? FILLED_BOX_CURSOR
6089 : cursorTag == 2 ? BAR_CURSOR
6090 : cursorTag == 3 ? HBAR_CURSOR : HOLLOW_BOX_CURSOR);
6092 if (expandSpace != prevExpandSpace)
6094 ns_expand_space = make_float (expandSpace);
6095 /* TODO: more needed: store needed metrics in nsfont_info, update
6096 frame default font max_bounds and fontp, recompute faces */
6097 /* FRAME_LINE_HEIGHT (frame) *= (expandSpace / prevExpandSpace);
6098 x_set_window_size (frame, 0, frame->text_cols, frame->text_lines); */
6099 prevExpandSpace = expandSpace;
6102 store_frame_param (frame, Qcursor_type, cursor_type);
6103 ns_set_cursor_type(frame, cursor_type, Qnil); /* FIXME: do only if changed */
6105 ns_alternate_modifier = ns_mod_to_lisp (altTag);
6106 ns_command_modifier = ns_mod_to_lisp (cmdTag);
6107 #ifdef NS_IMPL_COCOA
6108 ns_control_modifier = ns_mod_to_lisp (ctrlTag);
6109 ns_function_modifier = ns_mod_to_lisp (fnTag);
6110 ns_antialias_text = [smoothFontsCheck state] ? Qt : Qnil;
6111 ns_use_qd_smoothing = [useQuickdrawCheck state] ? Qt : Qnil;
6112 ns_use_system_highlight_color = [useSysHiliteCheck state] ? Qt : Qnil;
6113 if (! EQ (ns_use_system_highlight_color, prevUseHighlightColor))
6115 prevUseHighlightColor = ns_use_system_highlight_color;
6116 if (EQ (ns_use_system_highlight_color, Qt))
6118 ns_selection_color = [[NSUserDefaults standardUserDefaults]
6119 stringForKey: @"AppleHighlightColor"];
6120 if (ns_selection_color == nil)
6121 ns_selection_color = NS_SELECTION_COLOR_DEFAULT;
6124 ns_selection_color = NS_SELECTION_COLOR_DEFAULT;
6126 #endif /* NS_IMPL_COCOA */
6127 Fcall_interactively (intern ("ns-save-preferences"), Qnil, Qnil);
6132 - (IBAction)cancel: (id)sender
6134 [prefsWindow close];
6138 - (IBAction)ok: (id)sender
6140 [self setValuesFromPanel];
6141 [prefsWindow close];
6145 - (IBAction)resetToDefaults: (id)sender
6147 ns_set_default_prefs ();
6148 [self setPanelFromValues];
6152 - (IBAction)runHelp: (id)sender
6154 Feval (Fcons (intern ("info"),
6155 Fcons (build_string ("(ns-emacs)Preferences Panel"), Qnil)));
6156 SET_FRAME_GARBAGED (frame);
6157 ns_send_appdefined (-1);
6161 - (IBAction)setColors: (id)sender
6163 Lisp_Object lispFrame;
6164 XSETFRAME (lispFrame, frame);
6165 Fns_popup_color_panel (lispFrame);
6169 - (IBAction)setDefaultFont: (id)sender
6171 Lisp_Object lispFrame;
6172 XSETFRAME (lispFrame, frame);
6173 Fns_popup_font_panel (lispFrame);
6176 @end /* EmacsPrefsController */
6181 /* ==========================================================================
6183 Font-related functions; these used to be in nsfaces.m
6184 The XLFD functions (115 lines) are an abomination that should be removed.
6186 ========================================================================== */
6190 x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
6192 struct font *font = XFONT_OBJECT (font_object);
6195 fontset = fontset_from_font (font_object);
6196 FRAME_FONTSET (f) = fontset;
6198 if (FRAME_FONT (f) == font)
6199 /* This font is already set in frame F. There's nothing more to
6203 FRAME_FONT (f) = font;
6205 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
6206 FRAME_COLUMN_WIDTH (f) = font->average_width;
6207 FRAME_SPACE_WIDTH (f) = font->space_width;
6208 FRAME_LINE_HEIGHT (f) = font->height;
6210 compute_fringe_widths (f, 1);
6212 /* Compute the scroll bar width in character columns. */
6213 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
6215 int wid = FRAME_COLUMN_WIDTH (f);
6216 FRAME_CONFIG_SCROLL_BAR_COLS (f)
6217 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
6221 int wid = FRAME_COLUMN_WIDTH (f);
6222 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
6225 /* Now make the frame display the given font. */
6226 if (FRAME_NS_WINDOW (f) != 0)
6227 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
6233 /* XLFD: -foundry-family-weight-slant-swidth-adstyle-pxlsz-ptSz-resx-resy-spc-avgWidth-rgstry-encoding */
6236 ns_font_to_xlfd (NSFont *nsfont)
6237 /* --------------------------------------------------------------------------
6238 Convert an NS font name to an X font name (XLFD).
6239 The string returned is temporarily allocated.
6240 -------------------------------------------------------------------------- */
6242 NSFontManager *mgr = [NSFontManager sharedFontManager];
6243 NSString *sname = [nsfont /*familyName*/fontName];
6244 char *famName = (char *)[sname UTF8String];
6245 char *weightStr = [mgr fontNamed: sname hasTraits: NSBoldFontMask] ?
6247 char *slantStr = [mgr fontNamed: sname hasTraits: NSItalicFontMask] ?
6249 int size = [nsfont pointSize];
6250 int aWidth = lrint (10.0 * [nsfont widthOfString: @"a"]);
6254 /* change '-' to '$' to avoid messing w/XLFD separator */
6255 for (len = strlen (famName), i =0; i<len; i++)
6256 if (famName[i] == '-')
6262 xlfd = [[NSString stringWithFormat:
6263 @"-apple-%s-%s-%s-normal--%d-%d-75-75-m-%d-iso10646-1",
6264 famName, weightStr, slantStr, size, 10*size, aWidth]
6266 /*fprintf (stderr, "converted '%s' to '%s'\n",name,xlfd); */
6271 ns_fontname_to_xlfd (const char *name)
6272 /* --------------------------------------------------------------------------
6273 Convert an NS font name to an X font name (XLFD).
6275 The string returned is temporarily allocated.
6276 -------------------------------------------------------------------------- */
6279 char *weightStr = strcasestr (name, "bold") ? "bold" : "medium";
6280 char *slantStr = strcasestr (name, "italic") || strcasestr (name, "oblique")
6281 || strcasestr (name, "synthital") ? "i" : "r";
6285 /* change '-' to '$' to avoid messing w/XLFD separator, and ' ' to '_' */
6286 bzero (famName, 180);
6287 bcopy (name, famName, max (strlen (name), 179));
6288 for (len =strlen (famName), i =0; i<len; i++)
6290 if (famName[i] == '-')
6292 else if (famName[i] == ' ')
6296 xlfd = [[NSString stringWithFormat:
6297 @"-apple-%s-%s-%s-normal--0-0-75-75-m-0-iso10646-1",
6298 famName, weightStr, slantStr]
6300 /*fprintf (stderr, "converted '%s' to '%s'\n",name,xlfd); */
6306 ns_xlfd_to_fontname (const char *xlfd)
6307 /* --------------------------------------------------------------------------
6308 Convert an X font name (XLFD) to an NS font name.
6309 Only family is used.
6310 The string returned is temporarily allocated.
6311 -------------------------------------------------------------------------- */
6313 char *name = xmalloc (180);
6317 if (!strncmp (xlfd, "--", 2))
6318 sscanf (xlfd, "--%*[^-]-%[^-]179-", name);
6320 sscanf (xlfd, "-%*[^-]-%[^-]179-", name);
6322 /* stopgap for malformed XLFD input */
6323 if (strlen (name) == 0)
6324 strcpy (name, "Monaco");
6326 /* undo hack in ns_fontname_to_xlfd, converting '$' to '-', '_' to ' '
6327 also uppercase after '-' or ' ' */
6328 name[0] = toupper (name[0]);
6329 for (len =strlen (name), i =0; i<len; i++)
6335 name[i+1] = toupper (name[i+1]);
6337 else if (name[i] == '_')
6341 name[i+1] = toupper (name[i+1]);
6344 /*fprintf (stderr, "converted '%s' to '%s'\n",xlfd,name); */
6345 ret = [[NSString stringWithUTF8String: name] UTF8String];
6354 NSTRACE (syms_of_nsterm);
6355 DEFVAR_LISP ("ns-input-file", &ns_input_file,
6356 "The file specified in the last NS event.");
6357 ns_input_file =Qnil;
6359 DEFVAR_LISP ("ns-input-text", &ns_input_text,
6360 "The data received in the last NS text drag event.");
6361 ns_input_text =Qnil;
6363 DEFVAR_LISP ("ns-working-text", &ns_working_text,
6364 "String for visualizing working composition sequence.");
6365 ns_working_text =Qnil;
6367 DEFVAR_LISP ("ns-input-font", &ns_input_font,
6368 "The font specified in the last NS event.");
6369 ns_input_font =Qnil;
6371 DEFVAR_LISP ("ns-input-fontsize", &ns_input_fontsize,
6372 "The fontsize specified in the last NS event.");
6373 ns_input_fontsize =Qnil;
6375 DEFVAR_LISP ("ns-input-line", &ns_input_line,
6376 "The line specified in the last NS event.");
6377 ns_input_line =Qnil;
6379 DEFVAR_LISP ("ns-input-color", &ns_input_color,
6380 "The color specified in the last NS event.");
6381 ns_input_color =Qnil;
6383 DEFVAR_LISP ("ns-input-spi-name", &ns_input_spi_name,
6384 "The service name specified in the last NS event.");
6385 ns_input_spi_name =Qnil;
6387 DEFVAR_LISP ("ns-input-spi-arg", &ns_input_spi_arg,
6388 "The service argument specified in the last NS event.");
6389 ns_input_spi_arg =Qnil;
6391 DEFVAR_LISP ("ns-alternate-modifier", &ns_alternate_modifier,
6392 "This variable describes the behavior of the alternate or option key.\n\
6393 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
6394 Set to none means that the alternate / option key is not interpreted by Emacs\n\
6395 at all, allowing it to be used at a lower level for accented character entry.");
6397 DEFVAR_LISP ("ns-command-modifier", &ns_command_modifier,
6398 "This variable describes the behavior of the command key.\n\
6399 Set to control, meta, alt, super, or hyper means it is taken to be that key.");
6401 DEFVAR_LISP ("ns-control-modifier", &ns_control_modifier,
6402 "This variable describes the behavior of the control key.\n\
6403 Set to control, meta, alt, super, or hyper means it is taken to be that key.");
6405 DEFVAR_LISP ("ns-function-modifier", &ns_function_modifier,
6406 "This variable describes the behavior of the function key (on laptops).\n\
6407 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
6408 Set to none means that the function key is not interpreted by Emacs at all,\n\
6409 allowing it to be used at a lower level for accented character entry.");
6411 DEFVAR_LISP ("ns-expand-space", &ns_expand_space,
6412 "Amount by which spacing between lines is expanded (positive)\n\
6413 or shrunk (negative). Zero (the default) means standard line height.\n\
6414 (This variable should only be read, never set.)");
6416 DEFVAR_LISP ("ns-antialias-text", &ns_antialias_text,
6417 "Non-nil (the default) means to render text antialiased. Only has an effect on OS X Panther and above.");
6419 DEFVAR_LISP ("ns-use-qd-smoothing", &ns_use_qd_smoothing,
6420 "Whether to render text using QuickDraw (less heavy) antialiasing. Only has an effect on OS X Panther and above. Default is nil (use Quartz smoothing).");
6422 DEFVAR_LISP ("ns-use-system-highlight-color",
6423 &ns_use_system_highlight_color,
6424 "Whether to use the system default (on OS X only) for the highlight color. Nil means to use standard emacs (prior to version 21) 'grey'.");
6426 staticpro (&ns_display_name_list);
6427 ns_display_name_list = Qnil;
6429 staticpro (&last_mouse_motion_frame);
6430 last_mouse_motion_frame = Qnil;
6432 /*23: now apparently we need to tell emacs what modifiers there are.. */
6433 Qmodifier_value = intern ("modifier-value");
6434 Qalt = intern ("alt");
6435 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
6436 Qhyper = intern ("hyper");
6437 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
6438 Qmeta = intern ("meta");
6439 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
6440 Qsuper = intern ("super");
6441 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
6442 Qcontrol = intern ("control");
6443 Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
6445 /* TODO: move to common code */
6446 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
6447 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
6448 #ifdef USE_TOOLKIT_SCROLL_BARS
6449 Vx_toolkit_scroll_bars = Qt;
6451 Vx_toolkit_scroll_bars = Qnil;
6454 /* these are unsupported but we need the declarations to avoid whining
6455 messages from cus-start.el */
6456 DEFVAR_BOOL ("x-use-underline-position-properties",
6457 &x_use_underline_position_properties,
6458 doc: /* NOT SUPPORTED UNDER NS.
6459 *Non-nil means make use of UNDERLINE_POSITION font properties.
6460 A value of nil means ignore them. If you encounter fonts with bogus
6461 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
6462 to 4.1, set this to nil.
6464 NOTE: Not supported on Mac yet. */);
6465 x_use_underline_position_properties = 0;
6467 DEFVAR_BOOL ("x-underline-at-descent-line",
6468 &x_underline_at_descent_line,
6469 doc: /* NOT SUPPORTED UNDER NS.
6470 *Non-nil means to draw the underline at the same place as the descent line.
6471 A value of nil means to draw the underline according to the value of the
6472 variable `x-use-underline-position-properties', which is usually at the
6473 baseline level. The default value is nil. */);
6474 x_underline_at_descent_line = 0;
6476 /* Tell emacs about this window system. */
6477 Fprovide (intern ("ns"), Qnil);
6481 // arch-tag: 6eaa8f7d-a69b-4e1c-b43d-ab31defbe0d2