1 /* NeXT/Open/GNUstep / MacOSX communication module.
3 Copyright (C) 1989, 1993-1994, 2005-2006, 2008-2012
4 Free Software Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
22 Originally by Carl Edman
23 Updated by Christian Limpach (chris@nice.ch)
24 OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com)
25 MacOSX/Aqua port by Christophe de Dinechin (descubes@earthlink.net)
26 GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
29 /* This should be the first include, as it may set up #defines affecting
30 interpretation of even the system includes. */
34 #include
<sys
/types.h
>
41 #include
<c
-strcase.h
>
49 #include "blockinput.h"
50 #include "sysselect.h"
53 #include "character.h"
55 #include "composite.h"
58 #include "termhooks.h"
69 int term_trace_num
= 0;
70 #define NSTRACE
(x
) fprintf (stderr
, "
%s:%d: [%d] " #x "\n", \
71 __FILE__
, __LINE__
, ++term_trace_num
)
76 extern NSString
*NSMenuDidBeginTrackingNotification
;
78 /* ==========================================================================
82 ========================================================================== */
84 /* Convert a symbol indexed with an NSxxx value to a value as defined
85 in keyboard.c (lispy_function_key). I hope this is a correct way
87 static unsigned convert_ns_to_X_keysym
[] =
89 NSHomeFunctionKey
, 0x50,
90 NSLeftArrowFunctionKey
, 0x51,
91 NSUpArrowFunctionKey
, 0x52,
92 NSRightArrowFunctionKey
, 0x53,
93 NSDownArrowFunctionKey
, 0x54,
94 NSPageUpFunctionKey
, 0x55,
95 NSPageDownFunctionKey
, 0x56,
96 NSEndFunctionKey
, 0x57,
97 NSBeginFunctionKey
, 0x58,
98 NSSelectFunctionKey
, 0x60,
99 NSPrintFunctionKey
, 0x61,
100 NSExecuteFunctionKey
, 0x62,
101 NSInsertFunctionKey
, 0x63,
102 NSUndoFunctionKey
, 0x65,
103 NSRedoFunctionKey
, 0x66,
104 NSMenuFunctionKey
, 0x67,
105 NSFindFunctionKey
, 0x68,
106 NSHelpFunctionKey
, 0x6A,
107 NSBreakFunctionKey
, 0x6B,
109 NSF1FunctionKey
, 0xBE,
110 NSF2FunctionKey
, 0xBF,
111 NSF3FunctionKey
, 0xC0,
112 NSF4FunctionKey
, 0xC1,
113 NSF5FunctionKey
, 0xC2,
114 NSF6FunctionKey
, 0xC3,
115 NSF7FunctionKey
, 0xC4,
116 NSF8FunctionKey
, 0xC5,
117 NSF9FunctionKey
, 0xC6,
118 NSF10FunctionKey
, 0xC7,
119 NSF11FunctionKey
, 0xC8,
120 NSF12FunctionKey
, 0xC9,
121 NSF13FunctionKey
, 0xCA,
122 NSF14FunctionKey
, 0xCB,
123 NSF15FunctionKey
, 0xCC,
124 NSF16FunctionKey
, 0xCD,
125 NSF17FunctionKey
, 0xCE,
126 NSF18FunctionKey
, 0xCF,
127 NSF19FunctionKey
, 0xD0,
128 NSF20FunctionKey
, 0xD1,
129 NSF21FunctionKey
, 0xD2,
130 NSF22FunctionKey
, 0xD3,
131 NSF23FunctionKey
, 0xD4,
132 NSF24FunctionKey
, 0xD5,
134 NSBackspaceCharacter
, 0x08, /* 8: Not on some KBs. */
135 NSDeleteCharacter
, 0xFF, /* 127: Big 'delete' key upper right. */
136 NSDeleteFunctionKey
, 0x9F, /* 63272: Del forw key off main array. */
138 NSTabCharacter
, 0x09,
139 0x19, 0x09, /* left tab->regular since pass shift */
140 NSCarriageReturnCharacter
, 0x0D,
141 NSNewlineCharacter
, 0x0D,
142 NSEnterCharacter
, 0x8D,
144 0x1B, 0x1B /* escape */
147 static Lisp_Object Qmodifier_value
;
148 Lisp_Object Qalt
, Qcontrol
, Qhyper
, Qmeta
, Qsuper
;
149 extern Lisp_Object Qcursor_color
, Qcursor_type
, Qns
, Qleft
;
151 static Lisp_Object QUTF8_STRING
;
153 /* On OS X picks up the default NSGlobalDomain AppleAntiAliasingThreshold,
154 the maximum font size to NOT antialias. On GNUstep there is currently
155 no way to control this behavior. */
156 float ns_antialias_threshold
;
158 /* Used to pick up AppleHighlightColor on OS X */
159 NSString
*ns_selection_color
;
161 NSArray
*ns_send_types
=0, *ns_return_types
=0, *ns_drag_types
=0;
162 NSString
*ns_app_name
= @"Emacs"
; /* default changed later */
164 /* Display variables */
165 struct ns_display_info
*x_display_list
; /* Chain of existing displays */
166 Lisp_Object ns_display_name_list
;
167 long context_menu_value
= 0;
170 NSPoint last_mouse_motion_position
;
171 static NSRect last_mouse_glyph
;
172 static Time last_mouse_movement_time
= 0;
173 static Lisp_Object last_mouse_motion_frame
;
174 static EmacsScroller
*last_mouse_scroll_bar
= nil
;
175 static
struct frame
*ns_updating_frame
;
176 static NSView
*focus_view
= NULL;
177 static int ns_window_num
= 0;
178 #ifdef NS_IMPL_GNUSTEP
181 static BOOL gsaved
= NO
;
182 BOOL ns_in_resize
= NO
;
183 static BOOL ns_fake_keydown
= NO
;
184 int ns_tmp_flags
; /* FIXME */
185 struct nsfont_info
*ns_tmp_font
; /* FIXME */
186 static BOOL ns_menu_bar_is_hidden
= NO
;
187 /*static int debug_lock = 0; */
190 static BOOL send_appdefined
= YES
;
191 static NSEvent
*last_appdefined_event
= 0;
192 static NSTimer
*timed_entry
= 0;
193 static NSTimer
*scroll_repeat_entry
= nil
;
194 static fd_set select_readfds
, select_writefds
;
195 enum
{ SELECT_HAVE_READ
= 1, SELECT_HAVE_WRITE
= 2, SELECT_HAVE_TMO
= 4 };
196 static int select_nfds
= 0, select_valid
= 0;
197 static EMACS_TIME select_timeout
= { 0, 0 };
198 static int selfds
[2] = { -1, -1 };
199 static pthread_mutex_t select_mutex
;
200 static int apploopnr
= 0;
201 static NSAutoreleasePool
*outerpool
;
202 static
struct input_event
*emacs_event
= NULL;
203 static
struct input_event
*q_event_ptr
= NULL;
204 static int n_emacs_events_pending
= 0;
205 static NSMutableArray
*ns_pending_files
, *ns_pending_service_names
,
206 *ns_pending_service_args
;
207 static BOOL ns_do_open_file
= NO
;
209 /* Convert modifiers in a NeXTstep event to emacs style modifiers. */
210 #define NS_FUNCTION_KEY_MASK
0x800000
211 #define NSLeftControlKeyMask
(0x000001 | NSControlKeyMask
)
212 #define NSRightControlKeyMask
(0x002000 | NSControlKeyMask
)
213 #define NSLeftCommandKeyMask
(0x000008 | NSCommandKeyMask
)
214 #define NSRightCommandKeyMask
(0x000010 | NSCommandKeyMask
)
215 #define NSLeftAlternateKeyMask
(0x000020 | NSAlternateKeyMask
)
216 #define NSRightAlternateKeyMask
(0x000040 | NSAlternateKeyMask
)
217 #define EV_MODIFIERS
(e
) \
218 ((([e modifierFlags
] & NSHelpKeyMask
) ? \
219 hyper_modifier
: 0) \
220 |
(!EQ
(ns_right_alternate_modifier
, Qleft
) && \
221 (([e modifierFlags
] & NSRightAlternateKeyMask
) \
222 == NSRightAlternateKeyMask
) ? \
223 parse_solitary_modifier
(ns_right_alternate_modifier
) : 0) \
224 |
(([e modifierFlags
] & NSAlternateKeyMask
) ? \
225 parse_solitary_modifier
(ns_alternate_modifier
) : 0) \
226 |
(([e modifierFlags
] & NSShiftKeyMask
) ? \
227 shift_modifier
: 0) \
228 |
(!EQ
(ns_right_control_modifier
, Qleft
) && \
229 (([e modifierFlags
] & NSRightControlKeyMask
) \
230 == NSRightControlKeyMask
) ? \
231 parse_solitary_modifier
(ns_right_control_modifier
) : 0) \
232 |
(([e modifierFlags
] & NSControlKeyMask
) ? \
233 parse_solitary_modifier
(ns_control_modifier
) : 0) \
234 |
(([e modifierFlags
] & NS_FUNCTION_KEY_MASK
) ? \
235 parse_solitary_modifier
(ns_function_modifier
) : 0) \
236 |
(!EQ
(ns_right_command_modifier
, Qleft
) && \
237 (([e modifierFlags
] & NSRightCommandKeyMask
) \
238 == NSRightCommandKeyMask
) ? \
239 parse_solitary_modifier
(ns_right_command_modifier
) : 0) \
240 |
(([e modifierFlags
] & NSCommandKeyMask
) ? \
241 parse_solitary_modifier
(ns_command_modifier
):0))
243 #define EV_UDMODIFIERS
(e
) \
244 ((([e
type] == NSLeftMouseDown
) ? down_modifier
: 0) \
245 |
(([e
type] == NSRightMouseDown
) ? down_modifier
: 0) \
246 |
(([e
type] == NSOtherMouseDown
) ? down_modifier
: 0) \
247 |
(([e
type] == NSLeftMouseDragged
) ? down_modifier
: 0) \
248 |
(([e
type] == NSRightMouseDragged
) ? down_modifier
: 0) \
249 |
(([e
type] == NSOtherMouseDragged
) ? down_modifier
: 0) \
250 |
(([e
type] == NSLeftMouseUp
) ? up_modifier
: 0) \
251 |
(([e
type] == NSRightMouseUp
) ? up_modifier
: 0) \
252 |
(([e
type] == NSOtherMouseUp
) ? up_modifier
: 0))
254 #define EV_BUTTON
(e
) \
255 ((([e
type] == NSLeftMouseDown
) ||
([e
type] == NSLeftMouseUp
)) ?
0 : \
256 (([e
type] == NSRightMouseDown
) ||
([e
type] == NSRightMouseUp
)) ?
2 : \
257 [e buttonNumber
] - 1)
259 /* Convert the time field to a timestamp in milliseconds. */
260 #define EV_TIMESTAMP
(e
) ([e timestamp
] * 1000)
262 /* This is a piece of code which is common to all the event handling
263 methods. Maybe it should even be a function. */
264 #define EV_TRAILER
(e
) \
266 XSETFRAME
(emacs_event
->frame_or_window
, emacsframe
); \
267 if (e
) emacs_event
->timestamp
= EV_TIMESTAMP
(e
); \
270 n_emacs_events_pending
++; \
271 kbd_buffer_store_event_hold
(emacs_event
, q_event_ptr
); \
274 kbd_buffer_store_event
(emacs_event
); \
275 EVENT_INIT
(*emacs_event
); \
276 ns_send_appdefined
(-1); \
279 void x_set_cursor_type
(struct frame
*, Lisp_Object
, Lisp_Object
);
281 /* TODO: get rid of need for these forward declarations */
282 static void ns_condemn_scroll_bars
(struct frame
*f
);
283 static void ns_judge_scroll_bars
(struct frame
*f
);
284 void x_set_frame_alpha
(struct frame
*f
);
287 /* ==========================================================================
291 ========================================================================== */
295 append2
(Lisp_Object list
, Lisp_Object item
)
296 /* --------------------------------------------------------------------------
297 Utility to append to a list
298 -------------------------------------------------------------------------- */
300 Lisp_Object array
[2];
302 array
[1] = Fcons
(item
, Qnil
);
303 return Fnconc
(2, &array
[0]);
308 ns_etc_directory
(void
)
309 /* If running as a self-contained app bundle, return as a string the
310 filename of the etc directory, if present; else nil. */
312 NSBundle
*bundle
= [NSBundle mainBundle
];
313 NSString
*resourceDir
= [bundle resourcePath
];
314 NSString
*resourcePath
;
315 NSFileManager
*fileManager
= [NSFileManager defaultManager
];
318 resourcePath
= [resourceDir stringByAppendingPathComponent
: @"etc"
];
319 if ([fileManager fileExistsAtPath
: resourcePath isDirectory
: &isDir
])
321 if (isDir
) return [resourcePath UTF8String
];
329 /* If running as a self-contained app bundle, return as a path string
330 the filenames of the libexec and bin directories, ie libexec:bin.
331 Otherwise, return nil.
332 Normally, Emacs does not add its own bin/ directory to the PATH.
333 However, a self-contained NS build has a different layout, with
334 bin/ and libexec/ subdirectories in the directory that contains
336 We put libexec first, because init_callproc_1 uses the first
337 element to initialize exec-directory. An alternative would be
338 for init_callproc to check for invocation-directory/libexec.
341 NSBundle
*bundle
= [NSBundle mainBundle
];
342 NSString
*resourceDir
= [bundle resourcePath
];
343 NSString
*binDir
= [bundle bundlePath
];
344 NSString
*resourcePath
, *resourcePaths
;
346 NSString
*pathSeparator
= [NSString stringWithFormat
: @"
%c", SEPCHAR];
347 NSFileManager
*fileManager
= [NSFileManager defaultManager
];
349 NSEnumerator
*pathEnum
;
352 range
= [resourceDir rangeOfString
: @"Contents"
];
353 if (range.location
!= NSNotFound
)
355 binDir
= [binDir stringByAppendingPathComponent
: @"Contents"
];
357 binDir
= [binDir stringByAppendingPathComponent
: @"MacOS"
];
361 paths
= [binDir stringsByAppendingPaths
:
362 [NSArray arrayWithObjects
: @"libexec"
, @"bin"
, nil
]];
363 pathEnum
= [paths objectEnumerator
];
366 while ((resourcePath
= [pathEnum nextObject
]))
368 if ([fileManager fileExistsAtPath
: resourcePath isDirectory
: &isDir
])
371 if ([resourcePaths
length] > 0)
373 = [resourcePaths stringByAppendingString
: pathSeparator
];
375 = [resourcePaths stringByAppendingString
: resourcePath
];
378 if ([resourcePaths
length] > 0) return [resourcePaths UTF8String
];
386 /* If running as a self-contained app bundle, return as a path string
387 the filenames of the site-lisp, lisp and leim directories.
388 Ie, site-lisp:lisp:leim. Otherwise, return nil. */
390 NSBundle
*bundle
= [NSBundle mainBundle
];
391 NSString
*resourceDir
= [bundle resourcePath
];
392 NSString
*resourcePath
, *resourcePaths
;
393 NSString
*pathSeparator
= [NSString stringWithFormat
: @"
%c", SEPCHAR];
394 NSFileManager
*fileManager
= [NSFileManager defaultManager
];
396 NSArray
*paths
= [resourceDir stringsByAppendingPaths
:
397 [NSArray arrayWithObjects
:
398 @"site
-lisp"
, @"lisp"
, @"leim"
, nil
]];
399 NSEnumerator
*pathEnum
= [paths objectEnumerator
];
402 /* Hack to skip site-lisp. */
403 if (no_site_lisp
) resourcePath
= [pathEnum nextObject
];
405 while ((resourcePath
= [pathEnum nextObject
]))
407 if ([fileManager fileExistsAtPath
: resourcePath isDirectory
: &isDir
])
410 if ([resourcePaths
length] > 0)
412 = [resourcePaths stringByAppendingString
: pathSeparator
];
414 = [resourcePaths stringByAppendingString
: resourcePath
];
417 if ([resourcePaths
length] > 0) return [resourcePaths UTF8String
];
423 ns_timeout
(int usecs
)
424 /* --------------------------------------------------------------------------
425 Blocking timer utility used by ns_ring_bell
426 -------------------------------------------------------------------------- */
428 EMACS_TIME wakeup
= add_emacs_time
(current_emacs_time
(),
429 make_emacs_time
(0, usecs
* 1000));
431 /* Keep waiting until past the time wakeup. */
434 EMACS_TIME timeout
, now
= current_emacs_time
();
435 if (EMACS_TIME_LE
(wakeup
, now
))
437 timeout
= sub_emacs_time
(wakeup
, now
);
439 /* Try to wait that long--but we might wake up sooner. */
440 pselect
(0, NULL, NULL, NULL, &timeout
, NULL);
446 ns_release_object
(void
*obj
)
447 /* --------------------------------------------------------------------------
448 Release an object (callable from C)
449 -------------------------------------------------------------------------- */
456 ns_retain_object
(void
*obj
)
457 /* --------------------------------------------------------------------------
458 Retain an object (callable from C)
459 -------------------------------------------------------------------------- */
466 ns_alloc_autorelease_pool
(void
)
467 /* --------------------------------------------------------------------------
468 Allocate a pool for temporary objects (callable from C)
469 -------------------------------------------------------------------------- */
471 return [[NSAutoreleasePool alloc
] init
];
476 ns_release_autorelease_pool
(void
*pool
)
477 /* --------------------------------------------------------------------------
478 Free a pool and temporary objects it refers to (callable from C)
479 -------------------------------------------------------------------------- */
481 ns_release_object
(pool
);
486 /* ==========================================================================
488 Focus (clipping) and screen update
490 ========================================================================== */
493 ns_resize_handle_rect
(NSWindow
*window
)
495 NSRect r
= [window frame
];
496 r.origin.x
= r.
size.width
- RESIZE_HANDLE_SIZE
;
498 r.
size.width
= r.
size.height
= RESIZE_HANDLE_SIZE
;
504 // Window constraining
505 // -------------------
507 // To ensure that the windows are not placed under the
menu bar, they
508 // are typically moved by the call
-back constrainFrameRect. However
,
509 // by overriding it
, it
's possible to inhibit this, leaving the window
510 // in it's original position.
512 // It
's possible to hide the menu bar. However, technically, it's only
513 // possible to hide it when the application is active. To ensure that
514 // this work properly
, the
menu bar and window constraining are
515 // deferred until the application becomes active.
517 // Even though it
's not possible to manually move a window above the
518 // top of the screen, it is allowed if it's done programmatically
,
519 // when the
menu is
hidden. This allows the editable area to cover the
520 // full screen height.
525 // Use the following extra files
:
528 // ;; Hide
menu and place frame slightly above the top of the screen.
529 // (setq ns
-auto
-hide
-menu-bar t
)
530 // (set-frame
-position
(selected
-frame
) 0 -20)
534 // emacs
-Q
-l init.el
536 // Result
: No
menu bar, and the
title bar should be above the screen.
542 // Result
: Menu bar visible
, frame placed immediately below the
menu.
546 ns_constrain_all_frames
(void
)
548 Lisp_Object tail
, frame
;
550 FOR_EACH_FRAME
(tail
, frame
)
552 struct frame
*f
= XFRAME
(frame
);
555 NSView
*view = FRAME_NS_VIEW
(f
);
556 /* This no-op will trigger the default window placing
557 * constraint system. */
558 f
->output_data.ns
->dont_constrain
= 0;
559 [[view window
] setFrameOrigin
:[[view window
] frame
].origin
];
565 /* True, if the menu bar should be hidden. */
568 ns_menu_bar_should_be_hidden
(void
)
570 return !NILP
(ns_auto_hide_menu_bar
)
571 && [NSApp respondsToSelector
:@selector
(setPresentationOptions
:)];
575 /* Show or hide the menu bar, based on user setting. */
578 ns_update_auto_hide_menu_bar
(void
)
580 #ifndef MAC_OS_X_VERSION_10_6
581 #define MAC_OS_X_VERSION_10_6
1060
584 #
if MAC_OS_X_VERSION_MAX_ALLOWED
>= MAC_OS_X_VERSION_10_6
587 NSTRACE
(ns_update_auto_hide_menu_bar
);
591 && [NSApp respondsToSelector
:@selector
(setPresentationOptions
:)])
593 // Note
, "setPresentationOptions" triggers an
error unless the
594 // application is active.
595 BOOL menu_bar_should_be_hidden
= ns_menu_bar_should_be_hidden
();
597 if (menu_bar_should_be_hidden
!= ns_menu_bar_is_hidden
)
599 NSApplicationPresentationOptions options
600 = NSApplicationPresentationAutoHideDock
;
602 if (menu_bar_should_be_hidden
)
603 options |
= NSApplicationPresentationAutoHideMenuBar
;
605 [NSApp setPresentationOptions
: options
];
607 ns_menu_bar_is_hidden
= menu_bar_should_be_hidden
;
609 if (!ns_menu_bar_is_hidden
)
611 ns_constrain_all_frames
();
623 ns_update_begin
(struct frame
*f
)
624 /* --------------------------------------------------------------------------
625 Prepare for a grouped sequence of drawing calls
626 external (RIF) call; whole frame, called before update_window_begin
627 -------------------------------------------------------------------------- */
629 NSView
*view = FRAME_NS_VIEW
(f
);
630 NSTRACE
(ns_update_begin
);
632 ns_update_auto_hide_menu_bar
();
634 ns_updating_frame
= f
;
637 #ifdef NS_IMPL_GNUSTEP
638 uRect
= NSMakeRect
(0, 0, 0, 0);
644 ns_update_window_begin
(struct window
*w
)
645 /* --------------------------------------------------------------------------
646 Prepare for a grouped sequence of drawing calls
647 external (RIF) call; for one window, called after update_begin
648 -------------------------------------------------------------------------- */
650 struct frame
*f
= XFRAME
(WINDOW_FRAME
(w
));
651 Mouse_HLInfo
*hlinfo
= MOUSE_HL_INFO
(f
);
652 NSTRACE
(ns_update_window_begin
);
655 set_output_cursor
(&w
->cursor
);
659 if (f
== hlinfo
->mouse_face_mouse_frame
)
661 /* Don't do highlighting for mouse motion during the update. */
662 hlinfo
->mouse_face_defer
= 1;
664 /* If the frame needs to be redrawn,
665 simply forget about any prior mouse highlighting. */
666 if (FRAME_GARBAGED_P
(f
))
667 hlinfo
->mouse_face_window
= Qnil
;
669 /* (further code for mouse faces ifdef'd out in other terms elided) */
677 ns_update_window_end
(struct window
*w
, int cursor_on_p
,
678 int mouse_face_overwritten_p
)
679 /* --------------------------------------------------------------------------
680 Finished a grouped sequence of drawing calls
681 external (RIF) call; for one window called before update_end
682 -------------------------------------------------------------------------- */
684 Mouse_HLInfo
*hlinfo
= MOUSE_HL_INFO
(XFRAME
(w
->frame
));
686 /* note: this fn is nearly identical in all terms */
687 if (!w
->pseudo_window_p
)
692 display_and_set_cursor
(w
, 1,
693 output_cursor.hpos
, output_cursor.vpos
,
694 output_cursor.x
, output_cursor.y
);
696 if (draw_window_fringes
(w
, 1))
697 x_draw_vertical_border
(w
);
702 /* If a row with mouse-face was overwritten, arrange for
703 frame_up_to_date to redisplay the mouse highlight. */
704 if (mouse_face_overwritten_p
)
706 hlinfo
->mouse_face_beg_row
= hlinfo
->mouse_face_beg_col
= -1;
707 hlinfo
->mouse_face_end_row
= hlinfo
->mouse_face_end_col
= -1;
708 hlinfo
->mouse_face_window
= Qnil
;
711 updated_window
= NULL;
712 NSTRACE
(update_window_end
);
717 ns_update_end
(struct frame
*f
)
718 /* --------------------------------------------------------------------------
719 Finished a grouped sequence of drawing calls
720 external (RIF) call; for whole frame, called after update_window_end
721 -------------------------------------------------------------------------- */
723 NSView
*view = FRAME_NS_VIEW
(f
);
725 /* if (f == MOUSE_HL_INFO (f)->mouse_face_mouse_frame) */
726 MOUSE_HL_INFO
(f
)->mouse_face_defer
= 0;
730 #ifdef NS_IMPL_GNUSTEP
731 /* trigger flush only in the rectangle we tracked as being drawn */
732 [view unlockFocusNeedsFlush
: NO
];
733 /*fprintf (stderr, " (%.0f, %.0f : %.0f x %.0f)", uRect.origin.x, uRect.origin.y, uRect.size.width, uRect.size.height); */
734 [view lockFocusInRect
: uRect
];
738 [[view window
] flushWindow
];
741 ns_updating_frame
= NULL;
742 NSTRACE
(ns_update_end
);
747 ns_flush
(struct frame
*f
)
748 /* --------------------------------------------------------------------------
750 NS impl is no-op since currently we flush in ns_update_end and elsewhere
751 -------------------------------------------------------------------------- */
758 ns_focus
(struct frame
*f
, NSRect
*r
, int n
)
759 /* --------------------------------------------------------------------------
760 Internal: Focus on given frame. During small local updates this is used to
761 draw, however during large updates, ns_update_begin and ns_update_end are
762 called to wrap the whole thing, in which case these calls are stubbed out.
763 Except, on GNUstep, we accumulate the rectangle being drawn into, because
764 the back end won't do this automatically, and will just end up flushing
766 -------------------------------------------------------------------------- */
768 // NSTRACE
(ns_focus
);
769 #ifdef NS_IMPL_GNUSTEP
772 u
= NSUnionRect
(r
[0], r
[1]);
777 fprintf (stderr, "focus: %d", c++);
778 if (r) fprintf (stderr, " (%.0f, %.0f : %.0f x %.0f)", r->origin.x, r->origin.y, r->size.width, r->size.height);
779 fprintf (stderr, "\n"); */
781 if (f
!= ns_updating_frame
)
783 NSView
*view = FRAME_NS_VIEW
(f
);
784 if (view != focus_view
)
786 if (focus_view
!= NULL)
788 [focus_view unlockFocus
];
789 [[focus_view window
] flushWindow
];
794 #ifdef NS_IMPL_GNUSTEP
795 r ?
[view lockFocusInRect
: u
] : [view lockFocus
];
800 /*if (view) debug_lock++; */
802 #ifdef NS_IMPL_GNUSTEP
805 /* more than one rect being drawn into */
808 [view unlockFocus
]; /* add prev rect to redraw list */
809 [view lockFocusInRect
: u
]; /* focus for draw in new rect */
814 #ifdef NS_IMPL_GNUSTEP
817 /* in batch mode, but in GNUstep must still track rectangles explicitly */
818 uRect
= (r ? NSUnionRect
(uRect
, u
) : [FRAME_NS_VIEW
(f
) visibleRect
]);
825 [[NSGraphicsContext currentContext
] saveGraphicsState
];
827 NSRectClipList
(r
, 2);
836 ns_unfocus
(struct frame
*f
)
837 /* --------------------------------------------------------------------------
838 Internal: Remove focus on given frame
839 -------------------------------------------------------------------------- */
841 // NSTRACE
(ns_unfocus
);
845 [[NSGraphicsContext currentContext
] restoreGraphicsState
];
849 if (f
!= ns_updating_frame
)
851 if (focus_view
!= NULL)
853 [focus_view unlockFocus
];
854 [[focus_view window
] flushWindow
];
863 ns_clip_to_row
(struct window
*w
, struct glyph_row
*row
, int area
, BOOL gc
)
864 /* --------------------------------------------------------------------------
865 Internal (but parallels other terms): Focus drawing on given row
866 -------------------------------------------------------------------------- */
868 struct frame
*f
= XFRAME
(WINDOW_FRAME
(w
));
870 int window_x
, window_y
, window_width
;
872 window_box
(w
, area
, &window_x
, &window_y
, &window_width
, 0);
874 clip_rect.origin.x
= window_x
;
875 clip_rect.origin.y
= WINDOW_TO_FRAME_PIXEL_Y
(w
, max (0, row
->y
));
876 clip_rect.origin.y
= max (clip_rect.origin.y
, window_y
);
877 clip_rect.
size.width
= window_width
;
878 clip_rect.
size.height
= row
->visible_height
;
880 ns_focus
(f
, &clip_rect
, 1);
885 ns_ring_bell
(struct frame
*f
)
886 /* --------------------------------------------------------------------------
888 -------------------------------------------------------------------------- */
890 NSTRACE
(ns_ring_bell
);
893 NSAutoreleasePool
*pool
;
894 struct frame
*frame
= SELECTED_FRAME
();
898 pool
= [[NSAutoreleasePool alloc
] init
];
900 view = FRAME_NS_VIEW
(frame
);
904 NSPoint dim
= NSMakePoint
(128, 128);
907 r.origin.x
+= (r.
size.width
- dim.x
) / 2;
908 r.origin.y
+= (r.
size.height
- dim.y
) / 2;
909 r.
size.width
= dim.x
;
910 r.
size.height
= dim.y
;
911 surr
= NSInsetRect
(r
, -2, -2);
912 ns_focus
(frame
, &surr
, 1);
913 [[view window
] cacheImageInRect
: [view convertRect
: surr toView
:nil
]];
914 [ns_lookup_indexed_color
(NS_FACE_FOREGROUND
915 (FRAME_DEFAULT_FACE
(frame
)), frame
) set];
917 [[view window
] flushWindow
];
919 [[view window
] restoreCachedImage
];
920 [[view window
] flushWindow
];
934 ns_reset_terminal_modes
(struct terminal *terminal)
935 /* Externally called as hook */
937 NSTRACE
(ns_reset_terminal_modes
);
942 ns_set_terminal_modes
(struct terminal *terminal)
943 /* Externally called as hook */
945 NSTRACE
(ns_set_terminal_modes
);
950 /* ==========================================================================
952 Frame / window manager related functions
954 ========================================================================== */
958 ns_raise_frame
(struct frame
*f
)
959 /* --------------------------------------------------------------------------
960 Bring window to foreground and make it active
961 -------------------------------------------------------------------------- */
963 NSView
*view = FRAME_NS_VIEW
(f
);
966 FRAME_SAMPLE_VISIBILITY
(f
);
967 if (FRAME_VISIBLE_P
(f
))
969 [[view window
] makeKeyAndOrderFront
: NSApp
];
976 ns_lower_frame
(struct frame
*f
)
977 /* --------------------------------------------------------------------------
979 -------------------------------------------------------------------------- */
981 NSView
*view = FRAME_NS_VIEW
(f
);
984 [[view window
] orderBack
: NSApp
];
990 ns_frame_raise_lower
(struct frame
*f
, int raise
)
991 /* --------------------------------------------------------------------------
993 -------------------------------------------------------------------------- */
995 NSTRACE
(ns_frame_raise_lower
);
1005 ns_frame_rehighlight
(struct frame
*frame
)
1006 /* --------------------------------------------------------------------------
1007 External (hook): called on things like window switching within frame
1008 -------------------------------------------------------------------------- */
1010 struct ns_display_info
*dpyinfo
= FRAME_NS_DISPLAY_INFO
(frame
);
1011 struct frame
*old_highlight
= dpyinfo
->x_highlight_frame
;
1013 NSTRACE
(ns_frame_rehighlight
);
1014 if (dpyinfo
->x_focus_frame
)
1016 dpyinfo
->x_highlight_frame
1017 = (FRAMEP
(FRAME_FOCUS_FRAME
(dpyinfo
->x_focus_frame
))
1018 ? XFRAME
(FRAME_FOCUS_FRAME
(dpyinfo
->x_focus_frame
))
1019 : dpyinfo
->x_focus_frame
);
1020 if (!FRAME_LIVE_P
(dpyinfo
->x_highlight_frame
))
1022 fset_focus_frame
(dpyinfo
->x_focus_frame
, Qnil
);
1023 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
;
1027 dpyinfo
->x_highlight_frame
= 0;
1029 if (dpyinfo
->x_highlight_frame
&&
1030 dpyinfo
->x_highlight_frame
!= old_highlight
)
1034 x_update_cursor
(old_highlight
, 1);
1035 x_set_frame_alpha
(old_highlight
);
1037 if (dpyinfo
->x_highlight_frame
)
1039 x_update_cursor
(dpyinfo
->x_highlight_frame
, 1);
1040 x_set_frame_alpha
(dpyinfo
->x_highlight_frame
);
1047 x_make_frame_visible
(struct frame
*f
)
1048 /* --------------------------------------------------------------------------
1049 External: Show the window (X11 semantics)
1050 -------------------------------------------------------------------------- */
1052 NSTRACE
(x_make_frame_visible
);
1053 /* XXX: at some points in past this was not needed, as the only place that
1054 called this (frame.c:Fraise_frame ()) also called raise_lower;
1055 if this ends up the case again, comment this out again. */
1056 if (!FRAME_VISIBLE_P
(f
))
1058 f
->async_visible
= 1;
1065 x_make_frame_invisible
(struct frame
*f
)
1066 /* --------------------------------------------------------------------------
1067 External: Hide the window (X11 semantics)
1068 -------------------------------------------------------------------------- */
1070 NSView
* view = FRAME_NS_VIEW
(f
);
1071 NSTRACE
(x_make_frame_invisible
);
1073 [[view window
] orderOut
: NSApp
];
1074 f
->async_visible
= 0;
1075 f
->async_iconified
= 0;
1080 x_iconify_frame
(struct frame
*f
)
1081 /* --------------------------------------------------------------------------
1082 External: Iconify window
1083 -------------------------------------------------------------------------- */
1085 NSView
* view = FRAME_NS_VIEW
(f
);
1086 struct ns_display_info
*dpyinfo
= FRAME_NS_DISPLAY_INFO
(f
);
1087 NSTRACE
(x_iconify_frame
);
1090 if (dpyinfo
->x_highlight_frame
== f
)
1091 dpyinfo
->x_highlight_frame
= 0;
1093 if ([[view window
] windowNumber
] <= 0)
1095 /* the window is still deferred. Make it very small, bring it
1096 on screen and order it out. */
1097 NSRect s
= { { 100, 100}, {0, 0} };
1099 t
= [[view window
] frame
];
1100 [[view window
] setFrame
: s display
: NO
];
1101 [[view window
] orderBack
: NSApp
];
1102 [[view window
] orderOut
: NSApp
];
1103 [[view window
] setFrame
: t display
: NO
];
1105 [[view window
] miniaturize
: NSApp
];
1108 /* Free X resources of frame F. */
1111 x_free_frame_resources
(struct frame
*f
)
1113 NSView
*view = FRAME_NS_VIEW
(f
);
1114 struct ns_display_info
*dpyinfo
= FRAME_NS_DISPLAY_INFO
(f
);
1115 Mouse_HLInfo
*hlinfo
= MOUSE_HL_INFO
(f
);
1116 NSTRACE
(x_free_frame_resources
);
1119 [(EmacsView
*)view setWindowClosing
: YES
]; /* may not have been informed */
1123 free_frame_menubar
(f
);
1125 if (FRAME_FACE_CACHE
(f
))
1126 free_frame_faces
(f
);
1128 if (f
== dpyinfo
->x_focus_frame
)
1129 dpyinfo
->x_focus_frame
= 0;
1130 if (f
== dpyinfo
->x_highlight_frame
)
1131 dpyinfo
->x_highlight_frame
= 0;
1132 if (f
== hlinfo
->mouse_face_mouse_frame
)
1134 hlinfo
->mouse_face_beg_row
= hlinfo
->mouse_face_beg_col
= -1;
1135 hlinfo
->mouse_face_end_row
= hlinfo
->mouse_face_end_col
= -1;
1136 hlinfo
->mouse_face_window
= Qnil
;
1137 hlinfo
->mouse_face_deferred_gc
= 0;
1138 hlinfo
->mouse_face_mouse_frame
= 0;
1141 if (f
->output_data.ns
->miniimage
!= nil
)
1142 [f
->output_data.ns
->miniimage release
];
1144 [[view window
] close];
1147 xfree
(f
->output_data.ns
);
1153 x_destroy_window
(struct frame
*f
)
1154 /* --------------------------------------------------------------------------
1155 External: Delete the window
1156 -------------------------------------------------------------------------- */
1158 NSTRACE
(x_destroy_window
);
1160 x_free_frame_resources
(f
);
1166 x_set_offset
(struct frame
*f
, int xoff
, int yoff
, int change_grav
)
1167 /* --------------------------------------------------------------------------
1168 External: Position the window
1169 -------------------------------------------------------------------------- */
1171 NSView
*view = FRAME_NS_VIEW
(f
);
1172 NSArray
*screens
= [NSScreen screens
];
1173 NSScreen
*fscreen
= [screens objectAtIndex
: 0];
1174 NSScreen
*screen
= [[view window
] screen
];
1176 NSTRACE
(x_set_offset
);
1183 if (view != nil
&& screen
&& fscreen
)
1185 f
->left_pos
= f
->size_hint_flags
& XNegative
1186 ?
[screen visibleFrame
].
size.width
+ f
->left_pos
- FRAME_PIXEL_WIDTH
(f
)
1188 /* We use visibleFrame here to take menu bar into account.
1189 Ideally we should also adjust left/top with visibleFrame.origin. */
1191 f
->top_pos
= f
->size_hint_flags
& YNegative
1192 ?
([screen visibleFrame
].
size.height
+ f
->top_pos
1193 - FRAME_PIXEL_HEIGHT
(f
) - FRAME_NS_TITLEBAR_HEIGHT
(f
)
1194 - FRAME_TOOLBAR_HEIGHT
(f
))
1196 #ifdef NS_IMPL_GNUSTEP
1197 if (f
->left_pos
< 100)
1198 f
->left_pos
= 100; /* don't overlap menu */
1200 /* Constrain the setFrameTopLeftPoint so we don't move behind the
1202 f
->output_data.ns
->dont_constrain
= 0;
1203 [[view window
] setFrameTopLeftPoint
:
1204 NSMakePoint
(SCREENMAXBOUND
(f
->left_pos
),
1205 SCREENMAXBOUND
([fscreen frame
].
size.height
1206 - NS_TOP_POS
(f
)))];
1207 f
->size_hint_flags
&= ~
(XNegative|YNegative
);
1215 x_set_window_size
(struct frame
*f
, int change_grav
, int cols
, int rows
)
1216 /* --------------------------------------------------------------------------
1217 Adjust window pixel size based on given character grid size
1218 Impl is a bit more complex than other terms, need to do some
1220 -------------------------------------------------------------------------- */
1222 EmacsView
*view = FRAME_NS_VIEW
(f
);
1223 NSWindow
*window
= [view window
];
1224 NSRect wr
= [window frame
];
1225 int tb
= FRAME_EXTERNAL_TOOL_BAR
(f
);
1226 int pixelwidth
, pixelheight
;
1228 NSTRACE
(x_set_window_size
);
1233 /*fprintf (stderr, "\tsetWindowSize: %d x %d, font size %d x %d\n", cols, rows, FRAME_COLUMN_WIDTH (f), FRAME_LINE_HEIGHT (f)); */
1237 check_frame_size
(f
, &rows
, &cols
);
1239 f
->scroll_bar_actual_width
= NS_SCROLL_BAR_WIDTH
(f
);
1240 compute_fringe_widths
(f
, 0);
1242 pixelwidth
= FRAME_TEXT_COLS_TO_PIXEL_WIDTH
(f
, cols
);
1243 pixelheight
= FRAME_TEXT_LINES_TO_PIXEL_HEIGHT
(f
, rows
);
1245 /* If we have a toolbar, take its height into account. */
1247 /* NOTE: previously this would generate wrong result if toolbar not
1248 yet displayed and fixing toolbar_height=32 helped, but
1249 now (200903) seems no longer needed */
1250 FRAME_TOOLBAR_HEIGHT
(f
) =
1251 NSHeight
([window frameRectForContentRect
: NSMakeRect
(0, 0, 0, 0)])
1252 - FRAME_NS_TITLEBAR_HEIGHT
(f
);
1254 FRAME_TOOLBAR_HEIGHT
(f
) = 0;
1256 wr.
size.width
= pixelwidth
+ f
->border_width
;
1257 wr.
size.height
= pixelheight
+ FRAME_NS_TITLEBAR_HEIGHT
(f
)
1258 + FRAME_TOOLBAR_HEIGHT
(f
);
1260 /* Do not try to constrain to this screen. We may have multiple
1261 screens, and want Emacs to span those. Constraining to screen
1262 prevents that, and that is not nice to the user. */
1263 if (f
->output_data.ns
->zooming
)
1264 f
->output_data.ns
->zooming
= 0;
1266 wr.origin.y
+= FRAME_PIXEL_HEIGHT
(f
) - pixelheight
;
1268 [view setRows
: rows andColumns
: cols
];
1269 [window setFrame
: wr display
: YES
];
1271 /*fprintf (stderr, "\tx_set_window_size %d, %d\t%d, %d\n", cols, rows, pixelwidth, pixelheight); */
1273 /* This is a trick to compensate for Emacs' managing the scrollbar area
1274 as a fixed number of standard character columns. Instead of leaving
1275 blank space for the extra, we chopped it off above. Now for
1276 left-hand scrollbars, we shift all rendering to the left by the
1277 difference between the real width and Emacs' imagined one. For
1278 right-hand bars, don't worry about it since the extra is never used.
1279 (Obviously doesn't work for vertically split windows tho..) */
1281 NSPoint origin
= FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT
(f
)
1282 ? NSMakePoint
(FRAME_SCROLL_BAR_COLS
(f
) * FRAME_COLUMN_WIDTH
(f
)
1283 - NS_SCROLL_BAR_WIDTH
(f
), 0)
1284 : NSMakePoint
(0, 0);
1285 [view setFrame
: NSMakeRect
(0, 0, pixelwidth
, pixelheight
)];
1286 [view setBoundsOrigin
: origin
];
1289 change_frame_size
(f
, rows
, cols
, 0, 1, 0); /* pretend, delay, safe */
1290 FRAME_PIXEL_WIDTH
(f
) = pixelwidth
;
1291 FRAME_PIXEL_HEIGHT
(f
) = pixelheight
;
1292 /* SET_FRAME_GARBAGED (f); // this short-circuits expose call in drawRect */
1294 mark_window_cursors_off
(XWINDOW
(f
->root_window
));
1295 cancel_mouse_face
(f
);
1302 /* ==========================================================================
1306 ========================================================================== */
1310 ns_lookup_indexed_color
(unsigned
long idx
, struct frame
*f
)
1312 struct ns_color_table
*color_table
= FRAME_NS_DISPLAY_INFO
(f
)->color_table
;
1313 if (idx
< 1 || idx
>= color_table
->avail
)
1315 return color_table
->colors
[idx
];
1320 ns_index_color
(NSColor
*color
, struct frame
*f
)
1322 struct ns_color_table
*color_table
= FRAME_NS_DISPLAY_INFO
(f
)->color_table
;
1326 if (!color_table
->colors
)
1328 color_table
->size = NS_COLOR_CAPACITY
;
1329 color_table
->avail
= 1; /* skip idx=0 as marker */
1330 color_table
->colors
= xmalloc
(color_table
->size * sizeof
(NSColor
*));
1331 color_table
->colors
[0] = nil
;
1332 color_table
->empty_indices
= [[NSMutableSet alloc
] init
];
1335 /* do we already have this color ? */
1336 for (i
= 1; i
< color_table
->avail
; i
++)
1337 if (color_table
->colors
[i
] && [color_table
->colors
[i
] isEqual: color
])
1340 if ([color_table
->empty_indices count
] > 0)
1342 NSNumber
*index
= [color_table
->empty_indices anyObject
];
1343 [color_table
->empty_indices removeObject
: index
];
1344 idx
= [index unsignedLongValue
];
1348 if (color_table
->avail
== color_table
->size)
1349 color_table
->colors
=
1350 xpalloc
(color_table
->colors
, &color_table
->size, 1,
1351 min (ULONG_MAX
, PTRDIFF_MAX
), sizeof
*color_table
->colors
);
1352 idx
= color_table
->avail
++;
1355 color_table
->colors
[idx
] = color
;
1357 /*fprintf(stderr, "color_table: allocated %d\n",idx);*/
1363 ns_free_indexed_color
(unsigned
long idx
, struct frame
*f
)
1365 struct ns_color_table
*color_table
;
1372 color_table
= FRAME_NS_DISPLAY_INFO
(f
)->color_table
;
1374 if (idx
<= 0 || idx
>= color_table
->size) {
1375 message1
("ns_free_indexed_color
: Color index out of range.
\n"
);
1379 index
= [NSNumber numberWithUnsignedInt
: idx
];
1380 if ([color_table
->empty_indices containsObject
: index
]) {
1381 message1
("ns_free_indexed_color
: attempt to free already freed color.
\n"
);
1385 color
= color_table
->colors
[idx
];
1387 color_table
->colors
[idx
] = nil
;
1388 [color_table
->empty_indices addObject
: index
];
1389 /*fprintf(stderr, "color_table: FREED %d\n",idx);*/
1394 ns_get_color
(const
char *name
, NSColor
**col
)
1395 /* --------------------------------------------------------------------------
1397 -------------------------------------------------------------------------- */
1398 /* On *Step, we attempt to mimic the X11 platform here, down to installing an
1399 X11 rgb.txt-compatible color list in Emacs.clr (see ns_term_init()).
1400 See: http://thread.gmane.org/gmane.emacs.devel/113050/focus=113272). */
1403 static
char hex
[20];
1405 float r
= -1.0, g
, b
;
1406 NSString
*nsname
= [NSString stringWithUTF8String
: name
];
1408 /*fprintf (stderr, "ns_get_color: '%s'\n", name); */
1411 if ([nsname isEqualToString
: @"ns_selection_color"
])
1413 nsname
= ns_selection_color
;
1414 name
= [ns_selection_color UTF8String
];
1417 /* First, check for some sort of numeric specification. */
1420 if (name
[0] == '0' || name
[0] == '1' || name
[0] == '.') /* RGB decimal */
1422 NSScanner
*scanner
= [NSScanner scannerWithString
: nsname
];
1423 [scanner scanFloat
: &r
];
1424 [scanner scanFloat
: &g
];
1425 [scanner scanFloat
: &b
];
1427 else if (!strncmp
(name
, "rgb
:"
, 4)) /* A newer X11 format -- rgb:r/g/b */
1428 scaling
= (snprintf
(hex
, sizeof hex
, "
%s", name + 4) - 2) / 3;
1429 else if (name
[0] == '#') /* An old X11 format; convert to newer */
1431 int len
= (strlen
(name
) - 1);
1432 int start
= (len
% 3 == 0) ? 1 : len / 4 + 1;
1434 scaling
= strlen
(name
+start
) / 3;
1435 for (i
= 0; i
< 3; i
++)
1436 sprintf (hex
+ i
* (scaling
+ 1), "
%.*s/", scaling,
1437 name
+ start
+ i
* scaling
);
1438 hex
[3 * (scaling
+ 1) - 1] = '\0';
1444 float fscale
= scaling
== 4 ?
65535.0 : (scaling
== 2 ?
255.0 : 15.0);
1445 if (sscanf (hex
, "
%x/%x/%x", &rr, &gg, &bb))
1455 *col
= [NSColor colorWithCalibratedRed
: r green
: g blue
: b alpha
: 1.0];
1460 /* Otherwise, color is expected to be from a list */
1462 NSEnumerator
*lenum
, *cenum
;
1466 #ifdef NS_IMPL_GNUSTEP
1467 /* XXX: who is wrong, the requestor or the implementation? */
1468 if ([nsname compare
: @"Highlight" options
: NSCaseInsensitiveSearch
]
1470 nsname
= @"highlightColor"
;
1473 lenum
= [[NSColorList availableColorLists
] objectEnumerator
];
1474 while ( (clist
= [lenum nextObject
]) && new
== nil
)
1476 cenum
= [[clist allKeys
] objectEnumerator
];
1477 while ( (name
= [cenum nextObject
]) && new
== nil
)
1479 if ([name compare
: nsname
1480 options
: NSCaseInsensitiveSearch
] == NSOrderedSame
)
1481 new
= [clist colorWithKey
: name
];
1487 *col
= [new colorUsingColorSpaceName
: NSCalibratedRGBColorSpace
];
1494 ns_lisp_to_color
(Lisp_Object color
, NSColor
**col
)
1495 /* --------------------------------------------------------------------------
1496 Convert a Lisp string object to a NS color
1497 -------------------------------------------------------------------------- */
1499 NSTRACE
(ns_lisp_to_color
);
1500 if (STRINGP
(color
))
1501 return ns_get_color
(SSDATA
(color
), col
);
1502 else if (SYMBOLP
(color
))
1503 return ns_get_color
(SSDATA
(SYMBOL_NAME
(color
)), col
);
1509 ns_color_to_lisp
(NSColor
*col
)
1510 /* --------------------------------------------------------------------------
1511 Convert a color to a lisp string with the RGB equivalent
1512 -------------------------------------------------------------------------- */
1514 CGFloat red
, green
, blue
, alpha
, gray;
1517 NSTRACE
(ns_color_to_lisp
);
1520 if ([[col colorSpaceName
] isEqualToString
: NSNamedColorSpace
])
1522 if ((str
=[[col colorNameComponent
] UTF8String
]))
1525 return build_string
((char *)str
);
1528 [[col colorUsingColorSpaceName
: NSCalibratedRGBColorSpace
]
1529 getRed
: &red green
: &green blue
: &blue alpha
: &alpha
];
1530 if (red
==green
&& red
==blue
)
1532 [[col colorUsingColorSpaceName
: NSCalibratedWhiteColorSpace
]
1533 getWhite
: &gray alpha
: &alpha
];
1534 snprintf
(buf
, sizeof
(buf
), "#
%2.2lx%2.2lx%2.2lx",
1535 lrint
(gray * 0xff), lrint
(gray * 0xff), lrint
(gray * 0xff));
1537 return build_string
(buf
);
1540 snprintf
(buf
, sizeof
(buf
), "#
%2.2lx%2.2lx%2.2lx",
1541 lrint
(red
*0xff), lrint
(green
*0xff), lrint
(blue
*0xff));
1544 return build_string
(buf
);
1549 ns_query_color
(void
*col
, XColor
*color_def
, int setPixel
)
1550 /* --------------------------------------------------------------------------
1551 Get ARGB values out of NSColor col and put them into color_def.
1552 If setPixel, set the pixel to a concatenated version.
1553 and set color_def pixel to the resulting index.
1554 -------------------------------------------------------------------------- */
1558 [((NSColor
*)col
) getRed
: &r green
: &g blue
: &b alpha
: &a
];
1559 color_def
->red
= r
* 65535;
1560 color_def
->green
= g
* 65535;
1561 color_def
->blue
= b
* 65535;
1563 if (setPixel
== YES
)
1565 = ARGB_TO_ULONG
((int
)(a
*255),
1566 (int
)(r
*255), (int
)(g
*255), (int
)(b
*255));
1571 ns_defined_color
(struct frame
*f
,
1576 /* --------------------------------------------------------------------------
1577 Return 1 if named color found, and set color_def rgb accordingly.
1578 If makeIndex and alloc are nonzero put the color in the color_table,
1579 and set color_def pixel to the resulting index.
1580 If makeIndex is zero, set color_def pixel to ARGB.
1581 Return 0 if not found
1582 -------------------------------------------------------------------------- */
1585 NSTRACE
(ns_defined_color
);
1588 if (ns_get_color
(name
, &col
) != 0) /* Color not found */
1593 if (makeIndex
&& alloc
)
1594 color_def
->pixel
= ns_index_color
(col
, f
);
1595 ns_query_color
(col
, color_def
, !makeIndex
);
1602 ns_get_rgb_color
(struct frame
*f
, float r
, float g
, float b
, float a
)
1603 /* --------------------------------------------------------------------------
1604 return an autoreleased RGB color
1605 -------------------------------------------------------------------------- */
1607 /*static int c = 1; fprintf (stderr, "color request %d\n", c++); */
1608 if (r
< 0.0) r
= 0.0;
1609 else if (r
> 1.0) r
= 1.0;
1610 if (g
< 0.0) g
= 0.0;
1611 else if (g
> 1.0) g
= 1.0;
1612 if (b
< 0.0) b
= 0.0;
1613 else if (b
> 1.0) b
= 1.0;
1614 if (a
< 0.0) a
= 0.0;
1615 else if (a
> 1.0) a
= 1.0;
1616 return (unsigned
long) ns_index_color
(
1617 [NSColor colorWithCalibratedRed
: r green
: g blue
: b alpha
: a
], f
);
1622 x_set_frame_alpha
(struct frame
*f
)
1623 /* --------------------------------------------------------------------------
1624 change the entire-frame transparency
1625 -------------------------------------------------------------------------- */
1627 struct ns_display_info
*dpyinfo
= FRAME_NS_DISPLAY_INFO
(f
);
1628 EmacsView
*view = FRAME_NS_VIEW
(f
);
1630 double alpha_min
= 1.0;
1632 if (dpyinfo
->x_highlight_frame
== f
)
1633 alpha
= f
->alpha
[0];
1635 alpha
= f
->alpha
[1];
1637 if (FLOATP
(Vframe_alpha_lower_limit
))
1638 alpha_min
= XFLOAT_DATA
(Vframe_alpha_lower_limit
);
1639 else if (INTEGERP
(Vframe_alpha_lower_limit
))
1640 alpha_min
= (XINT
(Vframe_alpha_lower_limit
)) / 100.0;
1644 else if (1.0 < alpha
)
1646 else if (0.0 <= alpha
&& alpha
< alpha_min
&& alpha_min
<= 1.0)
1649 #ifdef NS_IMPL_COCOA
1650 [[view window
] setAlphaValue
: alpha
];
1655 /* ==========================================================================
1659 ========================================================================== */
1663 x_set_mouse_pixel_position
(struct frame
*f
, int pix_x
, int pix_y
)
1664 /* --------------------------------------------------------------------------
1665 Programmatically reposition mouse pointer in pixel coordinates
1666 -------------------------------------------------------------------------- */
1668 NSTRACE
(x_set_mouse_pixel_position
);
1671 /* FIXME: this does not work, and what about GNUstep? */
1672 #ifdef NS_IMPL_COCOA
1673 [FRAME_NS_VIEW
(f
) lockFocus
];
1674 PSsetmouse
((float
)pix_x
, (float
)pix_y
);
1675 [FRAME_NS_VIEW
(f
) unlockFocus
];
1682 x_set_mouse_position
(struct frame
*f
, int h
, int v
)
1683 /* --------------------------------------------------------------------------
1684 Programmatically reposition mouse pointer in character coordinates
1685 -------------------------------------------------------------------------- */
1689 pix_x
= FRAME_COL_TO_PIXEL_X
(f
, h
) + FRAME_COLUMN_WIDTH
(f
) / 2;
1690 pix_y
= FRAME_LINE_TO_PIXEL_Y
(f
, v
) + FRAME_LINE_HEIGHT
(f
) / 2;
1692 if (pix_x
< 0) pix_x
= 0;
1693 if (pix_x
> FRAME_PIXEL_WIDTH
(f
)) pix_x
= FRAME_PIXEL_WIDTH
(f
);
1695 if (pix_y
< 0) pix_y
= 0;
1696 if (pix_y
> FRAME_PIXEL_HEIGHT
(f
)) pix_y
= FRAME_PIXEL_HEIGHT
(f
);
1698 x_set_mouse_pixel_position
(f
, pix_x
, pix_y
);
1703 note_mouse_movement
(struct frame
*frame
, float x
, float y
)
1704 /* ------------------------------------------------------------------------
1705 Called by EmacsView on mouseMovement events. Passes on
1706 to emacs mainstream code if we moved off of a rect of interest
1707 known as last_mouse_glyph.
1708 ------------------------------------------------------------------------ */
1710 // NSTRACE
(note_mouse_movement
);
1712 XSETFRAME
(last_mouse_motion_frame
, frame
);
1714 /* Note, this doesn't get called for enter/leave, since we don't have a
1715 position. Those are taken care of in the corresponding NSView methods. */
1717 /* has movement gone beyond last rect we were tracking? */
1718 if (x
< last_mouse_glyph.origin.x ||
1719 x
>= (last_mouse_glyph.origin.x
+ last_mouse_glyph.
size.width
) ||
1720 y
< last_mouse_glyph.origin.y ||
1721 y
>= (last_mouse_glyph.origin.y
+ last_mouse_glyph.
size.height
))
1723 ns_update_begin
(frame
);
1724 frame
->mouse_moved
= 1;
1725 note_mouse_highlight
(frame
, x
, y
);
1726 remember_mouse_glyph
(frame
, x
, y
, &last_mouse_glyph
);
1727 ns_update_end
(frame
);
1736 ns_mouse_position
(struct frame
**fp
, int insist
, Lisp_Object
*bar_window
,
1737 enum scroll_bar_part
*part
, Lisp_Object
*x
, Lisp_Object
*y
,
1739 /* --------------------------------------------------------------------------
1740 External (hook): inform emacs about mouse position and hit parts.
1741 If a scrollbar is being dragged, set bar_window, part, x, y, time.
1742 x & y should be position in the scrollbar (the whole bar, not the handle)
1743 and length of scrollbar respectively
1744 -------------------------------------------------------------------------- */
1748 Lisp_Object frame
, tail
;
1750 struct ns_display_info
*dpyinfo
;
1752 NSTRACE
(ns_mouse_position
);
1756 fprintf (stderr
, "Warning
: ns_mouse_position
() called with
null *fp.
\n"
);
1760 dpyinfo
= FRAME_NS_DISPLAY_INFO
(*fp
);
1764 if (last_mouse_scroll_bar
!= nil
&& insist
== 0)
1766 /* TODO: we do not use this path at the moment because drag events will
1767 go directly to the EmacsScroller. Leaving code in for now. */
1768 [last_mouse_scroll_bar getMouseMotionPart
: (int
*)part window
: bar_window
1770 if (time
) *time
= last_mouse_movement_time
;
1771 last_mouse_scroll_bar
= nil
;
1775 /* Clear the mouse-moved flag for every frame on this display. */
1776 FOR_EACH_FRAME
(tail
, frame
)
1777 if (FRAME_NS_P
(XFRAME
(frame
))
1778 && FRAME_NS_DISPLAY
(XFRAME
(frame
)) == FRAME_NS_DISPLAY
(*fp
))
1779 XFRAME
(frame
)->mouse_moved
= 0;
1781 last_mouse_scroll_bar
= nil
;
1782 if (last_mouse_frame
&& FRAME_LIVE_P
(last_mouse_frame
))
1783 f
= last_mouse_frame
;
1785 f
= dpyinfo
->x_focus_frame ? dpyinfo
->x_focus_frame
1786 : SELECTED_FRAME
();
1788 if (f
&& f
->output_data.ns
) /* TODO: 2nd check no longer needed? */
1790 view = FRAME_NS_VIEW
(*fp
);
1792 position
= [[view window
] mouseLocationOutsideOfEventStream
];
1793 position
= [view convertPoint
: position fromView
: nil
];
1794 remember_mouse_glyph
(f
, position.x
, position.y
, &last_mouse_glyph
);
1795 /*fprintf (stderr, "ns_mouse_position: %.0f, %.0f\n", position.x, position.y); */
1797 if (bar_window
) *bar_window
= Qnil
;
1798 if (part
) *part
= 0; /*scroll_bar_handle; */
1800 if (x
) XSETINT
(*x
, lrint
(position.x
));
1801 if (y
) XSETINT
(*y
, lrint
(position.y
));
1802 if (time
) *time
= last_mouse_movement_time
;
1812 ns_frame_up_to_date
(struct frame
*f
)
1813 /* --------------------------------------------------------------------------
1814 External (hook): Fix up mouse highlighting right after a full update.
1815 Some highlighting was deferred if GC was happening during
1816 note_mouse_highlight (), while other highlighting was deferred for update.
1817 -------------------------------------------------------------------------- */
1819 NSTRACE
(ns_frame_up_to_date
);
1823 Mouse_HLInfo
*hlinfo
= MOUSE_HL_INFO
(f
);
1824 if ((hlinfo
->mouse_face_deferred_gc || f
==hlinfo
->mouse_face_mouse_frame
)
1825 /*&& hlinfo->mouse_face_mouse_frame*/)
1829 if (hlinfo
->mouse_face_mouse_frame
)
1830 note_mouse_highlight
(hlinfo
->mouse_face_mouse_frame
,
1831 hlinfo
->mouse_face_mouse_x
,
1832 hlinfo
->mouse_face_mouse_y
);
1833 hlinfo
->mouse_face_deferred_gc
= 0;
1842 ns_define_frame_cursor
(struct frame
*f
, Cursor cursor
)
1843 /* --------------------------------------------------------------------------
1844 External (RIF): set frame mouse pointer type.
1845 -------------------------------------------------------------------------- */
1847 NSTRACE
(ns_define_frame_cursor
);
1848 if (FRAME_POINTER_TYPE
(f
) != cursor
)
1850 EmacsView
*view = FRAME_NS_VIEW
(f
);
1851 FRAME_POINTER_TYPE
(f
) = cursor
;
1852 [[view window
] invalidateCursorRectsForView
: view];
1853 /* Redisplay assumes this function also draws the changed frame
1854 cursor, but this function doesn't, so do it explicitly. */
1855 x_update_cursor
(f
, 1);
1861 /* ==========================================================================
1865 ========================================================================== */
1869 ns_convert_key
(unsigned code
)
1870 /* --------------------------------------------------------------------------
1871 Internal call used by NSView-keyDown.
1872 -------------------------------------------------------------------------- */
1874 const unsigned last_keysym
= (sizeof
(convert_ns_to_X_keysym
)
1875 / sizeof
(convert_ns_to_X_keysym
[0]));
1877 /* An array would be faster, but less easy to read. */
1878 for (keysym
= 0; keysym
< last_keysym
; keysym
+= 2)
1879 if (code
== convert_ns_to_X_keysym
[keysym
])
1880 return 0xFF00 | convert_ns_to_X_keysym
[keysym
+1];
1882 /* if decide to use keyCode and Carbon table, use this line:
1883 return code > 0xff ? 0 : 0xFF00 | ns_keycode_to_xkeysym_table[code]; */
1888 x_get_keysym_name
(int keysym
)
1889 /* --------------------------------------------------------------------------
1890 Called by keyboard.c. Not sure if the return val is important, except
1892 -------------------------------------------------------------------------- */
1894 static
char value
[16];
1895 NSTRACE
(x_get_keysym_name
);
1896 sprintf (value
, "
%d", keysym);
1902 /* ==========================================================================
1904 Block drawing operations
1906 ========================================================================== */
1910 ns_redraw_scroll_bars
(struct frame
*f
)
1914 NSArray
*subviews
= [[FRAME_NS_VIEW
(f
) superview
] subviews
];
1915 NSTRACE
(ns_redraw_scroll_bars
);
1916 for (i
=[subviews count
]-1; i
>= 0; i
--)
1918 view = [subviews objectAtIndex
: i
];
1919 if (![view isKindOfClass
: [EmacsScroller
class]]) continue
;
1926 ns_clear_frame
(struct frame
*f
)
1927 /* --------------------------------------------------------------------------
1928 External (hook): Erase the entire frame
1929 -------------------------------------------------------------------------- */
1931 NSView
*view = FRAME_NS_VIEW
(f
);
1934 NSTRACE
(ns_clear_frame
);
1938 /* comes on initial frame because we have
1939 after-make-frame-functions = select-frame */
1940 if (!FRAME_DEFAULT_FACE
(f
))
1943 mark_window_cursors_off
(XWINDOW
(FRAME_ROOT_WINDOW
(f
)));
1945 output_cursor.hpos
= output_cursor.vpos
= 0;
1946 output_cursor.x
= -1;
1951 ns_focus
(f
, &r
, 1);
1952 [ns_lookup_indexed_color
(NS_FACE_BACKGROUND
(FRAME_DEFAULT_FACE
(f
)), f
) set];
1956 #ifdef NS_IMPL_COCOA
1957 [[view window
] display
]; /* redraw resize handle */
1960 /* as of 2006/11 or so this is now needed */
1961 ns_redraw_scroll_bars
(f
);
1967 ns_clear_frame_area
(struct frame
*f
, int x
, int y
, int width
, int height
)
1968 /* --------------------------------------------------------------------------
1969 External (RIF): Clear section of frame
1970 -------------------------------------------------------------------------- */
1972 NSRect r
= NSMakeRect
(x
, y
, width
, height
);
1973 NSView
*view = FRAME_NS_VIEW
(f
);
1974 struct face
*face
= FRAME_DEFAULT_FACE
(f
);
1979 NSTRACE
(ns_clear_frame_area
);
1981 r
= NSIntersectionRect
(r
, [view frame
]);
1982 ns_focus
(f
, &r
, 1);
1983 [ns_lookup_indexed_color
(NS_FACE_BACKGROUND
(face
), f
) set];
1985 #ifdef NS_IMPL_COCOA
1987 /* clip out the resize handle */
1988 NSWindow
*window
= [FRAME_NS_VIEW
(f
) window
];
1990 = [view convertRect
: ns_resize_handle_rect
(window
) fromView
: nil
];
1992 ir
= NSIntersectionRect
(r
, ir
);
1993 if (NSIsEmptyRect
(ir
))
1999 #ifdef NS_IMPL_COCOA
2003 NSRect r1
= r
, r2
= r
; /* upper and lower non-intersecting */
2004 r1.
size.height
-= ir.
size.height
;
2005 r2.origin.y
+= r1.
size.height
;
2006 r2.
size.width
-= ir.
size.width
;
2007 r2.
size.height
= ir.
size.height
;
2020 ns_scroll_run
(struct window
*w
, struct run
*run
)
2021 /* --------------------------------------------------------------------------
2022 External (RIF): Insert or delete n lines at line vpos
2023 -------------------------------------------------------------------------- */
2025 struct frame
*f
= XFRAME
(w
->frame
);
2026 int x
, y
, width
, height
, from_y
, to_y
, bottom_y
;
2028 NSTRACE
(ns_scroll_run
);
2030 /* begin copy from other terms */
2031 /* Get frame-relative bounding box of the text display area of W,
2032 without mode lines. Include in this box the left and right
2034 window_box
(w
, -1, &x
, &y
, &width
, &height
);
2036 from_y
= WINDOW_TO_FRAME_PIXEL_Y
(w
, run
->current_y
);
2037 to_y
= WINDOW_TO_FRAME_PIXEL_Y
(w
, run
->desired_y
);
2038 bottom_y
= y
+ height
;
2042 /* Scrolling up. Make sure we don't copy part of the mode
2043 line at the bottom. */
2044 if (from_y
+ run
->height
> bottom_y
)
2045 height
= bottom_y
- from_y
;
2047 height
= run
->height
;
2051 /* Scrolling down. Make sure we don't copy over the mode line.
2053 if (to_y
+ run
->height
> bottom_y
)
2054 height
= bottom_y
- to_y
;
2056 height
= run
->height
;
2058 /* end copy from other terms */
2069 NSRect srcRect
= NSMakeRect
(x
, from_y
, width
, height
);
2070 NSRect dstRect
= NSMakeRect
(x
, to_y
, width
, height
);
2071 NSPoint dstOrigin
= NSMakePoint
(x
, to_y
);
2073 ns_focus
(f
, &dstRect
, 1);
2074 NSCopyBits
(0, srcRect
, dstOrigin
);
2083 ns_after_update_window_line
(struct glyph_row
*desired_row
)
2084 /* --------------------------------------------------------------------------
2085 External (RIF): preparatory to fringe update after text was updated
2086 -------------------------------------------------------------------------- */
2088 struct window
*w
= updated_window
;
2092 NSTRACE
(ns_after_update_window_line
);
2094 /* begin copy from other terms */
2097 if (!desired_row
->mode_line_p
&& !w
->pseudo_window_p
)
2098 desired_row
->redraw_fringe_bitmaps_p
= 1;
2100 /* When a window has disappeared, make sure that no rest of
2101 full-width rows stays visible in the internal border. */
2102 if (windows_or_buffers_changed
2103 && desired_row
->full_width_p
2104 && (f
= XFRAME
(w
->frame
),
2105 width
= FRAME_INTERNAL_BORDER_WIDTH
(f
),
2107 && (height
= desired_row
->visible_height
,
2110 int y
= WINDOW_TO_FRAME_PIXEL_Y
(w
, max (0, desired_row
->y
));
2113 ns_clear_frame_area
(f
, 0, y
, width
, height
);
2114 ns_clear_frame_area
(f
,
2115 FRAME_PIXEL_WIDTH
(f
) - width
,
2123 ns_shift_glyphs_for_insert
(struct frame
*f
,
2124 int x
, int y
, int width
, int height
,
2126 /* --------------------------------------------------------------------------
2127 External (RIF): copy an area horizontally, don't worry about clearing src
2128 -------------------------------------------------------------------------- */
2130 NSRect srcRect
= NSMakeRect
(x
, y
, width
, height
);
2131 NSRect dstRect
= NSMakeRect
(x
+shift_by
, y
, width
, height
);
2132 NSPoint dstOrigin
= dstRect.origin
;
2134 NSTRACE
(ns_shift_glyphs_for_insert
);
2136 ns_focus
(f
, &dstRect
, 1);
2137 NSCopyBits
(0, srcRect
, dstOrigin
);
2143 /* ==========================================================================
2145 Character encoding and metrics
2147 ========================================================================== */
2151 ns_compute_glyph_string_overhangs
(struct glyph_string
*s
)
2152 /* --------------------------------------------------------------------------
2153 External (RIF); compute left/right overhang of whole string and set in s
2154 -------------------------------------------------------------------------- */
2156 struct font
*font
= s
->font
;
2160 struct font_metrics metrics
;
2161 unsigned int codes
[2];
2162 codes
[0] = *(s
->char2b
);
2163 codes
[1] = *(s
->char2b
+ s
->nchars
- 1);
2165 font
->driver
->text_extents
(font
, codes
, 2, &metrics
);
2166 s
->left_overhang
= -metrics.lbearing
;
2168 = metrics.rbearing
> metrics.width
2169 ? metrics.rbearing
- metrics.width
: 0;
2173 s
->left_overhang
= 0;
2174 s
->right_overhang
= ((struct nsfont_info
*)font
)->ital ?
2175 FONT_HEIGHT
(font
) * 0.2 : 0;
2181 /* ==========================================================================
2183 Fringe and cursor drawing
2185 ========================================================================== */
2188 extern int max_used_fringe_bitmap
;
2190 ns_draw_fringe_bitmap
(struct window
*w
, struct glyph_row
*row
,
2191 struct draw_fringe_bitmap_params
*p
)
2192 /* --------------------------------------------------------------------------
2193 External (RIF); fringe-related
2194 -------------------------------------------------------------------------- */
2196 struct frame
*f
= XFRAME
(WINDOW_FRAME
(w
));
2197 struct face
*face
= p
->face
;
2199 static EmacsImage
**bimgs
= NULL;
2200 static int nBimgs
= 0;
2202 /* grow bimgs if needed */
2203 if (nBimgs
< max_used_fringe_bitmap
)
2205 bimgs
= xrealloc
(bimgs
, max_used_fringe_bitmap
* sizeof
*bimgs
);
2206 memset
(bimgs
+ nBimgs
, 0,
2207 (max_used_fringe_bitmap
- nBimgs
) * sizeof
*bimgs
);
2208 nBimgs
= max_used_fringe_bitmap
;
2211 /* Must clip because of partially visible lines. */
2212 rowY
= WINDOW_TO_FRAME_PIXEL_Y
(w
, row
->y
);
2213 ns_clip_to_row
(w
, row
, -1, YES
);
2217 int bx
= p
->bx
, by
= p
->by
, nx
= p
->nx
, ny
= p
->ny
;
2219 /* If the fringe is adjacent to the left (right) scroll bar of a
2220 leftmost (rightmost, respectively) window, then extend its
2221 background to the gap between the fringe and the bar. */
2222 if ((WINDOW_LEFTMOST_P
(w
)
2223 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT
(w
))
2224 ||
(WINDOW_RIGHTMOST_P
(w
)
2225 && WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_RIGHT
(w
)))
2227 int sb_width
= WINDOW_CONFIG_SCROLL_BAR_WIDTH
(w
);
2231 int bar_area_x
= WINDOW_SCROLL_BAR_AREA_X
(w
);
2232 int bar_area_width
= (WINDOW_CONFIG_SCROLL_BAR_COLS
(w
)
2233 * FRAME_COLUMN_WIDTH
(f
));
2237 /* Bitmap fills the fringe. */
2238 if (bar_area_x
+ bar_area_width
== p
->x
)
2239 bx
= bar_area_x
+ sb_width
;
2240 else if (p
->x
+ p
->wd
== bar_area_x
)
2244 int header_line_height
= WINDOW_HEADER_LINE_HEIGHT
(w
);
2246 nx
= bar_area_width
- sb_width
;
2247 by
= WINDOW_TO_FRAME_PIXEL_Y
(w
, max (header_line_height
,
2249 ny
= row
->visible_height
;
2254 if (bar_area_x
+ bar_area_width
== bx
)
2256 bx
= bar_area_x
+ sb_width
;
2257 nx
+= bar_area_width
- sb_width
;
2259 else if (bx
+ nx
== bar_area_x
)
2260 nx
+= bar_area_width
- sb_width
;
2265 if (bx
>= 0 && nx
> 0)
2267 NSRect r
= NSMakeRect
(bx
, by
, nx
, ny
);
2269 [ns_lookup_indexed_color
(face
->background
, f
) set];
2276 NSRect r
= NSMakeRect
(p
->x
, p
->y
, p
->wd
, p
->h
);
2277 EmacsImage
*img
= bimgs
[p
->which - 1];
2281 unsigned short
*bits
= p
->bits
+ p
->dh
;
2284 unsigned
char *cbits
= xmalloc
(len
);
2286 for (i
= 0; i
< len
; i
++)
2287 cbits
[i
] = ~
(bits
[i
] & 0xff);
2288 img
= [[EmacsImage alloc
] initFromXBM
: cbits width
: 8 height
: p
->h
2290 bimgs
[p
->which - 1] = img
;
2295 /* Since we composite the bitmap instead of just blitting it, we need
2296 to erase the whole background. */
2297 [ns_lookup_indexed_color
(face
->background
, f
) set];
2299 [img setXBMColor
: ns_lookup_indexed_color
(face
->foreground
, f
)];
2301 fromRect
: NSZeroRect
2302 operation
: NSCompositeSourceOver
2312 ns_draw_window_cursor
(struct window
*w
, struct glyph_row
*glyph_row
,
2313 int x
, int y
, int cursor_type
, int cursor_width
,
2314 int on_p
, int active_p
)
2315 /* --------------------------------------------------------------------------
2316 External call (RIF): draw cursor.
2317 Note that CURSOR_WIDTH is meaningful only for (h)bar cursors.
2318 -------------------------------------------------------------------------- */
2321 int fx
, fy
, h
, cursor_height
;
2322 struct frame
*f
= WINDOW_XFRAME
(w
);
2323 struct glyph
*phys_cursor_glyph
;
2325 struct glyph
*cursor_glyph
;
2327 NSColor
*hollow_color
= FRAME_BACKGROUND_COLOR
(f
);
2329 /* If cursor is out of bounds, don't draw garbage. This can happen
2330 in mini-buffer windows when switching between echo area glyphs
2333 NSTRACE
(dumpcursor
);
2338 w
->phys_cursor_type
= cursor_type
;
2339 w
->phys_cursor_on_p
= on_p
;
2341 if (cursor_type
== NO_CURSOR
)
2343 w
->phys_cursor_width
= 0;
2347 if ((phys_cursor_glyph
= get_phys_cursor_glyph
(w
)) == NULL)
2349 if (glyph_row
->exact_window_width_line_p
2350 && w
->phys_cursor.hpos
>= glyph_row
->used
[TEXT_AREA
])
2352 glyph_row
->cursor_in_fringe_p
= 1;
2353 draw_fringe_bitmap
(w
, glyph_row
, 0);
2358 /* We draw the cursor (with NSRectFill), then draw the glyph on top
2359 (other terminals do it the other way round). We must set
2360 w->phys_cursor_width to the cursor width. For bar cursors, that
2361 is CURSOR_WIDTH; for box cursors, it is the glyph width. */
2362 get_phys_cursor_geometry
(w
, glyph_row
, phys_cursor_glyph
, &fx
, &fy
, &h
);
2364 /* The above get_phys_cursor_geometry call set w->phys_cursor_width
2365 to the glyph width; replace with CURSOR_WIDTH for (V)BAR cursors. */
2366 if (cursor_type
== BAR_CURSOR
)
2368 if (cursor_width
< 1)
2369 cursor_width
= max (FRAME_CURSOR_WIDTH
(f
), 1);
2370 w
->phys_cursor_width
= cursor_width
;
2372 /* If we have an HBAR, "cursor_width" MAY specify height. */
2373 else if (cursor_type
== HBAR_CURSOR
)
2375 cursor_height
= (cursor_width
< 1) ? lrint
(0.25 * h
) : cursor_width
;
2376 fy
+= h
- cursor_height
;
2380 r.origin.x
= fx
, r.origin.y
= fy
;
2382 r.
size.width
= w
->phys_cursor_width
;
2384 /* TODO: only needed in rare cases with last-resort font in HELLO..
2385 should we do this more efficiently? */
2386 ns_clip_to_row
(w
, glyph_row
, -1, NO
); /* do ns_focus(f, &r, 1); if remove */
2389 face
= FACE_FROM_ID
(f
, phys_cursor_glyph
->face_id
);
2390 if (face
&& NS_FACE_BACKGROUND
(face
)
2391 == ns_index_color
(FRAME_CURSOR_COLOR
(f
), f
))
2393 [ns_lookup_indexed_color
(NS_FACE_FOREGROUND
(face
), f
) set];
2394 hollow_color
= FRAME_CURSOR_COLOR
(f
);
2397 [FRAME_CURSOR_COLOR
(f
) set];
2399 #ifdef NS_IMPL_COCOA
2400 /* TODO: This makes drawing of cursor plus that of phys_cursor_glyph
2401 atomic. Cleaner ways of doing this should be investigated.
2402 One way would be to set a global variable DRAWING_CURSOR
2403 when making the call to draw_phys..(), don't focus in that
2404 case, then move the ns_unfocus() here after that call. */
2405 NSDisableScreenUpdates
();
2408 switch (cursor_type
)
2412 case FILLED_BOX_CURSOR
:
2415 case HOLLOW_BOX_CURSOR
:
2418 NSRectFill
(NSInsetRect
(r
, 1, 1));
2419 [FRAME_CURSOR_COLOR
(f
) set];
2426 /* If the character under cursor is R2L, draw the bar cursor
2427 on the right of its glyph, rather than on the left. */
2428 cursor_glyph
= get_phys_cursor_glyph
(w
);
2429 if ((cursor_glyph
->resolved_level
& 1) != 0)
2430 s.origin.x
+= cursor_glyph
->pixel_width
- s.
size.width
;
2437 /* draw the character under the cursor */
2438 if (cursor_type
!= NO_CURSOR
)
2439 draw_phys_cursor_glyph
(w
, glyph_row
, DRAW_CURSOR
);
2441 #ifdef NS_IMPL_COCOA
2442 NSEnableScreenUpdates
();
2449 ns_draw_vertical_window_border
(struct window
*w
, int x
, int y0
, int y1
)
2450 /* --------------------------------------------------------------------------
2451 External (RIF): Draw a vertical line.
2452 -------------------------------------------------------------------------- */
2454 struct frame
*f
= XFRAME
(WINDOW_FRAME
(w
));
2456 NSRect r
= NSMakeRect
(x
, y0
, 1, y1
-y0
);
2458 NSTRACE
(ns_draw_vertical_window_border
);
2460 face
= FACE_FROM_ID
(f
, VERTICAL_BORDER_FACE_ID
);
2462 [ns_lookup_indexed_color
(face
->foreground
, f
) set];
2464 ns_focus
(f
, &r
, 1);
2471 show_hourglass
(struct atimer
*timer
)
2473 if (hourglass_shown_p
)
2478 /* TODO: add NSProgressIndicator to selected frame (see macfns.c) */
2480 hourglass_shown_p
= 1;
2486 hide_hourglass
(void
)
2488 if (!hourglass_shown_p
)
2493 /* TODO: remove NSProgressIndicator from all frames */
2495 hourglass_shown_p
= 0;
2501 /* ==========================================================================
2503 Glyph drawing operations
2505 ========================================================================== */
2508 ns_get_glyph_string_clip_rect
(struct glyph_string
*s
, NativeRectangle
*nr
)
2509 /* --------------------------------------------------------------------------
2510 Wrapper utility to account for internal border width on full-width lines,
2511 and allow top full-width rows to hit the frame top. nr should be pointer
2512 to two successive NSRects. Number of rects actually used is returned.
2513 -------------------------------------------------------------------------- */
2515 int n
= get_glyph_string_clip_rects
(s
, nr
, 2);
2519 /* --------------------------------------------------------------------
2520 Draw a wavy line under glyph string s. The wave fills wave_height
2527 wave_height = 3 | * * * *
2528 --------------------------------------------------------------------- */
2531 ns_draw_underwave
(struct glyph_string
*s
, CGFloat width
, CGFloat x
)
2533 int wave_height
= 3, wave_length
= 3;
2534 int y
, dx
, dy
, odd
, xmax
;
2539 dy
= wave_height
- 1;
2543 /* Find and set clipping rectangle */
2544 waveClip
= NSMakeRect
(x
, y
, width
, wave_height
);
2545 [[NSGraphicsContext currentContext
] saveGraphicsState
];
2546 NSRectClip
(waveClip
);
2548 /* Draw the waves */
2549 a.x
= x
- ((int
)(x
) % dx);
2551 odd
= (int
)(a.x
/dx
) % 2;
2561 [NSBezierPath strokeLineFromPoint
:a toPoint
:b
];
2562 a.x
= b.x
, a.y
= b.y
;
2563 b.x
+= dx
, b.y
= y
+ odd
*dy
;
2567 /* Restore previous clipping rectangle(s) */
2568 [[NSGraphicsContext currentContext
] restoreGraphicsState
];
2574 ns_draw_text_decoration
(struct glyph_string
*s
, struct face
*face
,
2575 NSColor
*defaultCol
, CGFloat width
, CGFloat x
)
2576 /* --------------------------------------------------------------------------
2577 Draw underline, overline, and strike-through on glyph string s.
2578 -------------------------------------------------------------------------- */
2580 if (s
->for_overlaps
)
2584 if (face
->underline_p
)
2586 if (s
->face
->underline_type
== FACE_UNDER_WAVE
)
2588 if (face
->underline_defaulted_p
)
2591 [ns_lookup_indexed_color
(face
->underline_color
, s
->f
) set];
2593 ns_draw_underwave
(s
, width
, x
);
2595 else if (s
->face
->underline_type
== FACE_UNDER_LINE
)
2599 unsigned
long thickness
, position
;
2601 /* If the prev was underlined, match its appearance. */
2602 if (s
->prev
&& s
->prev
->face
->underline_p
2603 && s
->prev
->underline_thickness
> 0)
2605 thickness
= s
->prev
->underline_thickness
;
2606 position
= s
->prev
->underline_position
;
2611 unsigned
long descent
;
2614 descent
= s
->y
+ s
->height
- s
->ybase
;
2616 /* Use underline thickness of font, defaulting to 1. */
2617 thickness
= (font
&& font
->underline_thickness
> 0)
2618 ? font
->underline_thickness
: 1;
2620 /* Determine the offset of underlining from the baseline. */
2621 if (x_underline_at_descent_line
)
2622 position
= descent
- thickness
;
2623 else if (x_use_underline_position_properties
2624 && font
&& font
->underline_position
>= 0)
2625 position
= font
->underline_position
;
2627 position
= lround
(font
->descent
/ 2);
2629 position
= underline_minimum_offset
;
2631 position
= max (position
, underline_minimum_offset
);
2633 /* Ensure underlining is not cropped. */
2634 if (descent
<= position
)
2636 position
= descent
- 1;
2639 else if (descent
< position
+ thickness
)
2643 s
->underline_thickness
= thickness
;
2644 s
->underline_position
= position
;
2646 r
= NSMakeRect
(x
, s
->ybase
+ position
, width
, thickness
);
2648 if (face
->underline_defaulted_p
)
2651 [ns_lookup_indexed_color
(face
->underline_color
, s
->f
) set];
2655 /* Do overline. We follow other terms in using a thickness of 1
2656 and ignoring overline_margin. */
2657 if (face
->overline_p
)
2660 r
= NSMakeRect
(x
, s
->y
, width
, 1);
2662 if (face
->overline_color_defaulted_p
)
2665 [ns_lookup_indexed_color
(face
->overline_color
, s
->f
) set];
2669 /* Do strike-through. We follow other terms for thickness and
2670 vertical position.*/
2671 if (face
->strike_through_p
)
2676 dy
= lrint
((s
->height
- 1) / 2);
2677 r
= NSMakeRect
(x
, s
->y
+ dy
, width
, 1);
2679 if (face
->strike_through_color_defaulted_p
)
2682 [ns_lookup_indexed_color
(face
->strike_through_color
, s
->f
) set];
2688 ns_draw_box
(NSRect r
, float thickness
, NSColor
*col
, char left_p
, char right_p
)
2689 /* --------------------------------------------------------------------------
2690 Draw an unfilled rect inside r, optionally leaving left and/or right open.
2691 Note we can't just use an NSDrawRect command, because of the possibility
2692 of some sides not being drawn, and because the rect will be filled.
2693 -------------------------------------------------------------------------- */
2699 s.
size.height
= thickness
;
2701 s.origin.y
+= r.
size.height
- thickness
;
2704 s.
size.height
= r.
size.height
;
2705 s.origin.y
= r.origin.y
;
2707 /* left, right (optional) */
2708 s.
size.width
= thickness
;
2713 s.origin.x
+= r.
size.width
- thickness
;
2720 ns_draw_relief
(NSRect r
, int thickness
, char raised_p
,
2721 char top_p
, char bottom_p
, char left_p
, char right_p
,
2722 struct glyph_string
*s
)
2723 /* --------------------------------------------------------------------------
2724 Draw a relief rect inside r, optionally leaving some sides open.
2725 Note we can't just use an NSDrawBezel command, because of the possibility
2726 of some sides not being drawn, and because the rect will be filled.
2727 -------------------------------------------------------------------------- */
2729 static NSColor
*baseCol
= nil
, *lightCol
= nil
, *darkCol
= nil
;
2730 NSColor
*newBaseCol
= nil
;
2733 NSTRACE
(ns_draw_relief
);
2737 if (s
->face
->use_box_color_for_shadows_p
)
2739 newBaseCol
= ns_lookup_indexed_color
(s
->face
->box_color
, s
->f
);
2741 /* else if (s->first_glyph->type == IMAGE_GLYPH
2743 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
2745 newBaseCol = IMAGE_BACKGROUND (s->img, s->f, 0);
2749 newBaseCol
= ns_lookup_indexed_color
(s
->face
->background
, s
->f
);
2752 if (newBaseCol
== nil
)
2753 newBaseCol
= [NSColor grayColor
];
2755 if (newBaseCol
!= baseCol
) /* TODO: better check */
2758 baseCol
= [newBaseCol retain
];
2760 lightCol
= [[baseCol highlightWithLevel
: 0.2] retain
];
2762 darkCol
= [[baseCol shadowWithLevel
: 0.3] retain
];
2765 [(raised_p ? lightCol
: darkCol
) set];
2767 /* TODO: mitering. Using NSBezierPath doesn't work because of color switch. */
2770 sr.
size.height
= thickness
;
2771 if (top_p
) NSRectFill
(sr
);
2774 sr.
size.height
= r.
size.height
;
2775 sr.
size.width
= thickness
;
2776 if (left_p
) NSRectFill
(sr
);
2778 [(raised_p ? darkCol
: lightCol
) set];
2781 sr.
size.width
= r.
size.width
;
2782 sr.
size.height
= thickness
;
2783 sr.origin.y
+= r.
size.height
- thickness
;
2784 if (bottom_p
) NSRectFill
(sr
);
2787 sr.
size.height
= r.
size.height
;
2788 sr.origin.y
= r.origin.y
;
2789 sr.
size.width
= thickness
;
2790 sr.origin.x
+= r.
size.width
- thickness
;
2791 if (right_p
) NSRectFill
(sr
);
2796 ns_dumpglyphs_box_or_relief
(struct glyph_string
*s
)
2797 /* --------------------------------------------------------------------------
2798 Function modeled after x_draw_glyph_string_box ().
2799 Sets up parameters for drawing.
2800 -------------------------------------------------------------------------- */
2802 int right_x
, last_x
;
2803 char left_p
, right_p
;
2804 struct glyph
*last_glyph
;
2809 if (s
->hl
== DRAW_MOUSE_FACE
)
2811 face
= FACE_FROM_ID
(s
->f
, MOUSE_HL_INFO
(s
->f
)->mouse_face_face_id
);
2813 face
= FACE_FROM_ID
(s
->f
, MOUSE_FACE_ID
);
2818 thickness
= face
->box_line_width
;
2820 NSTRACE
(ns_dumpglyphs_box_or_relief
);
2822 last_x
= ((s
->row
->full_width_p
&& !s
->w
->pseudo_window_p
)
2823 ? WINDOW_RIGHT_EDGE_X
(s
->w
)
2824 : window_box_right
(s
->w
, s
->area
));
2825 last_glyph
= (s
->cmp || s
->img
2826 ? s
->first_glyph
: s
->first_glyph
+ s
->nchars
-1);
2828 right_x
= ((s
->row
->full_width_p
&& s
->extends_to_end_of_line_p
2829 ? last_x
- 1 : min (last_x
, s
->x
+ s
->background_width
) - 1));
2831 left_p
= (s
->first_glyph
->left_box_line_p
2832 ||
(s
->hl
== DRAW_MOUSE_FACE
2833 && (s
->prev
== NULL || s
->prev
->hl
!= s
->hl
)));
2834 right_p
= (last_glyph
->right_box_line_p
2835 ||
(s
->hl
== DRAW_MOUSE_FACE
2836 && (s
->next
== NULL || s
->next
->hl
!= s
->hl
)));
2838 r
= NSMakeRect
(s
->x
, s
->y
, right_x
- s
->x
+ 1, s
->height
);
2840 /* TODO: Sometimes box_color is 0 and this seems wrong; should investigate. */
2841 if (s
->face
->box
== FACE_SIMPLE_BOX
&& s
->face
->box_color
)
2843 ns_draw_box
(r
, abs (thickness
),
2844 ns_lookup_indexed_color
(face
->box_color
, s
->f
),
2849 ns_draw_relief
(r
, abs (thickness
), s
->face
->box
== FACE_RAISED_BOX
,
2850 1, 1, left_p
, right_p
, s
);
2856 ns_maybe_dumpglyphs_background
(struct glyph_string
*s
, char force_p
)
2857 /* --------------------------------------------------------------------------
2858 Modeled after x_draw_glyph_string_background, which draws BG in
2859 certain cases. Others are left to the text rendering routine.
2860 -------------------------------------------------------------------------- */
2862 NSTRACE
(ns_maybe_dumpglyphs_background
);
2864 if (!s
->background_filled_p
/* || s->hl == DRAW_MOUSE_FACE*/)
2866 int box_line_width
= max (s
->face
->box_line_width
, 0);
2867 if (FONT_HEIGHT
(s
->font
) < s
->height
- 2 * box_line_width
2868 || s
->font_not_found_p || s
->extends_to_end_of_line_p || force_p
)
2871 if (s
->hl
== DRAW_MOUSE_FACE
)
2873 face
= FACE_FROM_ID
(s
->f
,
2874 MOUSE_HL_INFO
(s
->f
)->mouse_face_face_id
);
2876 face
= FACE_FROM_ID
(s
->f
, MOUSE_FACE_ID
);
2879 face
= FACE_FROM_ID
(s
->f
, s
->first_glyph
->face_id
);
2881 [(NS_FACE_BACKGROUND
(face
) != 0
2882 ? ns_lookup_indexed_color
(NS_FACE_BACKGROUND
(face
), s
->f
)
2883 : FRAME_BACKGROUND_COLOR
(s
->f
)) set];
2886 struct ns_display_info
*dpyinfo
= FRAME_NS_DISPLAY_INFO
(s
->f
);
2887 [[dpyinfo
->bitmaps
[face
->stipple
-1].img stippleMask
] set];
2890 if (s
->hl
!= DRAW_CURSOR
)
2892 NSRect r
= NSMakeRect
(s
->x
, s
->y
+ box_line_width
,
2893 s
->background_width
,
2894 s
->height
-2*box_line_width
);
2898 s
->background_filled_p
= 1;
2905 ns_dumpglyphs_image
(struct glyph_string
*s
, NSRect r
)
2906 /* --------------------------------------------------------------------------
2907 Renders an image and associated borders.
2908 -------------------------------------------------------------------------- */
2910 EmacsImage
*img
= s
->img
->pixmap
;
2911 int box_line_vwidth
= max (s
->face
->box_line_width
, 0);
2912 int x
= s
->x
, y
= s
->ybase
- image_ascent
(s
->img
, s
->face
, &s
->slice);
2913 int bg_x
, bg_y
, bg_height
;
2920 NSTRACE
(ns_dumpglyphs_image
);
2922 if (s
->face
->box
!= FACE_NO_BOX
2923 && s
->first_glyph
->left_box_line_p
&& s
->slice.x
== 0)
2924 x
+= abs (s
->face
->box_line_width
);
2927 bg_y
= s
->slice.y
== 0 ? s
->y
: s
->y
+ box_line_vwidth
;
2928 bg_height
= s
->height
;
2929 /* other terms have this, but was causing problems w/tabbar mode */
2930 /* - 2 * box_line_vwidth; */
2932 if (s
->slice.x
== 0) x
+= s
->img
->hmargin
;
2933 if (s
->slice.y
== 0) y
+= s
->img
->vmargin
;
2935 /* Draw BG: if we need larger area than image itself cleared, do that,
2936 otherwise, since we composite the image under NS (instead of mucking
2937 with its background color), we must clear just the image area. */
2938 if (s
->hl
== DRAW_MOUSE_FACE
)
2940 face
= FACE_FROM_ID
(s
->f
, MOUSE_HL_INFO
(s
->f
)->mouse_face_face_id
);
2942 face
= FACE_FROM_ID
(s
->f
, MOUSE_FACE_ID
);
2945 face
= FACE_FROM_ID
(s
->f
, s
->first_glyph
->face_id
);
2947 [ns_lookup_indexed_color
(NS_FACE_BACKGROUND
(face
), s
->f
) set];
2949 if (bg_height
> s
->slice.height || s
->img
->hmargin || s
->img
->vmargin
2950 || s
->img
->mask || s
->img
->pixmap
== 0 || s
->width
!= s
->background_width
)
2952 br
= NSMakeRect
(bg_x
, bg_y
, s
->background_width
, bg_height
);
2953 s
->background_filled_p
= 1;
2957 br
= NSMakeRect
(x
, y
, s
->slice.width
, s
->slice.height
);
2962 /* Draw the image.. do we need to draw placeholder if img ==nil? */
2965 fromRect
: NSZeroRect
2966 operation
: NSCompositeSourceOver
2971 if (s
->hl
== DRAW_CURSOR
)
2973 [FRAME_CURSOR_COLOR
(s
->f
) set];
2974 if (s
->w
->phys_cursor_type
== FILLED_BOX_CURSOR
)
2975 tdCol
= ns_lookup_indexed_color
(NS_FACE_BACKGROUND
(face
), s
->f
);
2977 /* Currently on NS img->mask is always 0. Since
2978 get_window_cursor_type specifies a hollow box cursor when on
2979 a non-masked image we never reach this clause. But we put it
2980 in in anticipation of better support for image masks on
2982 tdCol
= ns_lookup_indexed_color
(NS_FACE_FOREGROUND
(face
), s
->f
);
2986 tdCol
= ns_lookup_indexed_color
(NS_FACE_FOREGROUND
(face
), s
->f
);
2989 /* Draw underline, overline, strike-through. */
2990 ns_draw_text_decoration
(s
, face
, tdCol
, br.
size.width
, br.origin.x
);
2992 /* Draw relief, if requested */
2993 if (s
->img
->relief || s
->hl
==DRAW_IMAGE_RAISED || s
->hl
==DRAW_IMAGE_SUNKEN
)
2995 if (s
->hl
== DRAW_IMAGE_SUNKEN || s
->hl
== DRAW_IMAGE_RAISED
)
2997 th
= tool_bar_button_relief
>= 0 ?
2998 tool_bar_button_relief
: DEFAULT_TOOL_BAR_BUTTON_RELIEF
;
2999 raised_p
= (s
->hl
== DRAW_IMAGE_RAISED
);
3003 th
= abs (s
->img
->relief
);
3004 raised_p
= (s
->img
->relief
> 0);
3007 r.origin.x
= x
- th
;
3008 r.origin.y
= y
- th
;
3009 r.
size.width
= s
->slice.width
+ 2*th
-1;
3010 r.
size.height
= s
->slice.height
+ 2*th
-1;
3011 ns_draw_relief
(r
, th
, raised_p
,
3013 s
->slice.y
+ s
->slice.height
== s
->img
->height
,
3015 s
->slice.x
+ s
->slice.width
== s
->img
->width
, s
);
3018 /* If there is no mask, the background won't be seen,
3019 so draw a rectangle on the image for the cursor.
3020 Do this for all images, getting transparency right is not reliable. */
3021 if (s
->hl
== DRAW_CURSOR
)
3023 int thickness
= abs (s
->img
->relief
);
3024 if (thickness
== 0) thickness
= 1;
3025 ns_draw_box
(br
, thickness
, FRAME_CURSOR_COLOR
(s
->f
), 1, 1);
3031 ns_dumpglyphs_stretch
(struct glyph_string
*s
)
3036 NSColor
*fgCol
, *bgCol
;
3038 if (!s
->background_filled_p
)
3040 n
= ns_get_glyph_string_clip_rect
(s
, r
);
3041 *r
= NSMakeRect
(s
->x
, s
->y
, s
->background_width
, s
->height
);
3043 ns_focus
(s
->f
, r
, n
);
3045 if (s
->hl
== DRAW_MOUSE_FACE
)
3047 face
= FACE_FROM_ID
(s
->f
, MOUSE_HL_INFO
(s
->f
)->mouse_face_face_id
);
3049 face
= FACE_FROM_ID
(s
->f
, MOUSE_FACE_ID
);
3052 face
= FACE_FROM_ID
(s
->f
, s
->first_glyph
->face_id
);
3054 bgCol
= ns_lookup_indexed_color
(NS_FACE_BACKGROUND
(face
), s
->f
);
3055 fgCol
= ns_lookup_indexed_color
(NS_FACE_FOREGROUND
(face
), s
->f
);
3057 for (i
= 0; i
< n
; ++i
)
3059 if (!s
->row
->full_width_p
)
3061 int overrun
, leftoverrun
;
3063 /* truncate to avoid overwriting fringe and/or scrollbar */
3064 overrun
= max (0, (s
->x
+ s
->background_width
)
3065 - (WINDOW_BOX_RIGHT_EDGE_X
(s
->w
)
3066 - WINDOW_RIGHT_FRINGE_WIDTH
(s
->w
)));
3067 r
[i
].
size.width
-= overrun
;
3069 /* truncate to avoid overwriting to left of the window box */
3070 leftoverrun
= (WINDOW_BOX_LEFT_EDGE_X
(s
->w
)
3071 + WINDOW_LEFT_FRINGE_WIDTH
(s
->w
)) - s
->x
;
3073 if (leftoverrun
> 0)
3075 r
[i
].origin.x
+= leftoverrun
;
3076 r
[i
].
size.width
-= leftoverrun
;
3079 /* XXX: Try to work between problem where a stretch glyph on
3080 a partially-visible bottom row will clear part of the
3081 modeline, and another where list-buffers headers and similar
3082 rows erroneously have visible_height set to 0. Not sure
3083 where this is coming from as other terms seem not to show. */
3084 r
[i
].
size.height
= min (s
->height
, s
->row
->visible_height
);
3089 /* NOTE: under NS this is NOT used to draw cursors, but we must avoid
3090 overwriting cursor (usually when cursor on a tab) */
3091 if (s
->hl
== DRAW_CURSOR
)
3096 width
= s
->w
->phys_cursor_width
;
3097 r
[i
].
size.width
-= width
;
3098 r
[i
].origin.x
+= width
;
3102 /* Draw overlining, etc. on the cursor. */
3103 if (s
->w
->phys_cursor_type
== FILLED_BOX_CURSOR
)
3104 ns_draw_text_decoration
(s
, face
, bgCol
, width
, x
);
3106 ns_draw_text_decoration
(s
, face
, fgCol
, width
, x
);
3113 /* Draw overlining, etc. on the stretch glyph (or the part
3114 of the stretch glyph after the cursor). */
3115 ns_draw_text_decoration
(s
, face
, fgCol
, r
[i
].
size.width
,
3119 s
->background_filled_p
= 1;
3125 ns_draw_glyph_string
(struct glyph_string
*s
)
3126 /* --------------------------------------------------------------------------
3127 External (RIF): Main draw-text call.
3128 -------------------------------------------------------------------------- */
3130 /* TODO (optimize): focus for box and contents draw */
3133 char box_drawn_p
= 0;
3135 NSTRACE
(ns_draw_glyph_string
);
3137 if (s
->next
&& s
->right_overhang
&& !s
->for_overlaps
/*&&s->hl!=DRAW_CURSOR*/)
3140 struct glyph_string
*next
;
3142 for (width
= 0, next
= s
->next
;
3143 next
&& width
< s
->right_overhang
;
3144 width
+= next
->width
, next
= next
->next
)
3145 if (next
->first_glyph
->type != IMAGE_GLYPH
)
3147 if (next
->first_glyph
->type != STRETCH_GLYPH
)
3149 n
= ns_get_glyph_string_clip_rect
(s
->next
, r
);
3150 ns_focus
(s
->f
, r
, n
);
3151 ns_maybe_dumpglyphs_background
(s
->next
, 1);
3156 ns_dumpglyphs_stretch
(s
->next
);
3158 next
->num_clips
= 0;
3162 if (!s
->for_overlaps
&& s
->face
->box
!= FACE_NO_BOX
3163 && (s
->first_glyph
->type == CHAR_GLYPH
3164 || s
->first_glyph
->type == COMPOSITE_GLYPH
))
3166 n
= ns_get_glyph_string_clip_rect
(s
, r
);
3167 ns_focus
(s
->f
, r
, n
);
3168 ns_maybe_dumpglyphs_background
(s
, 1);
3169 ns_dumpglyphs_box_or_relief
(s
);
3174 switch (s
->first_glyph
->type)
3178 n
= ns_get_glyph_string_clip_rect
(s
, r
);
3179 ns_focus
(s
->f
, r
, n
);
3180 ns_dumpglyphs_image
(s
, r
[0]);
3185 ns_dumpglyphs_stretch
(s
);
3189 case COMPOSITE_GLYPH
:
3190 n
= ns_get_glyph_string_clip_rect
(s
, r
);
3191 ns_focus
(s
->f
, r
, n
);
3193 if (s
->for_overlaps ||
(s
->cmp_from
> 0
3194 && ! s
->first_glyph
->u.cmp.automatic
))
3195 s
->background_filled_p
= 1;
3197 ns_maybe_dumpglyphs_background
3198 (s
, s
->first_glyph
->type == COMPOSITE_GLYPH
);
3200 ns_tmp_flags
= s
->hl
== DRAW_CURSOR ? NS_DUMPGLYPH_CURSOR
:
3201 (s
->hl
== DRAW_MOUSE_FACE ? NS_DUMPGLYPH_MOUSEFACE
:
3202 (s
->for_overlaps ? NS_DUMPGLYPH_FOREGROUND
:
3203 NS_DUMPGLYPH_NORMAL
));
3204 ns_tmp_font
= (struct nsfont_info
*)s
->face
->font
;
3205 if (ns_tmp_font
== NULL)
3206 ns_tmp_font
= (struct nsfont_info
*)FRAME_FONT
(s
->f
);
3208 if (s
->hl
== DRAW_CURSOR
&& s
->w
->phys_cursor_type
== FILLED_BOX_CURSOR
)
3210 unsigned
long tmp
= NS_FACE_BACKGROUND
(s
->face
);
3211 NS_FACE_BACKGROUND
(s
->face
) = NS_FACE_FOREGROUND
(s
->face
);
3212 NS_FACE_FOREGROUND
(s
->face
) = tmp
;
3215 ns_tmp_font
->font.driver
->draw
3216 (s
, 0, s
->nchars
, s
->x
, s
->y
,
3217 (ns_tmp_flags
== NS_DUMPGLYPH_NORMAL
&& !s
->background_filled_p
)
3218 || ns_tmp_flags
== NS_DUMPGLYPH_MOUSEFACE
);
3220 if (s
->hl
== DRAW_CURSOR
&& s
->w
->phys_cursor_type
== FILLED_BOX_CURSOR
)
3222 unsigned
long tmp
= NS_FACE_BACKGROUND
(s
->face
);
3223 NS_FACE_BACKGROUND
(s
->face
) = NS_FACE_FOREGROUND
(s
->face
);
3224 NS_FACE_FOREGROUND
(s
->face
) = tmp
;
3230 case GLYPHLESS_GLYPH
:
3231 n
= ns_get_glyph_string_clip_rect
(s
, r
);
3232 ns_focus
(s
->f
, r
, n
);
3234 if (s
->for_overlaps ||
(s
->cmp_from
> 0
3235 && ! s
->first_glyph
->u.cmp.automatic
))
3236 s
->background_filled_p
= 1;
3238 ns_maybe_dumpglyphs_background
3239 (s
, s
->first_glyph
->type == COMPOSITE_GLYPH
);
3241 /* Not yet implemented. */
3250 /* Draw box if not done already. */
3251 if (!s
->for_overlaps
&& !box_drawn_p
&& s
->face
->box
!= FACE_NO_BOX
)
3253 n
= ns_get_glyph_string_clip_rect
(s
, r
);
3254 ns_focus
(s
->f
, r
, n
);
3255 ns_dumpglyphs_box_or_relief
(s
);
3264 /* ==========================================================================
3268 ========================================================================== */
3272 ns_send_appdefined
(int value
)
3273 /* --------------------------------------------------------------------------
3274 Internal: post an appdefined event which EmacsApp-sendEvent will
3275 recognize and take as a command to halt the event loop.
3276 -------------------------------------------------------------------------- */
3278 /*NSTRACE (ns_send_appdefined); */
3280 /* Only post this event if we haven't already posted one. This will end
3281 the [NXApp run] main loop after having processed all events queued at
3283 if (send_appdefined
)
3287 /* We only need one NX_APPDEFINED event to stop NXApp from running. */
3288 send_appdefined
= NO
;
3290 /* Don't need wakeup timer any more */
3293 [timed_entry invalidate
];
3294 [timed_entry release
];
3298 nxev
= [NSEvent otherEventWithType
: NSApplicationDefined
3299 location
: NSMakePoint
(0, 0)
3302 windowNumber
: [[NSApp mainWindow
] windowNumber
]
3303 context
: [NSApp context
]
3308 /* Post an application defined event on the event queue. When this is
3309 received the [NXApp run] will return, thus having processed all
3310 events which are currently queued. */
3311 [NSApp postEvent
: nxev atStart
: NO
];
3316 ns_read_socket
(struct terminal *terminal, int expected
,
3317 struct input_event
*hold_quit
)
3318 /* --------------------------------------------------------------------------
3319 External (hook): Post an event to ourself and keep reading events until
3320 we read it back again. In effect process all events which were waiting.
3321 From 21+ we have to manage the event buffer ourselves.
3322 -------------------------------------------------------------------------- */
3324 struct input_event ev
;
3327 /* NSTRACE (ns_read_socket); */
3329 if ([NSApp modalWindow
] != nil
)
3332 if (interrupt_input_blocked
)
3334 interrupt_input_pending
= 1;
3336 pending_signals
= 1;
3341 interrupt_input_pending
= 0;
3343 pending_signals
= pending_atimers
;
3347 n_emacs_events_pending
= 0;
3350 q_event_ptr
= hold_quit
;
3352 /* we manage autorelease pools by allocate/reallocate each time around
3353 the loop; strict nesting is occasionally violated but seems not to
3354 matter.. earlier methods using full nesting caused major memory leaks */
3355 [outerpool release
];
3356 outerpool
= [[NSAutoreleasePool alloc
] init
];
3358 /* If have pending open-file requests, attend to the next one of those. */
3359 if (ns_pending_files
&& [ns_pending_files count
] != 0
3360 && [(EmacsApp
*)NSApp openFile
: [ns_pending_files objectAtIndex
: 0]])
3362 [ns_pending_files removeObjectAtIndex
: 0];
3364 /* Deal with pending service requests. */
3365 else if (ns_pending_service_names
&& [ns_pending_service_names count
] != 0
3367 NSApp fulfillService
: [ns_pending_service_names objectAtIndex
: 0]
3368 withArg
: [ns_pending_service_args objectAtIndex
: 0]])
3370 [ns_pending_service_names removeObjectAtIndex
: 0];
3371 [ns_pending_service_args removeObjectAtIndex
: 0];
3375 /* Run and wait for events. We must always send one NX_APPDEFINED event
3376 to ourself, otherwise [NXApp run] will never exit. */
3377 send_appdefined
= YES
;
3378 ns_send_appdefined
(-1);
3380 if (++apploopnr
!= 1)
3388 nevents
= n_emacs_events_pending
;
3389 n_emacs_events_pending
= 0;
3390 emacs_event
= q_event_ptr
= NULL;
3398 ns_select
(int nfds
, fd_set
*readfds
, fd_set
*writefds
,
3399 fd_set
*exceptfds
, EMACS_TIME
*timeout
, sigset_t
*sigmask
)
3400 /* --------------------------------------------------------------------------
3401 Replacement for select, checking for events
3402 -------------------------------------------------------------------------- */
3407 struct input_event event
;
3410 /* NSTRACE (ns_select); */
3412 for (k
= 0; readfds
&& k
< nfds
+1; k
++)
3413 if (FD_ISSET
(k
, readfds
)) ++nr
;
3416 ||
(timeout
&& timeout
->tv_sec
== 0 && timeout
->tv_nsec
== 0))
3417 return pselect
(nfds
, readfds
, writefds
, exceptfds
, timeout
, sigmask
);
3419 [outerpool release
];
3420 outerpool
= [[NSAutoreleasePool alloc
] init
];
3423 send_appdefined
= YES
;
3426 pthread_mutex_lock
(&select_mutex
);
3431 select_readfds
= *readfds
;
3432 select_valid
+= SELECT_HAVE_READ
;
3436 select_writefds
= *writefds
;
3437 select_valid
+= SELECT_HAVE_WRITE
;
3442 select_timeout
= *timeout
;
3443 select_valid
+= SELECT_HAVE_TMO
;
3446 pthread_mutex_unlock
(&select_mutex
);
3448 /* Inform fd_handler that select should be called */
3450 write
(selfds
[1], &c
, 1);
3452 else if (nr
== 0 && timeout
)
3454 /* No file descriptor, just a timeout, no need to wake fd_handler */
3455 double time
= EMACS_TIME_TO_DOUBLE
(*timeout
);
3456 timed_entry
= [[NSTimer scheduledTimerWithTimeInterval
: time
3459 @selector
(timeout_handler
:)
3464 else /* No timeout and no file descriptors, can this happen? */
3466 /* Send appdefined so we exit from the loop */
3467 ns_send_appdefined
(-1);
3472 emacs_event
= &event
;
3473 if (++apploopnr
!= 1)
3480 if (nr
> 0 && readfds
)
3483 write
(selfds
[1], &c
, 1);
3487 ev
= last_appdefined_event
;
3492 if ([ev
type] != NSApplicationDefined
)
3496 last_appdefined_event
= 0;
3500 /* The NX_APPDEFINED event we received was a timeout. */
3505 /* The NX_APPDEFINED event we received was the result of
3506 at least one real input event arriving. */
3512 /* Received back from select () in fd_handler; copy the results */
3513 pthread_mutex_lock
(&select_mutex
);
3514 if (readfds
) *readfds
= select_readfds
;
3515 if (writefds
) *writefds
= select_writefds
;
3516 if (timeout
) *timeout
= select_timeout
;
3517 pthread_mutex_unlock
(&select_mutex
);
3527 /* ==========================================================================
3531 ========================================================================== */
3535 ns_set_vertical_scroll_bar
(struct window
*window
,
3536 int portion
, int whole
, int position
)
3537 /* --------------------------------------------------------------------------
3538 External (hook): Update or add scrollbar
3539 -------------------------------------------------------------------------- */
3543 struct frame
*f
= XFRAME
(WINDOW_FRAME
(window
));
3544 EmacsView
*view = FRAME_NS_VIEW
(f
);
3545 int window_y
, window_height
;
3546 int top
, left
, height
, width
, sb_width
, sb_left
;
3548 BOOL fringe_extended_p
;
3550 /* optimization; display engine sends WAY too many of these.. */
3551 if (!NILP
(window
->vertical_scroll_bar
))
3553 bar = XNS_SCROLL_BAR
(window
->vertical_scroll_bar
);
3554 if ([bar checkSamePosition
: position portion
: portion whole
: whole
])
3556 if (view->scrollbarsNeedingUpdate
== 0)
3558 if (!windows_or_buffers_changed
)
3562 view->scrollbarsNeedingUpdate
--;
3566 NSTRACE
(ns_set_vertical_scroll_bar
);
3568 /* Get dimensions. */
3569 window_box
(window
, -1, 0, &window_y
, 0, &window_height
);
3571 height
= window_height
;
3572 width
= WINDOW_CONFIG_SCROLL_BAR_COLS
(window
) * FRAME_COLUMN_WIDTH
(f
);
3573 left
= WINDOW_SCROLL_BAR_AREA_X
(window
);
3575 /* allow for displaying a skinnier scrollbar than char area allotted */
3576 sb_width
= (WINDOW_CONFIG_SCROLL_BAR_WIDTH
(window
) > 0) ?
3577 WINDOW_CONFIG_SCROLL_BAR_WIDTH
(window
) : width
;
3580 r
= NSMakeRect
(sb_left
, top
, sb_width
, height
);
3581 /* the parent view is flipped, so we need to flip y value */
3583 r.origin.y
= (v.
size.height
- r.
size.height
- r.origin.y
);
3585 if (WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT
(window
))
3586 fringe_extended_p
= (WINDOW_LEFTMOST_P
(window
)
3587 && WINDOW_LEFT_FRINGE_WIDTH
(window
)
3588 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS
(window
)
3589 || WINDOW_LEFT_MARGIN_COLS
(window
) == 0));
3591 fringe_extended_p
= (WINDOW_RIGHTMOST_P
(window
)
3592 && WINDOW_RIGHT_FRINGE_WIDTH
(window
)
3593 && (WINDOW_HAS_FRINGES_OUTSIDE_MARGINS
(window
)
3594 || WINDOW_RIGHT_MARGIN_COLS
(window
) == 0));
3596 XSETWINDOW
(win
, window
);
3599 /* we want at least 5 lines to display a scrollbar */
3600 if (WINDOW_TOTAL_LINES
(window
) < 5)
3602 if (!NILP
(window
->vertical_scroll_bar
))
3604 bar = XNS_SCROLL_BAR
(window
->vertical_scroll_bar
);
3605 [bar removeFromSuperview
];
3606 wset_vertical_scroll_bar
(window
, Qnil
);
3608 ns_clear_frame_area
(f
, sb_left
, top
, width
, height
);
3613 if (NILP
(window
->vertical_scroll_bar
))
3615 if (width
> 0 && height
> 0)
3617 if (fringe_extended_p
)
3618 ns_clear_frame_area
(f
, sb_left
, top
, sb_width
, height
);
3620 ns_clear_frame_area
(f
, left
, top
, width
, height
);
3623 bar = [[EmacsScroller alloc
] initFrame
: r window
: win
];
3624 wset_vertical_scroll_bar
(window
, make_save_value
(bar, 0));
3629 bar = XNS_SCROLL_BAR
(window
->vertical_scroll_bar
);
3630 oldRect
= [bar frame
];
3631 r.
size.width
= oldRect.
size.width
;
3632 if (FRAME_LIVE_P
(f
) && !NSEqualRects
(oldRect
, r
))
3634 if (oldRect.origin.x
!= r.origin.x
)
3635 ns_clear_frame_area
(f
, sb_left
, top
, width
, height
);
3640 [bar setPosition
: position portion
: portion whole
: whole
];
3646 ns_condemn_scroll_bars
(struct frame
*f
)
3647 /* --------------------------------------------------------------------------
3648 External (hook): arrange for all frame's scrollbars to be removed
3649 at next call to judge_scroll_bars, except for those redeemed.
3650 -------------------------------------------------------------------------- */
3654 NSArray
*subviews
= [[FRAME_NS_VIEW
(f
) superview
] subviews
];
3656 NSTRACE
(ns_condemn_scroll_bars
);
3658 for (i
=[subviews count
]-1; i
>= 0; i
--)
3660 view = [subviews objectAtIndex
: i
];
3661 if ([view isKindOfClass
: [EmacsScroller
class]])
3668 ns_redeem_scroll_bar
(struct window
*window
)
3669 /* --------------------------------------------------------------------------
3670 External (hook): arrange to spare this window's scrollbar
3671 at next call to judge_scroll_bars.
3672 -------------------------------------------------------------------------- */
3675 NSTRACE
(ns_redeem_scroll_bar
);
3676 if (!NILP
(window
->vertical_scroll_bar
))
3678 bar = XNS_SCROLL_BAR
(window
->vertical_scroll_bar
);
3685 ns_judge_scroll_bars
(struct frame
*f
)
3686 /* --------------------------------------------------------------------------
3687 External (hook): destroy all scrollbars on frame that weren't
3688 redeemed after call to condemn_scroll_bars.
3689 -------------------------------------------------------------------------- */
3693 EmacsView
*eview
= FRAME_NS_VIEW
(f
);
3694 NSArray
*subviews
= [[eview superview
] subviews
];
3697 NSTRACE
(ns_judge_scroll_bars
);
3698 for (i
= [subviews count
]-1; i
>= 0; --i
)
3700 view = [subviews objectAtIndex
: i
];
3701 if (![view isKindOfClass
: [EmacsScroller
class]]) continue
;
3707 [eview updateFrameSize
];
3712 x_wm_set_icon_position
(struct frame
*f
, int icon_x
, int icon_y
)
3714 /* XXX irrelevant under NS */
3719 /* ==========================================================================
3723 ========================================================================== */
3726 x_display_pixel_height
(struct ns_display_info
*dpyinfo
)
3728 NSScreen
*screen
= [NSScreen mainScreen
];
3729 return [screen frame
].
size.height
;
3733 x_display_pixel_width
(struct ns_display_info
*dpyinfo
)
3735 NSScreen
*screen
= [NSScreen mainScreen
];
3736 return [screen frame
].
size.width
;
3740 static Lisp_Object ns_string_to_lispmod
(const
char *s
)
3741 /* --------------------------------------------------------------------------
3742 Convert modifier name to lisp symbol
3743 -------------------------------------------------------------------------- */
3745 if (!strncmp
(SSDATA
(SYMBOL_NAME
(Qmeta
)), s
, 10))
3747 else if (!strncmp
(SSDATA
(SYMBOL_NAME
(Qsuper
)), s
, 10))
3749 else if (!strncmp
(SSDATA
(SYMBOL_NAME
(Qcontrol
)), s
, 10))
3751 else if (!strncmp
(SSDATA
(SYMBOL_NAME
(Qalt
)), s
, 10))
3753 else if (!strncmp
(SSDATA
(SYMBOL_NAME
(Qhyper
)), s
, 10))
3755 else if (!strncmp
(SSDATA
(SYMBOL_NAME
(Qnone
)), s
, 10))
3763 ns_default
(const
char *parameter
, Lisp_Object
*result
,
3764 Lisp_Object yesval
, Lisp_Object noval
,
3765 BOOL is_float
, BOOL is_modstring
)
3766 /* --------------------------------------------------------------------------
3767 Check a parameter value in user's preferences
3768 -------------------------------------------------------------------------- */
3770 const
char *value
= ns_get_defaults_value
(parameter
);
3776 if (c_strcasecmp
(value
, "YES"
) == 0)
3778 else if (c_strcasecmp
(value
, "NO"
) == 0)
3780 else if (is_float
&& (f
= strtod
(value
, &pos
), pos
!= value
))
3781 *result
= make_float
(f
);
3782 else if (is_modstring
&& value
)
3783 *result
= ns_string_to_lispmod
(value
);
3784 else fprintf (stderr
,
3785 "Bad value
for default
\"%s\": \"%s\"\n", parameter, value);
3791 ns_initialize_display_info
(struct ns_display_info
*dpyinfo
)
3792 /* --------------------------------------------------------------------------
3793 Initialize global info and storage for display.
3794 -------------------------------------------------------------------------- */
3796 NSScreen
*screen
= [NSScreen mainScreen
];
3797 NSWindowDepth depth
= [screen depth
];
3798 Mouse_HLInfo
*hlinfo
= &dpyinfo
->mouse_highlight
;
3800 dpyinfo
->resx
= 72.27; /* used 75.0, but this makes pt == pixel, expected */
3801 dpyinfo
->resy
= 72.27;
3802 dpyinfo
->color_p
= ![NSDeviceWhiteColorSpace isEqualToString
:
3803 NSColorSpaceFromDepth
(depth
)]
3804 && ![NSCalibratedWhiteColorSpace isEqualToString
:
3805 NSColorSpaceFromDepth
(depth
)];
3806 dpyinfo
->n_planes
= NSBitsPerPixelFromDepth
(depth
);
3807 dpyinfo
->image_cache
= make_image_cache
();
3808 dpyinfo
->color_table
= xmalloc
(sizeof
*dpyinfo
->color_table
);
3809 dpyinfo
->color_table
->colors
= NULL;
3810 dpyinfo
->root_window
= 42; /* a placeholder.. */
3812 hlinfo
->mouse_face_mouse_frame
= NULL;
3813 hlinfo
->mouse_face_deferred_gc
= 0;
3814 hlinfo
->mouse_face_beg_row
= hlinfo
->mouse_face_beg_col
= -1;
3815 hlinfo
->mouse_face_end_row
= hlinfo
->mouse_face_end_col
= -1;
3816 hlinfo
->mouse_face_face_id
= DEFAULT_FACE_ID
;
3817 hlinfo
->mouse_face_window
= hlinfo
->mouse_face_overlay
= Qnil
;
3818 hlinfo
->mouse_face_hidden
= 0;
3820 hlinfo
->mouse_face_mouse_x
= hlinfo
->mouse_face_mouse_y
= 0;
3821 hlinfo
->mouse_face_defer
= 0;
3823 dpyinfo
->x_highlight_frame
= dpyinfo
->x_focus_frame
= NULL;
3825 dpyinfo
->n_fonts
= 0;
3826 dpyinfo
->smallest_font_height
= 1;
3827 dpyinfo
->smallest_char_width
= 1;
3831 /* This and next define (many of the) public functions in this file. */
3832 /* x_... are generic versions in xdisp.c that we, and other terms, get away
3833 with using despite presence in the "system dependent" redisplay
3834 interface. In addition, many of the ns_ methods have code that is
3835 shared with all terms, indicating need for further refactoring. */
3836 extern frame_parm_handler ns_frame_parm_handlers
[];
3837 static
struct redisplay_interface ns_redisplay_interface
=
3839 ns_frame_parm_handlers
,
3843 x_clear_end_of_line
,
3845 ns_after_update_window_line
,
3846 ns_update_window_begin
,
3847 ns_update_window_end
,
3850 0, /* flush_display_optional */
3851 x_clear_window_mouse_face
,
3852 x_get_glyph_overhangs
,
3853 x_fix_overlapping_area
,
3854 ns_draw_fringe_bitmap
,
3855 0, /* define_fringe_bitmap */ /* FIXME: simplify ns_draw_fringe_bitmap */
3856 0, /* destroy_fringe_bitmap */
3857 ns_compute_glyph_string_overhangs
,
3858 ns_draw_glyph_string
, /* interface to nsfont.m */
3859 ns_define_frame_cursor
,
3860 ns_clear_frame_area
,
3861 ns_draw_window_cursor
,
3862 ns_draw_vertical_window_border
,
3863 ns_shift_glyphs_for_insert
3868 ns_delete_display
(struct ns_display_info
*dpyinfo
)
3874 /* This function is called when the last frame on a display is deleted. */
3876 ns_delete_terminal
(struct terminal *terminal)
3878 struct ns_display_info
*dpyinfo
= terminal->display_info.ns
;
3880 /* Protect against recursive calls. delete_frame in
3881 delete_terminal calls us back when it deletes our last frame. */
3882 if (!terminal->name
)
3887 x_destroy_all_bitmaps
(dpyinfo
);
3888 ns_delete_display
(dpyinfo
);
3893 static
struct terminal *
3894 ns_create_terminal
(struct ns_display_info
*dpyinfo
)
3895 /* --------------------------------------------------------------------------
3896 Set up use of NS before we make the first connection.
3897 -------------------------------------------------------------------------- */
3899 struct terminal *terminal;
3901 NSTRACE
(ns_create_terminal
);
3903 terminal = create_terminal
();
3905 terminal->type = output_ns
;
3906 terminal->display_info.ns
= dpyinfo
;
3907 dpyinfo
->terminal = terminal;
3909 terminal->rif
= &ns_redisplay_interface
;
3911 terminal->clear_frame_hook
= ns_clear_frame
;
3912 terminal->ins_del_lines_hook
= 0; /* XXX vestigial? */
3913 terminal->delete_glyphs_hook
= 0; /* XXX vestigial? */
3914 terminal->ring_bell_hook
= ns_ring_bell
;
3915 terminal->reset_terminal_modes_hook
= ns_reset_terminal_modes
;
3916 terminal->set_terminal_modes_hook
= ns_set_terminal_modes
;
3917 terminal->update_begin_hook
= ns_update_begin
;
3918 terminal->update_end_hook
= ns_update_end
;
3919 terminal->set_terminal_window_hook
= NULL; /* XXX vestigial? */
3920 terminal->read_socket_hook
= ns_read_socket
;
3921 terminal->frame_up_to_date_hook
= ns_frame_up_to_date
;
3922 terminal->mouse_position_hook
= ns_mouse_position
;
3923 terminal->frame_rehighlight_hook
= ns_frame_rehighlight
;
3924 terminal->frame_raise_lower_hook
= ns_frame_raise_lower
;
3926 terminal->fullscreen_hook
= 0; /* see XTfullscreen_hook */
3928 terminal->set_vertical_scroll_bar_hook
= ns_set_vertical_scroll_bar
;
3929 terminal->condemn_scroll_bars_hook
= ns_condemn_scroll_bars
;
3930 terminal->redeem_scroll_bar_hook
= ns_redeem_scroll_bar
;
3931 terminal->judge_scroll_bars_hook
= ns_judge_scroll_bars
;
3933 terminal->delete_frame_hook
= x_destroy_window
;
3934 terminal->delete_terminal_hook
= ns_delete_terminal
;
3936 terminal->scroll_region_ok
= 1;
3937 terminal->char_ins_del_ok
= 1;
3938 terminal->line_ins_del_ok
= 1;
3939 terminal->fast_clear_end_of_line
= 1;
3940 terminal->memory_below_frame
= 0;
3946 struct ns_display_info
*
3947 ns_term_init
(Lisp_Object display_name
)
3948 /* --------------------------------------------------------------------------
3949 Start the Application and get things rolling.
3950 -------------------------------------------------------------------------- */
3952 struct terminal *terminal;
3953 struct ns_display_info
*dpyinfo
;
3954 static int ns_initialized
= 0;
3957 NSTRACE
(ns_term_init
);
3959 /* count object allocs (About, click icon); on OS X use ObjectAlloc tool */
3960 /*GSDebugAllocationActive (YES); */
3962 handling_signal
= 0;
3964 if (!ns_initialized
)
3967 Fset_input_interrupt_mode
(Qnil
);
3969 if (selfds
[0] == -1)
3971 if (pipe
(selfds
) == -1)
3973 fprintf (stderr
, "Failed to create pipe
: %s\n",
3974 emacs_strerror
(errno
));
3978 fcntl
(selfds
[0], F_SETFL
, O_NONBLOCK|fcntl
(selfds
[0], F_GETFL
));
3979 FD_ZERO
(&select_readfds
);
3980 FD_ZERO
(&select_writefds
);
3981 pthread_mutex_init
(&select_mutex
, NULL);
3986 ns_pending_files
= [[NSMutableArray alloc
] init
];
3987 ns_pending_service_names
= [[NSMutableArray alloc
] init
];
3988 ns_pending_service_args
= [[NSMutableArray alloc
] init
];
3990 /* Start app and create the main menu, window, view.
3991 Needs to be here because ns_initialize_display_info () uses AppKit classes.
3992 The view will then ask the NSApp to stop and return to Emacs. */
3993 [EmacsApp sharedApplication
];
3996 [NSApp setDelegate
: NSApp
];
3998 /* Start the select thread. */
3999 [NSThread detachNewThreadSelector
:@selector
(fd_handler
:)
4003 /* debugging: log all notifications */
4004 /* [[NSNotificationCenter defaultCenter] addObserver: NSApp
4005 selector: @selector (logNotification:)
4006 name: nil object: nil]; */
4008 dpyinfo
= xzalloc
(sizeof
*dpyinfo
);
4010 ns_initialize_display_info
(dpyinfo
);
4011 terminal = ns_create_terminal
(dpyinfo
);
4013 terminal->kboard
= xmalloc
(sizeof
*terminal->kboard
);
4014 init_kboard
(terminal->kboard
);
4015 kset_window_system
(terminal->kboard
, Qns
);
4016 terminal->kboard
->next_kboard
= all_kboards
;
4017 all_kboards
= terminal->kboard
;
4018 /* Don't let the initial kboard remain current longer than necessary.
4019 That would cause problems if a file loaded on startup tries to
4020 prompt in the mini-buffer. */
4021 if (current_kboard
== initial_kboard
)
4022 current_kboard
= terminal->kboard
;
4023 terminal->kboard
->reference_count
++;
4025 dpyinfo
->next
= x_display_list
;
4026 x_display_list
= dpyinfo
;
4028 /* Put it on ns_display_name_list */
4029 ns_display_name_list
= Fcons
(Fcons
(display_name
, Qnil
),
4030 ns_display_name_list
);
4031 dpyinfo
->name_list_element
= XCAR
(ns_display_name_list
);
4033 terminal->name
= xstrdup
(SSDATA
(display_name
));
4037 if (!inhibit_x_resources
)
4039 ns_default
("GSFontAntiAlias"
, &ns_antialias_text
,
4042 /* this is a standard variable */
4043 ns_default
("AppleAntiAliasingThreshold"
, &tmp
,
4044 make_float
(10.0), make_float
(6.0), YES
, NO
);
4045 ns_antialias_threshold
= NILP
(tmp
) ?
10.0 : XFLOATINT
(tmp
);
4048 ns_selection_color
= [[NSUserDefaults standardUserDefaults
]
4049 stringForKey
: @"AppleHighlightColor"
];
4050 if (ns_selection_color
== nil
)
4051 ns_selection_color
= NS_SELECTION_COLOR_DEFAULT
;
4054 NSColorList
*cl
= [NSColorList colorListNamed
: @"Emacs"
];
4058 Lisp_Object color_file
, color_map
, color
;
4062 color_file
= Fexpand_file_name
(build_string
("rgb.txt"
),
4063 Fsymbol_value
(intern
("data
-directory"
)));
4064 if (NILP
(Ffile_readable_p
(color_file
)))
4065 fatal
("Could not
find %s.\n", SDATA (color_file));
4067 color_map
= Fx_load_color_file
(color_file
);
4068 if (NILP
(color_map
))
4069 fatal
("Could not read
%s.\n", SDATA (color_file));
4071 cl
= [[NSColorList alloc
] initWithName
: @"Emacs"
];
4072 for ( ; CONSP
(color_map
); color_map
= XCDR
(color_map
))
4074 color
= XCAR
(color_map
);
4075 name
= SSDATA
(XCAR
(color
));
4076 c
= XINT
(XCDR
(color
));
4078 [NSColor colorWithCalibratedRed
: RED_FROM_ULONG
(c
) / 255.0
4079 green
: GREEN_FROM_ULONG
(c
) / 255.0
4080 blue
: BLUE_FROM_ULONG
(c
) / 255.0
4082 forKey
: [NSString stringWithUTF8String
: name
]];
4084 [cl writeToFile
: nil
];
4089 #ifdef NS_IMPL_GNUSTEP
4090 Vwindow_system_version
= build_string
(gnustep_base_version
);
4092 /*PSnextrelease (128, c); */
4093 char c
[DBL_BUFSIZE_BOUND
];
4094 int len
= dtoastr
(c
, sizeof c
, 0, 0, NSAppKitVersionNumber
);
4095 Vwindow_system_version
= make_unibyte_string
(c
, len
);
4099 delete_keyboard_wait_descriptor
(0);
4101 ns_app_name
= [[NSProcessInfo processInfo
] processName
];
4103 /* Set up OS X app menu */
4104 #ifdef NS_IMPL_COCOA
4108 /* set up the application menu */
4109 svcsMenu
= [[EmacsMenu alloc
] initWithTitle
: @"Services"
];
4110 [svcsMenu setAutoenablesItems
: NO
];
4111 appMenu
= [[EmacsMenu alloc
] initWithTitle
: @"Emacs"
];
4112 [appMenu setAutoenablesItems
: NO
];
4113 mainMenu
= [[EmacsMenu alloc
] initWithTitle
: @""
];
4114 dockMenu
= [[EmacsMenu alloc
] initWithTitle
: @""
];
4116 [appMenu insertItemWithTitle
: @"About Emacs"
4117 action
: @selector
(orderFrontStandardAboutPanel
:)
4120 [appMenu insertItem
: [NSMenuItem separatorItem
] atIndex
: 1];
4121 [appMenu insertItemWithTitle
: @"Preferences..."
4122 action
: @selector
(showPreferencesWindow
:)
4125 [appMenu insertItem
: [NSMenuItem separatorItem
] atIndex
: 3];
4126 item
= [appMenu insertItemWithTitle
: @"Services"
4127 action
: @selector
(menuDown
:)
4130 [appMenu setSubmenu
: svcsMenu forItem
: item
];
4131 [appMenu insertItem
: [NSMenuItem separatorItem
] atIndex
: 5];
4132 [appMenu insertItemWithTitle
: @"Hide Emacs"
4133 action
: @selector
(hide
:)
4136 item
= [appMenu insertItemWithTitle
: @"Hide Others"
4137 action
: @selector
(hideOtherApplications
:)
4140 [item setKeyEquivalentModifierMask
: NSCommandKeyMask | NSAlternateKeyMask
];
4141 [appMenu insertItem
: [NSMenuItem separatorItem
] atIndex
: 8];
4142 [appMenu insertItemWithTitle
: @"
Quit Emacs"
4143 action
: @selector
(terminate
:)
4147 item
= [mainMenu insertItemWithTitle
: ns_app_name
4148 action
: @selector
(menuDown
:)
4151 [mainMenu setSubmenu
: appMenu forItem
: item
];
4152 [dockMenu insertItemWithTitle
: @"New Frame"
4153 action
: @selector
(newFrame
:)
4157 [NSApp setMainMenu
: mainMenu
];
4158 [NSApp setAppleMenu
: appMenu
];
4159 [NSApp setServicesMenu
: svcsMenu
];
4160 /* Needed at least on Cocoa, to get dock menu to show windows */
4161 [NSApp setWindowsMenu
: [[NSMenu alloc
] init
]];
4163 [[NSNotificationCenter defaultCenter
]
4164 addObserver
: mainMenu
4165 selector
: @selector
(trackingNotification
:)
4166 name
: NSMenuDidBeginTrackingNotification object
: mainMenu
];
4167 [[NSNotificationCenter defaultCenter
]
4168 addObserver
: mainMenu
4169 selector
: @selector
(trackingNotification
:)
4170 name
: NSMenuDidEndTrackingNotification object
: mainMenu
];
4172 #endif
/* MAC OS X menu setup */
4175 ns_do_open_file
= YES
;
4181 ns_term_shutdown
(int sig
)
4183 [[NSUserDefaults standardUserDefaults
] synchronize
];
4185 /* code not reached in emacs.c after this is called by shut_down_emacs: */
4186 if (STRINGP
(Vauto_save_list_file_name
))
4187 unlink
(SSDATA
(Vauto_save_list_file_name
));
4189 if (sig
== 0 || sig
== SIGTERM
)
4191 [NSApp terminate
: NSApp
];
4193 else // force a stack
trace to happen
4200 /* ==========================================================================
4202 EmacsApp implementation
4204 ========================================================================== */
4207 @implementation EmacsApp
4209 - (void
)logNotification
: (NSNotification
*)notification
4211 const
char *name
= [[notification name
] UTF8String
];
4212 if (!strstr
(name
, "Update"
) && !strstr
(name
, "NSMenu"
)
4213 && !strstr
(name
, "WindowNumber"
))
4214 NSLog
(@"notification
: '%@'"
, [notification name
]);
4218 - (void
)sendEvent
: (NSEvent
*)theEvent
4219 /* --------------------------------------------------------------------------
4220 Called when NSApp is running for each event received. Used to stop
4221 the loop when we choose, since there's no way to just run one iteration.
4222 -------------------------------------------------------------------------- */
4224 int
type = [theEvent
type];
4225 NSWindow
*window
= [theEvent window
];
4226 /* NSTRACE (sendEvent); */
4227 /*fprintf (stderr, "received event of type %d\t%d\n", type);*/
4229 #ifdef NS_IMPL_COCOA
4230 if (type == NSApplicationDefined
4231 && [theEvent data2
] == NSAPP_DATA2_RUNASSCRIPT
)
4239 if (type == NSCursorUpdate
&& window
== nil
)
4241 fprintf (stderr
, "Dropping external cursor update event.
\n"
);
4245 #ifdef NS_IMPL_COCOA
4246 /* pass mouse down in resize handle and subsequent drags directly to
4247 EmacsWindow so we can generate continuous redisplays */
4250 if (type == NSLeftMouseDragged
)
4252 [window mouseDragged
: theEvent
];
4255 else if (type == NSLeftMouseUp
)
4257 [window mouseUp
: theEvent
];
4261 else if (type == NSLeftMouseDown
)
4263 NSRect r
= ns_resize_handle_rect
(window
);
4264 if (NSPointInRect
([theEvent locationInWindow
], r
))
4267 [window mouseDown
: theEvent
];
4273 if (type == NSApplicationDefined
)
4275 /* Events posted by ns_send_appdefined interrupt the run loop here.
4276 But, if a modal window is up, an appdefined can still come through,
4277 (e.g., from a makeKeyWindow event) but stopping self also stops the
4278 modal loop. Just defer it until later. */
4279 if ([NSApp modalWindow
] == nil
)
4281 last_appdefined_event
= theEvent
;
4286 send_appdefined
= YES
;
4290 [super sendEvent
: theEvent
];
4294 - (void
)showPreferencesWindow
: (id
)sender
4296 struct frame
*emacsframe
= SELECTED_FRAME
();
4297 NSEvent
*theEvent
= [NSApp currentEvent
];
4301 emacs_event
->kind
= NS_NONKEY_EVENT
;
4302 emacs_event
->code
= KEY_NS_SHOW_PREFS
;
4303 emacs_event
->modifiers
= 0;
4304 EV_TRAILER
(theEvent
);
4308 - (void
)newFrame
: (id
)sender
4310 struct frame
*emacsframe
= SELECTED_FRAME
();
4311 NSEvent
*theEvent
= [NSApp currentEvent
];
4315 emacs_event
->kind
= NS_NONKEY_EVENT
;
4316 emacs_event
->code
= KEY_NS_NEW_FRAME
;
4317 emacs_event
->modifiers
= 0;
4318 EV_TRAILER
(theEvent
);
4322 /* Open a file (used by below, after going into queue read by ns_read_socket) */
4323 - (BOOL
) openFile
: (NSString
*)fileName
4325 struct frame
*emacsframe
= SELECTED_FRAME
();
4326 NSEvent
*theEvent
= [NSApp currentEvent
];
4331 emacs_event
->kind
= NS_NONKEY_EVENT
;
4332 emacs_event
->code
= KEY_NS_OPEN_FILE_LINE
;
4333 ns_input_file
= append2
(ns_input_file
, build_string
([fileName UTF8String
]));
4334 ns_input_line
= Qnil
; /* can be start or cons start,end */
4335 emacs_event
->modifiers
=0;
4336 EV_TRAILER
(theEvent
);
4342 /* **************************************************************************
4344 EmacsApp delegate implementation
4346 ************************************************************************** */
4348 - (void
)applicationDidFinishLaunching
: (NSNotification
*)notification
4349 /* --------------------------------------------------------------------------
4350 When application is loaded, terminate event loop in ns_term_init
4351 -------------------------------------------------------------------------- */
4353 NSTRACE
(applicationDidFinishLaunching
);
4354 [NSApp setServicesProvider
: NSApp
];
4355 ns_send_appdefined
(-2);
4359 /* Termination sequences:
4362 MenuBar | File | Exit:
4363 Select Quit from App menubar:
4365 KEY_NS_POWER_OFF, (save-buffers-kill-emacs)
4368 Select Quit from Dock menu:
4371 Cancel -> Nothing else
4375 KEY_NS_POWER_OFF, (save-buffers-kill-emacs)
4380 - (void
) terminate
: (id
)sender
4382 struct frame
*emacsframe
= SELECTED_FRAME
();
4387 emacs_event
->kind
= NS_NONKEY_EVENT
;
4388 emacs_event
->code
= KEY_NS_POWER_OFF
;
4389 emacs_event
->arg
= Qt
; /* mark as non-key event */
4390 EV_TRAILER
((id
)nil
);
4394 - (NSApplicationTerminateReply
)applicationShouldTerminate
: (id
)sender
4398 if (NILP
(ns_confirm_quit
)) // || ns_shutdown_properly
--> TO DO
4399 return NSTerminateNow
;
4401 ret
= NSRunAlertPanel
(ns_app_name
,
4402 @"Exit requested. Would you like to
Save Buffers and Exit
, or Cancel the request?"
,
4403 @"
Save Buffers and Exit"
, @"Cancel"
, nil
);
4405 if (ret
== NSAlertDefaultReturn
)
4406 return NSTerminateNow
;
4407 else if (ret
== NSAlertAlternateReturn
)
4408 return NSTerminateCancel
;
4409 return NSTerminateNow
; /* just in case */
4413 not_in_argv
(NSString
*arg
)
4416 const
char *a
= [arg UTF8String
];
4417 for (k
= 1; k
< initial_argc
; ++k
)
4418 if (strcmp (a
, initial_argv
[k
]) == 0) return 0;
4422 /* Notification from the Workspace to open a file */
4423 - (BOOL
)application
: sender openFile
: (NSString
*)file
4425 if (ns_do_open_file || not_in_argv
(file
))
4426 [ns_pending_files addObject
: file
];
4431 /* Open a file as a temporary file */
4432 - (BOOL
)application
: sender openTempFile
: (NSString
*)file
4434 if (ns_do_open_file || not_in_argv
(file
))
4435 [ns_pending_files addObject
: file
];
4440 /* Notification from the Workspace to open a file noninteractively (?) */
4441 - (BOOL
)application
: sender openFileWithoutUI
: (NSString
*)file
4443 if (ns_do_open_file || not_in_argv
(file
))
4444 [ns_pending_files addObject
: file
];
4448 /* Notification from the Workspace to open multiple files */
4449 - (void
)application
: sender openFiles
: (NSArray
*)fileList
4451 NSEnumerator
*files
= [fileList objectEnumerator
];
4453 /* Don't open files from the command line unconditionally,
4454 Cocoa parses the command line wrong, --option value tries to open value
4455 if --option is the last option. */
4456 while ((file
= [files nextObject
]) != nil
)
4457 if (ns_do_open_file || not_in_argv
(file
))
4458 [ns_pending_files addObject
: file
];
4460 [self replyToOpenOrPrint
: NSApplicationDelegateReplySuccess
];
4465 /* Handle dock menu requests. */
4466 - (NSMenu
*)applicationDockMenu
: (NSApplication
*) sender
4472 /* TODO: these may help w/IO switching btwn terminal and NSApp */
4473 - (void
)applicationWillBecomeActive
: (NSNotification
*)notification
4475 //ns_app_active
=YES
;
4477 - (void
)applicationDidBecomeActive
: (NSNotification
*)notification
4479 NSTRACE
(applicationDidBecomeActive
);
4481 //ns_app_active
=YES
;
4483 ns_update_auto_hide_menu_bar
();
4484 // No constraining takes place when the application is not active.
4485 ns_constrain_all_frames
();
4487 - (void
)applicationDidResignActive
: (NSNotification
*)notification
4490 ns_send_appdefined
(-1);
4495 /* ==========================================================================
4497 EmacsApp aux handlers for managing event loop
4499 ========================================================================== */
4502 - (void
)timeout_handler
: (NSTimer
*)timedEntry
4503 /* --------------------------------------------------------------------------
4504 The timeout specified to ns_select has passed.
4505 -------------------------------------------------------------------------- */
4507 /*NSTRACE (timeout_handler); */
4508 ns_send_appdefined
(-2);
4511 - (void
)fd_handler
:(id
)unused
4512 /* --------------------------------------------------------------------------
4513 Check data waiting on file descriptors and terminate if so
4514 -------------------------------------------------------------------------- */
4517 int waiting
= 1, nfds
;
4520 SELECT_TYPE readfds
, writefds
, *wfds
;
4521 EMACS_TIME timeout
, *tmo
;
4522 NSAutoreleasePool
*pool
= nil
;
4524 /* NSTRACE (fd_handler); */
4529 pool
= [[NSAutoreleasePool alloc
] init
];
4535 FD_SET
(selfds
[0], &fds
);
4536 result
= select
(selfds
[0]+1, &fds
, NULL, NULL, NULL);
4539 read
(selfds
[0], &c
, 1);
4540 if (c
== 'g') waiting
= 0;
4545 pthread_mutex_lock
(&select_mutex
);
4548 if (select_valid
& SELECT_HAVE_READ
)
4549 readfds
= select_readfds
;
4553 if (select_valid
& SELECT_HAVE_WRITE
)
4555 writefds
= select_writefds
;
4560 if (select_valid
& SELECT_HAVE_TMO
)
4562 timeout
= select_timeout
;
4568 pthread_mutex_unlock
(&select_mutex
);
4570 FD_SET
(selfds
[0], &readfds
);
4571 if (selfds
[0] >= nfds
) nfds
= selfds
[0]+1;
4573 result
= pselect
(nfds
, &readfds
, wfds
, NULL, tmo
, NULL);
4576 ns_send_appdefined
(-2);
4577 else if (result
> 0)
4579 if (FD_ISSET
(selfds
[0], &readfds
))
4581 read
(selfds
[0], &c
, 1);
4582 if (c
== 's') waiting
= 1;
4586 pthread_mutex_lock
(&select_mutex
);
4587 if (select_valid
& SELECT_HAVE_READ
)
4588 select_readfds
= readfds
;
4589 if (select_valid
& SELECT_HAVE_WRITE
)
4590 select_writefds
= writefds
;
4591 if (select_valid
& SELECT_HAVE_TMO
)
4592 select_timeout
= timeout
;
4593 pthread_mutex_unlock
(&select_mutex
);
4595 ns_send_appdefined
(result
);
4605 /* ==========================================================================
4609 ========================================================================== */
4611 /* called from system: queue for next pass through event loop */
4612 - (void
)requestService
: (NSPasteboard
*)pboard
4613 userData
: (NSString
*)userData
4614 error: (NSString
**)error
4616 [ns_pending_service_names addObject
: userData
];
4617 [ns_pending_service_args addObject
: [NSString stringWithUTF8String
:
4618 SSDATA
(ns_string_from_pasteboard
(pboard
))]];
4622 /* called from ns_read_socket to clear queue */
4623 - (BOOL
)fulfillService
: (NSString
*)name withArg
: (NSString
*)arg
4625 struct frame
*emacsframe
= SELECTED_FRAME
();
4626 NSEvent
*theEvent
= [NSApp currentEvent
];
4631 emacs_event
->kind
= NS_NONKEY_EVENT
;
4632 emacs_event
->code
= KEY_NS_SPI_SERVICE_CALL
;
4633 ns_input_spi_name
= build_string
([name UTF8String
]);
4634 ns_input_spi_arg
= build_string
([arg UTF8String
]);
4635 emacs_event
->modifiers
= EV_MODIFIERS
(theEvent
);
4636 EV_TRAILER
(theEvent
);
4646 /* ==========================================================================
4648 EmacsView implementation
4650 ========================================================================== */
4653 @implementation EmacsView
4655 /* needed to inform when window closed from LISP */
4656 - (void
) setWindowClosing
: (BOOL
)closing
4658 windowClosing
= closing
;
4664 NSTRACE
(EmacsView_dealloc
);
4670 /* called on font panel selection */
4671 - (void
)changeFont
: (id
)sender
4673 NSEvent
*e
=[[self window
] currentEvent
];
4674 struct face
*face
=FRAME_DEFAULT_FACE
(emacsframe
);
4678 NSTRACE
(changeFont
);
4682 if ((newFont
= [sender convertFont
:
4683 ((struct nsfont_info
*)face
->font
)->nsfont
]))
4685 SET_FRAME_GARBAGED
(emacsframe
); /* now needed as of 2008/10 */
4687 emacs_event
->kind
= NS_NONKEY_EVENT
;
4688 emacs_event
->modifiers
= 0;
4689 emacs_event
->code
= KEY_NS_CHANGE_FONT
;
4691 size = [newFont pointSize
];
4692 ns_input_fontsize
= make_number
(lrint
(size));
4693 ns_input_font
= build_string
([[newFont familyName
] UTF8String
]);
4699 - (BOOL
)acceptsFirstResponder
4701 NSTRACE
(acceptsFirstResponder
);
4706 - (void
)resetCursorRects
4708 NSRect visible
= [self visibleRect
];
4709 NSCursor
*currentCursor
= FRAME_POINTER_TYPE
(emacsframe
);
4710 NSTRACE
(resetCursorRects
);
4712 if (currentCursor
== nil
)
4713 currentCursor
= [NSCursor arrowCursor
];
4715 if (!NSIsEmptyRect
(visible
))
4716 [self addCursorRect
: visible cursor
: currentCursor
];
4717 [currentCursor setOnMouseEntered
: YES
];
4722 /*****************************************************************************/
4723 /* Keyboard handling. */
4726 - (void
)keyDown
: (NSEvent
*)theEvent
4728 Mouse_HLInfo
*hlinfo
= MOUSE_HL_INFO
(emacsframe
);
4730 unsigned fnKeysym
= 0;
4732 static NSMutableArray
*nsEvArray
;
4733 #
if !defined
(NS_IMPL_COCOA
) || MAC_OS_X_VERSION_MAX_ALLOWED
< MAC_OS_X_VERSION_10_6
4734 static BOOL firstTime
= YES
;
4740 /* Rhapsody and OS X give up and down events for the arrow keys */
4741 if (ns_fake_keydown
== YES
)
4742 ns_fake_keydown
= NO
;
4743 else if ([theEvent
type] != NSKeyDown
)
4749 if (![[self window
] isKeyWindow
]
4750 && [[theEvent window
] isKindOfClass
: [EmacsWindow
class]]
4751 /* we must avoid an infinite loop here. */
4752 && (EmacsView
*)[[theEvent window
] delegate
] != self
)
4754 /* XXX: There is an occasional condition in which, when Emacs display
4755 updates a different frame from the current one, and temporarily
4756 selects it, then processes some interrupt-driven input
4757 (dispnew.c:3878), OS will send the event to the correct NSWindow, but
4758 for some reason that window has its first responder set to the NSView
4759 most recently updated (I guess), which is not the correct one. */
4760 [(EmacsView
*)[[theEvent window
] delegate
] keyDown
: theEvent
];
4764 if (nsEvArray
== nil
)
4765 nsEvArray
= [[NSMutableArray alloc
] initWithCapacity
: 1];
4767 [NSCursor setHiddenUntilMouseMoves
: YES
];
4769 if (hlinfo
->mouse_face_hidden
&& INTEGERP
(Vmouse_highlight
))
4771 clear_mouse_face
(hlinfo
);
4772 hlinfo
->mouse_face_hidden
= 1;
4775 if (!processingCompose
)
4777 /* When using screen sharing, no left or right information is sent,
4778 so use Left key in those cases. */
4779 int is_left_key
, is_right_key
;
4781 code
= ([[theEvent charactersIgnoringModifiers
] length] == 0) ?
4782 0 : [[theEvent charactersIgnoringModifiers
] characterAtIndex
: 0];
4784 /* (Carbon way: [theEvent keyCode]) */
4786 /* is it a "function key"? */
4787 fnKeysym
= ns_convert_key
(code
);
4790 /* COUNTERHACK: map 'Delete' on upper-right main KB to 'Backspace',
4791 because Emacs treats Delete and KP-Delete same (in simple.el). */
4792 if (fnKeysym
== 0xFFFF && [theEvent keyCode
] == 0x33)
4793 code
= 0xFF08; /* backspace */
4798 /* are there modifiers? */
4799 emacs_event
->modifiers
= 0;
4800 flags
= [theEvent modifierFlags
];
4802 if (flags
& NSHelpKeyMask
)
4803 emacs_event
->modifiers |
= hyper_modifier
;
4805 if (flags
& NSShiftKeyMask
)
4806 emacs_event
->modifiers |
= shift_modifier
;
4808 is_right_key
= (flags
& NSRightCommandKeyMask
) == NSRightCommandKeyMask
;
4809 is_left_key
= (flags
& NSLeftCommandKeyMask
) == NSLeftCommandKeyMask
4810 ||
(! is_right_key
&& (flags
& NSCommandKeyMask
) == NSCommandKeyMask
);
4813 emacs_event
->modifiers |
= parse_solitary_modifier
4814 (EQ
(ns_right_command_modifier
, Qleft
)
4815 ? ns_command_modifier
4816 : ns_right_command_modifier
);
4820 emacs_event
->modifiers |
= parse_solitary_modifier
4821 (ns_command_modifier
);
4823 /* if super (default), take input manager's word so things like
4824 dvorak / qwerty layout work */
4825 if (EQ
(ns_command_modifier
, Qsuper
)
4827 && [[theEvent characters
] length] != 0)
4829 /* XXX: the code we get will be unshifted, so if we have
4830 a shift modifier, must convert ourselves */
4831 if (!(flags
& NSShiftKeyMask
))
4832 code
= [[theEvent characters
] characterAtIndex
: 0];
4834 /* this is ugly and also requires linking w/Carbon framework
4835 (for LMGetKbdType) so for now leave this rare (?) case
4836 undealt with.. in future look into CGEvent methods */
4839 long smv
= GetScriptManagerVariable
(smKeyScript
);
4840 Handle uchrHandle
= GetResource
4841 ('uchr', GetScriptVariable
(smv
, smScriptKeys
));
4843 UCKeyTranslate
((UCKeyboardLayout
*)*uchrHandle
,
4844 [[theEvent characters
] characterAtIndex
: 0],
4845 kUCKeyActionDisplay
,
4846 (flags
& ~NSCommandKeyMask
) >> 8,
4847 LMGetKbdType
(), kUCKeyTranslateNoDeadKeysMask
,
4848 &dummy
, 1, &dummy
, &code
);
4855 is_right_key
= (flags
& NSRightControlKeyMask
) == NSRightControlKeyMask
;
4856 is_left_key
= (flags
& NSLeftControlKeyMask
) == NSLeftControlKeyMask
4857 ||
(! is_right_key
&& (flags
& NSControlKeyMask
) == NSControlKeyMask
);
4860 emacs_event
->modifiers |
= parse_solitary_modifier
4861 (EQ
(ns_right_control_modifier
, Qleft
)
4862 ? ns_control_modifier
4863 : ns_right_control_modifier
);
4866 emacs_event
->modifiers |
= parse_solitary_modifier
4867 (ns_control_modifier
);
4869 if (flags
& NS_FUNCTION_KEY_MASK
&& !fnKeysym
)
4870 emacs_event
->modifiers |
=
4871 parse_solitary_modifier
(ns_function_modifier
);
4873 left_is_none
= NILP
(ns_alternate_modifier
)
4874 || EQ
(ns_alternate_modifier
, Qnone
);
4876 is_right_key
= (flags
& NSRightAlternateKeyMask
)
4877 == NSRightAlternateKeyMask
;
4878 is_left_key
= (flags
& NSLeftAlternateKeyMask
) == NSLeftAlternateKeyMask
4880 && (flags
& NSAlternateKeyMask
) == NSAlternateKeyMask
);
4884 if ((NILP
(ns_right_alternate_modifier
)
4885 || EQ
(ns_right_alternate_modifier
, Qnone
)
4886 ||
(EQ
(ns_right_alternate_modifier
, Qleft
) && left_is_none
))
4888 { /* accept pre-interp alt comb */
4889 if ([[theEvent characters
] length] > 0)
4890 code
= [[theEvent characters
] characterAtIndex
: 0];
4891 /*HACK: clear lone shift modifier to stop next if from firing */
4892 if (emacs_event
->modifiers
== shift_modifier
)
4893 emacs_event
->modifiers
= 0;
4896 emacs_event
->modifiers |
= parse_solitary_modifier
4897 (EQ
(ns_right_alternate_modifier
, Qleft
)
4898 ? ns_alternate_modifier
4899 : ns_right_alternate_modifier
);
4902 if (is_left_key
) /* default = meta */
4904 if (left_is_none
&& !fnKeysym
)
4905 { /* accept pre-interp alt comb */
4906 if ([[theEvent characters
] length] > 0)
4907 code
= [[theEvent characters
] characterAtIndex
: 0];
4908 /*HACK: clear lone shift modifier to stop next if from firing */
4909 if (emacs_event
->modifiers
== shift_modifier
)
4910 emacs_event
->modifiers
= 0;
4913 emacs_event
->modifiers |
=
4914 parse_solitary_modifier
(ns_alternate_modifier
);
4918 fprintf (stderr
, "keyDown
: code
=%x\tfnKey =%x\tflags = %x\tmods = %x\n",
4919 code
, fnKeysym
, flags
, emacs_event
->modifiers
);
4921 /* if it was a function key or had modifiers, pass it directly to emacs */
4922 if (fnKeysym ||
(emacs_event
->modifiers
4923 && (emacs_event
->modifiers
!= shift_modifier
)
4924 && [[theEvent charactersIgnoringModifiers
] length] > 0))
4925 /*[[theEvent characters] length] */
4927 emacs_event
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
4929 code |
= (1<<28)|
(3<<16);
4930 else if (code
== 0x7f)
4931 code |
= (1<<28)|
(3<<16);
4933 emacs_event
->kind
= code
> 0xFF
4934 ? MULTIBYTE_CHAR_KEYSTROKE_EVENT
: ASCII_KEYSTROKE_EVENT
;
4936 emacs_event
->code
= code
;
4937 EV_TRAILER
(theEvent
);
4943 #
if !defined
(NS_IMPL_COCOA
) || MAC_OS_X_VERSION_MAX_ALLOWED
< MAC_OS_X_VERSION_10_6
4944 /* if we get here we should send the key for input manager processing */
4945 if (firstTime
&& [[NSInputManager currentInputManager
]
4946 wantsToDelayTextChangeNotifications
] == NO
)
4948 "Emacs
: WARNING
: TextInput mgr wants marked
text to be permanent
!\n"
);
4951 if (NS_KEYLOG
&& !processingCompose
)
4952 fprintf (stderr
, "keyDown
: Begin compose sequence.
\n"
);
4954 processingCompose
= YES
;
4955 [nsEvArray addObject
: theEvent
];
4956 [self interpretKeyEvents
: nsEvArray
];
4957 [nsEvArray removeObject
: theEvent
];
4961 #ifdef NS_IMPL_COCOA
4962 /* Needed to pick up Ctrl-tab and possibly other events that OS X has
4963 decided not to send key-down for.
4964 See http://osdir.com/ml/editors.vim.mac/2007-10/msg00141.html
4965 This only applies on Tiger and earlier.
4966 If it matches one of these, send it on to keyDown. */
4967 -(void
)keyUp
: (NSEvent
*)theEvent
4969 int flags
= [theEvent modifierFlags
];
4970 int code
= [theEvent keyCode
];
4971 if (floor (NSAppKitVersionNumber
) <= 824 /*NSAppKitVersionNumber10_4*/ &&
4972 code
== 0x30 && (flags
& NSControlKeyMask
) && !(flags
& NSCommandKeyMask
))
4975 fprintf (stderr
, "keyUp
: passed test"
);
4976 ns_fake_keydown
= YES
;
4977 [self keyDown
: theEvent
];
4983 /* <NSTextInput> implementation (called through super interpretKeyEvents:]). */
4986 /* <NSTextInput>: called when done composing;
4987 NOTE: also called when we delete over working text, followed immed.
4988 by doCommandBySelector: deleteBackward: */
4989 - (void
)insertText
: (id
)aString
4992 int len
= [(NSString
*)aString
length];
4996 NSLog
(@"insertText
'%@'\tlen
= %d", aString, len);
4997 processingCompose
= NO
;
5002 /* first, clear any working text */
5003 if (workingText
!= nil
)
5004 [self deleteWorkingText
];
5006 /* now insert the string as keystrokes */
5007 for (i
=0; i
<len
; i
++)
5009 code
= [aString characterAtIndex
: i
];
5010 /* TODO: still need this? */
5012 code
= '~'; /* 0x7E */
5013 if (code
!= 32) /* Space */
5014 emacs_event
->modifiers
= 0;
5016 = code
> 0xFF ? MULTIBYTE_CHAR_KEYSTROKE_EVENT
: ASCII_KEYSTROKE_EVENT
;
5017 emacs_event
->code
= code
;
5018 EV_TRAILER
((id
)nil
);
5023 /* <NSTextInput>: inserts display of composing characters */
5024 - (void
)setMarkedText
: (id
)aString selectedRange
: (NSRange
)selRange
5026 NSString
*str
= [aString respondsToSelector
: @selector
(string
)] ?
5027 [aString string
] : aString
;
5029 NSLog
(@"setMarkedText
'%@' len
=%d range %d from %d", str, [str length],
5030 selRange.
length, selRange.location
);
5032 if (workingText
!= nil
)
5033 [self deleteWorkingText
];
5034 if ([str
length] == 0)
5040 processingCompose
= YES
;
5041 workingText
= [str copy
];
5042 ns_working_text
= build_string
([workingText UTF8String
]);
5044 emacs_event
->kind
= NS_TEXT_EVENT
;
5045 emacs_event
->code
= KEY_NS_PUT_WORKING_TEXT
;
5046 EV_TRAILER
((id
)nil
);
5050 /* delete display of composing characters [not in <NSTextInput>] */
5051 - (void
)deleteWorkingText
5053 if (workingText
== nil
)
5056 NSLog
(@"deleteWorkingText len
=%d\n", [workingText length]);
5057 [workingText release
];
5059 processingCompose
= NO
;
5064 emacs_event
->kind
= NS_TEXT_EVENT
;
5065 emacs_event
->code
= KEY_NS_UNPUT_WORKING_TEXT
;
5066 EV_TRAILER
((id
)nil
);
5070 - (BOOL
)hasMarkedText
5072 return workingText
!= nil
;
5076 - (NSRange
)markedRange
5078 NSRange rng
= workingText
!= nil
5079 ? NSMakeRange
(0, [workingText
length]) : NSMakeRange
(NSNotFound
, 0);
5081 NSLog
(@"markedRange request"
);
5089 NSLog
(@"unmark
(accept
) text"
);
5090 [self deleteWorkingText
];
5091 processingCompose
= NO
;
5095 /* used to position char selection windows, etc. */
5096 - (NSRect
)firstRectForCharacterRange
: (NSRange
)theRange
5100 struct window
*win
= XWINDOW
(FRAME_SELECTED_WINDOW
(emacsframe
));
5102 NSLog
(@"firstRectForCharRange request"
);
5104 rect.
size.width
= theRange.
length * FRAME_COLUMN_WIDTH
(emacsframe
);
5105 rect.
size.height
= FRAME_LINE_HEIGHT
(emacsframe
);
5106 pt.x
= WINDOW_TEXT_TO_FRAME_PIXEL_X
(win
, win
->phys_cursor.x
);
5107 pt.y
= WINDOW_TO_FRAME_PIXEL_Y
(win
, win
->phys_cursor.y
5108 +FRAME_LINE_HEIGHT
(emacsframe
));
5110 pt
= [self convertPoint
: pt toView
: nil
];
5111 pt
= [[self window
] convertBaseToScreen
: pt
];
5117 - (NSInteger
)conversationIdentifier
5119 return (NSInteger
)self
;
5123 - (void
)doCommandBySelector
: (SEL
)aSelector
5126 NSLog
(@"doCommandBySelector
: %@", NSStringFromSelector (aSelector));
5128 if (aSelector
== @selector
(deleteBackward
:))
5130 /* happens when user backspaces over an ongoing composition:
5131 throw a 'delete' into the event queue */
5134 emacs_event
->kind
= NON_ASCII_KEYSTROKE_EVENT
;
5135 emacs_event
->code
= 0xFF08;
5136 EV_TRAILER
((id
)nil
);
5140 - (NSArray
*)validAttributesForMarkedText
5142 static NSArray
*arr
= nil
;
5143 if (arr
== nil
) arr
= [NSArray new
];
5144 /* [[NSArray arrayWithObject: NSUnderlineStyleAttributeName] retain]; */
5148 - (NSRange
)selectedRange
5151 NSLog
(@"selectedRange request"
);
5152 return NSMakeRange
(NSNotFound
, 0);
5155 - (NSUInteger
)characterIndexForPoint
: (NSPoint
)thePoint
5158 NSLog
(@"characterIndexForPoint request"
);
5162 - (NSAttributedString
*)attributedSubstringFromRange
: (NSRange
)theRange
5164 static NSAttributedString
*str
= nil
;
5165 if (str
== nil
) str
= [NSAttributedString new
];
5167 NSLog
(@"attributedSubstringFromRange request"
);
5171 /* End <NSTextInput> impl. */
5172 /*****************************************************************************/
5175 /* This is what happens when the user presses a mouse button. */
5176 - (void
)mouseDown
: (NSEvent
*)theEvent
5178 NSPoint p
= [self convertPoint
: [theEvent locationInWindow
] fromView
: nil
];
5180 NSTRACE
(mouseDown
);
5182 [self deleteWorkingText
];
5187 last_mouse_frame
= emacsframe
;
5188 /* appears to be needed to prevent spurious movement events generated on
5190 last_mouse_frame
->mouse_moved
= 0;
5192 if ([theEvent
type] == NSScrollWheel
)
5194 float delta
= [theEvent deltaY
];
5195 /* Mac notebooks send wheel events w/delta =0 when trackpad scrolling */
5198 emacs_event
->kind
= WHEEL_EVENT
;
5199 emacs_event
->code
= 0;
5200 emacs_event
->modifiers
= EV_MODIFIERS
(theEvent
) |
5201 ((delta
> 0) ? up_modifier
: down_modifier
);
5205 emacs_event
->kind
= MOUSE_CLICK_EVENT
;
5206 emacs_event
->code
= EV_BUTTON
(theEvent
);
5207 emacs_event
->modifiers
= EV_MODIFIERS
(theEvent
)
5208 | EV_UDMODIFIERS
(theEvent
);
5210 XSETINT
(emacs_event
->x
, lrint
(p.x
));
5211 XSETINT
(emacs_event
->y
, lrint
(p.y
));
5212 EV_TRAILER
(theEvent
);
5216 - (void
)rightMouseDown
: (NSEvent
*)theEvent
5218 NSTRACE
(rightMouseDown
);
5219 [self mouseDown
: theEvent
];
5223 - (void
)otherMouseDown
: (NSEvent
*)theEvent
5225 NSTRACE
(otherMouseDown
);
5226 [self mouseDown
: theEvent
];
5230 - (void
)mouseUp
: (NSEvent
*)theEvent
5233 [self mouseDown
: theEvent
];
5237 - (void
)rightMouseUp
: (NSEvent
*)theEvent
5239 NSTRACE
(rightMouseUp
);
5240 [self mouseDown
: theEvent
];
5244 - (void
)otherMouseUp
: (NSEvent
*)theEvent
5246 NSTRACE
(otherMouseUp
);
5247 [self mouseDown
: theEvent
];
5251 - (void
) scrollWheel
: (NSEvent
*)theEvent
5253 NSTRACE
(scrollWheel
);
5254 [self mouseDown
: theEvent
];
5258 /* Tell emacs the mouse has moved. */
5259 - (void
)mouseMoved
: (NSEvent
*)e
5261 Mouse_HLInfo
*hlinfo
= MOUSE_HL_INFO
(emacsframe
);
5264 // NSTRACE
(mouseMoved
);
5266 last_mouse_movement_time
= EV_TIMESTAMP
(e
);
5267 last_mouse_motion_position
5268 = [self convertPoint
: [e locationInWindow
] fromView
: nil
];
5270 /* update any mouse face */
5271 if (hlinfo
->mouse_face_hidden
)
5273 hlinfo
->mouse_face_hidden
= 0;
5274 clear_mouse_face
(hlinfo
);
5277 /* tooltip handling */
5278 previous_help_echo_string
= help_echo_string
;
5279 help_echo_string
= Qnil
;
5281 if (!note_mouse_movement
(emacsframe
, last_mouse_motion_position.x
,
5282 last_mouse_motion_position.y
))
5283 help_echo_string
= previous_help_echo_string
;
5285 XSETFRAME
(frame
, emacsframe
);
5286 if (!NILP
(help_echo_string
) ||
!NILP
(previous_help_echo_string
))
5288 /* NOTE: help_echo_{window,pos,object} are set in xdisp.c
5289 (note_mouse_highlight), which is called through the
5290 note_mouse_movement () call above */
5291 gen_help_event
(help_echo_string
, frame
, help_echo_window
,
5292 help_echo_object
, help_echo_pos
);
5296 help_echo_string
= Qnil
;
5297 gen_help_event
(Qnil
, frame
, Qnil
, Qnil
, 0);
5300 if (emacsframe
->mouse_moved
&& send_appdefined
)
5301 ns_send_appdefined
(-1);
5305 - (void
)mouseDragged
: (NSEvent
*)e
5307 NSTRACE
(mouseDragged
);
5308 [self mouseMoved
: e
];
5312 - (void
)rightMouseDragged
: (NSEvent
*)e
5314 NSTRACE
(rightMouseDragged
);
5315 [self mouseMoved
: e
];
5319 - (void
)otherMouseDragged
: (NSEvent
*)e
5321 NSTRACE
(otherMouseDragged
);
5322 [self mouseMoved
: e
];
5326 - (BOOL
)windowShouldClose
: (id
)sender
5328 NSEvent
*e
=[[self window
] currentEvent
];
5330 NSTRACE
(windowShouldClose
);
5331 windowClosing
= YES
;
5334 emacs_event
->kind
= DELETE_WINDOW_EVENT
;
5335 emacs_event
->modifiers
= 0;
5336 emacs_event
->code
= 0;
5338 /* Don't close this window, let this be done from lisp code. */
5342 - (void
) updateFrameSize
5344 NSWindow
*window
= [self window
];
5345 NSRect wr
= [window frame
];
5346 #ifdef NS_IMPL_GNUSTEP
5352 int oldc
= cols
, oldr
= rows
;
5353 int oldw
= FRAME_PIXEL_WIDTH
(emacsframe
),
5354 oldh
= FRAME_PIXEL_HEIGHT
(emacsframe
);
5357 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS
(emacsframe
, wr.
size.width
+ extra
);
5359 if (cols
< MINWIDTH
)
5362 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES
5363 (emacsframe
, wr.
size.height
5364 - FRAME_NS_TITLEBAR_HEIGHT
(emacsframe
) + extra
5365 - FRAME_TOOLBAR_HEIGHT
(emacsframe
));
5367 if (rows
< MINHEIGHT
)
5370 neww
= (int
)wr.
size.width
- emacsframe
->border_width
;
5371 newh
= ((int
)wr.
size.height
5372 - FRAME_NS_TITLEBAR_HEIGHT
(emacsframe
)
5373 - FRAME_TOOLBAR_HEIGHT
(emacsframe
));
5375 if (oldr
!= rows || oldc
!= cols || neww
!= oldw || newh
!= oldh
)
5377 NSView
*view = FRAME_NS_VIEW
(emacsframe
);
5378 FRAME_PIXEL_WIDTH
(emacsframe
) = neww
;
5379 FRAME_PIXEL_HEIGHT
(emacsframe
) = newh
;
5380 change_frame_size
(emacsframe
, rows
, cols
, 0, 0, 1);
5381 SET_FRAME_GARBAGED
(emacsframe
);
5382 cancel_mouse_face
(emacsframe
);
5383 [view setFrame
: NSMakeRect
(0, 0, neww
, newh
)];
5387 - (NSSize
)windowWillResize
: (NSWindow
*)sender toSize
: (NSSize
)frameSize
5388 /* normalize frame to gridded text size */
5390 NSTRACE
(windowWillResize
);
5391 /*fprintf (stderr,"Window will resize: %.0f x %.0f\n",frameSize.width,frameSize.height); */
5393 cols
= FRAME_PIXEL_WIDTH_TO_TEXT_COLS
(emacsframe
,
5394 #ifdef NS_IMPL_GNUSTEP
5395 frameSize.width
+ 3);
5399 if (cols
< MINWIDTH
)
5402 rows
= FRAME_PIXEL_HEIGHT_TO_TEXT_LINES
(emacsframe
, frameSize.height
5403 #ifdef NS_IMPL_GNUSTEP
5404 - FRAME_NS_TITLEBAR_HEIGHT
(emacsframe
) + 3
5405 - FRAME_TOOLBAR_HEIGHT
(emacsframe
));
5407 - FRAME_NS_TITLEBAR_HEIGHT
(emacsframe
)
5408 - FRAME_TOOLBAR_HEIGHT
(emacsframe
));
5410 if (rows
< MINHEIGHT
)
5412 #ifdef NS_IMPL_COCOA
5414 /* this sets window title to have size in it; the wm does this under GS */
5415 NSRect r
= [[self window
] frame
];
5416 if (r.
size.height
== frameSize.height
&& r.
size.width
== frameSize.width
)
5427 NSWindow
*window
= [self window
];
5430 const
char *t
= [[[self window
] title] UTF8String
];
5431 char *pos
= strstr
(t
, " — "
);
5434 old_title
= xstrdup
(t
);
5436 size_title
= xmalloc
(strlen
(old_title
) + 40);
5437 esprintf
(size_title
, "
%s — (%d x %d)", old_title, cols, rows);
5438 [window setTitle
: [NSString stringWithUTF8String
: size_title
]];
5443 #endif
/* NS_IMPL_COCOA */
5444 /*fprintf (stderr," ...size became %.0f x %.0f (%d x %d)\n",frameSize.width,frameSize.height,cols,rows); */
5450 - (void
)windowDidResize
: (NSNotification
*)notification
5452 #ifdef NS_IMPL_GNUSTEP
5453 NSWindow
*theWindow
= [notification object
];
5455 /* in GNUstep, at least currently, it's possible to get a didResize
5456 without getting a willResize.. therefore we need to act as if we got
5457 the willResize now */
5458 NSSize sz
= [theWindow frame
].
size;
5459 sz
= [self windowWillResize
: theWindow toSize
: sz
];
5460 #endif
/* NS_IMPL_GNUSTEP */
5462 NSTRACE
(windowDidResize
);
5463 /*fprintf (stderr,"windowDidResize: %.0f\n",[theWindow frame].size.height); */
5465 #ifdef NS_IMPL_COCOA
5471 #endif
/* NS_IMPL_COCOA */
5473 /* Avoid loop under GNUstep due to call at beginning of this function.
5474 (x_set_window_size causes a resize which causes
5475 a "windowDidResize" which calls x_set_window_size). */
5476 #ifndef NS_IMPL_GNUSTEP
5477 if (cols
> 0 && rows
> 0)
5480 x_set_window_size
(emacsframe
, 0, cols
, rows
);
5483 [self updateFrameSize
];
5488 ns_send_appdefined
(-1);
5492 - (void
)windowDidBecomeKey
: (NSNotification
*)notification
5493 /* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
5495 struct ns_display_info
*dpyinfo
= FRAME_NS_DISPLAY_INFO
(emacsframe
);
5496 struct frame
*old_focus
= dpyinfo
->x_focus_frame
;
5498 NSTRACE
(windowDidBecomeKey
);
5500 if (emacsframe
!= old_focus
)
5501 dpyinfo
->x_focus_frame
= emacsframe
;
5503 ns_frame_rehighlight
(emacsframe
);
5507 emacs_event
->kind
= FOCUS_IN_EVENT
;
5508 EV_TRAILER
((id
)nil
);
5513 - (void
)windowDidResignKey
: (NSNotification
*)notification
5514 /* cf. x_detect_focus_change(), x_focus_changed(), x_new_focus_frame() */
5516 struct ns_display_info
*dpyinfo
= FRAME_NS_DISPLAY_INFO
(emacsframe
);
5517 NSTRACE
(windowDidResignKey
);
5519 if (dpyinfo
->x_focus_frame
== emacsframe
)
5520 dpyinfo
->x_focus_frame
= 0;
5522 ns_frame_rehighlight
(emacsframe
);
5524 /* FIXME: for some reason needed on second and subsequent clicks away
5525 from sole-frame Emacs to get hollow box to show */
5526 if (!windowClosing
&& [[self window
] isVisible
] == YES
)
5528 x_update_cursor
(emacsframe
, 1);
5529 x_set_frame_alpha
(emacsframe
);
5534 [self deleteWorkingText
];
5535 emacs_event
->kind
= FOCUS_IN_EVENT
;
5536 EV_TRAILER
((id
)nil
);
5541 - (void
)windowWillMiniaturize
: sender
5543 NSTRACE
(windowWillMiniaturize
);
5559 - initFrameFromEmacs
: (struct frame
*)f
5564 NSButton
*toggleButton
;
5569 NSTRACE
(initFrameFromEmacs
);
5572 processingCompose
= NO
;
5573 scrollbarsNeedingUpdate
= 0;
5575 /*fprintf (stderr,"init with %d, %d\n",f->text_cols, f->text_lines); */
5577 ns_userRect
= NSMakeRect
(0, 0, 0, 0);
5578 r
= NSMakeRect
(0, 0, FRAME_TEXT_COLS_TO_PIXEL_WIDTH
(f
, f
->text_cols
),
5579 FRAME_TEXT_LINES_TO_PIXEL_HEIGHT
(f
, f
->text_lines
));
5580 [self initWithFrame
: r
];
5581 [self setAutoresizingMask
: NSViewWidthSizable | NSViewHeightSizable
];
5583 FRAME_NS_VIEW
(f
) = self
;
5587 win
= [[EmacsWindow alloc
]
5588 initWithContentRect
: r
5589 styleMask
: (NSResizableWindowMask |
5590 #
if MAC_OS_X_VERSION_MAX_ALLOWED
>= MAC_OS_X_VERSION_10_7
5591 NSTitledWindowMask |
5593 NSMiniaturizableWindowMask |
5594 NSClosableWindowMask
)
5595 backing
: NSBackingStoreBuffered
5599 f
->border_width
= wr.
size.width
- r.
size.width
;
5600 FRAME_NS_TITLEBAR_HEIGHT
(f
) = wr.
size.height
- r.
size.height
;
5602 [win setAcceptsMouseMovedEvents
: YES
];
5603 [win setDelegate
: self
];
5604 [win useOptimizedDrawing
: YES
];
5606 sz.width
= FRAME_COLUMN_WIDTH
(f
);
5607 sz.height
= FRAME_LINE_HEIGHT
(f
);
5608 [win setResizeIncrements
: sz
];
5610 [[win contentView
] addSubview
: self
];
5613 [self registerForDraggedTypes
: ns_drag_types
];
5616 name
= [NSString stringWithUTF8String
:
5617 NILP
(tem
) ? "Emacs"
: SSDATA
(tem
)];
5618 [win setTitle
: name
];
5620 /* toolbar support */
5621 toolbar
= [[EmacsToolbar alloc
] initForView
: self withIdentifier
:
5622 [NSString stringWithFormat
: @"Emacs Frame
%d",
5624 [win setToolbar
: toolbar
];
5625 [toolbar setVisible
: NO
];
5626 #ifdef NS_IMPL_COCOA
5627 toggleButton
= [win standardWindowButton
: NSWindowToolbarButton
];
5628 [toggleButton setTarget
: self
];
5629 [toggleButton setAction
: @selector
(toggleToolbar
: )];
5631 FRAME_TOOLBAR_HEIGHT
(f
) = 0;
5635 [win setMiniwindowTitle
:
5636 [NSString stringWithUTF8String
: SSDATA
(tem
)]];
5639 NSScreen
*screen
= [win screen
];
5642 [win setFrameTopLeftPoint
: NSMakePoint
5643 (IN_BOUND
(-SCREENMAX
, f
->left_pos
, SCREENMAX
),
5644 IN_BOUND
(-SCREENMAX
,
5645 [screen frame
].
size.height
- NS_TOP_POS
(f
), SCREENMAX
))];
5648 [win makeFirstResponder
: self
];
5650 col
= ns_lookup_indexed_color
(NS_FACE_BACKGROUND
5651 (FRAME_DEFAULT_FACE
(emacsframe
)), emacsframe
);
5652 [win setBackgroundColor
: col
];
5653 if ([col alphaComponent
] != 1.0)
5654 [win setOpaque
: NO
];
5656 [self allocateGState
];
5658 [NSApp registerServicesMenuSendTypes
: ns_send_types
5666 - (void
)windowDidMove
: sender
5668 NSWindow
*win
= [self window
];
5669 NSRect r
= [win frame
];
5670 NSArray
*screens
= [NSScreen screens
];
5671 NSScreen
*screen
= [screens objectAtIndex
: 0];
5673 NSTRACE
(windowDidMove
);
5675 if (!emacsframe
->output_data.ns
)
5679 emacsframe
->left_pos
= r.origin.x
;
5680 emacsframe
->top_pos
=
5681 [screen frame
].
size.height
- (r.origin.y
+ r.
size.height
);
5686 /* Called AFTER method below, but before our windowWillResize call there leads
5687 to windowDidResize -> x_set_window_size. Update emacs' notion of frame
5688 location so set_window_size moves the frame. */
5689 - (BOOL
)windowShouldZoom
: (NSWindow
*)sender toFrame
: (NSRect
)newFrame
5691 emacsframe
->output_data.ns
->zooming
= 1;
5696 /* Override to do something slightly nonstandard, but nice. First click on
5697 zoom button will zoom vertically. Second will zoom completely. Third
5698 returns to original. */
5699 - (NSRect
)windowWillUseStandardFrame
:(NSWindow
*)sender
5700 defaultFrame
:(NSRect
)defaultFrame
5702 NSRect result
= [sender frame
];
5704 NSTRACE
(windowWillUseStandardFrame
);
5706 if (abs (defaultFrame.
size.height
- result.
size.height
)
5707 > FRAME_LINE_HEIGHT
(emacsframe
))
5710 ns_userRect
= result
;
5711 result.
size.height
= defaultFrame.
size.height
;
5712 result.origin.y
= defaultFrame.origin.y
;
5716 if (abs (defaultFrame.
size.width
- result.
size.width
)
5717 > FRAME_COLUMN_WIDTH
(emacsframe
))
5718 result
= defaultFrame
; /* second click */
5722 result
= ns_userRect.
size.height ? ns_userRect
: result
;
5723 ns_userRect
= NSMakeRect
(0, 0, 0, 0);
5727 [self windowWillResize
: sender toSize
: result.
size];
5732 - (void
)windowDidDeminiaturize
: sender
5734 NSTRACE
(windowDidDeminiaturize
);
5735 if (!emacsframe
->output_data.ns
)
5737 emacsframe
->async_iconified
= 0;
5738 emacsframe
->async_visible
= 1;
5739 windows_or_buffers_changed
++;
5743 emacs_event
->kind
= ICONIFY_EVENT
;
5744 EV_TRAILER
((id
)nil
);
5749 - (void
)windowDidExpose
: sender
5751 NSTRACE
(windowDidExpose
);
5752 if (!emacsframe
->output_data.ns
)
5754 emacsframe
->async_visible
= 1;
5755 SET_FRAME_GARBAGED
(emacsframe
);
5757 if (send_appdefined
)
5758 ns_send_appdefined
(-1);
5762 - (void
)windowDidMiniaturize
: sender
5764 NSTRACE
(windowDidMiniaturize
);
5765 if (!emacsframe
->output_data.ns
)
5768 emacsframe
->async_iconified
= 1;
5769 emacsframe
->async_visible
= 0;
5773 emacs_event
->kind
= ICONIFY_EVENT
;
5774 EV_TRAILER
((id
)nil
);
5779 - (void
)mouseEntered
: (NSEvent
*)theEvent
5781 NSTRACE
(mouseEntered
);
5782 last_mouse_movement_time
= EV_TIMESTAMP
(theEvent
);
5786 - (void
)mouseExited
: (NSEvent
*)theEvent
5788 Mouse_HLInfo
*hlinfo
= emacsframe ? MOUSE_HL_INFO
(emacsframe
) : NULL;
5790 NSTRACE
(mouseExited
);
5795 last_mouse_movement_time
= EV_TIMESTAMP
(theEvent
);
5797 if (emacsframe
== hlinfo
->mouse_face_mouse_frame
)
5799 clear_mouse_face
(hlinfo
);
5800 hlinfo
->mouse_face_mouse_frame
= 0;
5808 if (context_menu_value
== -1)
5809 context_menu_value
= [sender tag
];
5812 NSInteger tag
= [sender tag
];
5813 find_and_call_menu_selection
(emacsframe
, emacsframe
->menu_bar_items_used
,
5814 emacsframe
->menu_bar_vector
,
5818 ns_send_appdefined
(-1);
5823 - (EmacsToolbar
*)toolbar
5829 /* this gets called on toolbar button click */
5830 - toolbarClicked
: (id
)item
5833 int idx
= [item tag
] * TOOL_BAR_ITEM_NSLOTS
;
5835 NSTRACE
(toolbarClicked
);
5840 /* send first event (for some reason two needed) */
5841 theEvent
= [[self window
] currentEvent
];
5842 emacs_event
->kind
= TOOL_BAR_EVENT
;
5843 XSETFRAME
(emacs_event
->arg
, emacsframe
);
5844 EV_TRAILER
(theEvent
);
5846 emacs_event
->kind
= TOOL_BAR_EVENT
;
5847 /* XSETINT (emacs_event->code, 0); */
5848 emacs_event
->arg
= AREF
(emacsframe
->tool_bar_items
,
5849 idx
+ TOOL_BAR_ITEM_KEY
);
5850 emacs_event
->modifiers
= EV_MODIFIERS
(theEvent
);
5851 EV_TRAILER
(theEvent
);
5856 - toggleToolbar
: (id
)sender
5861 emacs_event
->kind
= NS_NONKEY_EVENT
;
5862 emacs_event
->code
= KEY_NS_TOGGLE_TOOLBAR
;
5863 EV_TRAILER
((id
)nil
);
5868 - (void
)drawRect
: (NSRect
)rect
5870 int x
= NSMinX
(rect
), y
= NSMinY
(rect
);
5871 int width
= NSWidth
(rect
), height
= NSHeight
(rect
);
5875 if (!emacsframe ||
!emacsframe
->output_data.ns || ns_in_resize
)
5878 ns_clear_frame_area
(emacsframe
, x
, y
, width
, height
);
5879 expose_frame
(emacsframe
, x
, y
, width
, height
);
5882 drawRect: may be called (at least in OS X 10.5) for invisible
5883 views as well for some reason. Thus, do not infer visibility
5886 emacsframe->async_visible = 1;
5887 emacsframe->async_iconified = 0;
5892 /* NSDraggingDestination protocol methods. Actually this is not really a
5893 protocol, but a category of Object. O well... */
5895 -(NSUInteger
) draggingEntered
: (id
<NSDraggingInfo
>) sender
5897 NSTRACE
(draggingEntered
);
5898 return NSDragOperationGeneric
;
5902 -(BOOL
)prepareForDragOperation
: (id
<NSDraggingInfo
>) sender
5908 -(BOOL
)performDragOperation
: (id
<NSDraggingInfo
>) sender
5913 NSEvent
*theEvent
= [[self window
] currentEvent
];
5916 NSTRACE
(performDragOperation
);
5921 position
= [self convertPoint
: [sender draggingLocation
] fromView
: nil
];
5922 x
= lrint
(position.x
); y
= lrint
(position.y
);
5924 pb
= [sender draggingPasteboard
];
5925 type = [pb availableTypeFromArray
: ns_drag_types
];
5930 else if ([type isEqualToString
: NSFilenamesPboardType
])
5933 NSEnumerator
*fenum
;
5936 if (!(files
= [pb propertyListForType
: type]))
5939 fenum
= [files objectEnumerator
];
5940 while ( (file
= [fenum nextObject
]) )
5942 emacs_event
->kind
= NS_NONKEY_EVENT
;
5943 emacs_event
->code
= KEY_NS_DRAG_FILE
;
5944 XSETINT
(emacs_event
->x
, x
);
5945 XSETINT
(emacs_event
->y
, y
);
5946 ns_input_file
= append2
(ns_input_file
,
5947 build_string
([file UTF8String
]));
5948 emacs_event
->modifiers
= EV_MODIFIERS
(theEvent
);
5949 EV_TRAILER
(theEvent
);
5953 else if ([type isEqualToString
: NSURLPboardType
])
5958 if (!(fileURL
= [NSURL URLFromPasteboard
: pb
]) ||
5959 [fileURL isFileURL
] == NO
)
5962 file
= [fileURL
path];
5963 emacs_event
->kind
= NS_NONKEY_EVENT
;
5964 emacs_event
->code
= KEY_NS_DRAG_FILE
;
5965 XSETINT
(emacs_event
->x
, x
);
5966 XSETINT
(emacs_event
->y
, y
);
5967 ns_input_file
= append2
(ns_input_file
, build_string
([file UTF8String
]));
5968 emacs_event
->modifiers
= EV_MODIFIERS
(theEvent
);
5969 EV_TRAILER
(theEvent
);
5972 else if ([type isEqualToString
: NSStringPboardType
]
5973 ||
[type isEqualToString
: NSTabularTextPboardType
])
5977 if (! (data
= [pb stringForType
: type]))
5980 emacs_event
->kind
= NS_NONKEY_EVENT
;
5981 emacs_event
->code
= KEY_NS_DRAG_TEXT
;
5982 XSETINT
(emacs_event
->x
, x
);
5983 XSETINT
(emacs_event
->y
, y
);
5984 ns_input_text
= build_string
([data UTF8String
]);
5985 emacs_event
->modifiers
= EV_MODIFIERS
(theEvent
);
5986 EV_TRAILER
(theEvent
);
5989 else if ([type isEqualToString
: NSColorPboardType
])
5991 NSColor
*c
= [NSColor colorFromPasteboard
: pb
];
5992 emacs_event
->kind
= NS_NONKEY_EVENT
;
5993 emacs_event
->code
= KEY_NS_DRAG_COLOR
;
5994 XSETINT
(emacs_event
->x
, x
);
5995 XSETINT
(emacs_event
->y
, y
);
5996 ns_input_color
= ns_color_to_lisp
(c
);
5997 emacs_event
->modifiers
= EV_MODIFIERS
(theEvent
);
5998 EV_TRAILER
(theEvent
);
6001 else if ([type isEqualToString
: NSFontPboardType
])
6003 /* impl based on GNUstep NSTextView.m */
6004 NSData
*data
= [pb dataForType
: NSFontPboardType
];
6005 NSDictionary
*dict
= [NSUnarchiver unarchiveObjectWithData
: data
];
6006 NSFont
*font
= [dict objectForKey
: NSFontAttributeName
];
6012 emacs_event
->kind
= NS_NONKEY_EVENT
;
6013 emacs_event
->code
= KEY_NS_CHANGE_FONT
;
6014 XSETINT
(emacs_event
->x
, x
);
6015 XSETINT
(emacs_event
->y
, y
);
6016 ns_input_font
= build_string
([[font fontName
] UTF8String
]);
6017 snprintf
(fontSize
, 10, "
%f", [font pointSize]);
6018 ns_input_fontsize
= build_string
(fontSize
);
6019 emacs_event
->modifiers
= EV_MODIFIERS
(theEvent
);
6020 EV_TRAILER
(theEvent
);
6025 error ("Invalid data
type in dragging pasteboard."
);
6031 - (id
) validRequestorForSendType
: (NSString
*)typeSent
6032 returnType
: (NSString
*)typeReturned
6034 NSTRACE
(validRequestorForSendType
);
6035 if (typeSent
!= nil
&& [ns_send_types indexOfObject
: typeSent
] != NSNotFound
6036 && typeReturned
== nil
)
6038 if (! NILP
(ns_get_local_selection
(QPRIMARY
, QUTF8_STRING
)))
6042 return [super validRequestorForSendType
: typeSent
6043 returnType
: typeReturned
];
6047 /* The next two methods are part of NSServicesRequests informal protocol,
6048 supposedly called when a services menu item is chosen from this app.
6049 But this should not happen because we override the services menu with our
6050 own entries which call ns-perform-service.
6051 Nonetheless, it appeared to happen (under strange circumstances): bug#1435.
6052 So let's at least stub them out until further investigation can be done. */
6054 - (BOOL
) readSelectionFromPasteboard
: (NSPasteboard
*)pb
6056 /* we could call ns_string_from_pasteboard(pboard) here but then it should
6057 be written into the buffer in place of the existing selection..
6058 ordinary service calls go through functions defined in ns-win.el */
6062 - (BOOL
) writeSelectionToPasteboard
: (NSPasteboard
*)pb types
: (NSArray
*)types
6064 NSArray
*typesDeclared
;
6067 /* We only support NSStringPboardType */
6068 if ([types containsObject
:NSStringPboardType
] == NO
) {
6072 val
= ns_get_local_selection
(QPRIMARY
, QUTF8_STRING
);
6073 if (CONSP
(val
) && SYMBOLP
(XCAR
(val
)))
6076 if (CONSP
(val
) && NILP
(XCDR
(val
)))
6079 if (! STRINGP
(val
))
6082 typesDeclared
= [NSArray arrayWithObject
:NSStringPboardType
];
6083 [pb declareTypes
:typesDeclared owner
:nil
];
6084 ns_string_to_pasteboard
(pb
, val
);
6089 /* setMini =YES means set from internal (gives a finder icon), NO means set nil
6090 (gives a miniaturized version of the window); currently we use the latter for
6091 frames whose active buffer doesn't correspond to any file
6092 (e.g., '*scratch*') */
6093 - setMiniwindowImage
: (BOOL
) setMini
6095 id
image = [[self window
] miniwindowImage
];
6096 NSTRACE
(setMiniwindowImage
);
6098 /* NOTE: under Cocoa miniwindowImage always returns nil, documentation
6099 about "AppleDockIconEnabled" notwithstanding, however the set message
6100 below has its effect nonetheless. */
6101 if (image != emacsframe
->output_data.ns
->miniimage
)
6103 if (image && [image isKindOfClass
: [EmacsImage
class]])
6105 [[self window
] setMiniwindowImage
:
6106 setMini ? emacsframe
->output_data.ns
->miniimage
: nil
];
6113 - (void
) setRows
: (int
) r andColumns
: (int
) c
6119 @
end /* EmacsView */
6123 /* ==========================================================================
6125 EmacsWindow implementation
6127 ========================================================================== */
6129 @implementation EmacsWindow
6131 #ifdef NS_IMPL_COCOA
6132 - (id
)accessibilityAttributeValue
:(NSString
*)attribute
6134 Lisp_Object str
= Qnil
;
6135 struct frame
*f
= SELECTED_FRAME
();
6136 struct buffer
*curbuf
= XBUFFER
(XWINDOW
(f
->selected_window
)->buffer
);
6138 if ([attribute isEqualToString
:NSAccessibilityRoleAttribute
])
6139 return NSAccessibilityTextFieldRole
;
6141 if ([attribute isEqualToString
:NSAccessibilitySelectedTextAttribute
]
6142 && curbuf
&& ! NILP
(BVAR
(curbuf
, mark_active
)))
6144 str
= ns_get_local_selection
(QPRIMARY
, QUTF8_STRING
);
6146 else if (curbuf
&& [attribute isEqualToString
:NSAccessibilityValueAttribute
])
6148 if (! NILP
(BVAR
(curbuf
, mark_active
)))
6149 str
= ns_get_local_selection
(QPRIMARY
, QUTF8_STRING
);
6153 ptrdiff_t start_byte
= BUF_BEGV_BYTE
(curbuf
);
6154 ptrdiff_t byte_range
= BUF_ZV_BYTE
(curbuf
) - start_byte
;
6155 ptrdiff_t range
= BUF_ZV
(curbuf
) - BUF_BEGV
(curbuf
);
6157 if (! NILP
(BVAR
(curbuf
, enable_multibyte_characters
)))
6158 str
= make_uninit_multibyte_string
(range
, byte_range
);
6160 str
= make_uninit_string
(range
);
6161 /* To check: This returns emacs-utf-8, which is a superset of utf-8.
6162 Is this a problem? */
6163 memcpy
(SDATA
(str
), BYTE_POS_ADDR
(start_byte
), byte_range
);
6170 if (CONSP
(str
) && SYMBOLP
(XCAR
(str
)))
6173 if (CONSP
(str
) && NILP
(XCDR
(str
)))
6178 const
char *utfStr
= SSDATA
(str
);
6179 NSString
*nsStr
= [NSString stringWithUTF8String
: utfStr
];
6184 return [super accessibilityAttributeValue
:attribute
];
6186 #endif
/* NS_IMPL_COCOA */
6188 /* If we have multiple monitors, one above the other, we don't want to
6189 restrict the height to just one monitor. So we override this. */
6190 - (NSRect
)constrainFrameRect
:(NSRect
)frameRect toScreen
:(NSScreen
*)screen
6192 /* When making the frame visible for the first time or if there is just
6193 one screen, we want to constrain. Other times not. */
6194 NSUInteger nr_screens
= [[NSScreen screens
] count
];
6195 struct frame
*f
= ((EmacsView
*)[self delegate
])->emacsframe
;
6196 NSTRACE
(constrainFrameRect
);
6198 if (nr_screens
== 1)
6199 return [super constrainFrameRect
:frameRect toScreen
:screen
];
6201 if (f
->output_data.ns
->dont_constrain
6202 || ns_menu_bar_should_be_hidden
())
6205 f
->output_data.ns
->dont_constrain
= 1;
6206 return [super constrainFrameRect
:frameRect toScreen
:screen
];
6210 /* called only on resize clicks by special case in EmacsApp-sendEvent */
6211 - (void
)mouseDown
: (NSEvent
*)theEvent
6215 NSSize
size = [[theEvent window
] frame
].
size;
6216 grabOffset
= [theEvent locationInWindow
];
6217 grabOffset.x
= size.width
- grabOffset.x
;
6220 [super mouseDown
: theEvent
];
6225 - (void
)mouseUp
: (NSEvent
*)theEvent
6229 struct frame
*f
= ((EmacsView
*)[self delegate
])->emacsframe
;
6231 ns_set_name_as_filename
(f
);
6233 ns_send_appdefined
(-1);
6236 [super mouseUp
: theEvent
];
6240 /* send resize events */
6241 - (void
)mouseDragged
: (NSEvent
*)theEvent
6245 NSPoint p
= [theEvent locationInWindow
];
6246 NSSize
size, vettedSize
, origSize
= [self frame
].
size;
6248 size.width
= p.x
+ grabOffset.x
;
6249 size.height
= origSize.height
- p.y
+ grabOffset.y
;
6251 if (size.width
== origSize.width
&& size.height
== origSize.height
)
6254 vettedSize
= [[self delegate
] windowWillResize
: self toSize
: size];
6255 [[NSNotificationCenter defaultCenter
]
6256 postNotificationName
: NSWindowDidResizeNotification
6260 [super mouseDragged
: theEvent
];
6263 @
end /* EmacsWindow */
6266 /* ==========================================================================
6268 EmacsScroller implementation
6270 ========================================================================== */
6273 @implementation EmacsScroller
6275 /* for repeat button push */
6276 #define SCROLL_BAR_FIRST_DELAY
0.5
6277 #define SCROLL_BAR_CONTINUOUS_DELAY
(1.0 / 15)
6279 + (CGFloat
) scrollerWidth
6281 /* TODO: if we want to allow variable widths, this is the place to do it,
6282 however neither GNUstep nor Cocoa support it very well */
6283 return [NSScroller scrollerWidth
];
6287 - initFrame
: (NSRect
)r window
: (Lisp_Object
)nwin
6289 NSTRACE
(EmacsScroller_initFrame
);
6291 r.
size.width
= [EmacsScroller scrollerWidth
];
6292 [super initWithFrame
: r
/*NSMakeRect (0, 0, 0, 0)*/];
6293 [self setContinuous
: YES
];
6294 [self setEnabled
: YES
];
6296 /* Ensure auto resizing of scrollbars occurs within the emacs frame's view
6297 locked against the top and bottom edges, and right edge on OS X, where
6298 scrollers are on right. */
6299 #ifdef NS_IMPL_GNUSTEP
6300 [self setAutoresizingMask
: NSViewMaxXMargin | NSViewHeightSizable
];
6302 [self setAutoresizingMask
: NSViewMinXMargin | NSViewHeightSizable
];
6307 pixel_height
= NSHeight
(r
);
6308 if (pixel_height
== 0) pixel_height
= 1;
6309 min_portion
= 20 / pixel_height
;
6311 frame
= XFRAME
(XWINDOW
(win
)->frame
);
6312 if (FRAME_LIVE_P
(frame
))
6315 EmacsView
*view = FRAME_NS_VIEW
(frame
);
6316 NSView
*sview
= [[view window
] contentView
];
6317 NSArray
*subs
= [sview subviews
];
6319 /* disable optimization stopping redraw of other scrollbars */
6320 view->scrollbarsNeedingUpdate
= 0;
6321 for (i
=[subs count
]-1; i
>= 0; i
--)
6322 if ([[subs objectAtIndex
: i
] isKindOfClass
: [EmacsScroller
class]])
6323 view->scrollbarsNeedingUpdate
++;
6324 [sview addSubview
: self
];
6327 /* [self setFrame: r]; */
6333 - (void
)setFrame
: (NSRect
)newRect
6335 NSTRACE
(EmacsScroller_setFrame
);
6337 pixel_height
= NSHeight
(newRect
);
6338 if (pixel_height
== 0) pixel_height
= 1;
6339 min_portion
= 20 / pixel_height
;
6340 [super setFrame
: newRect
];
6342 /* UNBLOCK_INPUT; */
6348 NSTRACE
(EmacsScroller_dealloc
);
6350 wset_vertical_scroll_bar
(XWINDOW
(win
), Qnil
);
6378 /* ensure other scrollbar updates after deletion */
6379 view = (EmacsView
*)FRAME_NS_VIEW
(frame
);
6381 view->scrollbarsNeedingUpdate
++;
6382 [self removeFromSuperview
];
6390 - (void
)resetCursorRects
6392 NSRect visible
= [self visibleRect
];
6393 NSTRACE
(resetCursorRects
);
6395 if (!NSIsEmptyRect
(visible
))
6396 [self addCursorRect
: visible cursor
: [NSCursor arrowCursor
]];
6397 [[NSCursor arrowCursor
] setOnMouseEntered
: YES
];
6401 - (int
) checkSamePosition
: (int
) position portion
: (int
) portion
6404 return em_position
==position
&& em_portion
==portion
&& em_whole
==whole
6405 && portion
!= whole
; /* needed for resize empty buf */
6409 - setPosition
: (int
)position portion
: (int
)portion whole
: (int
)whole
6411 NSTRACE
(setPosition
);
6413 em_position
= position
;
6414 em_portion
= portion
;
6417 if (portion
>= whole
)
6419 #
if defined
(NS_IMPL_COCOA
) && MAC_OS_X_VERSION_MAX_ALLOWED
> MAC_OS_X_VERSION_10_5
6420 [self setKnobProportion
: 1.0];
6421 [self setDoubleValue
: 1.0];
6423 [self setFloatValue
: 0.0 knobProportion
: 1.0];
6429 portion
= max ((float
)whole
*min_portion
/pixel_height
, portion
);
6430 pos
= (float
)position
/ (whole
- portion
);
6431 por
= (float
)portion
/whole
;
6432 #
if defined
(NS_IMPL_COCOA
) && MAC_OS_X_VERSION_MAX_ALLOWED
> MAC_OS_X_VERSION_10_5
6433 [self setKnobProportion
: por
];
6434 [self setDoubleValue
: pos
];
6436 [self setFloatValue
: pos knobProportion
: por
];
6442 /* FIXME: unused at moment (see ns_mouse_position) at the moment because
6443 drag events will go directly to the EmacsScroller. Leaving in for now. */
6444 -(void
)getMouseMotionPart
: (int
*)part window
: (Lisp_Object
*)window
6445 x
: (Lisp_Object
*)x y
: ( Lisp_Object
*)y
6447 *part
= last_hit_part
;
6449 XSETINT
(*y
, pixel_height
);
6450 if ([self floatValue
] > 0.999)
6451 XSETINT
(*x
, pixel_height
);
6453 XSETINT
(*x
, pixel_height
* [self floatValue
]);
6457 /* set up emacs_event */
6458 - (void
) sendScrollEventAtLoc
: (float
)loc fromEvent
: (NSEvent
*)e
6463 emacs_event
->part
= last_hit_part
;
6464 emacs_event
->code
= 0;
6465 emacs_event
->modifiers
= EV_MODIFIERS
(e
) | down_modifier
;
6466 emacs_event
->frame_or_window
= win
;
6467 emacs_event
->timestamp
= EV_TIMESTAMP
(e
);
6468 emacs_event
->kind
= SCROLL_BAR_CLICK_EVENT
;
6469 emacs_event
->arg
= Qnil
;
6470 XSETINT
(emacs_event
->x
, loc
* pixel_height
);
6471 XSETINT
(emacs_event
->y
, pixel_height
-20);
6475 n_emacs_events_pending
++;
6476 kbd_buffer_store_event_hold
(emacs_event
, q_event_ptr
);
6479 kbd_buffer_store_event
(emacs_event
);
6480 EVENT_INIT
(*emacs_event
);
6481 ns_send_appdefined
(-1);
6485 /* called manually thru timer to implement repeated button action w/hold-down */
6486 - repeatScroll
: (NSTimer
*)scrollEntry
6488 NSEvent
*e
= [[self window
] currentEvent
];
6489 NSPoint p
= [[self window
] mouseLocationOutsideOfEventStream
];
6490 BOOL inKnob
= [self testPart
: p
] == NSScrollerKnob
;
6492 /* clear timer if need be */
6493 if (inKnob ||
[scroll_repeat_entry timeInterval
] == SCROLL_BAR_FIRST_DELAY
)
6495 [scroll_repeat_entry invalidate
];
6496 [scroll_repeat_entry release
];
6497 scroll_repeat_entry
= nil
;
6503 = [[NSTimer scheduledTimerWithTimeInterval
:
6504 SCROLL_BAR_CONTINUOUS_DELAY
6506 selector
: @selector
(repeatScroll
:)
6512 [self sendScrollEventAtLoc
: 0 fromEvent
: e
];
6517 /* Asynchronous mouse tracking for scroller. This allows us to dispatch
6518 mouseDragged events without going into a modal loop. */
6519 - (void
)mouseDown
: (NSEvent
*)e
6522 /* hitPart is only updated AFTER event is passed on */
6523 NSScrollerPart part
= [self testPart
: [e locationInWindow
]];
6524 double inc
= 0.0, loc
, kloc
, pos
;
6527 NSTRACE
(EmacsScroller_mouseDown
);
6531 case NSScrollerDecrementPage
:
6532 last_hit_part
= scroll_bar_above_handle
; inc
= -1.0; break;
6533 case NSScrollerIncrementPage
:
6534 last_hit_part
= scroll_bar_below_handle
; inc
= 1.0; break;
6535 case NSScrollerDecrementLine
:
6536 last_hit_part
= scroll_bar_up_arrow
; inc
= -0.1; break;
6537 case NSScrollerIncrementLine
:
6538 last_hit_part
= scroll_bar_down_arrow
; inc
= 0.1; break;
6539 case NSScrollerKnob
:
6540 last_hit_part
= scroll_bar_handle
; break;
6541 case NSScrollerKnobSlot
: /* GNUstep-only */
6542 last_hit_part
= scroll_bar_move_ratio
; break;
6543 default
: /* NSScrollerNoPart? */
6544 fprintf (stderr
, "EmacsScoller
-mouseDown
: unexpected part
%ld\n",
6551 pos
= 0; /* ignored */
6553 /* set a timer to repeat, as we can't let superclass do this modally */
6555 = [[NSTimer scheduledTimerWithTimeInterval
: SCROLL_BAR_FIRST_DELAY
6557 selector
: @selector
(repeatScroll
:)
6564 /* handle, or on GNUstep possibly slot */
6565 NSEvent
*fake_event
;
6567 /* compute float loc in slot and mouse offset on knob */
6568 sr
= [self convertRect
: [self rectForPart
: NSScrollerKnobSlot
]
6570 loc
= NSHeight
(sr
) - ([e locationInWindow
].y
- NSMinY
(sr
));
6576 else if (loc
>= NSHeight
(sr
))
6578 loc
= NSHeight
(sr
);
6586 kr
= [self convertRect
: [self rectForPart
: NSScrollerKnob
]
6588 kloc
= NSHeight
(kr
) - ([e locationInWindow
].y
- NSMinY
(kr
));
6590 last_mouse_offset
= kloc
;
6592 /* if knob, tell emacs a location offset by knob pos
6593 (to indicate top of handle) */
6594 if (part
== NSScrollerKnob
)
6595 pos
= (loc
- last_mouse_offset
) / NSHeight
(sr
);
6597 /* else this is a slot click on GNUstep: go straight there */
6598 pos
= loc
/ NSHeight
(sr
);
6600 /* send a fake mouse-up to super to preempt modal -trackKnob: mode */
6601 fake_event
= [NSEvent mouseEventWithType
: NSLeftMouseUp
6602 location
: [e locationInWindow
]
6603 modifierFlags
: [e modifierFlags
]
6604 timestamp
: [e timestamp
]
6605 windowNumber
: [e windowNumber
]
6606 context
: [e context
]
6607 eventNumber
: [e eventNumber
]
6608 clickCount
: [e clickCount
]
6609 pressure
: [e pressure
]];
6610 [super mouseUp
: fake_event
];
6613 if (part
!= NSScrollerKnob
)
6614 [self sendScrollEventAtLoc
: pos fromEvent
: e
];
6618 /* Called as we manually track scroller drags, rather than superclass. */
6619 - (void
)mouseDragged
: (NSEvent
*)e
6625 NSTRACE
(EmacsScroller_mouseDragged
);
6627 sr
= [self convertRect
: [self rectForPart
: NSScrollerKnobSlot
]
6629 loc
= NSHeight
(sr
) - ([e locationInWindow
].y
- NSMinY
(sr
));
6636 else if (loc
>= NSHeight
(sr
) + last_mouse_offset
)
6638 loc
= NSHeight
(sr
) + last_mouse_offset
;
6642 pos
= /*(edge ? loc :*/ (loc
- last_mouse_offset
) / NSHeight
(sr
);
6643 [self sendScrollEventAtLoc
: pos fromEvent
: e
];
6647 - (void
)mouseUp
: (NSEvent
*)e
6649 if (scroll_repeat_entry
)
6651 [scroll_repeat_entry invalidate
];
6652 [scroll_repeat_entry release
];
6653 scroll_repeat_entry
= nil
;
6659 /* treat scrollwheel events in the bar as though they were in the main window */
6660 - (void
) scrollWheel
: (NSEvent
*)theEvent
6662 EmacsView
*view = (EmacsView
*)FRAME_NS_VIEW
(frame
);
6663 [view mouseDown
: theEvent
];
6666 @
end /* EmacsScroller */
6671 /* ==========================================================================
6673 Font-related functions; these used to be in nsfaces.m
6675 ========================================================================== */
6679 x_new_font
(struct frame
*f
, Lisp_Object font_object
, int fontset
)
6681 struct font
*font
= XFONT_OBJECT
(font_object
);
6684 fontset
= fontset_from_font
(font_object
);
6685 FRAME_FONTSET
(f
) = fontset
;
6687 if (FRAME_FONT
(f
) == font
)
6688 /* This font is already set in frame F. There's nothing more to
6692 FRAME_FONT
(f
) = font
;
6694 FRAME_BASELINE_OFFSET
(f
) = font
->baseline_offset
;
6695 FRAME_COLUMN_WIDTH
(f
) = font
->average_width
;
6696 FRAME_SPACE_WIDTH
(f
) = font
->space_width
;
6697 FRAME_LINE_HEIGHT
(f
) = font
->height
;
6699 compute_fringe_widths
(f
, 1);
6701 /* Compute the scroll bar width in character columns. */
6702 if (FRAME_CONFIG_SCROLL_BAR_WIDTH
(f
) > 0)
6704 int wid
= FRAME_COLUMN_WIDTH
(f
);
6705 FRAME_CONFIG_SCROLL_BAR_COLS
(f
)
6706 = (FRAME_CONFIG_SCROLL_BAR_WIDTH
(f
) + wid
- 1) / wid
;
6710 int wid
= FRAME_COLUMN_WIDTH
(f
);
6711 FRAME_CONFIG_SCROLL_BAR_COLS
(f
) = (14 + wid
- 1) / wid
;
6714 /* Now make the frame display the given font. */
6715 if (FRAME_NS_WINDOW
(f
) != 0)
6716 x_set_window_size
(f
, 0, FRAME_COLS
(f
), FRAME_LINES
(f
));
6722 /* XLFD: -foundry-family-weight-slant-swidth-adstyle-pxlsz-ptSz-resx-resy-spc-avgWidth-rgstry-encoding */
6723 /* Note: ns_font_to_xlfd and ns_fontname_to_xlfd no longer needed, removed
6727 ns_xlfd_to_fontname
(const
char *xlfd
)
6728 /* --------------------------------------------------------------------------
6729 Convert an X font name (XLFD) to an NS font name.
6730 Only family is used.
6731 The string returned is temporarily allocated.
6732 -------------------------------------------------------------------------- */
6734 char *name
= xmalloc
(180);
6738 if (!strncmp
(xlfd
, "
--"
, 2))
6739 sscanf (xlfd
, "
--%*[^-]-%[^-]179-", name);
6741 sscanf (xlfd
, "
-%*[^-]-%[^-]179-", name);
6743 /* stopgap for malformed XLFD input */
6744 if (strlen
(name
) == 0)
6745 strcpy
(name
, "Monaco"
);
6747 /* undo hack in ns_fontname_to_xlfd, converting '$' to '-', '_' to ' '
6748 also uppercase after '-' or ' ' */
6749 name
[0] = c_toupper
(name
[0]);
6750 for (len
=strlen
(name
), i
=0; i
<len
; i
++)
6756 name
[i
+1] = c_toupper
(name
[i
+1]);
6758 else if (name
[i
] == '_')
6762 name
[i
+1] = c_toupper
(name
[i
+1]);
6765 /*fprintf (stderr, "converted '%s' to '%s'\n",xlfd,name); */
6766 ret
= [[NSString stringWithUTF8String
: name
] UTF8String
];
6773 syms_of_nsterm
(void
)
6775 NSTRACE
(syms_of_nsterm
);
6777 ns_antialias_threshold
= 10.0;
6779 /* from 23+ we need to tell emacs what modifiers there are.. */
6780 DEFSYM
(Qmodifier_value
, "modifier
-value"
);
6781 DEFSYM
(Qalt
, "alt"
);
6782 DEFSYM
(Qhyper
, "hyper"
);
6783 DEFSYM
(Qmeta
, "
meta"
);
6784 DEFSYM
(Qsuper
, "super"
);
6785 DEFSYM
(Qcontrol
, "control"
);
6786 DEFSYM
(QUTF8_STRING
, "UTF8_STRING"
);
6788 Fput
(Qalt
, Qmodifier_value
, make_number
(alt_modifier
));
6789 Fput
(Qhyper
, Qmodifier_value
, make_number
(hyper_modifier
));
6790 Fput
(Qmeta
, Qmodifier_value
, make_number
(meta_modifier
));
6791 Fput
(Qsuper
, Qmodifier_value
, make_number
(super_modifier
));
6792 Fput
(Qcontrol
, Qmodifier_value
, make_number
(ctrl_modifier
));
6794 DEFVAR_LISP
("ns
-input-file"
, ns_input_file
,
6795 "The file specified in the last NS event."
);
6796 ns_input_file
=Qnil
;
6798 DEFVAR_LISP
("ns
-input-text"
, ns_input_text
,
6799 "The data received in the last NS
text drag event."
);
6800 ns_input_text
=Qnil
;
6802 DEFVAR_LISP
("ns
-working
-text"
, ns_working_text
,
6803 "String
for visualizing working composition sequence."
);
6804 ns_working_text
=Qnil
;
6806 DEFVAR_LISP
("ns
-input-font"
, ns_input_font
,
6807 "The font specified in the last NS event."
);
6808 ns_input_font
=Qnil
;
6810 DEFVAR_LISP
("ns
-input-fontsize"
, ns_input_fontsize
,
6811 "The fontsize specified in the last NS event."
);
6812 ns_input_fontsize
=Qnil
;
6814 DEFVAR_LISP
("ns
-input-line"
, ns_input_line
,
6815 "The
line specified in the last NS event."
);
6816 ns_input_line
=Qnil
;
6818 DEFVAR_LISP
("ns
-input-color"
, ns_input_color
,
6819 "The color specified in the last NS event."
);
6820 ns_input_color
=Qnil
;
6822 DEFVAR_LISP
("ns
-input-spi
-name"
, ns_input_spi_name
,
6823 "The service name specified in the last NS event."
);
6824 ns_input_spi_name
=Qnil
;
6826 DEFVAR_LISP
("ns
-input-spi
-arg"
, ns_input_spi_arg
,
6827 "The service argument specified in the last NS event."
);
6828 ns_input_spi_arg
=Qnil
;
6830 DEFVAR_LISP
("ns
-alternate
-modifier"
, ns_alternate_modifier
,
6831 "This variable describes the behavior of the alternate or option key.
\n\
6832 Set to control
, meta, alt
, super
, or hyper means it is taken to be that key.
\n\
6833 Set to none means that the alternate
/ option key is not interpreted by Emacs
\n\
6834 at
all, allowing it to be used at a
lower level
for accented character entry."
);
6835 ns_alternate_modifier
= Qmeta
;
6837 DEFVAR_LISP
("ns
-right
-alternate
-modifier"
, ns_right_alternate_modifier
,
6838 "This variable describes the behavior of the right alternate or option key.
\n\
6839 Set to control
, meta, alt
, super
, or hyper means it is taken to be that key.
\n\
6840 Set to left means be the same key as `ns
-alternate
-modifier
'.\n\
6841 Set to none means that the alternate / option key is not interpreted by Emacs\n\
6842 at all, allowing it to be used at a lower level for accented character entry.");
6843 ns_right_alternate_modifier = Qleft;
6845 DEFVAR_LISP ("ns-command-modifier", ns_command_modifier,
6846 "This variable describes the behavior of the command key.\n\
6847 Set to control, meta, alt, super, or hyper means it is taken to be that key.");
6848 ns_command_modifier = Qsuper;
6850 DEFVAR_LISP ("ns-right-command-modifier", ns_right_command_modifier,
6851 "This variable describes the behavior of the right command key.\n\
6852 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
6853 Set to left means be the same key as `ns-command-modifier'.
\n\
6854 Set to none means that the command
/ option key is not interpreted by Emacs
\n\
6855 at
all, allowing it to be used at a
lower level
for accented character entry."
);
6856 ns_right_command_modifier
= Qleft
;
6858 DEFVAR_LISP
("ns
-control
-modifier"
, ns_control_modifier
,
6859 "This variable describes the behavior of the control key.
\n\
6860 Set to control
, meta, alt
, super
, or hyper means it is taken to be that key."
);
6861 ns_control_modifier
= Qcontrol
;
6863 DEFVAR_LISP
("ns
-right
-control
-modifier"
, ns_right_control_modifier
,
6864 "This variable describes the behavior of the right control key.
\n\
6865 Set to control
, meta, alt
, super
, or hyper means it is taken to be that key.
\n\
6866 Set to left means be the same key as `ns
-control
-modifier
'.\n\
6867 Set to none means that the control / option key is not interpreted by Emacs\n\
6868 at all, allowing it to be used at a lower level for accented character entry.");
6869 ns_right_control_modifier = Qleft;
6871 DEFVAR_LISP ("ns-function-modifier", ns_function_modifier,
6872 "This variable describes the behavior of the function key (on laptops).\n\
6873 Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
6874 Set to none means that the function key is not interpreted by Emacs at all,\n\
6875 allowing it to be used at a lower level for accented character entry.");
6876 ns_function_modifier = Qnone;
6878 DEFVAR_LISP ("ns-antialias-text", ns_antialias_text,
6879 "Non-nil (the default) means to render text antialiased. Only has an effect on OS X Panther and above.");
6880 ns_antialias_text = Qt;
6882 DEFVAR_LISP ("ns-confirm-quit", ns_confirm_quit,
6883 "Whether to confirm application quit using dialog.");
6884 ns_confirm_quit = Qnil;
6886 staticpro (&ns_display_name_list);
6887 ns_display_name_list = Qnil;
6889 staticpro (&last_mouse_motion_frame);
6890 last_mouse_motion_frame = Qnil;
6892 DEFVAR_LISP ("ns-auto-hide-menu-bar", ns_auto_hide_menu_bar,
6893 doc: /* Non-nil means that the menu bar is hidden, but appears when the mouse is near.
6894 Only works on OSX 10.6 or later. */);
6895 ns_auto_hide_menu_bar = Qnil;
6897 /* TODO: move to common code */
6898 DEFVAR_LISP ("x-toolkit-scroll-bars", Vx_toolkit_scroll_bars,
6899 doc: /* Which toolkit scroll bars Emacs uses, if any.
6900 A value of nil means Emacs doesn't use toolkit scroll bars.
6901 With the X Window system
, the value is a symbol describing the
6902 X toolkit. Possible values are
: gtk
, motif
, xaw
, or xaw3d.
6903 With MS Windows or Nextstep
, the value is t. */
);
6904 Vx_toolkit_scroll_bars
= Qt
;
6906 DEFVAR_BOOL
("x
-use
-underline
-position
-properties"
,
6907 x_use_underline_position_properties
,
6908 doc: /*Non-nil means make use of UNDERLINE_POSITION font properties.
6909 A value of nil means ignore them. If you encounter fonts with bogus
6910 UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
6911 to 4.1, set this to nil. */);
6912 x_use_underline_position_properties
= 0;
6914 DEFVAR_BOOL
("x
-underline
-at
-descent
-line"
,
6915 x_underline_at_descent_line
,
6916 doc: /* Non-nil means to draw the underline at the same place as the descent line.
6917 A value of nil means to draw the underline according to the value of the
6918 variable `x-use-underline-position-properties', which is usually at the
6919 baseline level. The default value is nil. */);
6920 x_underline_at_descent_line
= 0;
6922 /* Tell emacs about this window system. */
6923 Fprovide
(intern
("ns"
), Qnil
);