lisp/cedet/ChangeLog: Move entries for emacs-lisp/ files back to lisp/ChangeLog.
[emacs.git] / src / nsfns.m
blobdb8bbeb5f765ea598b3ab60b60952a69883cc14e
1 /* Functions for the NeXT/Open/GNUstep and MacOSX window system.
2    Copyright (C) 1989, 1992, 1993, 1994, 2005, 2006, 2008, 2009, 2010
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 /* This should be the first include, as it may set up #defines affecting
29    interpretation of even the system includes. */
30 #include <config.h>
32 #include <signal.h>
33 #include <math.h>
34 #include <setjmp.h>
36 #include "lisp.h"
37 #include "blockinput.h"
38 #include "nsterm.h"
39 #include "window.h"
40 #include "buffer.h"
41 #include "keyboard.h"
42 #include "termhooks.h"
43 #include "fontset.h"
44 #include "character.h"
45 #include "font.h"
47 #if 0
48 int fns_trace_num = 1;
49 #define NSTRACE(x)        fprintf (stderr, "%s:%d: [%d] " #x "\n",        \
50                                   __FILE__, __LINE__, ++fns_trace_num)
51 #else
52 #define NSTRACE(x)
53 #endif
55 #ifdef HAVE_NS
57 extern NSArray *ns_send_types, *ns_return_types, *ns_drag_types;
59 extern Lisp_Object Qforeground_color;
60 extern Lisp_Object Qbackground_color;
61 extern Lisp_Object Qcursor_color;
62 extern Lisp_Object Qinternal_border_width;
63 extern Lisp_Object Qvisibility;
64 extern Lisp_Object Qcursor_type;
65 extern Lisp_Object Qicon_type;
66 extern Lisp_Object Qicon_name;
67 extern Lisp_Object Qicon_left;
68 extern Lisp_Object Qicon_top;
69 extern Lisp_Object Qleft;
70 extern Lisp_Object Qright;
71 extern Lisp_Object Qtop;
72 extern Lisp_Object Qdisplay;
73 extern Lisp_Object Qvertical_scroll_bars;
74 extern Lisp_Object Qauto_raise;
75 extern Lisp_Object Qauto_lower;
76 extern Lisp_Object Qbox;
77 extern Lisp_Object Qscroll_bar_width;
78 extern Lisp_Object Qx_resource_name;
79 extern Lisp_Object Qface_set_after_frame_default;
80 extern Lisp_Object Qunderline, Qundefined;
81 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
82 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
83 extern Lisp_Object Qnone;
84 extern Lisp_Object Vframe_title_format;
86 /* The below are defined in frame.c.  */
88 extern Lisp_Object Vmenu_bar_mode, Vtool_bar_mode;
90 Lisp_Object Qbuffered;
91 Lisp_Object Qfontsize;
93 /* hack for OS X file panels */
94 char panelOK = 0;
96 /* Alist of elements (REGEXP . IMAGE) for images of icons associated
97    to frames.*/
98 static Lisp_Object Vns_icon_type_alist;
100 /* Toolkit version support. */
101 static Lisp_Object Vns_version_string;
103 EmacsTooltip *ns_tooltip;
105 /* Need forward declaration here to preserve organizational integrity of file */
106 Lisp_Object Fx_open_connection (Lisp_Object, Lisp_Object, Lisp_Object);
108 extern BOOL ns_in_resize;
111 /* ==========================================================================
113     Internal utility functions
115    ========================================================================== */
118 void
119 check_ns (void)
121  if (NSApp == nil)
122    error ("OpenStep is not in use or not initialized");
126 /* Nonzero if we can use mouse menus. */
128 have_menus_p (void)
130   return NSApp != nil;
134 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
135    and checking validity for NS.  */
136 static FRAME_PTR
137 check_ns_frame (Lisp_Object frame)
139   FRAME_PTR f;
141   if (NILP (frame))
142       f = SELECTED_FRAME ();
143   else
144     {
145       CHECK_LIVE_FRAME (frame);
146       f = XFRAME (frame);
147     }
148   if (! FRAME_NS_P (f))
149     error ("non-Nextstep frame used");
150   return f;
154 /* Let the user specify an Nextstep display with a frame.
155    nil stands for the selected frame--or, if that is not an Nextstep frame,
156    the first Nextstep display on the list.  */
157 static struct ns_display_info *
158 check_ns_display_info (Lisp_Object frame)
160   if (NILP (frame))
161     {
162       struct frame *f = SELECTED_FRAME ();
163       if (FRAME_NS_P (f) && FRAME_LIVE_P (f) )
164         return FRAME_NS_DISPLAY_INFO (f);
165       else if (x_display_list != 0)
166         return x_display_list;
167       else
168         error ("Nextstep windows are not in use or not initialized");
169     }
170   else if (INTEGERP (frame))
171     {
172       struct terminal *t = get_terminal (frame, 1);
174       if (t->type != output_ns)
175         error ("Terminal %d is not a Nextstep display", XINT (frame));
177       return t->display_info.ns;
178     }
179   else if (STRINGP (frame))
180     return ns_display_info_for_name (frame);
181   else
182     {
183       FRAME_PTR f;
185       CHECK_LIVE_FRAME (frame);
186       f = XFRAME (frame);
187       if (! FRAME_NS_P (f))
188         error ("non-Nextstep frame used");
189       return FRAME_NS_DISPLAY_INFO (f);
190     }
191   return NULL;  /* shut compiler up */
195 static id
196 ns_get_window (Lisp_Object maybeFrame)
198   id view =nil, window =nil;
200   if (!FRAMEP (maybeFrame) || !FRAME_NS_P (XFRAME (maybeFrame)))
201     maybeFrame = selected_frame;/*wrong_type_argument (Qframep, maybeFrame); */
203   if (!NILP (maybeFrame))
204     view = FRAME_NS_VIEW (XFRAME (maybeFrame));
205   if (view) window =[view window];
207   return window;
211 static NSScreen *
212 ns_get_screen (Lisp_Object screen)
214   struct frame *f;
215   struct terminal *terminal;
217   if (EQ (Qt, screen)) /* not documented */
218     return [NSScreen mainScreen];
220   terminal = get_terminal (screen, 1);
221   if (terminal->type != output_ns)
222     return NULL;
224   if (NILP (screen))
225     f = SELECTED_FRAME ();
226   else if (FRAMEP (screen))
227     f = XFRAME (screen);
228   else
229     {
230       struct ns_display_info *dpyinfo = terminal->display_info.ns;
231       f = dpyinfo->x_focus_frame
232         ? dpyinfo->x_focus_frame : dpyinfo->x_highlight_frame;
233     }
235   return ((f && FRAME_NS_P (f)) ? [[FRAME_NS_VIEW (f) window] screen]
236           : NULL);
240 /* Return the X display structure for the display named NAME.
241    Open a new connection if necessary.  */
242 struct ns_display_info *
243 ns_display_info_for_name (Lisp_Object name)
245   Lisp_Object names;
246   struct ns_display_info *dpyinfo;
248   CHECK_STRING (name);
250   for (dpyinfo = x_display_list, names = ns_display_name_list;
251        dpyinfo;
252        dpyinfo = dpyinfo->next, names = XCDR (names))
253     {
254       Lisp_Object tem;
255       tem = Fstring_equal (XCAR (XCAR (names)), name);
256       if (!NILP (tem))
257         return dpyinfo;
258     }
260   error ("Emacs for OpenStep does not yet support multi-display.");
262   Fx_open_connection (name, Qnil, Qnil);
263   dpyinfo = x_display_list;
265   if (dpyinfo == 0)
266     error ("OpenStep on %s not responding.\n", SDATA (name));
268   return dpyinfo;
272 static Lisp_Object
273 interpret_services_menu (NSMenu *menu, Lisp_Object prefix, Lisp_Object old)
274 /* --------------------------------------------------------------------------
275    Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side
276    -------------------------------------------------------------------------- */
278   int i, count;
279   NSMenuItem *item;
280   const char *name;
281   Lisp_Object nameStr;
282   unsigned short key;
283   NSString *keys;
284   Lisp_Object res;
286   count = [menu numberOfItems];
287   for (i = 0; i<count; i++)
288     {
289       item = [menu itemAtIndex: i];
290       name = [[item title] UTF8String];
291       if (!name) continue;
293       nameStr = build_string (name);
295       if ([item hasSubmenu])
296         {
297           old = interpret_services_menu ([item submenu],
298                                         Fcons (nameStr, prefix), old);
299         }
300       else
301         {
302           keys = [item keyEquivalent];
303           if (keys && [keys length] )
304             {
305               key = [keys characterAtIndex: 0];
306               res = make_number (key|super_modifier);
307             }
308           else
309             {
310               res = Qundefined;
311             }
312           old = Fcons (Fcons (res,
313                             Freverse (Fcons (nameStr,
314                                            prefix))),
315                     old);
316         }
317     }
318   return old;
323 /* ==========================================================================
325     Frame parameter setters
327    ========================================================================== */
330 static void
331 x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
333   NSColor *col;
335   if (ns_lisp_to_color (arg, &col))
336     {
337       store_frame_param (f, Qforeground_color, oldval);
338       error ("Unknown color");
339     }
341   [col retain];
342   [f->output_data.ns->foreground_color release];
343   f->output_data.ns->foreground_color = col;
345   if (FRAME_NS_VIEW (f))
346     {
347       update_face_from_frame_parameter (f, Qforeground_color, arg);
348       /*recompute_basic_faces (f); */
349       if (FRAME_VISIBLE_P (f))
350         redraw_frame (f);
351     }
355 static void
356 x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
358   struct face *face;
359   NSColor *col;
360   NSView *view = FRAME_NS_VIEW (f);
361   float alpha;
363   if (ns_lisp_to_color (arg, &col))
364     {
365       store_frame_param (f, Qbackground_color, oldval);
366       error ("Unknown color");
367     }
369   /* clear the frame; in some instances the NS-internal GC appears not to
370      update, or it does update and cannot clear old text properly */
371   if (FRAME_VISIBLE_P (f))
372     ns_clear_frame (f);
374   [col retain];
375   [f->output_data.ns->background_color release];
376   f->output_data.ns->background_color = col;
377   if (view != nil)
378     {
379       [[view window] setBackgroundColor: col];
380       alpha = [col alphaComponent];
382       if (alpha != 1.0)
383           [[view window] setOpaque: NO];
384       else
385           [[view window] setOpaque: YES];
387       face = FRAME_DEFAULT_FACE (f);
388       if (face)
389         {
390           col = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f);
391           face->background
392              = (EMACS_UINT) [[col colorWithAlphaComponent: alpha] retain];
393           [col release];
395           update_face_from_frame_parameter (f, Qbackground_color, arg);
396         }
398       if (FRAME_VISIBLE_P (f))
399         redraw_frame (f);
400     }
404 static void
405 x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
407   NSColor *col;
409   if (ns_lisp_to_color (arg, &col))
410     {
411       store_frame_param (f, Qcursor_color, oldval);
412       error ("Unknown color");
413     }
415   [FRAME_CURSOR_COLOR (f) release];
416   FRAME_CURSOR_COLOR (f) = [col retain];
418   if (FRAME_VISIBLE_P (f))
419     {
420       x_update_cursor (f, 0);
421       x_update_cursor (f, 1);
422     }
423   update_face_from_frame_parameter (f, Qcursor_color, arg);
427 static void
428 x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
430   NSView *view = FRAME_NS_VIEW (f);
431   NSTRACE (x_set_icon_name);
433   if (ns_in_resize)
434     return;
436   /* see if it's changed */
437   if (STRINGP (arg))
438     {
439       if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
440         return;
441     }
442   else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
443     return;
445   f->icon_name = arg;
447   if (NILP (arg))
448     {
449       if (!NILP (f->title))
450         arg = f->title;
451       else
452         /* explicit name and no icon-name -> explicit_name */
453         if (f->explicit_name)
454           arg = f->name;
455         else
456           {
457             /* no explicit name and no icon-name ->
458                name has to be rebuild from icon_title_format */
459             windows_or_buffers_changed++;
460             return;
461           }
462     }
464   /* Don't change the name if it's already NAME.  */
465   if ([[view window] miniwindowTitle] &&
466       ([[[view window] miniwindowTitle]
467              isEqualToString: [NSString stringWithUTF8String:
468                                            SDATA (arg)]]))
469     return;
471   [[view window] setMiniwindowTitle:
472         [NSString stringWithUTF8String: SDATA (arg)]];
476 static void
477 ns_set_name_iconic (struct frame *f, Lisp_Object name, int explicit)
479   NSView *view = FRAME_NS_VIEW (f);
480   NSTRACE (ns_set_name_iconic);
482   if (ns_in_resize)
483     return;
485   /* Make sure that requests from lisp code override requests from
486      Emacs redisplay code.  */
487   if (explicit)
488     {
489       /* If we're switching from explicit to implicit, we had better
490          update the mode lines and thereby update the title.  */
491       if (f->explicit_name && NILP (name))
492         update_mode_lines = 1;
494       f->explicit_name = ! NILP (name);
495     }
496   else if (f->explicit_name)
497     name = f->name;
499   /* title overrides explicit name */
500   if (! NILP (f->title))
501     name = f->title;
503   /* icon_name overrides title and explicit name */
504   if (! NILP (f->icon_name))
505     name = f->icon_name;
507   if (NILP (name))
508     name = build_string([ns_app_name UTF8String]);
509   else
510     CHECK_STRING (name);
512   /* Don't change the name if it's already NAME.  */
513   if ([[view window] miniwindowTitle] &&
514       ([[[view window] miniwindowTitle]
515              isEqualToString: [NSString stringWithUTF8String:
516                                            SDATA (name)]]))
517     return;
519   [[view window] setMiniwindowTitle:
520         [NSString stringWithUTF8String: SDATA (name)]];
524 static void
525 ns_set_name (struct frame *f, Lisp_Object name, int explicit)
527   NSView *view;
528   NSTRACE (ns_set_name);
530   if (ns_in_resize)
531     return;
533   /* Make sure that requests from lisp code override requests from
534      Emacs redisplay code.  */
535   if (explicit)
536     {
537       /* If we're switching from explicit to implicit, we had better
538          update the mode lines and thereby update the title.  */
539       if (f->explicit_name && NILP (name))
540         update_mode_lines = 1;
542       f->explicit_name = ! NILP (name);
543     }
544   else if (f->explicit_name)
545     return;
547   if (NILP (name))
548     name = build_string([ns_app_name UTF8String]);
550   f->name = name;
552   /* title overrides explicit name */
553   if (! NILP (f->title))
554     name = f->title;
556   CHECK_STRING (name);
558   view = FRAME_NS_VIEW (f);
560   /* Don't change the name if it's already NAME.  */
561   if ([[[view window] title]
562             isEqualToString: [NSString stringWithUTF8String:
563                                           SDATA (name)]])
564     return;
565   [[view window] setTitle: [NSString stringWithUTF8String:
566                                         SDATA (name)]];
570 /* This function should be called when the user's lisp code has
571    specified a name for the frame; the name will override any set by the
572    redisplay code.  */
573 static void
574 x_explicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
576   NSTRACE (x_explicitly_set_name);
577   ns_set_name_iconic (f, arg, 1);
578   ns_set_name (f, arg, 1);
582 /* This function should be called by Emacs redisplay code to set the
583    name; names set this way will never override names set by the user's
584    lisp code.  */
585 void
586 x_implicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
588   NSTRACE (x_implicitly_set_name);
589   if (FRAME_ICONIFIED_P (f))
590     ns_set_name_iconic (f, arg, 0);
591   else if (FRAME_NS_P (f) && EQ (Vframe_title_format, Qt))
592     ns_set_name_as_filename (f);
593   else
594     ns_set_name (f, arg, 0);
598 /* Change the title of frame F to NAME.
599    If NAME is nil, use the frame name as the title.
601    If EXPLICIT is non-zero, that indicates that lisp code is setting the
602    name; if NAME is a string, set F's name to NAME and set
603    F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
605    If EXPLICIT is zero, that indicates that Emacs redisplay code is
606    suggesting a new name, which lisp code should override; if
607    F->explicit_name is set, ignore the new name; otherwise, set it.  */
608 static void
609 x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
611   NSTRACE (x_set_title);
612   /* Don't change the title if it's already NAME.  */
613   if (EQ (name, f->title))
614     return;
616   update_mode_lines = 1;
618   f->title = name;
622 void
623 ns_set_name_as_filename (struct frame *f)
625   NSView *view;
626   Lisp_Object name;
627   Lisp_Object buf = XWINDOW (f->selected_window)->buffer;
628   const char *title;
629   NSAutoreleasePool *pool;
630   NSTRACE (ns_set_name_as_filename);
632   if (f->explicit_name || ! NILP (f->title) || ns_in_resize)
633     return;
635   BLOCK_INPUT;
636   pool = [[NSAutoreleasePool alloc] init];
637   name = XBUFFER (buf)->filename;
638   if (NILP (name) || FRAME_ICONIFIED_P (f)) name =XBUFFER (buf)->name;
640   if (FRAME_ICONIFIED_P (f) && !NILP (f->icon_name))
641     name = f->icon_name;
643   if (NILP (name))
644     name = build_string ([ns_app_name UTF8String]);
645   else
646     CHECK_STRING (name);
648   view = FRAME_NS_VIEW (f);
650   title = FRAME_ICONIFIED_P (f) ? [[[view window] miniwindowTitle] UTF8String]
651                                 : [[[view window] title] UTF8String];
653   if (title && (! strcmp (title, SDATA (name))))
654     {
655       [pool release];
656       UNBLOCK_INPUT;
657       return;
658     }
660   if (! FRAME_ICONIFIED_P (f))
661     {
662 #ifdef NS_IMPL_COCOA
663       /* work around a bug observed on 10.3 where
664          setTitleWithRepresentedFilename does not clear out previous state
665          if given filename does not exist */
666       NSString *str = [NSString stringWithUTF8String: SDATA (name)];
667       if (![[NSFileManager defaultManager] fileExistsAtPath: str])
668         {
669           [[view window] setTitleWithRepresentedFilename: @""];
670           [[view window] setTitle: str];
671         }
672       else
673         {
674           [[view window] setTitleWithRepresentedFilename: str];
675         }
676 #else
677       [[view window] setTitleWithRepresentedFilename:
678                          [NSString stringWithUTF8String: SDATA (name)]];
679 #endif
680       f->name = name;
681     }
682   else
683     {
684       [[view window] setMiniwindowTitle:
685             [NSString stringWithUTF8String: SDATA (name)]];
686     }
687   [pool release];
688   UNBLOCK_INPUT;
692 void
693 ns_set_doc_edited (struct frame *f, Lisp_Object arg)
695   NSView *view = FRAME_NS_VIEW (f);
696   NSAutoreleasePool *pool;
697   if (!MINI_WINDOW_P (XWINDOW (f->selected_window)))
698     {
699       BLOCK_INPUT;
700       pool = [[NSAutoreleasePool alloc] init];
701       [[view window] setDocumentEdited: !NILP (arg)];
702       [pool release];
703       UNBLOCK_INPUT;
704     }
708 void
709 x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
711   int nlines;
712   int olines = FRAME_MENU_BAR_LINES (f);
713   if (FRAME_MINIBUF_ONLY_P (f))
714     return;
716   if (INTEGERP (value))
717     nlines = XINT (value);
718   else
719     nlines = 0;
721   FRAME_MENU_BAR_LINES (f) = 0;
722   if (nlines)
723     {
724       FRAME_EXTERNAL_MENU_BAR (f) = 1;
725       /* does for all frames, whereas we just want for one frame
726          [NSMenu setMenuBarVisible: YES]; */
727     }
728   else
729     {
730       if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
731         free_frame_menubar (f);
732       /*      [NSMenu setMenuBarVisible: NO]; */
733       FRAME_EXTERNAL_MENU_BAR (f) = 0;
734     }
738 /* toolbar support */
739 void
740 x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
742   int nlines;
743   Lisp_Object root_window;
745   if (FRAME_MINIBUF_ONLY_P (f))
746     return;
748   if (INTEGERP (value) && XINT (value) >= 0)
749     nlines = XFASTINT (value);
750   else
751     nlines = 0;
753   if (nlines)
754     {
755       FRAME_EXTERNAL_TOOL_BAR (f) = 1;
756       update_frame_tool_bar (f);
757     }
758   else
759     {
760       if (FRAME_EXTERNAL_TOOL_BAR (f))
761         {
762           free_frame_tool_bar (f);
763           FRAME_EXTERNAL_TOOL_BAR (f) = 0;
764         }
765     }
767   x_set_window_size (f, 0, f->text_cols, f->text_lines);
771 void
772 ns_implicitly_set_icon_type (struct frame *f)
774   Lisp_Object tem;
775   EmacsView *view = FRAME_NS_VIEW (f);
776   id image =nil;
777   Lisp_Object chain, elt;
778   NSAutoreleasePool *pool;
779   BOOL setMini = YES;
781   NSTRACE (ns_implicitly_set_icon_type);
783   BLOCK_INPUT;
784   pool = [[NSAutoreleasePool alloc] init];
785   if (f->output_data.ns->miniimage
786       && [[NSString stringWithUTF8String: SDATA (f->name)]
787                isEqualToString: [(NSImage *)f->output_data.ns->miniimage name]])
788     {
789       [pool release];
790       UNBLOCK_INPUT;
791       return;
792     }
794   tem = assq_no_quit (Qicon_type, f->param_alist);
795   if (CONSP (tem) && ! NILP (XCDR (tem)))
796     {
797       [pool release];
798       UNBLOCK_INPUT;
799       return;
800     }
802   for (chain = Vns_icon_type_alist;
803        (image = nil) && CONSP (chain);
804        chain = XCDR (chain))
805     {
806       elt = XCAR (chain);
807       /* special case: 't' means go by file type */
808       if (SYMBOLP (elt) && EQ (elt, Qt) && SDATA (f->name)[0] == '/')
809         {
810           NSString *str
811              = [NSString stringWithUTF8String: SDATA (f->name)];
812           if ([[NSFileManager defaultManager] fileExistsAtPath: str])
813             image = [[[NSWorkspace sharedWorkspace] iconForFile: str] retain];
814         }
815       else if (CONSP (elt) &&
816                STRINGP (XCAR (elt)) &&
817                STRINGP (XCDR (elt)) &&
818                fast_string_match (XCAR (elt), f->name) >= 0)
819         {
820           image = [EmacsImage allocInitFromFile: XCDR (elt)];
821           if (image == nil)
822             image = [[NSImage imageNamed:
823                                [NSString stringWithUTF8String:
824                                             SDATA (XCDR (elt))]] retain];
825         }
826     }
828   if (image == nil)
829     {
830       image = [[[NSWorkspace sharedWorkspace] iconForFileType: @"text"] retain];
831       setMini = NO;
832     }
834   [f->output_data.ns->miniimage release];
835   f->output_data.ns->miniimage = image;
836   [view setMiniwindowImage: setMini];
837   [pool release];
838   UNBLOCK_INPUT;
842 static void
843 x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
845   EmacsView *view = FRAME_NS_VIEW (f);
846   id image = nil;
847   BOOL setMini = YES;
849   NSTRACE (x_set_icon_type);
851   if (!NILP (arg) && SYMBOLP (arg))
852     {
853       arg =build_string (SDATA (SYMBOL_NAME (arg)));
854       store_frame_param (f, Qicon_type, arg);
855     }
857   /* do it the implicit way */
858   if (NILP (arg))
859     {
860       ns_implicitly_set_icon_type (f);
861       return;
862     }
864   CHECK_STRING (arg);
866   image = [EmacsImage allocInitFromFile: arg];
867   if (image == nil)
868     image =[NSImage imageNamed: [NSString stringWithUTF8String:
869                                             SDATA (arg)]];
871   if (image == nil)
872     {
873       image = [NSImage imageNamed: @"text"];
874       setMini = NO;
875     }
877   f->output_data.ns->miniimage = image;
878   [view setMiniwindowImage: setMini];
882 /* Xism; we stub out (we do implement this in ns-win.el) */
884 XParseGeometry (char *string, int *x, int *y,
885                 unsigned int *width, unsigned int *height)
887   message1 ("Warning: XParseGeometry not supported under NS.\n");
888   return 0;
892 /* TODO: move to nsterm? */
894 ns_lisp_to_cursor_type (Lisp_Object arg)
896   char *str;
897   if (XTYPE (arg) == Lisp_String)
898     str = SDATA (arg);
899   else if (XTYPE (arg) == Lisp_Symbol)
900     str = SDATA (SYMBOL_NAME (arg));
901   else return -1;
902   if (!strcmp (str, "box"))     return FILLED_BOX_CURSOR;
903   if (!strcmp (str, "hollow"))  return HOLLOW_BOX_CURSOR;
904   if (!strcmp (str, "hbar"))    return HBAR_CURSOR;
905   if (!strcmp (str, "bar"))     return BAR_CURSOR;
906   if (!strcmp (str, "no"))      return NO_CURSOR;
907   return -1;
911 Lisp_Object
912 ns_cursor_type_to_lisp (int arg)
914   switch (arg)
915     {
916     case FILLED_BOX_CURSOR: return Qbox;
917     case HOLLOW_BOX_CURSOR: return intern ("hollow");
918     case HBAR_CURSOR:       return intern ("hbar");
919     case BAR_CURSOR:        return intern ("bar");
920     case NO_CURSOR:
921     default:                return intern ("no");
922     }
925 /* This is the same as the xfns.c definition.  */
926 void
927 x_set_cursor_type (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
929   set_frame_cursor_types (f, arg);
931   /* Make sure the cursor gets redrawn.  */
932   cursor_type_changed = 1;
936 /* called to set mouse pointer color, but all other terms use it to
937    initialize pointer types (and don't set the color ;) */
938 static void
939 x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
941   /* don't think we can do this on Nextstep */
945 #define Str(x) #x
946 #define Xstr(x) Str(x)
948 static Lisp_Object
949 ns_appkit_version_str (void)
951   char tmp[80];
953 #ifdef NS_IMPL_GNUSTEP
954   sprintf(tmp, "gnustep-gui-%s", Xstr(GNUSTEP_GUI_VERSION));
955 #elif defined(NS_IMPL_COCOA)
956   sprintf(tmp, "apple-appkit-%.2f", NSAppKitVersionNumber);
957 #else
958   tmp = "ns-unknown";
959 #endif
960   return build_string (tmp);
964 /* This is for use by x-server-version and collapses all version info we
965    have into a single int.  For a better picture of the implementation
966    running, use ns_appkit_version_str.*/
967 static int
968 ns_appkit_version_int (void)
970 #ifdef NS_IMPL_GNUSTEP
971   return GNUSTEP_GUI_MAJOR_VERSION * 100 + GNUSTEP_GUI_MINOR_VERSION;
972 #elif defined(NS_IMPL_COCOA)
973   return (int)NSAppKitVersionNumber;
974 #endif
975   return 0;
979 static void
980 x_icon (struct frame *f, Lisp_Object parms)
981 /* --------------------------------------------------------------------------
982    Strangely-named function to set icon position parameters in frame.
983    This is irrelevant under OS X, but might be needed under GNUstep,
984    depending on the window manager used.  Note, this is not a standard
985    frame parameter-setter; it is called directly from x-create-frame.
986    -------------------------------------------------------------------------- */
988   Lisp_Object icon_x, icon_y;
989   struct ns_display_info *dpyinfo = check_ns_display_info (Qnil);
991   f->output_data.ns->icon_top = Qnil;
992   f->output_data.ns->icon_left = Qnil;
994   /* Set the position of the icon.  */
995   icon_x = x_get_arg (dpyinfo, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
996   icon_y = x_get_arg (dpyinfo, parms, Qicon_top, 0, 0,  RES_TYPE_NUMBER);
997   if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
998     {
999       CHECK_NUMBER (icon_x);
1000       CHECK_NUMBER (icon_y);
1001       f->output_data.ns->icon_top = icon_y;
1002       f->output_data.ns->icon_left = icon_x;
1003     }
1004   else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
1005     error ("Both left and top icon corners of icon must be specified");
1009 /* Note: see frame.c for template, also where generic functions are impl */
1010 frame_parm_handler ns_frame_parm_handlers[] =
1012   x_set_autoraise, /* generic OK */
1013   x_set_autolower, /* generic OK */
1014   x_set_background_color,
1015   0, /* x_set_border_color,  may be impossible under Nextstep */
1016   0, /* x_set_border_width,  may be impossible under Nextstep */
1017   x_set_cursor_color,
1018   x_set_cursor_type,
1019   x_set_font, /* generic OK */
1020   x_set_foreground_color,
1021   x_set_icon_name,
1022   x_set_icon_type,
1023   x_set_internal_border_width, /* generic OK */
1024   x_set_menu_bar_lines,
1025   x_set_mouse_color,
1026   x_explicitly_set_name,
1027   x_set_scroll_bar_width, /* generic OK */
1028   x_set_title,
1029   x_set_unsplittable, /* generic OK */
1030   x_set_vertical_scroll_bars, /* generic OK */
1031   x_set_visibility, /* generic OK */
1032   x_set_tool_bar_lines,
1033   0, /* x_set_scroll_bar_foreground, will ignore (not possible on NS) */
1034   0, /* x_set_scroll_bar_background,  will ignore (not possible on NS) */
1035   x_set_screen_gamma, /* generic OK */
1036   x_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */
1037   x_set_fringe_width, /* generic OK */
1038   x_set_fringe_width, /* generic OK */
1039   0, /* x_set_wait_for_wm, will ignore */
1040   0,  /* x_set_fullscreen will ignore */
1041   x_set_font_backend, /* generic OK */
1042   x_set_alpha,
1043   0, /* x_set_sticky */  
1044   0, /* x_set_tool_bar_position */  
1049 /* ==========================================================================
1051     Lisp definitions
1053    ========================================================================== */
1055 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
1056        1, 1, 0,
1057        doc: /* Make a new Nextstep window, called a \"frame\" in Emacs terms.
1058 Return an Emacs frame object.
1059 PARMS is an alist of frame parameters.
1060 If the parameters specify that the frame should not have a minibuffer,
1061 and do not specify a specific minibuffer window to use,
1062 then `default-minibuffer-frame' must be a frame whose minibuffer can
1063 be shared by the new frame.  */)
1064      (Lisp_Object parms)
1066   static int desc_ctr = 1;
1067   struct frame *f;
1068   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1069   Lisp_Object frame, tem;
1070   Lisp_Object name;
1071   int minibuffer_only = 0;
1072   int count = specpdl_ptr - specpdl;
1073   Lisp_Object display;
1074   struct ns_display_info *dpyinfo = NULL;
1075   Lisp_Object parent;
1076   struct kboard *kb;
1077   Lisp_Object tfont, tfontsize;
1078   int window_prompting = 0;
1079   int width, height;
1081   check_ns ();
1083   /* Seems a little strange, but other terms do it. Perhaps the code below
1084      is modifying something? */
1085   parms = Fcopy_alist (parms);
1087   display = x_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_STRING);
1088   if (EQ (display, Qunbound))
1089     display = Qnil;
1090   dpyinfo = check_ns_display_info (display);
1092   if (!dpyinfo->terminal->name)
1093     error ("Terminal is not live, can't create new frames on it");
1095   kb = dpyinfo->terminal->kboard;
1097   name = x_get_arg (dpyinfo, parms, Qname, 0, 0, RES_TYPE_STRING);
1098   if (!STRINGP (name)
1099       && ! EQ (name, Qunbound)
1100       && ! NILP (name))
1101     error ("Invalid frame name--not a string or nil");
1103   if (STRINGP (name))
1104     Vx_resource_name = name;
1105   else
1106     Vx_resource_name = Vinvocation_name;
1108   parent = x_get_arg (dpyinfo, parms, Qparent_id, 0, 0, RES_TYPE_NUMBER);
1109   if (EQ (parent, Qunbound))
1110     parent = Qnil;
1111   if (! NILP (parent))
1112     CHECK_NUMBER (parent);
1114   frame = Qnil;
1115   GCPRO4 (parms, parent, name, frame);
1117   tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
1118                   RES_TYPE_SYMBOL);
1119   if (EQ (tem, Qnone) || NILP (tem))
1120     {
1121       f = make_frame_without_minibuffer (Qnil, kb, display);
1122     }
1123   else if (EQ (tem, Qonly))
1124     {
1125       f = make_minibuffer_frame ();
1126       minibuffer_only = 1;
1127     }
1128   else if (WINDOWP (tem))
1129     {
1130       f = make_frame_without_minibuffer (tem, kb, display);
1131     }
1132   else
1133     {
1134       f = make_frame (1);
1135     }
1137   /* Set the name; the functions to which we pass f expect the name to
1138      be set.  */
1139   if (EQ (name, Qunbound) || NILP (name) || (XTYPE (name) != Lisp_String))
1140     {
1141       f->name = build_string ([ns_app_name UTF8String]);
1142       f->explicit_name =0;
1143     }
1144   else
1145     {
1146       f->name = name;
1147       f->explicit_name = 1;
1148       specbind (Qx_resource_name, name);
1149     }
1151   XSETFRAME (frame, f);
1152   FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
1154   f->terminal = dpyinfo->terminal;
1155   f->terminal->reference_count++;
1157   f->output_method = output_ns;
1158   f->output_data.ns = (struct ns_output *)xmalloc (sizeof *(f->output_data.ns));
1159   memset (f->output_data.ns, 0, sizeof (*(f->output_data.ns)));
1161   FRAME_FONTSET (f) = -1;
1163   /* record_unwind_protect (unwind_create_frame, frame); safety; maybe later? */
1165   f->icon_name = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
1166                             RES_TYPE_STRING);
1167   if (! STRINGP (f->icon_name))
1168     f->icon_name = Qnil;
1170   FRAME_NS_DISPLAY_INFO (f) = dpyinfo;
1172   f->output_data.ns->window_desc = desc_ctr++;
1173   if (!NILP (parent))
1174     {
1175       f->output_data.ns->parent_desc = (Window) XFASTINT (parent);
1176       f->output_data.ns->explicit_parent = 1;
1177     }
1178   else
1179     {
1180       f->output_data.ns->parent_desc = FRAME_NS_DISPLAY_INFO (f)->root_window;
1181       f->output_data.ns->explicit_parent = 0;
1182     }
1184   f->resx = dpyinfo->resx;
1185   f->resy = dpyinfo->resy;
1187   BLOCK_INPUT;
1188   register_font_driver (&nsfont_driver, f);
1189   x_default_parameter (f, parms, Qfont_backend, Qnil,
1190                         "fontBackend", "FontBackend", RES_TYPE_STRING);
1192   {
1193     /* use for default font name */
1194     id font = [NSFont userFixedPitchFontOfSize: -1.0]; /* default */
1195     tfontsize = x_default_parameter (f, parms, Qfontsize,
1196                                     make_number (0 /*(int)[font pointSize]*/),
1197                                     "fontSize", "FontSize", RES_TYPE_NUMBER);
1198     tfont = x_default_parameter (f, parms, Qfont,
1199                                  build_string ([[font fontName] UTF8String]),
1200                                  "font", "Font", RES_TYPE_STRING);
1201   }
1202   UNBLOCK_INPUT;
1204   x_default_parameter (f, parms, Qborder_width, make_number (0),
1205                        "borderwidth", "BorderWidth", RES_TYPE_NUMBER);
1206   x_default_parameter (f, parms, Qinternal_border_width, make_number (2),
1207                       "internalBorderWidth", "InternalBorderWidth",
1208                       RES_TYPE_NUMBER);
1210   /* default scrollbars on right on Mac */
1211   {
1212       Lisp_Object spos
1213 #ifdef NS_IMPL_GNUSTEP
1214           = Qt;
1215 #else
1216           = Qright;
1217 #endif
1218       x_default_parameter (f, parms, Qvertical_scroll_bars, spos,
1219                            "verticalScrollBars", "VerticalScrollBars",
1220                            RES_TYPE_SYMBOL);
1221   }
1222   x_default_parameter (f, parms, Qforeground_color, build_string ("Black"),
1223                       "foreground", "Foreground", RES_TYPE_STRING);
1224   x_default_parameter (f, parms, Qbackground_color, build_string ("White"),
1225                       "background", "Background", RES_TYPE_STRING);
1226   x_default_parameter (f, parms, Qcursor_color, build_string ("grey"),
1227                       "cursorColor", "CursorColor", RES_TYPE_STRING);
1228   /* FIXME: not suppported yet in Nextstep */
1229   x_default_parameter (f, parms, Qline_spacing, Qnil,
1230                        "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
1231   x_default_parameter (f, parms, Qleft_fringe, Qnil,
1232                        "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
1233   x_default_parameter (f, parms, Qright_fringe, Qnil,
1234                        "rightFringe", "RightFringe", RES_TYPE_NUMBER);
1235   /* end PENDING */
1237   init_frame_faces (f);
1239   /* The X resources controlling the menu-bar and tool-bar are
1240      processed specially at startup, and reflected in the mode
1241      variables; ignore them here.  */
1242   x_default_parameter (f, parms, Qmenu_bar_lines,
1243                        NILP (Vmenu_bar_mode)
1244                        ? make_number (0) : make_number (1),
1245                        NULL, NULL, RES_TYPE_NUMBER);
1246   x_default_parameter (f, parms, Qtool_bar_lines,
1247                        NILP (Vtool_bar_mode)
1248                        ? make_number (0) : make_number (1),
1249                        NULL, NULL, RES_TYPE_NUMBER);
1251   x_default_parameter (f, parms, Qbuffer_predicate, Qnil, "bufferPredicate",
1252                        "BufferPredicate", RES_TYPE_SYMBOL);
1253   x_default_parameter (f, parms, Qtitle, Qnil, "title", "Title",
1254                        RES_TYPE_STRING);
1256 /* TODO: other terms seem to get away w/o this complexity.. */
1257   if (NILP (Fassq (Qwidth, parms)))
1258     {
1259       Lisp_Object value
1260          = x_get_arg (dpyinfo, parms, Qwidth, "width", "Width",
1261                       RES_TYPE_NUMBER);
1262       if (! EQ (value, Qunbound))
1263         parms = Fcons (Fcons (Qwidth, value), parms);
1264     }
1265   if (NILP (Fassq (Qheight, parms)))
1266     {
1267       Lisp_Object value
1268          = x_get_arg (dpyinfo, parms, Qheight, "height", "Height",
1269                       RES_TYPE_NUMBER);
1270       if (! EQ (value, Qunbound))
1271         parms = Fcons (Fcons (Qheight, value), parms);
1272     }
1273   if (NILP (Fassq (Qleft, parms)))
1274     {
1275       Lisp_Object value
1276          = x_get_arg (dpyinfo, parms, Qleft, "left", "Left", RES_TYPE_NUMBER);
1277       if (! EQ (value, Qunbound))
1278         parms = Fcons (Fcons (Qleft, value), parms);
1279     }
1280   if (NILP (Fassq (Qtop, parms)))
1281     {
1282       Lisp_Object value
1283          = x_get_arg (dpyinfo, parms, Qtop, "top", "Top", RES_TYPE_NUMBER);
1284       if (! EQ (value, Qunbound))
1285         parms = Fcons (Fcons (Qtop, value), parms);
1286     }
1288   window_prompting = x_figure_window_size (f, parms, 1);
1290   tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
1291   f->no_split = minibuffer_only || (!EQ (tem, Qunbound) && !EQ (tem, Qnil));
1293   /* NOTE: on other terms, this is done in set_mouse_color, however this
1294      was not getting called under Nextstep */
1295   f->output_data.ns->text_cursor = [NSCursor IBeamCursor];
1296   f->output_data.ns->nontext_cursor = [NSCursor arrowCursor];
1297   f->output_data.ns->modeline_cursor = [NSCursor pointingHandCursor];
1298   f->output_data.ns->hand_cursor = [NSCursor pointingHandCursor];
1299   f->output_data.ns->hourglass_cursor = [NSCursor disappearingItemCursor];
1300   f->output_data.ns->horizontal_drag_cursor = [NSCursor resizeLeftRightCursor];
1301   FRAME_NS_DISPLAY_INFO (f)->vertical_scroll_bar_cursor
1302      = [NSCursor arrowCursor];
1303   f->output_data.ns->current_pointer = f->output_data.ns->text_cursor;
1305   [[EmacsView alloc] initFrameFromEmacs: f];
1307   x_icon (f, parms);
1309   /* It is now ok to make the frame official even if we get an error below.
1310      The frame needs to be on Vframe_list or making it visible won't work. */
1311   Vframe_list = Fcons (frame, Vframe_list);
1312   /*FRAME_NS_DISPLAY_INFO (f)->reference_count++; */
1314   x_default_parameter (f, parms, Qicon_type, Qnil, "bitmapIcon", "BitmapIcon",
1315                       RES_TYPE_SYMBOL);
1316   x_default_parameter (f, parms, Qauto_raise, Qnil, "autoRaise", "AutoRaiseLower",
1317                       RES_TYPE_BOOLEAN);
1318   x_default_parameter (f, parms, Qauto_lower, Qnil, "autoLower", "AutoLower",
1319                       RES_TYPE_BOOLEAN);
1320   x_default_parameter (f, parms, Qcursor_type, Qbox, "cursorType", "CursorType",
1321                       RES_TYPE_SYMBOL);
1322   x_default_parameter (f, parms, Qscroll_bar_width, Qnil, "scrollBarWidth",
1323                       "ScrollBarWidth", RES_TYPE_NUMBER);
1324   x_default_parameter (f, parms, Qalpha, Qnil, "alpha", "Alpha",
1325                       RES_TYPE_NUMBER);
1327   width = FRAME_COLS (f);
1328   height = FRAME_LINES (f);
1330   SET_FRAME_COLS (f, 0);
1331   FRAME_LINES (f) = 0;
1332   change_frame_size (f, height, width, 1, 0, 0);
1334   if (! f->output_data.ns->explicit_parent)
1335     {
1336       tem = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
1337       if (EQ (tem, Qunbound))
1338         tem = Qt;
1339       x_set_visibility (f, tem, Qnil);
1340       if (EQ (tem, Qicon))
1341         x_iconify_frame (f);
1342       else if (! NILP (tem))
1343         {
1344           x_make_frame_visible (f);
1345           f->async_visible = 1;
1346           [[FRAME_NS_VIEW (f) window] makeKeyWindow];
1347         }
1348       else
1349           f->async_visible = 0;
1350     }
1352   if (FRAME_HAS_MINIBUF_P (f)
1353       && (!FRAMEP (kb->Vdefault_minibuffer_frame)
1354           || !FRAME_LIVE_P (XFRAME (kb->Vdefault_minibuffer_frame))))
1355     kb->Vdefault_minibuffer_frame = frame;
1357   /* All remaining specified parameters, which have not been "used"
1358      by x_get_arg and friends, now go in the misc. alist of the frame.  */
1359   for (tem = parms; CONSP (tem); tem = XCDR (tem))
1360     if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
1361       f->param_alist = Fcons (XCAR (tem), f->param_alist);
1363   UNGCPRO;
1364   Vwindow_list = Qnil;
1366   return unbind_to (count, frame);
1370 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
1371        doc: /* Set the input focus to FRAME.
1372 FRAME nil means use the selected frame.  */)
1373      (Lisp_Object frame)
1375   struct frame *f = check_ns_frame (frame);
1376   struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f);
1378   if (dpyinfo->x_focus_frame != f)
1379     {
1380       EmacsView *view = FRAME_NS_VIEW (f);
1381       BLOCK_INPUT;
1382       [NSApp activateIgnoringOtherApps: YES];
1383       [[view window] makeKeyAndOrderFront: view];
1384       UNBLOCK_INPUT;
1385     }
1387   return Qnil;
1391 DEFUN ("ns-popup-font-panel", Fns_popup_font_panel, Sns_popup_font_panel,
1392        0, 1, "",
1393        doc: /* Pop up the font panel. */)
1394      (Lisp_Object frame)
1396   id fm;
1397   struct frame *f;
1399   check_ns ();
1400   fm = [NSFontManager sharedFontManager];
1401   if (NILP (frame))
1402     f = SELECTED_FRAME ();
1403   else
1404     {
1405       CHECK_FRAME (frame);
1406       f = XFRAME (frame);
1407     }
1409   [fm setSelectedFont: ((struct nsfont_info *)f->output_data.ns->font)->nsfont
1410            isMultiple: NO];
1411   [fm orderFrontFontPanel: NSApp];
1412   return Qnil;
1416 DEFUN ("ns-popup-color-panel", Fns_popup_color_panel, Sns_popup_color_panel,
1417        0, 1, "",
1418        doc: /* Pop up the color panel.  */)
1419      (Lisp_Object frame)
1421   struct frame *f;
1423   check_ns ();
1424   if (NILP (frame))
1425     f = SELECTED_FRAME ();
1426   else
1427     {
1428       CHECK_FRAME (frame);
1429       f = XFRAME (frame);
1430     }
1432   [NSApp orderFrontColorPanel: NSApp];
1433   return Qnil;
1437 DEFUN ("ns-read-file-name", Fns_read_file_name, Sns_read_file_name, 1, 4, 0,
1438        doc: /* Use a graphical panel to read a file name, using prompt PROMPT.
1439 Optional arg DIR, if non-nil, supplies a default directory.
1440 Optional arg ISLOAD, if non-nil, means read a file name for saving.
1441 Optional arg INIT, if non-nil, provides a default file name to use.  */)
1442      (Lisp_Object prompt, Lisp_Object dir, Lisp_Object isLoad, Lisp_Object init)
1444   static id fileDelegate = nil;
1445   int ret;
1446   id panel;
1447   Lisp_Object fname;
1449   NSString *promptS = NILP (prompt) || !STRINGP (prompt) ? nil :
1450     [NSString stringWithUTF8String: SDATA (prompt)];
1451   NSString *dirS = NILP (dir) || !STRINGP (dir) ?
1452     [NSString stringWithUTF8String: SDATA (current_buffer->directory)] :
1453     [NSString stringWithUTF8String: SDATA (dir)];
1454   NSString *initS = NILP (init) || !STRINGP (init) ? nil :
1455     [NSString stringWithUTF8String: SDATA (init)];
1457   check_ns ();
1459   if (fileDelegate == nil)
1460     fileDelegate = [EmacsFileDelegate new];
1462   [NSCursor setHiddenUntilMouseMoves: NO];
1464   if ([dirS characterAtIndex: 0] == '~')
1465     dirS = [dirS stringByExpandingTildeInPath];
1467   panel = NILP (isLoad) ?
1468     (id)[EmacsSavePanel savePanel] : (id)[EmacsOpenPanel openPanel];
1470   [panel setTitle: promptS];
1472   /* Puma (10.1) does not have */
1473   if ([panel respondsToSelector: @selector (setAllowsOtherFileTypes:)])
1474     [panel setAllowsOtherFileTypes: YES];
1476   [panel setTreatsFilePackagesAsDirectories: YES];
1477   [panel setDelegate: fileDelegate];
1479   panelOK = 0;
1480   BLOCK_INPUT;
1481   if (NILP (isLoad))
1482     {
1483       ret = [panel runModalForDirectory: dirS file: initS];
1484     }
1485   else
1486     {
1487       [panel setCanChooseDirectories: YES];
1488       ret = [panel runModalForDirectory: dirS file: initS types: nil];
1489     }
1491   ret = (ret == NSOKButton) || panelOK;
1493   if (ret)
1494     fname = build_string ([[panel filename] UTF8String]);
1496   [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
1497   UNBLOCK_INPUT;
1499   return ret ? fname : Qnil;
1503 DEFUN ("ns-get-resource", Fns_get_resource, Sns_get_resource, 2, 2, 0,
1504        doc: /* Return the value of the property NAME of OWNER from the defaults database.
1505 If OWNER is nil, Emacs is assumed.  */)
1506      (Lisp_Object owner, Lisp_Object name)
1508   const char *value;
1510   check_ns ();
1511   if (NILP (owner))
1512     owner = build_string([ns_app_name UTF8String]);
1513   CHECK_STRING (name);
1514 /*fprintf (stderr, "ns-get-resource checking resource '%s'\n", SDATA (name)); */
1516   value =[[[NSUserDefaults standardUserDefaults]
1517             objectForKey: [NSString stringWithUTF8String: SDATA (name)]]
1518            UTF8String];
1520   if (value)
1521     return build_string (value);
1522   return Qnil;
1526 DEFUN ("ns-set-resource", Fns_set_resource, Sns_set_resource, 3, 3, 0,
1527        doc: /* Set property NAME of OWNER to VALUE, from the defaults database.
1528 If OWNER is nil, Emacs is assumed.
1529 If VALUE is nil, the default is removed.  */)
1530      (Lisp_Object owner, Lisp_Object name, Lisp_Object value)
1532   check_ns ();
1533   if (NILP (owner))
1534     owner = build_string ([ns_app_name UTF8String]);
1535   CHECK_STRING (name);
1536   if (NILP (value))
1537     {
1538       [[NSUserDefaults standardUserDefaults] removeObjectForKey:
1539                          [NSString stringWithUTF8String: SDATA (name)]];
1540     }
1541   else
1542     {
1543       CHECK_STRING (value);
1544       [[NSUserDefaults standardUserDefaults] setObject:
1545                 [NSString stringWithUTF8String: SDATA (value)]
1546                                         forKey: [NSString stringWithUTF8String:
1547                                                          SDATA (name)]];
1548     }
1550   return Qnil;
1554 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
1555        Sx_server_max_request_size,
1556        0, 1, 0,
1557        doc: /* This function is a no-op.  It is only present for completeness.  */)
1558      (Lisp_Object display)
1560   check_ns ();
1561   /* This function has no real equivalent under NeXTstep.  Return nil to
1562      indicate this. */
1563   return Qnil;
1567 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
1568        doc: /* Return the vendor ID string of Nextstep display server DISPLAY.
1569 DISPLAY should be either a frame or a display name (a string).
1570 If omitted or nil, the selected frame's display is used.  */)
1571      (Lisp_Object display)
1573 #ifdef NS_IMPL_GNUSTEP
1574   return build_string ("GNU");
1575 #else
1576   return build_string ("Apple");
1577 #endif
1581 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
1582        doc: /* Return the version numbers of the server of DISPLAY.
1583 The value is a list of three integers: the major and minor
1584 version numbers of the X Protocol in use, and the distributor-specific
1585 release number.  See also the function `x-server-vendor'.
1587 The optional argument DISPLAY specifies which display to ask about.
1588 DISPLAY should be either a frame or a display name (a string).
1589 If omitted or nil, that stands for the selected frame's display.  */)
1590      (Lisp_Object display)
1592   /*NOTE: it is unclear what would best correspond with "protocol";
1593           we return 10.3, meaning Panther, since this is roughly the
1594           level that GNUstep's APIs correspond to.
1595           The last number is where we distinguish between the Apple
1596           and GNUstep implementations ("distributor-specific release
1597           number") and give int'ized versions of major.minor. */
1598   return Fcons (make_number (10),
1599                 Fcons (make_number (3),
1600                        Fcons (make_number (ns_appkit_version_int()), Qnil)));
1604 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
1605        doc: /* Return the number of screens on Nextstep display server DISPLAY.
1606 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1607 If omitted or nil, the selected frame's display is used.  */)
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      (Lisp_Object display)
1626   check_ns ();
1627   return make_number ((int)
1628                      ([ns_get_screen (display) frame].size.height/(92.0/25.4)));
1632 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width,
1633        0, 1, 0,
1634        doc: /* Return the width of Nextstep display server DISPLAY, in millimeters.
1635 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1636 If omitted or nil, the selected frame's display is used.  */)
1637      (Lisp_Object display)
1639   check_ns ();
1640   return make_number ((int)
1641                      ([ns_get_screen (display) frame].size.width/(92.0/25.4)));
1645 DEFUN ("x-display-backing-store", Fx_display_backing_store,
1646        Sx_display_backing_store, 0, 1, 0,
1647        doc: /* Return whether the Nexstep display DISPLAY supports backing store.
1648 The value may be `buffered', `retained', or `non-retained'.
1649 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1650 If omitted or nil, the selected frame's display is used.  */)
1651      (Lisp_Object display)
1653   check_ns ();
1654   switch ([ns_get_window (display) backingType])
1655     {
1656     case NSBackingStoreBuffered:
1657       return intern ("buffered");
1658     case NSBackingStoreRetained:
1659       return intern ("retained");
1660     case NSBackingStoreNonretained:
1661       return intern ("non-retained");
1662     default:
1663       error ("Strange value for backingType parameter of frame");
1664     }
1665   return Qnil;  /* not reached, shut compiler up */
1669 DEFUN ("x-display-visual-class", Fx_display_visual_class,
1670        Sx_display_visual_class, 0, 1, 0,
1671        doc: /* Return the visual class of the Nextstep display server DISPLAY.
1672 The value is one of the symbols `static-gray', `gray-scale',
1673 `static-color', `pseudo-color', `true-color', or `direct-color'.
1674 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1675 If omitted or nil, the selected frame's display is used.  */)
1676      (Lisp_Object display)
1678   NSWindowDepth depth;
1679   check_ns ();
1680   depth = [ns_get_screen (display) depth];
1682   if ( depth == NSBestDepth (NSCalibratedWhiteColorSpace, 2, 2, YES, NULL))
1683     return intern ("static-gray");
1684   else if (depth == NSBestDepth (NSCalibratedWhiteColorSpace, 8, 8, YES, NULL))
1685     return intern ("gray-scale");
1686   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 8, YES, NULL))
1687     return intern ("pseudo-color");
1688   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 4, 12, NO, NULL))
1689     return intern ("true-color");
1690   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 24, NO, NULL))
1691     return intern ("direct-color");
1692   else
1693     /* color mgmt as far as we do it is really handled by Nextstep itself anyway */
1694     return intern ("direct-color");
1698 DEFUN ("x-display-save-under", Fx_display_save_under,
1699        Sx_display_save_under, 0, 1, 0,
1700        doc: /* Non-nil if the Nextstep display server supports the save-under feature.
1701 The optional argument DISPLAY specifies which display to ask about.
1702 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1703 If omitted or nil, the selected frame's display is used.  */)
1704      (Lisp_Object display)
1706   check_ns ();
1707   switch ([ns_get_window (display) backingType])
1708     {
1709     case NSBackingStoreBuffered:
1710       return Qt;
1712     case NSBackingStoreRetained:
1713     case NSBackingStoreNonretained:
1714       return Qnil;
1716     default:
1717       error ("Strange value for backingType parameter of frame");
1718     }
1719   return Qnil;  /* not reached, shut compiler up */
1723 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
1724        1, 3, 0,
1725        doc: /* Open a connection to a Nextstep display server.
1726 DISPLAY is the name of the display to connect to.
1727 Optional arguments XRM-STRING and MUST-SUCCEED are currently ignored.  */)
1728      (Lisp_Object display, Lisp_Object resource_string, Lisp_Object must_succeed)
1730   struct ns_display_info *dpyinfo;
1732   CHECK_STRING (display);
1734   nxatoms_of_nsselect ();
1735   dpyinfo = ns_term_init (display);
1736   if (dpyinfo == 0)
1737     {
1738       if (!NILP (must_succeed))
1739         fatal ("OpenStep on %s not responding.\n",
1740                SDATA (display));
1741       else
1742         error ("OpenStep on %s not responding.\n",
1743                SDATA (display));
1744     }
1746   /* Register our external input/output types, used for determining
1747      applicable services and also drag/drop eligibility. */
1748   ns_send_types = [[NSArray arrayWithObject: NSStringPboardType] retain];
1749   ns_return_types = [[NSArray arrayWithObject: NSStringPboardType] retain];
1750   ns_drag_types = [[NSArray arrayWithObjects:
1751                             NSStringPboardType,
1752                             NSTabularTextPboardType,
1753                             NSFilenamesPboardType,
1754                             NSURLPboardType,
1755                             NSColorPboardType,
1756                             NSFontPboardType, nil] retain];
1758   return Qnil;
1762 DEFUN ("x-close-connection", Fx_close_connection, Sx_close_connection,
1763        1, 1, 0,
1764        doc: /* Close the connection to the current Nextstep display server.
1765 The argument DISPLAY is currently ignored.  */)
1766      (Lisp_Object display)
1768   check_ns ();
1769   /*ns_delete_terminal (dpyinfo->terminal); */
1770   [NSApp terminate: NSApp];
1771   return Qnil;
1775 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
1776        doc: /* Return the list of display names that Emacs has connections to.  */)
1777      (void)
1779   Lisp_Object tail, result;
1781   result = Qnil;
1782   for (tail = ns_display_name_list; CONSP (tail); tail = XCDR (tail))
1783     result = Fcons (XCAR (XCAR (tail)), result);
1785   return result;
1789 DEFUN ("ns-hide-others", Fns_hide_others, Sns_hide_others,
1790        0, 0, 0,
1791        doc: /* Hides all applications other than Emacs.  */)
1792      (void)
1794   check_ns ();
1795   [NSApp hideOtherApplications: NSApp];
1796   return Qnil;
1799 DEFUN ("ns-hide-emacs", Fns_hide_emacs, Sns_hide_emacs,
1800        1, 1, 0,
1801        doc: /* If ON is non-nil, the entire Emacs application is hidden.
1802 Otherwise if Emacs is hidden, it is unhidden.
1803 If ON is equal to `activate', Emacs is unhidden and becomes
1804 the active application.  */)
1805      (Lisp_Object on)
1807   check_ns ();
1808   if (EQ (on, intern ("activate")))
1809     {
1810       [NSApp unhide: NSApp];
1811       [NSApp activateIgnoringOtherApps: YES];
1812     }
1813   else if (NILP (on))
1814     [NSApp unhide: NSApp];
1815   else
1816     [NSApp hide: NSApp];
1817   return Qnil;
1821 DEFUN ("ns-emacs-info-panel", Fns_emacs_info_panel, Sns_emacs_info_panel,
1822        0, 0, 0,
1823        doc: /* Shows the 'Info' or 'About' panel for Emacs.  */)
1824      (void)
1826   check_ns ();
1827   [NSApp orderFrontStandardAboutPanel: nil];
1828   return Qnil;
1832 DEFUN ("ns-font-name", Fns_font_name, Sns_font_name, 1, 1, 0,
1833        doc: /* Determine font postscript or family name for font NAME.
1834 NAME should be a string containing either the font name or an XLFD
1835 font descriptor.  If string contains `fontset' and not
1836 `fontset-startup', it is left alone. */)
1837      (Lisp_Object name)
1839   char *nm;
1840   CHECK_STRING (name);
1841   nm = SDATA (name);
1843   if (nm[0] != '-')
1844     return name;
1845   if (strstr (nm, "fontset") && !strstr (nm, "fontset-startup"))
1846     return name;
1848   return build_string (ns_xlfd_to_fontname (SDATA (name)));
1852 DEFUN ("ns-list-colors", Fns_list_colors, Sns_list_colors, 0, 1, 0,
1853        doc: /* Return a list of all available colors.
1854 The optional argument FRAME is currently ignored.  */)
1855      (Lisp_Object frame)
1857   Lisp_Object list = Qnil;
1858   NSEnumerator *colorlists;
1859   NSColorList *clist;
1861   if (!NILP (frame))
1862     {
1863       CHECK_FRAME (frame);
1864       if (! FRAME_NS_P (XFRAME (frame)))
1865         error ("non-Nextstep frame used in `ns-list-colors'");
1866     }
1868   BLOCK_INPUT;
1870   colorlists = [[NSColorList availableColorLists] objectEnumerator];
1871   while (clist = [colorlists nextObject])
1872     {
1873       if ([[clist name] length] < 7 ||
1874           [[clist name] rangeOfString: @"PANTONE"].location == 0)
1875         {
1876           NSEnumerator *cnames = [[clist allKeys] reverseObjectEnumerator];
1877           NSString *cname;
1878           while (cname = [cnames nextObject])
1879             list = Fcons (build_string ([cname UTF8String]), list);
1880 /*           for (i = [[clist allKeys] count] - 1; i >= 0; i--)
1881                list = Fcons (build_string ([[[clist allKeys] objectAtIndex: i]
1882                                              UTF8String]), list); */
1883         }
1884     }
1886   UNBLOCK_INPUT;
1888   return list;
1892 DEFUN ("ns-list-services", Fns_list_services, Sns_list_services, 0, 0, 0,
1893        doc: /* List available Nextstep services by querying NSApp.  */)
1894      (void)
1896   Lisp_Object ret = Qnil;
1897   NSMenu *svcs;
1898   id delegate;
1900   check_ns ();
1901   svcs = [[NSMenu alloc] initWithTitle: @"Services"];
1902   [NSApp setServicesMenu: svcs];  /* this and next rebuild on <10.4 */
1903   [NSApp registerServicesMenuSendTypes: ns_send_types
1904                            returnTypes: ns_return_types];
1906 /* On Tiger, services menu updating was made lazier (waits for user to
1907    actually click on the menu), so we have to force things along: */
1908 #ifdef NS_IMPL_COCOA
1909   if (NSAppKitVersionNumber >= 744.0)
1910     {
1911       delegate = [svcs delegate];
1912       if (delegate != nil)
1913         {
1914           if ([delegate respondsToSelector: @selector (menuNeedsUpdate:)])
1915               [delegate menuNeedsUpdate: svcs];
1916           if ([delegate respondsToSelector:
1917                             @selector (menu:updateItem:atIndex:shouldCancel:)])
1918             {
1919               int i, len = [delegate numberOfItemsInMenu: svcs];
1920               for (i =0; i<len; i++)
1921                   [svcs addItemWithTitle: @"" action: NULL keyEquivalent: @""];
1922               for (i =0; i<len; i++)
1923                   if (![delegate menu: svcs
1924                            updateItem: (NSMenuItem *)[svcs itemAtIndex: i]
1925                               atIndex: i shouldCancel: NO])
1926                     break;
1927             }
1928         }
1929     }
1930 #endif
1932   [svcs setAutoenablesItems: NO];
1933 #ifdef NS_IMPL_COCOA
1934   [svcs update]; /* on OS X, converts from '/' structure */
1935 #endif
1937   ret = interpret_services_menu (svcs, Qnil, ret);
1938   return ret;
1942 DEFUN ("ns-perform-service", Fns_perform_service, Sns_perform_service,
1943        2, 2, 0,
1944        doc: /* Perform Nextstep SERVICE on SEND.
1945 SEND should be either a string or nil.
1946 The return value is the result of the service, as string, or nil if
1947 there was no result.  */)
1948      (Lisp_Object service, Lisp_Object send)
1950   id pb;
1951   NSString *svcName;
1952   char *utfStr;
1953   int len;
1955   CHECK_STRING (service);
1956   check_ns ();
1958   utfStr = SDATA (service);
1959   svcName = [NSString stringWithUTF8String: utfStr];
1961   pb =[NSPasteboard pasteboardWithUniqueName];
1962   ns_string_to_pasteboard (pb, send);
1964   if (NSPerformService (svcName, pb) == NO)
1965     Fsignal (Qquit, Fcons (build_string ("service not available"), Qnil));
1967   if ([[pb types] count] == 0)
1968     return build_string ("");
1969   return ns_string_from_pasteboard (pb);
1973 DEFUN ("ns-convert-utf8-nfd-to-nfc", Fns_convert_utf8_nfd_to_nfc,
1974        Sns_convert_utf8_nfd_to_nfc, 1, 1, 0,
1975        doc: /* Return an NFC string that matches the UTF-8 NFD string STR.  */)
1976      (Lisp_Object str)
1978 /* TODO: If GNUstep ever implements precomposedStringWithCanonicalMapping,
1979          remove this. */
1980   NSString *utfStr;
1982   CHECK_STRING (str);
1983   utfStr = [NSString stringWithUTF8String: SDATA (str)];
1984   if (![utfStr respondsToSelector:
1985                  @selector (precomposedStringWithCanonicalMapping)])
1986     {
1987       message1
1988         ("Warning: ns-convert-utf8-nfd-to-nfc unsupported under GNUstep.\n");
1989       return Qnil;
1990     }
1991   else
1992     utfStr = [utfStr precomposedStringWithCanonicalMapping];
1993   return build_string ([utfStr UTF8String]);
1997 #ifdef NS_IMPL_COCOA
1999 /* Compile and execute the AppleScript SCRIPT and return the error
2000    status as function value.  A zero is returned if compilation and
2001    execution is successful, in which case *RESULT is set to a Lisp
2002    string or a number containing the resulting script value.  Otherwise,
2003    1 is returned. */
2004 static int
2005 ns_do_applescript (Lisp_Object script, Lisp_Object *result)
2007   NSAppleEventDescriptor *desc;
2008   NSDictionary* errorDict;
2009   NSAppleEventDescriptor* returnDescriptor = NULL;
2011   NSAppleScript* scriptObject =
2012     [[NSAppleScript alloc] initWithSource:
2013                              [NSString stringWithUTF8String: SDATA (script)]];
2015   returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
2016   [scriptObject release];
2018   *result = Qnil;
2020   if (returnDescriptor != NULL)
2021     {
2022       // successful execution
2023       if (kAENullEvent != [returnDescriptor descriptorType])
2024         {
2025           *result = Qt;
2026           // script returned an AppleScript result
2027           if ((typeUnicodeText == [returnDescriptor descriptorType]) ||
2028 #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
2029               (typeUTF16ExternalRepresentation
2030                == [returnDescriptor descriptorType]) ||
2031 #endif
2032               (typeUTF8Text == [returnDescriptor descriptorType]) ||
2033               (typeCString == [returnDescriptor descriptorType]))
2034             {
2035               desc = [returnDescriptor coerceToDescriptorType: typeUTF8Text];
2036               if (desc)
2037                 *result = build_string([[desc stringValue] UTF8String]);
2038             }
2039           else
2040             {
2041               /* use typeUTF16ExternalRepresentation? */
2042               // coerce the result to the appropriate ObjC type
2043               desc = [returnDescriptor coerceToDescriptorType: typeUTF8Text];
2044               if (desc)
2045                 *result = make_number([desc int32Value]);
2046             }
2047         }
2048     }
2049   else
2050     {
2051       // no script result, return error
2052       return 1;
2053     }
2054   return 0;
2057 DEFUN ("ns-do-applescript", Fns_do_applescript, Sns_do_applescript, 1, 1, 0,
2058        doc: /* Execute AppleScript SCRIPT and return the result.
2059 If compilation and execution are successful, the resulting script value
2060 is returned as a string, a number or, in the case of other constructs, t.
2061 In case the execution fails, an error is signaled. */)
2062      (Lisp_Object script)
2064   Lisp_Object result;
2065   long status;
2067   CHECK_STRING (script);
2068   check_ns ();
2070   BLOCK_INPUT;
2071   status = ns_do_applescript (script, &result);
2072   UNBLOCK_INPUT;
2073   if (status == 0)
2074     return result;
2075   else if (!STRINGP (result))
2076     error ("AppleScript error %d", status);
2077   else
2078     error ("%s", SDATA (result));
2080 #endif
2084 /* ==========================================================================
2086     Miscellaneous functions not called through hooks
2088    ========================================================================== */
2091 /* called from image.c */
2092 FRAME_PTR
2093 check_x_frame (Lisp_Object frame)
2095   return check_ns_frame (frame);
2099 /* called from frame.c */
2100 struct ns_display_info *
2101 check_x_display_info (Lisp_Object frame)
2103   return check_ns_display_info (frame);
2107 void
2108 x_set_scroll_bar_default_width (struct frame *f)
2110   int wid = FRAME_COLUMN_WIDTH (f);
2111   FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = NS_SCROLL_BAR_WIDTH_DEFAULT;
2112   FRAME_CONFIG_SCROLL_BAR_COLS (f) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) +
2113                                       wid - 1) / wid;
2117 /* terms impl this instead of x-get-resource directly */
2118 const char *
2119 x_get_string_resource (XrmDatabase rdb, char *name, char *class)
2121   /* remove appname prefix; TODO: allow for !="Emacs" */
2122   char *toCheck = class + (!strncmp (class, "Emacs.", 6) ? 6 : 0);
2123   const char *res;
2124   check_ns ();
2126   if (inhibit_x_resources)
2127     /* --quick was passed, so this is a no-op.  */
2128     return NULL;
2130   res = [[[NSUserDefaults standardUserDefaults] objectForKey:
2131             [NSString stringWithUTF8String: toCheck]] UTF8String];
2132   return !res ? NULL :
2133       (!strncasecmp (res, "YES", 3) ? "true" :
2134           (!strncasecmp (res, "NO", 2) ? "false" : res));
2138 Lisp_Object
2139 x_get_focus_frame (struct frame *frame)
2141   struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (frame);
2142   Lisp_Object nsfocus;
2144   if (!dpyinfo->x_focus_frame)
2145     return Qnil;
2147   XSETFRAME (nsfocus, dpyinfo->x_focus_frame);
2148   return nsfocus;
2153 x_pixel_width (struct frame *f)
2155   return FRAME_PIXEL_WIDTH (f);
2160 x_pixel_height (struct frame *f)
2162   return FRAME_PIXEL_HEIGHT (f);
2167 x_char_width (struct frame *f)
2169   return FRAME_COLUMN_WIDTH (f);
2174 x_char_height (struct frame *f)
2176   return FRAME_LINE_HEIGHT (f);
2181 x_screen_planes (struct frame *f)
2183   return FRAME_NS_DISPLAY_INFO (f)->n_planes;
2187 void
2188 x_sync (struct frame *f)
2190   /* XXX Not implemented XXX */
2191   return;
2196 /* ==========================================================================
2198     Lisp definitions that, for whatever reason, we can't alias as 'ns-XXX'.
2200    ========================================================================== */
2203 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
2204        doc: /* Return t if the current Nextstep display supports the color COLOR.
2205 The optional argument FRAME is currently ignored.  */)
2206      (Lisp_Object color, Lisp_Object frame)
2208   NSColor * col;
2209   check_ns ();
2210   return ns_lisp_to_color (color, &col) ? Qnil : Qt;
2214 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
2215        doc: /* Internal function called by `color-values', which see.  */)
2216      (Lisp_Object color, Lisp_Object frame)
2218   NSColor * col;
2219   CGFloat red, green, blue, alpha;
2221   check_ns ();
2222   CHECK_STRING (color);
2224   if (ns_lisp_to_color (color, &col))
2225     return Qnil;
2227   [[col colorUsingColorSpaceName: NSCalibratedRGBColorSpace]
2228         getRed: &red green: &green blue: &blue alpha: &alpha];
2229   return list3 (make_number (lrint (red*65280)),
2230                 make_number (lrint (green*65280)),
2231                 make_number (lrint (blue*65280)));
2235 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
2236        doc: /* Return t if the Nextstep display supports color.
2237 The optional argument DISPLAY specifies which display to ask about.
2238 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2239 If omitted or nil, that stands for the selected frame's display.  */)
2240      (Lisp_Object display)
2242   NSWindowDepth depth;
2243   NSString *colorSpace;
2244   check_ns ();
2245   depth = [ns_get_screen (display) depth];
2246   colorSpace = NSColorSpaceFromDepth (depth);
2248   return    [colorSpace isEqualToString: NSDeviceWhiteColorSpace]
2249          || [colorSpace isEqualToString: NSCalibratedWhiteColorSpace]
2250       ? Qnil : Qt;
2254 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p,
2255        Sx_display_grayscale_p, 0, 1, 0,
2256        doc: /* Return t if the Nextstep display supports shades of gray.
2257 Note that color displays do support shades of gray.
2258 The optional argument DISPLAY specifies which display to ask about.
2259 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2260 If omitted or nil, that stands for the selected frame's display. */)
2261      (Lisp_Object display)
2263   NSWindowDepth depth;
2264   check_ns ();
2265   depth = [ns_get_screen (display) depth];
2267   return NSBitsPerPixelFromDepth (depth) > 1 ? Qt : Qnil;
2271 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
2272        0, 1, 0,
2273        doc: /* Return the width in pixels of the Nextstep display DISPLAY.
2274 The optional argument DISPLAY specifies which display to ask about.
2275 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2276 If omitted or nil, that stands for the selected frame's display.  */)
2277      (Lisp_Object display)
2279   check_ns ();
2280   return make_number ((int) [ns_get_screen (display) frame].size.width);
2284 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
2285        Sx_display_pixel_height, 0, 1, 0,
2286        doc: /* Return the height in pixels of the Nextstep display DISPLAY.
2287 The optional argument DISPLAY specifies which display to ask about.
2288 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2289 If omitted or nil, that stands for the selected frame's display.  */)
2290      (Lisp_Object display)
2292   check_ns ();
2293   return make_number ((int) [ns_get_screen (display) frame].size.height);
2297 DEFUN ("display-usable-bounds", Fns_display_usable_bounds,
2298        Sns_display_usable_bounds, 0, 1, 0,
2299        doc: /* Return the bounds of the usable part of the screen.
2300 The return value is a list of integers (LEFT TOP WIDTH HEIGHT), which
2301 are the boundaries of the usable part of the screen, excluding areas
2302 reserved for the Mac menu, dock, and so forth.
2304 The screen queried corresponds to DISPLAY, which should be either a
2305 frame, a display name (a string), or terminal ID.  If omitted or nil,
2306 that stands for the selected frame's display. */)
2307      (Lisp_Object display)
2309   int top;
2310   NSScreen *screen;
2311   NSRect vScreen;
2313   check_ns ();
2314   screen = ns_get_screen (display);
2315   if (!screen)
2316     return Qnil;
2318   vScreen = [screen visibleFrame];
2320   /* NS coordinate system is upside-down.
2321      Transform to screen-specific coordinates. */
2322   return list4 (make_number ((int) vScreen.origin.x),
2323                 make_number ((int) [screen frame].size.height
2324                              - vScreen.size.height - vScreen.origin.y),
2325                 make_number ((int) vScreen.size.width),
2326                 make_number ((int) vScreen.size.height));
2330 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
2331        0, 1, 0,
2332        doc: /* Return the number of bitplanes of the Nextstep display DISPLAY.
2333 The optional argument DISPLAY specifies which display to ask about.
2334 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2335 If omitted or nil, that stands for the selected frame's display.  */)
2336      (Lisp_Object display)
2338   check_ns ();
2339   return make_number
2340     (NSBitsPerPixelFromDepth ([ns_get_screen (display) depth]));
2344 DEFUN ("x-display-color-cells", Fx_display_color_cells,
2345        Sx_display_color_cells, 0, 1, 0,
2346        doc: /* Returns the number of color cells 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      (Lisp_Object display)
2352   struct ns_display_info *dpyinfo;
2353   check_ns ();
2354   
2355   dpyinfo = check_ns_display_info (display);
2356   /* We force 24+ bit depths to 24-bit to prevent an overflow.  */
2357   return make_number (1 << min (dpyinfo->n_planes, 24));
2361 /* Unused dummy def needed for compatibility. */
2362 Lisp_Object tip_frame;
2364 /* TODO: move to xdisp or similar */
2365 static void
2366 compute_tip_xy (struct frame *f,
2367                 Lisp_Object parms,
2368                 Lisp_Object dx,
2369                 Lisp_Object dy,
2370                 int width,
2371                 int height,
2372                 int *root_x,
2373                 int *root_y)
2375   Lisp_Object left, top;
2376   EmacsView *view = FRAME_NS_VIEW (f);
2377   NSPoint pt;
2379   /* Start with user-specified or mouse position.  */
2380   left = Fcdr (Fassq (Qleft, parms));
2381   top = Fcdr (Fassq (Qtop, parms));
2383   if (!INTEGERP (left) || !INTEGERP (top))
2384     {
2385       pt = last_mouse_motion_position;
2386       /* Convert to screen coordinates */
2387       pt = [view convertPoint: pt toView: nil];
2388       pt = [[view window] convertBaseToScreen: pt];
2389     }
2390   else
2391     {
2392       /* Absolute coordinates.  */
2393       pt.x = XINT (left);
2394       pt.y = x_display_pixel_height (FRAME_NS_DISPLAY_INFO (f)) - XINT (top)
2395         - height;
2396     }
2397   
2398   /* Ensure in bounds.  (Note, screen origin = lower left.) */
2399   if (INTEGERP (left))
2400     *root_x = pt.x;
2401   else if (pt.x + XINT (dx) <= 0)
2402     *root_x = 0; /* Can happen for negative dx */
2403   else if (pt.x + XINT (dx) + width
2404            <= x_display_pixel_width (FRAME_NS_DISPLAY_INFO (f)))
2405     /* It fits to the right of the pointer.  */
2406     *root_x = pt.x + XINT (dx);
2407   else if (width + XINT (dx) <= pt.x)
2408     /* It fits to the left of the pointer.  */
2409     *root_x = pt.x - width - XINT (dx);
2410   else
2411     /* Put it left justified on the screen -- it ought to fit that way.  */
2412     *root_x = 0;
2414   if (INTEGERP (top))
2415     *root_y = pt.y;
2416   else if (pt.y - XINT (dy) - height >= 0)
2417     /* It fits below the pointer.  */
2418     *root_y = pt.y - height - XINT (dy);
2419   else if (pt.y + XINT (dy) + height
2420            <= x_display_pixel_height (FRAME_NS_DISPLAY_INFO (f)))
2421     /* It fits above the pointer */
2422       *root_y = pt.y + XINT (dy);
2423   else
2424     /* Put it on the top.  */
2425     *root_y = x_display_pixel_height (FRAME_NS_DISPLAY_INFO (f)) - height;
2429 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
2430        doc: /* Show STRING in a \"tooltip\" window on frame FRAME.
2431 A tooltip window is a small window displaying a string.
2433 FRAME nil or omitted means use the selected frame.
2435 PARMS is an optional list of frame parameters which can be used to
2436 change the tooltip's appearance.
2438 Automatically hide the tooltip after TIMEOUT seconds.  TIMEOUT nil
2439 means use the default timeout of 5 seconds.
2441 If the list of frame parameters PARMS contains a `left' parameter,
2442 the tooltip is displayed at that x-position.  Otherwise it is
2443 displayed at the mouse position, with offset DX added (default is 5 if
2444 DX isn't specified).  Likewise for the y-position; if a `top' frame
2445 parameter is specified, it determines the y-position of the tooltip
2446 window, otherwise it is displayed at the mouse position, with offset
2447 DY added (default is -10).
2449 A tooltip's maximum size is specified by `x-max-tooltip-size'.
2450 Text larger than the specified size is clipped.  */)
2451      (Lisp_Object string, Lisp_Object frame, Lisp_Object parms, Lisp_Object timeout, Lisp_Object dx, Lisp_Object dy)
2453   int root_x, root_y;
2454   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2455   int count = SPECPDL_INDEX ();
2456   struct frame *f;
2457   char *str;
2458   NSSize size;
2460   specbind (Qinhibit_redisplay, Qt);
2462   GCPRO4 (string, parms, frame, timeout);
2464   CHECK_STRING (string);
2465   str = SDATA (string);
2466   f = check_x_frame (frame);
2467   if (NILP (timeout))
2468     timeout = make_number (5);
2469   else
2470     CHECK_NATNUM (timeout);
2472   if (NILP (dx))
2473     dx = make_number (5);
2474   else
2475     CHECK_NUMBER (dx);
2477   if (NILP (dy))
2478     dy = make_number (-10);
2479   else
2480     CHECK_NUMBER (dy);
2482   BLOCK_INPUT;
2483   if (ns_tooltip == nil)
2484     ns_tooltip = [[EmacsTooltip alloc] init];
2485   else
2486     Fx_hide_tip ();
2488   [ns_tooltip setText: str];
2489   size = [ns_tooltip frame].size;
2491   /* Move the tooltip window where the mouse pointer is.  Resize and
2492      show it.  */
2493   compute_tip_xy (f, parms, dx, dy, (int)size.width, (int)size.height,
2494                   &root_x, &root_y);
2496   [ns_tooltip showAtX: root_x Y: root_y for: XINT (timeout)];
2497   UNBLOCK_INPUT;
2499   UNGCPRO;
2500   return unbind_to (count, Qnil);
2504 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
2505        doc: /* Hide the current tooltip window, if there is any.
2506 Value is t if tooltip was open, nil otherwise.  */)
2507      (void)
2509   if (ns_tooltip == nil || ![ns_tooltip isActive])
2510     return Qnil;
2511   [ns_tooltip hide];
2512   return Qt;
2516 /* ==========================================================================
2518     Class implementations
2520    ========================================================================== */
2523 @implementation EmacsSavePanel
2524 #ifdef NS_IMPL_COCOA
2525 /* --------------------------------------------------------------------------
2526    These are overridden to intercept on OS X: ending panel restarts NSApp
2527    event loop if it is stopped.  Not sure if this is correct behavior,
2528    perhaps should check if running and if so send an appdefined.
2529    -------------------------------------------------------------------------- */
2530 - (void) ok: (id)sender
2532   [super ok: sender];
2533   panelOK = 1;
2534   [NSApp stop: self];
2536 - (void) cancel: (id)sender
2538   [super cancel: sender];
2539   [NSApp stop: self];
2541 #endif
2542 @end
2545 @implementation EmacsOpenPanel
2546 #ifdef NS_IMPL_COCOA
2547 /* --------------------------------------------------------------------------
2548    These are overridden to intercept on OS X: ending panel restarts NSApp
2549    event loop if it is stopped.  Not sure if this is correct behavior,
2550    perhaps should check if running and if so send an appdefined.
2551    -------------------------------------------------------------------------- */
2552 - (void) ok: (id)sender
2554   [super ok: sender];
2555   panelOK = 1;
2556   [NSApp stop: self];
2558 - (void) cancel: (id)sender
2560   [super cancel: sender];
2561   [NSApp stop: self];
2563 #endif
2564 @end
2567 @implementation EmacsFileDelegate
2568 /* --------------------------------------------------------------------------
2569    Delegate methods for Open/Save panels
2570    -------------------------------------------------------------------------- */
2571 - (BOOL)panel: (id)sender isValidFilename: (NSString *)filename
2573   return YES;
2575 - (BOOL)panel: (id)sender shouldShowFilename: (NSString *)filename
2577   return YES;
2579 - (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename
2580           confirmed: (BOOL)okFlag
2582   return filename;
2584 @end
2586 #endif
2589 /* ==========================================================================
2591     Lisp interface declaration
2593    ========================================================================== */
2596 void
2597 syms_of_nsfns (void)
2599   int i;
2601   Qfontsize = intern_c_string ("fontsize");
2602   staticpro (&Qfontsize);
2604   DEFVAR_LISP ("ns-icon-type-alist", &Vns_icon_type_alist,
2605                doc: /* Alist of elements (REGEXP . IMAGE) for images of icons associated to frames.
2606 If the title of a frame matches REGEXP, then IMAGE.tiff is
2607 selected as the image of the icon representing the frame when it's
2608 miniaturized.  If an element is t, then Emacs tries to select an icon
2609 based on the filetype of the visited file.
2611 The images have to be installed in a folder called English.lproj in the
2612 Emacs folder.  You have to restart Emacs after installing new icons.
2614 Example: Install an icon Gnus.tiff and execute the following code
2616   (setq ns-icon-type-alist
2617         (append ns-icon-type-alist
2618                 '((\"^\\\\*\\\\(Group\\\\*$\\\\|Summary \\\\|Article\\\\*$\\\\)\"
2619                    . \"Gnus\"))))
2621 When you miniaturize a Group, Summary or Article frame, Gnus.tiff will
2622 be used as the image of the icon representing the frame.  */);
2623   Vns_icon_type_alist = Fcons (Qt, Qnil);
2625   DEFVAR_LISP ("ns-version-string", &Vns_version_string,
2626                doc: /* Toolkit version for NS Windowing.  */);
2627   Vns_version_string = ns_appkit_version_str ();
2629   defsubr (&Sns_read_file_name);
2630   defsubr (&Sns_get_resource);
2631   defsubr (&Sns_set_resource);
2632   defsubr (&Sxw_display_color_p); /* this and next called directly by C code */
2633   defsubr (&Sx_display_grayscale_p);
2634   defsubr (&Sns_font_name);
2635   defsubr (&Sns_list_colors);
2636 #ifdef NS_IMPL_COCOA
2637   defsubr (&Sns_do_applescript);
2638 #endif
2639   defsubr (&Sxw_color_defined_p);
2640   defsubr (&Sxw_color_values);
2641   defsubr (&Sx_server_max_request_size);
2642   defsubr (&Sx_server_vendor);
2643   defsubr (&Sx_server_version);
2644   defsubr (&Sx_display_pixel_width);
2645   defsubr (&Sx_display_pixel_height);
2646   defsubr (&Sns_display_usable_bounds);
2647   defsubr (&Sx_display_mm_width);
2648   defsubr (&Sx_display_mm_height);
2649   defsubr (&Sx_display_screens);
2650   defsubr (&Sx_display_planes);
2651   defsubr (&Sx_display_color_cells);
2652   defsubr (&Sx_display_visual_class);
2653   defsubr (&Sx_display_backing_store);
2654   defsubr (&Sx_display_save_under);
2655   defsubr (&Sx_create_frame);
2656   defsubr (&Sx_open_connection);
2657   defsubr (&Sx_close_connection);
2658   defsubr (&Sx_display_list);
2660   defsubr (&Sns_hide_others);
2661   defsubr (&Sns_hide_emacs);
2662   defsubr (&Sns_emacs_info_panel);
2663   defsubr (&Sns_list_services);
2664   defsubr (&Sns_perform_service);
2665   defsubr (&Sns_convert_utf8_nfd_to_nfc);
2666   defsubr (&Sx_focus_frame);
2667   defsubr (&Sns_popup_font_panel);
2668   defsubr (&Sns_popup_color_panel);
2670   defsubr (&Sx_show_tip);
2671   defsubr (&Sx_hide_tip);
2673   /* used only in fontset.c */
2674   check_window_system_func = check_ns;
2678 // arch-tag: dc2a3f74-1123-4daa-8eed-fb78db6a5642