Backport: Document the release process
[emacs.git] / src / nsfns.m
blob434fd6aa944fcb0d97af386e23bede40b4b6fc34
1 /* Functions for the NeXT/Open/GNUstep and MacOSX window system.
3 Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2015 Free Software
4 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. */
31 #include <config.h>
33 #include <math.h>
34 #include <c-strcase.h>
36 #include "lisp.h"
37 #include "blockinput.h"
38 #include "nsterm.h"
39 #include "window.h"
40 #include "character.h"
41 #include "buffer.h"
42 #include "keyboard.h"
43 #include "termhooks.h"
44 #include "fontset.h"
45 #include "font.h"
47 #ifdef NS_IMPL_COCOA
48 #include <IOKit/graphics/IOGraphicsLib.h>
49 #include "macfont.h"
50 #endif
53 #ifdef HAVE_NS
55 extern NSArray *ns_send_types, *ns_return_types, *ns_drag_types;
57 EmacsTooltip *ns_tooltip = nil;
59 /* Need forward declaration here to preserve organizational integrity of file */
60 Lisp_Object Fx_open_connection (Lisp_Object, Lisp_Object, Lisp_Object);
62 /* Static variables to handle applescript execution.  */
63 static Lisp_Object as_script, *as_result;
64 static int as_status;
66 static ptrdiff_t image_cache_refcount;
69 /* ==========================================================================
71     Internal utility functions
73    ========================================================================== */
75 /* Let the user specify a Nextstep display with a Lisp object.
76    OBJECT may be nil, a frame or a terminal object.
77    nil stands for the selected frame--or, if that is not a Nextstep frame,
78    the first Nextstep display on the list.  */
80 static struct ns_display_info *
81 check_ns_display_info (Lisp_Object object)
83   struct ns_display_info *dpyinfo = NULL;
85   if (NILP (object))
86     {
87       struct frame *sf = XFRAME (selected_frame);
89       if (FRAME_NS_P (sf) && FRAME_LIVE_P (sf))
90         dpyinfo = FRAME_DISPLAY_INFO (sf);
91       else if (x_display_list != 0)
92         dpyinfo = x_display_list;
93       else
94         error ("Nextstep windows are not in use or not initialized");
95     }
96   else if (TERMINALP (object))
97     {
98       struct terminal *t = decode_live_terminal (object);
100       if (t->type != output_ns)
101         error ("Terminal %d is not a Nextstep display", t->id);
103       dpyinfo = t->display_info.ns;
104     }
105   else if (STRINGP (object))
106     dpyinfo = ns_display_info_for_name (object);
107   else
108     {
109       struct frame *f = decode_window_system_frame (object);
110       dpyinfo = FRAME_DISPLAY_INFO (f);
111     }
113   return dpyinfo;
117 static id
118 ns_get_window (Lisp_Object maybeFrame)
120   id view =nil, window =nil;
122   if (!FRAMEP (maybeFrame) || !FRAME_NS_P (XFRAME (maybeFrame)))
123     maybeFrame = selected_frame;/*wrong_type_argument (Qframep, maybeFrame); */
125   if (!NILP (maybeFrame))
126     view = FRAME_NS_VIEW (XFRAME (maybeFrame));
127   if (view) window =[view window];
129   return window;
133 /* Return the X display structure for the display named NAME.
134    Open a new connection if necessary.  */
135 struct ns_display_info *
136 ns_display_info_for_name (Lisp_Object name)
138   struct ns_display_info *dpyinfo;
140   CHECK_STRING (name);
142   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
143     if (!NILP (Fstring_equal (XCAR (dpyinfo->name_list_element), name)))
144       return dpyinfo;
146   error ("Emacs for Nextstep does not yet support multi-display");
148   Fx_open_connection (name, Qnil, Qnil);
149   dpyinfo = x_display_list;
151   if (dpyinfo == 0)
152     error ("Display on %s not responding.\n", SDATA (name));
154   return dpyinfo;
157 static NSString *
158 ns_filename_from_panel (NSSavePanel *panel)
160 #ifdef NS_IMPL_COCOA
161   NSURL *url = [panel URL];
162   NSString *str = [url path];
163   return str;
164 #else
165   return [panel filename];
166 #endif
169 static NSString *
170 ns_directory_from_panel (NSSavePanel *panel)
172 #ifdef NS_IMPL_COCOA
173   NSURL *url = [panel directoryURL];
174   NSString *str = [url path];
175   return str;
176 #else
177   return [panel directory];
178 #endif
181 static Lisp_Object
182 interpret_services_menu (NSMenu *menu, Lisp_Object prefix, Lisp_Object old)
183 /* --------------------------------------------------------------------------
184    Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side
185    -------------------------------------------------------------------------- */
187   int i, count;
188   NSMenuItem *item;
189   const char *name;
190   Lisp_Object nameStr;
191   unsigned short key;
192   NSString *keys;
193   Lisp_Object res;
195   count = [menu numberOfItems];
196   for (i = 0; i<count; i++)
197     {
198       item = [menu itemAtIndex: i];
199       name = [[item title] UTF8String];
200       if (!name) continue;
202       nameStr = build_string (name);
204       if ([item hasSubmenu])
205         {
206           old = interpret_services_menu ([item submenu],
207                                         Fcons (nameStr, prefix), old);
208         }
209       else
210         {
211           keys = [item keyEquivalent];
212           if (keys && [keys length] )
213             {
214               key = [keys characterAtIndex: 0];
215               res = make_number (key|super_modifier);
216             }
217           else
218             {
219               res = Qundefined;
220             }
221           old = Fcons (Fcons (res,
222                             Freverse (Fcons (nameStr,
223                                            prefix))),
224                     old);
225         }
226     }
227   return old;
232 /* ==========================================================================
234     Frame parameter setters
236    ========================================================================== */
239 static void
240 x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
242   NSColor *col;
243   EmacsCGFloat r, g, b, alpha;
245   /* Must block_input, because ns_lisp_to_color does block/unblock_input
246      which means that col may be deallocated in its unblock_input if there
247      is user input, unless we also block_input.  */
248   block_input ();
249   if (ns_lisp_to_color (arg, &col))
250     {
251       store_frame_param (f, Qforeground_color, oldval);
252       unblock_input ();
253       error ("Unknown color");
254     }
256   [col retain];
257   [f->output_data.ns->foreground_color release];
258   f->output_data.ns->foreground_color = col;
260   [col getRed: &r green: &g blue: &b alpha: &alpha];
261   FRAME_FOREGROUND_PIXEL (f) =
262     ARGB_TO_ULONG ((int)(alpha*0xff), (int)(r*0xff), (int)(g*0xff), (int)(b*0xff));
264   if (FRAME_NS_VIEW (f))
265     {
266       update_face_from_frame_parameter (f, Qforeground_color, arg);
267       /*recompute_basic_faces (f); */
268       if (FRAME_VISIBLE_P (f))
269         SET_FRAME_GARBAGED (f);
270     }
271   unblock_input ();
275 static void
276 x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
278   struct face *face;
279   NSColor *col;
280   NSView *view = FRAME_NS_VIEW (f);
281   EmacsCGFloat r, g, b, alpha;
283   block_input ();
284   if (ns_lisp_to_color (arg, &col))
285     {
286       store_frame_param (f, Qbackground_color, oldval);
287       unblock_input ();
288       error ("Unknown color");
289     }
291   /* clear the frame; in some instances the NS-internal GC appears not to
292      update, or it does update and cannot clear old text properly */
293   if (FRAME_VISIBLE_P (f))
294     ns_clear_frame (f);
296   [col retain];
297   [f->output_data.ns->background_color release];
298   f->output_data.ns->background_color = col;
300   [col getRed: &r green: &g blue: &b alpha: &alpha];
301   FRAME_BACKGROUND_PIXEL (f) =
302     ARGB_TO_ULONG ((int)(alpha*0xff), (int)(r*0xff), (int)(g*0xff), (int)(b*0xff));
304   if (view != nil)
305     {
306       [[view window] setBackgroundColor: col];
308       if (alpha != (EmacsCGFloat) 1.0)
309           [[view window] setOpaque: NO];
310       else
311           [[view window] setOpaque: YES];
313       face = FRAME_DEFAULT_FACE (f);
314       if (face)
315         {
316           col = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f);
317           face->background = ns_index_color
318             ([col colorWithAlphaComponent: alpha], f);
320           update_face_from_frame_parameter (f, Qbackground_color, arg);
321         }
323       if (FRAME_VISIBLE_P (f))
324         SET_FRAME_GARBAGED (f);
325     }
326   unblock_input ();
330 static void
331 x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
333   NSColor *col;
335   block_input ();
336   if (ns_lisp_to_color (arg, &col))
337     {
338       store_frame_param (f, Qcursor_color, oldval);
339       unblock_input ();
340       error ("Unknown color");
341     }
343   [FRAME_CURSOR_COLOR (f) release];
344   FRAME_CURSOR_COLOR (f) = [col retain];
346   if (FRAME_VISIBLE_P (f))
347     {
348       x_update_cursor (f, 0);
349       x_update_cursor (f, 1);
350     }
351   update_face_from_frame_parameter (f, Qcursor_color, arg);
352   unblock_input ();
356 static void
357 x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
359   NSView *view = FRAME_NS_VIEW (f);
360   NSTRACE ("x_set_icon_name");
362   /* see if it's changed */
363   if (STRINGP (arg))
364     {
365       if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
366         return;
367     }
368   else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
369     return;
371   fset_icon_name (f, arg);
373   if (NILP (arg))
374     {
375       if (!NILP (f->title))
376         arg = f->title;
377       else
378         /* Explicit name and no icon-name -> explicit_name.  */
379         if (f->explicit_name)
380           arg = f->name;
381         else
382           {
383             /* No explicit name and no icon-name ->
384                name has to be rebuild from icon_title_format.  */
385             windows_or_buffers_changed = 62;
386             return;
387           }
388     }
390   /* Don't change the name if it's already NAME.  */
391   if ([[view window] miniwindowTitle]
392       && ([[[view window] miniwindowTitle]
393              isEqualToString: [NSString stringWithUTF8String:
394                                           SSDATA (arg)]]))
395     return;
397   [[view window] setMiniwindowTitle:
398         [NSString stringWithUTF8String: SSDATA (arg)]];
401 static void
402 ns_set_name_internal (struct frame *f, Lisp_Object name)
404   Lisp_Object encoded_name, encoded_icon_name;
405   NSString *str;
406   NSView *view = FRAME_NS_VIEW (f);
408   encoded_name = ENCODE_UTF_8 (name);
410   str = [NSString stringWithUTF8String: SSDATA (encoded_name)];
412   /* Don't change the name if it's already NAME.  */
413   if (! [[[view window] title] isEqualToString: str])
414     [[view window] setTitle: str];
416   if (!STRINGP (f->icon_name))
417     encoded_icon_name = encoded_name;
418   else
419     encoded_icon_name = ENCODE_UTF_8 (f->icon_name);
421   str = [NSString stringWithUTF8String: SSDATA (encoded_icon_name)];
423   if ([[view window] miniwindowTitle]
424       && ! [[[view window] miniwindowTitle] isEqualToString: str])
425     [[view window] setMiniwindowTitle: str];
429 static void
430 ns_set_name (struct frame *f, Lisp_Object name, int explicit)
432   NSTRACE ("ns_set_name");
434   /* Make sure that requests from lisp code override requests from
435      Emacs redisplay code.  */
436   if (explicit)
437     {
438       /* If we're switching from explicit to implicit, we had better
439          update the mode lines and thereby update the title.  */
440       if (f->explicit_name && NILP (name))
441         update_mode_lines = 21;
443       f->explicit_name = ! NILP (name);
444     }
445   else if (f->explicit_name)
446     return;
448   if (NILP (name))
449     name = build_string ([ns_app_name UTF8String]);
450   else
451     CHECK_STRING (name);
453   /* Don't change the name if it's already NAME.  */
454   if (! NILP (Fstring_equal (name, f->name)))
455     return;
457   fset_name (f, name);
459   /* Title overrides explicit name.  */
460   if (! NILP (f->title))
461     name = f->title;
463   ns_set_name_internal (f, name);
467 /* This function should be called when the user's lisp code has
468    specified a name for the frame; the name will override any set by the
469    redisplay code.  */
470 static void
471 x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
473   NSTRACE ("x_explicitly_set_name");
474   ns_set_name (f, arg, 1);
478 /* This function should be called by Emacs redisplay code to set the
479    name; names set this way will never override names set by the user's
480    lisp code.  */
481 void
482 x_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
484   NSTRACE ("x_implicitly_set_name");
486   /* Deal with NS specific format t.  */
487   if (FRAME_NS_P (f) && ((FRAME_ICONIFIED_P (f) && EQ (Vicon_title_format, Qt))
488                          || EQ (Vframe_title_format, Qt)))
489     ns_set_name_as_filename (f);
490   else
491     ns_set_name (f, arg, 0);
495 /* Change the title of frame F to NAME.
496    If NAME is nil, use the frame name as the title.  */
498 static void
499 x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
501   NSTRACE ("x_set_title");
502   /* Don't change the title if it's already NAME.  */
503   if (EQ (name, f->title))
504     return;
506   update_mode_lines = 22;
508   fset_title (f, name);
510   if (NILP (name))
511     name = f->name;
512   else
513     CHECK_STRING (name);
515   ns_set_name_internal (f, name);
519 void
520 ns_set_name_as_filename (struct frame *f)
522   NSView *view;
523   Lisp_Object name, filename;
524   Lisp_Object buf = XWINDOW (f->selected_window)->contents;
525   const char *title;
526   NSAutoreleasePool *pool;
527   Lisp_Object encoded_name, encoded_filename;
528   NSString *str;
529   NSTRACE ("ns_set_name_as_filename");
531   if (f->explicit_name || ! NILP (f->title))
532     return;
534   block_input ();
535   pool = [[NSAutoreleasePool alloc] init];
536   filename = BVAR (XBUFFER (buf), filename);
537   name = BVAR (XBUFFER (buf), name);
539   if (NILP (name))
540     {
541       if (! NILP (filename))
542         name = Ffile_name_nondirectory (filename);
543       else
544         name = build_string ([ns_app_name UTF8String]);
545     }
547   encoded_name = ENCODE_UTF_8 (name);
549   view = FRAME_NS_VIEW (f);
551   title = FRAME_ICONIFIED_P (f) ? [[[view window] miniwindowTitle] UTF8String]
552                                 : [[[view window] title] UTF8String];
554   if (title && (! strcmp (title, SSDATA (encoded_name))))
555     {
556       [pool release];
557       unblock_input ();
558       return;
559     }
561   str = [NSString stringWithUTF8String: SSDATA (encoded_name)];
562   if (str == nil) str = @"Bad coding";
564   if (FRAME_ICONIFIED_P (f))
565     [[view window] setMiniwindowTitle: str];
566   else
567     {
568       NSString *fstr;
570       if (! NILP (filename))
571         {
572           encoded_filename = ENCODE_UTF_8 (filename);
574           fstr = [NSString stringWithUTF8String: SSDATA (encoded_filename)];
575           if (fstr == nil) fstr = @"";
576         }
577       else
578         fstr = @"";
580       ns_set_represented_filename (fstr, f);
581       [[view window] setTitle: str];
582       fset_name (f, name);
583     }
585   [pool release];
586   unblock_input ();
590 void
591 ns_set_doc_edited (void)
593   NSAutoreleasePool *pool;
594   Lisp_Object tail, frame;
595   block_input ();
596   pool = [[NSAutoreleasePool alloc] init];
597   FOR_EACH_FRAME (tail, frame)
598     {
599       BOOL edited = NO;
600       struct frame *f = XFRAME (frame);
601       struct window *w;
602       NSView *view;
604       if (! FRAME_NS_P (f)) continue;
605       w = XWINDOW (FRAME_SELECTED_WINDOW (f));
606       view = FRAME_NS_VIEW (f);
607       if (!MINI_WINDOW_P (w))
608         edited = ! NILP (Fbuffer_modified_p (w->contents)) &&
609           ! NILP (Fbuffer_file_name (w->contents));
610       [[view window] setDocumentEdited: edited];
611     }
613   [pool release];
614   unblock_input ();
618 void
619 x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
621   int nlines;
622   if (FRAME_MINIBUF_ONLY_P (f))
623     return;
625   if (TYPE_RANGED_INTEGERP (int, value))
626     nlines = XINT (value);
627   else
628     nlines = 0;
630   FRAME_MENU_BAR_LINES (f) = 0;
631   if (nlines)
632     {
633       FRAME_EXTERNAL_MENU_BAR (f) = 1;
634       /* does for all frames, whereas we just want for one frame
635          [NSMenu setMenuBarVisible: YES]; */
636     }
637   else
638     {
639       if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
640         free_frame_menubar (f);
641       /*      [NSMenu setMenuBarVisible: NO]; */
642       FRAME_EXTERNAL_MENU_BAR (f) = 0;
643     }
647 /* toolbar support */
648 void
649 x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
651   /* Currently, when the tool bar change state, the frame is resized.
653      TODO: It would be better if this didn't occur when 1) the frame
654      is full height or maximized or 2) when specified by
655      `frame-inhibit-implied-resize'. */
656   int nlines;
658   NSTRACE ("x_set_tool_bar_lines");
660   if (FRAME_MINIBUF_ONLY_P (f))
661     return;
663   if (RANGED_INTEGERP (0, value, INT_MAX))
664     nlines = XFASTINT (value);
665   else
666     nlines = 0;
668   if (nlines)
669     {
670       FRAME_EXTERNAL_TOOL_BAR (f) = 1;
671       update_frame_tool_bar (f);
672     }
673   else
674     {
675       if (FRAME_EXTERNAL_TOOL_BAR (f))
676         {
677           free_frame_tool_bar (f);
678           FRAME_EXTERNAL_TOOL_BAR (f) = 0;
680           {
681             EmacsView *view = FRAME_NS_VIEW (f);
682             int fs_state = [view fullscreenState];
684             if (fs_state == FULLSCREEN_MAXIMIZED)
685               {
686                 [view setFSValue:FULLSCREEN_WIDTH];
687               }
688             else if (fs_state == FULLSCREEN_HEIGHT)
689               {
690                 [view setFSValue:FULLSCREEN_NONE];
691               }
692           }
693        }
694     }
696   {
697     int inhibit
698       = ((f->after_make_frame
699           && !f->tool_bar_resized
700           && (EQ (frame_inhibit_implied_resize, Qt)
701               || (CONSP (frame_inhibit_implied_resize)
702                   && !NILP (Fmemq (Qtool_bar_lines,
703                                    frame_inhibit_implied_resize))))
704           && NILP (get_frame_param (f, Qfullscreen)))
705          ? 0
706          : 2);
708     NSTRACE_MSG ("inhibit:%d", inhibit);
710     frame_size_history_add (f, Qupdate_frame_tool_bar, 0, 0, Qnil);
711     adjust_frame_size (f, -1, -1, inhibit, 0, Qtool_bar_lines);
712   }
716 void
717 x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
719   int old_width = FRAME_INTERNAL_BORDER_WIDTH (f);
721   CHECK_TYPE_RANGED_INTEGER (int, arg);
722   FRAME_INTERNAL_BORDER_WIDTH (f) = XINT (arg);
723   if (FRAME_INTERNAL_BORDER_WIDTH (f) < 0)
724     FRAME_INTERNAL_BORDER_WIDTH (f) = 0;
726   if (FRAME_INTERNAL_BORDER_WIDTH (f) == old_width)
727     return;
729   if (FRAME_X_WINDOW (f) != 0)
730     adjust_frame_size (f, -1, -1, 3, 0, Qinternal_border_width);
732   SET_FRAME_GARBAGED (f);
736 static void
737 ns_implicitly_set_icon_type (struct frame *f)
739   Lisp_Object tem;
740   EmacsView *view = FRAME_NS_VIEW (f);
741   id image = nil;
742   Lisp_Object chain, elt;
743   NSAutoreleasePool *pool;
744   BOOL setMini = YES;
746   NSTRACE ("ns_implicitly_set_icon_type");
748   block_input ();
749   pool = [[NSAutoreleasePool alloc] init];
750   if (f->output_data.ns->miniimage
751       && [[NSString stringWithUTF8String: SSDATA (f->name)]
752                isEqualToString: [(NSImage *)f->output_data.ns->miniimage name]])
753     {
754       [pool release];
755       unblock_input ();
756       return;
757     }
759   tem = assq_no_quit (Qicon_type, f->param_alist);
760   if (CONSP (tem) && ! NILP (XCDR (tem)))
761     {
762       [pool release];
763       unblock_input ();
764       return;
765     }
767   for (chain = Vns_icon_type_alist;
768        image == nil && CONSP (chain);
769        chain = XCDR (chain))
770     {
771       elt = XCAR (chain);
772       /* special case: t means go by file type */
773       if (SYMBOLP (elt) && EQ (elt, Qt) && SSDATA (f->name)[0] == '/')
774         {
775           NSString *str
776              = [NSString stringWithUTF8String: SSDATA (f->name)];
777           if ([[NSFileManager defaultManager] fileExistsAtPath: str])
778             image = [[[NSWorkspace sharedWorkspace] iconForFile: str] retain];
779         }
780       else if (CONSP (elt) &&
781                STRINGP (XCAR (elt)) &&
782                STRINGP (XCDR (elt)) &&
783                fast_string_match (XCAR (elt), f->name) >= 0)
784         {
785           image = [EmacsImage allocInitFromFile: XCDR (elt)];
786           if (image == nil)
787             image = [[NSImage imageNamed:
788                                [NSString stringWithUTF8String:
789                                             SSDATA (XCDR (elt))]] retain];
790         }
791     }
793   if (image == nil)
794     {
795       image = [[[NSWorkspace sharedWorkspace] iconForFileType: @"text"] retain];
796       setMini = NO;
797     }
799   [f->output_data.ns->miniimage release];
800   f->output_data.ns->miniimage = image;
801   [view setMiniwindowImage: setMini];
802   [pool release];
803   unblock_input ();
807 static void
808 x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
810   EmacsView *view = FRAME_NS_VIEW (f);
811   id image = nil;
812   BOOL setMini = YES;
814   NSTRACE ("x_set_icon_type");
816   if (!NILP (arg) && SYMBOLP (arg))
817     {
818       arg =build_string (SSDATA (SYMBOL_NAME (arg)));
819       store_frame_param (f, Qicon_type, arg);
820     }
822   /* do it the implicit way */
823   if (NILP (arg))
824     {
825       ns_implicitly_set_icon_type (f);
826       return;
827     }
829   CHECK_STRING (arg);
831   image = [EmacsImage allocInitFromFile: arg];
832   if (image == nil)
833     image =[NSImage imageNamed: [NSString stringWithUTF8String:
834                                             SSDATA (arg)]];
836   if (image == nil)
837     {
838       image = [NSImage imageNamed: @"text"];
839       setMini = NO;
840     }
842   f->output_data.ns->miniimage = image;
843   [view setMiniwindowImage: setMini];
847 /* TODO: move to nsterm? */
849 ns_lisp_to_cursor_type (Lisp_Object arg)
851   char *str;
852   if (XTYPE (arg) == Lisp_String)
853     str = SSDATA (arg);
854   else if (XTYPE (arg) == Lisp_Symbol)
855     str = SSDATA (SYMBOL_NAME (arg));
856   else return -1;
857   if (!strcmp (str, "box"))     return FILLED_BOX_CURSOR;
858   if (!strcmp (str, "hollow"))  return HOLLOW_BOX_CURSOR;
859   if (!strcmp (str, "hbar"))    return HBAR_CURSOR;
860   if (!strcmp (str, "bar"))     return BAR_CURSOR;
861   if (!strcmp (str, "no"))      return NO_CURSOR;
862   return -1;
866 Lisp_Object
867 ns_cursor_type_to_lisp (int arg)
869   switch (arg)
870     {
871     case FILLED_BOX_CURSOR: return Qbox;
872     case HOLLOW_BOX_CURSOR: return Qhollow;
873     case HBAR_CURSOR:       return Qhbar;
874     case BAR_CURSOR:        return Qbar;
875     case NO_CURSOR:
876     default:                return intern ("no");
877     }
880 /* This is the same as the xfns.c definition.  */
881 static void
882 x_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
884   set_frame_cursor_types (f, arg);
887 /* called to set mouse pointer color, but all other terms use it to
888    initialize pointer types (and don't set the color ;) */
889 static void
890 x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
892   /* don't think we can do this on Nextstep */
896 #define Str(x) #x
897 #define Xstr(x) Str(x)
899 static Lisp_Object
900 ns_appkit_version_str (void)
902   char tmp[256];
904 #ifdef NS_IMPL_GNUSTEP
905   sprintf(tmp, "gnustep-gui-%s", Xstr(GNUSTEP_GUI_VERSION));
906 #elif defined (NS_IMPL_COCOA)
907   NSString *osversion
908     = [[NSProcessInfo processInfo] operatingSystemVersionString];
909   sprintf(tmp, "appkit-%.2f %s",
910           NSAppKitVersionNumber,
911           [osversion UTF8String]);
912 #else
913   tmp = "ns-unknown";
914 #endif
915   return build_string (tmp);
919 /* This is for use by x-server-version and collapses all version info we
920    have into a single int.  For a better picture of the implementation
921    running, use ns_appkit_version_str.*/
922 static int
923 ns_appkit_version_int (void)
925 #ifdef NS_IMPL_GNUSTEP
926   return GNUSTEP_GUI_MAJOR_VERSION * 100 + GNUSTEP_GUI_MINOR_VERSION;
927 #elif defined (NS_IMPL_COCOA)
928   return (int)NSAppKitVersionNumber;
929 #endif
930   return 0;
934 static void
935 x_icon (struct frame *f, Lisp_Object parms)
936 /* --------------------------------------------------------------------------
937    Strangely-named function to set icon position parameters in frame.
938    This is irrelevant under OS X, but might be needed under GNUstep,
939    depending on the window manager used.  Note, this is not a standard
940    frame parameter-setter; it is called directly from x-create-frame.
941    -------------------------------------------------------------------------- */
943   Lisp_Object icon_x, icon_y;
944   struct ns_display_info *dpyinfo = check_ns_display_info (Qnil);
946   f->output_data.ns->icon_top = -1;
947   f->output_data.ns->icon_left = -1;
949   /* Set the position of the icon.  */
950   icon_x = x_get_arg (dpyinfo, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
951   icon_y = x_get_arg (dpyinfo, parms, Qicon_top, 0, 0,  RES_TYPE_NUMBER);
952   if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
953     {
954       CHECK_NUMBER (icon_x);
955       CHECK_NUMBER (icon_y);
956       f->output_data.ns->icon_top = XINT (icon_y);
957       f->output_data.ns->icon_left = XINT (icon_x);
958     }
959   else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
960     error ("Both left and top icon corners of icon must be specified");
964 /* Note: see frame.c for template, also where generic functions are impl */
965 frame_parm_handler ns_frame_parm_handlers[] =
967   x_set_autoraise, /* generic OK */
968   x_set_autolower, /* generic OK */
969   x_set_background_color,
970   0, /* x_set_border_color,  may be impossible under Nextstep */
971   0, /* x_set_border_width,  may be impossible under Nextstep */
972   x_set_cursor_color,
973   x_set_cursor_type,
974   x_set_font, /* generic OK */
975   x_set_foreground_color,
976   x_set_icon_name,
977   x_set_icon_type,
978   x_set_internal_border_width, /* generic OK */
979   0, /* x_set_right_divider_width */
980   0, /* x_set_bottom_divider_width */
981   x_set_menu_bar_lines,
982   x_set_mouse_color,
983   x_explicitly_set_name,
984   x_set_scroll_bar_width, /* generic OK */
985   x_set_scroll_bar_height, /* generic OK */
986   x_set_title,
987   x_set_unsplittable, /* generic OK */
988   x_set_vertical_scroll_bars, /* generic OK */
989   x_set_horizontal_scroll_bars, /* generic OK */
990   x_set_visibility, /* generic OK */
991   x_set_tool_bar_lines,
992   0, /* x_set_scroll_bar_foreground, will ignore (not possible on NS) */
993   0, /* x_set_scroll_bar_background,  will ignore (not possible on NS) */
994   x_set_screen_gamma, /* generic OK */
995   x_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */
996   x_set_left_fringe, /* generic OK */
997   x_set_right_fringe, /* generic OK */
998   0, /* x_set_wait_for_wm, will ignore */
999   x_set_fullscreen, /* generic OK */
1000   x_set_font_backend, /* generic OK */
1001   x_set_alpha,
1002   0, /* x_set_sticky */
1003   0, /* x_set_tool_bar_position */
1007 /* Handler for signals raised during x_create_frame.
1008    FRAME is the frame which is partially constructed.  */
1010 static void
1011 unwind_create_frame (Lisp_Object frame)
1013   struct frame *f = XFRAME (frame);
1015   /* If frame is already dead, nothing to do.  This can happen if the
1016      display is disconnected after the frame has become official, but
1017      before x_create_frame removes the unwind protect.  */
1018   if (!FRAME_LIVE_P (f))
1019     return;
1021   /* If frame is ``official'', nothing to do.  */
1022   if (NILP (Fmemq (frame, Vframe_list)))
1023     {
1024 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
1025       struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
1026 #endif
1028       /* If the frame's image cache refcount is still the same as our
1029          private shadow variable, it means we are unwinding a frame
1030          for which we didn't yet call init_frame_faces, where the
1031          refcount is incremented.  Therefore, we increment it here, so
1032          that free_frame_faces, called in x_free_frame_resources
1033          below, will not mistakenly decrement the counter that was not
1034          incremented yet to account for this new frame.  */
1035       if (FRAME_IMAGE_CACHE (f) != NULL
1036           && FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount)
1037         FRAME_IMAGE_CACHE (f)->refcount++;
1039       x_free_frame_resources (f);
1040       free_glyphs (f);
1042 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
1043       /* Check that reference counts are indeed correct.  */
1044       eassert (dpyinfo->terminal->image_cache->refcount == image_cache_refcount);
1045 #endif
1046     }
1050  * Read geometry related parameters from preferences if not in PARMS.
1051  * Returns the union of parms and any preferences read.
1052  */
1054 static Lisp_Object
1055 get_geometry_from_preferences (struct ns_display_info *dpyinfo,
1056                                Lisp_Object parms)
1058   struct {
1059     const char *val;
1060     const char *cls;
1061     Lisp_Object tem;
1062   } r[] = {
1063     { "width",  "Width", Qwidth },
1064     { "height", "Height", Qheight },
1065     { "left", "Left", Qleft },
1066     { "top", "Top", Qtop },
1067   };
1069   int i;
1070   for (i = 0; i < ARRAYELTS (r); ++i)
1071     {
1072       if (NILP (Fassq (r[i].tem, parms)))
1073         {
1074           Lisp_Object value
1075             = x_get_arg (dpyinfo, parms, r[i].tem, r[i].val, r[i].cls,
1076                          RES_TYPE_NUMBER);
1077           if (! EQ (value, Qunbound))
1078             parms = Fcons (Fcons (r[i].tem, value), parms);
1079         }
1080     }
1082   return parms;
1085 /* ==========================================================================
1087     Lisp definitions
1089    ========================================================================== */
1091 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
1092        1, 1, 0,
1093        doc: /* Make a new Nextstep window, called a "frame" in Emacs terms.
1094 Return an Emacs frame object.
1095 PARMS is an alist of frame parameters.
1096 If the parameters specify that the frame should not have a minibuffer,
1097 and do not specify a specific minibuffer window to use,
1098 then `default-minibuffer-frame' must be a frame whose minibuffer can
1099 be shared by the new frame.
1101 This function is an internal primitive--use `make-frame' instead.  */)
1102      (Lisp_Object parms)
1104   struct frame *f;
1105   Lisp_Object frame, tem;
1106   Lisp_Object name;
1107   int minibuffer_only = 0;
1108   long window_prompting = 0;
1109   ptrdiff_t count = specpdl_ptr - specpdl;
1110   Lisp_Object display;
1111   struct ns_display_info *dpyinfo = NULL;
1112   Lisp_Object parent;
1113   struct kboard *kb;
1114   static int desc_ctr = 1;
1115   int x_width = 0, x_height = 0;
1117   /* x_get_arg modifies parms.  */
1118   parms = Fcopy_alist (parms);
1120   /* Use this general default value to start with
1121      until we know if this frame has a specified name.  */
1122   Vx_resource_name = Vinvocation_name;
1124   display = x_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_STRING);
1125   if (EQ (display, Qunbound))
1126     display = Qnil;
1127   dpyinfo = check_ns_display_info (display);
1128   kb = dpyinfo->terminal->kboard;
1130   if (!dpyinfo->terminal->name)
1131     error ("Terminal is not live, can't create new frames on it");
1133   name = x_get_arg (dpyinfo, parms, Qname, 0, 0, RES_TYPE_STRING);
1134   if (!STRINGP (name)
1135       && ! EQ (name, Qunbound)
1136       && ! NILP (name))
1137     error ("Invalid frame name--not a string or nil");
1139   if (STRINGP (name))
1140     Vx_resource_name = name;
1142   parent = x_get_arg (dpyinfo, parms, Qparent_id, 0, 0, RES_TYPE_NUMBER);
1143   if (EQ (parent, Qunbound))
1144     parent = Qnil;
1145   if (! NILP (parent))
1146     CHECK_NUMBER (parent);
1148   /* make_frame_without_minibuffer can run Lisp code and garbage collect.  */
1149   /* No need to protect DISPLAY because that's not used after passing
1150      it to make_frame_without_minibuffer.  */
1151   frame = Qnil;
1152   tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
1153                   RES_TYPE_SYMBOL);
1154   if (EQ (tem, Qnone) || NILP (tem))
1155       f = make_frame_without_minibuffer (Qnil, kb, display);
1156   else if (EQ (tem, Qonly))
1157     {
1158       f = make_minibuffer_frame ();
1159       minibuffer_only = 1;
1160     }
1161   else if (WINDOWP (tem))
1162       f = make_frame_without_minibuffer (tem, kb, display);
1163   else
1164       f = make_frame (1);
1166   XSETFRAME (frame, f);
1168   f->terminal = dpyinfo->terminal;
1170   f->output_method = output_ns;
1171   f->output_data.ns = xzalloc (sizeof *f->output_data.ns);
1173   FRAME_FONTSET (f) = -1;
1175   fset_icon_name (f, x_get_arg (dpyinfo, parms, Qicon_name,
1176                                 "iconName", "Title",
1177                                 RES_TYPE_STRING));
1178   if (! STRINGP (f->icon_name))
1179     fset_icon_name (f, Qnil);
1181   FRAME_DISPLAY_INFO (f) = dpyinfo;
1183   /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe.  */
1184   record_unwind_protect (unwind_create_frame, frame);
1186   f->output_data.ns->window_desc = desc_ctr++;
1187   if (TYPE_RANGED_INTEGERP (Window, parent))
1188     {
1189       f->output_data.ns->parent_desc = XFASTINT (parent);
1190       f->output_data.ns->explicit_parent = 1;
1191     }
1192   else
1193     {
1194       f->output_data.ns->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
1195       f->output_data.ns->explicit_parent = 0;
1196     }
1198   /* Set the name; the functions to which we pass f expect the name to
1199      be set.  */
1200   if (EQ (name, Qunbound) || NILP (name) || ! STRINGP (name))
1201     {
1202       fset_name (f, build_string ([ns_app_name UTF8String]));
1203       f->explicit_name = 0;
1204     }
1205   else
1206     {
1207       fset_name (f, name);
1208       f->explicit_name = 1;
1209       specbind (Qx_resource_name, name);
1210     }
1212   block_input ();
1214 #ifdef NS_IMPL_COCOA
1215     mac_register_font_driver (f);
1216 #else
1217     register_font_driver (&nsfont_driver, f);
1218 #endif
1220   image_cache_refcount =
1221     FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
1223   x_default_parameter (f, parms, Qfont_backend, Qnil,
1224                         "fontBackend", "FontBackend", RES_TYPE_STRING);
1226   {
1227     /* use for default font name */
1228     id font = [NSFont userFixedPitchFontOfSize: -1.0]; /* default */
1229     x_default_parameter (f, parms, Qfontsize,
1230                                     make_number (0 /*(int)[font pointSize]*/),
1231                                     "fontSize", "FontSize", RES_TYPE_NUMBER);
1232     // Remove ' Regular', not handled by backends.
1233     char *fontname = xstrdup ([[font displayName] UTF8String]);
1234     int len = strlen (fontname);
1235     if (len > 8 && strcmp (fontname + len - 8, " Regular") == 0)
1236       fontname[len-8] = '\0';
1237     x_default_parameter (f, parms, Qfont,
1238                                  build_string (fontname),
1239                                  "font", "Font", RES_TYPE_STRING);
1240     xfree (fontname);
1241   }
1242   unblock_input ();
1244   x_default_parameter (f, parms, Qborder_width, make_number (0),
1245                        "borderwidth", "BorderWidth", RES_TYPE_NUMBER);
1246   x_default_parameter (f, parms, Qinternal_border_width, make_number (2),
1247                       "internalBorderWidth", "InternalBorderWidth",
1248                       RES_TYPE_NUMBER);
1250   /* default vertical scrollbars on right on Mac */
1251   {
1252       Lisp_Object spos
1253 #ifdef NS_IMPL_GNUSTEP
1254           = Qt;
1255 #else
1256           = Qright;
1257 #endif
1258       x_default_parameter (f, parms, Qvertical_scroll_bars, spos,
1259                            "verticalScrollBars", "VerticalScrollBars",
1260                            RES_TYPE_SYMBOL);
1261   }
1262   x_default_parameter (f, parms, Qhorizontal_scroll_bars, Qnil,
1263                        "horizontalScrollBars", "HorizontalScrollBars",
1264                        RES_TYPE_SYMBOL);
1265   x_default_parameter (f, parms, Qforeground_color, build_string ("Black"),
1266                       "foreground", "Foreground", RES_TYPE_STRING);
1267   x_default_parameter (f, parms, Qbackground_color, build_string ("White"),
1268                       "background", "Background", RES_TYPE_STRING);
1269   /* FIXME: not supported yet in Nextstep */
1270   x_default_parameter (f, parms, Qline_spacing, Qnil,
1271                        "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
1272   x_default_parameter (f, parms, Qleft_fringe, Qnil,
1273                        "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
1274   x_default_parameter (f, parms, Qright_fringe, Qnil,
1275                        "rightFringe", "RightFringe", RES_TYPE_NUMBER);
1277   init_frame_faces (f);
1279   /* Read comment about this code in corresponding place in xfns.c.  */
1280   adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
1281                      FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1,
1282                      Qx_create_frame_1);
1284   /* The resources controlling the menu-bar and tool-bar are
1285      processed specially at startup, and reflected in the mode
1286      variables; ignore them here.  */
1287   x_default_parameter (f, parms, Qmenu_bar_lines,
1288                        NILP (Vmenu_bar_mode)
1289                        ? make_number (0) : make_number (1),
1290                        NULL, NULL, RES_TYPE_NUMBER);
1291   x_default_parameter (f, parms, Qtool_bar_lines,
1292                        NILP (Vtool_bar_mode)
1293                        ? make_number (0) : make_number (1),
1294                        NULL, NULL, RES_TYPE_NUMBER);
1296   x_default_parameter (f, parms, Qbuffer_predicate, Qnil, "bufferPredicate",
1297                        "BufferPredicate", RES_TYPE_SYMBOL);
1298   x_default_parameter (f, parms, Qtitle, Qnil, "title", "Title",
1299                        RES_TYPE_STRING);
1301   parms = get_geometry_from_preferences (dpyinfo, parms);
1302   window_prompting = x_figure_window_size (f, parms, true, &x_width, &x_height);
1304   tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
1305   f->no_split = minibuffer_only || (!EQ (tem, Qunbound) && !EQ (tem, Qnil));
1307   /* NOTE: on other terms, this is done in set_mouse_color, however this
1308      was not getting called under Nextstep */
1309   f->output_data.ns->text_cursor = [NSCursor IBeamCursor];
1310   f->output_data.ns->nontext_cursor = [NSCursor arrowCursor];
1311   f->output_data.ns->modeline_cursor = [NSCursor pointingHandCursor];
1312   f->output_data.ns->hand_cursor = [NSCursor pointingHandCursor];
1313   f->output_data.ns->hourglass_cursor = [NSCursor disappearingItemCursor];
1314   f->output_data.ns->horizontal_drag_cursor = [NSCursor resizeLeftRightCursor];
1315   f->output_data.ns->vertical_drag_cursor = [NSCursor resizeUpDownCursor];
1316   FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor
1317      = [NSCursor arrowCursor];
1318   FRAME_DISPLAY_INFO (f)->horizontal_scroll_bar_cursor
1319      = [NSCursor arrowCursor];
1320   f->output_data.ns->current_pointer = f->output_data.ns->text_cursor;
1322   f->output_data.ns->in_animation = NO;
1324   [[EmacsView alloc] initFrameFromEmacs: f];
1326   x_icon (f, parms);
1328   /* ns_display_info does not have a reference_count.  */
1329   f->terminal->reference_count++;
1331   /* It is now ok to make the frame official even if we get an error below.
1332      The frame needs to be on Vframe_list or making it visible won't work. */
1333   Vframe_list = Fcons (frame, Vframe_list);
1335   x_default_parameter (f, parms, Qicon_type, Qnil,
1336                        "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
1338   x_default_parameter (f, parms, Qauto_raise, Qnil,
1339                        "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
1340   x_default_parameter (f, parms, Qauto_lower, Qnil,
1341                        "autoLower", "AutoLower", RES_TYPE_BOOLEAN);
1342   x_default_parameter (f, parms, Qcursor_type, Qbox,
1343                        "cursorType", "CursorType", RES_TYPE_SYMBOL);
1344   x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
1345                        "scrollBarWidth", "ScrollBarWidth",
1346                        RES_TYPE_NUMBER);
1347   x_default_parameter (f, parms, Qscroll_bar_height, Qnil,
1348                        "scrollBarHeight", "ScrollBarHeight",
1349                        RES_TYPE_NUMBER);
1350   x_default_parameter (f, parms, Qalpha, Qnil,
1351                        "alpha", "Alpha", RES_TYPE_NUMBER);
1352   x_default_parameter (f, parms, Qfullscreen, Qnil,
1353                        "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
1355   /* Allow x_set_window_size, now.  */
1356   f->can_x_set_window_size = true;
1358   if (x_width > 0)
1359     SET_FRAME_WIDTH (f, x_width);
1360   if (x_height > 0)
1361     SET_FRAME_HEIGHT (f, x_height);
1363   adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, 1,
1364                      Qx_create_frame_2);
1366   if (! f->output_data.ns->explicit_parent)
1367     {
1368       Lisp_Object visibility;
1370       visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
1371                               RES_TYPE_SYMBOL);
1372       if (EQ (visibility, Qunbound))
1373         visibility = Qt;
1375       if (EQ (visibility, Qicon))
1376         x_iconify_frame (f);
1377       else if (! NILP (visibility))
1378         {
1379           x_make_frame_visible (f);
1380           [[FRAME_NS_VIEW (f) window] makeKeyWindow];
1381         }
1382       else
1383         {
1384           /* Must have been Qnil.  */
1385         }
1386     }
1388   if (FRAME_HAS_MINIBUF_P (f)
1389       && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
1390           || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
1391     kset_default_minibuffer_frame (kb, frame);
1393   /* All remaining specified parameters, which have not been "used"
1394      by x_get_arg and friends, now go in the misc. alist of the frame.  */
1395   for (tem = parms; CONSP (tem); tem = XCDR (tem))
1396     if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
1397       fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
1399   if (window_prompting & USPosition)
1400     x_set_offset (f, f->left_pos, f->top_pos, 1);
1402   /* Make sure windows on this frame appear in calls to next-window
1403      and similar functions.  */
1404   Vwindow_list = Qnil;
1406   return unbind_to (count, frame);
1409 void
1410 x_focus_frame (struct frame *f)
1412   struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
1414   if (dpyinfo->x_focus_frame != f)
1415     {
1416       EmacsView *view = FRAME_NS_VIEW (f);
1417       block_input ();
1418       [NSApp activateIgnoringOtherApps: YES];
1419       [[view window] makeKeyAndOrderFront: view];
1420       unblock_input ();
1421     }
1425 DEFUN ("ns-popup-font-panel", Fns_popup_font_panel, Sns_popup_font_panel,
1426        0, 1, "",
1427        doc: /* Pop up the font panel. */)
1428      (Lisp_Object frame)
1430   struct frame *f = decode_window_system_frame (frame);
1431   id fm = [NSFontManager sharedFontManager];
1432   struct font *font = f->output_data.ns->font;
1433   NSFont *nsfont;
1434 #ifdef NS_IMPL_GNUSTEP
1435   nsfont = ((struct nsfont_info *)font)->nsfont;
1436 #endif
1437 #ifdef NS_IMPL_COCOA
1438   nsfont = (NSFont *) macfont_get_nsctfont (font);
1439 #endif
1440   [fm setSelectedFont: nsfont isMultiple: NO];
1441   [fm orderFrontFontPanel: NSApp];
1442   return Qnil;
1446 DEFUN ("ns-popup-color-panel", Fns_popup_color_panel, Sns_popup_color_panel,
1447        0, 1, "",
1448        doc: /* Pop up the color panel.  */)
1449      (Lisp_Object frame)
1451   check_window_system (NULL);
1452   [NSApp orderFrontColorPanel: NSApp];
1453   return Qnil;
1456 static struct
1458   id panel;
1459   BOOL ret;
1460 #ifdef NS_IMPL_GNUSTEP
1461   NSString *dirS, *initS;
1462   BOOL no_types;
1463 #endif
1464 } ns_fd_data;
1466 void
1467 ns_run_file_dialog (void)
1469   if (ns_fd_data.panel == nil) return;
1470 #ifdef NS_IMPL_COCOA
1471   ns_fd_data.ret = [ns_fd_data.panel runModal];
1472 #else
1473   if (ns_fd_data.no_types)
1474     {
1475       ns_fd_data.ret = [ns_fd_data.panel
1476                            runModalForDirectory: ns_fd_data.dirS
1477                            file: ns_fd_data.initS];
1478     }
1479   else
1480     {
1481       ns_fd_data.ret = [ns_fd_data.panel
1482                            runModalForDirectory: ns_fd_data.dirS
1483                            file: ns_fd_data.initS
1484                            types: nil];
1485     }
1486 #endif
1487   ns_fd_data.panel = nil;
1490 #ifdef NS_IMPL_COCOA
1491 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_9
1492 #define MODAL_OK_RESPONSE NSModalResponseOK
1493 #endif
1494 #endif
1495 #ifndef MODAL_OK_RESPONSE
1496 #define MODAL_OK_RESPONSE NSOKButton
1497 #endif
1499 DEFUN ("ns-read-file-name", Fns_read_file_name, Sns_read_file_name, 1, 5, 0,
1500        doc: /* Use a graphical panel to read a file name, using prompt PROMPT.
1501 Optional arg DIR, if non-nil, supplies a default directory.
1502 Optional arg MUSTMATCH, if non-nil, means the returned file or
1503 directory must exist.
1504 Optional arg INIT, if non-nil, provides a default file name to use.
1505 Optional arg DIR_ONLY_P, if non-nil, means choose only directories.  */)
1506   (Lisp_Object prompt, Lisp_Object dir, Lisp_Object mustmatch,
1507    Lisp_Object init, Lisp_Object dir_only_p)
1509   static id fileDelegate = nil;
1510   BOOL isSave = NILP (mustmatch) && NILP (dir_only_p);
1511   id panel;
1512   Lisp_Object fname = Qnil;
1514   NSString *promptS = NILP (prompt) || !STRINGP (prompt) ? nil :
1515     [NSString stringWithUTF8String: SSDATA (prompt)];
1516   NSString *dirS = NILP (dir) || !STRINGP (dir) ?
1517     [NSString stringWithUTF8String: SSDATA (BVAR (current_buffer, directory))] :
1518     [NSString stringWithUTF8String: SSDATA (dir)];
1519   NSString *initS = NILP (init) || !STRINGP (init) ? nil :
1520     [NSString stringWithUTF8String: SSDATA (init)];
1521   NSEvent *nxev;
1523   check_window_system (NULL);
1525   if (fileDelegate == nil)
1526     fileDelegate = [EmacsFileDelegate new];
1528   [NSCursor setHiddenUntilMouseMoves: NO];
1530   if ([dirS characterAtIndex: 0] == '~')
1531     dirS = [dirS stringByExpandingTildeInPath];
1533   panel = isSave ?
1534     (id)[EmacsSavePanel savePanel] : (id)[EmacsOpenPanel openPanel];
1536   [panel setTitle: promptS];
1538   [panel setAllowsOtherFileTypes: YES];
1539   [panel setTreatsFilePackagesAsDirectories: YES];
1540   [panel setDelegate: fileDelegate];
1542   if (! NILP (dir_only_p))
1543     {
1544       [panel setCanChooseDirectories: YES];
1545       [panel setCanChooseFiles: NO];
1546     }
1547   else if (! isSave)
1548     {
1549       /* This is not quite what the documentation says, but it is compatible
1550          with the Gtk+ code.  Also, the menu entry says "Open File...".  */
1551       [panel setCanChooseDirectories: NO];
1552       [panel setCanChooseFiles: YES];
1553     }
1555   block_input ();
1556   ns_fd_data.panel = panel;
1557   ns_fd_data.ret = NO;
1558 #ifdef NS_IMPL_COCOA
1559   if (! NILP (mustmatch) || ! NILP (dir_only_p))
1560     [panel setAllowedFileTypes: nil];
1561   if (dirS) [panel setDirectoryURL: [NSURL fileURLWithPath: dirS]];
1562   if (initS && NILP (Ffile_directory_p (init)))
1563     [panel setNameFieldStringValue: [initS lastPathComponent]];
1564   else
1565     [panel setNameFieldStringValue: @""];
1567 #else
1568   ns_fd_data.no_types = NILP (mustmatch) && NILP (dir_only_p);
1569   ns_fd_data.dirS = dirS;
1570   ns_fd_data.initS = initS;
1571 #endif
1573   /* runModalForDirectory/runModal restarts the main event loop when done,
1574      so we must start an event loop and then pop up the file dialog.
1575      The file dialog may pop up a confirm dialog after Ok has been pressed,
1576      so we can not simply pop down on the Ok/Cancel press.
1577    */
1578   nxev = [NSEvent otherEventWithType: NSApplicationDefined
1579                             location: NSMakePoint (0, 0)
1580                        modifierFlags: 0
1581                            timestamp: 0
1582                         windowNumber: [[NSApp mainWindow] windowNumber]
1583                              context: [NSApp context]
1584                              subtype: 0
1585                                data1: 0
1586                                data2: NSAPP_DATA2_RUNFILEDIALOG];
1588   [NSApp postEvent: nxev atStart: NO];
1589   while (ns_fd_data.panel != nil)
1590     [NSApp run];
1592   if (ns_fd_data.ret == MODAL_OK_RESPONSE)
1593     {
1594       NSString *str = ns_filename_from_panel (panel);
1595       if (! str) str = ns_directory_from_panel (panel);
1596       if (str) fname = build_string ([str UTF8String]);
1597     }
1599   [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
1600   unblock_input ();
1602   return fname;
1605 const char *
1606 ns_get_defaults_value (const char *key)
1608   NSObject *obj = [[NSUserDefaults standardUserDefaults]
1609                     objectForKey: [NSString stringWithUTF8String: key]];
1611   if (!obj) return NULL;
1613   return [[NSString stringWithFormat: @"%@", obj] UTF8String];
1617 DEFUN ("ns-get-resource", Fns_get_resource, Sns_get_resource, 2, 2, 0,
1618        doc: /* Return the value of the property NAME of OWNER from the defaults database.
1619 If OWNER is nil, Emacs is assumed.  */)
1620      (Lisp_Object owner, Lisp_Object name)
1622   const char *value;
1624   check_window_system (NULL);
1625   if (NILP (owner))
1626     owner = build_string([ns_app_name UTF8String]);
1627   CHECK_STRING (name);
1629   value = ns_get_defaults_value (SSDATA (name));
1631   if (value)
1632     return build_string (value);
1633   return Qnil;
1637 DEFUN ("ns-set-resource", Fns_set_resource, Sns_set_resource, 3, 3, 0,
1638        doc: /* Set property NAME of OWNER to VALUE, from the defaults database.
1639 If OWNER is nil, Emacs is assumed.
1640 If VALUE is nil, the default is removed.  */)
1641      (Lisp_Object owner, Lisp_Object name, Lisp_Object value)
1643   check_window_system (NULL);
1644   if (NILP (owner))
1645     owner = build_string ([ns_app_name UTF8String]);
1646   CHECK_STRING (name);
1647   if (NILP (value))
1648     {
1649       [[NSUserDefaults standardUserDefaults] removeObjectForKey:
1650                          [NSString stringWithUTF8String: SSDATA (name)]];
1651     }
1652   else
1653     {
1654       CHECK_STRING (value);
1655       [[NSUserDefaults standardUserDefaults] setObject:
1656                 [NSString stringWithUTF8String: SSDATA (value)]
1657                                         forKey: [NSString stringWithUTF8String:
1658                                                          SSDATA (name)]];
1659     }
1661   return Qnil;
1665 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
1666        Sx_server_max_request_size,
1667        0, 1, 0,
1668        doc: /* This function is a no-op.  It is only present for completeness.  */)
1669      (Lisp_Object terminal)
1671   check_ns_display_info (terminal);
1672   /* This function has no real equivalent under NeXTstep.  Return nil to
1673      indicate this. */
1674   return Qnil;
1678 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
1679        doc: /* Return the "vendor ID" string of Nextstep display server TERMINAL.
1680 (Labeling every distributor as a "vendor" embodies the false assumption
1681 that operating systems cannot be developed and distributed noncommercially.)
1682 The optional argument TERMINAL specifies which display to ask about.
1683 TERMINAL should be a terminal object, a frame or a display name (a string).
1684 If omitted or nil, that stands for the selected frame's display.  */)
1685   (Lisp_Object terminal)
1687   check_ns_display_info (terminal);
1688 #ifdef NS_IMPL_GNUSTEP
1689   return build_string ("GNU");
1690 #else
1691   return build_string ("Apple");
1692 #endif
1696 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
1697        doc: /* Return the version numbers of the server of display TERMINAL.
1698 The value is a list of three integers: the major and minor
1699 version numbers of the X Protocol in use, and the distributor-specific release
1700 number.  See also the function `x-server-vendor'.
1702 The optional argument TERMINAL specifies which display to ask about.
1703 TERMINAL should be a terminal object, a frame or a display name (a string).
1704 If omitted or nil, that stands for the selected frame's display.  */)
1705   (Lisp_Object terminal)
1707   check_ns_display_info (terminal);
1708   /*NOTE: it is unclear what would best correspond with "protocol";
1709           we return 10.3, meaning Panther, since this is roughly the
1710           level that GNUstep's APIs correspond to.
1711           The last number is where we distinguish between the Apple
1712           and GNUstep implementations ("distributor-specific release
1713           number") and give int'ized versions of major.minor. */
1714   return list3i (10, 3, ns_appkit_version_int ());
1718 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
1719        doc: /* Return the number of screens on Nextstep display server TERMINAL.
1720 The optional argument TERMINAL specifies which display to ask about.
1721 TERMINAL should be a terminal object, a frame or a display name (a string).
1722 If omitted or nil, that stands for the selected frame's display.
1724 Note: "screen" here is not in Nextstep terminology but in X11's.  For
1725 the number of physical monitors, use `(length
1726 (display-monitor-attributes-list TERMINAL))' instead.  */)
1727   (Lisp_Object terminal)
1729   check_ns_display_info (terminal);
1730   return make_number (1);
1734 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
1735        doc: /* Return the height in millimeters of the Nextstep display TERMINAL.
1736 The optional argument TERMINAL specifies which display to ask about.
1737 TERMINAL should be a terminal object, a frame or a display name (a string).
1738 If omitted or nil, that stands for the selected frame's display.
1740 On \"multi-monitor\" setups this refers to the height in millimeters for
1741 all physical monitors associated with TERMINAL.  To get information
1742 for each physical monitor, use `display-monitor-attributes-list'.  */)
1743   (Lisp_Object terminal)
1745   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
1747   return make_number (x_display_pixel_height (dpyinfo) / (92.0/25.4));
1751 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
1752        doc: /* Return the width in millimeters of the Nextstep display TERMINAL.
1753 The optional argument TERMINAL specifies which display to ask about.
1754 TERMINAL should be a terminal object, a frame or a display name (a string).
1755 If omitted or nil, that stands for the selected frame's display.
1757 On \"multi-monitor\" setups this refers to the width in millimeters for
1758 all physical monitors associated with TERMINAL.  To get information
1759 for each physical monitor, use `display-monitor-attributes-list'.  */)
1760   (Lisp_Object terminal)
1762   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
1764   return make_number (x_display_pixel_width (dpyinfo) / (92.0/25.4));
1768 DEFUN ("x-display-backing-store", Fx_display_backing_store,
1769        Sx_display_backing_store, 0, 1, 0,
1770        doc: /* Return an indication of whether the Nextstep display TERMINAL does backing store.
1771 The value may be `buffered', `retained', or `non-retained'.
1772 The optional argument TERMINAL specifies which display to ask about.
1773 TERMINAL should be a terminal object, a frame or a display name (a string).
1774 If omitted or nil, that stands for the selected frame's display.  */)
1775   (Lisp_Object terminal)
1777   check_ns_display_info (terminal);
1778   switch ([ns_get_window (terminal) backingType])
1779     {
1780     case NSBackingStoreBuffered:
1781       return intern ("buffered");
1782     case NSBackingStoreRetained:
1783       return intern ("retained");
1784     case NSBackingStoreNonretained:
1785       return intern ("non-retained");
1786     default:
1787       error ("Strange value for backingType parameter of frame");
1788     }
1789   return Qnil;  /* not reached, shut compiler up */
1793 DEFUN ("x-display-visual-class", Fx_display_visual_class,
1794        Sx_display_visual_class, 0, 1, 0,
1795        doc: /* Return the visual class of the Nextstep display TERMINAL.
1796 The value is one of the symbols `static-gray', `gray-scale',
1797 `static-color', `pseudo-color', `true-color', or `direct-color'.
1799 The optional argument TERMINAL specifies which display to ask about.
1800 TERMINAL should a terminal object, a frame or a display name (a string).
1801 If omitted or nil, that stands for the selected frame's display.  */)
1802   (Lisp_Object terminal)
1804   NSWindowDepth depth;
1806   check_ns_display_info (terminal);
1807   depth = [[[NSScreen screens] objectAtIndex:0] depth];
1809   if ( depth == NSBestDepth (NSCalibratedWhiteColorSpace, 2, 2, YES, NULL))
1810     return intern ("static-gray");
1811   else if (depth == NSBestDepth (NSCalibratedWhiteColorSpace, 8, 8, YES, NULL))
1812     return intern ("gray-scale");
1813   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 8, YES, NULL))
1814     return intern ("pseudo-color");
1815   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 4, 12, NO, NULL))
1816     return intern ("true-color");
1817   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 24, NO, NULL))
1818     return intern ("direct-color");
1819   else
1820     /* color mgmt as far as we do it is really handled by Nextstep itself anyway */
1821     return intern ("direct-color");
1825 DEFUN ("x-display-save-under", Fx_display_save_under,
1826        Sx_display_save_under, 0, 1, 0,
1827        doc: /* Return t if TERMINAL supports the save-under feature.
1828 The optional argument TERMINAL specifies which display to ask about.
1829 TERMINAL should be a terminal object, a frame or a display name (a string).
1830 If omitted or nil, that stands for the selected frame's display.  */)
1831   (Lisp_Object terminal)
1833   check_ns_display_info (terminal);
1834   switch ([ns_get_window (terminal) backingType])
1835     {
1836     case NSBackingStoreBuffered:
1837       return Qt;
1839     case NSBackingStoreRetained:
1840     case NSBackingStoreNonretained:
1841       return Qnil;
1843     default:
1844       error ("Strange value for backingType parameter of frame");
1845     }
1846   return Qnil;  /* not reached, shut compiler up */
1850 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
1851        1, 3, 0,
1852        doc: /* Open a connection to a display server.
1853 DISPLAY is the name of the display to connect to.
1854 Optional second arg XRM-STRING is a string of resources in xrdb format.
1855 If the optional third arg MUST-SUCCEED is non-nil,
1856 terminate Emacs if we can't open the connection.
1857 (In the Nextstep version, the last two arguments are currently ignored.)  */)
1858      (Lisp_Object display, Lisp_Object resource_string, Lisp_Object must_succeed)
1860   struct ns_display_info *dpyinfo;
1862   CHECK_STRING (display);
1864   nxatoms_of_nsselect ();
1865   dpyinfo = ns_term_init (display);
1866   if (dpyinfo == 0)
1867     {
1868       if (!NILP (must_succeed))
1869         fatal ("Display on %s not responding.\n",
1870                SSDATA (display));
1871       else
1872         error ("Display on %s not responding.\n",
1873                SSDATA (display));
1874     }
1876   return Qnil;
1880 DEFUN ("x-close-connection", Fx_close_connection, Sx_close_connection,
1881        1, 1, 0,
1882        doc: /* Close the connection to TERMINAL's Nextstep display server.
1883 For TERMINAL, specify a terminal object, a frame or a display name (a
1884 string).  If TERMINAL is nil, that stands for the selected frame's
1885 terminal.  */)
1886      (Lisp_Object terminal)
1888   check_ns_display_info (terminal);
1889   [NSApp terminate: NSApp];
1890   return Qnil;
1894 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
1895        doc: /* Return the list of display names that Emacs has connections to.  */)
1896      (void)
1898   Lisp_Object result = Qnil;
1899   struct ns_display_info *ndi;
1901   for (ndi = x_display_list; ndi; ndi = ndi->next)
1902     result = Fcons (XCAR (ndi->name_list_element), result);
1904   return result;
1908 DEFUN ("ns-hide-others", Fns_hide_others, Sns_hide_others,
1909        0, 0, 0,
1910        doc: /* Hides all applications other than Emacs.  */)
1911      (void)
1913   check_window_system (NULL);
1914   [NSApp hideOtherApplications: NSApp];
1915   return Qnil;
1918 DEFUN ("ns-hide-emacs", Fns_hide_emacs, Sns_hide_emacs,
1919        1, 1, 0,
1920        doc: /* If ON is non-nil, the entire Emacs application is hidden.
1921 Otherwise if Emacs is hidden, it is unhidden.
1922 If ON is equal to `activate', Emacs is unhidden and becomes
1923 the active application.  */)
1924      (Lisp_Object on)
1926   check_window_system (NULL);
1927   if (EQ (on, intern ("activate")))
1928     {
1929       [NSApp unhide: NSApp];
1930       [NSApp activateIgnoringOtherApps: YES];
1931     }
1932   else if (NILP (on))
1933     [NSApp unhide: NSApp];
1934   else
1935     [NSApp hide: NSApp];
1936   return Qnil;
1940 DEFUN ("ns-emacs-info-panel", Fns_emacs_info_panel, Sns_emacs_info_panel,
1941        0, 0, 0,
1942        doc: /* Shows the 'Info' or 'About' panel for Emacs.  */)
1943      (void)
1945   check_window_system (NULL);
1946   [NSApp orderFrontStandardAboutPanel: nil];
1947   return Qnil;
1951 DEFUN ("ns-font-name", Fns_font_name, Sns_font_name, 1, 1, 0,
1952        doc: /* Determine font PostScript or family name for font NAME.
1953 NAME should be a string containing either the font name or an XLFD
1954 font descriptor.  If string contains `fontset' and not
1955 `fontset-startup', it is left alone. */)
1956      (Lisp_Object name)
1958   char *nm;
1959   CHECK_STRING (name);
1960   nm = SSDATA (name);
1962   if (nm[0] != '-')
1963     return name;
1964   if (strstr (nm, "fontset") && !strstr (nm, "fontset-startup"))
1965     return name;
1967   return build_string (ns_xlfd_to_fontname (SSDATA (name)));
1971 DEFUN ("ns-list-colors", Fns_list_colors, Sns_list_colors, 0, 1, 0,
1972        doc: /* Return a list of all available colors.
1973 The optional argument FRAME is currently ignored.  */)
1974      (Lisp_Object frame)
1976   Lisp_Object list = Qnil;
1977   NSEnumerator *colorlists;
1978   NSColorList *clist;
1980   if (!NILP (frame))
1981     {
1982       CHECK_FRAME (frame);
1983       if (! FRAME_NS_P (XFRAME (frame)))
1984         error ("non-Nextstep frame used in `ns-list-colors'");
1985     }
1987   block_input ();
1989   colorlists = [[NSColorList availableColorLists] objectEnumerator];
1990   while ((clist = [colorlists nextObject]))
1991     {
1992       if ([[clist name] length] < 7 ||
1993           [[clist name] rangeOfString: @"PANTONE"].location == 0)
1994         {
1995           NSEnumerator *cnames = [[clist allKeys] reverseObjectEnumerator];
1996           NSString *cname;
1997           while ((cname = [cnames nextObject]))
1998             list = Fcons (build_string ([cname UTF8String]), list);
1999 /*           for (i = [[clist allKeys] count] - 1; i >= 0; i--)
2000                list = Fcons (build_string ([[[clist allKeys] objectAtIndex: i]
2001                                              UTF8String]), list); */
2002         }
2003     }
2005   unblock_input ();
2007   return list;
2011 DEFUN ("ns-list-services", Fns_list_services, Sns_list_services, 0, 0, 0,
2012        doc: /* List available Nextstep services by querying NSApp.  */)
2013      (void)
2015 #ifdef NS_IMPL_COCOA
2016   /* You can't get services like this in 10.6+.  */
2017   return Qnil;
2018 #else
2019   Lisp_Object ret = Qnil;
2020   NSMenu *svcs;
2021 #ifdef NS_IMPL_COCOA
2022   id delegate;
2023 #endif
2025   check_window_system (NULL);
2026   svcs = [[NSMenu alloc] initWithTitle: @"Services"];
2027   [NSApp setServicesMenu: svcs];
2028   [NSApp registerServicesMenuSendTypes: ns_send_types
2029                            returnTypes: ns_return_types];
2031 /* On Tiger, services menu updating was made lazier (waits for user to
2032    actually click on the menu), so we have to force things along: */
2033 #ifdef NS_IMPL_COCOA
2034   delegate = [svcs delegate];
2035   if (delegate != nil)
2036     {
2037       if ([delegate respondsToSelector: @selector (menuNeedsUpdate:)])
2038         [delegate menuNeedsUpdate: svcs];
2039       if ([delegate respondsToSelector:
2040                        @selector (menu:updateItem:atIndex:shouldCancel:)])
2041         {
2042           int i, len = [delegate numberOfItemsInMenu: svcs];
2043           for (i =0; i<len; i++)
2044             [svcs addItemWithTitle: @"" action: NULL keyEquivalent: @""];
2045           for (i =0; i<len; i++)
2046             if (![delegate menu: svcs
2047                      updateItem: (NSMenuItem *)[svcs itemAtIndex: i]
2048                         atIndex: i shouldCancel: NO])
2049               break;
2050         }
2051     }
2052 #endif
2054   [svcs setAutoenablesItems: NO];
2055 #ifdef NS_IMPL_COCOA
2056   [svcs update]; /* on OS X, converts from '/' structure */
2057 #endif
2059   ret = interpret_services_menu (svcs, Qnil, ret);
2060   return ret;
2061 #endif
2065 DEFUN ("ns-perform-service", Fns_perform_service, Sns_perform_service,
2066        2, 2, 0,
2067        doc: /* Perform Nextstep SERVICE on SEND.
2068 SEND should be either a string or nil.
2069 The return value is the result of the service, as string, or nil if
2070 there was no result.  */)
2071      (Lisp_Object service, Lisp_Object send)
2073   id pb;
2074   NSString *svcName;
2075   char *utfStr;
2077   CHECK_STRING (service);
2078   check_window_system (NULL);
2080   utfStr = SSDATA (service);
2081   svcName = [NSString stringWithUTF8String: utfStr];
2083   pb =[NSPasteboard pasteboardWithUniqueName];
2084   ns_string_to_pasteboard (pb, send);
2086   if (NSPerformService (svcName, pb) == NO)
2087     Fsignal (Qquit, list1 (build_string ("service not available")));
2089   if ([[pb types] count] == 0)
2090     return build_string ("");
2091   return ns_string_from_pasteboard (pb);
2095 DEFUN ("ns-convert-utf8-nfd-to-nfc", Fns_convert_utf8_nfd_to_nfc,
2096        Sns_convert_utf8_nfd_to_nfc, 1, 1, 0,
2097        doc: /* Return an NFC string that matches the UTF-8 NFD string STR.  */)
2098      (Lisp_Object str)
2100 /* TODO: If GNUstep ever implements precomposedStringWithCanonicalMapping,
2101          remove this. */
2102   NSString *utfStr;
2103   Lisp_Object ret = Qnil;
2104   NSAutoreleasePool *pool;
2106   CHECK_STRING (str);
2107   pool = [[NSAutoreleasePool alloc] init];
2108   utfStr = [NSString stringWithUTF8String: SSDATA (str)];
2109 #ifdef NS_IMPL_COCOA
2110   if (utfStr)
2111     utfStr = [utfStr precomposedStringWithCanonicalMapping];
2112 #endif
2113   if (utfStr)
2114     {
2115       const char *cstr = [utfStr UTF8String];
2116       if (cstr)
2117         ret = build_string (cstr);
2118     }
2120   [pool release];
2121   if (NILP (ret))
2122     error ("Invalid UTF-8");
2124   return ret;
2128 #ifdef NS_IMPL_COCOA
2130 /* Compile and execute the AppleScript SCRIPT and return the error
2131    status as function value.  A zero is returned if compilation and
2132    execution is successful, in which case *RESULT is set to a Lisp
2133    string or a number containing the resulting script value.  Otherwise,
2134    1 is returned. */
2135 static int
2136 ns_do_applescript (Lisp_Object script, Lisp_Object *result)
2138   NSAppleEventDescriptor *desc;
2139   NSDictionary* errorDict;
2140   NSAppleEventDescriptor* returnDescriptor = NULL;
2142   NSAppleScript* scriptObject =
2143     [[NSAppleScript alloc] initWithSource:
2144                              [NSString stringWithUTF8String: SSDATA (script)]];
2146   returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
2147   [scriptObject release];
2148   *result = Qnil;
2150   if (returnDescriptor != NULL)
2151     {
2152       // successful execution
2153       if (kAENullEvent != [returnDescriptor descriptorType])
2154         {
2155           *result = Qt;
2156           // script returned an AppleScript result
2157           if ((typeUnicodeText == [returnDescriptor descriptorType]) ||
2158 #if defined (NS_IMPL_COCOA)
2159               (typeUTF16ExternalRepresentation
2160                == [returnDescriptor descriptorType]) ||
2161 #endif
2162               (typeUTF8Text == [returnDescriptor descriptorType]) ||
2163               (typeCString == [returnDescriptor descriptorType]))
2164             {
2165               desc = [returnDescriptor coerceToDescriptorType: typeUTF8Text];
2166               if (desc)
2167                 *result = build_string([[desc stringValue] UTF8String]);
2168             }
2169           else
2170             {
2171               /* use typeUTF16ExternalRepresentation? */
2172               // coerce the result to the appropriate ObjC type
2173               desc = [returnDescriptor coerceToDescriptorType: typeUTF8Text];
2174               if (desc)
2175                 *result = make_number([desc int32Value]);
2176             }
2177         }
2178     }
2179   else
2180     {
2181       // no script result, return error
2182       return 1;
2183     }
2184   return 0;
2187 /* Helper function called from sendEvent to run applescript
2188    from within the main event loop.  */
2190 void
2191 ns_run_ascript (void)
2193   if (! NILP (as_script))
2194     as_status = ns_do_applescript (as_script, as_result);
2195   as_script = Qnil;
2198 DEFUN ("ns-do-applescript", Fns_do_applescript, Sns_do_applescript, 1, 1, 0,
2199        doc: /* Execute AppleScript SCRIPT and return the result.
2200 If compilation and execution are successful, the resulting script value
2201 is returned as a string, a number or, in the case of other constructs, t.
2202 In case the execution fails, an error is signaled. */)
2203      (Lisp_Object script)
2205   Lisp_Object result;
2206   int status;
2207   NSEvent *nxev;
2208   struct input_event ev;
2210   CHECK_STRING (script);
2211   check_window_system (NULL);
2213   block_input ();
2215   as_script = script;
2216   as_result = &result;
2218   /* executing apple script requires the event loop to run, otherwise
2219      errors aren't returned and executeAndReturnError hangs forever.
2220      Post an event that runs applescript and then start the event loop.
2221      The event loop is exited when the script is done.  */
2222   nxev = [NSEvent otherEventWithType: NSApplicationDefined
2223                             location: NSMakePoint (0, 0)
2224                        modifierFlags: 0
2225                            timestamp: 0
2226                         windowNumber: [[NSApp mainWindow] windowNumber]
2227                              context: [NSApp context]
2228                              subtype: 0
2229                                data1: 0
2230                                data2: NSAPP_DATA2_RUNASSCRIPT];
2232   [NSApp postEvent: nxev atStart: NO];
2234   // If there are other events, the event loop may exit.  Keep running
2235   // until the script has been handled.  */
2236   ns_init_events (&ev);
2237   while (! NILP (as_script))
2238     [NSApp run];
2239   ns_finish_events ();
2241   status = as_status;
2242   as_status = 0;
2243   as_result = 0;
2244   unblock_input ();
2245   if (status == 0)
2246     return result;
2247   else if (!STRINGP (result))
2248     error ("AppleScript error %d", status);
2249   else
2250     error ("%s", SSDATA (result));
2252 #endif
2256 /* ==========================================================================
2258     Miscellaneous functions not called through hooks
2260    ========================================================================== */
2262 /* called from frame.c */
2263 struct ns_display_info *
2264 check_x_display_info (Lisp_Object frame)
2266   return check_ns_display_info (frame);
2270 void
2271 x_set_scroll_bar_default_width (struct frame *f)
2273   int wid = FRAME_COLUMN_WIDTH (f);
2274   FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = NS_SCROLL_BAR_WIDTH_DEFAULT;
2275   FRAME_CONFIG_SCROLL_BAR_COLS (f) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) +
2276                                       wid - 1) / wid;
2279 void
2280 x_set_scroll_bar_default_height (struct frame *f)
2282   int height = FRAME_LINE_HEIGHT (f);
2283   FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = NS_SCROLL_BAR_WIDTH_DEFAULT;
2284   FRAME_CONFIG_SCROLL_BAR_LINES (f) = (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) +
2285                                        height - 1) / height;
2288 /* terms impl this instead of x-get-resource directly */
2289 char *
2290 x_get_string_resource (XrmDatabase rdb, const char *name, const char *class)
2292   /* remove appname prefix; TODO: allow for !="Emacs" */
2293   const char *res, *toCheck = class + (!strncmp (class, "Emacs.", 6) ? 6 : 0);
2295   check_window_system (NULL);
2297   if (inhibit_x_resources)
2298     /* --quick was passed, so this is a no-op.  */
2299     return NULL;
2301   res = ns_get_defaults_value (toCheck);
2302   return (!res ? NULL :
2303           (!c_strncasecmp (res, "YES", 3) ? "true" :
2304            (!c_strncasecmp (res, "NO", 2) ? "false" : (char *) res)));
2308 Lisp_Object
2309 x_get_focus_frame (struct frame *frame)
2311   struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
2312   Lisp_Object nsfocus;
2314   if (!dpyinfo->x_focus_frame)
2315     return Qnil;
2317   XSETFRAME (nsfocus, dpyinfo->x_focus_frame);
2318   return nsfocus;
2321 /* ==========================================================================
2323     Lisp definitions that, for whatever reason, we can't alias as 'ns-XXX'.
2325    ========================================================================== */
2328 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
2329        doc: /* Internal function called by `color-defined-p', which see.
2330 (Note that the Nextstep version of this function ignores FRAME.)  */)
2331      (Lisp_Object color, Lisp_Object frame)
2333   NSColor * col;
2334   check_window_system (NULL);
2335   return ns_lisp_to_color (color, &col) ? Qnil : Qt;
2339 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
2340        doc: /* Internal function called by `color-values', which see.  */)
2341      (Lisp_Object color, Lisp_Object frame)
2343   NSColor * col;
2344   EmacsCGFloat red, green, blue, alpha;
2346   check_window_system (NULL);
2347   CHECK_STRING (color);
2349   block_input ();
2350   if (ns_lisp_to_color (color, &col))
2351     {
2352       unblock_input ();
2353       return Qnil;
2354     }
2356   [[col colorUsingDefaultColorSpace]
2357         getRed: &red green: &green blue: &blue alpha: &alpha];
2358   unblock_input ();
2359   return list3i (lrint (red * 65280), lrint (green * 65280),
2360                  lrint (blue * 65280));
2364 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
2365        doc: /* Internal function called by `display-color-p', which see.  */)
2366      (Lisp_Object terminal)
2368   NSWindowDepth depth;
2369   NSString *colorSpace;
2371   check_ns_display_info (terminal);
2372   depth = [[[NSScreen screens] objectAtIndex:0] depth];
2373   colorSpace = NSColorSpaceFromDepth (depth);
2375   return    [colorSpace isEqualToString: NSDeviceWhiteColorSpace]
2376          || [colorSpace isEqualToString: NSCalibratedWhiteColorSpace]
2377       ? Qnil : Qt;
2381 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
2382        0, 1, 0,
2383        doc: /* Return t if the Nextstep display supports shades of gray.
2384 Note that color displays do support shades of gray.
2385 The optional argument TERMINAL specifies which display to ask about.
2386 TERMINAL should be a terminal object, a frame or a display name (a string).
2387 If omitted or nil, that stands for the selected frame's display.  */)
2388   (Lisp_Object terminal)
2390   NSWindowDepth depth;
2392   check_ns_display_info (terminal);
2393   depth = [[[NSScreen screens] objectAtIndex:0] depth];
2395   return NSBitsPerPixelFromDepth (depth) > 1 ? Qt : Qnil;
2399 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
2400        0, 1, 0,
2401        doc: /* Return the width in pixels of the Nextstep display TERMINAL.
2402 The optional argument TERMINAL specifies which display to ask about.
2403 TERMINAL should be a terminal object, a frame or a display name (a string).
2404 If omitted or nil, that stands for the selected frame's display.
2406 On \"multi-monitor\" setups this refers to the pixel width for all
2407 physical monitors associated with TERMINAL.  To get information for
2408 each physical monitor, use `display-monitor-attributes-list'.  */)
2409   (Lisp_Object terminal)
2411   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
2413   return make_number (x_display_pixel_width (dpyinfo));
2417 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
2418        Sx_display_pixel_height, 0, 1, 0,
2419        doc: /* Return the height in pixels of the Nextstep display TERMINAL.
2420 The optional argument TERMINAL specifies which display to ask about.
2421 TERMINAL should be a terminal object, a frame or a display name (a string).
2422 If omitted or nil, that stands for the selected frame's display.
2424 On \"multi-monitor\" setups this refers to the pixel height for all
2425 physical monitors associated with TERMINAL.  To get information for
2426 each physical monitor, use `display-monitor-attributes-list'.  */)
2427   (Lisp_Object terminal)
2429   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
2431   return make_number (x_display_pixel_height (dpyinfo));
2434 #ifdef NS_IMPL_COCOA
2436 /* Returns the name for the screen that OBJ represents, or NULL.
2437    Caller must free return value.
2440 static char *
2441 ns_get_name_from_ioreg (io_object_t obj)
2443   char *name = NULL;
2445   NSDictionary *info = (NSDictionary *)
2446     IODisplayCreateInfoDictionary (obj, kIODisplayOnlyPreferredName);
2447   NSDictionary *names = [info objectForKey:
2448                                 [NSString stringWithUTF8String:
2449                                             kDisplayProductName]];
2451   if ([names count] > 0)
2452     {
2453       NSString *n = [names objectForKey: [[names allKeys]
2454                                                  objectAtIndex:0]];
2455       if (n != nil) name = xstrdup ([n UTF8String]);
2456     }
2458   [info release];
2460   return name;
2463 /* Returns the name for the screen that DID came from, or NULL.
2464    Caller must free return value.
2467 static char *
2468 ns_screen_name (CGDirectDisplayID did)
2470   char *name = NULL;
2472 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
2473   mach_port_t masterPort;
2474   io_iterator_t it;
2475   io_object_t obj;
2477   // CGDisplayIOServicePort is deprecated.  Do it another (harder) way.
2479   if (IOMasterPort (MACH_PORT_NULL, &masterPort) != kIOReturnSuccess
2480       || IOServiceGetMatchingServices (masterPort,
2481                                        IOServiceMatching ("IONDRVDevice"),
2482                                        &it) != kIOReturnSuccess)
2483     return name;
2485   /* Must loop until we find a name.  Many devices can have the same unit
2486      number (represents different GPU parts), but only one has a name.  */
2487   while (! name && (obj = IOIteratorNext (it)))
2488     {
2489       CFMutableDictionaryRef props;
2490       const void *val;
2492       if (IORegistryEntryCreateCFProperties (obj,
2493                                              &props,
2494                                              kCFAllocatorDefault,
2495                                              kNilOptions) == kIOReturnSuccess
2496           && props != nil
2497           && (val = CFDictionaryGetValue(props, @"IOFBDependentIndex")))
2498         {
2499           unsigned nr = [(NSNumber *)val unsignedIntegerValue];
2500           if (nr == CGDisplayUnitNumber (did))
2501             name = ns_get_name_from_ioreg (obj);
2502         }
2504       CFRelease (props);
2505       IOObjectRelease (obj);
2506     }
2508   IOObjectRelease (it);
2510 #else
2512   name = ns_get_name_from_ioreg (CGDisplayIOServicePort (did));
2514 #endif
2515   return name;
2517 #endif
2519 static Lisp_Object
2520 ns_make_monitor_attribute_list (struct MonitorInfo *monitors,
2521                                 int n_monitors,
2522                                 int primary_monitor,
2523                                 const char *source)
2525   Lisp_Object monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
2526   Lisp_Object frame, rest;
2527   NSArray *screens = [NSScreen screens];
2528   int i;
2530   FOR_EACH_FRAME (rest, frame)
2531     {
2532       struct frame *f = XFRAME (frame);
2534       if (FRAME_NS_P (f))
2535         {
2536           NSView *view = FRAME_NS_VIEW (f);
2537           NSScreen *screen = [[view window] screen];
2538           NSUInteger k;
2540           i = -1;
2541           for (k = 0; i == -1 && k < [screens count]; ++k)
2542             {
2543               if ([screens objectAtIndex: k] == screen)
2544                 i = (int)k;
2545             }
2547           if (i > -1)
2548             ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
2549         }
2550     }
2552   return make_monitor_attribute_list (monitors, n_monitors, primary_monitor,
2553                                       monitor_frames, source);
2556 DEFUN ("ns-display-monitor-attributes-list",
2557        Fns_display_monitor_attributes_list,
2558        Sns_display_monitor_attributes_list,
2559        0, 1, 0,
2560        doc: /* Return a list of physical monitor attributes on the X display TERMINAL.
2562 The optional argument TERMINAL specifies which display to ask about.
2563 TERMINAL should be a terminal object, a frame or a display name (a string).
2564 If omitted or nil, that stands for the selected frame's display.
2566 In addition to the standard attribute keys listed in
2567 `display-monitor-attributes-list', the following keys are contained in
2568 the attributes:
2570  source -- String describing the source from which multi-monitor
2571            information is obtained, \"NS\" is always the source."
2573 Internal use only, use `display-monitor-attributes-list' instead.  */)
2574   (Lisp_Object terminal)
2576   struct terminal *term = decode_live_terminal (terminal);
2577   NSArray *screens;
2578   NSUInteger i, n_monitors;
2579   struct MonitorInfo *monitors;
2580   Lisp_Object attributes_list = Qnil;
2581   CGFloat primary_display_height = 0;
2583   if (term->type != output_ns)
2584     return Qnil;
2586   screens = [NSScreen screens];
2587   n_monitors = [screens count];
2588   if (n_monitors == 0)
2589     return Qnil;
2591   monitors = xzalloc (n_monitors * sizeof *monitors);
2593   for (i = 0; i < [screens count]; ++i)
2594     {
2595       NSScreen *s = [screens objectAtIndex:i];
2596       struct MonitorInfo *m = &monitors[i];
2597       NSRect fr = [s frame];
2598       NSRect vfr = [s visibleFrame];
2599       short y, vy;
2601 #ifdef NS_IMPL_COCOA
2602       NSDictionary *dict = [s deviceDescription];
2603       NSNumber *nid = [dict objectForKey:@"NSScreenNumber"];
2604       CGDirectDisplayID did = [nid unsignedIntValue];
2605 #endif
2606       if (i == 0)
2607         {
2608           primary_display_height = fr.size.height;
2609           y = (short) fr.origin.y;
2610           vy = (short) vfr.origin.y;
2611         }
2612       else
2613         {
2614           // Flip y coordinate as NS has y starting from the bottom.
2615           y = (short) (primary_display_height - fr.size.height - fr.origin.y);
2616           vy = (short) (primary_display_height -
2617                         vfr.size.height - vfr.origin.y);
2618         }
2620       m->geom.x = (short) fr.origin.x;
2621       m->geom.y = y;
2622       m->geom.width = (unsigned short) fr.size.width;
2623       m->geom.height = (unsigned short) fr.size.height;
2625       m->work.x = (short) vfr.origin.x;
2626       // y is flipped on NS, so vy - y are pixels missing at the bottom,
2627       // and fr.size.height - vfr.size.height are pixels missing in total.
2628       // Pixels missing at top are
2629       // fr.size.height - vfr.size.height - vy + y.
2630       // work.y is then pixels missing at top + y.
2631       m->work.y = (short) (fr.size.height - vfr.size.height) - vy + y + y;
2632       m->work.width = (unsigned short) vfr.size.width;
2633       m->work.height = (unsigned short) vfr.size.height;
2635 #ifdef NS_IMPL_COCOA
2636       m->name = ns_screen_name (did);
2638       {
2639         CGSize mms = CGDisplayScreenSize (did);
2640         m->mm_width = (int) mms.width;
2641         m->mm_height = (int) mms.height;
2642       }
2644 #else
2645       // Assume 92 dpi as x-display-mm-height/x-display-mm-width does.
2646       m->mm_width = (int) (25.4 * fr.size.width / 92.0);
2647       m->mm_height = (int) (25.4 * fr.size.height / 92.0);
2648 #endif
2649     }
2651   // Primary monitor is always first for NS.
2652   attributes_list = ns_make_monitor_attribute_list (monitors, n_monitors,
2653                                                     0, "NS");
2655   free_monitors (monitors, n_monitors);
2656   return attributes_list;
2660 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
2661        0, 1, 0,
2662        doc: /* Return the number of bitplanes of the Nextstep display TERMINAL.
2663 The optional argument TERMINAL specifies which display to ask about.
2664 TERMINAL should be a terminal object, a frame or a display name (a string).
2665 If omitted or nil, that stands for the selected frame's display.  */)
2666   (Lisp_Object terminal)
2668   check_ns_display_info (terminal);
2669   return make_number
2670     (NSBitsPerPixelFromDepth ([[[NSScreen screens] objectAtIndex:0] depth]));
2674 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
2675        0, 1, 0,
2676        doc: /* Returns the number of color cells of the Nextstep display TERMINAL.
2677 The optional argument TERMINAL specifies which display to ask about.
2678 TERMINAL should be a terminal object, a frame or a display name (a string).
2679 If omitted or nil, that stands for the selected frame's display.  */)
2680   (Lisp_Object terminal)
2682   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
2683   /* We force 24+ bit depths to 24-bit to prevent an overflow.  */
2684   return make_number (1 << min (dpyinfo->n_planes, 24));
2688 /* Unused dummy def needed for compatibility. */
2689 Lisp_Object tip_frame;
2691 /* TODO: move to xdisp or similar */
2692 static void
2693 compute_tip_xy (struct frame *f,
2694                 Lisp_Object parms,
2695                 Lisp_Object dx,
2696                 Lisp_Object dy,
2697                 int width,
2698                 int height,
2699                 int *root_x,
2700                 int *root_y)
2702   Lisp_Object left, top, right, bottom;
2703   EmacsView *view = FRAME_NS_VIEW (f);
2704   struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2705   NSPoint pt;
2707   /* Start with user-specified or mouse position.  */
2708   left = Fcdr (Fassq (Qleft, parms));
2709   top = Fcdr (Fassq (Qtop, parms));
2710   right = Fcdr (Fassq (Qright, parms));
2711   bottom = Fcdr (Fassq (Qbottom, parms));
2713   if ((!INTEGERP (left) && !INTEGERP (right))
2714       || (!INTEGERP (top) && !INTEGERP (bottom)))
2715     {
2716       pt.x = dpyinfo->last_mouse_motion_x;
2717       pt.y = dpyinfo->last_mouse_motion_y;
2718       /* Convert to screen coordinates */
2719       pt = [view convertPoint: pt toView: nil];
2720 #if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
2721       pt = [[view window] convertBaseToScreen: pt];
2722 #else
2723       {
2724         NSRect r = NSMakeRect (pt.x, pt.y, 0, 0);
2725         r = [[view window] convertRectToScreen: r];
2726         pt.x = r.origin.x;
2727         pt.y = r.origin.y;
2728       }
2729 #endif
2730     }
2731   else
2732     {
2733       /* Absolute coordinates.  */
2734       pt.x = INTEGERP (left) ? XINT (left) : XINT (right);
2735       pt.y = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
2736               - (INTEGERP (top) ? XINT (top) : XINT (bottom))
2737               - height);
2738     }
2740   /* Ensure in bounds.  (Note, screen origin = lower left.) */
2741   if (INTEGERP (left) || INTEGERP (right))
2742     *root_x = pt.x;
2743   else if (pt.x + XINT (dx) <= 0)
2744     *root_x = 0; /* Can happen for negative dx */
2745   else if (pt.x + XINT (dx) + width
2746            <= x_display_pixel_width (FRAME_DISPLAY_INFO (f)))
2747     /* It fits to the right of the pointer.  */
2748     *root_x = pt.x + XINT (dx);
2749   else if (width + XINT (dx) <= pt.x)
2750     /* It fits to the left of the pointer.  */
2751     *root_x = pt.x - width - XINT (dx);
2752   else
2753     /* Put it left justified on the screen -- it ought to fit that way.  */
2754     *root_x = 0;
2756   if (INTEGERP (top) || INTEGERP (bottom))
2757     *root_y = pt.y;
2758   else if (pt.y - XINT (dy) - height >= 0)
2759     /* It fits below the pointer.  */
2760     *root_y = pt.y - height - XINT (dy);
2761   else if (pt.y + XINT (dy) + height
2762            <= x_display_pixel_height (FRAME_DISPLAY_INFO (f)))
2763     /* It fits above the pointer */
2764       *root_y = pt.y + XINT (dy);
2765   else
2766     /* Put it on the top.  */
2767     *root_y = x_display_pixel_height (FRAME_DISPLAY_INFO (f)) - height;
2771 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
2772        doc: /* Show STRING in a \"tooltip\" window on frame FRAME.
2773 A tooltip window is a small window displaying a string.
2775 This is an internal function; Lisp code should call `tooltip-show'.
2777 FRAME nil or omitted means use the selected frame.
2779 PARMS is an optional list of frame parameters which can be used to
2780 change the tooltip's appearance.
2782 Automatically hide the tooltip after TIMEOUT seconds.  TIMEOUT nil
2783 means use the default timeout of 5 seconds.
2785 If the list of frame parameters PARMS contains a `left' parameter,
2786 display the tooltip at that x-position.  If the list of frame parameters
2787 PARMS contains no `left' but a `right' parameter, display the tooltip
2788 right-adjusted at that x-position. Otherwise display it at the
2789 x-position of the mouse, with offset DX added (default is 5 if DX isn't
2790 specified).
2792 Likewise for the y-position: If a `top' frame parameter is specified, it
2793 determines the position of the upper edge of the tooltip window.  If a
2794 `bottom' parameter but no `top' frame parameter is specified, it
2795 determines the position of the lower edge of the tooltip window.
2796 Otherwise display the tooltip window at the y-position of the mouse,
2797 with offset DY added (default is -10).
2799 A tooltip's maximum size is specified by `x-max-tooltip-size'.
2800 Text larger than the specified size is clipped.  */)
2801      (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
2803   int root_x, root_y;
2804   ptrdiff_t count = SPECPDL_INDEX ();
2805   struct frame *f;
2806   char *str;
2807   NSSize size;
2809   specbind (Qinhibit_redisplay, Qt);
2811   CHECK_STRING (string);
2812   str = SSDATA (string);
2813   f = decode_window_system_frame (frame);
2814   if (NILP (timeout))
2815     timeout = make_number (5);
2816   else
2817     CHECK_NATNUM (timeout);
2819   if (NILP (dx))
2820     dx = make_number (5);
2821   else
2822     CHECK_NUMBER (dx);
2824   if (NILP (dy))
2825     dy = make_number (-10);
2826   else
2827     CHECK_NUMBER (dy);
2829   block_input ();
2830   if (ns_tooltip == nil)
2831     ns_tooltip = [[EmacsTooltip alloc] init];
2832   else
2833     Fx_hide_tip ();
2835   [ns_tooltip setText: str];
2836   size = [ns_tooltip frame].size;
2838   /* Move the tooltip window where the mouse pointer is.  Resize and
2839      show it.  */
2840   compute_tip_xy (f, parms, dx, dy, (int)size.width, (int)size.height,
2841                   &root_x, &root_y);
2843   [ns_tooltip showAtX: root_x Y: root_y for: XINT (timeout)];
2844   unblock_input ();
2846   return unbind_to (count, Qnil);
2850 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
2851        doc: /* Hide the current tooltip window, if there is any.
2852 Value is t if tooltip was open, nil otherwise.  */)
2853      (void)
2855   if (ns_tooltip == nil || ![ns_tooltip isActive])
2856     return Qnil;
2857   [ns_tooltip hide];
2858   return Qt;
2861 /* Return geometric attributes of FRAME.  According to the value of
2862    ATTRIBUTES return the outer edges of FRAME (Qouter_edges), the inner
2863    edges of FRAME, the root window edges of frame (Qroot_edges).  Any
2864    other value means to return the geometry as returned by
2865    Fx_frame_geometry.  */
2866 static Lisp_Object
2867 frame_geometry (Lisp_Object frame, Lisp_Object attribute)
2869   struct frame *f = decode_live_frame (frame);
2870   Lisp_Object fullscreen_symbol = Fframe_parameter (frame, Qfullscreen);
2871   bool fullscreen = (EQ (fullscreen_symbol, Qfullboth)
2872                      || EQ (fullscreen_symbol, Qfullscreen));
2873   int border = fullscreen ? 0 : f->border_width;
2874   int title_height = fullscreen ? 0 : FRAME_NS_TITLEBAR_HEIGHT (f);
2875   int native_width = FRAME_PIXEL_WIDTH (f);
2876   int native_height = FRAME_PIXEL_HEIGHT (f);
2877   int outer_width = native_width + 2 * border;
2878   int outer_height = native_height + 2 * border + title_height;
2879   int native_left = f->left_pos + border;
2880   int native_top = f->top_pos + border + title_height;
2881   int native_right = f->left_pos + outer_width - border;
2882   int native_bottom = f->top_pos + outer_height - border;
2883   int internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
2884   int tool_bar_height = FRAME_TOOLBAR_HEIGHT (f);
2885   int tool_bar_width = (tool_bar_height
2886                         ? outer_width - 2 * internal_border_width
2887                         : 0);
2889   /* Construct list.  */
2890   if (EQ (attribute, Qouter_edges))
2891     return list4 (make_number (f->left_pos), make_number (f->top_pos),
2892                   make_number (f->left_pos + outer_width),
2893                   make_number (f->top_pos + outer_height));
2894   else if (EQ (attribute, Qnative_edges))
2895     return list4 (make_number (native_left), make_number (native_top),
2896                   make_number (native_right), make_number (native_bottom));
2897   else if (EQ (attribute, Qinner_edges))
2898     return list4 (make_number (native_left + internal_border_width),
2899                   make_number (native_top
2900                                + tool_bar_height
2901                                + internal_border_width),
2902                   make_number (native_right - internal_border_width),
2903                   make_number (native_bottom - internal_border_width));
2904   else
2905     return
2906       listn (CONSTYPE_HEAP, 10,
2907              Fcons (Qouter_position,
2908                     Fcons (make_number (f->left_pos),
2909                            make_number (f->top_pos))),
2910              Fcons (Qouter_size,
2911                     Fcons (make_number (outer_width),
2912                            make_number (outer_height))),
2913              Fcons (Qexternal_border_size,
2914                     (fullscreen
2915                      ? Fcons (make_number (0), make_number (0))
2916                      : Fcons (make_number (border), make_number (border)))),
2917              Fcons (Qtitle_bar_size,
2918                     Fcons (make_number (0), make_number (title_height))),
2919              Fcons (Qmenu_bar_external, Qnil),
2920              Fcons (Qmenu_bar_size, Fcons (make_number (0), make_number (0))),
2921              Fcons (Qtool_bar_external,
2922                     FRAME_EXTERNAL_TOOL_BAR (f) ? Qt : Qnil),
2923              Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)),
2924              Fcons (Qtool_bar_size,
2925                     Fcons (make_number (tool_bar_width),
2926                            make_number (tool_bar_height))),
2927              Fcons (Qinternal_border_width,
2928                     make_number (internal_border_width)));
2931 DEFUN ("ns-frame-geometry", Fns_frame_geometry, Sns_frame_geometry, 0, 1, 0,
2932        doc: /* Return geometric attributes of FRAME.
2933 FRAME must be a live frame and defaults to the selected one.  The return
2934 value is an association list of the attributes listed below.  All height
2935 and width values are in pixels.
2937 `outer-position' is a cons of the outer left and top edges of FRAME
2938   relative to the origin - the position (0, 0) - of FRAME's display.
2940 `outer-size' is a cons of the outer width and height of FRAME.  The
2941   outer size includes the title bar and the external borders as well as
2942   any menu and/or tool bar of frame.
2944 `external-border-size' is a cons of the horizontal and vertical width of
2945   FRAME's external borders as supplied by the window manager.
2947 `title-bar-size' is a cons of the width and height of the title bar of
2948   FRAME as supplied by the window manager.  If both of them are zero,
2949   FRAME has no title bar.  If only the width is zero, Emacs was not
2950   able to retrieve the width information.
2952 `menu-bar-external', if non-nil, means the menu bar is external (never
2953   included in the inner edges of FRAME).
2955 `menu-bar-size' is a cons of the width and height of the menu bar of
2956   FRAME.
2958 `tool-bar-external', if non-nil, means the tool bar is external (never
2959   included in the inner edges of FRAME).
2961 `tool-bar-position' tells on which side the tool bar on FRAME is and can
2962   be one of `left', `top', `right' or `bottom'.  If this is nil, FRAME
2963   has no tool bar.
2965 `tool-bar-size' is a cons of the width and height of the tool bar of
2966   FRAME.
2968 `internal-border-width' is the width of the internal border of
2969   FRAME.  */)
2970   (Lisp_Object frame)
2972   return frame_geometry (frame, Qnil);
2975 DEFUN ("ns-frame-edges", Fns_frame_edges, Sns_frame_edges, 0, 2, 0,
2976        doc: /* Return edge coordinates of FRAME.
2977 FRAME must be a live frame and defaults to the selected one.  The return
2978 value is a list of the form (LEFT, TOP, RIGHT, BOTTOM).  All values are
2979 in pixels relative to the origin - the position (0, 0) - of FRAME's
2980 display.
2982 If optional argument TYPE is the symbol `outer-edges', return the outer
2983 edges of FRAME.  The outer edges comprise the decorations of the window
2984 manager (like the title bar or external borders) as well as any external
2985 menu or tool bar of FRAME.  If optional argument TYPE is the symbol
2986 `native-edges' or nil, return the native edges of FRAME.  The native
2987 edges exclude the decorations of the window manager and any external
2988 menu or tool bar of FRAME.  If TYPE is the symbol `inner-edges', return
2989 the inner edges of FRAME.  These edges exclude title bar, any borders,
2990 menu bar or tool bar of FRAME.  */)
2991   (Lisp_Object frame, Lisp_Object type)
2993   return frame_geometry (frame, ((EQ (type, Qouter_edges)
2994                                   || EQ (type, Qinner_edges))
2995                                  ? type
2996                                  : Qnative_edges));
2999 /* ==========================================================================
3001     Class implementations
3003    ========================================================================== */
3006   Handle arrow/function/control keys and copy/paste/cut in file dialogs.
3007   Return YES if handled, NO if not.
3008  */
3009 static BOOL
3010 handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent)
3012   NSString *s;
3013   int i;
3014   BOOL ret = NO;
3016   if ([theEvent type] != NSKeyDown) return NO;
3017   s = [theEvent characters];
3019   for (i = 0; i < [s length]; ++i)
3020     {
3021       int ch = (int) [s characterAtIndex: i];
3022       switch (ch)
3023         {
3024         case NSHomeFunctionKey:
3025         case NSDownArrowFunctionKey:
3026         case NSUpArrowFunctionKey:
3027         case NSLeftArrowFunctionKey:
3028         case NSRightArrowFunctionKey:
3029         case NSPageUpFunctionKey:
3030         case NSPageDownFunctionKey:
3031         case NSEndFunctionKey:
3032           /* Don't send command modified keys, as those are handled in the
3033              performKeyEquivalent method of the super class.
3034           */
3035           if (! ([theEvent modifierFlags] & NSCommandKeyMask))
3036             {
3037               [panel sendEvent: theEvent];
3038               ret = YES;
3039             }
3040           break;
3041           /* As we don't have the standard key commands for
3042              copy/paste/cut/select-all in our edit menu, we must handle
3043              them here.  TODO: handle Emacs key bindings for copy/cut/select-all
3044              here, paste works, because we have that in our Edit menu.
3045              I.e. refactor out code in nsterm.m, keyDown: to figure out the
3046              correct modifier.
3047           */
3048         case 'x': // Cut
3049         case 'c': // Copy
3050         case 'v': // Paste
3051         case 'a': // Select all
3052           if ([theEvent modifierFlags] & NSCommandKeyMask)
3053             {
3054               [NSApp sendAction:
3055                        (ch == 'x'
3056                         ? @selector(cut:)
3057                         : (ch == 'c'
3058                            ? @selector(copy:)
3059                            : (ch == 'v'
3060                               ? @selector(paste:)
3061                               : @selector(selectAll:))))
3062                              to:nil from:panel];
3063               ret = YES;
3064             }
3065         default:
3066           // Send all control keys, as the text field supports C-a, C-f, C-e
3067           // C-b and more.
3068           if ([theEvent modifierFlags] & NSControlKeyMask)
3069             {
3070               [panel sendEvent: theEvent];
3071               ret = YES;
3072             }
3073           break;
3074         }
3075     }
3078   return ret;
3081 @implementation EmacsSavePanel
3082 - (BOOL)performKeyEquivalent:(NSEvent *)theEvent
3084   BOOL ret = handlePanelKeys (self, theEvent);
3085   if (! ret)
3086     ret = [super performKeyEquivalent:theEvent];
3087   return ret;
3089 @end
3092 @implementation EmacsOpenPanel
3093 - (BOOL)performKeyEquivalent:(NSEvent *)theEvent
3095   // NSOpenPanel inherits NSSavePanel, so passing self is OK.
3096   BOOL ret = handlePanelKeys (self, theEvent);
3097   if (! ret)
3098     ret = [super performKeyEquivalent:theEvent];
3099   return ret;
3101 @end
3104 @implementation EmacsFileDelegate
3105 /* --------------------------------------------------------------------------
3106    Delegate methods for Open/Save panels
3107    -------------------------------------------------------------------------- */
3108 - (BOOL)panel: (id)sender isValidFilename: (NSString *)filename
3110   return YES;
3112 - (BOOL)panel: (id)sender shouldShowFilename: (NSString *)filename
3114   return YES;
3116 - (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename
3117           confirmed: (BOOL)okFlag
3119   return filename;
3121 @end
3123 #endif
3126 /* ==========================================================================
3128     Lisp interface declaration
3130    ========================================================================== */
3133 void
3134 syms_of_nsfns (void)
3136   DEFSYM (Qfontsize, "fontsize");
3138   DEFVAR_LISP ("ns-icon-type-alist", Vns_icon_type_alist,
3139                doc: /* Alist of elements (REGEXP . IMAGE) for images of icons associated to frames.
3140 If the title of a frame matches REGEXP, then IMAGE.tiff is
3141 selected as the image of the icon representing the frame when it's
3142 miniaturized.  If an element is t, then Emacs tries to select an icon
3143 based on the filetype of the visited file.
3145 The images have to be installed in a folder called English.lproj in the
3146 Emacs folder.  You have to restart Emacs after installing new icons.
3148 Example: Install an icon Gnus.tiff and execute the following code
3150   (setq ns-icon-type-alist
3151         (append ns-icon-type-alist
3152                 '((\"^\\\\*\\\\(Group\\\\*$\\\\|Summary \\\\|Article\\\\*$\\\\)\"
3153                    . \"Gnus\"))))
3155 When you miniaturize a Group, Summary or Article frame, Gnus.tiff will
3156 be used as the image of the icon representing the frame.  */);
3157   Vns_icon_type_alist = list1 (Qt);
3159   DEFVAR_LISP ("ns-version-string", Vns_version_string,
3160                doc: /* Toolkit version for NS Windowing.  */);
3161   Vns_version_string = ns_appkit_version_str ();
3163   defsubr (&Sns_read_file_name);
3164   defsubr (&Sns_get_resource);
3165   defsubr (&Sns_set_resource);
3166   defsubr (&Sxw_display_color_p); /* this and next called directly by C code */
3167   defsubr (&Sx_display_grayscale_p);
3168   defsubr (&Sns_font_name);
3169   defsubr (&Sns_list_colors);
3170 #ifdef NS_IMPL_COCOA
3171   defsubr (&Sns_do_applescript);
3172 #endif
3173   defsubr (&Sxw_color_defined_p);
3174   defsubr (&Sxw_color_values);
3175   defsubr (&Sx_server_max_request_size);
3176   defsubr (&Sx_server_vendor);
3177   defsubr (&Sx_server_version);
3178   defsubr (&Sx_display_pixel_width);
3179   defsubr (&Sx_display_pixel_height);
3180   defsubr (&Sns_display_monitor_attributes_list);
3181   defsubr (&Sns_frame_geometry);
3182   defsubr (&Sns_frame_edges);
3183   defsubr (&Sx_display_mm_width);
3184   defsubr (&Sx_display_mm_height);
3185   defsubr (&Sx_display_screens);
3186   defsubr (&Sx_display_planes);
3187   defsubr (&Sx_display_color_cells);
3188   defsubr (&Sx_display_visual_class);
3189   defsubr (&Sx_display_backing_store);
3190   defsubr (&Sx_display_save_under);
3191   defsubr (&Sx_create_frame);
3192   defsubr (&Sx_open_connection);
3193   defsubr (&Sx_close_connection);
3194   defsubr (&Sx_display_list);
3196   defsubr (&Sns_hide_others);
3197   defsubr (&Sns_hide_emacs);
3198   defsubr (&Sns_emacs_info_panel);
3199   defsubr (&Sns_list_services);
3200   defsubr (&Sns_perform_service);
3201   defsubr (&Sns_convert_utf8_nfd_to_nfc);
3202   defsubr (&Sns_popup_font_panel);
3203   defsubr (&Sns_popup_color_panel);
3205   defsubr (&Sx_show_tip);
3206   defsubr (&Sx_hide_tip);
3208   as_status = 0;
3209   as_script = Qnil;
3210   as_result = 0;