* lisp/emacs-lisp/cl-generic.el: Accomodate future changes
[emacs.git] / src / nsfns.m
blobc24344436adc189a35c102cbeacf48c2e2e5a4b9
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   int nlines;
653   if (FRAME_MINIBUF_ONLY_P (f))
654     return;
656   if (RANGED_INTEGERP (0, value, INT_MAX))
657     nlines = XFASTINT (value);
658   else
659     nlines = 0;
661   if (nlines)
662     {
663       FRAME_EXTERNAL_TOOL_BAR (f) = 1;
664       update_frame_tool_bar (f);
665     }
666   else
667     {
668       if (FRAME_EXTERNAL_TOOL_BAR (f))
669         {
670           free_frame_tool_bar (f);
671           FRAME_EXTERNAL_TOOL_BAR (f) = 0;
672         }
673     }
675   {
676     int inhibit
677       = ((f->after_make_frame
678           && !f->tool_bar_resized
679           && (EQ (frame_inhibit_implied_resize, Qt)
680               || (CONSP (frame_inhibit_implied_resize)
681                   && !NILP (Fmemq (Qtool_bar_lines,
682                                    frame_inhibit_implied_resize))))
683           /* This will probably fail to DTRT in the
684              fullheight/-width cases.  */
685           && NILP (get_frame_param (f, Qfullscreen)))
686          ? 0
687          : 2);
689     frame_size_history_add (f, Qupdate_frame_tool_bar, 0, 0, Qnil);
690     adjust_frame_size (f, -1, -1, inhibit, 0, Qtool_bar_lines);
691   }
695 void
696 x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
698   int old_width = FRAME_INTERNAL_BORDER_WIDTH (f);
700   CHECK_TYPE_RANGED_INTEGER (int, arg);
701   FRAME_INTERNAL_BORDER_WIDTH (f) = XINT (arg);
702   if (FRAME_INTERNAL_BORDER_WIDTH (f) < 0)
703     FRAME_INTERNAL_BORDER_WIDTH (f) = 0;
705   if (FRAME_INTERNAL_BORDER_WIDTH (f) == old_width)
706     return;
708   if (FRAME_X_WINDOW (f) != 0)
709     adjust_frame_size (f, -1, -1, 3, 0, Qinternal_border_width);
711   SET_FRAME_GARBAGED (f);
715 static void
716 ns_implicitly_set_icon_type (struct frame *f)
718   Lisp_Object tem;
719   EmacsView *view = FRAME_NS_VIEW (f);
720   id image = nil;
721   Lisp_Object chain, elt;
722   NSAutoreleasePool *pool;
723   BOOL setMini = YES;
725   NSTRACE ("ns_implicitly_set_icon_type");
727   block_input ();
728   pool = [[NSAutoreleasePool alloc] init];
729   if (f->output_data.ns->miniimage
730       && [[NSString stringWithUTF8String: SSDATA (f->name)]
731                isEqualToString: [(NSImage *)f->output_data.ns->miniimage name]])
732     {
733       [pool release];
734       unblock_input ();
735       return;
736     }
738   tem = assq_no_quit (Qicon_type, f->param_alist);
739   if (CONSP (tem) && ! NILP (XCDR (tem)))
740     {
741       [pool release];
742       unblock_input ();
743       return;
744     }
746   for (chain = Vns_icon_type_alist;
747        image == nil && CONSP (chain);
748        chain = XCDR (chain))
749     {
750       elt = XCAR (chain);
751       /* special case: t means go by file type */
752       if (SYMBOLP (elt) && EQ (elt, Qt) && SSDATA (f->name)[0] == '/')
753         {
754           NSString *str
755              = [NSString stringWithUTF8String: SSDATA (f->name)];
756           if ([[NSFileManager defaultManager] fileExistsAtPath: str])
757             image = [[[NSWorkspace sharedWorkspace] iconForFile: str] retain];
758         }
759       else if (CONSP (elt) &&
760                STRINGP (XCAR (elt)) &&
761                STRINGP (XCDR (elt)) &&
762                fast_string_match (XCAR (elt), f->name) >= 0)
763         {
764           image = [EmacsImage allocInitFromFile: XCDR (elt)];
765           if (image == nil)
766             image = [[NSImage imageNamed:
767                                [NSString stringWithUTF8String:
768                                             SSDATA (XCDR (elt))]] retain];
769         }
770     }
772   if (image == nil)
773     {
774       image = [[[NSWorkspace sharedWorkspace] iconForFileType: @"text"] retain];
775       setMini = NO;
776     }
778   [f->output_data.ns->miniimage release];
779   f->output_data.ns->miniimage = image;
780   [view setMiniwindowImage: setMini];
781   [pool release];
782   unblock_input ();
786 static void
787 x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
789   EmacsView *view = FRAME_NS_VIEW (f);
790   id image = nil;
791   BOOL setMini = YES;
793   NSTRACE ("x_set_icon_type");
795   if (!NILP (arg) && SYMBOLP (arg))
796     {
797       arg =build_string (SSDATA (SYMBOL_NAME (arg)));
798       store_frame_param (f, Qicon_type, arg);
799     }
801   /* do it the implicit way */
802   if (NILP (arg))
803     {
804       ns_implicitly_set_icon_type (f);
805       return;
806     }
808   CHECK_STRING (arg);
810   image = [EmacsImage allocInitFromFile: arg];
811   if (image == nil)
812     image =[NSImage imageNamed: [NSString stringWithUTF8String:
813                                             SSDATA (arg)]];
815   if (image == nil)
816     {
817       image = [NSImage imageNamed: @"text"];
818       setMini = NO;
819     }
821   f->output_data.ns->miniimage = image;
822   [view setMiniwindowImage: setMini];
826 /* TODO: move to nsterm? */
828 ns_lisp_to_cursor_type (Lisp_Object arg)
830   char *str;
831   if (XTYPE (arg) == Lisp_String)
832     str = SSDATA (arg);
833   else if (XTYPE (arg) == Lisp_Symbol)
834     str = SSDATA (SYMBOL_NAME (arg));
835   else return -1;
836   if (!strcmp (str, "box"))     return FILLED_BOX_CURSOR;
837   if (!strcmp (str, "hollow"))  return HOLLOW_BOX_CURSOR;
838   if (!strcmp (str, "hbar"))    return HBAR_CURSOR;
839   if (!strcmp (str, "bar"))     return BAR_CURSOR;
840   if (!strcmp (str, "no"))      return NO_CURSOR;
841   return -1;
845 Lisp_Object
846 ns_cursor_type_to_lisp (int arg)
848   switch (arg)
849     {
850     case FILLED_BOX_CURSOR: return Qbox;
851     case HOLLOW_BOX_CURSOR: return Qhollow;
852     case HBAR_CURSOR:       return Qhbar;
853     case BAR_CURSOR:        return Qbar;
854     case NO_CURSOR:
855     default:                return intern ("no");
856     }
859 /* This is the same as the xfns.c definition.  */
860 static void
861 x_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
863   set_frame_cursor_types (f, arg);
866 /* called to set mouse pointer color, but all other terms use it to
867    initialize pointer types (and don't set the color ;) */
868 static void
869 x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
871   /* don't think we can do this on Nextstep */
875 #define Str(x) #x
876 #define Xstr(x) Str(x)
878 static Lisp_Object
879 ns_appkit_version_str (void)
881   char tmp[256];
883 #ifdef NS_IMPL_GNUSTEP
884   sprintf(tmp, "gnustep-gui-%s", Xstr(GNUSTEP_GUI_VERSION));
885 #elif defined (NS_IMPL_COCOA)
886   NSString *osversion
887     = [[NSProcessInfo processInfo] operatingSystemVersionString];
888   sprintf(tmp, "appkit-%.2f %s",
889           NSAppKitVersionNumber,
890           [osversion UTF8String]);
891 #else
892   tmp = "ns-unknown";
893 #endif
894   return build_string (tmp);
898 /* This is for use by x-server-version and collapses all version info we
899    have into a single int.  For a better picture of the implementation
900    running, use ns_appkit_version_str.*/
901 static int
902 ns_appkit_version_int (void)
904 #ifdef NS_IMPL_GNUSTEP
905   return GNUSTEP_GUI_MAJOR_VERSION * 100 + GNUSTEP_GUI_MINOR_VERSION;
906 #elif defined (NS_IMPL_COCOA)
907   return (int)NSAppKitVersionNumber;
908 #endif
909   return 0;
913 static void
914 x_icon (struct frame *f, Lisp_Object parms)
915 /* --------------------------------------------------------------------------
916    Strangely-named function to set icon position parameters in frame.
917    This is irrelevant under OS X, but might be needed under GNUstep,
918    depending on the window manager used.  Note, this is not a standard
919    frame parameter-setter; it is called directly from x-create-frame.
920    -------------------------------------------------------------------------- */
922   Lisp_Object icon_x, icon_y;
923   struct ns_display_info *dpyinfo = check_ns_display_info (Qnil);
925   f->output_data.ns->icon_top = -1;
926   f->output_data.ns->icon_left = -1;
928   /* Set the position of the icon.  */
929   icon_x = x_get_arg (dpyinfo, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
930   icon_y = x_get_arg (dpyinfo, parms, Qicon_top, 0, 0,  RES_TYPE_NUMBER);
931   if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
932     {
933       CHECK_NUMBER (icon_x);
934       CHECK_NUMBER (icon_y);
935       f->output_data.ns->icon_top = XINT (icon_y);
936       f->output_data.ns->icon_left = XINT (icon_x);
937     }
938   else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
939     error ("Both left and top icon corners of icon must be specified");
943 /* Note: see frame.c for template, also where generic functions are impl */
944 frame_parm_handler ns_frame_parm_handlers[] =
946   x_set_autoraise, /* generic OK */
947   x_set_autolower, /* generic OK */
948   x_set_background_color,
949   0, /* x_set_border_color,  may be impossible under Nextstep */
950   0, /* x_set_border_width,  may be impossible under Nextstep */
951   x_set_cursor_color,
952   x_set_cursor_type,
953   x_set_font, /* generic OK */
954   x_set_foreground_color,
955   x_set_icon_name,
956   x_set_icon_type,
957   x_set_internal_border_width, /* generic OK */
958   0, /* x_set_right_divider_width */
959   0, /* x_set_bottom_divider_width */
960   x_set_menu_bar_lines,
961   x_set_mouse_color,
962   x_explicitly_set_name,
963   x_set_scroll_bar_width, /* generic OK */
964   x_set_scroll_bar_height, /* generic OK */
965   x_set_title,
966   x_set_unsplittable, /* generic OK */
967   x_set_vertical_scroll_bars, /* generic OK */
968   x_set_horizontal_scroll_bars, /* generic OK */
969   x_set_visibility, /* generic OK */
970   x_set_tool_bar_lines,
971   0, /* x_set_scroll_bar_foreground, will ignore (not possible on NS) */
972   0, /* x_set_scroll_bar_background,  will ignore (not possible on NS) */
973   x_set_screen_gamma, /* generic OK */
974   x_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */
975   x_set_left_fringe, /* generic OK */
976   x_set_right_fringe, /* generic OK */
977   0, /* x_set_wait_for_wm, will ignore */
978   x_set_fullscreen, /* generic OK */
979   x_set_font_backend, /* generic OK */
980   x_set_alpha,
981   0, /* x_set_sticky */
982   0, /* x_set_tool_bar_position */
986 /* Handler for signals raised during x_create_frame.
987    FRAME is the frame which is partially constructed.  */
989 static void
990 unwind_create_frame (Lisp_Object frame)
992   struct frame *f = XFRAME (frame);
994   /* If frame is already dead, nothing to do.  This can happen if the
995      display is disconnected after the frame has become official, but
996      before x_create_frame removes the unwind protect.  */
997   if (!FRAME_LIVE_P (f))
998     return;
1000   /* If frame is ``official'', nothing to do.  */
1001   if (NILP (Fmemq (frame, Vframe_list)))
1002     {
1003 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
1004       struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
1005 #endif
1007       /* If the frame's image cache refcount is still the same as our
1008          private shadow variable, it means we are unwinding a frame
1009          for which we didn't yet call init_frame_faces, where the
1010          refcount is incremented.  Therefore, we increment it here, so
1011          that free_frame_faces, called in x_free_frame_resources
1012          below, will not mistakenly decrement the counter that was not
1013          incremented yet to account for this new frame.  */
1014       if (FRAME_IMAGE_CACHE (f) != NULL
1015           && FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount)
1016         FRAME_IMAGE_CACHE (f)->refcount++;
1018       x_free_frame_resources (f);
1019       free_glyphs (f);
1021 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
1022       /* Check that reference counts are indeed correct.  */
1023       eassert (dpyinfo->terminal->image_cache->refcount == image_cache_refcount);
1024 #endif
1025     }
1029  * Read geometry related parameters from preferences if not in PARMS.
1030  * Returns the union of parms and any preferences read.
1031  */
1033 static Lisp_Object
1034 get_geometry_from_preferences (struct ns_display_info *dpyinfo,
1035                                Lisp_Object parms)
1037   struct {
1038     const char *val;
1039     const char *cls;
1040     Lisp_Object tem;
1041   } r[] = {
1042     { "width",  "Width", Qwidth },
1043     { "height", "Height", Qheight },
1044     { "left", "Left", Qleft },
1045     { "top", "Top", Qtop },
1046   };
1048   int i;
1049   for (i = 0; i < ARRAYELTS (r); ++i)
1050     {
1051       if (NILP (Fassq (r[i].tem, parms)))
1052         {
1053           Lisp_Object value
1054             = x_get_arg (dpyinfo, parms, r[i].tem, r[i].val, r[i].cls,
1055                          RES_TYPE_NUMBER);
1056           if (! EQ (value, Qunbound))
1057             parms = Fcons (Fcons (r[i].tem, value), parms);
1058         }
1059     }
1061   return parms;
1064 /* ==========================================================================
1066     Lisp definitions
1068    ========================================================================== */
1070 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
1071        1, 1, 0,
1072        doc: /* Make a new Nextstep window, called a "frame" in Emacs terms.
1073 Return an Emacs frame object.
1074 PARMS is an alist of frame parameters.
1075 If the parameters specify that the frame should not have a minibuffer,
1076 and do not specify a specific minibuffer window to use,
1077 then `default-minibuffer-frame' must be a frame whose minibuffer can
1078 be shared by the new frame.
1080 This function is an internal primitive--use `make-frame' instead.  */)
1081      (Lisp_Object parms)
1083   struct frame *f;
1084   Lisp_Object frame, tem;
1085   Lisp_Object name;
1086   int minibuffer_only = 0;
1087   long window_prompting = 0;
1088   ptrdiff_t count = specpdl_ptr - specpdl;
1089   Lisp_Object display;
1090   struct ns_display_info *dpyinfo = NULL;
1091   Lisp_Object parent;
1092   struct kboard *kb;
1093   static int desc_ctr = 1;
1094   int x_width = 0, x_height = 0;
1096   /* x_get_arg modifies parms.  */
1097   parms = Fcopy_alist (parms);
1099   /* Use this general default value to start with
1100      until we know if this frame has a specified name.  */
1101   Vx_resource_name = Vinvocation_name;
1103   display = x_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_STRING);
1104   if (EQ (display, Qunbound))
1105     display = Qnil;
1106   dpyinfo = check_ns_display_info (display);
1107   kb = dpyinfo->terminal->kboard;
1109   if (!dpyinfo->terminal->name)
1110     error ("Terminal is not live, can't create new frames on it");
1112   name = x_get_arg (dpyinfo, parms, Qname, 0, 0, RES_TYPE_STRING);
1113   if (!STRINGP (name)
1114       && ! EQ (name, Qunbound)
1115       && ! NILP (name))
1116     error ("Invalid frame name--not a string or nil");
1118   if (STRINGP (name))
1119     Vx_resource_name = name;
1121   parent = x_get_arg (dpyinfo, parms, Qparent_id, 0, 0, RES_TYPE_NUMBER);
1122   if (EQ (parent, Qunbound))
1123     parent = Qnil;
1124   if (! NILP (parent))
1125     CHECK_NUMBER (parent);
1127   /* make_frame_without_minibuffer can run Lisp code and garbage collect.  */
1128   /* No need to protect DISPLAY because that's not used after passing
1129      it to make_frame_without_minibuffer.  */
1130   frame = Qnil;
1131   tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
1132                   RES_TYPE_SYMBOL);
1133   if (EQ (tem, Qnone) || NILP (tem))
1134       f = make_frame_without_minibuffer (Qnil, kb, display);
1135   else if (EQ (tem, Qonly))
1136     {
1137       f = make_minibuffer_frame ();
1138       minibuffer_only = 1;
1139     }
1140   else if (WINDOWP (tem))
1141       f = make_frame_without_minibuffer (tem, kb, display);
1142   else
1143       f = make_frame (1);
1145   XSETFRAME (frame, f);
1147   f->terminal = dpyinfo->terminal;
1149   f->output_method = output_ns;
1150   f->output_data.ns = xzalloc (sizeof *f->output_data.ns);
1152   FRAME_FONTSET (f) = -1;
1154   fset_icon_name (f, x_get_arg (dpyinfo, parms, Qicon_name,
1155                                 "iconName", "Title",
1156                                 RES_TYPE_STRING));
1157   if (! STRINGP (f->icon_name))
1158     fset_icon_name (f, Qnil);
1160   FRAME_DISPLAY_INFO (f) = dpyinfo;
1162   /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe.  */
1163   record_unwind_protect (unwind_create_frame, frame);
1165   f->output_data.ns->window_desc = desc_ctr++;
1166   if (TYPE_RANGED_INTEGERP (Window, parent))
1167     {
1168       f->output_data.ns->parent_desc = XFASTINT (parent);
1169       f->output_data.ns->explicit_parent = 1;
1170     }
1171   else
1172     {
1173       f->output_data.ns->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
1174       f->output_data.ns->explicit_parent = 0;
1175     }
1177   /* Set the name; the functions to which we pass f expect the name to
1178      be set.  */
1179   if (EQ (name, Qunbound) || NILP (name) || ! STRINGP (name))
1180     {
1181       fset_name (f, build_string ([ns_app_name UTF8String]));
1182       f->explicit_name = 0;
1183     }
1184   else
1185     {
1186       fset_name (f, name);
1187       f->explicit_name = 1;
1188       specbind (Qx_resource_name, name);
1189     }
1191   block_input ();
1193 #ifdef NS_IMPL_COCOA
1194     mac_register_font_driver (f);
1195 #else
1196     register_font_driver (&nsfont_driver, f);
1197 #endif
1199   image_cache_refcount =
1200     FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
1202   x_default_parameter (f, parms, Qfont_backend, Qnil,
1203                         "fontBackend", "FontBackend", RES_TYPE_STRING);
1205   {
1206     /* use for default font name */
1207     id font = [NSFont userFixedPitchFontOfSize: -1.0]; /* default */
1208     x_default_parameter (f, parms, Qfontsize,
1209                                     make_number (0 /*(int)[font pointSize]*/),
1210                                     "fontSize", "FontSize", RES_TYPE_NUMBER);
1211     // Remove ' Regular', not handled by backends.
1212     char *fontname = xstrdup ([[font displayName] UTF8String]);
1213     int len = strlen (fontname);
1214     if (len > 8 && strcmp (fontname + len - 8, " Regular") == 0)
1215       fontname[len-8] = '\0';
1216     x_default_parameter (f, parms, Qfont,
1217                                  build_string (fontname),
1218                                  "font", "Font", RES_TYPE_STRING);
1219     xfree (fontname);
1220   }
1221   unblock_input ();
1223   x_default_parameter (f, parms, Qborder_width, make_number (0),
1224                        "borderwidth", "BorderWidth", RES_TYPE_NUMBER);
1225   x_default_parameter (f, parms, Qinternal_border_width, make_number (2),
1226                       "internalBorderWidth", "InternalBorderWidth",
1227                       RES_TYPE_NUMBER);
1229   /* default vertical scrollbars on right on Mac */
1230   {
1231       Lisp_Object spos
1232 #ifdef NS_IMPL_GNUSTEP
1233           = Qt;
1234 #else
1235           = Qright;
1236 #endif
1237       x_default_parameter (f, parms, Qvertical_scroll_bars, spos,
1238                            "verticalScrollBars", "VerticalScrollBars",
1239                            RES_TYPE_SYMBOL);
1240   }
1241   x_default_parameter (f, parms, Qhorizontal_scroll_bars, Qnil,
1242                        "horizontalScrollBars", "HorizontalScrollBars",
1243                        RES_TYPE_SYMBOL);
1244   x_default_parameter (f, parms, Qforeground_color, build_string ("Black"),
1245                       "foreground", "Foreground", RES_TYPE_STRING);
1246   x_default_parameter (f, parms, Qbackground_color, build_string ("White"),
1247                       "background", "Background", RES_TYPE_STRING);
1248   /* FIXME: not supported yet in Nextstep */
1249   x_default_parameter (f, parms, Qline_spacing, Qnil,
1250                        "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
1251   x_default_parameter (f, parms, Qleft_fringe, Qnil,
1252                        "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
1253   x_default_parameter (f, parms, Qright_fringe, Qnil,
1254                        "rightFringe", "RightFringe", RES_TYPE_NUMBER);
1256   init_frame_faces (f);
1258   /* Read comment about this code in corresponding place in xfns.c.  */
1259   adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
1260                      FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1,
1261                      Qx_create_frame_1);
1263   /* The resources controlling the menu-bar and tool-bar are
1264      processed specially at startup, and reflected in the mode
1265      variables; ignore them here.  */
1266   x_default_parameter (f, parms, Qmenu_bar_lines,
1267                        NILP (Vmenu_bar_mode)
1268                        ? make_number (0) : make_number (1),
1269                        NULL, NULL, RES_TYPE_NUMBER);
1270   x_default_parameter (f, parms, Qtool_bar_lines,
1271                        NILP (Vtool_bar_mode)
1272                        ? make_number (0) : make_number (1),
1273                        NULL, NULL, RES_TYPE_NUMBER);
1275   x_default_parameter (f, parms, Qbuffer_predicate, Qnil, "bufferPredicate",
1276                        "BufferPredicate", RES_TYPE_SYMBOL);
1277   x_default_parameter (f, parms, Qtitle, Qnil, "title", "Title",
1278                        RES_TYPE_STRING);
1280   parms = get_geometry_from_preferences (dpyinfo, parms);
1281   window_prompting = x_figure_window_size (f, parms, true, &x_width, &x_height);
1283   tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
1284   f->no_split = minibuffer_only || (!EQ (tem, Qunbound) && !EQ (tem, Qnil));
1286   /* NOTE: on other terms, this is done in set_mouse_color, however this
1287      was not getting called under Nextstep */
1288   f->output_data.ns->text_cursor = [NSCursor IBeamCursor];
1289   f->output_data.ns->nontext_cursor = [NSCursor arrowCursor];
1290   f->output_data.ns->modeline_cursor = [NSCursor pointingHandCursor];
1291   f->output_data.ns->hand_cursor = [NSCursor pointingHandCursor];
1292   f->output_data.ns->hourglass_cursor = [NSCursor disappearingItemCursor];
1293   f->output_data.ns->horizontal_drag_cursor = [NSCursor resizeLeftRightCursor];
1294   f->output_data.ns->vertical_drag_cursor = [NSCursor resizeUpDownCursor];
1295   FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor
1296      = [NSCursor arrowCursor];
1297   FRAME_DISPLAY_INFO (f)->horizontal_scroll_bar_cursor
1298      = [NSCursor arrowCursor];
1299   f->output_data.ns->current_pointer = f->output_data.ns->text_cursor;
1301   f->output_data.ns->in_animation = NO;
1303   [[EmacsView alloc] initFrameFromEmacs: f];
1305   x_icon (f, parms);
1307   /* ns_display_info does not have a reference_count.  */
1308   f->terminal->reference_count++;
1310   /* It is now ok to make the frame official even if we get an error below.
1311      The frame needs to be on Vframe_list or making it visible won't work. */
1312   Vframe_list = Fcons (frame, Vframe_list);
1314   x_default_parameter (f, parms, Qicon_type, Qnil,
1315                        "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
1317   x_default_parameter (f, parms, Qauto_raise, Qnil,
1318                        "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
1319   x_default_parameter (f, parms, Qauto_lower, Qnil,
1320                        "autoLower", "AutoLower", RES_TYPE_BOOLEAN);
1321   x_default_parameter (f, parms, Qcursor_type, Qbox,
1322                        "cursorType", "CursorType", RES_TYPE_SYMBOL);
1323   x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
1324                        "scrollBarWidth", "ScrollBarWidth",
1325                        RES_TYPE_NUMBER);
1326   x_default_parameter (f, parms, Qscroll_bar_height, Qnil,
1327                        "scrollBarHeight", "ScrollBarHeight",
1328                        RES_TYPE_NUMBER);
1329   x_default_parameter (f, parms, Qalpha, Qnil,
1330                        "alpha", "Alpha", RES_TYPE_NUMBER);
1331   x_default_parameter (f, parms, Qfullscreen, Qnil,
1332                        "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
1334   /* Allow x_set_window_size, now.  */
1335   f->can_x_set_window_size = true;
1337   if (x_width > 0)
1338     SET_FRAME_WIDTH (f, x_width);
1339   if (x_height > 0)
1340     SET_FRAME_HEIGHT (f, x_height);
1342   adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, 1,
1343                      Qx_create_frame_2);
1345   if (! f->output_data.ns->explicit_parent)
1346     {
1347       Lisp_Object visibility;
1349       visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
1350                               RES_TYPE_SYMBOL);
1351       if (EQ (visibility, Qunbound))
1352         visibility = Qt;
1354       if (EQ (visibility, Qicon))
1355         x_iconify_frame (f);
1356       else if (! NILP (visibility))
1357         {
1358           x_make_frame_visible (f);
1359           [[FRAME_NS_VIEW (f) window] makeKeyWindow];
1360         }
1361       else
1362         {
1363           /* Must have been Qnil.  */
1364         }
1365     }
1367   if (FRAME_HAS_MINIBUF_P (f)
1368       && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
1369           || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
1370     kset_default_minibuffer_frame (kb, frame);
1372   /* All remaining specified parameters, which have not been "used"
1373      by x_get_arg and friends, now go in the misc. alist of the frame.  */
1374   for (tem = parms; CONSP (tem); tem = XCDR (tem))
1375     if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
1376       fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
1378   if (window_prompting & USPosition)
1379     x_set_offset (f, f->left_pos, f->top_pos, 1);
1381   /* Make sure windows on this frame appear in calls to next-window
1382      and similar functions.  */
1383   Vwindow_list = Qnil;
1385   return unbind_to (count, frame);
1388 void
1389 x_focus_frame (struct frame *f)
1391   struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
1393   if (dpyinfo->x_focus_frame != f)
1394     {
1395       EmacsView *view = FRAME_NS_VIEW (f);
1396       block_input ();
1397       [NSApp activateIgnoringOtherApps: YES];
1398       [[view window] makeKeyAndOrderFront: view];
1399       unblock_input ();
1400     }
1404 DEFUN ("ns-popup-font-panel", Fns_popup_font_panel, Sns_popup_font_panel,
1405        0, 1, "",
1406        doc: /* Pop up the font panel. */)
1407      (Lisp_Object frame)
1409   struct frame *f = decode_window_system_frame (frame);
1410   id fm = [NSFontManager sharedFontManager];
1411   struct font *font = f->output_data.ns->font;
1412   NSFont *nsfont;
1413 #ifdef NS_IMPL_GNUSTEP
1414   nsfont = ((struct nsfont_info *)font)->nsfont;
1415 #endif
1416 #ifdef NS_IMPL_COCOA
1417   nsfont = (NSFont *) macfont_get_nsctfont (font);
1418 #endif
1419   [fm setSelectedFont: nsfont isMultiple: NO];
1420   [fm orderFrontFontPanel: NSApp];
1421   return Qnil;
1425 DEFUN ("ns-popup-color-panel", Fns_popup_color_panel, Sns_popup_color_panel,
1426        0, 1, "",
1427        doc: /* Pop up the color panel.  */)
1428      (Lisp_Object frame)
1430   check_window_system (NULL);
1431   [NSApp orderFrontColorPanel: NSApp];
1432   return Qnil;
1435 static struct
1437   id panel;
1438   BOOL ret;
1439 #ifdef NS_IMPL_GNUSTEP
1440   NSString *dirS, *initS;
1441   BOOL no_types;
1442 #endif
1443 } ns_fd_data;
1445 void
1446 ns_run_file_dialog (void)
1448   if (ns_fd_data.panel == nil) return;
1449 #ifdef NS_IMPL_COCOA
1450   ns_fd_data.ret = [ns_fd_data.panel runModal];
1451 #else
1452   if (ns_fd_data.no_types)
1453     {
1454       ns_fd_data.ret = [ns_fd_data.panel
1455                            runModalForDirectory: ns_fd_data.dirS
1456                            file: ns_fd_data.initS];
1457     }
1458   else
1459     {
1460       ns_fd_data.ret = [ns_fd_data.panel
1461                            runModalForDirectory: ns_fd_data.dirS
1462                            file: ns_fd_data.initS
1463                            types: nil];
1464     }
1465 #endif
1466   ns_fd_data.panel = nil;
1469 #ifdef NS_IMPL_COCOA
1470 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_9
1471 #define MODAL_OK_RESPONSE NSModalResponseOK
1472 #endif
1473 #endif
1474 #ifndef MODAL_OK_RESPONSE
1475 #define MODAL_OK_RESPONSE NSOKButton
1476 #endif
1478 DEFUN ("ns-read-file-name", Fns_read_file_name, Sns_read_file_name, 1, 5, 0,
1479        doc: /* Use a graphical panel to read a file name, using prompt PROMPT.
1480 Optional arg DIR, if non-nil, supplies a default directory.
1481 Optional arg MUSTMATCH, if non-nil, means the returned file or
1482 directory must exist.
1483 Optional arg INIT, if non-nil, provides a default file name to use.
1484 Optional arg DIR_ONLY_P, if non-nil, means choose only directories.  */)
1485   (Lisp_Object prompt, Lisp_Object dir, Lisp_Object mustmatch,
1486    Lisp_Object init, Lisp_Object dir_only_p)
1488   static id fileDelegate = nil;
1489   BOOL isSave = NILP (mustmatch) && NILP (dir_only_p);
1490   id panel;
1491   Lisp_Object fname = Qnil;
1493   NSString *promptS = NILP (prompt) || !STRINGP (prompt) ? nil :
1494     [NSString stringWithUTF8String: SSDATA (prompt)];
1495   NSString *dirS = NILP (dir) || !STRINGP (dir) ?
1496     [NSString stringWithUTF8String: SSDATA (BVAR (current_buffer, directory))] :
1497     [NSString stringWithUTF8String: SSDATA (dir)];
1498   NSString *initS = NILP (init) || !STRINGP (init) ? nil :
1499     [NSString stringWithUTF8String: SSDATA (init)];
1500   NSEvent *nxev;
1502   check_window_system (NULL);
1504   if (fileDelegate == nil)
1505     fileDelegate = [EmacsFileDelegate new];
1507   [NSCursor setHiddenUntilMouseMoves: NO];
1509   if ([dirS characterAtIndex: 0] == '~')
1510     dirS = [dirS stringByExpandingTildeInPath];
1512   panel = isSave ?
1513     (id)[EmacsSavePanel savePanel] : (id)[EmacsOpenPanel openPanel];
1515   [panel setTitle: promptS];
1517   [panel setAllowsOtherFileTypes: YES];
1518   [panel setTreatsFilePackagesAsDirectories: YES];
1519   [panel setDelegate: fileDelegate];
1521   if (! NILP (dir_only_p))
1522     {
1523       [panel setCanChooseDirectories: YES];
1524       [panel setCanChooseFiles: NO];
1525     }
1526   else if (! isSave)
1527     {
1528       /* This is not quite what the documentation says, but it is compatible
1529          with the Gtk+ code.  Also, the menu entry says "Open File...".  */
1530       [panel setCanChooseDirectories: NO];
1531       [panel setCanChooseFiles: YES];
1532     }
1534   block_input ();
1535   ns_fd_data.panel = panel;
1536   ns_fd_data.ret = NO;
1537 #ifdef NS_IMPL_COCOA
1538   if (! NILP (mustmatch) || ! NILP (dir_only_p))
1539     [panel setAllowedFileTypes: nil];
1540   if (dirS) [panel setDirectoryURL: [NSURL fileURLWithPath: dirS]];
1541   if (initS && NILP (Ffile_directory_p (init)))
1542     [panel setNameFieldStringValue: [initS lastPathComponent]];
1543   else
1544     [panel setNameFieldStringValue: @""];
1546 #else
1547   ns_fd_data.no_types = NILP (mustmatch) && NILP (dir_only_p);
1548   ns_fd_data.dirS = dirS;
1549   ns_fd_data.initS = initS;
1550 #endif
1552   /* runModalForDirectory/runModal restarts the main event loop when done,
1553      so we must start an event loop and then pop up the file dialog.
1554      The file dialog may pop up a confirm dialog after Ok has been pressed,
1555      so we can not simply pop down on the Ok/Cancel press.
1556    */
1557   nxev = [NSEvent otherEventWithType: NSApplicationDefined
1558                             location: NSMakePoint (0, 0)
1559                        modifierFlags: 0
1560                            timestamp: 0
1561                         windowNumber: [[NSApp mainWindow] windowNumber]
1562                              context: [NSApp context]
1563                              subtype: 0
1564                                data1: 0
1565                                data2: NSAPP_DATA2_RUNFILEDIALOG];
1567   [NSApp postEvent: nxev atStart: NO];
1568   while (ns_fd_data.panel != nil)
1569     [NSApp run];
1571   if (ns_fd_data.ret == MODAL_OK_RESPONSE)
1572     {
1573       NSString *str = ns_filename_from_panel (panel);
1574       if (! str) str = ns_directory_from_panel (panel);
1575       if (str) fname = build_string ([str UTF8String]);
1576     }
1578   [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
1579   unblock_input ();
1581   return fname;
1584 const char *
1585 ns_get_defaults_value (const char *key)
1587   NSObject *obj = [[NSUserDefaults standardUserDefaults]
1588                     objectForKey: [NSString stringWithUTF8String: key]];
1590   if (!obj) return NULL;
1592   return [[NSString stringWithFormat: @"%@", obj] UTF8String];
1596 DEFUN ("ns-get-resource", Fns_get_resource, Sns_get_resource, 2, 2, 0,
1597        doc: /* Return the value of the property NAME of OWNER from the defaults database.
1598 If OWNER is nil, Emacs is assumed.  */)
1599      (Lisp_Object owner, Lisp_Object name)
1601   const char *value;
1603   check_window_system (NULL);
1604   if (NILP (owner))
1605     owner = build_string([ns_app_name UTF8String]);
1606   CHECK_STRING (name);
1608   value = ns_get_defaults_value (SSDATA (name));
1610   if (value)
1611     return build_string (value);
1612   return Qnil;
1616 DEFUN ("ns-set-resource", Fns_set_resource, Sns_set_resource, 3, 3, 0,
1617        doc: /* Set property NAME of OWNER to VALUE, from the defaults database.
1618 If OWNER is nil, Emacs is assumed.
1619 If VALUE is nil, the default is removed.  */)
1620      (Lisp_Object owner, Lisp_Object name, Lisp_Object value)
1622   check_window_system (NULL);
1623   if (NILP (owner))
1624     owner = build_string ([ns_app_name UTF8String]);
1625   CHECK_STRING (name);
1626   if (NILP (value))
1627     {
1628       [[NSUserDefaults standardUserDefaults] removeObjectForKey:
1629                          [NSString stringWithUTF8String: SSDATA (name)]];
1630     }
1631   else
1632     {
1633       CHECK_STRING (value);
1634       [[NSUserDefaults standardUserDefaults] setObject:
1635                 [NSString stringWithUTF8String: SSDATA (value)]
1636                                         forKey: [NSString stringWithUTF8String:
1637                                                          SSDATA (name)]];
1638     }
1640   return Qnil;
1644 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
1645        Sx_server_max_request_size,
1646        0, 1, 0,
1647        doc: /* This function is a no-op.  It is only present for completeness.  */)
1648      (Lisp_Object terminal)
1650   check_ns_display_info (terminal);
1651   /* This function has no real equivalent under NeXTstep.  Return nil to
1652      indicate this. */
1653   return Qnil;
1657 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
1658        doc: /* Return the "vendor ID" string of Nextstep display server TERMINAL.
1659 (Labeling every distributor as a "vendor" embodies the false assumption
1660 that operating systems cannot be developed and distributed noncommercially.)
1661 The optional argument TERMINAL specifies which display to ask about.
1662 TERMINAL should be a terminal object, a frame or a display name (a string).
1663 If omitted or nil, that stands for the selected frame's display.  */)
1664   (Lisp_Object terminal)
1666   check_ns_display_info (terminal);
1667 #ifdef NS_IMPL_GNUSTEP
1668   return build_string ("GNU");
1669 #else
1670   return build_string ("Apple");
1671 #endif
1675 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
1676        doc: /* Return the version numbers of the server of display TERMINAL.
1677 The value is a list of three integers: the major and minor
1678 version numbers of the X Protocol in use, and the distributor-specific release
1679 number.  See also the function `x-server-vendor'.
1681 The optional argument TERMINAL specifies which display to ask about.
1682 TERMINAL should be a terminal object, a frame or a display name (a string).
1683 If omitted or nil, that stands for the selected frame's display.  */)
1684   (Lisp_Object terminal)
1686   check_ns_display_info (terminal);
1687   /*NOTE: it is unclear what would best correspond with "protocol";
1688           we return 10.3, meaning Panther, since this is roughly the
1689           level that GNUstep's APIs correspond to.
1690           The last number is where we distinguish between the Apple
1691           and GNUstep implementations ("distributor-specific release
1692           number") and give int'ized versions of major.minor. */
1693   return list3i (10, 3, ns_appkit_version_int ());
1697 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
1698        doc: /* Return the number of screens on Nextstep display server TERMINAL.
1699 The optional argument TERMINAL specifies which display to ask about.
1700 TERMINAL should be a terminal object, a frame or a display name (a string).
1701 If omitted or nil, that stands for the selected frame's display.
1703 Note: "screen" here is not in Nextstep terminology but in X11's.  For
1704 the number of physical monitors, use `(length
1705 (display-monitor-attributes-list TERMINAL))' instead.  */)
1706   (Lisp_Object terminal)
1708   check_ns_display_info (terminal);
1709   return make_number (1);
1713 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
1714        doc: /* Return the height in millimeters of the Nextstep display TERMINAL.
1715 The optional argument TERMINAL specifies which display to ask about.
1716 TERMINAL should be a terminal object, a frame or a display name (a string).
1717 If omitted or nil, that stands for the selected frame's display.
1719 On \"multi-monitor\" setups this refers to the height in millimeters for
1720 all physical monitors associated with TERMINAL.  To get information
1721 for each physical monitor, use `display-monitor-attributes-list'.  */)
1722   (Lisp_Object terminal)
1724   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
1726   return make_number (x_display_pixel_height (dpyinfo) / (92.0/25.4));
1730 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
1731        doc: /* Return the width in millimeters of the Nextstep display TERMINAL.
1732 The optional argument TERMINAL specifies which display to ask about.
1733 TERMINAL should be a terminal object, a frame or a display name (a string).
1734 If omitted or nil, that stands for the selected frame's display.
1736 On \"multi-monitor\" setups this refers to the width in millimeters for
1737 all physical monitors associated with TERMINAL.  To get information
1738 for each physical monitor, use `display-monitor-attributes-list'.  */)
1739   (Lisp_Object terminal)
1741   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
1743   return make_number (x_display_pixel_width (dpyinfo) / (92.0/25.4));
1747 DEFUN ("x-display-backing-store", Fx_display_backing_store,
1748        Sx_display_backing_store, 0, 1, 0,
1749        doc: /* Return an indication of whether the Nextstep display TERMINAL does backing store.
1750 The value may be `buffered', `retained', or `non-retained'.
1751 The optional argument TERMINAL specifies which display to ask about.
1752 TERMINAL should be a terminal object, a frame or a display name (a string).
1753 If omitted or nil, that stands for the selected frame's display.  */)
1754   (Lisp_Object terminal)
1756   check_ns_display_info (terminal);
1757   switch ([ns_get_window (terminal) backingType])
1758     {
1759     case NSBackingStoreBuffered:
1760       return intern ("buffered");
1761     case NSBackingStoreRetained:
1762       return intern ("retained");
1763     case NSBackingStoreNonretained:
1764       return intern ("non-retained");
1765     default:
1766       error ("Strange value for backingType parameter of frame");
1767     }
1768   return Qnil;  /* not reached, shut compiler up */
1772 DEFUN ("x-display-visual-class", Fx_display_visual_class,
1773        Sx_display_visual_class, 0, 1, 0,
1774        doc: /* Return the visual class of the Nextstep display TERMINAL.
1775 The value is one of the symbols `static-gray', `gray-scale',
1776 `static-color', `pseudo-color', `true-color', or `direct-color'.
1778 The optional argument TERMINAL specifies which display to ask about.
1779 TERMINAL should a terminal object, a frame or a display name (a string).
1780 If omitted or nil, that stands for the selected frame's display.  */)
1781   (Lisp_Object terminal)
1783   NSWindowDepth depth;
1785   check_ns_display_info (terminal);
1786   depth = [[[NSScreen screens] objectAtIndex:0] depth];
1788   if ( depth == NSBestDepth (NSCalibratedWhiteColorSpace, 2, 2, YES, NULL))
1789     return intern ("static-gray");
1790   else if (depth == NSBestDepth (NSCalibratedWhiteColorSpace, 8, 8, YES, NULL))
1791     return intern ("gray-scale");
1792   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 8, YES, NULL))
1793     return intern ("pseudo-color");
1794   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 4, 12, NO, NULL))
1795     return intern ("true-color");
1796   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 24, NO, NULL))
1797     return intern ("direct-color");
1798   else
1799     /* color mgmt as far as we do it is really handled by Nextstep itself anyway */
1800     return intern ("direct-color");
1804 DEFUN ("x-display-save-under", Fx_display_save_under,
1805        Sx_display_save_under, 0, 1, 0,
1806        doc: /* Return t if TERMINAL supports the save-under feature.
1807 The optional argument TERMINAL specifies which display to ask about.
1808 TERMINAL should be a terminal object, a frame or a display name (a string).
1809 If omitted or nil, that stands for the selected frame's display.  */)
1810   (Lisp_Object terminal)
1812   check_ns_display_info (terminal);
1813   switch ([ns_get_window (terminal) backingType])
1814     {
1815     case NSBackingStoreBuffered:
1816       return Qt;
1818     case NSBackingStoreRetained:
1819     case NSBackingStoreNonretained:
1820       return Qnil;
1822     default:
1823       error ("Strange value for backingType parameter of frame");
1824     }
1825   return Qnil;  /* not reached, shut compiler up */
1829 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
1830        1, 3, 0,
1831        doc: /* Open a connection to a display server.
1832 DISPLAY is the name of the display to connect to.
1833 Optional second arg XRM-STRING is a string of resources in xrdb format.
1834 If the optional third arg MUST-SUCCEED is non-nil,
1835 terminate Emacs if we can't open the connection.
1836 (In the Nextstep version, the last two arguments are currently ignored.)  */)
1837      (Lisp_Object display, Lisp_Object resource_string, Lisp_Object must_succeed)
1839   struct ns_display_info *dpyinfo;
1841   CHECK_STRING (display);
1843   nxatoms_of_nsselect ();
1844   dpyinfo = ns_term_init (display);
1845   if (dpyinfo == 0)
1846     {
1847       if (!NILP (must_succeed))
1848         fatal ("Display on %s not responding.\n",
1849                SSDATA (display));
1850       else
1851         error ("Display on %s not responding.\n",
1852                SSDATA (display));
1853     }
1855   return Qnil;
1859 DEFUN ("x-close-connection", Fx_close_connection, Sx_close_connection,
1860        1, 1, 0,
1861        doc: /* Close the connection to TERMINAL's Nextstep display server.
1862 For TERMINAL, specify a terminal object, a frame or a display name (a
1863 string).  If TERMINAL is nil, that stands for the selected frame's
1864 terminal.  */)
1865      (Lisp_Object terminal)
1867   check_ns_display_info (terminal);
1868   [NSApp terminate: NSApp];
1869   return Qnil;
1873 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
1874        doc: /* Return the list of display names that Emacs has connections to.  */)
1875      (void)
1877   Lisp_Object result = Qnil;
1878   struct ns_display_info *ndi;
1880   for (ndi = x_display_list; ndi; ndi = ndi->next)
1881     result = Fcons (XCAR (ndi->name_list_element), result);
1883   return result;
1887 DEFUN ("ns-hide-others", Fns_hide_others, Sns_hide_others,
1888        0, 0, 0,
1889        doc: /* Hides all applications other than Emacs.  */)
1890      (void)
1892   check_window_system (NULL);
1893   [NSApp hideOtherApplications: NSApp];
1894   return Qnil;
1897 DEFUN ("ns-hide-emacs", Fns_hide_emacs, Sns_hide_emacs,
1898        1, 1, 0,
1899        doc: /* If ON is non-nil, the entire Emacs application is hidden.
1900 Otherwise if Emacs is hidden, it is unhidden.
1901 If ON is equal to `activate', Emacs is unhidden and becomes
1902 the active application.  */)
1903      (Lisp_Object on)
1905   check_window_system (NULL);
1906   if (EQ (on, intern ("activate")))
1907     {
1908       [NSApp unhide: NSApp];
1909       [NSApp activateIgnoringOtherApps: YES];
1910     }
1911   else if (NILP (on))
1912     [NSApp unhide: NSApp];
1913   else
1914     [NSApp hide: NSApp];
1915   return Qnil;
1919 DEFUN ("ns-emacs-info-panel", Fns_emacs_info_panel, Sns_emacs_info_panel,
1920        0, 0, 0,
1921        doc: /* Shows the 'Info' or 'About' panel for Emacs.  */)
1922      (void)
1924   check_window_system (NULL);
1925   [NSApp orderFrontStandardAboutPanel: nil];
1926   return Qnil;
1930 DEFUN ("ns-font-name", Fns_font_name, Sns_font_name, 1, 1, 0,
1931        doc: /* Determine font PostScript or family name for font NAME.
1932 NAME should be a string containing either the font name or an XLFD
1933 font descriptor.  If string contains `fontset' and not
1934 `fontset-startup', it is left alone. */)
1935      (Lisp_Object name)
1937   char *nm;
1938   CHECK_STRING (name);
1939   nm = SSDATA (name);
1941   if (nm[0] != '-')
1942     return name;
1943   if (strstr (nm, "fontset") && !strstr (nm, "fontset-startup"))
1944     return name;
1946   return build_string (ns_xlfd_to_fontname (SSDATA (name)));
1950 DEFUN ("ns-list-colors", Fns_list_colors, Sns_list_colors, 0, 1, 0,
1951        doc: /* Return a list of all available colors.
1952 The optional argument FRAME is currently ignored.  */)
1953      (Lisp_Object frame)
1955   Lisp_Object list = Qnil;
1956   NSEnumerator *colorlists;
1957   NSColorList *clist;
1959   if (!NILP (frame))
1960     {
1961       CHECK_FRAME (frame);
1962       if (! FRAME_NS_P (XFRAME (frame)))
1963         error ("non-Nextstep frame used in `ns-list-colors'");
1964     }
1966   block_input ();
1968   colorlists = [[NSColorList availableColorLists] objectEnumerator];
1969   while ((clist = [colorlists nextObject]))
1970     {
1971       if ([[clist name] length] < 7 ||
1972           [[clist name] rangeOfString: @"PANTONE"].location == 0)
1973         {
1974           NSEnumerator *cnames = [[clist allKeys] reverseObjectEnumerator];
1975           NSString *cname;
1976           while ((cname = [cnames nextObject]))
1977             list = Fcons (build_string ([cname UTF8String]), list);
1978 /*           for (i = [[clist allKeys] count] - 1; i >= 0; i--)
1979                list = Fcons (build_string ([[[clist allKeys] objectAtIndex: i]
1980                                              UTF8String]), list); */
1981         }
1982     }
1984   unblock_input ();
1986   return list;
1990 DEFUN ("ns-list-services", Fns_list_services, Sns_list_services, 0, 0, 0,
1991        doc: /* List available Nextstep services by querying NSApp.  */)
1992      (void)
1994 #ifdef NS_IMPL_COCOA
1995   /* You can't get services like this in 10.6+.  */
1996   return Qnil;
1997 #else
1998   Lisp_Object ret = Qnil;
1999   NSMenu *svcs;
2000 #ifdef NS_IMPL_COCOA
2001   id delegate;
2002 #endif
2004   check_window_system (NULL);
2005   svcs = [[NSMenu alloc] initWithTitle: @"Services"];
2006   [NSApp setServicesMenu: svcs];
2007   [NSApp registerServicesMenuSendTypes: ns_send_types
2008                            returnTypes: ns_return_types];
2010 /* On Tiger, services menu updating was made lazier (waits for user to
2011    actually click on the menu), so we have to force things along: */
2012 #ifdef NS_IMPL_COCOA
2013   delegate = [svcs delegate];
2014   if (delegate != nil)
2015     {
2016       if ([delegate respondsToSelector: @selector (menuNeedsUpdate:)])
2017         [delegate menuNeedsUpdate: svcs];
2018       if ([delegate respondsToSelector:
2019                        @selector (menu:updateItem:atIndex:shouldCancel:)])
2020         {
2021           int i, len = [delegate numberOfItemsInMenu: svcs];
2022           for (i =0; i<len; i++)
2023             [svcs addItemWithTitle: @"" action: NULL keyEquivalent: @""];
2024           for (i =0; i<len; i++)
2025             if (![delegate menu: svcs
2026                      updateItem: (NSMenuItem *)[svcs itemAtIndex: i]
2027                         atIndex: i shouldCancel: NO])
2028               break;
2029         }
2030     }
2031 #endif
2033   [svcs setAutoenablesItems: NO];
2034 #ifdef NS_IMPL_COCOA
2035   [svcs update]; /* on OS X, converts from '/' structure */
2036 #endif
2038   ret = interpret_services_menu (svcs, Qnil, ret);
2039   return ret;
2040 #endif
2044 DEFUN ("ns-perform-service", Fns_perform_service, Sns_perform_service,
2045        2, 2, 0,
2046        doc: /* Perform Nextstep SERVICE on SEND.
2047 SEND should be either a string or nil.
2048 The return value is the result of the service, as string, or nil if
2049 there was no result.  */)
2050      (Lisp_Object service, Lisp_Object send)
2052   id pb;
2053   NSString *svcName;
2054   char *utfStr;
2056   CHECK_STRING (service);
2057   check_window_system (NULL);
2059   utfStr = SSDATA (service);
2060   svcName = [NSString stringWithUTF8String: utfStr];
2062   pb =[NSPasteboard pasteboardWithUniqueName];
2063   ns_string_to_pasteboard (pb, send);
2065   if (NSPerformService (svcName, pb) == NO)
2066     Fsignal (Qquit, list1 (build_string ("service not available")));
2068   if ([[pb types] count] == 0)
2069     return build_string ("");
2070   return ns_string_from_pasteboard (pb);
2074 DEFUN ("ns-convert-utf8-nfd-to-nfc", Fns_convert_utf8_nfd_to_nfc,
2075        Sns_convert_utf8_nfd_to_nfc, 1, 1, 0,
2076        doc: /* Return an NFC string that matches the UTF-8 NFD string STR.  */)
2077      (Lisp_Object str)
2079 /* TODO: If GNUstep ever implements precomposedStringWithCanonicalMapping,
2080          remove this. */
2081   NSString *utfStr;
2082   Lisp_Object ret = Qnil;
2083   NSAutoreleasePool *pool;
2085   CHECK_STRING (str);
2086   pool = [[NSAutoreleasePool alloc] init];
2087   utfStr = [NSString stringWithUTF8String: SSDATA (str)];
2088 #ifdef NS_IMPL_COCOA
2089   if (utfStr)
2090     utfStr = [utfStr precomposedStringWithCanonicalMapping];
2091 #endif
2092   if (utfStr)
2093     {
2094       const char *cstr = [utfStr UTF8String];
2095       if (cstr)
2096         ret = build_string (cstr);
2097     }
2099   [pool release];
2100   if (NILP (ret))
2101     error ("Invalid UTF-8");
2103   return ret;
2107 #ifdef NS_IMPL_COCOA
2109 /* Compile and execute the AppleScript SCRIPT and return the error
2110    status as function value.  A zero is returned if compilation and
2111    execution is successful, in which case *RESULT is set to a Lisp
2112    string or a number containing the resulting script value.  Otherwise,
2113    1 is returned. */
2114 static int
2115 ns_do_applescript (Lisp_Object script, Lisp_Object *result)
2117   NSAppleEventDescriptor *desc;
2118   NSDictionary* errorDict;
2119   NSAppleEventDescriptor* returnDescriptor = NULL;
2121   NSAppleScript* scriptObject =
2122     [[NSAppleScript alloc] initWithSource:
2123                              [NSString stringWithUTF8String: SSDATA (script)]];
2125   returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
2126   [scriptObject release];
2127   *result = Qnil;
2129   if (returnDescriptor != NULL)
2130     {
2131       // successful execution
2132       if (kAENullEvent != [returnDescriptor descriptorType])
2133         {
2134           *result = Qt;
2135           // script returned an AppleScript result
2136           if ((typeUnicodeText == [returnDescriptor descriptorType]) ||
2137 #if defined (NS_IMPL_COCOA)
2138               (typeUTF16ExternalRepresentation
2139                == [returnDescriptor descriptorType]) ||
2140 #endif
2141               (typeUTF8Text == [returnDescriptor descriptorType]) ||
2142               (typeCString == [returnDescriptor descriptorType]))
2143             {
2144               desc = [returnDescriptor coerceToDescriptorType: typeUTF8Text];
2145               if (desc)
2146                 *result = build_string([[desc stringValue] UTF8String]);
2147             }
2148           else
2149             {
2150               /* use typeUTF16ExternalRepresentation? */
2151               // coerce the result to the appropriate ObjC type
2152               desc = [returnDescriptor coerceToDescriptorType: typeUTF8Text];
2153               if (desc)
2154                 *result = make_number([desc int32Value]);
2155             }
2156         }
2157     }
2158   else
2159     {
2160       // no script result, return error
2161       return 1;
2162     }
2163   return 0;
2166 /* Helper function called from sendEvent to run applescript
2167    from within the main event loop.  */
2169 void
2170 ns_run_ascript (void)
2172   if (! NILP (as_script))
2173     as_status = ns_do_applescript (as_script, as_result);
2174   as_script = Qnil;
2177 DEFUN ("ns-do-applescript", Fns_do_applescript, Sns_do_applescript, 1, 1, 0,
2178        doc: /* Execute AppleScript SCRIPT and return the result.
2179 If compilation and execution are successful, the resulting script value
2180 is returned as a string, a number or, in the case of other constructs, t.
2181 In case the execution fails, an error is signaled. */)
2182      (Lisp_Object script)
2184   Lisp_Object result;
2185   int status;
2186   NSEvent *nxev;
2187   struct input_event ev;
2189   CHECK_STRING (script);
2190   check_window_system (NULL);
2192   block_input ();
2194   as_script = script;
2195   as_result = &result;
2197   /* executing apple script requires the event loop to run, otherwise
2198      errors aren't returned and executeAndReturnError hangs forever.
2199      Post an event that runs applescript and then start the event loop.
2200      The event loop is exited when the script is done.  */
2201   nxev = [NSEvent otherEventWithType: NSApplicationDefined
2202                             location: NSMakePoint (0, 0)
2203                        modifierFlags: 0
2204                            timestamp: 0
2205                         windowNumber: [[NSApp mainWindow] windowNumber]
2206                              context: [NSApp context]
2207                              subtype: 0
2208                                data1: 0
2209                                data2: NSAPP_DATA2_RUNASSCRIPT];
2211   [NSApp postEvent: nxev atStart: NO];
2213   // If there are other events, the event loop may exit.  Keep running
2214   // until the script has been handled.  */
2215   ns_init_events (&ev);
2216   while (! NILP (as_script))
2217     [NSApp run];
2218   ns_finish_events ();
2220   status = as_status;
2221   as_status = 0;
2222   as_result = 0;
2223   unblock_input ();
2224   if (status == 0)
2225     return result;
2226   else if (!STRINGP (result))
2227     error ("AppleScript error %d", status);
2228   else
2229     error ("%s", SSDATA (result));
2231 #endif
2235 /* ==========================================================================
2237     Miscellaneous functions not called through hooks
2239    ========================================================================== */
2241 /* called from frame.c */
2242 struct ns_display_info *
2243 check_x_display_info (Lisp_Object frame)
2245   return check_ns_display_info (frame);
2249 void
2250 x_set_scroll_bar_default_width (struct frame *f)
2252   int wid = FRAME_COLUMN_WIDTH (f);
2253   FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = NS_SCROLL_BAR_WIDTH_DEFAULT;
2254   FRAME_CONFIG_SCROLL_BAR_COLS (f) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) +
2255                                       wid - 1) / wid;
2258 void
2259 x_set_scroll_bar_default_height (struct frame *f)
2261   int height = FRAME_LINE_HEIGHT (f);
2262   FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = NS_SCROLL_BAR_WIDTH_DEFAULT;
2263   FRAME_CONFIG_SCROLL_BAR_LINES (f) = (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) +
2264                                        height - 1) / height;
2267 /* terms impl this instead of x-get-resource directly */
2268 char *
2269 x_get_string_resource (XrmDatabase rdb, const char *name, const char *class)
2271   /* remove appname prefix; TODO: allow for !="Emacs" */
2272   const char *res, *toCheck = class + (!strncmp (class, "Emacs.", 6) ? 6 : 0);
2274   check_window_system (NULL);
2276   if (inhibit_x_resources)
2277     /* --quick was passed, so this is a no-op.  */
2278     return NULL;
2280   res = ns_get_defaults_value (toCheck);
2281   return (!res ? NULL :
2282           (!c_strncasecmp (res, "YES", 3) ? "true" :
2283            (!c_strncasecmp (res, "NO", 2) ? "false" : (char *) res)));
2287 Lisp_Object
2288 x_get_focus_frame (struct frame *frame)
2290   struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
2291   Lisp_Object nsfocus;
2293   if (!dpyinfo->x_focus_frame)
2294     return Qnil;
2296   XSETFRAME (nsfocus, dpyinfo->x_focus_frame);
2297   return nsfocus;
2300 /* ==========================================================================
2302     Lisp definitions that, for whatever reason, we can't alias as 'ns-XXX'.
2304    ========================================================================== */
2307 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
2308        doc: /* Internal function called by `color-defined-p', which see.
2309 (Note that the Nextstep version of this function ignores FRAME.)  */)
2310      (Lisp_Object color, Lisp_Object frame)
2312   NSColor * col;
2313   check_window_system (NULL);
2314   return ns_lisp_to_color (color, &col) ? Qnil : Qt;
2318 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
2319        doc: /* Internal function called by `color-values', which see.  */)
2320      (Lisp_Object color, Lisp_Object frame)
2322   NSColor * col;
2323   EmacsCGFloat red, green, blue, alpha;
2325   check_window_system (NULL);
2326   CHECK_STRING (color);
2328   block_input ();
2329   if (ns_lisp_to_color (color, &col))
2330     {
2331       unblock_input ();
2332       return Qnil;
2333     }
2335   [[col colorUsingDefaultColorSpace]
2336         getRed: &red green: &green blue: &blue alpha: &alpha];
2337   unblock_input ();
2338   return list3i (lrint (red * 65280), lrint (green * 65280),
2339                  lrint (blue * 65280));
2343 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
2344        doc: /* Internal function called by `display-color-p', which see.  */)
2345      (Lisp_Object terminal)
2347   NSWindowDepth depth;
2348   NSString *colorSpace;
2350   check_ns_display_info (terminal);
2351   depth = [[[NSScreen screens] objectAtIndex:0] depth];
2352   colorSpace = NSColorSpaceFromDepth (depth);
2354   return    [colorSpace isEqualToString: NSDeviceWhiteColorSpace]
2355          || [colorSpace isEqualToString: NSCalibratedWhiteColorSpace]
2356       ? Qnil : Qt;
2360 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
2361        0, 1, 0,
2362        doc: /* Return t if the Nextstep display supports shades of gray.
2363 Note that color displays do support shades of gray.
2364 The optional argument TERMINAL specifies which display to ask about.
2365 TERMINAL should be a terminal object, a frame or a display name (a string).
2366 If omitted or nil, that stands for the selected frame's display.  */)
2367   (Lisp_Object terminal)
2369   NSWindowDepth depth;
2371   check_ns_display_info (terminal);
2372   depth = [[[NSScreen screens] objectAtIndex:0] depth];
2374   return NSBitsPerPixelFromDepth (depth) > 1 ? Qt : Qnil;
2378 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
2379        0, 1, 0,
2380        doc: /* Return the width in pixels of the Nextstep display TERMINAL.
2381 The optional argument TERMINAL specifies which display to ask about.
2382 TERMINAL should be a terminal object, a frame or a display name (a string).
2383 If omitted or nil, that stands for the selected frame's display.
2385 On \"multi-monitor\" setups this refers to the pixel width for all
2386 physical monitors associated with TERMINAL.  To get information for
2387 each physical monitor, use `display-monitor-attributes-list'.  */)
2388   (Lisp_Object terminal)
2390   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
2392   return make_number (x_display_pixel_width (dpyinfo));
2396 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
2397        Sx_display_pixel_height, 0, 1, 0,
2398        doc: /* Return the height in pixels of the Nextstep display TERMINAL.
2399 The optional argument TERMINAL specifies which display to ask about.
2400 TERMINAL should be a terminal object, a frame or a display name (a string).
2401 If omitted or nil, that stands for the selected frame's display.
2403 On \"multi-monitor\" setups this refers to the pixel height for all
2404 physical monitors associated with TERMINAL.  To get information for
2405 each physical monitor, use `display-monitor-attributes-list'.  */)
2406   (Lisp_Object terminal)
2408   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
2410   return make_number (x_display_pixel_height (dpyinfo));
2413 #ifdef NS_IMPL_COCOA
2415 /* Returns the name for the screen that OBJ represents, or NULL.
2416    Caller must free return value.
2419 static char *
2420 ns_get_name_from_ioreg (io_object_t obj)
2422   char *name = NULL;
2424   NSDictionary *info = (NSDictionary *)
2425     IODisplayCreateInfoDictionary (obj, kIODisplayOnlyPreferredName);
2426   NSDictionary *names = [info objectForKey:
2427                                 [NSString stringWithUTF8String:
2428                                             kDisplayProductName]];
2430   if ([names count] > 0)
2431     {
2432       NSString *n = [names objectForKey: [[names allKeys]
2433                                                  objectAtIndex:0]];
2434       if (n != nil) name = xstrdup ([n UTF8String]);
2435     }
2437   [info release];
2439   return name;
2442 /* Returns the name for the screen that DID came from, or NULL.
2443    Caller must free return value.
2446 static char *
2447 ns_screen_name (CGDirectDisplayID did)
2449   char *name = NULL;
2451 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
2452   mach_port_t masterPort;
2453   io_iterator_t it;
2454   io_object_t obj;
2456   // CGDisplayIOServicePort is deprecated.  Do it another (harder) way.
2458   if (IOMasterPort (MACH_PORT_NULL, &masterPort) != kIOReturnSuccess
2459       || IOServiceGetMatchingServices (masterPort,
2460                                        IOServiceMatching ("IONDRVDevice"),
2461                                        &it) != kIOReturnSuccess)
2462     return name;
2464   /* Must loop until we find a name.  Many devices can have the same unit
2465      number (represents different GPU parts), but only one has a name.  */
2466   while (! name && (obj = IOIteratorNext (it)))
2467     {
2468       CFMutableDictionaryRef props;
2469       const void *val;
2471       if (IORegistryEntryCreateCFProperties (obj,
2472                                              &props,
2473                                              kCFAllocatorDefault,
2474                                              kNilOptions) == kIOReturnSuccess
2475           && props != nil
2476           && (val = CFDictionaryGetValue(props, @"IOFBDependentIndex")))
2477         {
2478           unsigned nr = [(NSNumber *)val unsignedIntegerValue];
2479           if (nr == CGDisplayUnitNumber (did))
2480             name = ns_get_name_from_ioreg (obj);
2481         }
2483       CFRelease (props);
2484       IOObjectRelease (obj);
2485     }
2487   IOObjectRelease (it);
2489 #else
2491   name = ns_get_name_from_ioreg (CGDisplayIOServicePort (did));
2493 #endif
2494   return name;
2496 #endif
2498 static Lisp_Object
2499 ns_make_monitor_attribute_list (struct MonitorInfo *monitors,
2500                                 int n_monitors,
2501                                 int primary_monitor,
2502                                 const char *source)
2504   Lisp_Object monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
2505   Lisp_Object frame, rest;
2506   NSArray *screens = [NSScreen screens];
2507   int i;
2509   FOR_EACH_FRAME (rest, frame)
2510     {
2511       struct frame *f = XFRAME (frame);
2513       if (FRAME_NS_P (f))
2514         {
2515           NSView *view = FRAME_NS_VIEW (f);
2516           NSScreen *screen = [[view window] screen];
2517           NSUInteger k;
2519           i = -1;
2520           for (k = 0; i == -1 && k < [screens count]; ++k)
2521             {
2522               if ([screens objectAtIndex: k] == screen)
2523                 i = (int)k;
2524             }
2526           if (i > -1)
2527             ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
2528         }
2529     }
2531   return make_monitor_attribute_list (monitors, n_monitors, primary_monitor,
2532                                       monitor_frames, source);
2535 DEFUN ("ns-display-monitor-attributes-list",
2536        Fns_display_monitor_attributes_list,
2537        Sns_display_monitor_attributes_list,
2538        0, 1, 0,
2539        doc: /* Return a list of physical monitor attributes on the X display TERMINAL.
2541 The optional argument TERMINAL specifies which display to ask about.
2542 TERMINAL should be a terminal object, a frame or a display name (a string).
2543 If omitted or nil, that stands for the selected frame's display.
2545 In addition to the standard attribute keys listed in
2546 `display-monitor-attributes-list', the following keys are contained in
2547 the attributes:
2549  source -- String describing the source from which multi-monitor
2550            information is obtained, \"NS\" is always the source."
2552 Internal use only, use `display-monitor-attributes-list' instead.  */)
2553   (Lisp_Object terminal)
2555   struct terminal *term = decode_live_terminal (terminal);
2556   NSArray *screens;
2557   NSUInteger i, n_monitors;
2558   struct MonitorInfo *monitors;
2559   Lisp_Object attributes_list = Qnil;
2560   CGFloat primary_display_height = 0;
2562   if (term->type != output_ns)
2563     return Qnil;
2565   screens = [NSScreen screens];
2566   n_monitors = [screens count];
2567   if (n_monitors == 0)
2568     return Qnil;
2570   monitors = xzalloc (n_monitors * sizeof *monitors);
2572   for (i = 0; i < [screens count]; ++i)
2573     {
2574       NSScreen *s = [screens objectAtIndex:i];
2575       struct MonitorInfo *m = &monitors[i];
2576       NSRect fr = [s frame];
2577       NSRect vfr = [s visibleFrame];
2578       short y, vy;
2580 #ifdef NS_IMPL_COCOA
2581       NSDictionary *dict = [s deviceDescription];
2582       NSNumber *nid = [dict objectForKey:@"NSScreenNumber"];
2583       CGDirectDisplayID did = [nid unsignedIntValue];
2584 #endif
2585       if (i == 0)
2586         {
2587           primary_display_height = fr.size.height;
2588           y = (short) fr.origin.y;
2589           vy = (short) vfr.origin.y;
2590         }
2591       else
2592         {
2593           // Flip y coordinate as NS has y starting from the bottom.
2594           y = (short) (primary_display_height - fr.size.height - fr.origin.y);
2595           vy = (short) (primary_display_height -
2596                         vfr.size.height - vfr.origin.y);
2597         }
2599       m->geom.x = (short) fr.origin.x;
2600       m->geom.y = y;
2601       m->geom.width = (unsigned short) fr.size.width;
2602       m->geom.height = (unsigned short) fr.size.height;
2604       m->work.x = (short) vfr.origin.x;
2605       // y is flipped on NS, so vy - y are pixels missing at the bottom,
2606       // and fr.size.height - vfr.size.height are pixels missing in total.
2607       // Pixels missing at top are
2608       // fr.size.height - vfr.size.height - vy + y.
2609       // work.y is then pixels missing at top + y.
2610       m->work.y = (short) (fr.size.height - vfr.size.height) - vy + y + y;
2611       m->work.width = (unsigned short) vfr.size.width;
2612       m->work.height = (unsigned short) vfr.size.height;
2614 #ifdef NS_IMPL_COCOA
2615       m->name = ns_screen_name (did);
2617       {
2618         CGSize mms = CGDisplayScreenSize (did);
2619         m->mm_width = (int) mms.width;
2620         m->mm_height = (int) mms.height;
2621       }
2623 #else
2624       // Assume 92 dpi as x-display-mm-height/x-display-mm-width does.
2625       m->mm_width = (int) (25.4 * fr.size.width / 92.0);
2626       m->mm_height = (int) (25.4 * fr.size.height / 92.0);
2627 #endif
2628     }
2630   // Primary monitor is always first for NS.
2631   attributes_list = ns_make_monitor_attribute_list (monitors, n_monitors,
2632                                                     0, "NS");
2634   free_monitors (monitors, n_monitors);
2635   return attributes_list;
2639 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
2640        0, 1, 0,
2641        doc: /* Return the number of bitplanes of the Nextstep display TERMINAL.
2642 The optional argument TERMINAL specifies which display to ask about.
2643 TERMINAL should be a terminal object, a frame or a display name (a string).
2644 If omitted or nil, that stands for the selected frame's display.  */)
2645   (Lisp_Object terminal)
2647   check_ns_display_info (terminal);
2648   return make_number
2649     (NSBitsPerPixelFromDepth ([[[NSScreen screens] objectAtIndex:0] depth]));
2653 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
2654        0, 1, 0,
2655        doc: /* Returns the number of color cells of the Nextstep display TERMINAL.
2656 The optional argument TERMINAL specifies which display to ask about.
2657 TERMINAL should be a terminal object, a frame or a display name (a string).
2658 If omitted or nil, that stands for the selected frame's display.  */)
2659   (Lisp_Object terminal)
2661   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
2662   /* We force 24+ bit depths to 24-bit to prevent an overflow.  */
2663   return make_number (1 << min (dpyinfo->n_planes, 24));
2667 /* Unused dummy def needed for compatibility. */
2668 Lisp_Object tip_frame;
2670 /* TODO: move to xdisp or similar */
2671 static void
2672 compute_tip_xy (struct frame *f,
2673                 Lisp_Object parms,
2674                 Lisp_Object dx,
2675                 Lisp_Object dy,
2676                 int width,
2677                 int height,
2678                 int *root_x,
2679                 int *root_y)
2681   Lisp_Object left, top, right, bottom;
2682   EmacsView *view = FRAME_NS_VIEW (f);
2683   struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2684   NSPoint pt;
2686   /* Start with user-specified or mouse position.  */
2687   left = Fcdr (Fassq (Qleft, parms));
2688   top = Fcdr (Fassq (Qtop, parms));
2689   right = Fcdr (Fassq (Qright, parms));
2690   bottom = Fcdr (Fassq (Qbottom, parms));
2692   if ((!INTEGERP (left) && !INTEGERP (right))
2693       || (!INTEGERP (top) && !INTEGERP (bottom)))
2694     {
2695       pt.x = dpyinfo->last_mouse_motion_x;
2696       pt.y = dpyinfo->last_mouse_motion_y;
2697       /* Convert to screen coordinates */
2698       pt = [view convertPoint: pt toView: nil];
2699 #if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
2700       pt = [[view window] convertBaseToScreen: pt];
2701 #else
2702       {
2703         NSRect r = NSMakeRect (pt.x, pt.y, 0, 0);
2704         r = [[view window] convertRectToScreen: r];
2705         pt.x = r.origin.x;
2706         pt.y = r.origin.y;
2707       }
2708 #endif
2709     }
2710   else
2711     {
2712       /* Absolute coordinates.  */
2713       pt.x = INTEGERP (left) ? XINT (left) : XINT (right);
2714       pt.y = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
2715               - (INTEGERP (top) ? XINT (top) : XINT (bottom))
2716               - height);
2717     }
2719   /* Ensure in bounds.  (Note, screen origin = lower left.) */
2720   if (INTEGERP (left) || INTEGERP (right))
2721     *root_x = pt.x;
2722   else if (pt.x + XINT (dx) <= 0)
2723     *root_x = 0; /* Can happen for negative dx */
2724   else if (pt.x + XINT (dx) + width
2725            <= x_display_pixel_width (FRAME_DISPLAY_INFO (f)))
2726     /* It fits to the right of the pointer.  */
2727     *root_x = pt.x + XINT (dx);
2728   else if (width + XINT (dx) <= pt.x)
2729     /* It fits to the left of the pointer.  */
2730     *root_x = pt.x - width - XINT (dx);
2731   else
2732     /* Put it left justified on the screen -- it ought to fit that way.  */
2733     *root_x = 0;
2735   if (INTEGERP (top) || INTEGERP (bottom))
2736     *root_y = pt.y;
2737   else if (pt.y - XINT (dy) - height >= 0)
2738     /* It fits below the pointer.  */
2739     *root_y = pt.y - height - XINT (dy);
2740   else if (pt.y + XINT (dy) + height
2741            <= x_display_pixel_height (FRAME_DISPLAY_INFO (f)))
2742     /* It fits above the pointer */
2743       *root_y = pt.y + XINT (dy);
2744   else
2745     /* Put it on the top.  */
2746     *root_y = x_display_pixel_height (FRAME_DISPLAY_INFO (f)) - height;
2750 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
2751        doc: /* Show STRING in a \"tooltip\" window on frame FRAME.
2752 A tooltip window is a small window displaying a string.
2754 This is an internal function; Lisp code should call `tooltip-show'.
2756 FRAME nil or omitted means use the selected frame.
2758 PARMS is an optional list of frame parameters which can be used to
2759 change the tooltip's appearance.
2761 Automatically hide the tooltip after TIMEOUT seconds.  TIMEOUT nil
2762 means use the default timeout of 5 seconds.
2764 If the list of frame parameters PARMS contains a `left' parameter,
2765 display the tooltip at that x-position.  If the list of frame parameters
2766 PARMS contains no `left' but a `right' parameter, display the tooltip
2767 right-adjusted at that x-position. Otherwise display it at the
2768 x-position of the mouse, with offset DX added (default is 5 if DX isn't
2769 specified).
2771 Likewise for the y-position: If a `top' frame parameter is specified, it
2772 determines the position of the upper edge of the tooltip window.  If a
2773 `bottom' parameter but no `top' frame parameter is specified, it
2774 determines the position of the lower edge of the tooltip window.
2775 Otherwise display the tooltip window at the y-position of the mouse,
2776 with offset DY added (default is -10).
2778 A tooltip's maximum size is specified by `x-max-tooltip-size'.
2779 Text larger than the specified size is clipped.  */)
2780      (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
2782   int root_x, root_y;
2783   ptrdiff_t count = SPECPDL_INDEX ();
2784   struct frame *f;
2785   char *str;
2786   NSSize size;
2788   specbind (Qinhibit_redisplay, Qt);
2790   CHECK_STRING (string);
2791   str = SSDATA (string);
2792   f = decode_window_system_frame (frame);
2793   if (NILP (timeout))
2794     timeout = make_number (5);
2795   else
2796     CHECK_NATNUM (timeout);
2798   if (NILP (dx))
2799     dx = make_number (5);
2800   else
2801     CHECK_NUMBER (dx);
2803   if (NILP (dy))
2804     dy = make_number (-10);
2805   else
2806     CHECK_NUMBER (dy);
2808   block_input ();
2809   if (ns_tooltip == nil)
2810     ns_tooltip = [[EmacsTooltip alloc] init];
2811   else
2812     Fx_hide_tip ();
2814   [ns_tooltip setText: str];
2815   size = [ns_tooltip frame].size;
2817   /* Move the tooltip window where the mouse pointer is.  Resize and
2818      show it.  */
2819   compute_tip_xy (f, parms, dx, dy, (int)size.width, (int)size.height,
2820                   &root_x, &root_y);
2822   [ns_tooltip showAtX: root_x Y: root_y for: XINT (timeout)];
2823   unblock_input ();
2825   return unbind_to (count, Qnil);
2829 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
2830        doc: /* Hide the current tooltip window, if there is any.
2831 Value is t if tooltip was open, nil otherwise.  */)
2832      (void)
2834   if (ns_tooltip == nil || ![ns_tooltip isActive])
2835     return Qnil;
2836   [ns_tooltip hide];
2837   return Qt;
2840 /* Return geometric attributes of FRAME.  According to the value of
2841    ATTRIBUTES return the outer edges of FRAME (Qouter_edges), the inner
2842    edges of FRAME, the root window edges of frame (Qroot_edges).  Any
2843    other value means to return the geometry as returned by
2844    Fx_frame_geometry.  */
2845 static Lisp_Object
2846 frame_geometry (Lisp_Object frame, Lisp_Object attribute)
2848   struct frame *f = decode_live_frame (frame);
2849   Lisp_Object fullscreen_symbol = Fframe_parameter (frame, Qfullscreen);
2850   bool fullscreen = (EQ (fullscreen_symbol, Qfullboth)
2851                      || EQ (fullscreen_symbol, Qfullscreen));
2852   int border = fullscreen ? 0 : f->border_width;
2853   int title_height = fullscreen ? 0 : FRAME_NS_TITLEBAR_HEIGHT (f);
2854   int native_width = FRAME_PIXEL_WIDTH (f);
2855   int native_height = FRAME_PIXEL_HEIGHT (f);
2856   int outer_width = native_width + 2 * border;
2857   int outer_height = native_height + 2 * border + title_height;
2858   int native_left = f->left_pos + border;
2859   int native_top = f->top_pos + border + title_height;
2860   int native_right = f->left_pos + outer_width - border;
2861   int native_bottom = f->top_pos + outer_height - border;
2862   int internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
2863   int tool_bar_height = FRAME_TOOLBAR_HEIGHT (f);
2864   int tool_bar_width = (tool_bar_height
2865                         ? outer_width - 2 * internal_border_width
2866                         : 0);
2868   /* Construct list.  */
2869   if (EQ (attribute, Qouter_edges))
2870     return list4 (make_number (f->left_pos), make_number (f->top_pos),
2871                   make_number (f->left_pos + outer_width),
2872                   make_number (f->top_pos + outer_height));
2873   else if (EQ (attribute, Qnative_edges))
2874     return list4 (make_number (native_left), make_number (native_top),
2875                   make_number (native_right), make_number (native_bottom));
2876   else if (EQ (attribute, Qinner_edges))
2877     return list4 (make_number (native_left + internal_border_width),
2878                   make_number (native_top
2879                                + tool_bar_height
2880                                + internal_border_width),
2881                   make_number (native_right - internal_border_width),
2882                   make_number (native_bottom - internal_border_width));
2883   else
2884     return
2885       listn (CONSTYPE_HEAP, 10,
2886              Fcons (Qouter_position,
2887                     Fcons (make_number (f->left_pos),
2888                            make_number (f->top_pos))),
2889              Fcons (Qouter_size,
2890                     Fcons (make_number (outer_width),
2891                            make_number (outer_height))),
2892              Fcons (Qexternal_border_size,
2893                     (fullscreen
2894                      ? Fcons (make_number (0), make_number (0))
2895                      : Fcons (make_number (border), make_number (border)))),
2896              Fcons (Qtitle_bar_size,
2897                     Fcons (make_number (0), make_number (title_height))),
2898              Fcons (Qmenu_bar_external, Qnil),
2899              Fcons (Qmenu_bar_size, Fcons (make_number (0), make_number (0))),
2900              Fcons (Qtool_bar_external,
2901                     FRAME_EXTERNAL_TOOL_BAR (f) ? Qt : Qnil),
2902              Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)),
2903              Fcons (Qtool_bar_size,
2904                     Fcons (make_number (tool_bar_width),
2905                            make_number (tool_bar_height))),
2906              Fcons (Qinternal_border_width,
2907                     make_number (internal_border_width)));
2910 DEFUN ("ns-frame-geometry", Fns_frame_geometry, Sns_frame_geometry, 0, 1, 0,
2911        doc: /* Return geometric attributes of FRAME.
2912 FRAME must be a live frame and defaults to the selected one.  The return
2913 value is an association list of the attributes listed below.  All height
2914 and width values are in pixels.
2916 `outer-position' is a cons of the outer left and top edges of FRAME
2917   relative to the origin - the position (0, 0) - of FRAME's display.
2919 `outer-size' is a cons of the outer width and height of FRAME.  The
2920   outer size includes the title bar and the external borders as well as
2921   any menu and/or tool bar of frame.
2923 `external-border-size' is a cons of the horizontal and vertical width of
2924   FRAME's external borders as supplied by the window manager.
2926 `title-bar-size' is a cons of the width and height of the title bar of
2927   FRAME as supplied by the window manager.  If both of them are zero,
2928   FRAME has no title bar.  If only the width is zero, Emacs was not
2929   able to retrieve the width information.
2931 `menu-bar-external', if non-nil, means the menu bar is external (never
2932   included in the inner edges of FRAME).
2934 `menu-bar-size' is a cons of the width and height of the menu bar of
2935   FRAME.
2937 `tool-bar-external', if non-nil, means the tool bar is external (never
2938   included in the inner edges of FRAME).
2940 `tool-bar-position' tells on which side the tool bar on FRAME is and can
2941   be one of `left', `top', `right' or `bottom'.  If this is nil, FRAME
2942   has no tool bar.
2944 `tool-bar-size' is a cons of the width and height of the tool bar of
2945   FRAME.
2947 `internal-border-width' is the width of the internal border of
2948   FRAME.  */)
2949   (Lisp_Object frame)
2951   return frame_geometry (frame, Qnil);
2954 DEFUN ("ns-frame-edges", Fns_frame_edges, Sns_frame_edges, 0, 2, 0,
2955        doc: /* Return edge coordinates of FRAME.
2956 FRAME must be a live frame and defaults to the selected one.  The return
2957 value is a list of the form (LEFT, TOP, RIGHT, BOTTOM).  All values are
2958 in pixels relative to the origin - the position (0, 0) - of FRAME's
2959 display.
2961 If optional argument TYPE is the symbol `outer-edges', return the outer
2962 edges of FRAME.  The outer edges comprise the decorations of the window
2963 manager (like the title bar or external borders) as well as any external
2964 menu or tool bar of FRAME.  If optional argument TYPE is the symbol
2965 `native-edges' or nil, return the native edges of FRAME.  The native
2966 edges exclude the decorations of the window manager and any external
2967 menu or tool bar of FRAME.  If TYPE is the symbol `inner-edges', return
2968 the inner edges of FRAME.  These edges exclude title bar, any borders,
2969 menu bar or tool bar of FRAME.  */)
2970   (Lisp_Object frame, Lisp_Object type)
2972   return frame_geometry (frame, ((EQ (type, Qouter_edges)
2973                                   || EQ (type, Qinner_edges))
2974                                  ? type
2975                                  : Qnative_edges));
2978 /* ==========================================================================
2980     Class implementations
2982    ========================================================================== */
2985   Handle arrow/function/control keys and copy/paste/cut in file dialogs.
2986   Return YES if handled, NO if not.
2987  */
2988 static BOOL
2989 handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent)
2991   NSString *s;
2992   int i;
2993   BOOL ret = NO;
2995   if ([theEvent type] != NSKeyDown) return NO;
2996   s = [theEvent characters];
2998   for (i = 0; i < [s length]; ++i)
2999     {
3000       int ch = (int) [s characterAtIndex: i];
3001       switch (ch)
3002         {
3003         case NSHomeFunctionKey:
3004         case NSDownArrowFunctionKey:
3005         case NSUpArrowFunctionKey:
3006         case NSLeftArrowFunctionKey:
3007         case NSRightArrowFunctionKey:
3008         case NSPageUpFunctionKey:
3009         case NSPageDownFunctionKey:
3010         case NSEndFunctionKey:
3011           /* Don't send command modified keys, as those are handled in the
3012              performKeyEquivalent method of the super class.
3013           */
3014           if (! ([theEvent modifierFlags] & NSCommandKeyMask))
3015             {
3016               [panel sendEvent: theEvent];
3017               ret = YES;
3018             }
3019           break;
3020           /* As we don't have the standard key commands for
3021              copy/paste/cut/select-all in our edit menu, we must handle
3022              them here.  TODO: handle Emacs key bindings for copy/cut/select-all
3023              here, paste works, because we have that in our Edit menu.
3024              I.e. refactor out code in nsterm.m, keyDown: to figure out the
3025              correct modifier.
3026           */
3027         case 'x': // Cut
3028         case 'c': // Copy
3029         case 'v': // Paste
3030         case 'a': // Select all
3031           if ([theEvent modifierFlags] & NSCommandKeyMask)
3032             {
3033               [NSApp sendAction:
3034                        (ch == 'x'
3035                         ? @selector(cut:)
3036                         : (ch == 'c'
3037                            ? @selector(copy:)
3038                            : (ch == 'v'
3039                               ? @selector(paste:)
3040                               : @selector(selectAll:))))
3041                              to:nil from:panel];
3042               ret = YES;
3043             }
3044         default:
3045           // Send all control keys, as the text field supports C-a, C-f, C-e
3046           // C-b and more.
3047           if ([theEvent modifierFlags] & NSControlKeyMask)
3048             {
3049               [panel sendEvent: theEvent];
3050               ret = YES;
3051             }
3052           break;
3053         }
3054     }
3057   return ret;
3060 @implementation EmacsSavePanel
3061 - (BOOL)performKeyEquivalent:(NSEvent *)theEvent
3063   BOOL ret = handlePanelKeys (self, theEvent);
3064   if (! ret)
3065     ret = [super performKeyEquivalent:theEvent];
3066   return ret;
3068 @end
3071 @implementation EmacsOpenPanel
3072 - (BOOL)performKeyEquivalent:(NSEvent *)theEvent
3074   // NSOpenPanel inherits NSSavePanel, so passing self is OK.
3075   BOOL ret = handlePanelKeys (self, theEvent);
3076   if (! ret)
3077     ret = [super performKeyEquivalent:theEvent];
3078   return ret;
3080 @end
3083 @implementation EmacsFileDelegate
3084 /* --------------------------------------------------------------------------
3085    Delegate methods for Open/Save panels
3086    -------------------------------------------------------------------------- */
3087 - (BOOL)panel: (id)sender isValidFilename: (NSString *)filename
3089   return YES;
3091 - (BOOL)panel: (id)sender shouldShowFilename: (NSString *)filename
3093   return YES;
3095 - (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename
3096           confirmed: (BOOL)okFlag
3098   return filename;
3100 @end
3102 #endif
3105 /* ==========================================================================
3107     Lisp interface declaration
3109    ========================================================================== */
3112 void
3113 syms_of_nsfns (void)
3115   DEFSYM (Qfontsize, "fontsize");
3117   DEFVAR_LISP ("ns-icon-type-alist", Vns_icon_type_alist,
3118                doc: /* Alist of elements (REGEXP . IMAGE) for images of icons associated to frames.
3119 If the title of a frame matches REGEXP, then IMAGE.tiff is
3120 selected as the image of the icon representing the frame when it's
3121 miniaturized.  If an element is t, then Emacs tries to select an icon
3122 based on the filetype of the visited file.
3124 The images have to be installed in a folder called English.lproj in the
3125 Emacs folder.  You have to restart Emacs after installing new icons.
3127 Example: Install an icon Gnus.tiff and execute the following code
3129   (setq ns-icon-type-alist
3130         (append ns-icon-type-alist
3131                 '((\"^\\\\*\\\\(Group\\\\*$\\\\|Summary \\\\|Article\\\\*$\\\\)\"
3132                    . \"Gnus\"))))
3134 When you miniaturize a Group, Summary or Article frame, Gnus.tiff will
3135 be used as the image of the icon representing the frame.  */);
3136   Vns_icon_type_alist = list1 (Qt);
3138   DEFVAR_LISP ("ns-version-string", Vns_version_string,
3139                doc: /* Toolkit version for NS Windowing.  */);
3140   Vns_version_string = ns_appkit_version_str ();
3142   defsubr (&Sns_read_file_name);
3143   defsubr (&Sns_get_resource);
3144   defsubr (&Sns_set_resource);
3145   defsubr (&Sxw_display_color_p); /* this and next called directly by C code */
3146   defsubr (&Sx_display_grayscale_p);
3147   defsubr (&Sns_font_name);
3148   defsubr (&Sns_list_colors);
3149 #ifdef NS_IMPL_COCOA
3150   defsubr (&Sns_do_applescript);
3151 #endif
3152   defsubr (&Sxw_color_defined_p);
3153   defsubr (&Sxw_color_values);
3154   defsubr (&Sx_server_max_request_size);
3155   defsubr (&Sx_server_vendor);
3156   defsubr (&Sx_server_version);
3157   defsubr (&Sx_display_pixel_width);
3158   defsubr (&Sx_display_pixel_height);
3159   defsubr (&Sns_display_monitor_attributes_list);
3160   defsubr (&Sns_frame_geometry);
3161   defsubr (&Sns_frame_edges);
3162   defsubr (&Sx_display_mm_width);
3163   defsubr (&Sx_display_mm_height);
3164   defsubr (&Sx_display_screens);
3165   defsubr (&Sx_display_planes);
3166   defsubr (&Sx_display_color_cells);
3167   defsubr (&Sx_display_visual_class);
3168   defsubr (&Sx_display_backing_store);
3169   defsubr (&Sx_display_save_under);
3170   defsubr (&Sx_create_frame);
3171   defsubr (&Sx_open_connection);
3172   defsubr (&Sx_close_connection);
3173   defsubr (&Sx_display_list);
3175   defsubr (&Sns_hide_others);
3176   defsubr (&Sns_hide_emacs);
3177   defsubr (&Sns_emacs_info_panel);
3178   defsubr (&Sns_list_services);
3179   defsubr (&Sns_perform_service);
3180   defsubr (&Sns_convert_utf8_nfd_to_nfc);
3181   defsubr (&Sns_popup_font_panel);
3182   defsubr (&Sns_popup_color_panel);
3184   defsubr (&Sx_show_tip);
3185   defsubr (&Sx_hide_tip);
3187   as_status = 0;
3188   as_script = Qnil;
3189   as_result = 0;