* makefile.w32-in (INFO_TARGETS, DVI_TARGETS, clean): Add ns-emacs.
[emacs.git] / src / nsfns.m
blobb8e28f1d13f1c6e1e184a44d7175bc6434339b9d
1 /* Functions for the NeXT/Open/GNUstep and MacOSX window system.
2    Copyright (C) 1989, 1992, 1993, 1994, 2005, 2006, 2008
3      Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
21 Originally by Carl Edman
22 Updated by Christian Limpach (chris@nice.ch)
23 OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com)
24 MacOSX/Aqua port by Christophe de Dinechin (descubes@earthlink.net)
25 GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
28 #include <signal.h>
29 #include <math.h>
30 #include "config.h"
31 #include "lisp.h"
32 #include "blockinput.h"
33 #include "nsterm.h"
34 #include "window.h"
35 #include "buffer.h"
36 #include "keyboard.h"
37 #include "termhooks.h"
38 #include "fontset.h"
40 #include "character.h"
41 #include "font.h"
43 #if 0
44 int fns_trace_num = 1;
45 #define NSTRACE(x)        fprintf (stderr, "%s:%d: [%d] " #x "\n",        \
46                                   __FILE__, __LINE__, ++fns_trace_num)
47 #else
48 #define NSTRACE(x)
49 #endif
51 #ifdef HAVE_NS
53 extern NSArray *ns_send_types, *ns_return_types, *ns_drag_types;
55 extern Lisp_Object Qforeground_color;
56 extern Lisp_Object Qbackground_color;
57 extern Lisp_Object Qcursor_color;
58 extern Lisp_Object Qinternal_border_width;
59 extern Lisp_Object Qvisibility;
60 extern Lisp_Object Qcursor_type;
61 extern Lisp_Object Qicon_type;
62 extern Lisp_Object Qicon_name;
63 extern Lisp_Object Qicon_left;
64 extern Lisp_Object Qicon_top;
65 extern Lisp_Object Qleft;
66 extern Lisp_Object Qright;
67 extern Lisp_Object Qtop;
68 extern Lisp_Object Qdisplay;
69 extern Lisp_Object Qvertical_scroll_bars;
70 extern Lisp_Object Qauto_raise;
71 extern Lisp_Object Qauto_lower;
72 extern Lisp_Object Qbox;
73 extern Lisp_Object Qscroll_bar_width;
74 extern Lisp_Object Qx_resource_name;
75 extern Lisp_Object Qface_set_after_frame_default;
76 extern Lisp_Object Qunderline, Qundefined;
77 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
78 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
80 Lisp_Object Qnone;
81 Lisp_Object Qns_frame_parameter;
82 Lisp_Object Qbuffered;
83 Lisp_Object Qfontsize;
85 /* hack for OS X file panels */
86 char panelOK = 0;
88 /* Alist of elements (REGEXP . IMAGE) for images of icons associated
89    to frames.*/
90 Lisp_Object Vns_icon_type_alist;
92 EmacsTooltip *ns_tooltip;
94 /* Need forward declaration here to preserve organizational integrity of file */
95 Lisp_Object Fx_open_connection (Lisp_Object, Lisp_Object, Lisp_Object);
97 extern BOOL ns_in_resize;
100 /* ==========================================================================
102     Internal utility functions
104    ========================================================================== */
107 void
108 check_ns (void)
110  if (NSApp == nil)
111    error ("OpenStep is not in use or not initialized");
115 /* Nonzero if we can use mouse menus. */
117 have_menus_p ()
119   return NSApp != nil;
123 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
124    and checking validity for NS.  */
125 static FRAME_PTR
126 check_ns_frame (Lisp_Object frame)
128   FRAME_PTR f;
130   if (NILP (frame))
131       f = SELECTED_FRAME ();
132   else
133     {
134       CHECK_LIVE_FRAME (frame);
135       f = XFRAME (frame);
136     }
137   if (! FRAME_NS_P (f))
138     error ("non-Nextstep frame used");
139   return f;
143 /* Let the user specify an Nextstep display with a frame.
144    nil stands for the selected frame--or, if that is not an Nextstep frame,
145    the first Nextstep display on the list.  */
146 static struct ns_display_info *
147 check_ns_display_info (Lisp_Object frame)
149   if (NILP (frame))
150     {
151       struct frame *f = SELECTED_FRAME ();
152       if (FRAME_NS_P (f) && FRAME_LIVE_P (f) )
153         return FRAME_NS_DISPLAY_INFO (f);
154       else if (x_display_list != 0)
155         return x_display_list;
156       else
157         error ("Nextstep windows are not in use or not initialized");
158     }
159   else if (INTEGERP (frame))
160     {
161       struct terminal *t = get_terminal (frame, 1);
163       if (t->type != output_ns)
164         error ("Terminal %d is not a Nextstep display", XINT (frame));
166       return t->display_info.ns;
167     }
168   else if (STRINGP (frame))
169     return ns_display_info_for_name (frame);
170   else
171     {
172       FRAME_PTR f;
174       CHECK_LIVE_FRAME (frame);
175       f = XFRAME (frame);
176       if (! FRAME_NS_P (f))
177         error ("non-Nextstep frame used");
178       return FRAME_NS_DISPLAY_INFO (f);
179     }
180   return NULL;  /* shut compiler up */
184 static id
185 ns_get_window (Lisp_Object maybeFrame)
187   id view =nil, window =nil;
189   if (!FRAMEP (maybeFrame) || !FRAME_NS_P (XFRAME (maybeFrame)))
190     maybeFrame = selected_frame;/*wrong_type_argument (Qframep, maybeFrame); */
192   if (!NILP (maybeFrame))
193     view = FRAME_NS_VIEW (XFRAME (maybeFrame));
194   if (view) window =[view window];
196   return window;
200 static NSScreen *
201 ns_get_screen (Lisp_Object anythingUnderTheSun)
203   id window =nil;
204   NSScreen *screen = 0;
206   struct terminal *terminal;
207   struct ns_display_info *dpyinfo;
208   struct frame *f = NULL;
209   Lisp_Object frame;
211   if (INTEGERP (anythingUnderTheSun)) {
212     /* we got a terminal */
213     terminal = get_terminal (anythingUnderTheSun, 1);
214     dpyinfo = terminal->display_info.ns;
215     f = dpyinfo->x_focus_frame;
216     if (!f)
217       f = dpyinfo->x_highlight_frame;
219   } else if (FRAMEP (anythingUnderTheSun) &&
220              FRAME_NS_P (XFRAME (anythingUnderTheSun))) {
221     /* we got a frame */
222     f = XFRAME (anythingUnderTheSun);
224   } else if (STRINGP (anythingUnderTheSun)) { /* FIXME/cl for multi-display */
225   }
227   if (!f)
228     f = SELECTED_FRAME ();
229   if (f)
230     {
231       XSETFRAME (frame, f);
232       window = ns_get_window (frame);
233     }
235   if (window)
236     screen = [window screen];
237   if (!screen)
238     screen = [NSScreen mainScreen];
240   return screen;
244 /* Return the X display structure for the display named NAME.
245    Open a new connection if necessary.  */
246 struct ns_display_info *
247 ns_display_info_for_name (name)
248      Lisp_Object name;
250   Lisp_Object names;
251   struct ns_display_info *dpyinfo;
253   CHECK_STRING (name);
255   for (dpyinfo = x_display_list, names = ns_display_name_list;
256        dpyinfo;
257        dpyinfo = dpyinfo->next, names = XCDR (names))
258     {
259       Lisp_Object tem;
260       tem = Fstring_equal (XCAR (XCAR (names)), name);
261       if (!NILP (tem))
262         return dpyinfo;
263     }
265   error ("Emacs for OpenStep does not yet support multi-display.");
267   Fx_open_connection (name, Qnil, Qnil);
268   dpyinfo = x_display_list;
270   if (dpyinfo == 0)
271     error ("OpenStep on %s not responding.\n", SDATA (name));
273   return dpyinfo;
277 static Lisp_Object
278 interpret_services_menu (NSMenu *menu, Lisp_Object prefix, Lisp_Object old)
279 /* --------------------------------------------------------------------------
280    Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side
281    -------------------------------------------------------------------------- */
283   int i, count;
284   id<NSMenuItem> item;
285   const char *name;
286   Lisp_Object nameStr;
287   unsigned short key;
288   NSString *keys;
289   Lisp_Object res;
291   count = [menu numberOfItems];
292   for (i = 0; i<count; i++)
293     {
294       item = [menu itemAtIndex: i];
295       name = [[item title] UTF8String];
296       if (!name) continue;
298       nameStr = build_string (name);
300       if ([item hasSubmenu])
301         {
302           old = interpret_services_menu ([item submenu],
303                                         Fcons (nameStr, prefix), old);
304         }
305       else
306         {
307           keys = [item keyEquivalent];
308           if (keys && [keys length] )
309             {
310               key = [keys characterAtIndex: 0];
311               res = make_number (key|super_modifier);
312             }
313           else
314             {
315               res = Qundefined;
316             }
317           old = Fcons (Fcons (res,
318                             Freverse (Fcons (nameStr,
319                                            prefix))),
320                     old);
321         }
322     }
323   return old;
328 /* ==========================================================================
330     Frame parameter setters
332    ========================================================================== */
335 static void
336 ns_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
338   NSColor *col;
340   if (ns_lisp_to_color (arg, &col))
341     {
342       store_frame_param (f, Qforeground_color, oldval);
343       error ("Unknown color");
344     }
346   [col retain];
347   [f->output_data.ns->foreground_color release];
348   f->output_data.ns->foreground_color = col;
350   if (FRAME_NS_VIEW (f))
351     {
352       update_face_from_frame_parameter (f, Qforeground_color, arg);
353       /*recompute_basic_faces (f); */
354       if (FRAME_VISIBLE_P (f))
355         redraw_frame (f);
356     }
360 static void
361 ns_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
363   struct face *face;
364   NSColor *col;
365   NSView *view = FRAME_NS_VIEW (f);
366   float alpha;
368   if (ns_lisp_to_color (arg, &col))
369     {
370       store_frame_param (f, Qbackground_color, oldval);
371       error ("Unknown color");
372     }
374   /* clear the frame; in some instances the NS-internal GC appears not to
375      update, or it does update and cannot clear old text properly */
376   if (FRAME_VISIBLE_P (f))
377     ns_clear_frame (f);
379   [col retain];
380   [f->output_data.ns->background_color release];
381   f->output_data.ns->background_color = col;
382   if (view != nil)
383     {
384       [[view window] setBackgroundColor: col];
385       alpha = [col alphaComponent];
387 #ifdef NS_IMPL_COCOA
388       /* the alpha code below only works on 10.4, so we need to do something
389          else (albeit less good) otherwise.
390          Check NSApplication.h for useful NSAppKitVersionNumber values. */
391       if (NSAppKitVersionNumber < 744.0)
392           [[view window] setAlphaValue: alpha];
393 #endif
395       if (alpha != 1.0)
396           [[view window] setOpaque: NO];
397       else
398           [[view window] setOpaque: YES];
400       face = FRAME_DEFAULT_FACE (f);
401       if (face)
402         {
403           col = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f);
404           face->background
405              = (EMACS_UINT) [[col colorWithAlphaComponent: alpha] retain];
406           [col release];
408           update_face_from_frame_parameter (f, Qbackground_color, arg);
409         }
411       if (FRAME_VISIBLE_P (f))
412         redraw_frame (f);
413     }
417 static void
418 ns_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
420   NSColor *col;
422   if (ns_lisp_to_color (arg, &col))
423     {
424       store_frame_param (f, Qcursor_color, oldval);
425       error ("Unknown color");
426     }
428   [f->output_data.ns->desired_cursor_color release];
429   f->output_data.ns->desired_cursor_color = [col retain];
431   if (FRAME_VISIBLE_P (f))
432     {
433       x_update_cursor (f, 0);
434       x_update_cursor (f, 1);
435     }
436   update_face_from_frame_parameter (f, Qcursor_color, arg);
440 static void
441 ns_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
443   NSView *view = FRAME_NS_VIEW (f);
444   NSTRACE (ns_set_icon_name);
446   if (ns_in_resize)
447     return;
449   /* see if it's changed */
450   if (STRINGP (arg))
451     {
452       if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
453         return;
454     }
455   else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
456     return;
458   f->icon_name = arg;
460   if (NILP (arg))
461     {
462       if (!NILP (f->title))
463         arg = f->title;
464       else
465         /* explicit name and no icon-name -> explicit_name */
466         if (f->explicit_name)
467           arg = f->name;
468         else
469           {
470             /* no explicit name and no icon-name ->
471                name has to be rebuild from icon_title_format */
472             windows_or_buffers_changed++;
473             return;
474           }
475     }
477   /* Don't change the name if it's already NAME.  */
478   if ([[view window] miniwindowTitle] &&
479       ([[[view window] miniwindowTitle]
480              isEqualToString: [NSString stringWithUTF8String:
481                                            SDATA (arg)]]))
482     return;
484   [[view window] setMiniwindowTitle:
485         [NSString stringWithUTF8String: SDATA (arg)]];
489 static void
490 ns_set_name_iconic (struct frame *f, Lisp_Object name, int explicit)
492   NSView *view = FRAME_NS_VIEW (f);
493   NSTRACE (ns_set_name_iconic);
495   if (ns_in_resize)
496     return;
498   /* Make sure that requests from lisp code override requests from
499      Emacs redisplay code.  */
500   if (explicit)
501     {
502       /* If we're switching from explicit to implicit, we had better
503          update the mode lines and thereby update the title.  */
504       if (f->explicit_name && NILP (name))
505         update_mode_lines = 1;
507       f->explicit_name = ! NILP (name);
508     }
509   else if (f->explicit_name)
510     name = f->name;
512   /* title overrides explicit name */
513   if (! NILP (f->title))
514     name = f->title;
516   /* icon_name overrides title and explicit name */
517   if (! NILP (f->icon_name))
518     name = f->icon_name;
520   if (NILP (name))
521     name = build_string
522         ([[[NSProcessInfo processInfo] processName] UTF8String]);
523   else
524     CHECK_STRING (name);
526   /* Don't change the name if it's already NAME.  */
527   if ([[view window] miniwindowTitle] &&
528       ([[[view window] miniwindowTitle]
529              isEqualToString: [NSString stringWithUTF8String:
530                                            SDATA (name)]]))
531     return;
533   [[view window] setMiniwindowTitle:
534         [NSString stringWithUTF8String: SDATA (name)]];
538 static void
539 ns_set_name (struct frame *f, Lisp_Object name, int explicit)
541   NSView *view = FRAME_NS_VIEW (f);
542   NSTRACE (ns_set_name);
544   if (ns_in_resize)
545     return;
547   /* Make sure that requests from lisp code override requests from
548      Emacs redisplay code.  */
549   if (explicit)
550     {
551       /* If we're switching from explicit to implicit, we had better
552          update the mode lines and thereby update the title.  */
553       if (f->explicit_name && NILP (name))
554         update_mode_lines = 1;
556       f->explicit_name = ! NILP (name);
557     }
558   else if (f->explicit_name)
559     return;
561   if (NILP (name))
562     name = build_string
563         ([[[NSProcessInfo processInfo] processName] UTF8String]);
565   f->name = name;
567   /* title overrides explicit name */
568   if (! NILP (f->title))
569     name = f->title;
571   CHECK_STRING (name);
573   /* Don't change the name if it's already NAME.  */
574   if ([[[view window] title]
575             isEqualToString: [NSString stringWithUTF8String:
576                                           SDATA (name)]])
577     return;
578   [[view window] setTitle: [NSString stringWithUTF8String:
579                                         SDATA (name)]];
583 /* This function should be called when the user's lisp code has
584    specified a name for the frame; the name will override any set by the
585    redisplay code.  */
586 static void
587 ns_explicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
589   NSTRACE (ns_explicitly_set_name);
590   ns_set_name_iconic (f, arg, 1);
591   ns_set_name (f, arg, 1);
595 /* This function should be called by Emacs redisplay code to set the
596    name; names set this way will never override names set by the user's
597    lisp code.  */
598 void
599 x_implicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
601   NSTRACE (x_implicitly_set_name);
602   if (FRAME_ICONIFIED_P (f))
603     ns_set_name_iconic (f, arg, 0);
604   else
605     ns_set_name (f, arg, 0);
609 /* Change the title of frame F to NAME.
610    If NAME is nil, use the frame name as the title.
612    If EXPLICIT is non-zero, that indicates that lisp code is setting the
613    name; if NAME is a string, set F's name to NAME and set
614    F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
616    If EXPLICIT is zero, that indicates that Emacs redisplay code is
617    suggesting a new name, which lisp code should override; if
618    F->explicit_name is set, ignore the new name; otherwise, set it.  */
619 static void
620 ns_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
622   NSTRACE (ns_set_title);
623   /* Don't change the title if it's already NAME.  */
624   if (EQ (name, f->title))
625     return;
627   update_mode_lines = 1;
629   f->title = name;
633 void
634 ns_set_name_as_filename (struct frame *f)
636   NSView *view = FRAME_NS_VIEW (f);
637   Lisp_Object name;
638   Lisp_Object buf = XWINDOW (f->selected_window)->buffer;
639   const char *title;
640   NSAutoreleasePool *pool;
641   NSTRACE (ns_set_name_as_filename);
643   if (f->explicit_name || ! NILP (f->title) || ns_in_resize)
644     return;
646   BLOCK_INPUT;
647   pool = [[NSAutoreleasePool alloc] init];
648   name =XBUFFER (buf)->filename;
649   if (NILP (name) || FRAME_ICONIFIED_P (f)) name =XBUFFER (buf)->name;
651   if (FRAME_ICONIFIED_P (f) && !NILP (f->icon_name))
652     name = f->icon_name;
654   if (NILP (name))
655     name = build_string
656         ([[[NSProcessInfo processInfo] processName] UTF8String]);
657   else
658     CHECK_STRING (name);
660   title = FRAME_ICONIFIED_P (f) ? [[[view window] miniwindowTitle] UTF8String]
661                                 : [[[view window] title] UTF8String];
663   if (title && (! strcmp (title, SDATA (name))))
664     {
665       [pool release];
666       UNBLOCK_INPUT;
667       return;
668     }
670   if (! FRAME_ICONIFIED_P (f))
671     {
672 #ifdef NS_IMPL_COCOA
673       /* work around a bug observed on 10.3 where
674          setTitleWithRepresentedFilename does not clear out previous state
675          if given filename does not exist */
676       NSString *str = [NSString stringWithUTF8String: SDATA (name)];
677       if (![[NSFileManager defaultManager] fileExistsAtPath: str])
678         {
679           [[view window] setTitleWithRepresentedFilename: @""];
680           [[view window] setTitle: str];
681         }
682       else
683         {
684           [[view window] setTitleWithRepresentedFilename: str];
685         }
686 #else
687       [[view window] setTitleWithRepresentedFilename:
688                          [NSString stringWithUTF8String: SDATA (name)]];
689 #endif
690       f->name = name;
691     }
692   else
693     {
694       [[view window] setMiniwindowTitle:
695             [NSString stringWithUTF8String: SDATA (name)]];
696     }
697   [pool release];
698   UNBLOCK_INPUT;
702 void
703 ns_set_doc_edited (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
705   NSView *view = FRAME_NS_VIEW (f);
706   NSAutoreleasePool *pool;
707   BLOCK_INPUT;
708   pool = [[NSAutoreleasePool alloc] init];
709   [[view window] setDocumentEdited: !NILP (arg)];
710   [pool release];
711   UNBLOCK_INPUT;
715 void
716 x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
718   int nlines;
719   int olines = FRAME_MENU_BAR_LINES (f);
720   if (FRAME_MINIBUF_ONLY_P (f))
721     return;
723   if (INTEGERP (value))
724     nlines = XINT (value);
725   else
726     nlines = 0;
728   FRAME_MENU_BAR_LINES (f) = 0;
729   if (nlines)
730     {
731       FRAME_EXTERNAL_MENU_BAR (f) = 1;
732       /* does for all frames, whereas we just want for one frame
733          [NSMenu setMenuBarVisible: YES]; */
734     }
735   else
736     {
737       if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
738         free_frame_menubar (f);
739       /*      [NSMenu setMenuBarVisible: NO]; */
740       FRAME_EXTERNAL_MENU_BAR (f) = 0;
741     }
745 /* 23: toolbar support */
746 void
747 x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
749   int nlines;
750   Lisp_Object root_window;
752   if (FRAME_MINIBUF_ONLY_P (f))
753     return;
755   if (INTEGERP (value) && XINT (value) >= 0)
756     nlines = XFASTINT (value);
757   else
758     nlines = 0;
760   if (nlines)
761     {
762       FRAME_EXTERNAL_TOOL_BAR (f) = 1;
763       update_frame_tool_bar (f);
764     }
765   else
766     {
767       if (FRAME_EXTERNAL_TOOL_BAR (f))
768         {
769           free_frame_tool_bar (f);
770           FRAME_EXTERNAL_TOOL_BAR (f) = 0;
771         }
772     }
774   x_set_window_size (f, 0, f->text_cols, f->text_lines);
778 void
779 ns_implicitly_set_icon_type (struct frame *f)
781   Lisp_Object tem;
782   EmacsView *view = FRAME_NS_VIEW (f);
783   id image =nil;
784   Lisp_Object chain, elt;
785   NSAutoreleasePool *pool;
786   BOOL setMini = YES;
788   NSTRACE (ns_implicitly_set_icon_type);
790   BLOCK_INPUT;
791   pool = [[NSAutoreleasePool alloc] init];
792   if (f->output_data.ns->miniimage
793       && [[NSString stringWithUTF8String: SDATA (f->name)]
794                isEqualToString: [(NSImage *)f->output_data.ns->miniimage name]])
795     {
796       [pool release];
797       UNBLOCK_INPUT;
798       return;
799     }
801   tem = assq_no_quit (Qicon_type, f->param_alist);
802   if (CONSP (tem) && ! NILP (XCDR (tem)))
803     {
804       [pool release];
805       UNBLOCK_INPUT;
806       return;
807     }
809   for (chain = Vns_icon_type_alist;
810        (image = nil) && CONSP (chain);
811        chain = XCDR (chain))
812     {
813       elt = XCAR (chain);
814       /* special case: 't' means go by file type */
815       if (SYMBOLP (elt) && EQ (elt, Qt) && SDATA (f->name)[0] == '/')
816         {
817           NSString *str
818              = [NSString stringWithUTF8String: SDATA (f->name)];
819           if ([[NSFileManager defaultManager] fileExistsAtPath: str])
820             image = [[[NSWorkspace sharedWorkspace] iconForFile: str] retain];
821         }
822       else if (CONSP (elt) &&
823                STRINGP (XCAR (elt)) &&
824                STRINGP (XCDR (elt)) &&
825                fast_string_match (XCAR (elt), f->name) >= 0)
826         {
827           image = [EmacsImage allocInitFromFile: XCDR (elt)];
828           if (image == nil)
829             image = [[NSImage imageNamed:
830                                [NSString stringWithUTF8String:
831                                             SDATA (XCDR (elt))]] retain];
832         }
833     }
835   if (image == nil)
836     {
837       image = [[[NSWorkspace sharedWorkspace] iconForFileType: @"text"] retain];
838       setMini = NO;
839     }
841   [f->output_data.ns->miniimage release];
842   f->output_data.ns->miniimage = image;
843   [view setMiniwindowImage: setMini];
844   [pool release];
845   UNBLOCK_INPUT;
849 static void
850 ns_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
852   EmacsView *view = FRAME_NS_VIEW (f);
853   id image = nil;
854   BOOL setMini = YES;
856   NSTRACE (ns_set_icon_type);
858   if (!NILP (arg) && SYMBOLP (arg))
859     {
860       arg =build_string (SDATA (SYMBOL_NAME (arg)));
861       store_frame_param (f, Qicon_type, arg);
862     }
864   /* do it the implicit way */
865   if (NILP (arg))
866     {
867       ns_implicitly_set_icon_type (f);
868       return;
869     }
871   CHECK_STRING (arg);
873   image = [EmacsImage allocInitFromFile: arg];
874   if (image == nil)
875     image =[NSImage imageNamed: [NSString stringWithUTF8String:
876                                             SDATA (arg)]];
878   if (image == nil)
879     {
880       image = [NSImage imageNamed: @"text"];
881       setMini = NO;
882     }
884   f->output_data.ns->miniimage = image;
885   [view setMiniwindowImage: setMini];
889 /* 23: added Xism; we stub out (we do implement this in ns-win.el) */
891 XParseGeometry (char *string, int *x, int *y,
892                 unsigned int *width, unsigned int *height)
894   message1 ("Warning: XParseGeometry not supported under NS.\n");
895   return 0;
899 /* TODO: move to nsterm? */
901 ns_lisp_to_cursor_type (Lisp_Object arg)
903   char *str;
904   if (XTYPE (arg) == Lisp_String)
905     str = SDATA (arg);
906   else if (XTYPE (arg) == Lisp_Symbol)
907     str = SDATA (SYMBOL_NAME (arg));
908   else return -1;
909   if (!strcmp (str, "box"))      return filled_box;
910   if (!strcmp (str, "hollow"))   return hollow_box;
911   if (!strcmp (str, "underscore")) return underscore;
912   if (!strcmp (str, "bar"))      return bar;
913   if (!strcmp (str, "no"))       return no_highlight;
914   return -1;
918 Lisp_Object
919 ns_cursor_type_to_lisp (int arg)
921   switch (arg)
922     {
923     case filled_box: return Qbox;
924     case hollow_box: return intern ("hollow");
925     case underscore: return intern ("underscore");
926     case bar:        return intern ("bar");
927     case no_highlight:
928     default:         return intern ("no");
929     }
933 static void
934 ns_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
936   int val;
938   val = ns_lisp_to_cursor_type (arg);
939   if (val >= 0)
940     {
941       f->output_data.ns->desired_cursor =val;
942     }
943   else
944     {
945       store_frame_param (f, Qcursor_type, oldval);
946       error ("the `cursor-type' frame parameter should be either `no', `box', \
947 `hollow', `underscore' or `bar'.");
948     }
950   update_mode_lines++;
954 /* 23: called to set mouse pointer color, but all other terms use it to
955        initialize pointer types (and don't set the color ;) */
956 static void
957 ns_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
959   /* don't think we can do this on Nextstep */
963 static void
964 x_icon (struct frame *f, Lisp_Object parms)
965 /* --------------------------------------------------------------------------
966    Strangely-named function to set icon position parameters in frame.
967    This is irrelevant under OS X, but might be needed under GNUstep,
968    depending on the window manager used.  Note, this is not a standard
969    frame parameter-setter; it is called directly from x-create-frame.
970    -------------------------------------------------------------------------- */
972   Lisp_Object icon_x, icon_y;
973   struct ns_display_info *dpyinfo = check_ns_display_info (Qnil);
975   f->output_data.ns->icon_top = Qnil;
976   f->output_data.ns->icon_left = Qnil;
978   /* Set the position of the icon.  */
979   icon_x = x_get_arg (dpyinfo, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
980   icon_y = x_get_arg (dpyinfo, parms, Qicon_top, 0, 0,  RES_TYPE_NUMBER);
981   if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
982     {
983       CHECK_NUMBER (icon_x);
984       CHECK_NUMBER (icon_y);
985       f->output_data.ns->icon_top = icon_y;
986       f->output_data.ns->icon_left = icon_x;
987     }
988   else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
989     error ("Both left and top icon corners of icon must be specified");
993 /* 23 Note: commented out ns_... entries are no longer used in 23.
994             commented out x_... entries have not been implemented yet.
995    see frame.c for template, also where all generic OK functions are impl */
996 frame_parm_handler ns_frame_parm_handlers[] =
998   x_set_autoraise, /* generic OK */
999   x_set_autolower, /* generic OK */
1000   ns_set_background_color,
1001   0, /* x_set_border_color,  may be impossible under Nextstep */
1002   0, /* x_set_border_width,  may be impossible under Nextstep */
1003   ns_set_cursor_color,
1004   ns_set_cursor_type,
1005   x_set_font, /* generic OK */
1006   ns_set_foreground_color,
1007   ns_set_icon_name,
1008   ns_set_icon_type,
1009   x_set_internal_border_width, /* generic OK */
1010   x_set_menu_bar_lines,
1011   ns_set_mouse_color,
1012   ns_explicitly_set_name,
1013   x_set_scroll_bar_width, /* generic OK */
1014   ns_set_title,
1015   x_set_unsplittable, /* generic OK */
1016   x_set_vertical_scroll_bars, /* generic OK */
1017   x_set_visibility, /* generic OK */
1018   x_set_tool_bar_lines,
1019   0, /* x_set_scroll_bar_foreground, will ignore (not possible on NS) */
1020   0, /* x_set_scroll_bar_background,  will ignore (not possible on NS) */
1021   x_set_screen_gamma, /* generic OK */
1022   x_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */
1023   x_set_fringe_width, /* generic OK */
1024   x_set_fringe_width, /* generic OK */
1025   0, /* x_set_wait_for_wm, will ignore */
1026   0,  /* x_set_fullscreen will ignore */
1027   x_set_font_backend /* generic OK */
1031 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
1032        1, 1, 0,
1033        doc: /* Make a new Nextstep window, called a \"frame\" in Emacs terms.
1034 Return an Emacs frame object.
1035 PARMS is an alist of frame parameters.
1036 If the parameters specify that the frame should not have a minibuffer,
1037 and do not specify a specific minibuffer window to use,
1038 then `default-minibuffer-frame' must be a frame whose minibuffer can
1039 be shared by the new frame.  */)
1040      (parms)
1041      Lisp_Object parms;
1043   static int desc_ctr = 1;
1044   struct frame *f;
1045   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1046   Lisp_Object frame, tem;
1047   Lisp_Object name;
1048   int minibuffer_only = 0;
1049   int count = specpdl_ptr - specpdl;
1050   Lisp_Object display;
1051   struct ns_display_info *dpyinfo = NULL;
1052   Lisp_Object parent;
1053   struct kboard *kb;
1054   Lisp_Object tfont, tfontsize;
1055   int window_prompting = 0;
1056   int width, height;
1058   check_ns ();
1060   display = x_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_STRING);
1061   if (EQ (display, Qunbound))
1062     display = Qnil;
1063   dpyinfo = check_ns_display_info (display);
1065   if (!dpyinfo->terminal->name)
1066     error ("Terminal is not live, can't create new frames on it");
1068   kb = dpyinfo->terminal->kboard;
1070   name = x_get_arg (dpyinfo, parms, Qname, 0, 0, RES_TYPE_STRING);
1071   if (!STRINGP (name)
1072       && ! EQ (name, Qunbound)
1073       && ! NILP (name))
1074     error ("Invalid frame name--not a string or nil");
1076   if (STRINGP (name))
1077     Vx_resource_name = name;
1079   parent = x_get_arg (dpyinfo, parms, Qparent_id, 0, 0, RES_TYPE_NUMBER);
1080   if (EQ (parent, Qunbound))
1081     parent = Qnil;
1082   if (! NILP (parent))
1083     CHECK_NUMBER (parent);
1085   frame = Qnil;
1086   GCPRO4 (parms, parent, name, frame);
1088   tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
1089                   RES_TYPE_SYMBOL);
1090   if (EQ (tem, Qnone) || NILP (tem))
1091     {
1092       f = make_frame_without_minibuffer (Qnil, kb, display);
1093     }
1094   else if (EQ (tem, Qonly))
1095     {
1096       f = make_minibuffer_frame ();
1097       minibuffer_only = 1;
1098     }
1099   else if (WINDOWP (tem))
1100     {
1101       f = make_frame_without_minibuffer (tem, kb, display);
1102     }
1103   else
1104     {
1105       f = make_frame (1);
1106     }
1108   /* Set the name; the functions to which we pass f expect the name to
1109      be set.  */
1110   if (EQ (name, Qunbound) || NILP (name) || (XTYPE (name) != Lisp_String))
1111     {
1112       f->name
1113          = build_string ([[[NSProcessInfo processInfo] processName] UTF8String]);
1114       f->explicit_name =0;
1115     }
1116   else
1117     {
1118       f->name = name;
1119       f->explicit_name = 1;
1120       specbind (Qx_resource_name, name);
1121     }
1123   XSETFRAME (frame, f);
1124   FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
1126   f->terminal = dpyinfo->terminal;
1127   f->terminal->reference_count++;
1129   f->output_method = output_ns;
1130   f->output_data.ns = (struct ns_output *)xmalloc (sizeof *(f->output_data.ns));
1131   bzero (f->output_data.ns, sizeof (*(f->output_data.ns)));
1133   FRAME_FONTSET (f) = -1;
1135   /* record_unwind_protect (unwind_create_frame, frame); safety; maybe later? */
1137   f->icon_name = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
1138                             RES_TYPE_STRING);
1139   if (EQ (f->icon_name, Qunbound) || (XTYPE (f->icon_name) != Lisp_String))
1140     f->icon_name = Qnil;
1142   FRAME_NS_DISPLAY_INFO (f) = dpyinfo;
1144   f->output_data.ns->window_desc = desc_ctr++;
1145   if (!NILP (parent))
1146     {
1147       f->output_data.ns->parent_desc = (Window) XFASTINT (parent);
1148       f->output_data.ns->explicit_parent = 1;
1149     }
1150   else
1151     {
1152       f->output_data.ns->parent_desc = FRAME_NS_DISPLAY_INFO (f)->root_window;
1153       f->output_data.ns->explicit_parent = 0;
1154     }
1156   f->resx = dpyinfo->resx;
1157   f->resy = dpyinfo->resy;
1159   BLOCK_INPUT;
1160   register_font_driver (&nsfont_driver, f);
1161   x_default_parameter (f, parms, Qfont_backend, Qnil,
1162                         "fontBackend", "FontBackend", RES_TYPE_STRING);
1164   {
1165     /* use for default font name */
1166     id font = [NSFont userFixedPitchFontOfSize: -1.0]; /* default */
1167     tfontsize = x_default_parameter (f, parms, Qfontsize,
1168                                     make_number (0 /*(int)[font pointSize]*/),
1169                                     "fontSize", "FontSize", RES_TYPE_NUMBER);
1170     tfont = x_default_parameter (f, parms, Qfont,
1171                                  build_string ([[font fontName] UTF8String]),
1172                                  "font", "Font", RES_TYPE_STRING);
1173   }
1174   UNBLOCK_INPUT;
1176   x_default_parameter (f, parms, Qborder_width, make_number (0),
1177                        "borderwidth", "BorderWidth", RES_TYPE_NUMBER);
1178   x_default_parameter (f, parms, Qinternal_border_width, make_number (2),
1179                       "internalBorderWidth", "InternalBorderWidth",
1180                       RES_TYPE_NUMBER);
1182   /* default scrollbars on right on Mac */
1183   {
1184       Lisp_Object spos
1185 #ifdef NS_IMPL_GNUSTEP
1186           = Qt;
1187 #else
1188           = Qright;
1189 #endif
1190       x_default_parameter (f, parms, Qvertical_scroll_bars, spos,
1191                            "verticalScrollBars", "VerticalScrollBars",
1192                            RES_TYPE_SYMBOL);
1193   }
1194   x_default_parameter (f, parms, Qforeground_color, build_string ("Black"),
1195                       "foreground", "Foreground", RES_TYPE_STRING);
1196   x_default_parameter (f, parms, Qbackground_color, build_string ("White"),
1197                       "background", "Background", RES_TYPE_STRING);
1198   x_default_parameter (f, parms, Qcursor_color, build_string ("grey"),
1199                       "cursorColor", "CursorColor", RES_TYPE_STRING);
1200   /* FIXME: not suppported yet in Nextstep */
1201   x_default_parameter (f, parms, Qline_spacing, Qnil,
1202                        "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
1203   x_default_parameter (f, parms, Qleft_fringe, Qnil,
1204                        "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
1205   x_default_parameter (f, parms, Qright_fringe, Qnil,
1206                        "rightFringe", "RightFringe", RES_TYPE_NUMBER);
1207   /* end PENDING */
1209   init_frame_faces (f);
1211   x_default_parameter (f, parms, Qmenu_bar_lines, make_number (0), "menuBar",
1212                       "menuBar", RES_TYPE_NUMBER);
1213   x_default_parameter (f, parms, Qtool_bar_lines, make_number (0), "toolBar",
1214                       "toolBar", RES_TYPE_NUMBER);
1215   x_default_parameter (f, parms, Qbuffer_predicate, Qnil, "bufferPredicate",
1216                        "BufferPredicate", RES_TYPE_SYMBOL);
1217   x_default_parameter (f, parms, Qtitle, Qnil, "title", "Title",
1218                        RES_TYPE_STRING);
1220 /* TODO: other terms seem to get away w/o this complexity.. */
1221   if (NILP (Fassq (Qwidth, parms)))
1222     {
1223       Lisp_Object value
1224          = x_get_arg (dpyinfo, parms, Qwidth, "width", "Width",
1225                       RES_TYPE_NUMBER);
1226       if (! EQ (value, Qunbound))
1227         parms = Fcons (Fcons (Qwidth, value), parms);
1228     }
1229   if (NILP (Fassq (Qheight, parms)))
1230     {
1231       Lisp_Object value
1232          = x_get_arg (dpyinfo, parms, Qheight, "height", "Height",
1233                       RES_TYPE_NUMBER);
1234       if (! EQ (value, Qunbound))
1235         parms = Fcons (Fcons (Qheight, value), parms);
1236     }
1237   if (NILP (Fassq (Qleft, parms)))
1238     {
1239       Lisp_Object value
1240          = x_get_arg (dpyinfo, parms, Qleft, "left", "Left", RES_TYPE_NUMBER);
1241       if (! EQ (value, Qunbound))
1242         parms = Fcons (Fcons (Qleft, value), parms);
1243     }
1244   if (NILP (Fassq (Qtop, parms)))
1245     {
1246       Lisp_Object value
1247          = x_get_arg (dpyinfo, parms, Qtop, "top", "Top", RES_TYPE_NUMBER);
1248       if (! EQ (value, Qunbound))
1249         parms = Fcons (Fcons (Qtop, value), parms);
1250     }
1252   window_prompting = x_figure_window_size (f, parms, 1);
1254   tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
1255   f->no_split = minibuffer_only || (!EQ (tem, Qunbound) && !EQ (tem, Qnil));
1257   /* NOTE: on other terms, this is done in set_mouse_color, however this
1258      was not getting called under Nextstep */
1259   f->output_data.ns->text_cursor = [NSCursor IBeamCursor];
1260   f->output_data.ns->nontext_cursor = [NSCursor arrowCursor];
1261   f->output_data.ns->modeline_cursor = [NSCursor pointingHandCursor];
1262   f->output_data.ns->hand_cursor = [NSCursor pointingHandCursor];
1263   f->output_data.ns->hourglass_cursor = [NSCursor disappearingItemCursor];
1264   f->output_data.ns->horizontal_drag_cursor = [NSCursor resizeLeftRightCursor];
1265   FRAME_NS_DISPLAY_INFO (f)->vertical_scroll_bar_cursor
1266      = [NSCursor arrowCursor];
1267   f->output_data.ns->current_pointer = f->output_data.ns->text_cursor;
1269   [[EmacsView alloc] initFrameFromEmacs: f];
1271   x_icon (f, parms);
1273   /* It is now ok to make the frame official even if we get an error below.
1274      The frame needs to be on Vframe_list or making it visible won't work. */
1275   Vframe_list = Fcons (frame, Vframe_list);
1276   /*FRAME_NS_DISPLAY_INFO (f)->reference_count++; */
1278   x_default_parameter (f, parms, Qcursor_type, Qbox, "cursorType", "CursorType",
1279                       RES_TYPE_SYMBOL);
1280   x_default_parameter (f, parms, Qscroll_bar_width, Qnil, "scrollBarWidth",
1281                       "ScrollBarWidth", RES_TYPE_NUMBER);
1282   x_default_parameter (f, parms, Qicon_type, Qnil, "bitmapIcon", "BitmapIcon",
1283                       RES_TYPE_SYMBOL);
1284   x_default_parameter (f, parms, Qauto_raise, Qnil, "autoRaise", "AutoRaise",
1285                       RES_TYPE_BOOLEAN);
1286   x_default_parameter (f, parms, Qauto_lower, Qnil, "autoLower", "AutoLower",
1287                       RES_TYPE_BOOLEAN);
1288   x_default_parameter (f, parms, Qbuffered, Qt, "buffered", "Buffered",
1289                       RES_TYPE_BOOLEAN);
1291   width = FRAME_COLS (f);
1292   height = FRAME_LINES (f);
1294   SET_FRAME_COLS (f, 0);
1295   FRAME_LINES (f) = 0;
1296   change_frame_size (f, height, width, 1, 0, 0);
1298   if (! f->output_data.ns->explicit_parent)
1299     {
1300         tem = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_BOOLEAN);
1301         if (EQ (tem, Qunbound))
1302             tem = Qnil;
1304         x_set_visibility (f, tem, Qnil);
1305         if (EQ (tem, Qt))
1306             [[FRAME_NS_VIEW (f) window] makeKeyWindow];
1307     }
1309   if (FRAME_HAS_MINIBUF_P (f)
1310       && (!FRAMEP (kb->Vdefault_minibuffer_frame)
1311           || !FRAME_LIVE_P (XFRAME (kb->Vdefault_minibuffer_frame))))
1312     kb->Vdefault_minibuffer_frame = frame;
1314   /* All remaining specified parameters, which have not been "used"
1315      by x_get_arg and friends, now go in the misc. alist of the frame.  */
1316   for (tem = parms; CONSP (tem); tem = XCDR (tem))
1317     if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
1318       f->param_alist = Fcons (XCAR (tem), f->param_alist);
1320   UNGCPRO;
1321   Vwindow_list = Qnil;
1323   return unbind_to (count, frame);
1327 /* ==========================================================================
1329     Lisp definitions
1331    ========================================================================== */
1333 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
1334        doc: /* Set the input focus to FRAME.
1335 FRAME nil means use the selected frame.  */)
1336      (frame)
1337      Lisp_Object frame;
1339   struct frame *f = check_ns_frame (frame);
1340   struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f);
1342   if (dpyinfo->x_focus_frame != f)
1343     {
1344       EmacsView *view = FRAME_NS_VIEW (f);
1345       BLOCK_INPUT;
1346       [[view window] makeKeyAndOrderFront: view];
1347       UNBLOCK_INPUT;
1348     }
1350   return Qnil;
1354 DEFUN ("ns-popup-prefs-panel", Fns_popup_prefs_panel, Sns_popup_prefs_panel,
1355        0, 0, "",
1356        doc: /* Pop up the preferences panel. */)
1357      ()
1359   check_ns ();
1360   [(EmacsApp *)NSApp showPreferencesWindow: NSApp];
1361   return Qnil;
1365 DEFUN ("ns-popup-font-panel", Fns_popup_font_panel, Sns_popup_font_panel,
1366        0, 1, "",
1367        doc: /* Pop up the font panel. */)
1368      (frame)
1369      Lisp_Object frame;
1371   id fm;
1372   struct frame *f;
1374   check_ns ();
1375   fm = [NSFontManager new];
1376   if (NILP (frame))
1377     f = SELECTED_FRAME ();
1378   else
1379     {
1380       CHECK_FRAME (frame);
1381       f = XFRAME (frame);
1382     }
1384   [fm setSelectedFont: ((struct nsfont_info *)f->output_data.ns->font)->nsfont
1385            isMultiple: NO];
1386   [fm orderFrontFontPanel: NSApp];
1387   return Qnil;
1391 DEFUN ("ns-popup-color-panel", Fns_popup_color_panel, Sns_popup_color_panel, 
1392        0, 1, "",
1393        doc: /* Pop up the color panel.  */)
1394      (frame)
1395      Lisp_Object frame;
1397   struct frame *f;
1399   check_ns ();
1400   if (NILP (frame))
1401     f = SELECTED_FRAME ();
1402   else
1403     {
1404       CHECK_FRAME (frame);
1405       f = XFRAME (frame);
1406     }
1408   [NSApp orderFrontColorPanel: NSApp];
1409   return Qnil;
1413 DEFUN ("ns-read-file-name", Fns_read_file_name, Sns_read_file_name, 1, 4, 0,
1414        doc: /* Use a graphical panel to read a file name, using prompt PROMPT.
1415 Optional arg DIR, if non-nil, supplies a default directory.
1416 Optional arg ISLOAD, if non-nil, means read a file name for saving.
1417 Optional arg INIT, if non-nil, provides a default file name to use.  */)
1418      (prompt, dir, isLoad, init)
1419      Lisp_Object prompt, dir, isLoad, init;
1421   static id fileDelegate = nil;
1422   int ret;
1423   id panel;
1424   NSString *fname;
1426   NSString *promptS = NILP (prompt) || !STRINGP (prompt) ? nil :
1427     [NSString stringWithUTF8String: SDATA (prompt)];
1428   NSString *dirS = NILP (dir) || !STRINGP (dir) ?
1429     [NSString stringWithUTF8String: SDATA (current_buffer->directory)] :
1430     [NSString stringWithUTF8String: SDATA (dir)];
1431   NSString *initS = NILP (init) || !STRINGP (init) ? nil :
1432     [NSString stringWithUTF8String: SDATA (init)];
1434   check_ns ();
1436   if (fileDelegate == nil)
1437     fileDelegate = [EmacsFileDelegate new];
1439   [NSCursor setHiddenUntilMouseMoves: NO];
1441   if ([dirS characterAtIndex: 0] == '~')
1442     dirS = [dirS stringByExpandingTildeInPath];
1444   panel = NILP (isLoad) ?
1445     [EmacsSavePanel savePanel] : [EmacsOpenPanel openPanel];
1447   [panel setTitle: promptS];
1449   /* Puma (10.1) does not have */
1450   if ([panel respondsToSelector: @selector (setAllowsOtherFileTypes:)])
1451     [panel setAllowsOtherFileTypes: YES];
1453   [panel setTreatsFilePackagesAsDirectories: YES];
1454   [panel setDelegate: fileDelegate];
1456   panelOK = 0;
1457   if (NILP (isLoad))
1458     {
1459       ret = [panel runModalForDirectory: dirS file: initS];
1460     }
1461   else
1462     {
1463       [panel setCanChooseDirectories: YES];
1464       ret = [panel runModalForDirectory: dirS file: initS types: nil];
1465     }
1467   ret = (ret = NSOKButton) || panelOK;
1469   fname = [panel filename];
1471   [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
1473   return ret ? build_string ([fname UTF8String]) : Qnil;
1477 DEFUN ("ns-get-resource", Fns_get_resource, Sns_get_resource, 2, 2, 0,
1478        doc: /* Return the value of the property NAME of OWNER from the defaults database.
1479 If OWNER is nil, Emacs is assumed.  */)
1480      (owner, name)
1481      Lisp_Object owner, name;
1483   const char *value;
1485   check_ns ();
1486   if (NILP (owner))
1487     owner = build_string
1488         ([[[NSProcessInfo processInfo] processName] UTF8String]);
1489   /* CHECK_STRING (owner);  this should be just "Emacs" */
1490   CHECK_STRING (name);
1491 /*fprintf (stderr, "ns-get-resource checking resource '%s'\n", SDATA (name)); */
1493   value =[[[NSUserDefaults standardUserDefaults]
1494             objectForKey: [NSString stringWithUTF8String: SDATA (name)]]
1495            UTF8String];
1497   if (value)
1498     return build_string (value);
1499   return Qnil;
1503 DEFUN ("ns-set-resource", Fns_set_resource, Sns_set_resource, 3, 3, 0,
1504        doc: /* Set property NAME of OWNER to VALUE, from the defaults database.
1505 If OWNER is nil, Emacs is assumed.
1506 If VALUE is nil, the default is removed.  */)
1507      (owner, name, value)
1508      Lisp_Object owner, name, value;
1510   check_ns ();
1511   if (NILP (owner))
1512     owner
1513        = build_string ([[[NSProcessInfo processInfo] processName] UTF8String]);
1514   CHECK_STRING (owner);
1515   CHECK_STRING (name);
1516   if (NILP (value))
1517     {
1518       [[NSUserDefaults standardUserDefaults] removeObjectForKey:
1519                          [NSString stringWithUTF8String: SDATA (name)]];
1520     }
1521   else
1522     {
1523       CHECK_STRING (value);
1524       [[NSUserDefaults standardUserDefaults] setObject:
1525                 [NSString stringWithUTF8String: SDATA (value)]
1526                                         forKey: [NSString stringWithUTF8String:
1527                                                          SDATA (name)]];
1528     }
1530   return Qnil;
1534 DEFUN ("ns-set-alpha", Fns_set_alpha, Sns_set_alpha, 2, 2, 0,
1535        doc: /* Return a color equivalent to COLOR with alpha setting ALPHA.
1536 The argument ALPHA should be a number between 0 and 1, where 0 is full
1537 transparency and 1 is opaque.  */)
1538      (color, alpha)
1539      Lisp_Object color;
1540      Lisp_Object alpha;
1542   NSColor *col;
1543   float a;
1545   CHECK_STRING (color);
1546   CHECK_NUMBER_OR_FLOAT (alpha);
1548   if (ns_lisp_to_color (color, &col))
1549     error ("Unknown color.");
1551   a = XFLOATINT (alpha);
1552   if (a < 0.0 || a > 1.0)
1553     error ("Alpha value should be between 0 and 1 inclusive.");
1555   col = [col colorWithAlphaComponent: a];
1556   return ns_color_to_lisp (col);
1560 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
1561        Sx_server_max_request_size,
1562        0, 1, 0,
1563        doc: /* This function is a no-op.  It is only present for completeness.  */)
1564      (display)
1565      Lisp_Object display;
1567   check_ns ();
1568   /* This function has no real equivalent under NeXTstep.  Return nil to
1569      indicate this. */
1570   return Qnil;
1574 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
1575        doc: /* Return the vendor ID string of Nextstep display server DISPLAY.
1576 DISPLAY should be either a frame or a display name (a string).
1577 If omitted or nil, the selected frame's display is used.  */)
1578      (display)
1579      Lisp_Object display;
1581   check_ns ();
1582 #ifdef NS_IMPL_GNUSTEP
1583   return build_string ("GNU");
1584 #else
1585   return build_string ("Apple");
1586 #endif
1590 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
1591        doc: /* Return the version number of Nextstep display server DISPLAY.
1592 DISPLAY should be either a frame or a display name (a string).
1593 If omitted or nil, the selected frame's display is used.
1594 See also the function `ns-server-vendor'.  */)
1595      (display)
1596      Lisp_Object display;
1598   /* FIXME: return GUI version on GNUSTEP, ?? on OS X */
1599   return build_string ("1.0");
1603 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
1604        doc: /* Return the number of screens on Nextstep display server DISPLAY.
1605 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1606 If omitted or nil, the selected frame's display is used.  */)
1607      (display)
1608      Lisp_Object display;
1610   int num;
1612   check_ns ();
1613   num = [[NSScreen screens] count];
1615   return (num != 0) ? make_number (num) : Qnil;
1619 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height,
1620        0, 1, 0,
1621        doc: /* Return the height of Nextstep display server DISPLAY, in millimeters.
1622 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1623 If omitted or nil, the selected frame's display is used.  */)
1624      (display)
1625      Lisp_Object display;
1627   check_ns ();
1628   return make_number ((int)
1629                      ([ns_get_screen (display) frame].size.height/(92.0/25.4)));
1633 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width,
1634        0, 1, 0,
1635        doc: /* Return the width of Nextstep display server DISPLAY, in millimeters.
1636 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1637 If omitted or nil, the selected frame's display is used.  */)
1638      (display)
1639      Lisp_Object display;
1641   check_ns ();
1642   return make_number ((int)
1643                      ([ns_get_screen (display) frame].size.width/(92.0/25.4)));
1647 DEFUN ("x-display-backing-store", Fx_display_backing_store,
1648        Sx_display_backing_store, 0, 1, 0,
1649        doc: /* Return whether the Nexstep display DISPLAY supports backing store.
1650 The value may be `buffered', `retained', or `non-retained'.
1651 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1652 If omitted or nil, the selected frame's display is used.  */)
1653      (display)
1654      Lisp_Object display;
1656   check_ns ();
1657   switch ([ns_get_window (display) backingType])
1658     {
1659     case NSBackingStoreBuffered:
1660       return intern ("buffered");
1661     case NSBackingStoreRetained:
1662       return intern ("retained");
1663     case NSBackingStoreNonretained:
1664       return intern ("non-retained");
1665     default:
1666       error ("Strange value for backingType parameter of frame");
1667     }
1668   return Qnil;  /* not reached, shut compiler up */
1672 DEFUN ("x-display-visual-class", Fx_display_visual_class,
1673        Sx_display_visual_class, 0, 1, 0,
1674        doc: /* Return the visual class of the Nextstep display server DISPLAY.
1675 The value is one of the symbols `static-gray', `gray-scale',
1676 `static-color', `pseudo-color', `true-color', or `direct-color'.
1677 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1678 If omitted or nil, the selected frame's display is used.  */)
1679      (display)
1680      Lisp_Object display;
1682   NSWindowDepth depth;
1683   check_ns ();
1684   depth = [ns_get_screen (display) depth];
1686   if ( depth == NSBestDepth (NSCalibratedWhiteColorSpace, 2, 2, YES, NULL))
1687     return intern ("static-gray");
1688   else if (depth == NSBestDepth (NSCalibratedWhiteColorSpace, 8, 8, YES, NULL))
1689     return intern ("gray-scale");
1690   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 8, YES, NULL))
1691     return intern ("pseudo-color");
1692   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 4, 12, NO, NULL))
1693     return intern ("true-color");
1694   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 24, NO, NULL))
1695     return intern ("direct-color");
1696   else
1697     /* color mgmt as far as we do it is really handled by Nextstep itself anyway */
1698     return intern ("direct-color");
1702 DEFUN ("x-display-save-under", Fx_display_save_under,
1703        Sx_display_save_under, 0, 1, 0,
1704        doc: /* Non-nil if the Nextstep display server supports the save-under feature.
1705 The optional argument DISPLAY specifies which display to ask about.
1706 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1707 If omitted or nil, the selected frame's display is used.  */)
1708      (display)
1709      Lisp_Object display;
1711   check_ns ();
1712   switch ([ns_get_window (display) backingType])
1713     {
1714     case NSBackingStoreBuffered:
1715       return Qt;
1717     case NSBackingStoreRetained:
1718     case NSBackingStoreNonretained:
1719       return Qnil;
1721     default:
1722       error ("Strange value for backingType parameter of frame");
1723     }
1724   return Qnil;  /* not reached, shut compiler up */
1728 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
1729        1, 3, 0,
1730        doc: /* Open a connection to a Nextstep display server.
1731 DISPLAY is the name of the display to connect to.
1732 Optional arguments XRM-STRING and MUST-SUCCEED are currently ignored.  */)
1733      (display, resource_string, must_succeed)
1734      Lisp_Object display, resource_string, must_succeed;
1736   struct ns_display_info *dpyinfo;
1738   CHECK_STRING (display);
1740   nxatoms_of_nsselect ();
1741   dpyinfo = ns_term_init (display);
1742   if (dpyinfo == 0)
1743     {
1744       if (!NILP (must_succeed))
1745         fatal ("OpenStep on %s not responding.\n",
1746                SDATA (display));
1747       else
1748         error ("OpenStep on %s not responding.\n",
1749                SDATA (display));
1750     }
1752   /* Register our external input/output types, used for determining
1753      applicable services and also drag/drop eligibility. */
1754   ns_send_types = [[NSArray arrayWithObject: NSStringPboardType] retain];
1755   ns_return_types = [[NSArray arrayWithObject: NSStringPboardType] retain];
1756   ns_drag_types = [[NSArray arrayWithObjects:
1757                             NSStringPboardType,
1758                             NSTabularTextPboardType,
1759                             NSFilenamesPboardType,
1760                             NSURLPboardType,
1761                             NSColorPboardType,
1762                             NSFontPboardType, nil] retain];
1764   return Qnil;
1768 DEFUN ("x-close-connection", Fx_close_connection, Sx_close_connection,
1769        1, 1, 0,
1770        doc: /* Close the connection to the current Nextstep display server.
1771 The second argument DISPLAY is currently ignored.  */)
1772      (display)
1773      Lisp_Object display;
1775   check_ns ();
1776 #ifdef NS_IMPL_COCOA
1777   PSFlush ();
1778 #endif
1779   /*ns_delete_terminal (dpyinfo->terminal); */
1780   [NSApp terminate: NSApp];
1781   return Qnil;
1785 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
1786        doc: /* Return the list of display names that Emacs has connections to.  */)
1787      ()
1789   Lisp_Object tail, result;
1791   result = Qnil;
1792   for (tail = ns_display_name_list; CONSP (tail); tail = XCDR (tail))
1793     result = Fcons (XCAR (XCAR (tail)), result);
1795   return result;
1799 DEFUN ("ns-hide-others", Fns_hide_others, Sns_hide_others,
1800        0, 0, 0,
1801        doc: /* Hides all applications other than emacs.  */)
1802      ()
1804   check_ns ();
1805   [NSApp hideOtherApplications: NSApp];
1806   return Qnil;
1809 DEFUN ("ns-hide-emacs", Fns_hide_emacs, Sns_hide_emacs,
1810        1, 1, 0,
1811        doc: /* If ON is non-nil, the entire emacs application is hidden.
1812 Otherwise if emacs is hidden, it is unhidden.
1813 If ON is equal to `activate', emacs is unhidden and becomes
1814 the active application.  */)
1815      (on)
1816      Lisp_Object on;
1818   check_ns ();
1819   if (EQ (on, intern ("activate")))
1820     {
1821       [NSApp unhide: NSApp];
1822       [NSApp activateIgnoringOtherApps: YES];
1823     }
1824   else if (NILP (on))
1825     [NSApp unhide: NSApp];
1826   else
1827     [NSApp hide: NSApp];
1828   return Qnil;
1832 DEFUN ("ns-emacs-info-panel", Fns_emacs_info_panel, Sns_emacs_info_panel,
1833        0, 0, 0,
1834        doc: /* Shows the 'Info' or 'About' panel for Emacs.  */)
1835      ()
1837   check_ns ();
1838   [NSApp orderFrontStandardAboutPanel: nil];
1839   return Qnil;
1843 DEFUN ("ns-font-name", Fns_font_name, Sns_font_name, 1, 1, 0,
1844        doc: /* Determine font postscript or family name for font NAME.
1845 NAME should be a string containing either the font name or an XLFD
1846 font descriptor.  If string contains `fontset' and not
1847 `fontset-startup', it is left alone. */)
1848      (name)
1849      Lisp_Object name;
1851   char *nm;
1852   CHECK_STRING (name);
1853   nm = SDATA (name);
1855   if (nm[0] != '-')
1856     return name;
1857   if (strstr (nm, "fontset") && !strstr (nm, "fontset-startup"))
1858     return name;
1860   return build_string (ns_xlfd_to_fontname (SDATA (name)));
1864 DEFUN ("ns-list-colors", Fns_list_colors, Sns_list_colors, 0, 1, 0,
1865        doc: /* Return a list of all available colors.
1866 The optional argument FRAME is currently ignored.  */)
1867      (frame)
1868      Lisp_Object frame;
1870   Lisp_Object list = Qnil;
1871   NSEnumerator *colorlists;
1872   NSColorList *clist;
1874   if (!NILP (frame))
1875     {
1876       CHECK_FRAME (frame);
1877       if (! FRAME_NS_P (XFRAME (frame)))
1878         error ("non-Nextstep frame used in `ns-list-colors'");
1879     }
1881   BLOCK_INPUT;
1883   colorlists = [[NSColorList availableColorLists] objectEnumerator];
1884   while (clist = [colorlists nextObject])
1885     {
1886       if ([[clist name] length] < 7 ||
1887           [[clist name] rangeOfString: @"PANTONE"].location == 0)
1888         {
1889           NSEnumerator *cnames = [[clist allKeys] reverseObjectEnumerator];
1890           NSString *cname;
1891           while (cname = [cnames nextObject])
1892             list = Fcons (build_string ([cname UTF8String]), list);
1893 /*           for (i = [[clist allKeys] count] - 1; i >= 0; i--)
1894                list = Fcons (build_string ([[[clist allKeys] objectAtIndex: i]
1895                                              UTF8String]), list); */
1896         }
1897     }
1899   UNBLOCK_INPUT;
1901   return list;
1905 DEFUN ("ns-list-services", Fns_list_services, Sns_list_services, 0, 0, 0,
1906        doc: /* List available Nextstep services by querying NSApp.  */)
1907      ()
1909   Lisp_Object ret = Qnil;
1910   NSMenu *svcs;
1911   id delegate;
1913   check_ns ();
1914   svcs = [[NSMenu alloc] initWithTitle: @"Services"];
1915   [NSApp setServicesMenu: svcs];  /* this and next rebuild on <10.4 */
1916   [NSApp registerServicesMenuSendTypes: ns_send_types
1917                            returnTypes: ns_return_types];
1919 /* On Tiger, services menu updating was made lazier (waits for user to
1920    actually click on the menu), so we have to force things along: */
1921 #ifdef NS_IMPL_COCOA
1922   if (NSAppKitVersionNumber >= 744.0)
1923     {
1924       delegate = [svcs delegate];
1925       if (delegate != nil)
1926         {
1927           if ([delegate respondsToSelector: @selector (menuNeedsUpdate:)])
1928               [delegate menuNeedsUpdate: svcs];
1929           if ([delegate respondsToSelector:
1930                             @selector (menu:updateItem:atIndex:shouldCancel:)])
1931             {
1932               int i, len = [delegate numberOfItemsInMenu: svcs];
1933               for (i =0; i<len; i++)
1934                   [svcs addItemWithTitle: @"" action: NULL keyEquivalent: @""];
1935               for (i =0; i<len; i++)
1936                   if (![delegate menu: svcs
1937                            updateItem: (NSMenuItem *)[svcs itemAtIndex: i]
1938                               atIndex: i shouldCancel: NO])
1939                     break;
1940             }
1941         }
1942     }
1943 #endif
1945   [svcs setAutoenablesItems: NO];
1946 #ifdef NS_IMPL_COCOA
1947   [svcs update]; /* on OS X, converts from '/' structure */
1948 #endif
1950   ret = interpret_services_menu (svcs, Qnil, ret);
1951   return ret;
1955 DEFUN ("ns-perform-service", Fns_perform_service, Sns_perform_service,
1956        2, 2, 0,
1957        doc: /* Perform Nextstep SERVICE on SEND.
1958 SEND should be either a string or nil.
1959 The return value is the result of the service, as string, or nil if
1960 there was no result.  */)
1961      (service, send)
1962      Lisp_Object service, send;
1964   id pb;
1965   NSString *svcName;
1966   char *utfStr;
1967   int len;
1969   CHECK_STRING (service);
1970   check_ns ();
1972   utfStr = SDATA (service);
1973   svcName = [NSString stringWithUTF8String: utfStr];
1975   pb =[NSPasteboard pasteboardWithUniqueName];
1976   ns_string_to_pasteboard (pb, send);
1978   if (NSPerformService (svcName, pb) == NO)
1979     Fsignal (Qquit, Fcons (build_string ("service not available"), Qnil));
1981   if ([[pb types] count] == 0)
1982     return build_string ("");
1983   return ns_string_from_pasteboard (pb);
1987 DEFUN ("ns-convert-utf8-nfd-to-nfc", Fns_convert_utf8_nfd_to_nfc,
1988        Sns_convert_utf8_nfd_to_nfc, 1, 1, 0,
1989        doc: /* Return an NFC string that matches  the UTF-8 NFD string STR.  */)
1990     (str)
1991     Lisp_Object str;
1993   NSString *utfStr;
1995   CHECK_STRING (str);
1996   utfStr = [[NSString stringWithUTF8String: SDATA (str)]
1997              precomposedStringWithCanonicalMapping];
1998   return build_string ([utfStr UTF8String]);
2002 /* ==========================================================================
2004     Miscellaneous functions not called through hooks
2006    ========================================================================== */
2009 /* 23: call in image.c */
2010 FRAME_PTR
2011 check_x_frame (Lisp_Object frame)
2013   return check_ns_frame (frame);
2016 /* 23: added, due to call in frame.c */
2017 struct ns_display_info *
2018 check_x_display_info (Lisp_Object frame)
2020   return check_ns_display_info (frame);
2024 /* 23: new function; we don't have much in the way of flexibility though */
2025 void
2026 x_set_scroll_bar_default_width (f)
2027      struct frame *f;
2029   int wid = FRAME_COLUMN_WIDTH (f);
2030   FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = NS_SCROLL_BAR_WIDTH_DEFAULT;
2031   FRAME_CONFIG_SCROLL_BAR_COLS (f) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) +
2032                                       wid - 1) / wid;
2036 /* 23: terms now impl this instead of x-get-resource directly */
2037 const char *
2038 x_get_string_resource (XrmDatabase rdb, char *name, char *class)
2040   /* remove appname prefix; TODO: allow for !="Emacs" */
2041   char *toCheck = class + (!strncmp (class, "Emacs.", 6) ? 6 : 0);
2042   const char *res;
2043   check_ns ();
2045   /* Support emacs-20-style face resources for backwards compatibility */
2046   if (!strncmp (toCheck, "Face", 4))
2047     toCheck = name + (!strncmp (name, "emacs.", 6) ? 6 : 0);
2049 /*fprintf (stderr, "Checking '%s'\n", toCheck); */
2050   
2051   res = [[[NSUserDefaults standardUserDefaults] objectForKey:
2052                    [NSString stringWithUTF8String: toCheck]] UTF8String];
2053   return !res ? NULL :
2054       (!strncasecmp (res, "YES", 3) ? "true" :
2055           (!strncasecmp (res, "NO", 2) ? "false" : res));
2059 Lisp_Object
2060 x_get_focus_frame (struct frame *frame)
2062   struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (frame);
2063   Lisp_Object nsfocus;
2065   if (!dpyinfo->x_focus_frame)
2066     return Qnil;
2068   XSETFRAME (nsfocus, dpyinfo->x_focus_frame);
2069   return nsfocus;
2074 x_pixel_width (struct frame *f)
2076   return FRAME_PIXEL_WIDTH (f);
2081 x_pixel_height (struct frame *f)
2083   return FRAME_PIXEL_HEIGHT (f);
2088 x_char_width (struct frame *f)
2090   return FRAME_COLUMN_WIDTH (f);
2095 x_char_height (struct frame *f)
2097   return FRAME_LINE_HEIGHT (f);
2102 x_screen_planes (struct frame *f)
2104   return FRAME_NS_DISPLAY_INFO (f)->n_planes;
2108 void
2109 x_sync (Lisp_Object frame)
2111   /* XXX Not implemented XXX */
2112   return;
2117 /* ==========================================================================
2119     Lisp definitions that, for whatever reason, we can't alias as 'ns-XXX'.
2121    ========================================================================== */
2124 #ifdef NS_IMPL_COCOA
2126 /* Compile and execute the AppleScript SCRIPT and return the error
2127    status as function value.  A zero is returned if compilation and
2128    execution is successful, in which case *RESULT is set to a Lisp
2129    string or a number containing the resulting script value.  Otherwise,
2130    1 is returned. */
2132 static int
2133 do_applescript (script, result)
2134      Lisp_Object script, *result;
2136   NSAppleEventDescriptor *desc;
2137   NSDictionary* errorDict;
2138   NSAppleEventDescriptor* returnDescriptor = NULL;
2140   NSAppleScript* scriptObject =
2141     [[NSAppleScript alloc] initWithSource:
2142                              [NSString stringWithUTF8String: SDATA (script)]];
2144   returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
2145   [scriptObject release];
2146   
2147   *result = Qnil;
2148   
2149   if (returnDescriptor != NULL)
2150     {
2151       // successful execution
2152       if (kAENullEvent != [returnDescriptor descriptorType])
2153         {
2154           *result = Qt;
2155           // script returned an AppleScript result
2156           if ((typeUnicodeText == [returnDescriptor descriptorType]) ||
2157               (typeUTF16ExternalRepresentation 
2158                == [returnDescriptor descriptorType]) ||
2159               (typeUTF8Text == [returnDescriptor descriptorType]) ||
2160               (typeCString == [returnDescriptor descriptorType]))
2161             {
2162               desc = [returnDescriptor coerceToDescriptorType: typeUTF8Text];
2163               if (desc)
2164                 *result = build_string([[desc stringValue] UTF8String]);
2165             }
2166           else
2167             {
2168               /* use typeUTF16ExternalRepresentation? */
2169               // coerce the result to the appropriate ObjC type
2170               desc = [returnDescriptor coerceToDescriptorType: typeUTF8Text];
2171               if (desc)
2172                 *result = make_number([desc int32Value]);
2173             }
2174         }
2175     }
2176   else
2177     {
2178       // no script result, return error
2179       return 1;
2180     }
2181   return 0;
2184 DEFUN ("do-applescript", Fdo_applescript, Sdo_applescript, 1, 1, 0,
2185        doc: /* Execute AppleScript SCRIPT and return the result.  If
2186 compilation and execution are successful, the resulting script value
2187 is returned as a string, a number or, in the case of other constructs,
2188 t.  In case the execution fails, an error is signaled. */)
2189     (script)
2190     Lisp_Object script;
2192   Lisp_Object result;
2193   long status;
2195   CHECK_STRING (script);
2196   check_ns ();
2198   BLOCK_INPUT;
2199   status = do_applescript (script, &result);
2200   UNBLOCK_INPUT;
2201   if (status == 0)
2202     return result;
2203   else if (!STRINGP (result))
2204     error ("AppleScript error %d", status);
2205   else
2206     error ("%s", SDATA (result));
2208 #endif
2210 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
2211        doc: /* Return t if the current Nextstep display supports the color COLOR.
2212 The optional argument FRAME is currently ignored.  */)
2213      (color, frame)
2214      Lisp_Object color, frame;
2216   NSColor * col;
2217   check_ns ();
2218   return ns_lisp_to_color (color, &col) ? Qnil : Qt;
2222 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
2223        doc: /* Return a description of the color named COLOR.
2224 The value is a list of integer RGBA values--(RED GREEN BLUE ALPHA).
2225 These values appear to range from 0 to 65280; white is (65280 65280 65280 0).
2226 The optional argument FRAME is currently ignored.  */)
2227      (color, frame)
2228      Lisp_Object color, frame;
2230   NSColor * col;
2231   float red, green, blue, alpha;
2232   Lisp_Object rgba[4];
2234   check_ns ();
2235   CHECK_STRING (color);
2237   if (ns_lisp_to_color (color, &col))
2238     return Qnil;
2240   [[col colorUsingColorSpaceName: NSCalibratedRGBColorSpace]
2241         getRed: &red green: &green blue: &blue alpha: &alpha];
2242   rgba[0] = make_number (lrint (red*65280));
2243   rgba[1] = make_number (lrint (green*65280));
2244   rgba[2] = make_number (lrint (blue*65280));
2245   rgba[3] = make_number (lrint (alpha*65280));
2247   return Flist (4, rgba);
2251 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
2252        doc: /* Return t if the Nextstep display supports color.
2253 The optional argument DISPLAY specifies which display to ask about.
2254 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2255 If omitted or nil, that stands for the selected frame's display.  */)
2256      (display)
2257      Lisp_Object display;
2259   NSWindowDepth depth;
2260   NSString *colorSpace;
2261   check_ns ();
2262   depth = [ns_get_screen (display) depth];
2263   colorSpace = NSColorSpaceFromDepth (depth);
2265   return    [colorSpace isEqualToString: NSDeviceWhiteColorSpace]
2266          || [colorSpace isEqualToString: NSCalibratedWhiteColorSpace]
2267       ? Qnil : Qt;
2271 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p,
2272        Sx_display_grayscale_p, 0, 1, 0,
2273        doc: /* Return t if the Nextstep display supports shades of gray.
2274 Note that color displays do support shades of gray.
2275 The optional argument DISPLAY specifies which display to ask about.
2276 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2277 If omitted or nil, that stands for the selected frame's display. */)
2278      (display)
2279      Lisp_Object display;
2281   NSWindowDepth depth;
2282   check_ns ();
2283   depth = [ns_get_screen (display) depth];
2285   return NSBitsPerPixelFromDepth (depth) > 1 ? Qt : Qnil;
2289 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
2290        0, 1, 0,
2291        doc: /* Returns the width in pixels of the Nextstep display DISPLAY.
2292 The optional argument DISPLAY specifies which display to ask about.
2293 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2294 If omitted or nil, that stands for the selected frame's display.  */)
2295      (display)
2296      Lisp_Object display;
2298   check_ns ();
2299   return make_number ((int) [ns_get_screen (display) frame].size.width);
2303 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
2304        Sx_display_pixel_height, 0, 1, 0,
2305        doc: /* Returns the height in pixels of the Nextstep display DISPLAY.
2306 The optional argument DISPLAY specifies which display to ask about.
2307 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2308 If omitted or nil, that stands for the selected frame's display.  */)
2309      (display)
2310      Lisp_Object display;
2312   check_ns ();
2313   return make_number ((int) [ns_get_screen (display) frame].size.height);
2316 DEFUN ("display-usable-bounds", Fns_display_usable_bounds,
2317        Sns_display_usable_bounds, 0, 1, 0,
2318        doc: /*Return the bounds of the usable part of the screen.
2319 The return value is a list of integers (LEFT TOP WIDTH HEIGHT), which
2320 are the boundaries of the usable part of the screen, excluding areas
2321 reserved for the Mac menu, dock, and so forth.
2323 The screen queried corresponds to DISPLAY, which should be either a
2324 frame, a display name (a string), or terminal ID.  If omitted or nil,
2325 that stands for the selected frame's display. */)
2326      (display)
2327      Lisp_Object display;
2329   int top;
2330   NSRect vScreen;
2332   check_ns ();
2333   vScreen = [ns_get_screen (display) visibleFrame];
2334   top = vScreen.origin.y == 0.0 ?
2335     (int) [ns_get_screen (display) frame].size.height - vScreen.size.height : 0;
2337   return list4 (make_number ((int) vScreen.origin.x),
2338                 make_number (top),
2339                 make_number ((int) vScreen.size.width),
2340                 make_number ((int) vScreen.size.height));
2344 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
2345        0, 1, 0,
2346        doc: /* Returns the number of bitplanes of the Nextstep display DISPLAY.
2347 The optional argument DISPLAY specifies which display to ask about.
2348 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2349 If omitted or nil, that stands for the selected frame's display.  */)
2350      (display)
2351      Lisp_Object display;
2353   check_ns ();
2354   return make_number
2355     (NSBitsPerSampleFromDepth ([ns_get_screen (display) depth]));
2359 DEFUN ("x-display-color-cells", Fx_display_color_cells,
2360        Sx_display_color_cells, 0, 1, 0,
2361        doc: /* Returns the number of color cells of the Nextstep display DISPLAY.
2362 The optional argument DISPLAY specifies which display to ask about.
2363 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2364 If omitted or nil, that stands for the selected frame's display.  */)
2365      (display)
2366      Lisp_Object display;
2368   check_ns ();
2369   struct ns_display_info *dpyinfo = check_ns_display_info (display);
2371   /* We force 24+ bit depths to 24-bit to prevent an overflow.  */
2372   return make_number (1 << min (dpyinfo->n_planes, 24));
2376 /* Unused dummy def needed for compatibility. */
2377 Lisp_Object tip_frame;
2379 /* TODO: move to xdisp or similar */
2380 static void
2381 compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
2382      struct frame *f;
2383      Lisp_Object parms, dx, dy;
2384      int width, height;
2385      int *root_x, *root_y;
2387   Lisp_Object left, top;
2388   EmacsView *view = FRAME_NS_VIEW (f);
2389   NSPoint pt;
2390   
2391   /* Start with user-specified or mouse position.  */
2392   left = Fcdr (Fassq (Qleft, parms));
2393   if (INTEGERP (left))
2394     pt.x = XINT (left);
2395   else
2396     pt.x = last_mouse_motion_position.x;
2397   top = Fcdr (Fassq (Qtop, parms));
2398   if (INTEGERP (top))
2399     pt.y = XINT (top);
2400   else
2401     pt.y = last_mouse_motion_position.y;
2403   /* Convert to screen coordinates */
2404   pt = [view convertPoint: pt toView: nil];
2405   pt = [[view window] convertBaseToScreen: pt];
2407   /* Ensure in bounds.  (Note, screen origin = lower left.) */
2408   if (pt.x + XINT (dx) <= 0)
2409     *root_x = 0; /* Can happen for negative dx */
2410   else if (pt.x + XINT (dx) + width <= FRAME_NS_DISPLAY_INFO (f)->width)
2411     /* It fits to the right of the pointer.  */
2412     *root_x = pt.x + XINT (dx);
2413   else if (width + XINT (dx) <= pt.x)
2414     /* It fits to the left of the pointer.  */
2415     *root_x = pt.x - width - XINT (dx);
2416   else
2417     /* Put it left justified on the screen -- it ought to fit that way.  */
2418     *root_x = 0;
2420   if (pt.y - XINT (dy) - height >= 0)
2421     /* It fits below the pointer.  */
2422     *root_y = pt.y - height - XINT (dy);
2423   else if (pt.y + XINT (dy) + height <= FRAME_NS_DISPLAY_INFO (f)->height)
2424     /* It fits above the pointer */
2425       *root_y = pt.y + XINT (dy);
2426   else
2427     /* Put it on the top.  */
2428     *root_y = FRAME_NS_DISPLAY_INFO (f)->height - height;
2432 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
2433        doc: /* Show STRING in a "tooltip" window on frame FRAME.
2434 A tooltip window is a small window displaying a string.
2436 FRAME nil or omitted means use the selected frame.
2438 PARMS is an optional list of frame parameters which can be used to
2439 change the tooltip's appearance.
2441 Automatically hide the tooltip after TIMEOUT seconds.  TIMEOUT nil
2442 means use the default timeout of 5 seconds.
2444 If the list of frame parameters PARMS contains a `left' parameter,
2445 the tooltip is displayed at that x-position.  Otherwise it is
2446 displayed at the mouse position, with offset DX added (default is 5 if
2447 DX isn't specified).  Likewise for the y-position; if a `top' frame
2448 parameter is specified, it determines the y-position of the tooltip
2449 window, otherwise it is displayed at the mouse position, with offset
2450 DY added (default is -10).
2452 A tooltip's maximum size is specified by `x-max-tooltip-size'.
2453 Text larger than the specified size is clipped.  */)
2454      (string, frame, parms, timeout, dx, dy)
2455      Lisp_Object string, frame, parms, timeout, dx, dy;
2457   int root_x, root_y;
2458   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2459   int count = SPECPDL_INDEX ();
2460   struct frame *f;
2461   char *str;
2462   NSSize size;
2464   specbind (Qinhibit_redisplay, Qt);
2466   GCPRO4 (string, parms, frame, timeout);
2468   CHECK_STRING (string);
2469   str = SDATA (string);
2470   f = check_x_frame (frame);
2471   if (NILP (timeout))
2472     timeout = make_number (5);
2473   else
2474     CHECK_NATNUM (timeout);
2476   if (NILP (dx))
2477     dx = make_number (5);
2478   else
2479     CHECK_NUMBER (dx);
2481   if (NILP (dy))
2482     dy = make_number (-10);
2483   else
2484     CHECK_NUMBER (dy);
2486   BLOCK_INPUT;
2487   if (ns_tooltip == nil)
2488     ns_tooltip = [[EmacsTooltip alloc] init];
2489   else
2490     Fx_hide_tip ();
2492   [ns_tooltip setText: str];
2493   size = [ns_tooltip frame].size;
2495   /* Move the tooltip window where the mouse pointer is.  Resize and
2496      show it.  */
2497   compute_tip_xy (f, parms, dx, dy, (int)size.width, (int)size.height,
2498                   &root_x, &root_y);
2500   [ns_tooltip showAtX: root_x Y: root_y for: XINT (timeout)];
2501   UNBLOCK_INPUT;
2503   UNGCPRO;
2504   return unbind_to (count, Qnil);
2508 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
2509        doc: /* Hide the current tooltip window, if there is any.
2510 Value is t if tooltip was open, nil otherwise.  */)
2511      ()
2513   if (ns_tooltip == nil || ![ns_tooltip isActive])
2514     return Qnil;
2515   [ns_tooltip hide];
2516   return Qt;
2520 /* ==========================================================================
2522     Class implementations
2524    ========================================================================== */
2527 @implementation EmacsSavePanel
2528 #ifdef NS_IMPL_COCOA
2529 /* --------------------------------------------------------------------------
2530    These are overridden to intercept on OS X: ending panel restarts NSApp
2531    event loop if it is stopped.  Not sure if this is correct behavior,
2532    perhaps should check if running and if so send an appdefined.
2533    -------------------------------------------------------------------------- */
2534 - (void) ok: (id)sender
2536   [super ok: sender];
2537   panelOK = 1;
2538   [NSApp stop: self];
2540 - (void) cancel: (id)sender
2542   [super cancel: sender];
2543   [NSApp stop: self];
2545 #endif
2546 @end
2549 @implementation EmacsOpenPanel
2550 #ifdef NS_IMPL_COCOA
2551 /* --------------------------------------------------------------------------
2552    These are overridden to intercept on OS X: ending panel restarts NSApp
2553    event loop if it is stopped.  Not sure if this is correct behavior,
2554    perhaps should check if running and if so send an appdefined.
2555    -------------------------------------------------------------------------- */
2556 - (void) ok: (id)sender
2558   [super ok: sender];
2559   panelOK = 1;
2560   [NSApp stop: self];
2562 - (void) cancel: (id)sender
2564   [super cancel: sender];
2565   [NSApp stop: self];
2567 #endif
2568 @end
2571 @implementation EmacsFileDelegate
2572 /* --------------------------------------------------------------------------
2573    Delegate methods for Open/Save panels
2574    -------------------------------------------------------------------------- */
2575 - (BOOL)panel: (id)sender isValidFilename: (NSString *)filename
2577   return YES;
2579 - (BOOL)panel: (id)sender shouldShowFilename: (NSString *)filename
2581   return YES;
2583 - (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename
2584           confirmed: (BOOL)okFlag
2586   return filename;
2588 @end
2590 #endif
2592 /* ==========================================================================
2594     Lisp interface declaration
2596    ========================================================================== */
2599 void
2600 syms_of_nsfns ()
2602   int i;
2604   Qns_frame_parameter = intern ("ns-frame-parameter");
2605   staticpro (&Qns_frame_parameter);
2606   Qnone = intern ("none");
2607   staticpro (&Qnone);
2608   Qbuffered = intern ("bufferd");
2609   staticpro (&Qbuffered);
2610   Qfontsize = intern ("fontsize");
2611   staticpro (&Qfontsize);
2613   DEFVAR_LISP ("ns-icon-type-alist", &Vns_icon_type_alist,
2614                doc: /* Alist of elements (REGEXP . IMAGE) for images of icons associated to frames.
2615 If the title of a frame matches REGEXP, then IMAGE.tiff is
2616 selected as the image of the icon representing the frame when it's
2617 miniaturized.  If an element is t, then Emacs tries to select an icon
2618 based on the filetype of the visited file.
2620 The images have to be installed in a folder called English.lproj in the
2621 Emacs folder.  You have to restart Emacs after installing new icons.
2623 Example: Install an icon Gnus.tiff and execute the following code
2625   (setq ns-icon-type-alist
2626         (append ns-icon-type-alist
2627                 '((\"^\\\\*\\\\(Group\\\\*$\\\\|Summary \\\\|Article\\\\*$\\\\)\"
2628                    . \"Gnus\"))))
2630 When you miniaturize a Group, Summary or Article frame, Gnus.tiff will
2631 be used as the image of the icon representing the frame.  */);
2632   Vns_icon_type_alist = Fcons (Qt, Qnil);
2634   defsubr (&Sns_read_file_name);
2635   defsubr (&Sns_get_resource);
2636   defsubr (&Sns_set_resource);
2637   defsubr (&Sxw_display_color_p); /* this and next called directly by C code */
2638   defsubr (&Sx_display_grayscale_p);
2639   defsubr (&Sns_font_name);
2640   defsubr (&Sns_list_colors);
2641 #ifdef NS_IMPL_COCOA
2642   defsubr (&Sdo_applescript);
2643 #endif
2644   defsubr (&Sxw_color_defined_p);
2645   defsubr (&Sxw_color_values);
2646   defsubr (&Sx_server_max_request_size);
2647   defsubr (&Sx_server_vendor);
2648   defsubr (&Sx_server_version);
2649   defsubr (&Sx_display_pixel_width);
2650   defsubr (&Sx_display_pixel_height);
2651   defsubr (&Sns_display_usable_bounds);
2652   defsubr (&Sx_display_mm_width);
2653   defsubr (&Sx_display_mm_height);
2654   defsubr (&Sx_display_screens);
2655   defsubr (&Sx_display_planes);
2656   defsubr (&Sx_display_color_cells);
2657   defsubr (&Sx_display_visual_class);
2658   defsubr (&Sx_display_backing_store);
2659   defsubr (&Sx_display_save_under);
2660   defsubr (&Sx_create_frame);
2661   defsubr (&Sns_set_alpha);
2662   defsubr (&Sx_open_connection);
2663   defsubr (&Sx_close_connection);
2664   defsubr (&Sx_display_list);
2666   defsubr (&Sns_hide_others);
2667   defsubr (&Sns_hide_emacs);
2668   defsubr (&Sns_emacs_info_panel);
2669   defsubr (&Sns_list_services);
2670   defsubr (&Sns_perform_service);
2671   defsubr (&Sns_convert_utf8_nfd_to_nfc);
2672   defsubr (&Sx_focus_frame);
2673   defsubr (&Sns_popup_prefs_panel);
2674   defsubr (&Sns_popup_font_panel);
2675   defsubr (&Sns_popup_color_panel);
2677   defsubr (&Sx_show_tip);
2678   defsubr (&Sx_hide_tip);
2680   /* used only in fontset.c */
2681   check_window_system_func = check_ns;
2685 // arch-tag: dc2a3f74-1123-4daa-8eed-fb78db6a5642