* .gitignore: Avoid "**", as it requires Git 1.8.2 or later.
[emacs.git] / src / nsfns.m
blobe0f8cfee14a5993bd20b44eedd624d2959244ea7
1 /* Functions for the NeXT/Open/GNUstep and MacOSX window system.
3 Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2014 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 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
50 #include "macfont.h"
51 #endif
52 #endif
54 #if 0
55 int fns_trace_num = 1;
56 #define NSTRACE(x)        fprintf (stderr, "%s:%d: [%d] " #x "\n",        \
57                                   __FILE__, __LINE__, ++fns_trace_num)
58 #else
59 #define NSTRACE(x)
60 #endif
62 #ifdef HAVE_NS
64 extern NSArray *ns_send_types, *ns_return_types, *ns_drag_types;
66 extern Lisp_Object Qforeground_color;
67 extern Lisp_Object Qbackground_color;
68 extern Lisp_Object Qcursor_color;
69 extern Lisp_Object Qinternal_border_width;
70 extern Lisp_Object Qvisibility;
71 extern Lisp_Object Qcursor_type;
72 extern Lisp_Object Qicon_type;
73 extern Lisp_Object Qicon_name;
74 extern Lisp_Object Qicon_left;
75 extern Lisp_Object Qicon_top;
76 extern Lisp_Object Qleft;
77 extern Lisp_Object Qright;
78 extern Lisp_Object Qtop;
79 extern Lisp_Object Qdisplay;
80 extern Lisp_Object Qvertical_scroll_bars;
81 extern Lisp_Object Qauto_raise;
82 extern Lisp_Object Qauto_lower;
83 extern Lisp_Object Qbox;
84 extern Lisp_Object Qscroll_bar_width;
85 extern Lisp_Object Qx_resource_name;
86 extern Lisp_Object Qface_set_after_frame_default;
87 extern Lisp_Object Qunderline, Qundefined;
88 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
89 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
92 Lisp_Object Qbuffered;
93 Lisp_Object Qfontsize;
95 EmacsTooltip *ns_tooltip = nil;
97 /* Need forward declaration here to preserve organizational integrity of file */
98 Lisp_Object Fx_open_connection (Lisp_Object, Lisp_Object, Lisp_Object);
100 /* Static variables to handle applescript execution.  */
101 static Lisp_Object as_script, *as_result;
102 static int as_status;
104 #ifdef GLYPH_DEBUG
105 static ptrdiff_t image_cache_refcount;
106 #endif
109 /* ==========================================================================
111     Internal utility functions
113    ========================================================================== */
115 /* Let the user specify a Nextstep display with a Lisp object.
116    OBJECT may be nil, a frame or a terminal object.
117    nil stands for the selected frame--or, if that is not a Nextstep frame,
118    the first Nextstep display on the list.  */
120 static struct ns_display_info *
121 check_ns_display_info (Lisp_Object object)
123   struct ns_display_info *dpyinfo = NULL;
125   if (NILP (object))
126     {
127       struct frame *sf = XFRAME (selected_frame);
129       if (FRAME_NS_P (sf) && FRAME_LIVE_P (sf))
130         dpyinfo = FRAME_DISPLAY_INFO (sf);
131       else if (x_display_list != 0)
132         dpyinfo = x_display_list;
133       else
134         error ("Nextstep windows are not in use or not initialized");
135     }
136   else if (TERMINALP (object))
137     {
138       struct terminal *t = get_terminal (object, 1);
140       if (t->type != output_ns)
141         error ("Terminal %d is not a Nextstep display", t->id);
143       dpyinfo = t->display_info.ns;
144     }
145   else if (STRINGP (object))
146     dpyinfo = ns_display_info_for_name (object);
147   else
148     {
149       struct frame *f = decode_window_system_frame (object);
150       dpyinfo = FRAME_DISPLAY_INFO (f);
151     }
153   return dpyinfo;
157 static id
158 ns_get_window (Lisp_Object maybeFrame)
160   id view =nil, window =nil;
162   if (!FRAMEP (maybeFrame) || !FRAME_NS_P (XFRAME (maybeFrame)))
163     maybeFrame = selected_frame;/*wrong_type_argument (Qframep, maybeFrame); */
165   if (!NILP (maybeFrame))
166     view = FRAME_NS_VIEW (XFRAME (maybeFrame));
167   if (view) window =[view window];
169   return window;
173 /* Return the X display structure for the display named NAME.
174    Open a new connection if necessary.  */
175 struct ns_display_info *
176 ns_display_info_for_name (Lisp_Object name)
178   struct ns_display_info *dpyinfo;
180   CHECK_STRING (name);
182   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
183     if (!NILP (Fstring_equal (XCAR (dpyinfo->name_list_element), name)))
184       return dpyinfo;
186   error ("Emacs for Nextstep does not yet support multi-display");
188   Fx_open_connection (name, Qnil, Qnil);
189   dpyinfo = x_display_list;
191   if (dpyinfo == 0)
192     error ("Display on %s not responding.\n", SDATA (name));
194   return dpyinfo;
197 static NSString *
198 ns_filename_from_panel (NSSavePanel *panel)
200 #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
201   NSURL *url = [panel URL];
202   NSString *str = [url path];
203   return str;
204 #else
205   return [panel filename];
206 #endif
209 static NSString *
210 ns_directory_from_panel (NSSavePanel *panel)
212 #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
213   NSURL *url = [panel directoryURL];
214   NSString *str = [url path];
215   return str;
216 #else
217   return [panel directory];
218 #endif
221 static Lisp_Object
222 interpret_services_menu (NSMenu *menu, Lisp_Object prefix, Lisp_Object old)
223 /* --------------------------------------------------------------------------
224    Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side
225    -------------------------------------------------------------------------- */
227   int i, count;
228   NSMenuItem *item;
229   const char *name;
230   Lisp_Object nameStr;
231   unsigned short key;
232   NSString *keys;
233   Lisp_Object res;
235   count = [menu numberOfItems];
236   for (i = 0; i<count; i++)
237     {
238       item = [menu itemAtIndex: i];
239       name = [[item title] UTF8String];
240       if (!name) continue;
242       nameStr = build_string (name);
244       if ([item hasSubmenu])
245         {
246           old = interpret_services_menu ([item submenu],
247                                         Fcons (nameStr, prefix), old);
248         }
249       else
250         {
251           keys = [item keyEquivalent];
252           if (keys && [keys length] )
253             {
254               key = [keys characterAtIndex: 0];
255               res = make_number (key|super_modifier);
256             }
257           else
258             {
259               res = Qundefined;
260             }
261           old = Fcons (Fcons (res,
262                             Freverse (Fcons (nameStr,
263                                            prefix))),
264                     old);
265         }
266     }
267   return old;
272 /* ==========================================================================
274     Frame parameter setters
276    ========================================================================== */
279 static void
280 x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
282   NSColor *col;
283   EmacsCGFloat r, g, b, alpha;
285   /* Must block_input, because ns_lisp_to_color does block/unblock_input
286      which means that col may be deallocated in its unblock_input if there
287      is user input, unless we also block_input.  */
288   block_input ();
289   if (ns_lisp_to_color (arg, &col))
290     {
291       store_frame_param (f, Qforeground_color, oldval);
292       unblock_input ();
293       error ("Unknown color");
294     }
296   [col retain];
297   [f->output_data.ns->foreground_color release];
298   f->output_data.ns->foreground_color = col;
300   [col getRed: &r green: &g blue: &b alpha: &alpha];
301   FRAME_FOREGROUND_PIXEL (f) =
302     ARGB_TO_ULONG ((int)(alpha*0xff), (int)(r*0xff), (int)(g*0xff), (int)(b*0xff));
304   if (FRAME_NS_VIEW (f))
305     {
306       update_face_from_frame_parameter (f, Qforeground_color, arg);
307       /*recompute_basic_faces (f); */
308       if (FRAME_VISIBLE_P (f))
309         SET_FRAME_GARBAGED (f);
310     }
311   unblock_input ();
315 static void
316 x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
318   struct face *face;
319   NSColor *col;
320   NSView *view = FRAME_NS_VIEW (f);
321   EmacsCGFloat r, g, b, alpha;
323   block_input ();
324   if (ns_lisp_to_color (arg, &col))
325     {
326       store_frame_param (f, Qbackground_color, oldval);
327       unblock_input ();
328       error ("Unknown color");
329     }
331   /* clear the frame; in some instances the NS-internal GC appears not to
332      update, or it does update and cannot clear old text properly */
333   if (FRAME_VISIBLE_P (f))
334     ns_clear_frame (f);
336   [col retain];
337   [f->output_data.ns->background_color release];
338   f->output_data.ns->background_color = col;
340   [col getRed: &r green: &g blue: &b alpha: &alpha];
341   FRAME_BACKGROUND_PIXEL (f) =
342     ARGB_TO_ULONG ((int)(alpha*0xff), (int)(r*0xff), (int)(g*0xff), (int)(b*0xff));
344   if (view != nil)
345     {
346       [[view window] setBackgroundColor: col];
348       if (alpha != (EmacsCGFloat) 1.0)
349           [[view window] setOpaque: NO];
350       else
351           [[view window] setOpaque: YES];
353       face = FRAME_DEFAULT_FACE (f);
354       if (face)
355         {
356           col = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f);
357           face->background = ns_index_color
358             ([col colorWithAlphaComponent: alpha], f);
360           update_face_from_frame_parameter (f, Qbackground_color, arg);
361         }
363       if (FRAME_VISIBLE_P (f))
364         SET_FRAME_GARBAGED (f);
365     }
366   unblock_input ();
370 static void
371 x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
373   NSColor *col;
375   block_input ();
376   if (ns_lisp_to_color (arg, &col))
377     {
378       store_frame_param (f, Qcursor_color, oldval);
379       unblock_input ();
380       error ("Unknown color");
381     }
383   [FRAME_CURSOR_COLOR (f) release];
384   FRAME_CURSOR_COLOR (f) = [col retain];
386   if (FRAME_VISIBLE_P (f))
387     {
388       x_update_cursor (f, 0);
389       x_update_cursor (f, 1);
390     }
391   update_face_from_frame_parameter (f, Qcursor_color, arg);
392   unblock_input ();
396 static void
397 x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
399   NSView *view = FRAME_NS_VIEW (f);
400   NSTRACE (x_set_icon_name);
402   /* see if it's changed */
403   if (STRINGP (arg))
404     {
405       if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
406         return;
407     }
408   else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
409     return;
411   fset_icon_name (f, arg);
413   if (NILP (arg))
414     {
415       if (!NILP (f->title))
416         arg = f->title;
417       else
418         /* Explicit name and no icon-name -> explicit_name.  */
419         if (f->explicit_name)
420           arg = f->name;
421         else
422           {
423             /* No explicit name and no icon-name ->
424                name has to be rebuild from icon_title_format.  */
425             windows_or_buffers_changed = 62;
426             return;
427           }
428     }
430   /* Don't change the name if it's already NAME.  */
431   if ([[view window] miniwindowTitle]
432       && ([[[view window] miniwindowTitle]
433              isEqualToString: [NSString stringWithUTF8String:
434                                           SSDATA (arg)]]))
435     return;
437   [[view window] setMiniwindowTitle:
438         [NSString stringWithUTF8String: SSDATA (arg)]];
441 static void
442 ns_set_name_internal (struct frame *f, Lisp_Object name)
444   struct gcpro gcpro1;
445   Lisp_Object encoded_name, encoded_icon_name;
446   NSString *str;
447   NSView *view = FRAME_NS_VIEW (f);
449   GCPRO1 (name);
450   encoded_name = ENCODE_UTF_8 (name);
451   UNGCPRO;
453   str = [NSString stringWithUTF8String: SSDATA (encoded_name)];
455   /* Don't change the name if it's already NAME.  */
456   if (! [[[view window] title] isEqualToString: str])
457     [[view window] setTitle: str];
459   if (!STRINGP (f->icon_name))
460     encoded_icon_name = encoded_name;
461   else
462     encoded_icon_name = ENCODE_UTF_8 (f->icon_name);
464   str = [NSString stringWithUTF8String: SSDATA (encoded_icon_name)];
466   if ([[view window] miniwindowTitle]
467       && ! [[[view window] miniwindowTitle] isEqualToString: str])
468     [[view window] setMiniwindowTitle: str];
472 static void
473 ns_set_name (struct frame *f, Lisp_Object name, int explicit)
475   NSTRACE (ns_set_name);
477   /* Make sure that requests from lisp code override requests from
478      Emacs redisplay code.  */
479   if (explicit)
480     {
481       /* If we're switching from explicit to implicit, we had better
482          update the mode lines and thereby update the title.  */
483       if (f->explicit_name && NILP (name))
484         update_mode_lines = 21;
486       f->explicit_name = ! NILP (name);
487     }
488   else if (f->explicit_name)
489     return;
491   if (NILP (name))
492     name = build_string ([ns_app_name UTF8String]);
493   else
494     CHECK_STRING (name);
496   /* Don't change the name if it's already NAME.  */
497   if (! NILP (Fstring_equal (name, f->name)))
498     return;
500   fset_name (f, name);
502   /* Title overrides explicit name.  */
503   if (! NILP (f->title))
504     name = f->title;
506   ns_set_name_internal (f, name);
510 /* This function should be called when the user's lisp code has
511    specified a name for the frame; the name will override any set by the
512    redisplay code.  */
513 static void
514 x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
516   NSTRACE (x_explicitly_set_name);
517   ns_set_name (f, arg, 1);
521 /* This function should be called by Emacs redisplay code to set the
522    name; names set this way will never override names set by the user's
523    lisp code.  */
524 void
525 x_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
527   NSTRACE (x_implicitly_set_name);
529   /* Deal with NS specific format t.  */
530   if (FRAME_NS_P (f) && ((FRAME_ICONIFIED_P (f) && EQ (Vicon_title_format, Qt))
531                          || EQ (Vframe_title_format, Qt)))
532     ns_set_name_as_filename (f);
533   else
534     ns_set_name (f, arg, 0);
538 /* Change the title of frame F to NAME.
539    If NAME is nil, use the frame name as the title.  */
541 static void
542 x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
544   NSTRACE (x_set_title);
545   /* Don't change the title if it's already NAME.  */
546   if (EQ (name, f->title))
547     return;
549   update_mode_lines = 22;
551   fset_title (f, name);
553   if (NILP (name))
554     name = f->name;
555   else
556     CHECK_STRING (name);
558   ns_set_name_internal (f, name);
562 void
563 ns_set_name_as_filename (struct frame *f)
565   NSView *view;
566   Lisp_Object name, filename;
567   Lisp_Object buf = XWINDOW (f->selected_window)->contents;
568   const char *title;
569   NSAutoreleasePool *pool;
570   struct gcpro gcpro1;
571   Lisp_Object encoded_name, encoded_filename;
572   NSString *str;
573   NSTRACE (ns_set_name_as_filename);
575   if (f->explicit_name || ! NILP (f->title))
576     return;
578   block_input ();
579   pool = [[NSAutoreleasePool alloc] init];
580   filename = BVAR (XBUFFER (buf), filename);
581   name = BVAR (XBUFFER (buf), name);
583   if (NILP (name))
584     {
585       if (! NILP (filename))
586         name = Ffile_name_nondirectory (filename);
587       else
588         name = build_string ([ns_app_name UTF8String]);
589     }
591   GCPRO1 (name);
592   encoded_name = ENCODE_UTF_8 (name);
593   UNGCPRO;
595   view = FRAME_NS_VIEW (f);
597   title = FRAME_ICONIFIED_P (f) ? [[[view window] miniwindowTitle] UTF8String]
598                                 : [[[view window] title] UTF8String];
600   if (title && (! strcmp (title, SSDATA (encoded_name))))
601     {
602       [pool release];
603       unblock_input ();
604       return;
605     }
607   str = [NSString stringWithUTF8String: SSDATA (encoded_name)];
608   if (str == nil) str = @"Bad coding";
610   if (FRAME_ICONIFIED_P (f))
611     [[view window] setMiniwindowTitle: str];
612   else
613     {
614       NSString *fstr;
616       if (! NILP (filename))
617         {
618           GCPRO1 (filename);
619           encoded_filename = ENCODE_UTF_8 (filename);
620           UNGCPRO;
622           fstr = [NSString stringWithUTF8String: SSDATA (encoded_filename)];
623           if (fstr == nil) fstr = @"";
624 #ifdef NS_IMPL_COCOA
625           /* work around a bug observed on 10.3 and later where
626              setTitleWithRepresentedFilename does not clear out previous state
627              if given filename does not exist */
628           if (! [[NSFileManager defaultManager] fileExistsAtPath: fstr])
629             [[view window] setRepresentedFilename: @""];
630 #endif
631         }
632       else
633         fstr = @"";
635       [[view window] setRepresentedFilename: fstr];
636       [[view window] setTitle: str];
637       fset_name (f, name);
638     }
640   [pool release];
641   unblock_input ();
645 void
646 ns_set_doc_edited (void)
648   NSAutoreleasePool *pool;
649   Lisp_Object tail, frame;
650   block_input ();
651   pool = [[NSAutoreleasePool alloc] init];
652   FOR_EACH_FRAME (tail, frame)
653     {
654       BOOL edited = NO;
655       struct frame *f = XFRAME (frame);
656       struct window *w;
657       NSView *view;
659       if (! FRAME_NS_P (f)) continue;
660       w = XWINDOW (FRAME_SELECTED_WINDOW (f));
661       view = FRAME_NS_VIEW (f);
662       if (!MINI_WINDOW_P (w))
663         edited = ! NILP (Fbuffer_modified_p (w->contents)) &&
664           ! NILP (Fbuffer_file_name (w->contents));
665       [[view window] setDocumentEdited: edited];
666     }
668   [pool release];
669   unblock_input ();
673 void
674 x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
676   int nlines;
677   if (FRAME_MINIBUF_ONLY_P (f))
678     return;
680   if (TYPE_RANGED_INTEGERP (int, value))
681     nlines = XINT (value);
682   else
683     nlines = 0;
685   FRAME_MENU_BAR_LINES (f) = 0;
686   if (nlines)
687     {
688       FRAME_EXTERNAL_MENU_BAR (f) = 1;
689       /* does for all frames, whereas we just want for one frame
690          [NSMenu setMenuBarVisible: YES]; */
691     }
692   else
693     {
694       if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
695         free_frame_menubar (f);
696       /*      [NSMenu setMenuBarVisible: NO]; */
697       FRAME_EXTERNAL_MENU_BAR (f) = 0;
698     }
702 /* toolbar support */
703 void
704 x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
706   int nlines;
708   if (FRAME_MINIBUF_ONLY_P (f))
709     return;
711   if (RANGED_INTEGERP (0, value, INT_MAX))
712     nlines = XFASTINT (value);
713   else
714     nlines = 0;
716   if (nlines)
717     {
718       FRAME_EXTERNAL_TOOL_BAR (f) = 1;
719       update_frame_tool_bar (f);
720     }
721   else
722     {
723       if (FRAME_EXTERNAL_TOOL_BAR (f))
724         {
725           free_frame_tool_bar (f);
726           FRAME_EXTERNAL_TOOL_BAR (f) = 0;
727         }
728     }
730   x_set_window_size (f, 0, f->text_cols, f->text_lines, 0);
734 static void
735 ns_implicitly_set_icon_type (struct frame *f)
737   Lisp_Object tem;
738   EmacsView *view = FRAME_NS_VIEW (f);
739   id image = nil;
740   Lisp_Object chain, elt;
741   NSAutoreleasePool *pool;
742   BOOL setMini = YES;
744   NSTRACE (ns_implicitly_set_icon_type);
746   block_input ();
747   pool = [[NSAutoreleasePool alloc] init];
748   if (f->output_data.ns->miniimage
749       && [[NSString stringWithUTF8String: SSDATA (f->name)]
750                isEqualToString: [(NSImage *)f->output_data.ns->miniimage name]])
751     {
752       [pool release];
753       unblock_input ();
754       return;
755     }
757   tem = assq_no_quit (Qicon_type, f->param_alist);
758   if (CONSP (tem) && ! NILP (XCDR (tem)))
759     {
760       [pool release];
761       unblock_input ();
762       return;
763     }
765   for (chain = Vns_icon_type_alist;
766        image == nil && CONSP (chain);
767        chain = XCDR (chain))
768     {
769       elt = XCAR (chain);
770       /* special case: 't' means go by file type */
771       if (SYMBOLP (elt) && EQ (elt, Qt) && SSDATA (f->name)[0] == '/')
772         {
773           NSString *str
774              = [NSString stringWithUTF8String: SSDATA (f->name)];
775           if ([[NSFileManager defaultManager] fileExistsAtPath: str])
776             image = [[[NSWorkspace sharedWorkspace] iconForFile: str] retain];
777         }
778       else if (CONSP (elt) &&
779                STRINGP (XCAR (elt)) &&
780                STRINGP (XCDR (elt)) &&
781                fast_string_match (XCAR (elt), f->name) >= 0)
782         {
783           image = [EmacsImage allocInitFromFile: XCDR (elt)];
784           if (image == nil)
785             image = [[NSImage imageNamed:
786                                [NSString stringWithUTF8String:
787                                             SSDATA (XCDR (elt))]] retain];
788         }
789     }
791   if (image == nil)
792     {
793       image = [[[NSWorkspace sharedWorkspace] iconForFileType: @"text"] retain];
794       setMini = NO;
795     }
797   [f->output_data.ns->miniimage release];
798   f->output_data.ns->miniimage = image;
799   [view setMiniwindowImage: setMini];
800   [pool release];
801   unblock_input ();
805 static void
806 x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
808   EmacsView *view = FRAME_NS_VIEW (f);
809   id image = nil;
810   BOOL setMini = YES;
812   NSTRACE (x_set_icon_type);
814   if (!NILP (arg) && SYMBOLP (arg))
815     {
816       arg =build_string (SSDATA (SYMBOL_NAME (arg)));
817       store_frame_param (f, Qicon_type, arg);
818     }
820   /* do it the implicit way */
821   if (NILP (arg))
822     {
823       ns_implicitly_set_icon_type (f);
824       return;
825     }
827   CHECK_STRING (arg);
829   image = [EmacsImage allocInitFromFile: arg];
830   if (image == nil)
831     image =[NSImage imageNamed: [NSString stringWithUTF8String:
832                                             SSDATA (arg)]];
834   if (image == nil)
835     {
836       image = [NSImage imageNamed: @"text"];
837       setMini = NO;
838     }
840   f->output_data.ns->miniimage = image;
841   [view setMiniwindowImage: setMini];
845 /* TODO: move to nsterm? */
847 ns_lisp_to_cursor_type (Lisp_Object arg)
849   char *str;
850   if (XTYPE (arg) == Lisp_String)
851     str = SSDATA (arg);
852   else if (XTYPE (arg) == Lisp_Symbol)
853     str = SSDATA (SYMBOL_NAME (arg));
854   else return -1;
855   if (!strcmp (str, "box"))     return FILLED_BOX_CURSOR;
856   if (!strcmp (str, "hollow"))  return HOLLOW_BOX_CURSOR;
857   if (!strcmp (str, "hbar"))    return HBAR_CURSOR;
858   if (!strcmp (str, "bar"))     return BAR_CURSOR;
859   if (!strcmp (str, "no"))      return NO_CURSOR;
860   return -1;
864 Lisp_Object
865 ns_cursor_type_to_lisp (int arg)
867   switch (arg)
868     {
869     case FILLED_BOX_CURSOR: return Qbox;
870     case HOLLOW_BOX_CURSOR: return intern ("hollow");
871     case HBAR_CURSOR:       return intern ("hbar");
872     case BAR_CURSOR:        return intern ("bar");
873     case NO_CURSOR:
874     default:                return intern ("no");
875     }
878 /* This is the same as the xfns.c definition.  */
879 static void
880 x_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
882   set_frame_cursor_types (f, arg);
885 /* called to set mouse pointer color, but all other terms use it to
886    initialize pointer types (and don't set the color ;) */
887 static void
888 x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
890   /* don't think we can do this on Nextstep */
894 #define Str(x) #x
895 #define Xstr(x) Str(x)
897 static Lisp_Object
898 ns_appkit_version_str (void)
900   char tmp[80];
902 #ifdef NS_IMPL_GNUSTEP
903   sprintf(tmp, "gnustep-gui-%s", Xstr(GNUSTEP_GUI_VERSION));
904 #elif defined (NS_IMPL_COCOA)
905   sprintf(tmp, "apple-appkit-%.2f", NSAppKitVersionNumber);
906 #else
907   tmp = "ns-unknown";
908 #endif
909   return build_string (tmp);
913 /* This is for use by x-server-version and collapses all version info we
914    have into a single int.  For a better picture of the implementation
915    running, use ns_appkit_version_str.*/
916 static int
917 ns_appkit_version_int (void)
919 #ifdef NS_IMPL_GNUSTEP
920   return GNUSTEP_GUI_MAJOR_VERSION * 100 + GNUSTEP_GUI_MINOR_VERSION;
921 #elif defined (NS_IMPL_COCOA)
922   return (int)NSAppKitVersionNumber;
923 #endif
924   return 0;
928 static void
929 x_icon (struct frame *f, Lisp_Object parms)
930 /* --------------------------------------------------------------------------
931    Strangely-named function to set icon position parameters in frame.
932    This is irrelevant under OS X, but might be needed under GNUstep,
933    depending on the window manager used.  Note, this is not a standard
934    frame parameter-setter; it is called directly from x-create-frame.
935    -------------------------------------------------------------------------- */
937   Lisp_Object icon_x, icon_y;
938   struct ns_display_info *dpyinfo = check_ns_display_info (Qnil);
940   f->output_data.ns->icon_top = -1;
941   f->output_data.ns->icon_left = -1;
943   /* Set the position of the icon.  */
944   icon_x = x_get_arg (dpyinfo, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
945   icon_y = x_get_arg (dpyinfo, parms, Qicon_top, 0, 0,  RES_TYPE_NUMBER);
946   if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
947     {
948       CHECK_NUMBER (icon_x);
949       CHECK_NUMBER (icon_y);
950       f->output_data.ns->icon_top = XINT (icon_y);
951       f->output_data.ns->icon_left = XINT (icon_x);
952     }
953   else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
954     error ("Both left and top icon corners of icon must be specified");
958 /* Note: see frame.c for template, also where generic functions are impl */
959 frame_parm_handler ns_frame_parm_handlers[] =
961   x_set_autoraise, /* generic OK */
962   x_set_autolower, /* generic OK */
963   x_set_background_color,
964   0, /* x_set_border_color,  may be impossible under Nextstep */
965   0, /* x_set_border_width,  may be impossible under Nextstep */
966   x_set_cursor_color,
967   x_set_cursor_type,
968   x_set_font, /* generic OK */
969   x_set_foreground_color,
970   x_set_icon_name,
971   x_set_icon_type,
972   x_set_internal_border_width, /* generic OK */
973   0, /* x_set_right_divider_width */
974   0, /* x_set_bottom_divider_width */
975   x_set_menu_bar_lines,
976   x_set_mouse_color,
977   x_explicitly_set_name,
978   x_set_scroll_bar_width, /* generic OK */
979   x_set_title,
980   x_set_unsplittable, /* generic OK */
981   x_set_vertical_scroll_bars, /* generic OK */
982   x_set_visibility, /* generic OK */
983   x_set_tool_bar_lines,
984   0, /* x_set_scroll_bar_foreground, will ignore (not possible on NS) */
985   0, /* x_set_scroll_bar_background,  will ignore (not possible on NS) */
986   x_set_screen_gamma, /* generic OK */
987   x_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */
988   x_set_fringe_width, /* generic OK */
989   x_set_fringe_width, /* generic OK */
990   0, /* x_set_wait_for_wm, will ignore */
991   x_set_fullscreen, /* generic OK */
992   x_set_font_backend, /* generic OK */
993   x_set_alpha,
994   0, /* x_set_sticky */
995   0, /* x_set_tool_bar_position */
999 /* Handler for signals raised during x_create_frame.
1000    FRAME is the frame which is partially constructed.  */
1002 static void
1003 unwind_create_frame (Lisp_Object frame)
1005   struct frame *f = XFRAME (frame);
1007   /* If frame is already dead, nothing to do.  This can happen if the
1008      display is disconnected after the frame has become official, but
1009      before x_create_frame removes the unwind protect.  */
1010   if (!FRAME_LIVE_P (f))
1011     return;
1013   /* If frame is ``official'', nothing to do.  */
1014   if (NILP (Fmemq (frame, Vframe_list)))
1015     {
1016 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
1017       struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
1018 #endif
1020       x_free_frame_resources (f);
1021       free_glyphs (f);
1023 #ifdef GLYPH_DEBUG
1024       /* Check that reference counts are indeed correct.  */
1025       eassert (dpyinfo->terminal->image_cache->refcount == image_cache_refcount);
1026 #endif
1027     }
1031  * Read geometry related parameters from preferences if not in PARMS.
1032  * Returns the union of parms and any preferences read.
1033  */
1035 static Lisp_Object
1036 get_geometry_from_preferences (struct ns_display_info *dpyinfo,
1037                                Lisp_Object parms)
1039   struct {
1040     const char *val;
1041     const char *cls;
1042     Lisp_Object tem;
1043   } r[] = {
1044     { "width",  "Width", Qwidth },
1045     { "height", "Height", Qheight },
1046     { "left", "Left", Qleft },
1047     { "top", "Top", Qtop },
1048   };
1050   int i;
1051   for (i = 0; i < sizeof (r)/sizeof (r[0]); ++i)
1052     {
1053       if (NILP (Fassq (r[i].tem, parms)))
1054         {
1055           Lisp_Object value
1056             = x_get_arg (dpyinfo, parms, r[i].tem, r[i].val, r[i].cls,
1057                          RES_TYPE_NUMBER);
1058           if (! EQ (value, Qunbound))
1059             parms = Fcons (Fcons (r[i].tem, value), parms);
1060         }
1061     }
1063   return parms;
1066 /* ==========================================================================
1068     Lisp definitions
1070    ========================================================================== */
1072 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
1073        1, 1, 0,
1074        doc: /* Make a new Nextstep window, called a "frame" in Emacs terms.
1075 Return an Emacs frame object.
1076 PARMS is an alist of frame parameters.
1077 If the parameters specify that the frame should not have a minibuffer,
1078 and do not specify a specific minibuffer window to use,
1079 then `default-minibuffer-frame' must be a frame whose minibuffer can
1080 be shared by the new frame.
1082 This function is an internal primitive--use `make-frame' instead.  */)
1083      (Lisp_Object parms)
1085   struct frame *f;
1086   Lisp_Object frame, tem;
1087   Lisp_Object name;
1088   int minibuffer_only = 0;
1089   long window_prompting = 0;
1090   int width, height;
1091   ptrdiff_t count = specpdl_ptr - specpdl;
1092   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1093   Lisp_Object display;
1094   struct ns_display_info *dpyinfo = NULL;
1095   Lisp_Object parent;
1096   struct kboard *kb;
1097   static int desc_ctr = 1;
1099   /* x_get_arg modifies parms.  */
1100   parms = Fcopy_alist (parms);
1102   /* Use this general default value to start with
1103      until we know if this frame has a specified name.  */
1104   Vx_resource_name = Vinvocation_name;
1106   display = x_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_STRING);
1107   if (EQ (display, Qunbound))
1108     display = Qnil;
1109   dpyinfo = check_ns_display_info (display);
1110   kb = dpyinfo->terminal->kboard;
1112   if (!dpyinfo->terminal->name)
1113     error ("Terminal is not live, can't create new frames on it");
1115   name = x_get_arg (dpyinfo, parms, Qname, 0, 0, RES_TYPE_STRING);
1116   if (!STRINGP (name)
1117       && ! EQ (name, Qunbound)
1118       && ! NILP (name))
1119     error ("Invalid frame name--not a string or nil");
1121   if (STRINGP (name))
1122     Vx_resource_name = name;
1124   parent = x_get_arg (dpyinfo, parms, Qparent_id, 0, 0, RES_TYPE_NUMBER);
1125   if (EQ (parent, Qunbound))
1126     parent = Qnil;
1127   if (! NILP (parent))
1128     CHECK_NUMBER (parent);
1130   /* make_frame_without_minibuffer can run Lisp code and garbage collect.  */
1131   /* No need to protect DISPLAY because that's not used after passing
1132      it to make_frame_without_minibuffer.  */
1133   frame = Qnil;
1134   GCPRO4 (parms, parent, name, frame);
1135   tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
1136                   RES_TYPE_SYMBOL);
1137   if (EQ (tem, Qnone) || NILP (tem))
1138       f = make_frame_without_minibuffer (Qnil, kb, display);
1139   else if (EQ (tem, Qonly))
1140     {
1141       f = make_minibuffer_frame ();
1142       minibuffer_only = 1;
1143     }
1144   else if (WINDOWP (tem))
1145       f = make_frame_without_minibuffer (tem, kb, display);
1146   else
1147       f = make_frame (1);
1149   XSETFRAME (frame, f);
1151   f->terminal = dpyinfo->terminal;
1153   f->output_method = output_ns;
1154   f->output_data.ns = xzalloc (sizeof *f->output_data.ns);
1156   FRAME_FONTSET (f) = -1;
1158   fset_icon_name (f, x_get_arg (dpyinfo, parms, Qicon_name,
1159                                 "iconName", "Title",
1160                                 RES_TYPE_STRING));
1161   if (! STRINGP (f->icon_name))
1162     fset_icon_name (f, Qnil);
1164   FRAME_DISPLAY_INFO (f) = dpyinfo;
1166   /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe.  */
1167   record_unwind_protect (unwind_create_frame, frame);
1169   f->output_data.ns->window_desc = desc_ctr++;
1170   if (TYPE_RANGED_INTEGERP (Window, parent))
1171     {
1172       f->output_data.ns->parent_desc = XFASTINT (parent);
1173       f->output_data.ns->explicit_parent = 1;
1174     }
1175   else
1176     {
1177       f->output_data.ns->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
1178       f->output_data.ns->explicit_parent = 0;
1179     }
1181   /* Set the name; the functions to which we pass f expect the name to
1182      be set.  */
1183   if (EQ (name, Qunbound) || NILP (name) || ! STRINGP (name))
1184     {
1185       fset_name (f, build_string ([ns_app_name UTF8String]));
1186       f->explicit_name = 0;
1187     }
1188   else
1189     {
1190       fset_name (f, name);
1191       f->explicit_name = 1;
1192       specbind (Qx_resource_name, name);
1193     }
1195   block_input ();
1197 #ifdef NS_IMPL_COCOA
1198 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
1199   if (CTGetCoreTextVersion != NULL
1200       && CTGetCoreTextVersion () >= kCTVersionNumber10_5)
1201     mac_register_font_driver (f);
1202 #endif
1203 #endif
1204   register_font_driver (&nsfont_driver, f);
1206   x_default_parameter (f, parms, Qfont_backend, Qnil,
1207                         "fontBackend", "FontBackend", RES_TYPE_STRING);
1209   {
1210     /* use for default font name */
1211     id font = [NSFont userFixedPitchFontOfSize: -1.0]; /* default */
1212     x_default_parameter (f, parms, Qfontsize,
1213                                     make_number (0 /*(int)[font pointSize]*/),
1214                                     "fontSize", "FontSize", RES_TYPE_NUMBER);
1215     // Remove ' Regular', not handled by backends.
1216     char *fontname = xstrdup ([[font displayName] UTF8String]);
1217     int len = strlen (fontname);
1218     if (len > 8 && strcmp (fontname + len - 8, " Regular") == 0)
1219       fontname[len-8] = '\0';
1220     x_default_parameter (f, parms, Qfont,
1221                                  build_string (fontname),
1222                                  "font", "Font", RES_TYPE_STRING);
1223     xfree (fontname);
1224   }
1225   unblock_input ();
1227   x_default_parameter (f, parms, Qborder_width, make_number (0),
1228                        "borderwidth", "BorderWidth", RES_TYPE_NUMBER);
1229   x_default_parameter (f, parms, Qinternal_border_width, make_number (2),
1230                       "internalBorderWidth", "InternalBorderWidth",
1231                       RES_TYPE_NUMBER);
1233   /* default scrollbars on right on Mac */
1234   {
1235       Lisp_Object spos
1236 #ifdef NS_IMPL_GNUSTEP
1237           = Qt;
1238 #else
1239           = Qright;
1240 #endif
1241       x_default_parameter (f, parms, Qvertical_scroll_bars, spos,
1242                            "verticalScrollBars", "VerticalScrollBars",
1243                            RES_TYPE_SYMBOL);
1244   }
1245   x_default_parameter (f, parms, Qforeground_color, build_string ("Black"),
1246                       "foreground", "Foreground", RES_TYPE_STRING);
1247   x_default_parameter (f, parms, Qbackground_color, build_string ("White"),
1248                       "background", "Background", RES_TYPE_STRING);
1249   /* FIXME: not supported yet in Nextstep */
1250   x_default_parameter (f, parms, Qline_spacing, Qnil,
1251                        "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
1252   x_default_parameter (f, parms, Qleft_fringe, Qnil,
1253                        "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
1254   x_default_parameter (f, parms, Qright_fringe, Qnil,
1255                        "rightFringe", "RightFringe", RES_TYPE_NUMBER);
1257 #ifdef GLYPH_DEBUG
1258   image_cache_refcount =
1259     FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
1260 #endif
1262   init_frame_faces (f);
1264   /* Read comment about this code in corresponding place in xfns.c.  */
1265   width = FRAME_TEXT_WIDTH (f);
1266   height = FRAME_TEXT_HEIGHT (f);
1267   FRAME_TEXT_HEIGHT (f) = 0;
1268   SET_FRAME_WIDTH (f, 0);
1269   change_frame_size (f, width, height, 1, 0, 0, 1);
1271   /* The resources controlling the menu-bar and tool-bar are
1272      processed specially at startup, and reflected in the mode
1273      variables; ignore them here.  */
1274   x_default_parameter (f, parms, Qmenu_bar_lines,
1275                        NILP (Vmenu_bar_mode)
1276                        ? make_number (0) : make_number (1),
1277                        NULL, NULL, RES_TYPE_NUMBER);
1278   x_default_parameter (f, parms, Qtool_bar_lines,
1279                        NILP (Vtool_bar_mode)
1280                        ? make_number (0) : make_number (1),
1281                        NULL, NULL, RES_TYPE_NUMBER);
1283   x_default_parameter (f, parms, Qbuffer_predicate, Qnil, "bufferPredicate",
1284                        "BufferPredicate", RES_TYPE_SYMBOL);
1285   x_default_parameter (f, parms, Qtitle, Qnil, "title", "Title",
1286                        RES_TYPE_STRING);
1288   parms = get_geometry_from_preferences (dpyinfo, parms);
1289   window_prompting = x_figure_window_size (f, parms, 1);
1291   tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
1292   f->no_split = minibuffer_only || (!EQ (tem, Qunbound) && !EQ (tem, Qnil));
1294   /* NOTE: on other terms, this is done in set_mouse_color, however this
1295      was not getting called under Nextstep */
1296   f->output_data.ns->text_cursor = [NSCursor IBeamCursor];
1297   f->output_data.ns->nontext_cursor = [NSCursor arrowCursor];
1298   f->output_data.ns->modeline_cursor = [NSCursor pointingHandCursor];
1299   f->output_data.ns->hand_cursor = [NSCursor pointingHandCursor];
1300   f->output_data.ns->hourglass_cursor = [NSCursor disappearingItemCursor];
1301   f->output_data.ns->horizontal_drag_cursor = [NSCursor resizeLeftRightCursor];
1302   f->output_data.ns->vertical_drag_cursor = [NSCursor resizeUpDownCursor];
1303   FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor
1304      = [NSCursor arrowCursor];
1305   f->output_data.ns->current_pointer = f->output_data.ns->text_cursor;
1307   [[EmacsView alloc] initFrameFromEmacs: f];
1309   x_icon (f, parms);
1311   /* ns_display_info does not have a reference_count.  */
1312   f->terminal->reference_count++;
1314   /* It is now ok to make the frame official even if we get an error below.
1315      The frame needs to be on Vframe_list or making it visible won't work. */
1316   Vframe_list = Fcons (frame, Vframe_list);
1318   x_default_parameter (f, parms, Qicon_type, Qnil,
1319                        "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
1321   x_default_parameter (f, parms, Qauto_raise, Qnil,
1322                        "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
1323   x_default_parameter (f, parms, Qauto_lower, Qnil,
1324                        "autoLower", "AutoLower", RES_TYPE_BOOLEAN);
1325   x_default_parameter (f, parms, Qcursor_type, Qbox,
1326                        "cursorType", "CursorType", RES_TYPE_SYMBOL);
1327   x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
1328                        "scrollBarWidth", "ScrollBarWidth",
1329                        RES_TYPE_NUMBER);
1330   x_default_parameter (f, parms, Qalpha, Qnil,
1331                        "alpha", "Alpha", RES_TYPE_NUMBER);
1332   x_default_parameter (f, parms, Qfullscreen, Qnil,
1333                        "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
1335   width = FRAME_TEXT_WIDTH (f);
1336   height = FRAME_TEXT_HEIGHT (f);
1337   FRAME_TEXT_HEIGHT (f) = 0;
1338   SET_FRAME_WIDTH (f, 0);
1339   change_frame_size (f, width, height, 1, 0, 0, 1);
1341   if (! f->output_data.ns->explicit_parent)
1342     {
1343       Lisp_Object visibility;
1345       visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
1346                               RES_TYPE_SYMBOL);
1347       if (EQ (visibility, Qunbound))
1348         visibility = Qt;
1350       if (EQ (visibility, Qicon))
1351         x_iconify_frame (f);
1352       else if (! NILP (visibility))
1353         {
1354           x_make_frame_visible (f);
1355           [[FRAME_NS_VIEW (f) window] makeKeyWindow];
1356         }
1357       else
1358         {
1359           /* Must have been Qnil.  */
1360         }
1361     }
1363   if (FRAME_HAS_MINIBUF_P (f)
1364       && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
1365           || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
1366     kset_default_minibuffer_frame (kb, frame);
1368   /* All remaining specified parameters, which have not been "used"
1369      by x_get_arg and friends, now go in the misc. alist of the frame.  */
1370   for (tem = parms; CONSP (tem); tem = XCDR (tem))
1371     if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
1372       fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
1374   UNGCPRO;
1376   if (window_prompting & USPosition)
1377     x_set_offset (f, f->left_pos, f->top_pos, 1);
1379   /* Make sure windows on this frame appear in calls to next-window
1380      and similar functions.  */
1381   Vwindow_list = Qnil;
1383   return unbind_to (count, frame);
1386 void
1387 x_focus_frame (struct frame *f)
1389   struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
1391   if (dpyinfo->x_focus_frame != f)
1392     {
1393       EmacsView *view = FRAME_NS_VIEW (f);
1394       block_input ();
1395       [NSApp activateIgnoringOtherApps: YES];
1396       [[view window] makeKeyAndOrderFront: view];
1397       unblock_input ();
1398     }
1402 DEFUN ("ns-popup-font-panel", Fns_popup_font_panel, Sns_popup_font_panel,
1403        0, 1, "",
1404        doc: /* Pop up the font panel. */)
1405      (Lisp_Object frame)
1407   struct frame *f = decode_window_system_frame (frame);
1408   id fm = [NSFontManager sharedFontManager];
1409   struct font *font = f->output_data.ns->font;
1410   NSFont *nsfont;
1411   if (EQ (font->driver->type, Qns))
1412     nsfont = ((struct nsfont_info *)font)->nsfont;
1413 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_5
1414   else
1415     nsfont = (NSFont *) macfont_get_nsctfont (font);
1416 #endif
1417   [fm setSelectedFont: nsfont isMultiple: NO];
1418   [fm orderFrontFontPanel: NSApp];
1419   return Qnil;
1423 DEFUN ("ns-popup-color-panel", Fns_popup_color_panel, Sns_popup_color_panel,
1424        0, 1, "",
1425        doc: /* Pop up the color panel.  */)
1426      (Lisp_Object frame)
1428   check_window_system (NULL);
1429   [NSApp orderFrontColorPanel: NSApp];
1430   return Qnil;
1433 static struct
1435   id panel;
1436   BOOL ret;
1437 #if ! defined (NS_IMPL_COCOA) || \
1438   MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6
1439   NSString *dirS, *initS;
1440   BOOL no_types;
1441 #endif
1442 } ns_fd_data;
1444 void
1445 ns_run_file_dialog (void)
1447   if (ns_fd_data.panel == nil) return;
1448 #if defined (NS_IMPL_COCOA) && \
1449   MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
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 DEFUN ("ns-read-file-name", Fns_read_file_name, Sns_read_file_name, 1, 5, 0,
1470        doc: /* Use a graphical panel to read a file name, using prompt PROMPT.
1471 Optional arg DIR, if non-nil, supplies a default directory.
1472 Optional arg MUSTMATCH, if non-nil, means the returned file or
1473 directory must exist.
1474 Optional arg INIT, if non-nil, provides a default file name to use.
1475 Optional arg DIR_ONLY_P, if non-nil, means choose only directories.  */)
1476   (Lisp_Object prompt, Lisp_Object dir, Lisp_Object mustmatch,
1477    Lisp_Object init, Lisp_Object dir_only_p)
1479   static id fileDelegate = nil;
1480   BOOL ret;
1481   BOOL isSave = NILP (mustmatch) && NILP (dir_only_p);
1482   id panel;
1483   Lisp_Object fname;
1485   NSString *promptS = NILP (prompt) || !STRINGP (prompt) ? nil :
1486     [NSString stringWithUTF8String: SSDATA (prompt)];
1487   NSString *dirS = NILP (dir) || !STRINGP (dir) ?
1488     [NSString stringWithUTF8String: SSDATA (BVAR (current_buffer, directory))] :
1489     [NSString stringWithUTF8String: SSDATA (dir)];
1490   NSString *initS = NILP (init) || !STRINGP (init) ? nil :
1491     [NSString stringWithUTF8String: SSDATA (init)];
1492   NSEvent *nxev;
1494   check_window_system (NULL);
1496   if (fileDelegate == nil)
1497     fileDelegate = [EmacsFileDelegate new];
1499   [NSCursor setHiddenUntilMouseMoves: NO];
1501   if ([dirS characterAtIndex: 0] == '~')
1502     dirS = [dirS stringByExpandingTildeInPath];
1504   panel = isSave ?
1505     (id)[EmacsSavePanel savePanel] : (id)[EmacsOpenPanel openPanel];
1507   [panel setTitle: promptS];
1509   [panel setAllowsOtherFileTypes: YES];
1510   [panel setTreatsFilePackagesAsDirectories: YES];
1511   [panel setDelegate: fileDelegate];
1513   if (! NILP (dir_only_p))
1514     {
1515       [panel setCanChooseDirectories: YES];
1516       [panel setCanChooseFiles: NO];
1517     }
1518   else if (! isSave)
1519     {
1520       /* This is not quite what the documentation says, but it is compatible
1521          with the Gtk+ code.  Also, the menu entry says "Open File...".  */
1522       [panel setCanChooseDirectories: NO];
1523       [panel setCanChooseFiles: YES];
1524     }
1526   block_input ();
1527   ns_fd_data.panel = panel;
1528   ns_fd_data.ret = NO;
1529 #if defined (NS_IMPL_COCOA) && \
1530   MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
1531   if (! NILP (mustmatch) || ! NILP (dir_only_p))
1532     [panel setAllowedFileTypes: nil];
1533   if (dirS) [panel setDirectoryURL: [NSURL fileURLWithPath: dirS]];
1534   if (initS && NILP (Ffile_directory_p (init)))
1535     [panel setNameFieldStringValue: [initS lastPathComponent]];
1536   else
1537     [panel setNameFieldStringValue: @""];
1539 #else
1540   ns_fd_data.no_types = NILP (mustmatch) && NILP (dir_only_p);
1541   ns_fd_data.dirS = dirS;
1542   ns_fd_data.initS = initS;
1543 #endif
1545   /* runModalForDirectory/runModal restarts the main event loop when done,
1546      so we must start an event loop and then pop up the file dialog.
1547      The file dialog may pop up a confirm dialog after Ok has been pressed,
1548      so we can not simply pop down on the Ok/Cancel press.
1549    */
1550   nxev = [NSEvent otherEventWithType: NSApplicationDefined
1551                             location: NSMakePoint (0, 0)
1552                        modifierFlags: 0
1553                            timestamp: 0
1554                         windowNumber: [[NSApp mainWindow] windowNumber]
1555                              context: [NSApp context]
1556                              subtype: 0
1557                                data1: 0
1558                                data2: NSAPP_DATA2_RUNFILEDIALOG];
1560   [NSApp postEvent: nxev atStart: NO];
1561   while (ns_fd_data.panel != nil)
1562     [NSApp run];
1564   ret = (ns_fd_data.ret == NSOKButton);
1566   if (ret)
1567     {
1568       NSString *str = ns_filename_from_panel (panel);
1569       if (! str) str = ns_directory_from_panel (panel);
1570       if (! str) ret = NO;
1571       else fname = build_string ([str UTF8String]);
1572     }
1574   [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
1575   unblock_input ();
1577   return ret ? fname : Qnil;
1580 const char *
1581 ns_get_defaults_value (const char *key)
1583   NSObject *obj = [[NSUserDefaults standardUserDefaults]
1584                     objectForKey: [NSString stringWithUTF8String: key]];
1586   if (!obj) return NULL;
1588   return [[NSString stringWithFormat: @"%@", obj] UTF8String];
1592 DEFUN ("ns-get-resource", Fns_get_resource, Sns_get_resource, 2, 2, 0,
1593        doc: /* Return the value of the property NAME of OWNER from the defaults database.
1594 If OWNER is nil, Emacs is assumed.  */)
1595      (Lisp_Object owner, Lisp_Object name)
1597   const char *value;
1599   check_window_system (NULL);
1600   if (NILP (owner))
1601     owner = build_string([ns_app_name UTF8String]);
1602   CHECK_STRING (name);
1604   value = ns_get_defaults_value (SSDATA (name));
1606   if (value)
1607     return build_string (value);
1608   return Qnil;
1612 DEFUN ("ns-set-resource", Fns_set_resource, Sns_set_resource, 3, 3, 0,
1613        doc: /* Set property NAME of OWNER to VALUE, from the defaults database.
1614 If OWNER is nil, Emacs is assumed.
1615 If VALUE is nil, the default is removed.  */)
1616      (Lisp_Object owner, Lisp_Object name, Lisp_Object value)
1618   check_window_system (NULL);
1619   if (NILP (owner))
1620     owner = build_string ([ns_app_name UTF8String]);
1621   CHECK_STRING (name);
1622   if (NILP (value))
1623     {
1624       [[NSUserDefaults standardUserDefaults] removeObjectForKey:
1625                          [NSString stringWithUTF8String: SSDATA (name)]];
1626     }
1627   else
1628     {
1629       CHECK_STRING (value);
1630       [[NSUserDefaults standardUserDefaults] setObject:
1631                 [NSString stringWithUTF8String: SSDATA (value)]
1632                                         forKey: [NSString stringWithUTF8String:
1633                                                          SSDATA (name)]];
1634     }
1636   return Qnil;
1640 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
1641        Sx_server_max_request_size,
1642        0, 1, 0,
1643        doc: /* This function is a no-op.  It is only present for completeness.  */)
1644      (Lisp_Object terminal)
1646   check_ns_display_info (terminal);
1647   /* This function has no real equivalent under NeXTstep.  Return nil to
1648      indicate this. */
1649   return Qnil;
1653 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
1654        doc: /* Return the "vendor ID" string of Nextstep display server TERMINAL.
1655 \(Labeling every distributor as a "vendor" embodies the false assumption
1656 that operating systems cannot be developed and distributed noncommercially.)
1657 The optional argument TERMINAL specifies which display to ask about.
1658 TERMINAL should be a terminal object, a frame or a display name (a string).
1659 If omitted or nil, that stands for the selected frame's display.  */)
1660   (Lisp_Object terminal)
1662   check_ns_display_info (terminal);
1663 #ifdef NS_IMPL_GNUSTEP
1664   return build_string ("GNU");
1665 #else
1666   return build_string ("Apple");
1667 #endif
1671 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
1672        doc: /* Return the version numbers of the server of display TERMINAL.
1673 The value is a list of three integers: the major and minor
1674 version numbers of the X Protocol in use, and the distributor-specific release
1675 number.  See also the function `x-server-vendor'.
1677 The optional argument TERMINAL specifies which display to ask about.
1678 TERMINAL should be a terminal object, a frame or a display name (a string).
1679 If omitted or nil, that stands for the selected frame's display.  */)
1680   (Lisp_Object terminal)
1682   check_ns_display_info (terminal);
1683   /*NOTE: it is unclear what would best correspond with "protocol";
1684           we return 10.3, meaning Panther, since this is roughly the
1685           level that GNUstep's APIs correspond to.
1686           The last number is where we distinguish between the Apple
1687           and GNUstep implementations ("distributor-specific release
1688           number") and give int'ized versions of major.minor. */
1689   return list3i (10, 3, ns_appkit_version_int ());
1693 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
1694        doc: /* Return the number of screens on Nextstep display server TERMINAL.
1695 The optional argument TERMINAL specifies which display to ask about.
1696 TERMINAL should be a terminal object, a frame or a display name (a string).
1697 If omitted or nil, that stands for the selected frame's display.
1699 Note: "screen" here is not in Nextstep terminology but in X11's.  For
1700 the number of physical monitors, use `(length
1701 (display-monitor-attributes-list TERMINAL))' instead.  */)
1702   (Lisp_Object terminal)
1704   check_ns_display_info (terminal);
1705   return make_number (1);
1709 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
1710        doc: /* Return the height in millimeters of the Nextstep display TERMINAL.
1711 The optional argument TERMINAL specifies which display to ask about.
1712 TERMINAL should be a terminal object, a frame or a display name (a string).
1713 If omitted or nil, that stands for the selected frame's display.
1715 On \"multi-monitor\" setups this refers to the height in millimeters for
1716 all physical monitors associated with TERMINAL.  To get information
1717 for each physical monitor, use `display-monitor-attributes-list'.  */)
1718   (Lisp_Object terminal)
1720   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
1722   return make_number (x_display_pixel_height (dpyinfo) / (92.0/25.4));
1726 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
1727        doc: /* Return the width in millimeters of the Nextstep display TERMINAL.
1728 The optional argument TERMINAL specifies which display to ask about.
1729 TERMINAL should be a terminal object, a frame or a display name (a string).
1730 If omitted or nil, that stands for the selected frame's display.
1732 On \"multi-monitor\" setups this refers to the width in millimeters for
1733 all physical monitors associated with TERMINAL.  To get information
1734 for each physical monitor, use `display-monitor-attributes-list'.  */)
1735   (Lisp_Object terminal)
1737   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
1739   return make_number (x_display_pixel_width (dpyinfo) / (92.0/25.4));
1743 DEFUN ("x-display-backing-store", Fx_display_backing_store,
1744        Sx_display_backing_store, 0, 1, 0,
1745        doc: /* Return an indication of whether the Nextstep display TERMINAL does backing store.
1746 The value may be `buffered', `retained', or `non-retained'.
1747 The optional argument TERMINAL specifies which display to ask about.
1748 TERMINAL should be a terminal object, a frame or a display name (a string).
1749 If omitted or nil, that stands for the selected frame's display.  */)
1750   (Lisp_Object terminal)
1752   check_ns_display_info (terminal);
1753   switch ([ns_get_window (terminal) backingType])
1754     {
1755     case NSBackingStoreBuffered:
1756       return intern ("buffered");
1757     case NSBackingStoreRetained:
1758       return intern ("retained");
1759     case NSBackingStoreNonretained:
1760       return intern ("non-retained");
1761     default:
1762       error ("Strange value for backingType parameter of frame");
1763     }
1764   return Qnil;  /* not reached, shut compiler up */
1768 DEFUN ("x-display-visual-class", Fx_display_visual_class,
1769        Sx_display_visual_class, 0, 1, 0,
1770        doc: /* Return the visual class of the Nextstep display TERMINAL.
1771 The value is one of the symbols `static-gray', `gray-scale',
1772 `static-color', `pseudo-color', `true-color', or `direct-color'.
1774 The optional argument TERMINAL specifies which display to ask about.
1775 TERMINAL should a terminal object, a frame or a display name (a string).
1776 If omitted or nil, that stands for the selected frame's display.  */)
1777   (Lisp_Object terminal)
1779   NSWindowDepth depth;
1781   check_ns_display_info (terminal);
1782   depth = [[[NSScreen screens] objectAtIndex:0] depth];
1784   if ( depth == NSBestDepth (NSCalibratedWhiteColorSpace, 2, 2, YES, NULL))
1785     return intern ("static-gray");
1786   else if (depth == NSBestDepth (NSCalibratedWhiteColorSpace, 8, 8, YES, NULL))
1787     return intern ("gray-scale");
1788   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 8, YES, NULL))
1789     return intern ("pseudo-color");
1790   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 4, 12, NO, NULL))
1791     return intern ("true-color");
1792   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 24, NO, NULL))
1793     return intern ("direct-color");
1794   else
1795     /* color mgmt as far as we do it is really handled by Nextstep itself anyway */
1796     return intern ("direct-color");
1800 DEFUN ("x-display-save-under", Fx_display_save_under,
1801        Sx_display_save_under, 0, 1, 0,
1802        doc: /* Return t if TERMINAL supports the save-under feature.
1803 The optional argument TERMINAL specifies which display to ask about.
1804 TERMINAL should be a terminal object, a frame or a display name (a string).
1805 If omitted or nil, that stands for the selected frame's display.  */)
1806   (Lisp_Object terminal)
1808   check_ns_display_info (terminal);
1809   switch ([ns_get_window (terminal) backingType])
1810     {
1811     case NSBackingStoreBuffered:
1812       return Qt;
1814     case NSBackingStoreRetained:
1815     case NSBackingStoreNonretained:
1816       return Qnil;
1818     default:
1819       error ("Strange value for backingType parameter of frame");
1820     }
1821   return Qnil;  /* not reached, shut compiler up */
1825 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
1826        1, 3, 0,
1827        doc: /* Open a connection to a display server.
1828 DISPLAY is the name of the display to connect to.
1829 Optional second arg XRM-STRING is a string of resources in xrdb format.
1830 If the optional third arg MUST-SUCCEED is non-nil,
1831 terminate Emacs if we can't open the connection.
1832 \(In the Nextstep version, the last two arguments are currently ignored.)  */)
1833      (Lisp_Object display, Lisp_Object resource_string, Lisp_Object must_succeed)
1835   struct ns_display_info *dpyinfo;
1837   CHECK_STRING (display);
1839   nxatoms_of_nsselect ();
1840   dpyinfo = ns_term_init (display);
1841   if (dpyinfo == 0)
1842     {
1843       if (!NILP (must_succeed))
1844         fatal ("Display on %s not responding.\n",
1845                SSDATA (display));
1846       else
1847         error ("Display on %s not responding.\n",
1848                SSDATA (display));
1849     }
1851   return Qnil;
1855 DEFUN ("x-close-connection", Fx_close_connection, Sx_close_connection,
1856        1, 1, 0,
1857        doc: /* Close the connection to TERMINAL's Nextstep display server.
1858 For TERMINAL, specify a terminal object, a frame or a display name (a
1859 string).  If TERMINAL is nil, that stands for the selected frame's
1860 terminal.  */)
1861      (Lisp_Object terminal)
1863   check_ns_display_info (terminal);
1864   [NSApp terminate: NSApp];
1865   return Qnil;
1869 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
1870        doc: /* Return the list of display names that Emacs has connections to.  */)
1871      (void)
1873   Lisp_Object result = Qnil;
1874   struct ns_display_info *ndi;
1876   for (ndi = x_display_list; ndi; ndi = ndi->next)
1877     result = Fcons (XCAR (ndi->name_list_element), result);
1879   return result;
1883 DEFUN ("ns-hide-others", Fns_hide_others, Sns_hide_others,
1884        0, 0, 0,
1885        doc: /* Hides all applications other than Emacs.  */)
1886      (void)
1888   check_window_system (NULL);
1889   [NSApp hideOtherApplications: NSApp];
1890   return Qnil;
1893 DEFUN ("ns-hide-emacs", Fns_hide_emacs, Sns_hide_emacs,
1894        1, 1, 0,
1895        doc: /* If ON is non-nil, the entire Emacs application is hidden.
1896 Otherwise if Emacs is hidden, it is unhidden.
1897 If ON is equal to `activate', Emacs is unhidden and becomes
1898 the active application.  */)
1899      (Lisp_Object on)
1901   check_window_system (NULL);
1902   if (EQ (on, intern ("activate")))
1903     {
1904       [NSApp unhide: NSApp];
1905       [NSApp activateIgnoringOtherApps: YES];
1906     }
1907   else if (NILP (on))
1908     [NSApp unhide: NSApp];
1909   else
1910     [NSApp hide: NSApp];
1911   return Qnil;
1915 DEFUN ("ns-emacs-info-panel", Fns_emacs_info_panel, Sns_emacs_info_panel,
1916        0, 0, 0,
1917        doc: /* Shows the 'Info' or 'About' panel for Emacs.  */)
1918      (void)
1920   check_window_system (NULL);
1921   [NSApp orderFrontStandardAboutPanel: nil];
1922   return Qnil;
1926 DEFUN ("ns-font-name", Fns_font_name, Sns_font_name, 1, 1, 0,
1927        doc: /* Determine font PostScript or family name for font NAME.
1928 NAME should be a string containing either the font name or an XLFD
1929 font descriptor.  If string contains `fontset' and not
1930 `fontset-startup', it is left alone. */)
1931      (Lisp_Object name)
1933   char *nm;
1934   CHECK_STRING (name);
1935   nm = SSDATA (name);
1937   if (nm[0] != '-')
1938     return name;
1939   if (strstr (nm, "fontset") && !strstr (nm, "fontset-startup"))
1940     return name;
1942   return build_string (ns_xlfd_to_fontname (SSDATA (name)));
1946 DEFUN ("ns-list-colors", Fns_list_colors, Sns_list_colors, 0, 1, 0,
1947        doc: /* Return a list of all available colors.
1948 The optional argument FRAME is currently ignored.  */)
1949      (Lisp_Object frame)
1951   Lisp_Object list = Qnil;
1952   NSEnumerator *colorlists;
1953   NSColorList *clist;
1955   if (!NILP (frame))
1956     {
1957       CHECK_FRAME (frame);
1958       if (! FRAME_NS_P (XFRAME (frame)))
1959         error ("non-Nextstep frame used in `ns-list-colors'");
1960     }
1962   block_input ();
1964   colorlists = [[NSColorList availableColorLists] objectEnumerator];
1965   while ((clist = [colorlists nextObject]))
1966     {
1967       if ([[clist name] length] < 7 ||
1968           [[clist name] rangeOfString: @"PANTONE"].location == 0)
1969         {
1970           NSEnumerator *cnames = [[clist allKeys] reverseObjectEnumerator];
1971           NSString *cname;
1972           while ((cname = [cnames nextObject]))
1973             list = Fcons (build_string ([cname UTF8String]), list);
1974 /*           for (i = [[clist allKeys] count] - 1; i >= 0; i--)
1975                list = Fcons (build_string ([[[clist allKeys] objectAtIndex: i]
1976                                              UTF8String]), list); */
1977         }
1978     }
1980   unblock_input ();
1982   return list;
1986 DEFUN ("ns-list-services", Fns_list_services, Sns_list_services, 0, 0, 0,
1987        doc: /* List available Nextstep services by querying NSApp.  */)
1988      (void)
1990 #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6
1991   /* You can't get services like this in 10.6+.  */
1992   return Qnil;
1993 #else
1994   Lisp_Object ret = Qnil;
1995   NSMenu *svcs;
1996 #ifdef NS_IMPL_COCOA
1997   id delegate;
1998 #endif
2000   check_window_system (NULL);
2001   svcs = [[NSMenu alloc] initWithTitle: @"Services"];
2002   [NSApp setServicesMenu: svcs];
2003   [NSApp registerServicesMenuSendTypes: ns_send_types
2004                            returnTypes: ns_return_types];
2006 /* On Tiger, services menu updating was made lazier (waits for user to
2007    actually click on the menu), so we have to force things along: */
2008 #ifdef NS_IMPL_COCOA
2009   delegate = [svcs delegate];
2010   if (delegate != nil)
2011     {
2012       if ([delegate respondsToSelector: @selector (menuNeedsUpdate:)])
2013         [delegate menuNeedsUpdate: svcs];
2014       if ([delegate respondsToSelector:
2015                        @selector (menu:updateItem:atIndex:shouldCancel:)])
2016         {
2017           int i, len = [delegate numberOfItemsInMenu: svcs];
2018           for (i =0; i<len; i++)
2019             [svcs addItemWithTitle: @"" action: NULL keyEquivalent: @""];
2020           for (i =0; i<len; i++)
2021             if (![delegate menu: svcs
2022                      updateItem: (NSMenuItem *)[svcs itemAtIndex: i]
2023                         atIndex: i shouldCancel: NO])
2024               break;
2025         }
2026     }
2027 #endif
2029   [svcs setAutoenablesItems: NO];
2030 #ifdef NS_IMPL_COCOA
2031   [svcs update]; /* on OS X, converts from '/' structure */
2032 #endif
2034   ret = interpret_services_menu (svcs, Qnil, ret);
2035   return ret;
2036 #endif
2040 DEFUN ("ns-perform-service", Fns_perform_service, Sns_perform_service,
2041        2, 2, 0,
2042        doc: /* Perform Nextstep SERVICE on SEND.
2043 SEND should be either a string or nil.
2044 The return value is the result of the service, as string, or nil if
2045 there was no result.  */)
2046      (Lisp_Object service, Lisp_Object send)
2048   id pb;
2049   NSString *svcName;
2050   char *utfStr;
2052   CHECK_STRING (service);
2053   check_window_system (NULL);
2055   utfStr = SSDATA (service);
2056   svcName = [NSString stringWithUTF8String: utfStr];
2058   pb =[NSPasteboard pasteboardWithUniqueName];
2059   ns_string_to_pasteboard (pb, send);
2061   if (NSPerformService (svcName, pb) == NO)
2062     Fsignal (Qquit, list1 (build_string ("service not available")));
2064   if ([[pb types] count] == 0)
2065     return build_string ("");
2066   return ns_string_from_pasteboard (pb);
2070 DEFUN ("ns-convert-utf8-nfd-to-nfc", Fns_convert_utf8_nfd_to_nfc,
2071        Sns_convert_utf8_nfd_to_nfc, 1, 1, 0,
2072        doc: /* Return an NFC string that matches the UTF-8 NFD string STR.  */)
2073      (Lisp_Object str)
2075 /* TODO: If GNUstep ever implements precomposedStringWithCanonicalMapping,
2076          remove this. */
2077   NSString *utfStr;
2078   Lisp_Object ret = Qnil;
2079   NSAutoreleasePool *pool;
2081   CHECK_STRING (str);
2082   pool = [[NSAutoreleasePool alloc] init];
2083   utfStr = [NSString stringWithUTF8String: SSDATA (str)];
2084 #ifdef NS_IMPL_COCOA
2085   if (utfStr)
2086     utfStr = [utfStr precomposedStringWithCanonicalMapping];
2087 #endif
2088   if (utfStr)
2089     {
2090       const char *cstr = [utfStr UTF8String];
2091       if (cstr)
2092         ret = build_string (cstr);
2093     }
2095   [pool release];
2096   if (NILP (ret))
2097     error ("Invalid UTF-8");
2099   return ret;
2103 #ifdef NS_IMPL_COCOA
2105 /* Compile and execute the AppleScript SCRIPT and return the error
2106    status as function value.  A zero is returned if compilation and
2107    execution is successful, in which case *RESULT is set to a Lisp
2108    string or a number containing the resulting script value.  Otherwise,
2109    1 is returned. */
2110 static int
2111 ns_do_applescript (Lisp_Object script, Lisp_Object *result)
2113   NSAppleEventDescriptor *desc;
2114   NSDictionary* errorDict;
2115   NSAppleEventDescriptor* returnDescriptor = NULL;
2117   NSAppleScript* scriptObject =
2118     [[NSAppleScript alloc] initWithSource:
2119                              [NSString stringWithUTF8String: SSDATA (script)]];
2121   returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
2122   [scriptObject release];
2124   *result = Qnil;
2126   if (returnDescriptor != NULL)
2127     {
2128       // successful execution
2129       if (kAENullEvent != [returnDescriptor descriptorType])
2130         {
2131           *result = Qt;
2132           // script returned an AppleScript result
2133           if ((typeUnicodeText == [returnDescriptor descriptorType]) ||
2134 #if defined (NS_IMPL_COCOA)
2135               (typeUTF16ExternalRepresentation
2136                == [returnDescriptor descriptorType]) ||
2137 #endif
2138               (typeUTF8Text == [returnDescriptor descriptorType]) ||
2139               (typeCString == [returnDescriptor descriptorType]))
2140             {
2141               desc = [returnDescriptor coerceToDescriptorType: typeUTF8Text];
2142               if (desc)
2143                 *result = build_string([[desc stringValue] UTF8String]);
2144             }
2145           else
2146             {
2147               /* use typeUTF16ExternalRepresentation? */
2148               // coerce the result to the appropriate ObjC type
2149               desc = [returnDescriptor coerceToDescriptorType: typeUTF8Text];
2150               if (desc)
2151                 *result = make_number([desc int32Value]);
2152             }
2153         }
2154     }
2155   else
2156     {
2157       // no script result, return error
2158       return 1;
2159     }
2160   return 0;
2163 /* Helper function called from sendEvent to run applescript
2164    from within the main event loop.  */
2166 void
2167 ns_run_ascript (void)
2169   if (! NILP (as_script))
2170     as_status = ns_do_applescript (as_script, as_result);
2171   as_script = Qnil;
2174 DEFUN ("ns-do-applescript", Fns_do_applescript, Sns_do_applescript, 1, 1, 0,
2175        doc: /* Execute AppleScript SCRIPT and return the result.
2176 If compilation and execution are successful, the resulting script value
2177 is returned as a string, a number or, in the case of other constructs, t.
2178 In case the execution fails, an error is signaled. */)
2179      (Lisp_Object script)
2181   Lisp_Object result;
2182   int status;
2183   NSEvent *nxev;
2185   CHECK_STRING (script);
2186   check_window_system (NULL);
2188   block_input ();
2190   as_script = script;
2191   as_result = &result;
2193   /* executing apple script requires the event loop to run, otherwise
2194      errors aren't returned and executeAndReturnError hangs forever.
2195      Post an event that runs applescript and then start the event loop.
2196      The event loop is exited when the script is done.  */
2197   nxev = [NSEvent otherEventWithType: NSApplicationDefined
2198                             location: NSMakePoint (0, 0)
2199                        modifierFlags: 0
2200                            timestamp: 0
2201                         windowNumber: [[NSApp mainWindow] windowNumber]
2202                              context: [NSApp context]
2203                              subtype: 0
2204                                data1: 0
2205                                data2: NSAPP_DATA2_RUNASSCRIPT];
2207   [NSApp postEvent: nxev atStart: NO];
2209   // If there are other events, the event loop may exit.  Keep running
2210   // until the script has been handled.  */
2211   while (! NILP (as_script))
2212     [NSApp run];
2214   status = as_status;
2215   as_status = 0;
2216   as_result = 0;
2217   unblock_input ();
2218   if (status == 0)
2219     return result;
2220   else if (!STRINGP (result))
2221     error ("AppleScript error %d", status);
2222   else
2223     error ("%s", SSDATA (result));
2225 #endif
2229 /* ==========================================================================
2231     Miscellaneous functions not called through hooks
2233    ========================================================================== */
2235 /* called from frame.c */
2236 struct ns_display_info *
2237 check_x_display_info (Lisp_Object frame)
2239   return check_ns_display_info (frame);
2243 void
2244 x_set_scroll_bar_default_width (struct frame *f)
2246   int wid = FRAME_COLUMN_WIDTH (f);
2247   FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = NS_SCROLL_BAR_WIDTH_DEFAULT;
2248   FRAME_CONFIG_SCROLL_BAR_COLS (f) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) +
2249                                       wid - 1) / wid;
2252 /* terms impl this instead of x-get-resource directly */
2253 char *
2254 x_get_string_resource (XrmDatabase rdb, const char *name, const char *class)
2256   /* remove appname prefix; TODO: allow for !="Emacs" */
2257   const char *res, *toCheck = class + (!strncmp (class, "Emacs.", 6) ? 6 : 0);
2259   check_window_system (NULL);
2261   if (inhibit_x_resources)
2262     /* --quick was passed, so this is a no-op.  */
2263     return NULL;
2265   res = ns_get_defaults_value (toCheck);
2266   return (!res ? NULL :
2267           (!c_strncasecmp (res, "YES", 3) ? "true" :
2268            (!c_strncasecmp (res, "NO", 2) ? "false" : (char *) res)));
2272 Lisp_Object
2273 x_get_focus_frame (struct frame *frame)
2275   struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
2276   Lisp_Object nsfocus;
2278   if (!dpyinfo->x_focus_frame)
2279     return Qnil;
2281   XSETFRAME (nsfocus, dpyinfo->x_focus_frame);
2282   return nsfocus;
2285 /* ==========================================================================
2287     Lisp definitions that, for whatever reason, we can't alias as 'ns-XXX'.
2289    ========================================================================== */
2292 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
2293        doc: /* Internal function called by `color-defined-p', which see.
2294 \(Note that the Nextstep version of this function ignores FRAME.)  */)
2295      (Lisp_Object color, Lisp_Object frame)
2297   NSColor * col;
2298   check_window_system (NULL);
2299   return ns_lisp_to_color (color, &col) ? Qnil : Qt;
2303 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
2304        doc: /* Internal function called by `color-values', which see.  */)
2305      (Lisp_Object color, Lisp_Object frame)
2307   NSColor * col;
2308   EmacsCGFloat red, green, blue, alpha;
2310   check_window_system (NULL);
2311   CHECK_STRING (color);
2313   block_input ();
2314   if (ns_lisp_to_color (color, &col))
2315     {
2316       unblock_input ();
2317       return Qnil;
2318     }
2320   [[col colorUsingDefaultColorSpace]
2321         getRed: &red green: &green blue: &blue alpha: &alpha];
2322   unblock_input ();
2323   return list3i (lrint (red * 65280), lrint (green * 65280),
2324                  lrint (blue * 65280));
2328 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
2329        doc: /* Internal function called by `display-color-p', which see.  */)
2330      (Lisp_Object terminal)
2332   NSWindowDepth depth;
2333   NSString *colorSpace;
2335   check_ns_display_info (terminal);
2336   depth = [[[NSScreen screens] objectAtIndex:0] depth];
2337   colorSpace = NSColorSpaceFromDepth (depth);
2339   return    [colorSpace isEqualToString: NSDeviceWhiteColorSpace]
2340          || [colorSpace isEqualToString: NSCalibratedWhiteColorSpace]
2341       ? Qnil : Qt;
2345 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
2346        0, 1, 0,
2347        doc: /* Return t if the Nextstep display supports shades of gray.
2348 Note that color displays do support shades of gray.
2349 The optional argument TERMINAL specifies which display to ask about.
2350 TERMINAL should be a terminal object, a frame or a display name (a string).
2351 If omitted or nil, that stands for the selected frame's display.  */)
2352   (Lisp_Object terminal)
2354   NSWindowDepth depth;
2356   check_ns_display_info (terminal);
2357   depth = [[[NSScreen screens] objectAtIndex:0] depth];
2359   return NSBitsPerPixelFromDepth (depth) > 1 ? Qt : Qnil;
2363 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
2364        0, 1, 0,
2365        doc: /* Return the width in pixels of the Nextstep display TERMINAL.
2366 The optional argument TERMINAL specifies which display to ask about.
2367 TERMINAL should be a terminal object, a frame or a display name (a string).
2368 If omitted or nil, that stands for the selected frame's display.
2370 On \"multi-monitor\" setups this refers to the pixel width for all
2371 physical monitors associated with TERMINAL.  To get information for
2372 each physical monitor, use `display-monitor-attributes-list'.  */)
2373   (Lisp_Object terminal)
2375   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
2377   return make_number (x_display_pixel_width (dpyinfo));
2381 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
2382        Sx_display_pixel_height, 0, 1, 0,
2383        doc: /* Return the height in pixels of the Nextstep display TERMINAL.
2384 The optional argument TERMINAL specifies which display to ask about.
2385 TERMINAL should be a terminal object, a frame or a display name (a string).
2386 If omitted or nil, that stands for the selected frame's display.
2388 On \"multi-monitor\" setups this refers to the pixel height for all
2389 physical monitors associated with TERMINAL.  To get information for
2390 each physical monitor, use `display-monitor-attributes-list'.  */)
2391   (Lisp_Object terminal)
2393   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
2395   return make_number (x_display_pixel_height (dpyinfo));
2398 #ifdef NS_IMPL_COCOA
2400 /* Returns the name for the screen that OBJ represents, or NULL.
2401    Caller must free return value.
2404 static char *
2405 ns_get_name_from_ioreg (io_object_t obj)
2407   char *name = NULL;
2409   NSDictionary *info = (NSDictionary *)
2410     IODisplayCreateInfoDictionary (obj, kIODisplayOnlyPreferredName);
2411   NSDictionary *names = [info objectForKey:
2412                                 [NSString stringWithUTF8String:
2413                                             kDisplayProductName]];
2415   if ([names count] > 0)
2416     {
2417       NSString *n = [names objectForKey: [[names allKeys]
2418                                                  objectAtIndex:0]];
2419       if (n != nil) name = xstrdup ([n UTF8String]);
2420     }
2422   [info release];
2424   return name;
2427 /* Returns the name for the screen that DID came from, or NULL.
2428    Caller must free return value.
2431 static char *
2432 ns_screen_name (CGDirectDisplayID did)
2434   char *name = NULL;
2436 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
2437   mach_port_t masterPort;
2438   io_iterator_t it;
2439   io_object_t obj;
2441   // CGDisplayIOServicePort is deprecated.  Do it another (harder) way.
2443   if (IOMasterPort (MACH_PORT_NULL, &masterPort) != kIOReturnSuccess
2444       || IOServiceGetMatchingServices (masterPort,
2445                                        IOServiceMatching ("IONDRVDevice"),
2446                                        &it) != kIOReturnSuccess)
2447     return name;
2449   /* Must loop until we find a name.  Many devices can have the same unit
2450      number (represents different GPU parts), but only one has a name.  */
2451   while (! name && (obj = IOIteratorNext (it)))
2452     {
2453       CFMutableDictionaryRef props;
2454       const void *val;
2456       if (IORegistryEntryCreateCFProperties (obj,
2457                                              &props,
2458                                              kCFAllocatorDefault,
2459                                              kNilOptions) == kIOReturnSuccess
2460           && props != nil
2461           && (val = CFDictionaryGetValue(props, @"IOFBDependentIndex")))
2462         {
2463           unsigned nr = [(NSNumber *)val unsignedIntegerValue];
2464           if (nr == CGDisplayUnitNumber (did))
2465             name = ns_get_name_from_ioreg (obj);
2466         }
2468       CFRelease (props);
2469       IOObjectRelease (obj);
2470     }
2472   IOObjectRelease (it);
2474 #else
2476   name = ns_get_name_from_ioreg (CGDisplayIOServicePort (did));
2478 #endif
2479   return name;
2481 #endif
2483 static Lisp_Object
2484 ns_make_monitor_attribute_list (struct MonitorInfo *monitors,
2485                                 int n_monitors,
2486                                 int primary_monitor,
2487                                 const char *source)
2489   Lisp_Object monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
2490   Lisp_Object frame, rest;
2491   NSArray *screens = [NSScreen screens];
2492   int i;
2494   FOR_EACH_FRAME (rest, frame)
2495     {
2496       struct frame *f = XFRAME (frame);
2498       if (FRAME_NS_P (f))
2499         {
2500           NSView *view = FRAME_NS_VIEW (f);
2501           NSScreen *screen = [[view window] screen];
2502           NSUInteger k;
2504           i = -1;
2505           for (k = 0; i == -1 && k < [screens count]; ++k)
2506             {
2507               if ([screens objectAtIndex: k] == screen)
2508                 i = (int)k;
2509             }
2511           if (i > -1)
2512             ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
2513         }
2514     }
2516   return make_monitor_attribute_list (monitors, n_monitors, primary_monitor,
2517                                       monitor_frames, source);
2520 DEFUN ("ns-display-monitor-attributes-list",
2521        Fns_display_monitor_attributes_list,
2522        Sns_display_monitor_attributes_list,
2523        0, 1, 0,
2524        doc: /* Return a list of physical monitor attributes on the X display TERMINAL.
2526 The optional argument TERMINAL specifies which display to ask about.
2527 TERMINAL should be a terminal object, a frame or a display name (a string).
2528 If omitted or nil, that stands for the selected frame's display.
2530 In addition to the standard attribute keys listed in
2531 `display-monitor-attributes-list', the following keys are contained in
2532 the attributes:
2534  source -- String describing the source from which multi-monitor
2535            information is obtained, \"NS\" is always the source."
2537 Internal use only, use `display-monitor-attributes-list' instead.  */)
2538   (Lisp_Object terminal)
2540   struct terminal *term = get_terminal (terminal, 1);
2541   NSArray *screens;
2542   NSUInteger i, n_monitors;
2543   struct MonitorInfo *monitors;
2544   Lisp_Object attributes_list = Qnil;
2545   CGFloat primary_display_height = 0;
2547   if (term->type != output_ns)
2548     return Qnil;
2550   screens = [NSScreen screens];
2551   n_monitors = [screens count];
2552   if (n_monitors == 0)
2553     return Qnil;
2555   monitors = xzalloc (n_monitors * sizeof *monitors);
2557   for (i = 0; i < [screens count]; ++i)
2558     {
2559       NSScreen *s = [screens objectAtIndex:i];
2560       struct MonitorInfo *m = &monitors[i];
2561       NSRect fr = [s frame];
2562       NSRect vfr = [s visibleFrame];
2563       short y, vy;
2565 #ifdef NS_IMPL_COCOA
2566       NSDictionary *dict = [s deviceDescription];
2567       NSNumber *nid = [dict objectForKey:@"NSScreenNumber"];
2568       CGDirectDisplayID did = [nid unsignedIntValue];
2569 #endif
2570       if (i == 0)
2571         {
2572           primary_display_height = fr.size.height;
2573           y = (short) fr.origin.y;
2574           vy = (short) vfr.origin.y;
2575         }
2576       else
2577         {
2578           // Flip y coordinate as NS has y starting from the bottom.
2579           y = (short) (primary_display_height - fr.size.height - fr.origin.y);
2580           vy = (short) (primary_display_height -
2581                         vfr.size.height - vfr.origin.y);
2582         }
2584       m->geom.x = (short) fr.origin.x;
2585       m->geom.y = y;
2586       m->geom.width = (unsigned short) fr.size.width;
2587       m->geom.height = (unsigned short) fr.size.height;
2589       m->work.x = (short) vfr.origin.x;
2590       // y is flipped on NS, so vy - y are pixels missing at the bottom,
2591       // and fr.size.height - vfr.size.height are pixels missing in total.
2592       // Pixels missing at top are
2593       // fr.size.height - vfr.size.height - vy + y.
2594       // work.y is then pixels missing at top + y.
2595       m->work.y = (short) (fr.size.height - vfr.size.height) - vy + y + y;
2596       m->work.width = (unsigned short) vfr.size.width;
2597       m->work.height = (unsigned short) vfr.size.height;
2599 #ifdef NS_IMPL_COCOA
2600       m->name = ns_screen_name (did);
2602       {
2603         CGSize mms = CGDisplayScreenSize (did);
2604         m->mm_width = (int) mms.width;
2605         m->mm_height = (int) mms.height;
2606       }
2608 #else
2609       // Assume 92 dpi as x-display-mm-height/x-display-mm-width does.
2610       m->mm_width = (int) (25.4 * fr.size.width / 92.0);
2611       m->mm_height = (int) (25.4 * fr.size.height / 92.0);
2612 #endif
2613     }
2615   // Primary monitor is always first for NS.
2616   attributes_list = ns_make_monitor_attribute_list (monitors, n_monitors,
2617                                                     0, "NS");
2619   free_monitors (monitors, n_monitors);
2620   return attributes_list;
2624 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
2625        0, 1, 0,
2626        doc: /* Return the number of bitplanes of the Nextstep display TERMINAL.
2627 The optional argument TERMINAL specifies which display to ask about.
2628 TERMINAL should be a terminal object, a frame or a display name (a string).
2629 If omitted or nil, that stands for the selected frame's display.  */)
2630   (Lisp_Object terminal)
2632   check_ns_display_info (terminal);
2633   return make_number
2634     (NSBitsPerPixelFromDepth ([[[NSScreen screens] objectAtIndex:0] depth]));
2638 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
2639        0, 1, 0,
2640        doc: /* Returns the number of color cells of the Nextstep display TERMINAL.
2641 The optional argument TERMINAL specifies which display to ask about.
2642 TERMINAL should be a terminal object, a frame or a display name (a string).
2643 If omitted or nil, that stands for the selected frame's display.  */)
2644   (Lisp_Object terminal)
2646   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
2647   /* We force 24+ bit depths to 24-bit to prevent an overflow.  */
2648   return make_number (1 << min (dpyinfo->n_planes, 24));
2652 /* Unused dummy def needed for compatibility. */
2653 Lisp_Object tip_frame;
2655 /* TODO: move to xdisp or similar */
2656 static void
2657 compute_tip_xy (struct frame *f,
2658                 Lisp_Object parms,
2659                 Lisp_Object dx,
2660                 Lisp_Object dy,
2661                 int width,
2662                 int height,
2663                 int *root_x,
2664                 int *root_y)
2666   Lisp_Object left, top;
2667   EmacsView *view = FRAME_NS_VIEW (f);
2668   struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2669   NSPoint pt;
2671   /* Start with user-specified or mouse position.  */
2672   left = Fcdr (Fassq (Qleft, parms));
2673   top = Fcdr (Fassq (Qtop, parms));
2675   if (!INTEGERP (left) || !INTEGERP (top))
2676     {
2677       pt.x = dpyinfo->last_mouse_motion_x;
2678       pt.y = dpyinfo->last_mouse_motion_y;
2679       /* Convert to screen coordinates */
2680       pt = [view convertPoint: pt toView: nil];
2681       pt = [[view window] convertBaseToScreen: pt];
2682     }
2683   else
2684     {
2685       /* Absolute coordinates.  */
2686       pt.x = XINT (left);
2687       pt.y = x_display_pixel_height (FRAME_DISPLAY_INFO (f)) - XINT (top)
2688         - height;
2689     }
2691   /* Ensure in bounds.  (Note, screen origin = lower left.) */
2692   if (INTEGERP (left))
2693     *root_x = pt.x;
2694   else if (pt.x + XINT (dx) <= 0)
2695     *root_x = 0; /* Can happen for negative dx */
2696   else if (pt.x + XINT (dx) + width
2697            <= x_display_pixel_width (FRAME_DISPLAY_INFO (f)))
2698     /* It fits to the right of the pointer.  */
2699     *root_x = pt.x + XINT (dx);
2700   else if (width + XINT (dx) <= pt.x)
2701     /* It fits to the left of the pointer.  */
2702     *root_x = pt.x - width - XINT (dx);
2703   else
2704     /* Put it left justified on the screen -- it ought to fit that way.  */
2705     *root_x = 0;
2707   if (INTEGERP (top))
2708     *root_y = pt.y;
2709   else if (pt.y - XINT (dy) - height >= 0)
2710     /* It fits below the pointer.  */
2711     *root_y = pt.y - height - XINT (dy);
2712   else if (pt.y + XINT (dy) + height
2713            <= x_display_pixel_height (FRAME_DISPLAY_INFO (f)))
2714     /* It fits above the pointer */
2715       *root_y = pt.y + XINT (dy);
2716   else
2717     /* Put it on the top.  */
2718     *root_y = x_display_pixel_height (FRAME_DISPLAY_INFO (f)) - height;
2722 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
2723        doc: /* Show STRING in a \"tooltip\" window on frame FRAME.
2724 A tooltip window is a small window displaying a string.
2726 This is an internal function; Lisp code should call `tooltip-show'.
2728 FRAME nil or omitted means use the selected frame.
2730 PARMS is an optional list of frame parameters which can be used to
2731 change the tooltip's appearance.
2733 Automatically hide the tooltip after TIMEOUT seconds.  TIMEOUT nil
2734 means use the default timeout of 5 seconds.
2736 If the list of frame parameters PARMS contains a `left' parameter,
2737 the tooltip is displayed at that x-position.  Otherwise it is
2738 displayed at the mouse position, with offset DX added (default is 5 if
2739 DX isn't specified).  Likewise for the y-position; if a `top' frame
2740 parameter is specified, it determines the y-position of the tooltip
2741 window, otherwise it is displayed at the mouse position, with offset
2742 DY added (default is -10).
2744 A tooltip's maximum size is specified by `x-max-tooltip-size'.
2745 Text larger than the specified size is clipped.  */)
2746      (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
2748   int root_x, root_y;
2749   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2750   ptrdiff_t count = SPECPDL_INDEX ();
2751   struct frame *f;
2752   char *str;
2753   NSSize size;
2755   specbind (Qinhibit_redisplay, Qt);
2757   GCPRO4 (string, parms, frame, timeout);
2759   CHECK_STRING (string);
2760   str = SSDATA (string);
2761   f = decode_window_system_frame (frame);
2762   if (NILP (timeout))
2763     timeout = make_number (5);
2764   else
2765     CHECK_NATNUM (timeout);
2767   if (NILP (dx))
2768     dx = make_number (5);
2769   else
2770     CHECK_NUMBER (dx);
2772   if (NILP (dy))
2773     dy = make_number (-10);
2774   else
2775     CHECK_NUMBER (dy);
2777   block_input ();
2778   if (ns_tooltip == nil)
2779     ns_tooltip = [[EmacsTooltip alloc] init];
2780   else
2781     Fx_hide_tip ();
2783   [ns_tooltip setText: str];
2784   size = [ns_tooltip frame].size;
2786   /* Move the tooltip window where the mouse pointer is.  Resize and
2787      show it.  */
2788   compute_tip_xy (f, parms, dx, dy, (int)size.width, (int)size.height,
2789                   &root_x, &root_y);
2791   [ns_tooltip showAtX: root_x Y: root_y for: XINT (timeout)];
2792   unblock_input ();
2794   UNGCPRO;
2795   return unbind_to (count, Qnil);
2799 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
2800        doc: /* Hide the current tooltip window, if there is any.
2801 Value is t if tooltip was open, nil otherwise.  */)
2802      (void)
2804   if (ns_tooltip == nil || ![ns_tooltip isActive])
2805     return Qnil;
2806   [ns_tooltip hide];
2807   return Qt;
2811 /* ==========================================================================
2813     Class implementations
2815    ========================================================================== */
2818   Handle arrow/function/control keys and copy/paste/cut in file dialogs.
2819   Return YES if handled, NO if not.
2820  */
2821 static BOOL
2822 handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent)
2824   NSString *s;
2825   int i;
2826   BOOL ret = NO;
2828   if ([theEvent type] != NSKeyDown) return NO;
2829   s = [theEvent characters];
2831   for (i = 0; i < [s length]; ++i)
2832     {
2833       int ch = (int) [s characterAtIndex: i];
2834       switch (ch)
2835         {
2836         case NSHomeFunctionKey:
2837         case NSDownArrowFunctionKey:
2838         case NSUpArrowFunctionKey:
2839         case NSLeftArrowFunctionKey:
2840         case NSRightArrowFunctionKey:
2841         case NSPageUpFunctionKey:
2842         case NSPageDownFunctionKey:
2843         case NSEndFunctionKey:
2844           /* Don't send command modified keys, as those are handled in the
2845              performKeyEquivalent method of the super class.
2846           */
2847           if (! ([theEvent modifierFlags] & NSCommandKeyMask))
2848             {
2849               [panel sendEvent: theEvent];
2850               ret = YES;
2851             }
2852           break;
2853           /* As we don't have the standard key commands for
2854              copy/paste/cut/select-all in our edit menu, we must handle
2855              them here.  TODO: handle Emacs key bindings for copy/cut/select-all
2856              here, paste works, because we have that in our Edit menu.
2857              I.e. refactor out code in nsterm.m, keyDown: to figure out the
2858              correct modifier.
2859           */
2860         case 'x': // Cut
2861         case 'c': // Copy
2862         case 'v': // Paste
2863         case 'a': // Select all
2864           if ([theEvent modifierFlags] & NSCommandKeyMask)
2865             {
2866               [NSApp sendAction:
2867                        (ch == 'x'
2868                         ? @selector(cut:)
2869                         : (ch == 'c'
2870                            ? @selector(copy:)
2871                            : (ch == 'v'
2872                               ? @selector(paste:)
2873                               : @selector(selectAll:))))
2874                              to:nil from:panel];
2875               ret = YES;
2876             }
2877         default:
2878           // Send all control keys, as the text field supports C-a, C-f, C-e
2879           // C-b and more.
2880           if ([theEvent modifierFlags] & NSControlKeyMask)
2881             {
2882               [panel sendEvent: theEvent];
2883               ret = YES;
2884             }
2885           break;
2886         }
2887     }
2890   return ret;
2893 @implementation EmacsSavePanel
2894 - (BOOL)performKeyEquivalent:(NSEvent *)theEvent
2896   BOOL ret = handlePanelKeys (self, theEvent);
2897   if (! ret)
2898     ret = [super performKeyEquivalent:theEvent];
2899   return ret;
2901 @end
2904 @implementation EmacsOpenPanel
2905 - (BOOL)performKeyEquivalent:(NSEvent *)theEvent
2907   // NSOpenPanel inherits NSSavePanel, so passing self is OK.
2908   BOOL ret = handlePanelKeys (self, theEvent);
2909   if (! ret)
2910     ret = [super performKeyEquivalent:theEvent];
2911   return ret;
2913 @end
2916 @implementation EmacsFileDelegate
2917 /* --------------------------------------------------------------------------
2918    Delegate methods for Open/Save panels
2919    -------------------------------------------------------------------------- */
2920 - (BOOL)panel: (id)sender isValidFilename: (NSString *)filename
2922   return YES;
2924 - (BOOL)panel: (id)sender shouldShowFilename: (NSString *)filename
2926   return YES;
2928 - (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename
2929           confirmed: (BOOL)okFlag
2931   return filename;
2933 @end
2935 #endif
2938 /* ==========================================================================
2940     Lisp interface declaration
2942    ========================================================================== */
2945 void
2946 syms_of_nsfns (void)
2948   Qfontsize = intern_c_string ("fontsize");
2949   staticpro (&Qfontsize);
2951   DEFVAR_LISP ("ns-icon-type-alist", Vns_icon_type_alist,
2952                doc: /* Alist of elements (REGEXP . IMAGE) for images of icons associated to frames.
2953 If the title of a frame matches REGEXP, then IMAGE.tiff is
2954 selected as the image of the icon representing the frame when it's
2955 miniaturized.  If an element is t, then Emacs tries to select an icon
2956 based on the filetype of the visited file.
2958 The images have to be installed in a folder called English.lproj in the
2959 Emacs folder.  You have to restart Emacs after installing new icons.
2961 Example: Install an icon Gnus.tiff and execute the following code
2963   (setq ns-icon-type-alist
2964         (append ns-icon-type-alist
2965                 '((\"^\\\\*\\\\(Group\\\\*$\\\\|Summary \\\\|Article\\\\*$\\\\)\"
2966                    . \"Gnus\"))))
2968 When you miniaturize a Group, Summary or Article frame, Gnus.tiff will
2969 be used as the image of the icon representing the frame.  */);
2970   Vns_icon_type_alist = list1 (Qt);
2972   DEFVAR_LISP ("ns-version-string", Vns_version_string,
2973                doc: /* Toolkit version for NS Windowing.  */);
2974   Vns_version_string = ns_appkit_version_str ();
2976   defsubr (&Sns_read_file_name);
2977   defsubr (&Sns_get_resource);
2978   defsubr (&Sns_set_resource);
2979   defsubr (&Sxw_display_color_p); /* this and next called directly by C code */
2980   defsubr (&Sx_display_grayscale_p);
2981   defsubr (&Sns_font_name);
2982   defsubr (&Sns_list_colors);
2983 #ifdef NS_IMPL_COCOA
2984   defsubr (&Sns_do_applescript);
2985 #endif
2986   defsubr (&Sxw_color_defined_p);
2987   defsubr (&Sxw_color_values);
2988   defsubr (&Sx_server_max_request_size);
2989   defsubr (&Sx_server_vendor);
2990   defsubr (&Sx_server_version);
2991   defsubr (&Sx_display_pixel_width);
2992   defsubr (&Sx_display_pixel_height);
2993   defsubr (&Sns_display_monitor_attributes_list);
2994   defsubr (&Sx_display_mm_width);
2995   defsubr (&Sx_display_mm_height);
2996   defsubr (&Sx_display_screens);
2997   defsubr (&Sx_display_planes);
2998   defsubr (&Sx_display_color_cells);
2999   defsubr (&Sx_display_visual_class);
3000   defsubr (&Sx_display_backing_store);
3001   defsubr (&Sx_display_save_under);
3002   defsubr (&Sx_create_frame);
3003   defsubr (&Sx_open_connection);
3004   defsubr (&Sx_close_connection);
3005   defsubr (&Sx_display_list);
3007   defsubr (&Sns_hide_others);
3008   defsubr (&Sns_hide_emacs);
3009   defsubr (&Sns_emacs_info_panel);
3010   defsubr (&Sns_list_services);
3011   defsubr (&Sns_perform_service);
3012   defsubr (&Sns_convert_utf8_nfd_to_nfc);
3013   defsubr (&Sns_popup_font_panel);
3014   defsubr (&Sns_popup_color_panel);
3016   defsubr (&Sx_show_tip);
3017   defsubr (&Sx_hide_tip);
3019   as_status = 0;
3020   as_script = Qnil;
3021   as_result = 0;