* lisp/gnus/gnus-topic.el: Silence some warnings
[emacs.git] / src / nsfns.m
blob1ed3e23cba5c722722093ea632891b8b0c151768
1 /* Functions for the NeXT/Open/GNUstep and MacOSX window system.
3 Copyright (C) 1989, 1992-1994, 2005-2006, 2008-2015 Free Software
4 Foundation, Inc.
6 This file is part of GNU Emacs.
8 GNU Emacs is free software: you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation, either version 3 of the License, or
11 (at your option) any later version.
13 GNU Emacs is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
22 Originally by Carl Edman
23 Updated by Christian Limpach (chris@nice.ch)
24 OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com)
25 MacOSX/Aqua port by Christophe de Dinechin (descubes@earthlink.net)
26 GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
29 /* This should be the first include, as it may set up #defines affecting
30    interpretation of even the system includes. */
31 #include <config.h>
33 #include <math.h>
34 #include <c-strcase.h>
36 #include "lisp.h"
37 #include "blockinput.h"
38 #include "nsterm.h"
39 #include "window.h"
40 #include "character.h"
41 #include "buffer.h"
42 #include "keyboard.h"
43 #include "termhooks.h"
44 #include "fontset.h"
45 #include "font.h"
47 #ifdef NS_IMPL_COCOA
48 #include <IOKit/graphics/IOGraphicsLib.h>
49 #include "macfont.h"
50 #endif
53 #ifdef HAVE_NS
55 extern NSArray *ns_send_types, *ns_return_types, *ns_drag_types;
57 EmacsTooltip *ns_tooltip = nil;
59 /* Need forward declaration here to preserve organizational integrity of file */
60 Lisp_Object Fx_open_connection (Lisp_Object, Lisp_Object, Lisp_Object);
62 /* Static variables to handle applescript execution.  */
63 static Lisp_Object as_script, *as_result;
64 static int as_status;
66 static ptrdiff_t image_cache_refcount;
69 /* ==========================================================================
71     Internal utility functions
73    ========================================================================== */
75 /* Let the user specify a Nextstep display with a Lisp object.
76    OBJECT may be nil, a frame or a terminal object.
77    nil stands for the selected frame--or, if that is not a Nextstep frame,
78    the first Nextstep display on the list.  */
80 static struct ns_display_info *
81 check_ns_display_info (Lisp_Object object)
83   struct ns_display_info *dpyinfo = NULL;
85   if (NILP (object))
86     {
87       struct frame *sf = XFRAME (selected_frame);
89       if (FRAME_NS_P (sf) && FRAME_LIVE_P (sf))
90         dpyinfo = FRAME_DISPLAY_INFO (sf);
91       else if (x_display_list != 0)
92         dpyinfo = x_display_list;
93       else
94         error ("Nextstep windows are not in use or not initialized");
95     }
96   else if (TERMINALP (object))
97     {
98       struct terminal *t = decode_live_terminal (object);
100       if (t->type != output_ns)
101         error ("Terminal %d is not a Nextstep display", t->id);
103       dpyinfo = t->display_info.ns;
104     }
105   else if (STRINGP (object))
106     dpyinfo = ns_display_info_for_name (object);
107   else
108     {
109       struct frame *f = decode_window_system_frame (object);
110       dpyinfo = FRAME_DISPLAY_INFO (f);
111     }
113   return dpyinfo;
117 static id
118 ns_get_window (Lisp_Object maybeFrame)
120   id view =nil, window =nil;
122   if (!FRAMEP (maybeFrame) || !FRAME_NS_P (XFRAME (maybeFrame)))
123     maybeFrame = selected_frame;/*wrong_type_argument (Qframep, maybeFrame); */
125   if (!NILP (maybeFrame))
126     view = FRAME_NS_VIEW (XFRAME (maybeFrame));
127   if (view) window =[view window];
129   return window;
133 /* Return the X display structure for the display named NAME.
134    Open a new connection if necessary.  */
135 struct ns_display_info *
136 ns_display_info_for_name (Lisp_Object name)
138   struct ns_display_info *dpyinfo;
140   CHECK_STRING (name);
142   for (dpyinfo = x_display_list; dpyinfo; dpyinfo = dpyinfo->next)
143     if (!NILP (Fstring_equal (XCAR (dpyinfo->name_list_element), name)))
144       return dpyinfo;
146   error ("Emacs for Nextstep does not yet support multi-display");
148   Fx_open_connection (name, Qnil, Qnil);
149   dpyinfo = x_display_list;
151   if (dpyinfo == 0)
152     error ("Display on %s not responding.\n", SDATA (name));
154   return dpyinfo;
157 static NSString *
158 ns_filename_from_panel (NSSavePanel *panel)
160 #ifdef NS_IMPL_COCOA
161   NSURL *url = [panel URL];
162   NSString *str = [url path];
163   return str;
164 #else
165   return [panel filename];
166 #endif
169 static NSString *
170 ns_directory_from_panel (NSSavePanel *panel)
172 #ifdef NS_IMPL_COCOA
173   NSURL *url = [panel directoryURL];
174   NSString *str = [url path];
175   return str;
176 #else
177   return [panel directory];
178 #endif
181 static Lisp_Object
182 interpret_services_menu (NSMenu *menu, Lisp_Object prefix, Lisp_Object old)
183 /* --------------------------------------------------------------------------
184    Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side
185    -------------------------------------------------------------------------- */
187   int i, count;
188   NSMenuItem *item;
189   const char *name;
190   Lisp_Object nameStr;
191   unsigned short key;
192   NSString *keys;
193   Lisp_Object res;
195   count = [menu numberOfItems];
196   for (i = 0; i<count; i++)
197     {
198       item = [menu itemAtIndex: i];
199       name = [[item title] UTF8String];
200       if (!name) continue;
202       nameStr = build_string (name);
204       if ([item hasSubmenu])
205         {
206           old = interpret_services_menu ([item submenu],
207                                         Fcons (nameStr, prefix), old);
208         }
209       else
210         {
211           keys = [item keyEquivalent];
212           if (keys && [keys length] )
213             {
214               key = [keys characterAtIndex: 0];
215               res = make_number (key|super_modifier);
216             }
217           else
218             {
219               res = Qundefined;
220             }
221           old = Fcons (Fcons (res,
222                             Freverse (Fcons (nameStr,
223                                            prefix))),
224                     old);
225         }
226     }
227   return old;
232 /* ==========================================================================
234     Frame parameter setters
236    ========================================================================== */
239 static void
240 x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
242   NSColor *col;
243   EmacsCGFloat r, g, b, alpha;
245   /* Must block_input, because ns_lisp_to_color does block/unblock_input
246      which means that col may be deallocated in its unblock_input if there
247      is user input, unless we also block_input.  */
248   block_input ();
249   if (ns_lisp_to_color (arg, &col))
250     {
251       store_frame_param (f, Qforeground_color, oldval);
252       unblock_input ();
253       error ("Unknown color");
254     }
256   [col retain];
257   [f->output_data.ns->foreground_color release];
258   f->output_data.ns->foreground_color = col;
260   [col getRed: &r green: &g blue: &b alpha: &alpha];
261   FRAME_FOREGROUND_PIXEL (f) =
262     ARGB_TO_ULONG ((int)(alpha*0xff), (int)(r*0xff), (int)(g*0xff), (int)(b*0xff));
264   if (FRAME_NS_VIEW (f))
265     {
266       update_face_from_frame_parameter (f, Qforeground_color, arg);
267       /*recompute_basic_faces (f); */
268       if (FRAME_VISIBLE_P (f))
269         SET_FRAME_GARBAGED (f);
270     }
271   unblock_input ();
275 static void
276 x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
278   struct face *face;
279   NSColor *col;
280   NSView *view = FRAME_NS_VIEW (f);
281   EmacsCGFloat r, g, b, alpha;
283   block_input ();
284   if (ns_lisp_to_color (arg, &col))
285     {
286       store_frame_param (f, Qbackground_color, oldval);
287       unblock_input ();
288       error ("Unknown color");
289     }
291   /* clear the frame; in some instances the NS-internal GC appears not to
292      update, or it does update and cannot clear old text properly */
293   if (FRAME_VISIBLE_P (f))
294     ns_clear_frame (f);
296   [col retain];
297   [f->output_data.ns->background_color release];
298   f->output_data.ns->background_color = col;
300   [col getRed: &r green: &g blue: &b alpha: &alpha];
301   FRAME_BACKGROUND_PIXEL (f) =
302     ARGB_TO_ULONG ((int)(alpha*0xff), (int)(r*0xff), (int)(g*0xff), (int)(b*0xff));
304   if (view != nil)
305     {
306       [[view window] setBackgroundColor: col];
308       if (alpha != (EmacsCGFloat) 1.0)
309           [[view window] setOpaque: NO];
310       else
311           [[view window] setOpaque: YES];
313       face = FRAME_DEFAULT_FACE (f);
314       if (face)
315         {
316           col = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f);
317           face->background = ns_index_color
318             ([col colorWithAlphaComponent: alpha], f);
320           update_face_from_frame_parameter (f, Qbackground_color, arg);
321         }
323       if (FRAME_VISIBLE_P (f))
324         SET_FRAME_GARBAGED (f);
325     }
326   unblock_input ();
330 static void
331 x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
333   NSColor *col;
335   block_input ();
336   if (ns_lisp_to_color (arg, &col))
337     {
338       store_frame_param (f, Qcursor_color, oldval);
339       unblock_input ();
340       error ("Unknown color");
341     }
343   [FRAME_CURSOR_COLOR (f) release];
344   FRAME_CURSOR_COLOR (f) = [col retain];
346   if (FRAME_VISIBLE_P (f))
347     {
348       x_update_cursor (f, 0);
349       x_update_cursor (f, 1);
350     }
351   update_face_from_frame_parameter (f, Qcursor_color, arg);
352   unblock_input ();
356 static void
357 x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
359   NSView *view = FRAME_NS_VIEW (f);
360   NSTRACE ("x_set_icon_name");
362   /* see if it's changed */
363   if (STRINGP (arg))
364     {
365       if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
366         return;
367     }
368   else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
369     return;
371   fset_icon_name (f, arg);
373   if (NILP (arg))
374     {
375       if (!NILP (f->title))
376         arg = f->title;
377       else
378         /* Explicit name and no icon-name -> explicit_name.  */
379         if (f->explicit_name)
380           arg = f->name;
381         else
382           {
383             /* No explicit name and no icon-name ->
384                name has to be rebuild from icon_title_format.  */
385             windows_or_buffers_changed = 62;
386             return;
387           }
388     }
390   /* Don't change the name if it's already NAME.  */
391   if ([[view window] miniwindowTitle]
392       && ([[[view window] miniwindowTitle]
393              isEqualToString: [NSString stringWithUTF8String:
394                                           SSDATA (arg)]]))
395     return;
397   [[view window] setMiniwindowTitle:
398         [NSString stringWithUTF8String: SSDATA (arg)]];
401 static void
402 ns_set_name_internal (struct frame *f, Lisp_Object name)
404   Lisp_Object encoded_name, encoded_icon_name;
405   NSString *str;
406   NSView *view = FRAME_NS_VIEW (f);
408   encoded_name = ENCODE_UTF_8 (name);
410   str = [NSString stringWithUTF8String: SSDATA (encoded_name)];
412   /* Don't change the name if it's already NAME.  */
413   if (! [[[view window] title] isEqualToString: str])
414     [[view window] setTitle: str];
416   if (!STRINGP (f->icon_name))
417     encoded_icon_name = encoded_name;
418   else
419     encoded_icon_name = ENCODE_UTF_8 (f->icon_name);
421   str = [NSString stringWithUTF8String: SSDATA (encoded_icon_name)];
423   if ([[view window] miniwindowTitle]
424       && ! [[[view window] miniwindowTitle] isEqualToString: str])
425     [[view window] setMiniwindowTitle: str];
429 static void
430 ns_set_name (struct frame *f, Lisp_Object name, int explicit)
432   NSTRACE ("ns_set_name");
434   /* Make sure that requests from lisp code override requests from
435      Emacs redisplay code.  */
436   if (explicit)
437     {
438       /* If we're switching from explicit to implicit, we had better
439          update the mode lines and thereby update the title.  */
440       if (f->explicit_name && NILP (name))
441         update_mode_lines = 21;
443       f->explicit_name = ! NILP (name);
444     }
445   else if (f->explicit_name)
446     return;
448   if (NILP (name))
449     name = build_string ([ns_app_name UTF8String]);
450   else
451     CHECK_STRING (name);
453   /* Don't change the name if it's already NAME.  */
454   if (! NILP (Fstring_equal (name, f->name)))
455     return;
457   fset_name (f, name);
459   /* Title overrides explicit name.  */
460   if (! NILP (f->title))
461     name = f->title;
463   ns_set_name_internal (f, name);
467 /* This function should be called when the user's lisp code has
468    specified a name for the frame; the name will override any set by the
469    redisplay code.  */
470 static void
471 x_explicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
473   NSTRACE ("x_explicitly_set_name");
474   ns_set_name (f, arg, 1);
478 /* This function should be called by Emacs redisplay code to set the
479    name; names set this way will never override names set by the user's
480    lisp code.  */
481 void
482 x_implicitly_set_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
484   NSTRACE ("x_implicitly_set_name");
486   /* Deal with NS specific format t.  */
487   if (FRAME_NS_P (f) && ((FRAME_ICONIFIED_P (f) && EQ (Vicon_title_format, Qt))
488                          || EQ (Vframe_title_format, Qt)))
489     ns_set_name_as_filename (f);
490   else
491     ns_set_name (f, arg, 0);
495 /* Change the title of frame F to NAME.
496    If NAME is nil, use the frame name as the title.  */
498 static void
499 x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
501   NSTRACE ("x_set_title");
502   /* Don't change the title if it's already NAME.  */
503   if (EQ (name, f->title))
504     return;
506   update_mode_lines = 22;
508   fset_title (f, name);
510   if (NILP (name))
511     name = f->name;
512   else
513     CHECK_STRING (name);
515   ns_set_name_internal (f, name);
519 void
520 ns_set_name_as_filename (struct frame *f)
522   NSView *view;
523   Lisp_Object name, filename;
524   Lisp_Object buf = XWINDOW (f->selected_window)->contents;
525   const char *title;
526   NSAutoreleasePool *pool;
527   Lisp_Object encoded_name, encoded_filename;
528   NSString *str;
529   NSTRACE ("ns_set_name_as_filename");
531   if (f->explicit_name || ! NILP (f->title))
532     return;
534   block_input ();
535   pool = [[NSAutoreleasePool alloc] init];
536   filename = BVAR (XBUFFER (buf), filename);
537   name = BVAR (XBUFFER (buf), name);
539   if (NILP (name))
540     {
541       if (! NILP (filename))
542         name = Ffile_name_nondirectory (filename);
543       else
544         name = build_string ([ns_app_name UTF8String]);
545     }
547   encoded_name = ENCODE_UTF_8 (name);
549   view = FRAME_NS_VIEW (f);
551   title = FRAME_ICONIFIED_P (f) ? [[[view window] miniwindowTitle] UTF8String]
552                                 : [[[view window] title] UTF8String];
554   if (title && (! strcmp (title, SSDATA (encoded_name))))
555     {
556       [pool release];
557       unblock_input ();
558       return;
559     }
561   str = [NSString stringWithUTF8String: SSDATA (encoded_name)];
562   if (str == nil) str = @"Bad coding";
564   if (FRAME_ICONIFIED_P (f))
565     [[view window] setMiniwindowTitle: str];
566   else
567     {
568       NSString *fstr;
570       if (! NILP (filename))
571         {
572           encoded_filename = ENCODE_UTF_8 (filename);
574           fstr = [NSString stringWithUTF8String: SSDATA (encoded_filename)];
575           if (fstr == nil) fstr = @"";
576         }
577       else
578         fstr = @"";
580       ns_set_represented_filename (fstr, f);
581       [[view window] setTitle: str];
582       fset_name (f, name);
583     }
585   [pool release];
586   unblock_input ();
590 void
591 ns_set_doc_edited (void)
593   NSAutoreleasePool *pool;
594   Lisp_Object tail, frame;
595   block_input ();
596   pool = [[NSAutoreleasePool alloc] init];
597   FOR_EACH_FRAME (tail, frame)
598     {
599       BOOL edited = NO;
600       struct frame *f = XFRAME (frame);
601       struct window *w;
602       NSView *view;
604       if (! FRAME_NS_P (f)) continue;
605       w = XWINDOW (FRAME_SELECTED_WINDOW (f));
606       view = FRAME_NS_VIEW (f);
607       if (!MINI_WINDOW_P (w))
608         edited = ! NILP (Fbuffer_modified_p (w->contents)) &&
609           ! NILP (Fbuffer_file_name (w->contents));
610       [[view window] setDocumentEdited: edited];
611     }
613   [pool release];
614   unblock_input ();
618 void
619 x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
621   int nlines;
622   if (FRAME_MINIBUF_ONLY_P (f))
623     return;
625   if (TYPE_RANGED_INTEGERP (int, value))
626     nlines = XINT (value);
627   else
628     nlines = 0;
630   FRAME_MENU_BAR_LINES (f) = 0;
631   if (nlines)
632     {
633       FRAME_EXTERNAL_MENU_BAR (f) = 1;
634       /* does for all frames, whereas we just want for one frame
635          [NSMenu setMenuBarVisible: YES]; */
636     }
637   else
638     {
639       if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
640         free_frame_menubar (f);
641       /*      [NSMenu setMenuBarVisible: NO]; */
642       FRAME_EXTERNAL_MENU_BAR (f) = 0;
643     }
647 /* toolbar support */
648 void
649 x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
651   int nlines;
653   if (FRAME_MINIBUF_ONLY_P (f))
654     return;
656   if (RANGED_INTEGERP (0, value, INT_MAX))
657     nlines = XFASTINT (value);
658   else
659     nlines = 0;
661   if (nlines)
662     {
663       FRAME_EXTERNAL_TOOL_BAR (f) = 1;
664       update_frame_tool_bar (f);
665     }
666   else
667     {
668       if (FRAME_EXTERNAL_TOOL_BAR (f))
669         {
670           free_frame_tool_bar (f);
671           FRAME_EXTERNAL_TOOL_BAR (f) = 0;
672         }
673     }
675   {
676     int inhibit
677       = ((f->after_make_frame
678           && !f->tool_bar_resized
679           && (EQ (frame_inhibit_implied_resize, Qt)
680               || (CONSP (frame_inhibit_implied_resize)
681                   && !NILP (Fmemq (Qtool_bar_lines,
682                                    frame_inhibit_implied_resize))))
683           /* This will probably fail to DTRT in the
684              fullheight/-width cases.  */
685           && NILP (get_frame_param (f, Qfullscreen)))
686          ? 0
687          : 2);
689     frame_size_history_add (f, Qupdate_frame_tool_bar, 0, 0, Qnil);
690     adjust_frame_size (f, -1, -1, inhibit, 0, Qtool_bar_lines);
691   }
695 void
696 x_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
698   int old_width = FRAME_INTERNAL_BORDER_WIDTH (f);
700   CHECK_TYPE_RANGED_INTEGER (int, arg);
701   FRAME_INTERNAL_BORDER_WIDTH (f) = XINT (arg);
702   if (FRAME_INTERNAL_BORDER_WIDTH (f) < 0)
703     FRAME_INTERNAL_BORDER_WIDTH (f) = 0;
705   if (FRAME_INTERNAL_BORDER_WIDTH (f) == old_width)
706     return;
708   if (FRAME_X_WINDOW (f) != 0)
709     adjust_frame_size (f, -1, -1, 3, 0, Qinternal_border_width);
711   SET_FRAME_GARBAGED (f);
715 static void
716 ns_implicitly_set_icon_type (struct frame *f)
718   Lisp_Object tem;
719   EmacsView *view = FRAME_NS_VIEW (f);
720   id image = nil;
721   Lisp_Object chain, elt;
722   NSAutoreleasePool *pool;
723   BOOL setMini = YES;
725   NSTRACE ("ns_implicitly_set_icon_type");
727   block_input ();
728   pool = [[NSAutoreleasePool alloc] init];
729   if (f->output_data.ns->miniimage
730       && [[NSString stringWithUTF8String: SSDATA (f->name)]
731                isEqualToString: [(NSImage *)f->output_data.ns->miniimage name]])
732     {
733       [pool release];
734       unblock_input ();
735       return;
736     }
738   tem = assq_no_quit (Qicon_type, f->param_alist);
739   if (CONSP (tem) && ! NILP (XCDR (tem)))
740     {
741       [pool release];
742       unblock_input ();
743       return;
744     }
746   for (chain = Vns_icon_type_alist;
747        image == nil && CONSP (chain);
748        chain = XCDR (chain))
749     {
750       elt = XCAR (chain);
751       /* special case: t means go by file type */
752       if (SYMBOLP (elt) && EQ (elt, Qt) && SSDATA (f->name)[0] == '/')
753         {
754           NSString *str
755              = [NSString stringWithUTF8String: SSDATA (f->name)];
756           if ([[NSFileManager defaultManager] fileExistsAtPath: str])
757             image = [[[NSWorkspace sharedWorkspace] iconForFile: str] retain];
758         }
759       else if (CONSP (elt) &&
760                STRINGP (XCAR (elt)) &&
761                STRINGP (XCDR (elt)) &&
762                fast_string_match (XCAR (elt), f->name) >= 0)
763         {
764           image = [EmacsImage allocInitFromFile: XCDR (elt)];
765           if (image == nil)
766             image = [[NSImage imageNamed:
767                                [NSString stringWithUTF8String:
768                                             SSDATA (XCDR (elt))]] retain];
769         }
770     }
772   if (image == nil)
773     {
774       image = [[[NSWorkspace sharedWorkspace] iconForFileType: @"text"] retain];
775       setMini = NO;
776     }
778   [f->output_data.ns->miniimage release];
779   f->output_data.ns->miniimage = image;
780   [view setMiniwindowImage: setMini];
781   [pool release];
782   unblock_input ();
786 static void
787 x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
789   EmacsView *view = FRAME_NS_VIEW (f);
790   id image = nil;
791   BOOL setMini = YES;
793   NSTRACE ("x_set_icon_type");
795   if (!NILP (arg) && SYMBOLP (arg))
796     {
797       arg =build_string (SSDATA (SYMBOL_NAME (arg)));
798       store_frame_param (f, Qicon_type, arg);
799     }
801   /* do it the implicit way */
802   if (NILP (arg))
803     {
804       ns_implicitly_set_icon_type (f);
805       return;
806     }
808   CHECK_STRING (arg);
810   image = [EmacsImage allocInitFromFile: arg];
811   if (image == nil)
812     image =[NSImage imageNamed: [NSString stringWithUTF8String:
813                                             SSDATA (arg)]];
815   if (image == nil)
816     {
817       image = [NSImage imageNamed: @"text"];
818       setMini = NO;
819     }
821   f->output_data.ns->miniimage = image;
822   [view setMiniwindowImage: setMini];
826 /* TODO: move to nsterm? */
828 ns_lisp_to_cursor_type (Lisp_Object arg)
830   char *str;
831   if (XTYPE (arg) == Lisp_String)
832     str = SSDATA (arg);
833   else if (XTYPE (arg) == Lisp_Symbol)
834     str = SSDATA (SYMBOL_NAME (arg));
835   else return -1;
836   if (!strcmp (str, "box"))     return FILLED_BOX_CURSOR;
837   if (!strcmp (str, "hollow"))  return HOLLOW_BOX_CURSOR;
838   if (!strcmp (str, "hbar"))    return HBAR_CURSOR;
839   if (!strcmp (str, "bar"))     return BAR_CURSOR;
840   if (!strcmp (str, "no"))      return NO_CURSOR;
841   return -1;
845 Lisp_Object
846 ns_cursor_type_to_lisp (int arg)
848   switch (arg)
849     {
850     case FILLED_BOX_CURSOR: return Qbox;
851     case HOLLOW_BOX_CURSOR: return Qhollow;
852     case HBAR_CURSOR:       return Qhbar;
853     case BAR_CURSOR:        return Qbar;
854     case NO_CURSOR:
855     default:                return intern ("no");
856     }
859 /* This is the same as the xfns.c definition.  */
860 static void
861 x_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
863   set_frame_cursor_types (f, arg);
866 /* called to set mouse pointer color, but all other terms use it to
867    initialize pointer types (and don't set the color ;) */
868 static void
869 x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
871   /* don't think we can do this on Nextstep */
875 #define Str(x) #x
876 #define Xstr(x) Str(x)
878 static Lisp_Object
879 ns_appkit_version_str (void)
881   char tmp[256];
883 #ifdef NS_IMPL_GNUSTEP
884   sprintf(tmp, "gnustep-gui-%s", Xstr(GNUSTEP_GUI_VERSION));
885 #elif defined (NS_IMPL_COCOA)
886   NSString *osversion
887     = [[NSProcessInfo processInfo] operatingSystemVersionString];
888   sprintf(tmp, "appkit-%.2f %s",
889           NSAppKitVersionNumber,
890           [osversion UTF8String]);
891 #else
892   tmp = "ns-unknown";
893 #endif
894   return build_string (tmp);
898 /* This is for use by x-server-version and collapses all version info we
899    have into a single int.  For a better picture of the implementation
900    running, use ns_appkit_version_str.*/
901 static int
902 ns_appkit_version_int (void)
904 #ifdef NS_IMPL_GNUSTEP
905   return GNUSTEP_GUI_MAJOR_VERSION * 100 + GNUSTEP_GUI_MINOR_VERSION;
906 #elif defined (NS_IMPL_COCOA)
907   return (int)NSAppKitVersionNumber;
908 #endif
909   return 0;
913 static void
914 x_icon (struct frame *f, Lisp_Object parms)
915 /* --------------------------------------------------------------------------
916    Strangely-named function to set icon position parameters in frame.
917    This is irrelevant under OS X, but might be needed under GNUstep,
918    depending on the window manager used.  Note, this is not a standard
919    frame parameter-setter; it is called directly from x-create-frame.
920    -------------------------------------------------------------------------- */
922   Lisp_Object icon_x, icon_y;
923   struct ns_display_info *dpyinfo = check_ns_display_info (Qnil);
925   f->output_data.ns->icon_top = -1;
926   f->output_data.ns->icon_left = -1;
928   /* Set the position of the icon.  */
929   icon_x = x_get_arg (dpyinfo, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
930   icon_y = x_get_arg (dpyinfo, parms, Qicon_top, 0, 0,  RES_TYPE_NUMBER);
931   if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
932     {
933       CHECK_NUMBER (icon_x);
934       CHECK_NUMBER (icon_y);
935       f->output_data.ns->icon_top = XINT (icon_y);
936       f->output_data.ns->icon_left = XINT (icon_x);
937     }
938   else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
939     error ("Both left and top icon corners of icon must be specified");
943 /* Note: see frame.c for template, also where generic functions are impl */
944 frame_parm_handler ns_frame_parm_handlers[] =
946   x_set_autoraise, /* generic OK */
947   x_set_autolower, /* generic OK */
948   x_set_background_color,
949   0, /* x_set_border_color,  may be impossible under Nextstep */
950   0, /* x_set_border_width,  may be impossible under Nextstep */
951   x_set_cursor_color,
952   x_set_cursor_type,
953   x_set_font, /* generic OK */
954   x_set_foreground_color,
955   x_set_icon_name,
956   x_set_icon_type,
957   x_set_internal_border_width, /* generic OK */
958   0, /* x_set_right_divider_width */
959   0, /* x_set_bottom_divider_width */
960   x_set_menu_bar_lines,
961   x_set_mouse_color,
962   x_explicitly_set_name,
963   x_set_scroll_bar_width, /* generic OK */
964   x_set_scroll_bar_height, /* generic OK */
965   x_set_title,
966   x_set_unsplittable, /* generic OK */
967   x_set_vertical_scroll_bars, /* generic OK */
968   x_set_horizontal_scroll_bars, /* generic OK */
969   x_set_visibility, /* generic OK */
970   x_set_tool_bar_lines,
971   0, /* x_set_scroll_bar_foreground, will ignore (not possible on NS) */
972   0, /* x_set_scroll_bar_background,  will ignore (not possible on NS) */
973   x_set_screen_gamma, /* generic OK */
974   x_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */
975   x_set_left_fringe, /* generic OK */
976   x_set_right_fringe, /* generic OK */
977   0, /* x_set_wait_for_wm, will ignore */
978   x_set_fullscreen, /* generic OK */
979   x_set_font_backend, /* generic OK */
980   x_set_alpha,
981   0, /* x_set_sticky */
982   0, /* x_set_tool_bar_position */
986 /* Handler for signals raised during x_create_frame.
987    FRAME is the frame which is partially constructed.  */
989 static void
990 unwind_create_frame (Lisp_Object frame)
992   struct frame *f = XFRAME (frame);
994   /* If frame is already dead, nothing to do.  This can happen if the
995      display is disconnected after the frame has become official, but
996      before x_create_frame removes the unwind protect.  */
997   if (!FRAME_LIVE_P (f))
998     return;
1000   /* If frame is ``official'', nothing to do.  */
1001   if (NILP (Fmemq (frame, Vframe_list)))
1002     {
1003 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
1004       struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
1005 #endif
1007       /* If the frame's image cache refcount is still the same as our
1008          private shadow variable, it means we are unwinding a frame
1009          for which we didn't yet call init_frame_faces, where the
1010          refcount is incremented.  Therefore, we increment it here, so
1011          that free_frame_faces, called in x_free_frame_resources
1012          below, will not mistakenly decrement the counter that was not
1013          incremented yet to account for this new frame.  */
1014       if (FRAME_IMAGE_CACHE (f) != NULL
1015           && FRAME_IMAGE_CACHE (f)->refcount == image_cache_refcount)
1016         FRAME_IMAGE_CACHE (f)->refcount++;
1018       x_free_frame_resources (f);
1019       free_glyphs (f);
1021 #if defined GLYPH_DEBUG && defined ENABLE_CHECKING
1022       /* Check that reference counts are indeed correct.  */
1023       eassert (dpyinfo->terminal->image_cache->refcount == image_cache_refcount);
1024 #endif
1025     }
1029  * Read geometry related parameters from preferences if not in PARMS.
1030  * Returns the union of parms and any preferences read.
1031  */
1033 static Lisp_Object
1034 get_geometry_from_preferences (struct ns_display_info *dpyinfo,
1035                                Lisp_Object parms)
1037   struct {
1038     const char *val;
1039     const char *cls;
1040     Lisp_Object tem;
1041   } r[] = {
1042     { "width",  "Width", Qwidth },
1043     { "height", "Height", Qheight },
1044     { "left", "Left", Qleft },
1045     { "top", "Top", Qtop },
1046   };
1048   int i;
1049   for (i = 0; i < ARRAYELTS (r); ++i)
1050     {
1051       if (NILP (Fassq (r[i].tem, parms)))
1052         {
1053           Lisp_Object value
1054             = x_get_arg (dpyinfo, parms, r[i].tem, r[i].val, r[i].cls,
1055                          RES_TYPE_NUMBER);
1056           if (! EQ (value, Qunbound))
1057             parms = Fcons (Fcons (r[i].tem, value), parms);
1058         }
1059     }
1061   return parms;
1064 /* ==========================================================================
1066     Lisp definitions
1068    ========================================================================== */
1070 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
1071        1, 1, 0,
1072        doc: /* Make a new Nextstep window, called a "frame" in Emacs terms.
1073 Return an Emacs frame object.
1074 PARMS is an alist of frame parameters.
1075 If the parameters specify that the frame should not have a minibuffer,
1076 and do not specify a specific minibuffer window to use,
1077 then `default-minibuffer-frame' must be a frame whose minibuffer can
1078 be shared by the new frame.
1080 This function is an internal primitive--use `make-frame' instead.  */)
1081      (Lisp_Object parms)
1083   struct frame *f;
1084   Lisp_Object frame, tem;
1085   Lisp_Object name;
1086   int minibuffer_only = 0;
1087   long window_prompting = 0;
1088   ptrdiff_t count = specpdl_ptr - specpdl;
1089   Lisp_Object display;
1090   struct ns_display_info *dpyinfo = NULL;
1091   Lisp_Object parent;
1092   struct kboard *kb;
1093   static int desc_ctr = 1;
1094   int x_width = 0, x_height = 0;
1096   /* x_get_arg modifies parms.  */
1097   parms = Fcopy_alist (parms);
1099   /* Use this general default value to start with
1100      until we know if this frame has a specified name.  */
1101   Vx_resource_name = Vinvocation_name;
1103   display = x_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_STRING);
1104   if (EQ (display, Qunbound))
1105     display = Qnil;
1106   dpyinfo = check_ns_display_info (display);
1107   kb = dpyinfo->terminal->kboard;
1109   if (!dpyinfo->terminal->name)
1110     error ("Terminal is not live, can't create new frames on it");
1112   name = x_get_arg (dpyinfo, parms, Qname, 0, 0, RES_TYPE_STRING);
1113   if (!STRINGP (name)
1114       && ! EQ (name, Qunbound)
1115       && ! NILP (name))
1116     error ("Invalid frame name--not a string or nil");
1118   if (STRINGP (name))
1119     Vx_resource_name = name;
1121   parent = x_get_arg (dpyinfo, parms, Qparent_id, 0, 0, RES_TYPE_NUMBER);
1122   if (EQ (parent, Qunbound))
1123     parent = Qnil;
1124   if (! NILP (parent))
1125     CHECK_NUMBER (parent);
1127   /* make_frame_without_minibuffer can run Lisp code and garbage collect.  */
1128   /* No need to protect DISPLAY because that's not used after passing
1129      it to make_frame_without_minibuffer.  */
1130   frame = Qnil;
1131   tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
1132                   RES_TYPE_SYMBOL);
1133   if (EQ (tem, Qnone) || NILP (tem))
1134       f = make_frame_without_minibuffer (Qnil, kb, display);
1135   else if (EQ (tem, Qonly))
1136     {
1137       f = make_minibuffer_frame ();
1138       minibuffer_only = 1;
1139     }
1140   else if (WINDOWP (tem))
1141       f = make_frame_without_minibuffer (tem, kb, display);
1142   else
1143       f = make_frame (1);
1145   XSETFRAME (frame, f);
1147   f->terminal = dpyinfo->terminal;
1149   f->output_method = output_ns;
1150   f->output_data.ns = xzalloc (sizeof *f->output_data.ns);
1152   FRAME_FONTSET (f) = -1;
1154   fset_icon_name (f, x_get_arg (dpyinfo, parms, Qicon_name,
1155                                 "iconName", "Title",
1156                                 RES_TYPE_STRING));
1157   if (! STRINGP (f->icon_name))
1158     fset_icon_name (f, Qnil);
1160   FRAME_DISPLAY_INFO (f) = dpyinfo;
1162   /* With FRAME_DISPLAY_INFO set up, this unwind-protect is safe.  */
1163   record_unwind_protect (unwind_create_frame, frame);
1165   f->output_data.ns->window_desc = desc_ctr++;
1166   if (TYPE_RANGED_INTEGERP (Window, parent))
1167     {
1168       f->output_data.ns->parent_desc = XFASTINT (parent);
1169       f->output_data.ns->explicit_parent = 1;
1170     }
1171   else
1172     {
1173       f->output_data.ns->parent_desc = FRAME_DISPLAY_INFO (f)->root_window;
1174       f->output_data.ns->explicit_parent = 0;
1175     }
1177   /* Set the name; the functions to which we pass f expect the name to
1178      be set.  */
1179   if (EQ (name, Qunbound) || NILP (name) || ! STRINGP (name))
1180     {
1181       fset_name (f, build_string ([ns_app_name UTF8String]));
1182       f->explicit_name = 0;
1183     }
1184   else
1185     {
1186       fset_name (f, name);
1187       f->explicit_name = 1;
1188       specbind (Qx_resource_name, name);
1189     }
1191   block_input ();
1193 #ifdef NS_IMPL_COCOA
1194     mac_register_font_driver (f);
1195 #else
1196     register_font_driver (&nsfont_driver, f);
1197 #endif
1199   image_cache_refcount =
1200     FRAME_IMAGE_CACHE (f) ? FRAME_IMAGE_CACHE (f)->refcount : 0;
1202   x_default_parameter (f, parms, Qfont_backend, Qnil,
1203                         "fontBackend", "FontBackend", RES_TYPE_STRING);
1205   {
1206     /* use for default font name */
1207     id font = [NSFont userFixedPitchFontOfSize: -1.0]; /* default */
1208     x_default_parameter (f, parms, Qfontsize,
1209                                     make_number (0 /*(int)[font pointSize]*/),
1210                                     "fontSize", "FontSize", RES_TYPE_NUMBER);
1211     // Remove ' Regular', not handled by backends.
1212     char *fontname = xstrdup ([[font displayName] UTF8String]);
1213     int len = strlen (fontname);
1214     if (len > 8 && strcmp (fontname + len - 8, " Regular") == 0)
1215       fontname[len-8] = '\0';
1216     x_default_parameter (f, parms, Qfont,
1217                                  build_string (fontname),
1218                                  "font", "Font", RES_TYPE_STRING);
1219     xfree (fontname);
1220   }
1221   unblock_input ();
1223   x_default_parameter (f, parms, Qborder_width, make_number (0),
1224                        "borderwidth", "BorderWidth", RES_TYPE_NUMBER);
1225   x_default_parameter (f, parms, Qinternal_border_width, make_number (2),
1226                       "internalBorderWidth", "InternalBorderWidth",
1227                       RES_TYPE_NUMBER);
1229   /* default vertical scrollbars on right on Mac */
1230   {
1231       Lisp_Object spos
1232 #ifdef NS_IMPL_GNUSTEP
1233           = Qt;
1234 #else
1235           = Qright;
1236 #endif
1237       x_default_parameter (f, parms, Qvertical_scroll_bars, spos,
1238                            "verticalScrollBars", "VerticalScrollBars",
1239                            RES_TYPE_SYMBOL);
1240   }
1241   x_default_parameter (f, parms, Qhorizontal_scroll_bars, Qnil,
1242                        "horizontalScrollBars", "HorizontalScrollBars",
1243                        RES_TYPE_SYMBOL);
1244   x_default_parameter (f, parms, Qforeground_color, build_string ("Black"),
1245                       "foreground", "Foreground", RES_TYPE_STRING);
1246   x_default_parameter (f, parms, Qbackground_color, build_string ("White"),
1247                       "background", "Background", RES_TYPE_STRING);
1248   /* FIXME: not supported yet in Nextstep */
1249   x_default_parameter (f, parms, Qline_spacing, Qnil,
1250                        "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
1251   x_default_parameter (f, parms, Qleft_fringe, Qnil,
1252                        "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
1253   x_default_parameter (f, parms, Qright_fringe, Qnil,
1254                        "rightFringe", "RightFringe", RES_TYPE_NUMBER);
1256   init_frame_faces (f);
1258   /* Read comment about this code in corresponding place in xfns.c.  */
1259   adjust_frame_size (f, FRAME_COLS (f) * FRAME_COLUMN_WIDTH (f),
1260                      FRAME_LINES (f) * FRAME_LINE_HEIGHT (f), 5, 1,
1261                      Qx_create_frame_1);
1263   /* The resources controlling the menu-bar and tool-bar are
1264      processed specially at startup, and reflected in the mode
1265      variables; ignore them here.  */
1266   x_default_parameter (f, parms, Qmenu_bar_lines,
1267                        NILP (Vmenu_bar_mode)
1268                        ? make_number (0) : make_number (1),
1269                        NULL, NULL, RES_TYPE_NUMBER);
1270   x_default_parameter (f, parms, Qtool_bar_lines,
1271                        NILP (Vtool_bar_mode)
1272                        ? make_number (0) : make_number (1),
1273                        NULL, NULL, RES_TYPE_NUMBER);
1275   x_default_parameter (f, parms, Qbuffer_predicate, Qnil, "bufferPredicate",
1276                        "BufferPredicate", RES_TYPE_SYMBOL);
1277   x_default_parameter (f, parms, Qtitle, Qnil, "title", "Title",
1278                        RES_TYPE_STRING);
1280   parms = get_geometry_from_preferences (dpyinfo, parms);
1281   window_prompting = x_figure_window_size (f, parms, true, &x_width, &x_height);
1283   tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
1284   f->no_split = minibuffer_only || (!EQ (tem, Qunbound) && !EQ (tem, Qnil));
1286   /* NOTE: on other terms, this is done in set_mouse_color, however this
1287      was not getting called under Nextstep */
1288   f->output_data.ns->text_cursor = [NSCursor IBeamCursor];
1289   f->output_data.ns->nontext_cursor = [NSCursor arrowCursor];
1290   f->output_data.ns->modeline_cursor = [NSCursor pointingHandCursor];
1291   f->output_data.ns->hand_cursor = [NSCursor pointingHandCursor];
1292   f->output_data.ns->hourglass_cursor = [NSCursor disappearingItemCursor];
1293   f->output_data.ns->horizontal_drag_cursor = [NSCursor resizeLeftRightCursor];
1294   f->output_data.ns->vertical_drag_cursor = [NSCursor resizeUpDownCursor];
1295   FRAME_DISPLAY_INFO (f)->vertical_scroll_bar_cursor
1296      = [NSCursor arrowCursor];
1297   FRAME_DISPLAY_INFO (f)->horizontal_scroll_bar_cursor
1298      = [NSCursor arrowCursor];
1299   f->output_data.ns->current_pointer = f->output_data.ns->text_cursor;
1301   [[EmacsView alloc] initFrameFromEmacs: f];
1303   x_icon (f, parms);
1305   /* ns_display_info does not have a reference_count.  */
1306   f->terminal->reference_count++;
1308   /* It is now ok to make the frame official even if we get an error below.
1309      The frame needs to be on Vframe_list or making it visible won't work. */
1310   Vframe_list = Fcons (frame, Vframe_list);
1312   x_default_parameter (f, parms, Qicon_type, Qnil,
1313                        "bitmapIcon", "BitmapIcon", RES_TYPE_SYMBOL);
1315   x_default_parameter (f, parms, Qauto_raise, Qnil,
1316                        "autoRaise", "AutoRaiseLower", RES_TYPE_BOOLEAN);
1317   x_default_parameter (f, parms, Qauto_lower, Qnil,
1318                        "autoLower", "AutoLower", RES_TYPE_BOOLEAN);
1319   x_default_parameter (f, parms, Qcursor_type, Qbox,
1320                        "cursorType", "CursorType", RES_TYPE_SYMBOL);
1321   x_default_parameter (f, parms, Qscroll_bar_width, Qnil,
1322                        "scrollBarWidth", "ScrollBarWidth",
1323                        RES_TYPE_NUMBER);
1324   x_default_parameter (f, parms, Qscroll_bar_height, Qnil,
1325                        "scrollBarHeight", "ScrollBarHeight",
1326                        RES_TYPE_NUMBER);
1327   x_default_parameter (f, parms, Qalpha, Qnil,
1328                        "alpha", "Alpha", RES_TYPE_NUMBER);
1329   x_default_parameter (f, parms, Qfullscreen, Qnil,
1330                        "fullscreen", "Fullscreen", RES_TYPE_SYMBOL);
1332   /* Allow x_set_window_size, now.  */
1333   f->can_x_set_window_size = true;
1335   if (x_width > 0)
1336     SET_FRAME_WIDTH (f, x_width);
1337   if (x_height > 0)
1338     SET_FRAME_HEIGHT (f, x_height);
1340   adjust_frame_size (f, FRAME_TEXT_WIDTH (f), FRAME_TEXT_HEIGHT (f), 0, 1,
1341                      Qx_create_frame_2);
1343   if (! f->output_data.ns->explicit_parent)
1344     {
1345       Lisp_Object visibility;
1347       visibility = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0,
1348                               RES_TYPE_SYMBOL);
1349       if (EQ (visibility, Qunbound))
1350         visibility = Qt;
1352       if (EQ (visibility, Qicon))
1353         x_iconify_frame (f);
1354       else if (! NILP (visibility))
1355         {
1356           x_make_frame_visible (f);
1357           [[FRAME_NS_VIEW (f) window] makeKeyWindow];
1358         }
1359       else
1360         {
1361           /* Must have been Qnil.  */
1362         }
1363     }
1365   if (FRAME_HAS_MINIBUF_P (f)
1366       && (!FRAMEP (KVAR (kb, Vdefault_minibuffer_frame))
1367           || !FRAME_LIVE_P (XFRAME (KVAR (kb, Vdefault_minibuffer_frame)))))
1368     kset_default_minibuffer_frame (kb, frame);
1370   /* All remaining specified parameters, which have not been "used"
1371      by x_get_arg and friends, now go in the misc. alist of the frame.  */
1372   for (tem = parms; CONSP (tem); tem = XCDR (tem))
1373     if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
1374       fset_param_alist (f, Fcons (XCAR (tem), f->param_alist));
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 #ifdef NS_IMPL_GNUSTEP
1412   nsfont = ((struct nsfont_info *)font)->nsfont;
1413 #endif
1414 #ifdef NS_IMPL_COCOA
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 #ifdef NS_IMPL_GNUSTEP
1438   NSString *dirS, *initS;
1439   BOOL no_types;
1440 #endif
1441 } ns_fd_data;
1443 void
1444 ns_run_file_dialog (void)
1446   if (ns_fd_data.panel == nil) return;
1447 #ifdef NS_IMPL_COCOA
1448   ns_fd_data.ret = [ns_fd_data.panel runModal];
1449 #else
1450   if (ns_fd_data.no_types)
1451     {
1452       ns_fd_data.ret = [ns_fd_data.panel
1453                            runModalForDirectory: ns_fd_data.dirS
1454                            file: ns_fd_data.initS];
1455     }
1456   else
1457     {
1458       ns_fd_data.ret = [ns_fd_data.panel
1459                            runModalForDirectory: ns_fd_data.dirS
1460                            file: ns_fd_data.initS
1461                            types: nil];
1462     }
1463 #endif
1464   ns_fd_data.panel = nil;
1467 #ifdef NS_IMPL_COCOA
1468 #if MAC_OS_X_VERSION_MAX_ALLOWED > MAC_OS_X_VERSION_10_9
1469 #define MODAL_OK_RESPONSE NSModalResponseOK
1470 #endif
1471 #endif
1472 #ifndef MODAL_OK_RESPONSE
1473 #define MODAL_OK_RESPONSE NSOKButton
1474 #endif
1476 DEFUN ("ns-read-file-name", Fns_read_file_name, Sns_read_file_name, 1, 5, 0,
1477        doc: /* Use a graphical panel to read a file name, using prompt PROMPT.
1478 Optional arg DIR, if non-nil, supplies a default directory.
1479 Optional arg MUSTMATCH, if non-nil, means the returned file or
1480 directory must exist.
1481 Optional arg INIT, if non-nil, provides a default file name to use.
1482 Optional arg DIR_ONLY_P, if non-nil, means choose only directories.  */)
1483   (Lisp_Object prompt, Lisp_Object dir, Lisp_Object mustmatch,
1484    Lisp_Object init, Lisp_Object dir_only_p)
1486   static id fileDelegate = nil;
1487   BOOL isSave = NILP (mustmatch) && NILP (dir_only_p);
1488   id panel;
1489   Lisp_Object fname = Qnil;
1491   NSString *promptS = NILP (prompt) || !STRINGP (prompt) ? nil :
1492     [NSString stringWithUTF8String: SSDATA (prompt)];
1493   NSString *dirS = NILP (dir) || !STRINGP (dir) ?
1494     [NSString stringWithUTF8String: SSDATA (BVAR (current_buffer, directory))] :
1495     [NSString stringWithUTF8String: SSDATA (dir)];
1496   NSString *initS = NILP (init) || !STRINGP (init) ? nil :
1497     [NSString stringWithUTF8String: SSDATA (init)];
1498   NSEvent *nxev;
1500   check_window_system (NULL);
1502   if (fileDelegate == nil)
1503     fileDelegate = [EmacsFileDelegate new];
1505   [NSCursor setHiddenUntilMouseMoves: NO];
1507   if ([dirS characterAtIndex: 0] == '~')
1508     dirS = [dirS stringByExpandingTildeInPath];
1510   panel = isSave ?
1511     (id)[EmacsSavePanel savePanel] : (id)[EmacsOpenPanel openPanel];
1513   [panel setTitle: promptS];
1515   [panel setAllowsOtherFileTypes: YES];
1516   [panel setTreatsFilePackagesAsDirectories: YES];
1517   [panel setDelegate: fileDelegate];
1519   if (! NILP (dir_only_p))
1520     {
1521       [panel setCanChooseDirectories: YES];
1522       [panel setCanChooseFiles: NO];
1523     }
1524   else if (! isSave)
1525     {
1526       /* This is not quite what the documentation says, but it is compatible
1527          with the Gtk+ code.  Also, the menu entry says "Open File...".  */
1528       [panel setCanChooseDirectories: NO];
1529       [panel setCanChooseFiles: YES];
1530     }
1532   block_input ();
1533   ns_fd_data.panel = panel;
1534   ns_fd_data.ret = NO;
1535 #ifdef NS_IMPL_COCOA
1536   if (! NILP (mustmatch) || ! NILP (dir_only_p))
1537     [panel setAllowedFileTypes: nil];
1538   if (dirS) [panel setDirectoryURL: [NSURL fileURLWithPath: dirS]];
1539   if (initS && NILP (Ffile_directory_p (init)))
1540     [panel setNameFieldStringValue: [initS lastPathComponent]];
1541   else
1542     [panel setNameFieldStringValue: @""];
1544 #else
1545   ns_fd_data.no_types = NILP (mustmatch) && NILP (dir_only_p);
1546   ns_fd_data.dirS = dirS;
1547   ns_fd_data.initS = initS;
1548 #endif
1550   /* runModalForDirectory/runModal restarts the main event loop when done,
1551      so we must start an event loop and then pop up the file dialog.
1552      The file dialog may pop up a confirm dialog after Ok has been pressed,
1553      so we can not simply pop down on the Ok/Cancel press.
1554    */
1555   nxev = [NSEvent otherEventWithType: NSApplicationDefined
1556                             location: NSMakePoint (0, 0)
1557                        modifierFlags: 0
1558                            timestamp: 0
1559                         windowNumber: [[NSApp mainWindow] windowNumber]
1560                              context: [NSApp context]
1561                              subtype: 0
1562                                data1: 0
1563                                data2: NSAPP_DATA2_RUNFILEDIALOG];
1565   [NSApp postEvent: nxev atStart: NO];
1566   while (ns_fd_data.panel != nil)
1567     [NSApp run];
1569   if (ns_fd_data.ret == MODAL_OK_RESPONSE)
1570     {
1571       NSString *str = ns_filename_from_panel (panel);
1572       if (! str) str = ns_directory_from_panel (panel);
1573       if (str) fname = build_string ([str UTF8String]);
1574     }
1576   [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
1577   unblock_input ();
1579   return fname;
1582 const char *
1583 ns_get_defaults_value (const char *key)
1585   NSObject *obj = [[NSUserDefaults standardUserDefaults]
1586                     objectForKey: [NSString stringWithUTF8String: key]];
1588   if (!obj) return NULL;
1590   return [[NSString stringWithFormat: @"%@", obj] UTF8String];
1594 DEFUN ("ns-get-resource", Fns_get_resource, Sns_get_resource, 2, 2, 0,
1595        doc: /* Return the value of the property NAME of OWNER from the defaults database.
1596 If OWNER is nil, Emacs is assumed.  */)
1597      (Lisp_Object owner, Lisp_Object name)
1599   const char *value;
1601   check_window_system (NULL);
1602   if (NILP (owner))
1603     owner = build_string([ns_app_name UTF8String]);
1604   CHECK_STRING (name);
1606   value = ns_get_defaults_value (SSDATA (name));
1608   if (value)
1609     return build_string (value);
1610   return Qnil;
1614 DEFUN ("ns-set-resource", Fns_set_resource, Sns_set_resource, 3, 3, 0,
1615        doc: /* Set property NAME of OWNER to VALUE, from the defaults database.
1616 If OWNER is nil, Emacs is assumed.
1617 If VALUE is nil, the default is removed.  */)
1618      (Lisp_Object owner, Lisp_Object name, Lisp_Object value)
1620   check_window_system (NULL);
1621   if (NILP (owner))
1622     owner = build_string ([ns_app_name UTF8String]);
1623   CHECK_STRING (name);
1624   if (NILP (value))
1625     {
1626       [[NSUserDefaults standardUserDefaults] removeObjectForKey:
1627                          [NSString stringWithUTF8String: SSDATA (name)]];
1628     }
1629   else
1630     {
1631       CHECK_STRING (value);
1632       [[NSUserDefaults standardUserDefaults] setObject:
1633                 [NSString stringWithUTF8String: SSDATA (value)]
1634                                         forKey: [NSString stringWithUTF8String:
1635                                                          SSDATA (name)]];
1636     }
1638   return Qnil;
1642 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
1643        Sx_server_max_request_size,
1644        0, 1, 0,
1645        doc: /* This function is a no-op.  It is only present for completeness.  */)
1646      (Lisp_Object terminal)
1648   check_ns_display_info (terminal);
1649   /* This function has no real equivalent under NeXTstep.  Return nil to
1650      indicate this. */
1651   return Qnil;
1655 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
1656        doc: /* Return the "vendor ID" string of Nextstep display server TERMINAL.
1657 (Labeling every distributor as a "vendor" embodies the false assumption
1658 that operating systems cannot be developed and distributed noncommercially.)
1659 The optional argument TERMINAL specifies which display to ask about.
1660 TERMINAL should be a terminal object, a frame or a display name (a string).
1661 If omitted or nil, that stands for the selected frame's display.  */)
1662   (Lisp_Object terminal)
1664   check_ns_display_info (terminal);
1665 #ifdef NS_IMPL_GNUSTEP
1666   return build_string ("GNU");
1667 #else
1668   return build_string ("Apple");
1669 #endif
1673 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
1674        doc: /* Return the version numbers of the server of display TERMINAL.
1675 The value is a list of three integers: the major and minor
1676 version numbers of the X Protocol in use, and the distributor-specific release
1677 number.  See also the function `x-server-vendor'.
1679 The optional argument TERMINAL specifies which display to ask about.
1680 TERMINAL should be a terminal object, a frame or a display name (a string).
1681 If omitted or nil, that stands for the selected frame's display.  */)
1682   (Lisp_Object terminal)
1684   check_ns_display_info (terminal);
1685   /*NOTE: it is unclear what would best correspond with "protocol";
1686           we return 10.3, meaning Panther, since this is roughly the
1687           level that GNUstep's APIs correspond to.
1688           The last number is where we distinguish between the Apple
1689           and GNUstep implementations ("distributor-specific release
1690           number") and give int'ized versions of major.minor. */
1691   return list3i (10, 3, ns_appkit_version_int ());
1695 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
1696        doc: /* Return the number of screens on Nextstep display server TERMINAL.
1697 The optional argument TERMINAL specifies which display to ask about.
1698 TERMINAL should be a terminal object, a frame or a display name (a string).
1699 If omitted or nil, that stands for the selected frame's display.
1701 Note: "screen" here is not in Nextstep terminology but in X11's.  For
1702 the number of physical monitors, use `(length
1703 (display-monitor-attributes-list TERMINAL))' instead.  */)
1704   (Lisp_Object terminal)
1706   check_ns_display_info (terminal);
1707   return make_number (1);
1711 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height, 0, 1, 0,
1712        doc: /* Return the height in millimeters of the Nextstep display TERMINAL.
1713 The optional argument TERMINAL specifies which display to ask about.
1714 TERMINAL should be a terminal object, a frame or a display name (a string).
1715 If omitted or nil, that stands for the selected frame's display.
1717 On \"multi-monitor\" setups this refers to the height in millimeters for
1718 all physical monitors associated with TERMINAL.  To get information
1719 for each physical monitor, use `display-monitor-attributes-list'.  */)
1720   (Lisp_Object terminal)
1722   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
1724   return make_number (x_display_pixel_height (dpyinfo) / (92.0/25.4));
1728 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width, 0, 1, 0,
1729        doc: /* Return the width in millimeters of the Nextstep display TERMINAL.
1730 The optional argument TERMINAL specifies which display to ask about.
1731 TERMINAL should be a terminal object, a frame or a display name (a string).
1732 If omitted or nil, that stands for the selected frame's display.
1734 On \"multi-monitor\" setups this refers to the width in millimeters for
1735 all physical monitors associated with TERMINAL.  To get information
1736 for each physical monitor, use `display-monitor-attributes-list'.  */)
1737   (Lisp_Object terminal)
1739   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
1741   return make_number (x_display_pixel_width (dpyinfo) / (92.0/25.4));
1745 DEFUN ("x-display-backing-store", Fx_display_backing_store,
1746        Sx_display_backing_store, 0, 1, 0,
1747        doc: /* Return an indication of whether the Nextstep display TERMINAL does backing store.
1748 The value may be `buffered', `retained', or `non-retained'.
1749 The optional argument TERMINAL specifies which display to ask about.
1750 TERMINAL should be a terminal object, a frame or a display name (a string).
1751 If omitted or nil, that stands for the selected frame's display.  */)
1752   (Lisp_Object terminal)
1754   check_ns_display_info (terminal);
1755   switch ([ns_get_window (terminal) backingType])
1756     {
1757     case NSBackingStoreBuffered:
1758       return intern ("buffered");
1759     case NSBackingStoreRetained:
1760       return intern ("retained");
1761     case NSBackingStoreNonretained:
1762       return intern ("non-retained");
1763     default:
1764       error ("Strange value for backingType parameter of frame");
1765     }
1766   return Qnil;  /* not reached, shut compiler up */
1770 DEFUN ("x-display-visual-class", Fx_display_visual_class,
1771        Sx_display_visual_class, 0, 1, 0,
1772        doc: /* Return the visual class of the Nextstep display TERMINAL.
1773 The value is one of the symbols `static-gray', `gray-scale',
1774 `static-color', `pseudo-color', `true-color', or `direct-color'.
1776 The optional argument TERMINAL specifies which display to ask about.
1777 TERMINAL should a terminal object, a frame or a display name (a string).
1778 If omitted or nil, that stands for the selected frame's display.  */)
1779   (Lisp_Object terminal)
1781   NSWindowDepth depth;
1783   check_ns_display_info (terminal);
1784   depth = [[[NSScreen screens] objectAtIndex:0] depth];
1786   if ( depth == NSBestDepth (NSCalibratedWhiteColorSpace, 2, 2, YES, NULL))
1787     return intern ("static-gray");
1788   else if (depth == NSBestDepth (NSCalibratedWhiteColorSpace, 8, 8, YES, NULL))
1789     return intern ("gray-scale");
1790   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 8, YES, NULL))
1791     return intern ("pseudo-color");
1792   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 4, 12, NO, NULL))
1793     return intern ("true-color");
1794   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 24, NO, NULL))
1795     return intern ("direct-color");
1796   else
1797     /* color mgmt as far as we do it is really handled by Nextstep itself anyway */
1798     return intern ("direct-color");
1802 DEFUN ("x-display-save-under", Fx_display_save_under,
1803        Sx_display_save_under, 0, 1, 0,
1804        doc: /* Return t if TERMINAL supports the save-under feature.
1805 The optional argument TERMINAL specifies which display to ask about.
1806 TERMINAL should be a terminal object, a frame or a display name (a string).
1807 If omitted or nil, that stands for the selected frame's display.  */)
1808   (Lisp_Object terminal)
1810   check_ns_display_info (terminal);
1811   switch ([ns_get_window (terminal) backingType])
1812     {
1813     case NSBackingStoreBuffered:
1814       return Qt;
1816     case NSBackingStoreRetained:
1817     case NSBackingStoreNonretained:
1818       return Qnil;
1820     default:
1821       error ("Strange value for backingType parameter of frame");
1822     }
1823   return Qnil;  /* not reached, shut compiler up */
1827 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
1828        1, 3, 0,
1829        doc: /* Open a connection to a display server.
1830 DISPLAY is the name of the display to connect to.
1831 Optional second arg XRM-STRING is a string of resources in xrdb format.
1832 If the optional third arg MUST-SUCCEED is non-nil,
1833 terminate Emacs if we can't open the connection.
1834 (In the Nextstep version, the last two arguments are currently ignored.)  */)
1835      (Lisp_Object display, Lisp_Object resource_string, Lisp_Object must_succeed)
1837   struct ns_display_info *dpyinfo;
1839   CHECK_STRING (display);
1841   nxatoms_of_nsselect ();
1842   dpyinfo = ns_term_init (display);
1843   if (dpyinfo == 0)
1844     {
1845       if (!NILP (must_succeed))
1846         fatal ("Display on %s not responding.\n",
1847                SSDATA (display));
1848       else
1849         error ("Display on %s not responding.\n",
1850                SSDATA (display));
1851     }
1853   return Qnil;
1857 DEFUN ("x-close-connection", Fx_close_connection, Sx_close_connection,
1858        1, 1, 0,
1859        doc: /* Close the connection to TERMINAL's Nextstep display server.
1860 For TERMINAL, specify a terminal object, a frame or a display name (a
1861 string).  If TERMINAL is nil, that stands for the selected frame's
1862 terminal.  */)
1863      (Lisp_Object terminal)
1865   check_ns_display_info (terminal);
1866   [NSApp terminate: NSApp];
1867   return Qnil;
1871 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
1872        doc: /* Return the list of display names that Emacs has connections to.  */)
1873      (void)
1875   Lisp_Object result = Qnil;
1876   struct ns_display_info *ndi;
1878   for (ndi = x_display_list; ndi; ndi = ndi->next)
1879     result = Fcons (XCAR (ndi->name_list_element), result);
1881   return result;
1885 DEFUN ("ns-hide-others", Fns_hide_others, Sns_hide_others,
1886        0, 0, 0,
1887        doc: /* Hides all applications other than Emacs.  */)
1888      (void)
1890   check_window_system (NULL);
1891   [NSApp hideOtherApplications: NSApp];
1892   return Qnil;
1895 DEFUN ("ns-hide-emacs", Fns_hide_emacs, Sns_hide_emacs,
1896        1, 1, 0,
1897        doc: /* If ON is non-nil, the entire Emacs application is hidden.
1898 Otherwise if Emacs is hidden, it is unhidden.
1899 If ON is equal to `activate', Emacs is unhidden and becomes
1900 the active application.  */)
1901      (Lisp_Object on)
1903   check_window_system (NULL);
1904   if (EQ (on, intern ("activate")))
1905     {
1906       [NSApp unhide: NSApp];
1907       [NSApp activateIgnoringOtherApps: YES];
1908     }
1909   else if (NILP (on))
1910     [NSApp unhide: NSApp];
1911   else
1912     [NSApp hide: NSApp];
1913   return Qnil;
1917 DEFUN ("ns-emacs-info-panel", Fns_emacs_info_panel, Sns_emacs_info_panel,
1918        0, 0, 0,
1919        doc: /* Shows the 'Info' or 'About' panel for Emacs.  */)
1920      (void)
1922   check_window_system (NULL);
1923   [NSApp orderFrontStandardAboutPanel: nil];
1924   return Qnil;
1928 DEFUN ("ns-font-name", Fns_font_name, Sns_font_name, 1, 1, 0,
1929        doc: /* Determine font PostScript or family name for font NAME.
1930 NAME should be a string containing either the font name or an XLFD
1931 font descriptor.  If string contains `fontset' and not
1932 `fontset-startup', it is left alone. */)
1933      (Lisp_Object name)
1935   char *nm;
1936   CHECK_STRING (name);
1937   nm = SSDATA (name);
1939   if (nm[0] != '-')
1940     return name;
1941   if (strstr (nm, "fontset") && !strstr (nm, "fontset-startup"))
1942     return name;
1944   return build_string (ns_xlfd_to_fontname (SSDATA (name)));
1948 DEFUN ("ns-list-colors", Fns_list_colors, Sns_list_colors, 0, 1, 0,
1949        doc: /* Return a list of all available colors.
1950 The optional argument FRAME is currently ignored.  */)
1951      (Lisp_Object frame)
1953   Lisp_Object list = Qnil;
1954   NSEnumerator *colorlists;
1955   NSColorList *clist;
1957   if (!NILP (frame))
1958     {
1959       CHECK_FRAME (frame);
1960       if (! FRAME_NS_P (XFRAME (frame)))
1961         error ("non-Nextstep frame used in `ns-list-colors'");
1962     }
1964   block_input ();
1966   colorlists = [[NSColorList availableColorLists] objectEnumerator];
1967   while ((clist = [colorlists nextObject]))
1968     {
1969       if ([[clist name] length] < 7 ||
1970           [[clist name] rangeOfString: @"PANTONE"].location == 0)
1971         {
1972           NSEnumerator *cnames = [[clist allKeys] reverseObjectEnumerator];
1973           NSString *cname;
1974           while ((cname = [cnames nextObject]))
1975             list = Fcons (build_string ([cname UTF8String]), list);
1976 /*           for (i = [[clist allKeys] count] - 1; i >= 0; i--)
1977                list = Fcons (build_string ([[[clist allKeys] objectAtIndex: i]
1978                                              UTF8String]), list); */
1979         }
1980     }
1982   unblock_input ();
1984   return list;
1988 DEFUN ("ns-list-services", Fns_list_services, Sns_list_services, 0, 0, 0,
1989        doc: /* List available Nextstep services by querying NSApp.  */)
1990      (void)
1992 #ifdef NS_IMPL_COCOA
1993   /* You can't get services like this in 10.6+.  */
1994   return Qnil;
1995 #else
1996   Lisp_Object ret = Qnil;
1997   NSMenu *svcs;
1998 #ifdef NS_IMPL_COCOA
1999   id delegate;
2000 #endif
2002   check_window_system (NULL);
2003   svcs = [[NSMenu alloc] initWithTitle: @"Services"];
2004   [NSApp setServicesMenu: svcs];
2005   [NSApp registerServicesMenuSendTypes: ns_send_types
2006                            returnTypes: ns_return_types];
2008 /* On Tiger, services menu updating was made lazier (waits for user to
2009    actually click on the menu), so we have to force things along: */
2010 #ifdef NS_IMPL_COCOA
2011   delegate = [svcs delegate];
2012   if (delegate != nil)
2013     {
2014       if ([delegate respondsToSelector: @selector (menuNeedsUpdate:)])
2015         [delegate menuNeedsUpdate: svcs];
2016       if ([delegate respondsToSelector:
2017                        @selector (menu:updateItem:atIndex:shouldCancel:)])
2018         {
2019           int i, len = [delegate numberOfItemsInMenu: svcs];
2020           for (i =0; i<len; i++)
2021             [svcs addItemWithTitle: @"" action: NULL keyEquivalent: @""];
2022           for (i =0; i<len; i++)
2023             if (![delegate menu: svcs
2024                      updateItem: (NSMenuItem *)[svcs itemAtIndex: i]
2025                         atIndex: i shouldCancel: NO])
2026               break;
2027         }
2028     }
2029 #endif
2031   [svcs setAutoenablesItems: NO];
2032 #ifdef NS_IMPL_COCOA
2033   [svcs update]; /* on OS X, converts from '/' structure */
2034 #endif
2036   ret = interpret_services_menu (svcs, Qnil, ret);
2037   return ret;
2038 #endif
2042 DEFUN ("ns-perform-service", Fns_perform_service, Sns_perform_service,
2043        2, 2, 0,
2044        doc: /* Perform Nextstep SERVICE on SEND.
2045 SEND should be either a string or nil.
2046 The return value is the result of the service, as string, or nil if
2047 there was no result.  */)
2048      (Lisp_Object service, Lisp_Object send)
2050   id pb;
2051   NSString *svcName;
2052   char *utfStr;
2054   CHECK_STRING (service);
2055   check_window_system (NULL);
2057   utfStr = SSDATA (service);
2058   svcName = [NSString stringWithUTF8String: utfStr];
2060   pb =[NSPasteboard pasteboardWithUniqueName];
2061   ns_string_to_pasteboard (pb, send);
2063   if (NSPerformService (svcName, pb) == NO)
2064     Fsignal (Qquit, list1 (build_string ("service not available")));
2066   if ([[pb types] count] == 0)
2067     return build_string ("");
2068   return ns_string_from_pasteboard (pb);
2072 DEFUN ("ns-convert-utf8-nfd-to-nfc", Fns_convert_utf8_nfd_to_nfc,
2073        Sns_convert_utf8_nfd_to_nfc, 1, 1, 0,
2074        doc: /* Return an NFC string that matches the UTF-8 NFD string STR.  */)
2075      (Lisp_Object str)
2077 /* TODO: If GNUstep ever implements precomposedStringWithCanonicalMapping,
2078          remove this. */
2079   NSString *utfStr;
2080   Lisp_Object ret = Qnil;
2081   NSAutoreleasePool *pool;
2083   CHECK_STRING (str);
2084   pool = [[NSAutoreleasePool alloc] init];
2085   utfStr = [NSString stringWithUTF8String: SSDATA (str)];
2086 #ifdef NS_IMPL_COCOA
2087   if (utfStr)
2088     utfStr = [utfStr precomposedStringWithCanonicalMapping];
2089 #endif
2090   if (utfStr)
2091     {
2092       const char *cstr = [utfStr UTF8String];
2093       if (cstr)
2094         ret = build_string (cstr);
2095     }
2097   [pool release];
2098   if (NILP (ret))
2099     error ("Invalid UTF-8");
2101   return ret;
2105 #ifdef NS_IMPL_COCOA
2107 /* Compile and execute the AppleScript SCRIPT and return the error
2108    status as function value.  A zero is returned if compilation and
2109    execution is successful, in which case *RESULT is set to a Lisp
2110    string or a number containing the resulting script value.  Otherwise,
2111    1 is returned. */
2112 static int
2113 ns_do_applescript (Lisp_Object script, Lisp_Object *result)
2115   NSAppleEventDescriptor *desc;
2116   NSDictionary* errorDict;
2117   NSAppleEventDescriptor* returnDescriptor = NULL;
2119   NSAppleScript* scriptObject =
2120     [[NSAppleScript alloc] initWithSource:
2121                              [NSString stringWithUTF8String: SSDATA (script)]];
2123   returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
2124   [scriptObject release];
2125   *result = Qnil;
2127   if (returnDescriptor != NULL)
2128     {
2129       // successful execution
2130       if (kAENullEvent != [returnDescriptor descriptorType])
2131         {
2132           *result = Qt;
2133           // script returned an AppleScript result
2134           if ((typeUnicodeText == [returnDescriptor descriptorType]) ||
2135 #if defined (NS_IMPL_COCOA)
2136               (typeUTF16ExternalRepresentation
2137                == [returnDescriptor descriptorType]) ||
2138 #endif
2139               (typeUTF8Text == [returnDescriptor descriptorType]) ||
2140               (typeCString == [returnDescriptor descriptorType]))
2141             {
2142               desc = [returnDescriptor coerceToDescriptorType: typeUTF8Text];
2143               if (desc)
2144                 *result = build_string([[desc stringValue] UTF8String]);
2145             }
2146           else
2147             {
2148               /* use typeUTF16ExternalRepresentation? */
2149               // coerce the result to the appropriate ObjC type
2150               desc = [returnDescriptor coerceToDescriptorType: typeUTF8Text];
2151               if (desc)
2152                 *result = make_number([desc int32Value]);
2153             }
2154         }
2155     }
2156   else
2157     {
2158       // no script result, return error
2159       return 1;
2160     }
2161   return 0;
2164 /* Helper function called from sendEvent to run applescript
2165    from within the main event loop.  */
2167 void
2168 ns_run_ascript (void)
2170   if (! NILP (as_script))
2171     as_status = ns_do_applescript (as_script, as_result);
2172   as_script = Qnil;
2175 DEFUN ("ns-do-applescript", Fns_do_applescript, Sns_do_applescript, 1, 1, 0,
2176        doc: /* Execute AppleScript SCRIPT and return the result.
2177 If compilation and execution are successful, the resulting script value
2178 is returned as a string, a number or, in the case of other constructs, t.
2179 In case the execution fails, an error is signaled. */)
2180      (Lisp_Object script)
2182   Lisp_Object result;
2183   int status;
2184   NSEvent *nxev;
2185   struct input_event ev;
2187   CHECK_STRING (script);
2188   check_window_system (NULL);
2190   block_input ();
2192   as_script = script;
2193   as_result = &result;
2195   /* executing apple script requires the event loop to run, otherwise
2196      errors aren't returned and executeAndReturnError hangs forever.
2197      Post an event that runs applescript and then start the event loop.
2198      The event loop is exited when the script is done.  */
2199   nxev = [NSEvent otherEventWithType: NSApplicationDefined
2200                             location: NSMakePoint (0, 0)
2201                        modifierFlags: 0
2202                            timestamp: 0
2203                         windowNumber: [[NSApp mainWindow] windowNumber]
2204                              context: [NSApp context]
2205                              subtype: 0
2206                                data1: 0
2207                                data2: NSAPP_DATA2_RUNASSCRIPT];
2209   [NSApp postEvent: nxev atStart: NO];
2211   // If there are other events, the event loop may exit.  Keep running
2212   // until the script has been handled.  */
2213   ns_init_events (&ev);
2214   while (! NILP (as_script))
2215     [NSApp run];
2216   ns_finish_events ();
2218   status = as_status;
2219   as_status = 0;
2220   as_result = 0;
2221   unblock_input ();
2222   if (status == 0)
2223     return result;
2224   else if (!STRINGP (result))
2225     error ("AppleScript error %d", status);
2226   else
2227     error ("%s", SSDATA (result));
2229 #endif
2233 /* ==========================================================================
2235     Miscellaneous functions not called through hooks
2237    ========================================================================== */
2239 /* called from frame.c */
2240 struct ns_display_info *
2241 check_x_display_info (Lisp_Object frame)
2243   return check_ns_display_info (frame);
2247 void
2248 x_set_scroll_bar_default_width (struct frame *f)
2250   int wid = FRAME_COLUMN_WIDTH (f);
2251   FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = NS_SCROLL_BAR_WIDTH_DEFAULT;
2252   FRAME_CONFIG_SCROLL_BAR_COLS (f) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) +
2253                                       wid - 1) / wid;
2256 void
2257 x_set_scroll_bar_default_height (struct frame *f)
2259   int height = FRAME_LINE_HEIGHT (f);
2260   FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) = NS_SCROLL_BAR_WIDTH_DEFAULT;
2261   FRAME_CONFIG_SCROLL_BAR_LINES (f) = (FRAME_CONFIG_SCROLL_BAR_HEIGHT (f) +
2262                                        height - 1) / height;
2265 /* terms impl this instead of x-get-resource directly */
2266 char *
2267 x_get_string_resource (XrmDatabase rdb, const char *name, const char *class)
2269   /* remove appname prefix; TODO: allow for !="Emacs" */
2270   const char *res, *toCheck = class + (!strncmp (class, "Emacs.", 6) ? 6 : 0);
2272   check_window_system (NULL);
2274   if (inhibit_x_resources)
2275     /* --quick was passed, so this is a no-op.  */
2276     return NULL;
2278   res = ns_get_defaults_value (toCheck);
2279   return (!res ? NULL :
2280           (!c_strncasecmp (res, "YES", 3) ? "true" :
2281            (!c_strncasecmp (res, "NO", 2) ? "false" : (char *) res)));
2285 Lisp_Object
2286 x_get_focus_frame (struct frame *frame)
2288   struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (frame);
2289   Lisp_Object nsfocus;
2291   if (!dpyinfo->x_focus_frame)
2292     return Qnil;
2294   XSETFRAME (nsfocus, dpyinfo->x_focus_frame);
2295   return nsfocus;
2298 /* ==========================================================================
2300     Lisp definitions that, for whatever reason, we can't alias as 'ns-XXX'.
2302    ========================================================================== */
2305 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
2306        doc: /* Internal function called by `color-defined-p', which see.
2307 (Note that the Nextstep version of this function ignores FRAME.)  */)
2308      (Lisp_Object color, Lisp_Object frame)
2310   NSColor * col;
2311   check_window_system (NULL);
2312   return ns_lisp_to_color (color, &col) ? Qnil : Qt;
2316 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
2317        doc: /* Internal function called by `color-values', which see.  */)
2318      (Lisp_Object color, Lisp_Object frame)
2320   NSColor * col;
2321   EmacsCGFloat red, green, blue, alpha;
2323   check_window_system (NULL);
2324   CHECK_STRING (color);
2326   block_input ();
2327   if (ns_lisp_to_color (color, &col))
2328     {
2329       unblock_input ();
2330       return Qnil;
2331     }
2333   [[col colorUsingDefaultColorSpace]
2334         getRed: &red green: &green blue: &blue alpha: &alpha];
2335   unblock_input ();
2336   return list3i (lrint (red * 65280), lrint (green * 65280),
2337                  lrint (blue * 65280));
2341 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
2342        doc: /* Internal function called by `display-color-p', which see.  */)
2343      (Lisp_Object terminal)
2345   NSWindowDepth depth;
2346   NSString *colorSpace;
2348   check_ns_display_info (terminal);
2349   depth = [[[NSScreen screens] objectAtIndex:0] depth];
2350   colorSpace = NSColorSpaceFromDepth (depth);
2352   return    [colorSpace isEqualToString: NSDeviceWhiteColorSpace]
2353          || [colorSpace isEqualToString: NSCalibratedWhiteColorSpace]
2354       ? Qnil : Qt;
2358 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p, Sx_display_grayscale_p,
2359        0, 1, 0,
2360        doc: /* Return t if the Nextstep display supports shades of gray.
2361 Note that color displays do support shades of gray.
2362 The optional argument TERMINAL specifies which display to ask about.
2363 TERMINAL should be a terminal object, a frame or a display name (a string).
2364 If omitted or nil, that stands for the selected frame's display.  */)
2365   (Lisp_Object terminal)
2367   NSWindowDepth depth;
2369   check_ns_display_info (terminal);
2370   depth = [[[NSScreen screens] objectAtIndex:0] depth];
2372   return NSBitsPerPixelFromDepth (depth) > 1 ? Qt : Qnil;
2376 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
2377        0, 1, 0,
2378        doc: /* Return the width in pixels of the Nextstep display TERMINAL.
2379 The optional argument TERMINAL specifies which display to ask about.
2380 TERMINAL should be a terminal object, a frame or a display name (a string).
2381 If omitted or nil, that stands for the selected frame's display.
2383 On \"multi-monitor\" setups this refers to the pixel width for all
2384 physical monitors associated with TERMINAL.  To get information for
2385 each physical monitor, use `display-monitor-attributes-list'.  */)
2386   (Lisp_Object terminal)
2388   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
2390   return make_number (x_display_pixel_width (dpyinfo));
2394 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
2395        Sx_display_pixel_height, 0, 1, 0,
2396        doc: /* Return the height in pixels of the Nextstep display TERMINAL.
2397 The optional argument TERMINAL specifies which display to ask about.
2398 TERMINAL should be a terminal object, a frame or a display name (a string).
2399 If omitted or nil, that stands for the selected frame's display.
2401 On \"multi-monitor\" setups this refers to the pixel height for all
2402 physical monitors associated with TERMINAL.  To get information for
2403 each physical monitor, use `display-monitor-attributes-list'.  */)
2404   (Lisp_Object terminal)
2406   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
2408   return make_number (x_display_pixel_height (dpyinfo));
2411 #ifdef NS_IMPL_COCOA
2413 /* Returns the name for the screen that OBJ represents, or NULL.
2414    Caller must free return value.
2417 static char *
2418 ns_get_name_from_ioreg (io_object_t obj)
2420   char *name = NULL;
2422   NSDictionary *info = (NSDictionary *)
2423     IODisplayCreateInfoDictionary (obj, kIODisplayOnlyPreferredName);
2424   NSDictionary *names = [info objectForKey:
2425                                 [NSString stringWithUTF8String:
2426                                             kDisplayProductName]];
2428   if ([names count] > 0)
2429     {
2430       NSString *n = [names objectForKey: [[names allKeys]
2431                                                  objectAtIndex:0]];
2432       if (n != nil) name = xstrdup ([n UTF8String]);
2433     }
2435   [info release];
2437   return name;
2440 /* Returns the name for the screen that DID came from, or NULL.
2441    Caller must free return value.
2444 static char *
2445 ns_screen_name (CGDirectDisplayID did)
2447   char *name = NULL;
2449 #if MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_9
2450   mach_port_t masterPort;
2451   io_iterator_t it;
2452   io_object_t obj;
2454   // CGDisplayIOServicePort is deprecated.  Do it another (harder) way.
2456   if (IOMasterPort (MACH_PORT_NULL, &masterPort) != kIOReturnSuccess
2457       || IOServiceGetMatchingServices (masterPort,
2458                                        IOServiceMatching ("IONDRVDevice"),
2459                                        &it) != kIOReturnSuccess)
2460     return name;
2462   /* Must loop until we find a name.  Many devices can have the same unit
2463      number (represents different GPU parts), but only one has a name.  */
2464   while (! name && (obj = IOIteratorNext (it)))
2465     {
2466       CFMutableDictionaryRef props;
2467       const void *val;
2469       if (IORegistryEntryCreateCFProperties (obj,
2470                                              &props,
2471                                              kCFAllocatorDefault,
2472                                              kNilOptions) == kIOReturnSuccess
2473           && props != nil
2474           && (val = CFDictionaryGetValue(props, @"IOFBDependentIndex")))
2475         {
2476           unsigned nr = [(NSNumber *)val unsignedIntegerValue];
2477           if (nr == CGDisplayUnitNumber (did))
2478             name = ns_get_name_from_ioreg (obj);
2479         }
2481       CFRelease (props);
2482       IOObjectRelease (obj);
2483     }
2485   IOObjectRelease (it);
2487 #else
2489   name = ns_get_name_from_ioreg (CGDisplayIOServicePort (did));
2491 #endif
2492   return name;
2494 #endif
2496 static Lisp_Object
2497 ns_make_monitor_attribute_list (struct MonitorInfo *monitors,
2498                                 int n_monitors,
2499                                 int primary_monitor,
2500                                 const char *source)
2502   Lisp_Object monitor_frames = Fmake_vector (make_number (n_monitors), Qnil);
2503   Lisp_Object frame, rest;
2504   NSArray *screens = [NSScreen screens];
2505   int i;
2507   FOR_EACH_FRAME (rest, frame)
2508     {
2509       struct frame *f = XFRAME (frame);
2511       if (FRAME_NS_P (f))
2512         {
2513           NSView *view = FRAME_NS_VIEW (f);
2514           NSScreen *screen = [[view window] screen];
2515           NSUInteger k;
2517           i = -1;
2518           for (k = 0; i == -1 && k < [screens count]; ++k)
2519             {
2520               if ([screens objectAtIndex: k] == screen)
2521                 i = (int)k;
2522             }
2524           if (i > -1)
2525             ASET (monitor_frames, i, Fcons (frame, AREF (monitor_frames, i)));
2526         }
2527     }
2529   return make_monitor_attribute_list (monitors, n_monitors, primary_monitor,
2530                                       monitor_frames, source);
2533 DEFUN ("ns-display-monitor-attributes-list",
2534        Fns_display_monitor_attributes_list,
2535        Sns_display_monitor_attributes_list,
2536        0, 1, 0,
2537        doc: /* Return a list of physical monitor attributes on the X display TERMINAL.
2539 The optional argument TERMINAL specifies which display to ask about.
2540 TERMINAL should be a terminal object, a frame or a display name (a string).
2541 If omitted or nil, that stands for the selected frame's display.
2543 In addition to the standard attribute keys listed in
2544 `display-monitor-attributes-list', the following keys are contained in
2545 the attributes:
2547  source -- String describing the source from which multi-monitor
2548            information is obtained, \"NS\" is always the source."
2550 Internal use only, use `display-monitor-attributes-list' instead.  */)
2551   (Lisp_Object terminal)
2553   struct terminal *term = decode_live_terminal (terminal);
2554   NSArray *screens;
2555   NSUInteger i, n_monitors;
2556   struct MonitorInfo *monitors;
2557   Lisp_Object attributes_list = Qnil;
2558   CGFloat primary_display_height = 0;
2560   if (term->type != output_ns)
2561     return Qnil;
2563   screens = [NSScreen screens];
2564   n_monitors = [screens count];
2565   if (n_monitors == 0)
2566     return Qnil;
2568   monitors = xzalloc (n_monitors * sizeof *monitors);
2570   for (i = 0; i < [screens count]; ++i)
2571     {
2572       NSScreen *s = [screens objectAtIndex:i];
2573       struct MonitorInfo *m = &monitors[i];
2574       NSRect fr = [s frame];
2575       NSRect vfr = [s visibleFrame];
2576       short y, vy;
2578 #ifdef NS_IMPL_COCOA
2579       NSDictionary *dict = [s deviceDescription];
2580       NSNumber *nid = [dict objectForKey:@"NSScreenNumber"];
2581       CGDirectDisplayID did = [nid unsignedIntValue];
2582 #endif
2583       if (i == 0)
2584         {
2585           primary_display_height = fr.size.height;
2586           y = (short) fr.origin.y;
2587           vy = (short) vfr.origin.y;
2588         }
2589       else
2590         {
2591           // Flip y coordinate as NS has y starting from the bottom.
2592           y = (short) (primary_display_height - fr.size.height - fr.origin.y);
2593           vy = (short) (primary_display_height -
2594                         vfr.size.height - vfr.origin.y);
2595         }
2597       m->geom.x = (short) fr.origin.x;
2598       m->geom.y = y;
2599       m->geom.width = (unsigned short) fr.size.width;
2600       m->geom.height = (unsigned short) fr.size.height;
2602       m->work.x = (short) vfr.origin.x;
2603       // y is flipped on NS, so vy - y are pixels missing at the bottom,
2604       // and fr.size.height - vfr.size.height are pixels missing in total.
2605       // Pixels missing at top are
2606       // fr.size.height - vfr.size.height - vy + y.
2607       // work.y is then pixels missing at top + y.
2608       m->work.y = (short) (fr.size.height - vfr.size.height) - vy + y + y;
2609       m->work.width = (unsigned short) vfr.size.width;
2610       m->work.height = (unsigned short) vfr.size.height;
2612 #ifdef NS_IMPL_COCOA
2613       m->name = ns_screen_name (did);
2615       {
2616         CGSize mms = CGDisplayScreenSize (did);
2617         m->mm_width = (int) mms.width;
2618         m->mm_height = (int) mms.height;
2619       }
2621 #else
2622       // Assume 92 dpi as x-display-mm-height/x-display-mm-width does.
2623       m->mm_width = (int) (25.4 * fr.size.width / 92.0);
2624       m->mm_height = (int) (25.4 * fr.size.height / 92.0);
2625 #endif
2626     }
2628   // Primary monitor is always first for NS.
2629   attributes_list = ns_make_monitor_attribute_list (monitors, n_monitors,
2630                                                     0, "NS");
2632   free_monitors (monitors, n_monitors);
2633   return attributes_list;
2637 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
2638        0, 1, 0,
2639        doc: /* Return the number of bitplanes of the Nextstep display TERMINAL.
2640 The optional argument TERMINAL specifies which display to ask about.
2641 TERMINAL should be a terminal object, a frame or a display name (a string).
2642 If omitted or nil, that stands for the selected frame's display.  */)
2643   (Lisp_Object terminal)
2645   check_ns_display_info (terminal);
2646   return make_number
2647     (NSBitsPerPixelFromDepth ([[[NSScreen screens] objectAtIndex:0] depth]));
2651 DEFUN ("x-display-color-cells", Fx_display_color_cells, Sx_display_color_cells,
2652        0, 1, 0,
2653        doc: /* Returns the number of color cells of the Nextstep display TERMINAL.
2654 The optional argument TERMINAL specifies which display to ask about.
2655 TERMINAL should be a terminal object, a frame or a display name (a string).
2656 If omitted or nil, that stands for the selected frame's display.  */)
2657   (Lisp_Object terminal)
2659   struct ns_display_info *dpyinfo = check_ns_display_info (terminal);
2660   /* We force 24+ bit depths to 24-bit to prevent an overflow.  */
2661   return make_number (1 << min (dpyinfo->n_planes, 24));
2665 /* Unused dummy def needed for compatibility. */
2666 Lisp_Object tip_frame;
2668 /* TODO: move to xdisp or similar */
2669 static void
2670 compute_tip_xy (struct frame *f,
2671                 Lisp_Object parms,
2672                 Lisp_Object dx,
2673                 Lisp_Object dy,
2674                 int width,
2675                 int height,
2676                 int *root_x,
2677                 int *root_y)
2679   Lisp_Object left, top, right, bottom;
2680   EmacsView *view = FRAME_NS_VIEW (f);
2681   struct ns_display_info *dpyinfo = FRAME_DISPLAY_INFO (f);
2682   NSPoint pt;
2684   /* Start with user-specified or mouse position.  */
2685   left = Fcdr (Fassq (Qleft, parms));
2686   top = Fcdr (Fassq (Qtop, parms));
2687   right = Fcdr (Fassq (Qright, parms));
2688   bottom = Fcdr (Fassq (Qbottom, parms));
2690   if ((!INTEGERP (left) && !INTEGERP (right))
2691       || (!INTEGERP (top) && !INTEGERP (bottom)))
2692     {
2693       pt.x = dpyinfo->last_mouse_motion_x;
2694       pt.y = dpyinfo->last_mouse_motion_y;
2695       /* Convert to screen coordinates */
2696       pt = [view convertPoint: pt toView: nil];
2697 #if !defined (NS_IMPL_COCOA) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7
2698       pt = [[view window] convertBaseToScreen: pt];
2699 #else
2700       {
2701         NSRect r = NSMakeRect (pt.x, pt.y, 0, 0);
2702         r = [[view window] convertRectToScreen: r];
2703         pt.x = r.origin.x;
2704         pt.y = r.origin.y;
2705       }
2706 #endif
2707     }
2708   else
2709     {
2710       /* Absolute coordinates.  */
2711       pt.x = INTEGERP (left) ? XINT (left) : XINT (right);
2712       pt.y = (x_display_pixel_height (FRAME_DISPLAY_INFO (f))
2713               - (INTEGERP (top) ? XINT (top) : XINT (bottom))
2714               - height);
2715     }
2717   /* Ensure in bounds.  (Note, screen origin = lower left.) */
2718   if (INTEGERP (left) || INTEGERP (right))
2719     *root_x = pt.x;
2720   else if (pt.x + XINT (dx) <= 0)
2721     *root_x = 0; /* Can happen for negative dx */
2722   else if (pt.x + XINT (dx) + width
2723            <= x_display_pixel_width (FRAME_DISPLAY_INFO (f)))
2724     /* It fits to the right of the pointer.  */
2725     *root_x = pt.x + XINT (dx);
2726   else if (width + XINT (dx) <= pt.x)
2727     /* It fits to the left of the pointer.  */
2728     *root_x = pt.x - width - XINT (dx);
2729   else
2730     /* Put it left justified on the screen -- it ought to fit that way.  */
2731     *root_x = 0;
2733   if (INTEGERP (top) || INTEGERP (bottom))
2734     *root_y = pt.y;
2735   else if (pt.y - XINT (dy) - height >= 0)
2736     /* It fits below the pointer.  */
2737     *root_y = pt.y - height - XINT (dy);
2738   else if (pt.y + XINT (dy) + height
2739            <= x_display_pixel_height (FRAME_DISPLAY_INFO (f)))
2740     /* It fits above the pointer */
2741       *root_y = pt.y + XINT (dy);
2742   else
2743     /* Put it on the top.  */
2744     *root_y = x_display_pixel_height (FRAME_DISPLAY_INFO (f)) - height;
2748 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
2749        doc: /* Show STRING in a \"tooltip\" window on frame FRAME.
2750 A tooltip window is a small window displaying a string.
2752 This is an internal function; Lisp code should call `tooltip-show'.
2754 FRAME nil or omitted means use the selected frame.
2756 PARMS is an optional list of frame parameters which can be used to
2757 change the tooltip's appearance.
2759 Automatically hide the tooltip after TIMEOUT seconds.  TIMEOUT nil
2760 means use the default timeout of 5 seconds.
2762 If the list of frame parameters PARMS contains a `left' parameter,
2763 display the tooltip at that x-position.  If the list of frame parameters
2764 PARMS contains no `left' but a `right' parameter, display the tooltip
2765 right-adjusted at that x-position. Otherwise display it at the
2766 x-position of the mouse, with offset DX added (default is 5 if DX isn't
2767 specified).
2769 Likewise for the y-position: If a `top' frame parameter is specified, it
2770 determines the position of the upper edge of the tooltip window.  If a
2771 `bottom' parameter but no `top' frame parameter is specified, it
2772 determines the position of the lower edge of the tooltip window.
2773 Otherwise display the tooltip window at the y-position of the mouse,
2774 with offset DY added (default is -10).
2776 A tooltip's maximum size is specified by `x-max-tooltip-size'.
2777 Text larger than the specified size is clipped.  */)
2778      (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
2780   int root_x, root_y;
2781   ptrdiff_t count = SPECPDL_INDEX ();
2782   struct frame *f;
2783   char *str;
2784   NSSize size;
2786   specbind (Qinhibit_redisplay, Qt);
2788   CHECK_STRING (string);
2789   str = SSDATA (string);
2790   f = decode_window_system_frame (frame);
2791   if (NILP (timeout))
2792     timeout = make_number (5);
2793   else
2794     CHECK_NATNUM (timeout);
2796   if (NILP (dx))
2797     dx = make_number (5);
2798   else
2799     CHECK_NUMBER (dx);
2801   if (NILP (dy))
2802     dy = make_number (-10);
2803   else
2804     CHECK_NUMBER (dy);
2806   block_input ();
2807   if (ns_tooltip == nil)
2808     ns_tooltip = [[EmacsTooltip alloc] init];
2809   else
2810     Fx_hide_tip ();
2812   [ns_tooltip setText: str];
2813   size = [ns_tooltip frame].size;
2815   /* Move the tooltip window where the mouse pointer is.  Resize and
2816      show it.  */
2817   compute_tip_xy (f, parms, dx, dy, (int)size.width, (int)size.height,
2818                   &root_x, &root_y);
2820   [ns_tooltip showAtX: root_x Y: root_y for: XINT (timeout)];
2821   unblock_input ();
2823   return unbind_to (count, Qnil);
2827 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
2828        doc: /* Hide the current tooltip window, if there is any.
2829 Value is t if tooltip was open, nil otherwise.  */)
2830      (void)
2832   if (ns_tooltip == nil || ![ns_tooltip isActive])
2833     return Qnil;
2834   [ns_tooltip hide];
2835   return Qt;
2838 /* Return geometric attributes of FRAME.  According to the value of
2839    ATTRIBUTES return the outer edges of FRAME (Qouter_edges), the inner
2840    edges of FRAME, the root window edges of frame (Qroot_edges).  Any
2841    other value means to return the geometry as returned by
2842    Fx_frame_geometry.  */
2843 static Lisp_Object
2844 frame_geometry (Lisp_Object frame, Lisp_Object attribute)
2846   struct frame *f = decode_live_frame (frame);
2847   Lisp_Object fullscreen_symbol = Fframe_parameter (frame, Qfullscreen);
2848   bool fullscreen = (EQ (fullscreen_symbol, Qfullboth)
2849                      || EQ (fullscreen_symbol, Qfullscreen));
2850   int border = fullscreen ? 0 : f->border_width;
2851   int title_height = fullscreen ? 0 : FRAME_NS_TITLEBAR_HEIGHT (f);
2852   int native_width = FRAME_PIXEL_WIDTH (f);
2853   int native_height = FRAME_PIXEL_HEIGHT (f);
2854   int outer_width = native_width + 2 * border;
2855   int outer_height = native_height + 2 * border + title_height;
2856   int native_left = f->left_pos + border;
2857   int native_top = f->top_pos + border + title_height;
2858   int native_right = f->left_pos + outer_width - border;
2859   int native_bottom = f->top_pos + outer_height - border;
2860   int internal_border_width = FRAME_INTERNAL_BORDER_WIDTH (f);
2861   int tool_bar_height = FRAME_TOOLBAR_HEIGHT (f);
2862   int tool_bar_width = (tool_bar_height
2863                         ? outer_width - 2 * internal_border_width
2864                         : 0);
2866   /* Construct list.  */
2867   if (EQ (attribute, Qouter_edges))
2868     return list4 (make_number (f->left_pos), make_number (f->top_pos),
2869                   make_number (f->left_pos + outer_width),
2870                   make_number (f->top_pos + outer_height));
2871   else if (EQ (attribute, Qnative_edges))
2872     return list4 (make_number (native_left), make_number (native_top),
2873                   make_number (native_right), make_number (native_bottom));
2874   else if (EQ (attribute, Qinner_edges))
2875     return list4 (make_number (native_left + internal_border_width),
2876                   make_number (native_top
2877                                + tool_bar_height
2878                                + internal_border_width),
2879                   make_number (native_right - internal_border_width),
2880                   make_number (native_bottom - internal_border_width));
2881   else
2882     return
2883       listn (CONSTYPE_HEAP, 10,
2884              Fcons (Qouter_position,
2885                     Fcons (make_number (f->left_pos),
2886                            make_number (f->top_pos))),
2887              Fcons (Qouter_size,
2888                     Fcons (make_number (outer_width),
2889                            make_number (outer_height))),
2890              Fcons (Qexternal_border_size,
2891                     (fullscreen
2892                      ? Fcons (make_number (0), make_number (0))
2893                      : Fcons (make_number (border), make_number (border)))),
2894              Fcons (Qtitle_bar_size,
2895                     Fcons (make_number (0), make_number (title_height))),
2896              Fcons (Qmenu_bar_external, Qnil),
2897              Fcons (Qmenu_bar_size, Fcons (make_number (0), make_number (0))),
2898              Fcons (Qtool_bar_external,
2899                     FRAME_EXTERNAL_TOOL_BAR (f) ? Qt : Qnil),
2900              Fcons (Qtool_bar_position, FRAME_TOOL_BAR_POSITION (f)),
2901              Fcons (Qtool_bar_size,
2902                     Fcons (make_number (tool_bar_width),
2903                            make_number (tool_bar_height))),
2904              Fcons (Qinternal_border_width,
2905                     make_number (internal_border_width)));
2908 DEFUN ("ns-frame-geometry", Fns_frame_geometry, Sns_frame_geometry, 0, 1, 0,
2909        doc: /* Return geometric attributes of FRAME.
2910 FRAME must be a live frame and defaults to the selected one.  The return
2911 value is an association list of the attributes listed below.  All height
2912 and width values are in pixels.
2914 `outer-position' is a cons of the outer left and top edges of FRAME
2915   relative to the origin - the position (0, 0) - of FRAME's display.
2917 `outer-size' is a cons of the outer width and height of FRAME.  The
2918   outer size includes the title bar and the external borders as well as
2919   any menu and/or tool bar of frame.
2921 `external-border-size' is a cons of the horizontal and vertical width of
2922   FRAME's external borders as supplied by the window manager.
2924 `title-bar-size' is a cons of the width and height of the title bar of
2925   FRAME as supplied by the window manager.  If both of them are zero,
2926   FRAME has no title bar.  If only the width is zero, Emacs was not
2927   able to retrieve the width information.
2929 `menu-bar-external', if non-nil, means the menu bar is external (never
2930   included in the inner edges of FRAME).
2932 `menu-bar-size' is a cons of the width and height of the menu bar of
2933   FRAME.
2935 `tool-bar-external', if non-nil, means the tool bar is external (never
2936   included in the inner edges of FRAME).
2938 `tool-bar-position' tells on which side the tool bar on FRAME is and can
2939   be one of `left', `top', `right' or `bottom'.  If this is nil, FRAME
2940   has no tool bar.
2942 `tool-bar-size' is a cons of the width and height of the tool bar of
2943   FRAME.
2945 `internal-border-width' is the width of the internal border of
2946   FRAME.  */)
2947   (Lisp_Object frame)
2949   return frame_geometry (frame, Qnil);
2952 DEFUN ("ns-frame-edges", Fns_frame_edges, Sns_frame_edges, 0, 2, 0,
2953        doc: /* Return edge coordinates of FRAME.
2954 FRAME must be a live frame and defaults to the selected one.  The return
2955 value is a list of the form (LEFT, TOP, RIGHT, BOTTOM).  All values are
2956 in pixels relative to the origin - the position (0, 0) - of FRAME's
2957 display.
2959 If optional argument TYPE is the symbol `outer-edges', return the outer
2960 edges of FRAME.  The outer edges comprise the decorations of the window
2961 manager (like the title bar or external borders) as well as any external
2962 menu or tool bar of FRAME.  If optional argument TYPE is the symbol
2963 `native-edges' or nil, return the native edges of FRAME.  The native
2964 edges exclude the decorations of the window manager and any external
2965 menu or tool bar of FRAME.  If TYPE is the symbol `inner-edges', return
2966 the inner edges of FRAME.  These edges exclude title bar, any borders,
2967 menu bar or tool bar of FRAME.  */)
2968   (Lisp_Object frame, Lisp_Object type)
2970   return frame_geometry (frame, ((EQ (type, Qouter_edges)
2971                                   || EQ (type, Qinner_edges))
2972                                  ? type
2973                                  : Qnative_edges));
2976 /* ==========================================================================
2978     Class implementations
2980    ========================================================================== */
2983   Handle arrow/function/control keys and copy/paste/cut in file dialogs.
2984   Return YES if handled, NO if not.
2985  */
2986 static BOOL
2987 handlePanelKeys (NSSavePanel *panel, NSEvent *theEvent)
2989   NSString *s;
2990   int i;
2991   BOOL ret = NO;
2993   if ([theEvent type] != NSKeyDown) return NO;
2994   s = [theEvent characters];
2996   for (i = 0; i < [s length]; ++i)
2997     {
2998       int ch = (int) [s characterAtIndex: i];
2999       switch (ch)
3000         {
3001         case NSHomeFunctionKey:
3002         case NSDownArrowFunctionKey:
3003         case NSUpArrowFunctionKey:
3004         case NSLeftArrowFunctionKey:
3005         case NSRightArrowFunctionKey:
3006         case NSPageUpFunctionKey:
3007         case NSPageDownFunctionKey:
3008         case NSEndFunctionKey:
3009           /* Don't send command modified keys, as those are handled in the
3010              performKeyEquivalent method of the super class.
3011           */
3012           if (! ([theEvent modifierFlags] & NSCommandKeyMask))
3013             {
3014               [panel sendEvent: theEvent];
3015               ret = YES;
3016             }
3017           break;
3018           /* As we don't have the standard key commands for
3019              copy/paste/cut/select-all in our edit menu, we must handle
3020              them here.  TODO: handle Emacs key bindings for copy/cut/select-all
3021              here, paste works, because we have that in our Edit menu.
3022              I.e. refactor out code in nsterm.m, keyDown: to figure out the
3023              correct modifier.
3024           */
3025         case 'x': // Cut
3026         case 'c': // Copy
3027         case 'v': // Paste
3028         case 'a': // Select all
3029           if ([theEvent modifierFlags] & NSCommandKeyMask)
3030             {
3031               [NSApp sendAction:
3032                        (ch == 'x'
3033                         ? @selector(cut:)
3034                         : (ch == 'c'
3035                            ? @selector(copy:)
3036                            : (ch == 'v'
3037                               ? @selector(paste:)
3038                               : @selector(selectAll:))))
3039                              to:nil from:panel];
3040               ret = YES;
3041             }
3042         default:
3043           // Send all control keys, as the text field supports C-a, C-f, C-e
3044           // C-b and more.
3045           if ([theEvent modifierFlags] & NSControlKeyMask)
3046             {
3047               [panel sendEvent: theEvent];
3048               ret = YES;
3049             }
3050           break;
3051         }
3052     }
3055   return ret;
3058 @implementation EmacsSavePanel
3059 - (BOOL)performKeyEquivalent:(NSEvent *)theEvent
3061   BOOL ret = handlePanelKeys (self, theEvent);
3062   if (! ret)
3063     ret = [super performKeyEquivalent:theEvent];
3064   return ret;
3066 @end
3069 @implementation EmacsOpenPanel
3070 - (BOOL)performKeyEquivalent:(NSEvent *)theEvent
3072   // NSOpenPanel inherits NSSavePanel, so passing self is OK.
3073   BOOL ret = handlePanelKeys (self, theEvent);
3074   if (! ret)
3075     ret = [super performKeyEquivalent:theEvent];
3076   return ret;
3078 @end
3081 @implementation EmacsFileDelegate
3082 /* --------------------------------------------------------------------------
3083    Delegate methods for Open/Save panels
3084    -------------------------------------------------------------------------- */
3085 - (BOOL)panel: (id)sender isValidFilename: (NSString *)filename
3087   return YES;
3089 - (BOOL)panel: (id)sender shouldShowFilename: (NSString *)filename
3091   return YES;
3093 - (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename
3094           confirmed: (BOOL)okFlag
3096   return filename;
3098 @end
3100 #endif
3103 /* ==========================================================================
3105     Lisp interface declaration
3107    ========================================================================== */
3110 void
3111 syms_of_nsfns (void)
3113   DEFSYM (Qfontsize, "fontsize");
3115   DEFVAR_LISP ("ns-icon-type-alist", Vns_icon_type_alist,
3116                doc: /* Alist of elements (REGEXP . IMAGE) for images of icons associated to frames.
3117 If the title of a frame matches REGEXP, then IMAGE.tiff is
3118 selected as the image of the icon representing the frame when it's
3119 miniaturized.  If an element is t, then Emacs tries to select an icon
3120 based on the filetype of the visited file.
3122 The images have to be installed in a folder called English.lproj in the
3123 Emacs folder.  You have to restart Emacs after installing new icons.
3125 Example: Install an icon Gnus.tiff and execute the following code
3127   (setq ns-icon-type-alist
3128         (append ns-icon-type-alist
3129                 '((\"^\\\\*\\\\(Group\\\\*$\\\\|Summary \\\\|Article\\\\*$\\\\)\"
3130                    . \"Gnus\"))))
3132 When you miniaturize a Group, Summary or Article frame, Gnus.tiff will
3133 be used as the image of the icon representing the frame.  */);
3134   Vns_icon_type_alist = list1 (Qt);
3136   DEFVAR_LISP ("ns-version-string", Vns_version_string,
3137                doc: /* Toolkit version for NS Windowing.  */);
3138   Vns_version_string = ns_appkit_version_str ();
3140   defsubr (&Sns_read_file_name);
3141   defsubr (&Sns_get_resource);
3142   defsubr (&Sns_set_resource);
3143   defsubr (&Sxw_display_color_p); /* this and next called directly by C code */
3144   defsubr (&Sx_display_grayscale_p);
3145   defsubr (&Sns_font_name);
3146   defsubr (&Sns_list_colors);
3147 #ifdef NS_IMPL_COCOA
3148   defsubr (&Sns_do_applescript);
3149 #endif
3150   defsubr (&Sxw_color_defined_p);
3151   defsubr (&Sxw_color_values);
3152   defsubr (&Sx_server_max_request_size);
3153   defsubr (&Sx_server_vendor);
3154   defsubr (&Sx_server_version);
3155   defsubr (&Sx_display_pixel_width);
3156   defsubr (&Sx_display_pixel_height);
3157   defsubr (&Sns_display_monitor_attributes_list);
3158   defsubr (&Sns_frame_geometry);
3159   defsubr (&Sns_frame_edges);
3160   defsubr (&Sx_display_mm_width);
3161   defsubr (&Sx_display_mm_height);
3162   defsubr (&Sx_display_screens);
3163   defsubr (&Sx_display_planes);
3164   defsubr (&Sx_display_color_cells);
3165   defsubr (&Sx_display_visual_class);
3166   defsubr (&Sx_display_backing_store);
3167   defsubr (&Sx_display_save_under);
3168   defsubr (&Sx_create_frame);
3169   defsubr (&Sx_open_connection);
3170   defsubr (&Sx_close_connection);
3171   defsubr (&Sx_display_list);
3173   defsubr (&Sns_hide_others);
3174   defsubr (&Sns_hide_emacs);
3175   defsubr (&Sns_emacs_info_panel);
3176   defsubr (&Sns_list_services);
3177   defsubr (&Sns_perform_service);
3178   defsubr (&Sns_convert_utf8_nfd_to_nfc);
3179   defsubr (&Sns_popup_font_panel);
3180   defsubr (&Sns_popup_color_panel);
3182   defsubr (&Sx_show_tip);
3183   defsubr (&Sx_hide_tip);
3185   as_status = 0;
3186   as_script = Qnil;
3187   as_result = 0;