(echolisp): New rule.
[emacs.git] / src / nsfns.m
blobe01edcadcc915c2ee158d5c711de62cecc428b8f
1 /* Functions for the NeXT/Open/GNUstep and MacOSX window system.
2    Copyright (C) 1989, 1992, 1993, 1994, 2005, 2006, 2008, 2009
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>
35 #include "lisp.h"
36 #include "blockinput.h"
37 #include "nsterm.h"
38 #include "window.h"
39 #include "buffer.h"
40 #include "keyboard.h"
41 #include "termhooks.h"
42 #include "fontset.h"
43 #include "character.h"
44 #include "font.h"
46 #if 0
47 int fns_trace_num = 1;
48 #define NSTRACE(x)        fprintf (stderr, "%s:%d: [%d] " #x "\n",        \
49                                   __FILE__, __LINE__, ++fns_trace_num)
50 #else
51 #define NSTRACE(x)
52 #endif
54 #ifdef HAVE_NS
56 extern NSArray *ns_send_types, *ns_return_types, *ns_drag_types;
58 extern Lisp_Object Qforeground_color;
59 extern Lisp_Object Qbackground_color;
60 extern Lisp_Object Qcursor_color;
61 extern Lisp_Object Qinternal_border_width;
62 extern Lisp_Object Qvisibility;
63 extern Lisp_Object Qcursor_type;
64 extern Lisp_Object Qicon_type;
65 extern Lisp_Object Qicon_name;
66 extern Lisp_Object Qicon_left;
67 extern Lisp_Object Qicon_top;
68 extern Lisp_Object Qleft;
69 extern Lisp_Object Qright;
70 extern Lisp_Object Qtop;
71 extern Lisp_Object Qdisplay;
72 extern Lisp_Object Qvertical_scroll_bars;
73 extern Lisp_Object Qauto_raise;
74 extern Lisp_Object Qauto_lower;
75 extern Lisp_Object Qbox;
76 extern Lisp_Object Qscroll_bar_width;
77 extern Lisp_Object Qx_resource_name;
78 extern Lisp_Object Qface_set_after_frame_default;
79 extern Lisp_Object Qunderline, Qundefined;
80 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
81 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
83 Lisp_Object Qnone;
84 Lisp_Object Qbuffered;
85 Lisp_Object Qfontsize;
87 /* hack for OS X file panels */
88 char panelOK = 0;
90 /* Alist of elements (REGEXP . IMAGE) for images of icons associated
91    to frames.*/
92 static Lisp_Object Vns_icon_type_alist;
94 /* Toolkit version support. */
95 static Lisp_Object Vns_version_string;
97 EmacsTooltip *ns_tooltip;
99 /* Need forward declaration here to preserve organizational integrity of file */
100 Lisp_Object Fx_open_connection (Lisp_Object, Lisp_Object, Lisp_Object);
102 extern BOOL ns_in_resize;
105 /* ==========================================================================
107     Internal utility functions
109    ========================================================================== */
112 void
113 check_ns (void)
115  if (NSApp == nil)
116    error ("OpenStep is not in use or not initialized");
120 /* Nonzero if we can use mouse menus. */
122 have_menus_p ()
124   return NSApp != nil;
128 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
129    and checking validity for NS.  */
130 static FRAME_PTR
131 check_ns_frame (Lisp_Object frame)
133   FRAME_PTR f;
135   if (NILP (frame))
136       f = SELECTED_FRAME ();
137   else
138     {
139       CHECK_LIVE_FRAME (frame);
140       f = XFRAME (frame);
141     }
142   if (! FRAME_NS_P (f))
143     error ("non-Nextstep frame used");
144   return f;
148 /* Let the user specify an Nextstep display with a frame.
149    nil stands for the selected frame--or, if that is not an Nextstep frame,
150    the first Nextstep display on the list.  */
151 static struct ns_display_info *
152 check_ns_display_info (Lisp_Object frame)
154   if (NILP (frame))
155     {
156       struct frame *f = SELECTED_FRAME ();
157       if (FRAME_NS_P (f) && FRAME_LIVE_P (f) )
158         return FRAME_NS_DISPLAY_INFO (f);
159       else if (x_display_list != 0)
160         return x_display_list;
161       else
162         error ("Nextstep windows are not in use or not initialized");
163     }
164   else if (INTEGERP (frame))
165     {
166       struct terminal *t = get_terminal (frame, 1);
168       if (t->type != output_ns)
169         error ("Terminal %d is not a Nextstep display", XINT (frame));
171       return t->display_info.ns;
172     }
173   else if (STRINGP (frame))
174     return ns_display_info_for_name (frame);
175   else
176     {
177       FRAME_PTR f;
179       CHECK_LIVE_FRAME (frame);
180       f = XFRAME (frame);
181       if (! FRAME_NS_P (f))
182         error ("non-Nextstep frame used");
183       return FRAME_NS_DISPLAY_INFO (f);
184     }
185   return NULL;  /* shut compiler up */
189 static id
190 ns_get_window (Lisp_Object maybeFrame)
192   id view =nil, window =nil;
194   if (!FRAMEP (maybeFrame) || !FRAME_NS_P (XFRAME (maybeFrame)))
195     maybeFrame = selected_frame;/*wrong_type_argument (Qframep, maybeFrame); */
197   if (!NILP (maybeFrame))
198     view = FRAME_NS_VIEW (XFRAME (maybeFrame));
199   if (view) window =[view window];
201   return window;
205 static NSScreen *
206 ns_get_screen (Lisp_Object screen)
208   struct terminal *terminal = get_terminal (screen, 1);
209   if (terminal->type != output_ns)
210     // Not sure if this special case for nil is needed.  It does seem to be
211     // important in xfns.c for the make-frame call in frame-initialize,
212     // so let's keep it here for now.
213     return (NILP (screen) ? [NSScreen mainScreen] : NULL);
214   else
215     {
216       struct ns_display_info *dpyinfo = terminal->display_info.ns;
217       struct frame *f = dpyinfo->x_focus_frame;
218       if (!f)
219         f = dpyinfo->x_highlight_frame;
220       if (!f)
221         return NULL;
222       else
223         {
224           id window = nil;
225           Lisp_Object frame;
226           eassert (FRAME_NS_P (f));
227           XSETFRAME (frame, f);
228           window = ns_get_window (frame);
229           return window ? [window screen] : NULL;
230         }
231     }
235 /* Return the X display structure for the display named NAME.
236    Open a new connection if necessary.  */
237 struct ns_display_info *
238 ns_display_info_for_name (name)
239      Lisp_Object name;
241   Lisp_Object names;
242   struct ns_display_info *dpyinfo;
244   CHECK_STRING (name);
246   for (dpyinfo = x_display_list, names = ns_display_name_list;
247        dpyinfo;
248        dpyinfo = dpyinfo->next, names = XCDR (names))
249     {
250       Lisp_Object tem;
251       tem = Fstring_equal (XCAR (XCAR (names)), name);
252       if (!NILP (tem))
253         return dpyinfo;
254     }
256   error ("Emacs for OpenStep does not yet support multi-display.");
258   Fx_open_connection (name, Qnil, Qnil);
259   dpyinfo = x_display_list;
261   if (dpyinfo == 0)
262     error ("OpenStep on %s not responding.\n", SDATA (name));
264   return dpyinfo;
268 static Lisp_Object
269 interpret_services_menu (NSMenu *menu, Lisp_Object prefix, Lisp_Object old)
270 /* --------------------------------------------------------------------------
271    Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side
272    -------------------------------------------------------------------------- */
274   int i, count;
275   NSMenuItem *item;
276   const char *name;
277   Lisp_Object nameStr;
278   unsigned short key;
279   NSString *keys;
280   Lisp_Object res;
282   count = [menu numberOfItems];
283   for (i = 0; i<count; i++)
284     {
285       item = [menu itemAtIndex: i];
286       name = [[item title] UTF8String];
287       if (!name) continue;
289       nameStr = build_string (name);
291       if ([item hasSubmenu])
292         {
293           old = interpret_services_menu ([item submenu],
294                                         Fcons (nameStr, prefix), old);
295         }
296       else
297         {
298           keys = [item keyEquivalent];
299           if (keys && [keys length] )
300             {
301               key = [keys characterAtIndex: 0];
302               res = make_number (key|super_modifier);
303             }
304           else
305             {
306               res = Qundefined;
307             }
308           old = Fcons (Fcons (res,
309                             Freverse (Fcons (nameStr,
310                                            prefix))),
311                     old);
312         }
313     }
314   return old;
319 /* ==========================================================================
321     Frame parameter setters
323    ========================================================================== */
326 static void
327 x_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
329   NSColor *col;
331   if (ns_lisp_to_color (arg, &col))
332     {
333       store_frame_param (f, Qforeground_color, oldval);
334       error ("Unknown color");
335     }
337   [col retain];
338   [f->output_data.ns->foreground_color release];
339   f->output_data.ns->foreground_color = col;
341   if (FRAME_NS_VIEW (f))
342     {
343       update_face_from_frame_parameter (f, Qforeground_color, arg);
344       /*recompute_basic_faces (f); */
345       if (FRAME_VISIBLE_P (f))
346         redraw_frame (f);
347     }
351 static void
352 x_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
354   struct face *face;
355   NSColor *col;
356   NSView *view = FRAME_NS_VIEW (f);
357   float alpha;
359   if (ns_lisp_to_color (arg, &col))
360     {
361       store_frame_param (f, Qbackground_color, oldval);
362       error ("Unknown color");
363     }
365   /* clear the frame; in some instances the NS-internal GC appears not to
366      update, or it does update and cannot clear old text properly */
367   if (FRAME_VISIBLE_P (f))
368     ns_clear_frame (f);
370   [col retain];
371   [f->output_data.ns->background_color release];
372   f->output_data.ns->background_color = col;
373   if (view != nil)
374     {
375       [[view window] setBackgroundColor: col];
376       alpha = [col alphaComponent];
378       if (alpha != 1.0)
379           [[view window] setOpaque: NO];
380       else
381           [[view window] setOpaque: YES];
383       face = FRAME_DEFAULT_FACE (f);
384       if (face)
385         {
386           col = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f);
387           face->background
388              = (EMACS_UINT) [[col colorWithAlphaComponent: alpha] retain];
389           [col release];
391           update_face_from_frame_parameter (f, Qbackground_color, arg);
392         }
394       if (FRAME_VISIBLE_P (f))
395         redraw_frame (f);
396     }
400 static void
401 x_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
403   NSColor *col;
405   if (ns_lisp_to_color (arg, &col))
406     {
407       store_frame_param (f, Qcursor_color, oldval);
408       error ("Unknown color");
409     }
411   [FRAME_CURSOR_COLOR (f) release];
412   FRAME_CURSOR_COLOR (f) = [col retain];
414   if (FRAME_VISIBLE_P (f))
415     {
416       x_update_cursor (f, 0);
417       x_update_cursor (f, 1);
418     }
419   update_face_from_frame_parameter (f, Qcursor_color, arg);
423 static void
424 x_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
426   NSView *view = FRAME_NS_VIEW (f);
427   NSTRACE (x_set_icon_name);
429   if (ns_in_resize)
430     return;
432   /* see if it's changed */
433   if (STRINGP (arg))
434     {
435       if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
436         return;
437     }
438   else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
439     return;
441   f->icon_name = arg;
443   if (NILP (arg))
444     {
445       if (!NILP (f->title))
446         arg = f->title;
447       else
448         /* explicit name and no icon-name -> explicit_name */
449         if (f->explicit_name)
450           arg = f->name;
451         else
452           {
453             /* no explicit name and no icon-name ->
454                name has to be rebuild from icon_title_format */
455             windows_or_buffers_changed++;
456             return;
457           }
458     }
460   /* Don't change the name if it's already NAME.  */
461   if ([[view window] miniwindowTitle] &&
462       ([[[view window] miniwindowTitle]
463              isEqualToString: [NSString stringWithUTF8String:
464                                            SDATA (arg)]]))
465     return;
467   [[view window] setMiniwindowTitle:
468         [NSString stringWithUTF8String: SDATA (arg)]];
472 static void
473 ns_set_name_iconic (struct frame *f, Lisp_Object name, int explicit)
475   NSView *view = FRAME_NS_VIEW (f);
476   NSTRACE (ns_set_name_iconic);
478   if (ns_in_resize)
479     return;
481   /* Make sure that requests from lisp code override requests from
482      Emacs redisplay code.  */
483   if (explicit)
484     {
485       /* If we're switching from explicit to implicit, we had better
486          update the mode lines and thereby update the title.  */
487       if (f->explicit_name && NILP (name))
488         update_mode_lines = 1;
490       f->explicit_name = ! NILP (name);
491     }
492   else if (f->explicit_name)
493     name = f->name;
495   /* title overrides explicit name */
496   if (! NILP (f->title))
497     name = f->title;
499   /* icon_name overrides title and explicit name */
500   if (! NILP (f->icon_name))
501     name = f->icon_name;
503   if (NILP (name))
504     name = build_string([ns_app_name UTF8String]);
505   else
506     CHECK_STRING (name);
508   /* Don't change the name if it's already NAME.  */
509   if ([[view window] miniwindowTitle] &&
510       ([[[view window] miniwindowTitle]
511              isEqualToString: [NSString stringWithUTF8String:
512                                            SDATA (name)]]))
513     return;
515   [[view window] setMiniwindowTitle:
516         [NSString stringWithUTF8String: SDATA (name)]];
520 static void
521 ns_set_name (struct frame *f, Lisp_Object name, int explicit)
523   NSView *view = FRAME_NS_VIEW (f);
524   NSTRACE (ns_set_name);
526   if (ns_in_resize)
527     return;
529   /* Make sure that requests from lisp code override requests from
530      Emacs redisplay code.  */
531   if (explicit)
532     {
533       /* If we're switching from explicit to implicit, we had better
534          update the mode lines and thereby update the title.  */
535       if (f->explicit_name && NILP (name))
536         update_mode_lines = 1;
538       f->explicit_name = ! NILP (name);
539     }
540   else if (f->explicit_name)
541     return;
543   if (NILP (name))
544     name = build_string([ns_app_name UTF8String]);
546   f->name = name;
548   /* title overrides explicit name */
549   if (! NILP (f->title))
550     name = f->title;
552   CHECK_STRING (name);
554   /* Don't change the name if it's already NAME.  */
555   if ([[[view window] title]
556             isEqualToString: [NSString stringWithUTF8String:
557                                           SDATA (name)]])
558     return;
559   [[view window] setTitle: [NSString stringWithUTF8String:
560                                         SDATA (name)]];
564 /* This function should be called when the user's lisp code has
565    specified a name for the frame; the name will override any set by the
566    redisplay code.  */
567 static void
568 x_explicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
570   NSTRACE (x_explicitly_set_name);
571   ns_set_name_iconic (f, arg, 1);
572   ns_set_name (f, arg, 1);
576 /* This function should be called by Emacs redisplay code to set the
577    name; names set this way will never override names set by the user's
578    lisp code.  */
579 void
580 x_implicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
582   NSTRACE (x_implicitly_set_name);
583   if (FRAME_ICONIFIED_P (f))
584     ns_set_name_iconic (f, arg, 0);
585   else
586     ns_set_name (f, arg, 0);
590 /* Change the title of frame F to NAME.
591    If NAME is nil, use the frame name as the title.
593    If EXPLICIT is non-zero, that indicates that lisp code is setting the
594    name; if NAME is a string, set F's name to NAME and set
595    F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
597    If EXPLICIT is zero, that indicates that Emacs redisplay code is
598    suggesting a new name, which lisp code should override; if
599    F->explicit_name is set, ignore the new name; otherwise, set it.  */
600 static void
601 x_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
603   NSTRACE (x_set_title);
604   /* Don't change the title if it's already NAME.  */
605   if (EQ (name, f->title))
606     return;
608   update_mode_lines = 1;
610   f->title = name;
614 void
615 ns_set_name_as_filename (struct frame *f)
617   NSView *view = FRAME_NS_VIEW (f);
618   Lisp_Object name;
619   Lisp_Object buf = XWINDOW (f->selected_window)->buffer;
620   const char *title;
621   NSAutoreleasePool *pool;
622   NSTRACE (ns_set_name_as_filename);
624   if (f->explicit_name || ! NILP (f->title) || ns_in_resize)
625     return;
627   BLOCK_INPUT;
628   pool = [[NSAutoreleasePool alloc] init];
629   name =XBUFFER (buf)->filename;
630   if (NILP (name) || FRAME_ICONIFIED_P (f)) name =XBUFFER (buf)->name;
632   if (FRAME_ICONIFIED_P (f) && !NILP (f->icon_name))
633     name = f->icon_name;
635   if (NILP (name))
636     name = build_string([ns_app_name UTF8String]);
637   else
638     CHECK_STRING (name);
640   title = FRAME_ICONIFIED_P (f) ? [[[view window] miniwindowTitle] UTF8String]
641                                 : [[[view window] title] UTF8String];
643   if (title && (! strcmp (title, SDATA (name))))
644     {
645       [pool release];
646       UNBLOCK_INPUT;
647       return;
648     }
650   if (! FRAME_ICONIFIED_P (f))
651     {
652 #ifdef NS_IMPL_COCOA
653       /* work around a bug observed on 10.3 where
654          setTitleWithRepresentedFilename does not clear out previous state
655          if given filename does not exist */
656       NSString *str = [NSString stringWithUTF8String: SDATA (name)];
657       if (![[NSFileManager defaultManager] fileExistsAtPath: str])
658         {
659           [[view window] setTitleWithRepresentedFilename: @""];
660           [[view window] setTitle: str];
661         }
662       else
663         {
664           [[view window] setTitleWithRepresentedFilename: str];
665         }
666 #else
667       [[view window] setTitleWithRepresentedFilename:
668                          [NSString stringWithUTF8String: SDATA (name)]];
669 #endif
670       f->name = name;
671     }
672   else
673     {
674       [[view window] setMiniwindowTitle:
675             [NSString stringWithUTF8String: SDATA (name)]];
676     }
677   [pool release];
678   UNBLOCK_INPUT;
682 void
683 ns_set_doc_edited (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
685   NSView *view = FRAME_NS_VIEW (f);
686   NSAutoreleasePool *pool;
687   BLOCK_INPUT;
688   pool = [[NSAutoreleasePool alloc] init];
689   [[view window] setDocumentEdited: !NILP (arg)];
690   [pool release];
691   UNBLOCK_INPUT;
695 void
696 x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
698   int nlines;
699   int olines = FRAME_MENU_BAR_LINES (f);
700   if (FRAME_MINIBUF_ONLY_P (f))
701     return;
703   if (INTEGERP (value))
704     nlines = XINT (value);
705   else
706     nlines = 0;
708   FRAME_MENU_BAR_LINES (f) = 0;
709   if (nlines)
710     {
711       FRAME_EXTERNAL_MENU_BAR (f) = 1;
712       /* does for all frames, whereas we just want for one frame
713          [NSMenu setMenuBarVisible: YES]; */
714     }
715   else
716     {
717       if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
718         free_frame_menubar (f);
719       /*      [NSMenu setMenuBarVisible: NO]; */
720       FRAME_EXTERNAL_MENU_BAR (f) = 0;
721     }
725 /* toolbar support */
726 void
727 x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
729   int nlines;
730   Lisp_Object root_window;
732   if (FRAME_MINIBUF_ONLY_P (f))
733     return;
735   if (INTEGERP (value) && XINT (value) >= 0)
736     nlines = XFASTINT (value);
737   else
738     nlines = 0;
740   if (nlines)
741     {
742       FRAME_EXTERNAL_TOOL_BAR (f) = 1;
743       update_frame_tool_bar (f);
744     }
745   else
746     {
747       if (FRAME_EXTERNAL_TOOL_BAR (f))
748         {
749           free_frame_tool_bar (f);
750           FRAME_EXTERNAL_TOOL_BAR (f) = 0;
751         }
752     }
754   x_set_window_size (f, 0, f->text_cols, f->text_lines);
758 void
759 ns_implicitly_set_icon_type (struct frame *f)
761   Lisp_Object tem;
762   EmacsView *view = FRAME_NS_VIEW (f);
763   id image =nil;
764   Lisp_Object chain, elt;
765   NSAutoreleasePool *pool;
766   BOOL setMini = YES;
768   NSTRACE (ns_implicitly_set_icon_type);
770   BLOCK_INPUT;
771   pool = [[NSAutoreleasePool alloc] init];
772   if (f->output_data.ns->miniimage
773       && [[NSString stringWithUTF8String: SDATA (f->name)]
774                isEqualToString: [(NSImage *)f->output_data.ns->miniimage name]])
775     {
776       [pool release];
777       UNBLOCK_INPUT;
778       return;
779     }
781   tem = assq_no_quit (Qicon_type, f->param_alist);
782   if (CONSP (tem) && ! NILP (XCDR (tem)))
783     {
784       [pool release];
785       UNBLOCK_INPUT;
786       return;
787     }
789   for (chain = Vns_icon_type_alist;
790        (image = nil) && CONSP (chain);
791        chain = XCDR (chain))
792     {
793       elt = XCAR (chain);
794       /* special case: 't' means go by file type */
795       if (SYMBOLP (elt) && EQ (elt, Qt) && SDATA (f->name)[0] == '/')
796         {
797           NSString *str
798              = [NSString stringWithUTF8String: SDATA (f->name)];
799           if ([[NSFileManager defaultManager] fileExistsAtPath: str])
800             image = [[[NSWorkspace sharedWorkspace] iconForFile: str] retain];
801         }
802       else if (CONSP (elt) &&
803                STRINGP (XCAR (elt)) &&
804                STRINGP (XCDR (elt)) &&
805                fast_string_match (XCAR (elt), f->name) >= 0)
806         {
807           image = [EmacsImage allocInitFromFile: XCDR (elt)];
808           if (image == nil)
809             image = [[NSImage imageNamed:
810                                [NSString stringWithUTF8String:
811                                             SDATA (XCDR (elt))]] retain];
812         }
813     }
815   if (image == nil)
816     {
817       image = [[[NSWorkspace sharedWorkspace] iconForFileType: @"text"] retain];
818       setMini = NO;
819     }
821   [f->output_data.ns->miniimage release];
822   f->output_data.ns->miniimage = image;
823   [view setMiniwindowImage: setMini];
824   [pool release];
825   UNBLOCK_INPUT;
829 static void
830 x_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
832   EmacsView *view = FRAME_NS_VIEW (f);
833   id image = nil;
834   BOOL setMini = YES;
836   NSTRACE (x_set_icon_type);
838   if (!NILP (arg) && SYMBOLP (arg))
839     {
840       arg =build_string (SDATA (SYMBOL_NAME (arg)));
841       store_frame_param (f, Qicon_type, arg);
842     }
844   /* do it the implicit way */
845   if (NILP (arg))
846     {
847       ns_implicitly_set_icon_type (f);
848       return;
849     }
851   CHECK_STRING (arg);
853   image = [EmacsImage allocInitFromFile: arg];
854   if (image == nil)
855     image =[NSImage imageNamed: [NSString stringWithUTF8String:
856                                             SDATA (arg)]];
858   if (image == nil)
859     {
860       image = [NSImage imageNamed: @"text"];
861       setMini = NO;
862     }
864   f->output_data.ns->miniimage = image;
865   [view setMiniwindowImage: setMini];
869 /* Xism; we stub out (we do implement this in ns-win.el) */
871 XParseGeometry (char *string, int *x, int *y,
872                 unsigned int *width, unsigned int *height)
874   message1 ("Warning: XParseGeometry not supported under NS.\n");
875   return 0;
879 /* TODO: move to nsterm? */
881 ns_lisp_to_cursor_type (Lisp_Object arg)
883   char *str;
884   if (XTYPE (arg) == Lisp_String)
885     str = SDATA (arg);
886   else if (XTYPE (arg) == Lisp_Symbol)
887     str = SDATA (SYMBOL_NAME (arg));
888   else return -1;
889   if (!strcmp (str, "box"))     return FILLED_BOX_CURSOR;
890   if (!strcmp (str, "hollow"))  return HOLLOW_BOX_CURSOR;
891   if (!strcmp (str, "hbar"))    return HBAR_CURSOR;
892   if (!strcmp (str, "bar"))     return BAR_CURSOR;
893   if (!strcmp (str, "no"))      return NO_CURSOR;
894   return -1;
898 Lisp_Object
899 ns_cursor_type_to_lisp (int arg)
901   switch (arg)
902     {
903     case FILLED_BOX_CURSOR: return Qbox;
904     case HOLLOW_BOX_CURSOR: return intern ("hollow");
905     case HBAR_CURSOR:       return intern ("hbar");
906     case BAR_CURSOR:        return intern ("bar");
907     case NO_CURSOR:
908     default:                return intern ("no");
909     }
912 /* This is the same as the xfns.c definition.  */
913 void
914 x_set_cursor_type (f, arg, oldval)
915      FRAME_PTR f;
916      Lisp_Object arg, oldval;
918   set_frame_cursor_types (f, arg);
920   /* Make sure the cursor gets redrawn.  */
921   cursor_type_changed = 1;
925 /* called to set mouse pointer color, but all other terms use it to
926    initialize pointer types (and don't set the color ;) */
927 static void
928 x_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
930   /* don't think we can do this on Nextstep */
934 #define Str(x) #x
935 #define Xstr(x) Str(x)
937 static Lisp_Object
938 ns_appkit_version_str ()
940   char tmp[80];
942 #ifdef NS_IMPL_GNUSTEP
943   sprintf(tmp, "gnustep-gui-%s", Xstr(GNUSTEP_GUI_VERSION));
944 #elif defined(NS_IMPL_COCOA)
945   sprintf(tmp, "apple-appkit-%.2f", NSAppKitVersionNumber);
946 #else
947   tmp = "ns-unknown";
948 #endif
949   return build_string (tmp);
953 /* This is for use by x-server-version and collapses all version info we
954    have into a single int.  For a better picture of the implementation
955    running, use ns_appkit_version_str.*/
956 static int
957 ns_appkit_version_int ()
959 #ifdef NS_IMPL_GNUSTEP
960   return GNUSTEP_GUI_MAJOR_VERSION * 100 + GNUSTEP_GUI_MINOR_VERSION;
961 #elif defined(NS_IMPL_COCOA)
962   return (int)NSAppKitVersionNumber;
963 #endif
964   return 0;
968 static void
969 x_icon (struct frame *f, Lisp_Object parms)
970 /* --------------------------------------------------------------------------
971    Strangely-named function to set icon position parameters in frame.
972    This is irrelevant under OS X, but might be needed under GNUstep,
973    depending on the window manager used.  Note, this is not a standard
974    frame parameter-setter; it is called directly from x-create-frame.
975    -------------------------------------------------------------------------- */
977   Lisp_Object icon_x, icon_y;
978   struct ns_display_info *dpyinfo = check_ns_display_info (Qnil);
980   f->output_data.ns->icon_top = Qnil;
981   f->output_data.ns->icon_left = Qnil;
983   /* Set the position of the icon.  */
984   icon_x = x_get_arg (dpyinfo, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
985   icon_y = x_get_arg (dpyinfo, parms, Qicon_top, 0, 0,  RES_TYPE_NUMBER);
986   if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
987     {
988       CHECK_NUMBER (icon_x);
989       CHECK_NUMBER (icon_y);
990       f->output_data.ns->icon_top = icon_y;
991       f->output_data.ns->icon_left = icon_x;
992     }
993   else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
994     error ("Both left and top icon corners of icon must be specified");
998 /* Note: see frame.c for template, also where generic functions are impl */
999 frame_parm_handler ns_frame_parm_handlers[] =
1001   x_set_autoraise, /* generic OK */
1002   x_set_autolower, /* generic OK */
1003   x_set_background_color,
1004   0, /* x_set_border_color,  may be impossible under Nextstep */
1005   0, /* x_set_border_width,  may be impossible under Nextstep */
1006   x_set_cursor_color,
1007   x_set_cursor_type,
1008   x_set_font, /* generic OK */
1009   x_set_foreground_color,
1010   x_set_icon_name,
1011   x_set_icon_type,
1012   x_set_internal_border_width, /* generic OK */
1013   x_set_menu_bar_lines,
1014   x_set_mouse_color,
1015   x_explicitly_set_name,
1016   x_set_scroll_bar_width, /* generic OK */
1017   x_set_title,
1018   x_set_unsplittable, /* generic OK */
1019   x_set_vertical_scroll_bars, /* generic OK */
1020   x_set_visibility, /* generic OK */
1021   x_set_tool_bar_lines,
1022   0, /* x_set_scroll_bar_foreground, will ignore (not possible on NS) */
1023   0, /* x_set_scroll_bar_background,  will ignore (not possible on NS) */
1024   x_set_screen_gamma, /* generic OK */
1025   x_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */
1026   x_set_fringe_width, /* generic OK */
1027   x_set_fringe_width, /* generic OK */
1028   0, /* x_set_wait_for_wm, will ignore */
1029   0,  /* x_set_fullscreen will ignore */
1030   x_set_font_backend, /* generic OK */
1031   x_set_alpha,
1032   0, /* x_set_sticky */  
1037 /* ==========================================================================
1039     Lisp definitions
1041    ========================================================================== */
1043 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
1044        1, 1, 0,
1045        doc: /* Make a new Nextstep window, called a \"frame\" in Emacs terms.
1046 Return an Emacs frame object.
1047 PARMS is an alist of frame parameters.
1048 If the parameters specify that the frame should not have a minibuffer,
1049 and do not specify a specific minibuffer window to use,
1050 then `default-minibuffer-frame' must be a frame whose minibuffer can
1051 be shared by the new frame.  */)
1052      (parms)
1053      Lisp_Object parms;
1055   static int desc_ctr = 1;
1056   struct frame *f;
1057   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1058   Lisp_Object frame, tem;
1059   Lisp_Object name;
1060   int minibuffer_only = 0;
1061   int count = specpdl_ptr - specpdl;
1062   Lisp_Object display;
1063   struct ns_display_info *dpyinfo = NULL;
1064   Lisp_Object parent;
1065   struct kboard *kb;
1066   Lisp_Object tfont, tfontsize;
1067   int window_prompting = 0;
1068   int width, height;
1070   check_ns ();
1072   /* Seems a little strange, but other terms do it. Perhaps the code below
1073      is modifying something? */
1074   parms = Fcopy_alist (parms);
1076   display = x_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_STRING);
1077   if (EQ (display, Qunbound))
1078     display = Qnil;
1079   dpyinfo = check_ns_display_info (display);
1081   if (!dpyinfo->terminal->name)
1082     error ("Terminal is not live, can't create new frames on it");
1084   kb = dpyinfo->terminal->kboard;
1086   name = x_get_arg (dpyinfo, parms, Qname, 0, 0, RES_TYPE_STRING);
1087   if (!STRINGP (name)
1088       && ! EQ (name, Qunbound)
1089       && ! NILP (name))
1090     error ("Invalid frame name--not a string or nil");
1092   if (STRINGP (name))
1093     Vx_resource_name = name;
1094   else
1095     Vx_resource_name = Vinvocation_name;
1097   parent = x_get_arg (dpyinfo, parms, Qparent_id, 0, 0, RES_TYPE_NUMBER);
1098   if (EQ (parent, Qunbound))
1099     parent = Qnil;
1100   if (! NILP (parent))
1101     CHECK_NUMBER (parent);
1103   frame = Qnil;
1104   GCPRO4 (parms, parent, name, frame);
1106   tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
1107                   RES_TYPE_SYMBOL);
1108   if (EQ (tem, Qnone) || NILP (tem))
1109     {
1110       f = make_frame_without_minibuffer (Qnil, kb, display);
1111     }
1112   else if (EQ (tem, Qonly))
1113     {
1114       f = make_minibuffer_frame ();
1115       minibuffer_only = 1;
1116     }
1117   else if (WINDOWP (tem))
1118     {
1119       f = make_frame_without_minibuffer (tem, kb, display);
1120     }
1121   else
1122     {
1123       f = make_frame (1);
1124     }
1126   /* Set the name; the functions to which we pass f expect the name to
1127      be set.  */
1128   if (EQ (name, Qunbound) || NILP (name) || (XTYPE (name) != Lisp_String))
1129     {
1130       f->name = build_string ([ns_app_name UTF8String]);
1131       f->explicit_name =0;
1132     }
1133   else
1134     {
1135       f->name = name;
1136       f->explicit_name = 1;
1137       specbind (Qx_resource_name, name);
1138     }
1140   XSETFRAME (frame, f);
1141   FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
1143   f->terminal = dpyinfo->terminal;
1144   f->terminal->reference_count++;
1146   f->output_method = output_ns;
1147   f->output_data.ns = (struct ns_output *)xmalloc (sizeof *(f->output_data.ns));
1148   bzero (f->output_data.ns, sizeof (*(f->output_data.ns)));
1150   FRAME_FONTSET (f) = -1;
1152   /* record_unwind_protect (unwind_create_frame, frame); safety; maybe later? */
1154   f->icon_name = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
1155                             RES_TYPE_STRING);
1156   if (! STRINGP (f->icon_name))
1157     f->icon_name = Qnil;
1159   FRAME_NS_DISPLAY_INFO (f) = dpyinfo;
1161   f->output_data.ns->window_desc = desc_ctr++;
1162   if (!NILP (parent))
1163     {
1164       f->output_data.ns->parent_desc = (Window) XFASTINT (parent);
1165       f->output_data.ns->explicit_parent = 1;
1166     }
1167   else
1168     {
1169       f->output_data.ns->parent_desc = FRAME_NS_DISPLAY_INFO (f)->root_window;
1170       f->output_data.ns->explicit_parent = 0;
1171     }
1173   f->resx = dpyinfo->resx;
1174   f->resy = dpyinfo->resy;
1176   BLOCK_INPUT;
1177   register_font_driver (&nsfont_driver, f);
1178   x_default_parameter (f, parms, Qfont_backend, Qnil,
1179                         "fontBackend", "FontBackend", RES_TYPE_STRING);
1181   {
1182     /* use for default font name */
1183     id font = [NSFont userFixedPitchFontOfSize: -1.0]; /* default */
1184     tfontsize = x_default_parameter (f, parms, Qfontsize,
1185                                     make_number (0 /*(int)[font pointSize]*/),
1186                                     "fontSize", "FontSize", RES_TYPE_NUMBER);
1187     tfont = x_default_parameter (f, parms, Qfont,
1188                                  build_string ([[font fontName] UTF8String]),
1189                                  "font", "Font", RES_TYPE_STRING);
1190   }
1191   UNBLOCK_INPUT;
1193   x_default_parameter (f, parms, Qborder_width, make_number (0),
1194                        "borderwidth", "BorderWidth", RES_TYPE_NUMBER);
1195   x_default_parameter (f, parms, Qinternal_border_width, make_number (2),
1196                       "internalBorderWidth", "InternalBorderWidth",
1197                       RES_TYPE_NUMBER);
1199   /* default scrollbars on right on Mac */
1200   {
1201       Lisp_Object spos
1202 #ifdef NS_IMPL_GNUSTEP
1203           = Qt;
1204 #else
1205           = Qright;
1206 #endif
1207       x_default_parameter (f, parms, Qvertical_scroll_bars, spos,
1208                            "verticalScrollBars", "VerticalScrollBars",
1209                            RES_TYPE_SYMBOL);
1210   }
1211   x_default_parameter (f, parms, Qforeground_color, build_string ("Black"),
1212                       "foreground", "Foreground", RES_TYPE_STRING);
1213   x_default_parameter (f, parms, Qbackground_color, build_string ("White"),
1214                       "background", "Background", RES_TYPE_STRING);
1215   x_default_parameter (f, parms, Qcursor_color, build_string ("grey"),
1216                       "cursorColor", "CursorColor", RES_TYPE_STRING);
1217   /* FIXME: not suppported yet in Nextstep */
1218   x_default_parameter (f, parms, Qline_spacing, Qnil,
1219                        "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
1220   x_default_parameter (f, parms, Qleft_fringe, Qnil,
1221                        "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
1222   x_default_parameter (f, parms, Qright_fringe, Qnil,
1223                        "rightFringe", "RightFringe", RES_TYPE_NUMBER);
1224   /* end PENDING */
1226   init_frame_faces (f);
1228   x_default_parameter (f, parms, Qmenu_bar_lines, make_number (0), "menuBar",
1229                       "menuBar", RES_TYPE_NUMBER);
1230   x_default_parameter (f, parms, Qtool_bar_lines, make_number (0), "toolBar",
1231                       "toolBar", RES_TYPE_NUMBER);
1232   x_default_parameter (f, parms, Qbuffer_predicate, Qnil, "bufferPredicate",
1233                        "BufferPredicate", RES_TYPE_SYMBOL);
1234   x_default_parameter (f, parms, Qtitle, Qnil, "title", "Title",
1235                        RES_TYPE_STRING);
1237 /* TODO: other terms seem to get away w/o this complexity.. */
1238   if (NILP (Fassq (Qwidth, parms)))
1239     {
1240       Lisp_Object value
1241          = x_get_arg (dpyinfo, parms, Qwidth, "width", "Width",
1242                       RES_TYPE_NUMBER);
1243       if (! EQ (value, Qunbound))
1244         parms = Fcons (Fcons (Qwidth, value), parms);
1245     }
1246   if (NILP (Fassq (Qheight, parms)))
1247     {
1248       Lisp_Object value
1249          = x_get_arg (dpyinfo, parms, Qheight, "height", "Height",
1250                       RES_TYPE_NUMBER);
1251       if (! EQ (value, Qunbound))
1252         parms = Fcons (Fcons (Qheight, value), parms);
1253     }
1254   if (NILP (Fassq (Qleft, parms)))
1255     {
1256       Lisp_Object value
1257          = x_get_arg (dpyinfo, parms, Qleft, "left", "Left", RES_TYPE_NUMBER);
1258       if (! EQ (value, Qunbound))
1259         parms = Fcons (Fcons (Qleft, value), parms);
1260     }
1261   if (NILP (Fassq (Qtop, parms)))
1262     {
1263       Lisp_Object value
1264          = x_get_arg (dpyinfo, parms, Qtop, "top", "Top", RES_TYPE_NUMBER);
1265       if (! EQ (value, Qunbound))
1266         parms = Fcons (Fcons (Qtop, value), parms);
1267     }
1269   window_prompting = x_figure_window_size (f, parms, 1);
1271   tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
1272   f->no_split = minibuffer_only || (!EQ (tem, Qunbound) && !EQ (tem, Qnil));
1274   /* NOTE: on other terms, this is done in set_mouse_color, however this
1275      was not getting called under Nextstep */
1276   f->output_data.ns->text_cursor = [NSCursor IBeamCursor];
1277   f->output_data.ns->nontext_cursor = [NSCursor arrowCursor];
1278   f->output_data.ns->modeline_cursor = [NSCursor pointingHandCursor];
1279   f->output_data.ns->hand_cursor = [NSCursor pointingHandCursor];
1280   f->output_data.ns->hourglass_cursor = [NSCursor disappearingItemCursor];
1281   f->output_data.ns->horizontal_drag_cursor = [NSCursor resizeLeftRightCursor];
1282   FRAME_NS_DISPLAY_INFO (f)->vertical_scroll_bar_cursor
1283      = [NSCursor arrowCursor];
1284   f->output_data.ns->current_pointer = f->output_data.ns->text_cursor;
1286   [[EmacsView alloc] initFrameFromEmacs: f];
1288   x_icon (f, parms);
1290   /* It is now ok to make the frame official even if we get an error below.
1291      The frame needs to be on Vframe_list or making it visible won't work. */
1292   Vframe_list = Fcons (frame, Vframe_list);
1293   /*FRAME_NS_DISPLAY_INFO (f)->reference_count++; */
1295   x_default_parameter (f, parms, Qicon_type, Qnil, "bitmapIcon", "BitmapIcon",
1296                       RES_TYPE_SYMBOL);
1297   x_default_parameter (f, parms, Qauto_raise, Qnil, "autoRaise", "AutoRaiseLower",
1298                       RES_TYPE_BOOLEAN);
1299   x_default_parameter (f, parms, Qauto_lower, Qnil, "autoLower", "AutoLower",
1300                       RES_TYPE_BOOLEAN);
1301   x_default_parameter (f, parms, Qcursor_type, Qbox, "cursorType", "CursorType",
1302                       RES_TYPE_SYMBOL);
1303   x_default_parameter (f, parms, Qscroll_bar_width, Qnil, "scrollBarWidth",
1304                       "ScrollBarWidth", RES_TYPE_NUMBER);
1305   x_default_parameter (f, parms, Qalpha, Qnil, "alpha", "Alpha",
1306                       RES_TYPE_NUMBER);
1308   width = FRAME_COLS (f);
1309   height = FRAME_LINES (f);
1311   SET_FRAME_COLS (f, 0);
1312   FRAME_LINES (f) = 0;
1313   change_frame_size (f, height, width, 1, 0, 0);
1315   if (! f->output_data.ns->explicit_parent)
1316     {
1317       tem = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_SYMBOL);
1318       if (EQ (tem, Qunbound))
1319         tem = Qt;
1320       x_set_visibility (f, tem, Qnil);
1321       if (EQ (tem, Qicon))
1322         x_iconify_frame (f);
1323       else if (! NILP (tem))
1324         {
1325           x_make_frame_visible (f);
1326           f->async_visible = 1;
1327           [[FRAME_NS_VIEW (f) window] makeKeyWindow];
1328         }
1329       else
1330           f->async_visible = 0;
1331     }
1333   if (FRAME_HAS_MINIBUF_P (f)
1334       && (!FRAMEP (kb->Vdefault_minibuffer_frame)
1335           || !FRAME_LIVE_P (XFRAME (kb->Vdefault_minibuffer_frame))))
1336     kb->Vdefault_minibuffer_frame = frame;
1338   /* All remaining specified parameters, which have not been "used"
1339      by x_get_arg and friends, now go in the misc. alist of the frame.  */
1340   for (tem = parms; CONSP (tem); tem = XCDR (tem))
1341     if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
1342       f->param_alist = Fcons (XCAR (tem), f->param_alist);
1344   UNGCPRO;
1345   Vwindow_list = Qnil;
1347   return unbind_to (count, frame);
1351 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
1352        doc: /* Set the input focus to FRAME.
1353 FRAME nil means use the selected frame.  */)
1354      (frame)
1355      Lisp_Object frame;
1357   struct frame *f = check_ns_frame (frame);
1358   struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f);
1360   if (dpyinfo->x_focus_frame != f)
1361     {
1362       EmacsView *view = FRAME_NS_VIEW (f);
1363       BLOCK_INPUT;
1364       [NSApp activateIgnoringOtherApps: YES];
1365       [[view window] makeKeyAndOrderFront: view];
1366       UNBLOCK_INPUT;
1367     }
1369   return Qnil;
1373 DEFUN ("ns-popup-font-panel", Fns_popup_font_panel, Sns_popup_font_panel,
1374        0, 1, "",
1375        doc: /* Pop up the font panel. */)
1376      (frame)
1377      Lisp_Object frame;
1379   id fm;
1380   struct frame *f;
1382   check_ns ();
1383   fm = [NSFontManager sharedFontManager];
1384   if (NILP (frame))
1385     f = SELECTED_FRAME ();
1386   else
1387     {
1388       CHECK_FRAME (frame);
1389       f = XFRAME (frame);
1390     }
1392   [fm setSelectedFont: ((struct nsfont_info *)f->output_data.ns->font)->nsfont
1393            isMultiple: NO];
1394   [fm orderFrontFontPanel: NSApp];
1395   return Qnil;
1399 DEFUN ("ns-popup-color-panel", Fns_popup_color_panel, Sns_popup_color_panel,
1400        0, 1, "",
1401        doc: /* Pop up the color panel.  */)
1402      (frame)
1403      Lisp_Object frame;
1405   struct frame *f;
1407   check_ns ();
1408   if (NILP (frame))
1409     f = SELECTED_FRAME ();
1410   else
1411     {
1412       CHECK_FRAME (frame);
1413       f = XFRAME (frame);
1414     }
1416   [NSApp orderFrontColorPanel: NSApp];
1417   return Qnil;
1421 DEFUN ("ns-read-file-name", Fns_read_file_name, Sns_read_file_name, 1, 4, 0,
1422        doc: /* Use a graphical panel to read a file name, using prompt PROMPT.
1423 Optional arg DIR, if non-nil, supplies a default directory.
1424 Optional arg ISLOAD, if non-nil, means read a file name for saving.
1425 Optional arg INIT, if non-nil, provides a default file name to use.  */)
1426      (prompt, dir, isLoad, init)
1427      Lisp_Object prompt, dir, isLoad, init;
1429   static id fileDelegate = nil;
1430   int ret;
1431   id panel;
1432   Lisp_Object fname;
1434   NSString *promptS = NILP (prompt) || !STRINGP (prompt) ? nil :
1435     [NSString stringWithUTF8String: SDATA (prompt)];
1436   NSString *dirS = NILP (dir) || !STRINGP (dir) ?
1437     [NSString stringWithUTF8String: SDATA (current_buffer->directory)] :
1438     [NSString stringWithUTF8String: SDATA (dir)];
1439   NSString *initS = NILP (init) || !STRINGP (init) ? nil :
1440     [NSString stringWithUTF8String: SDATA (init)];
1442   check_ns ();
1444   if (fileDelegate == nil)
1445     fileDelegate = [EmacsFileDelegate new];
1447   [NSCursor setHiddenUntilMouseMoves: NO];
1449   if ([dirS characterAtIndex: 0] == '~')
1450     dirS = [dirS stringByExpandingTildeInPath];
1452   panel = NILP (isLoad) ?
1453     (id)[EmacsSavePanel savePanel] : (id)[EmacsOpenPanel openPanel];
1455   [panel setTitle: promptS];
1457   /* Puma (10.1) does not have */
1458   if ([panel respondsToSelector: @selector (setAllowsOtherFileTypes:)])
1459     [panel setAllowsOtherFileTypes: YES];
1461   [panel setTreatsFilePackagesAsDirectories: YES];
1462   [panel setDelegate: fileDelegate];
1464   panelOK = 0;
1465   BLOCK_INPUT;
1466   if (NILP (isLoad))
1467     {
1468       ret = [panel runModalForDirectory: dirS file: initS];
1469     }
1470   else
1471     {
1472       [panel setCanChooseDirectories: YES];
1473       ret = [panel runModalForDirectory: dirS file: initS types: nil];
1474     }
1476   ret = (ret == NSOKButton) || panelOK;
1478   if (ret)
1479     fname = build_string ([[panel filename] UTF8String]);
1481   [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
1482   UNBLOCK_INPUT;
1484   return ret ? fname : Qnil;
1488 DEFUN ("ns-get-resource", Fns_get_resource, Sns_get_resource, 2, 2, 0,
1489        doc: /* Return the value of the property NAME of OWNER from the defaults database.
1490 If OWNER is nil, Emacs is assumed.  */)
1491      (owner, name)
1492      Lisp_Object owner, name;
1494   const char *value;
1496   check_ns ();
1497   if (NILP (owner))
1498     owner = build_string([ns_app_name UTF8String]);
1499   CHECK_STRING (name);
1500 /*fprintf (stderr, "ns-get-resource checking resource '%s'\n", SDATA (name)); */
1502   value =[[[NSUserDefaults standardUserDefaults]
1503             objectForKey: [NSString stringWithUTF8String: SDATA (name)]]
1504            UTF8String];
1506   if (value)
1507     return build_string (value);
1508   return Qnil;
1512 DEFUN ("ns-set-resource", Fns_set_resource, Sns_set_resource, 3, 3, 0,
1513        doc: /* Set property NAME of OWNER to VALUE, from the defaults database.
1514 If OWNER is nil, Emacs is assumed.
1515 If VALUE is nil, the default is removed.  */)
1516      (owner, name, value)
1517      Lisp_Object owner, name, value;
1519   check_ns ();
1520   if (NILP (owner))
1521     owner = build_string ([ns_app_name UTF8String]);
1522   CHECK_STRING (name);
1523   if (NILP (value))
1524     {
1525       [[NSUserDefaults standardUserDefaults] removeObjectForKey:
1526                          [NSString stringWithUTF8String: SDATA (name)]];
1527     }
1528   else
1529     {
1530       CHECK_STRING (value);
1531       [[NSUserDefaults standardUserDefaults] setObject:
1532                 [NSString stringWithUTF8String: SDATA (value)]
1533                                         forKey: [NSString stringWithUTF8String:
1534                                                          SDATA (name)]];
1535     }
1537   return Qnil;
1541 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
1542        Sx_server_max_request_size,
1543        0, 1, 0,
1544        doc: /* This function is a no-op.  It is only present for completeness.  */)
1545      (display)
1546      Lisp_Object display;
1548   check_ns ();
1549   /* This function has no real equivalent under NeXTstep.  Return nil to
1550      indicate this. */
1551   return Qnil;
1555 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
1556        doc: /* Return the vendor ID string of Nextstep display server DISPLAY.
1557 DISPLAY should be either a frame or a display name (a string).
1558 If omitted or nil, the selected frame's display is used.  */)
1559      (display)
1560      Lisp_Object display;
1562 #ifdef NS_IMPL_GNUSTEP
1563   return build_string ("GNU");
1564 #else
1565   return build_string ("Apple");
1566 #endif
1570 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
1571        doc: /* Return the version numbers of the server of DISPLAY.
1572 The value is a list of three integers: the major and minor
1573 version numbers of the X Protocol in use, and the distributor-specific
1574 release number.  See also the function `x-server-vendor'.
1576 The optional argument DISPLAY specifies which display to ask about.
1577 DISPLAY should be either a frame or a display name (a string).
1578 If omitted or nil, that stands for the selected frame's display.  */)
1579      (display)
1580      Lisp_Object display;
1582   /*NOTE: it is unclear what would best correspond with "protocol";
1583           we return 10.3, meaning Panther, since this is roughly the
1584           level that GNUstep's APIs correspond to.
1585           The last number is where we distinguish between the Apple
1586           and GNUstep implementations ("distributor-specific release
1587           number") and give int'ized versions of major.minor. */
1588   return Fcons (make_number (10),
1589                 Fcons (make_number (3),
1590                        Fcons (make_number (ns_appkit_version_int()), Qnil)));
1594 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
1595        doc: /* Return the number of screens on Nextstep display server DISPLAY.
1596 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1597 If omitted or nil, the selected frame's display is used.  */)
1598      (display)
1599      Lisp_Object display;
1601   int num;
1603   check_ns ();
1604   num = [[NSScreen screens] count];
1606   return (num != 0) ? make_number (num) : Qnil;
1610 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height,
1611        0, 1, 0,
1612        doc: /* Return the height of Nextstep display server DISPLAY, in millimeters.
1613 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1614 If omitted or nil, the selected frame's display is used.  */)
1615      (display)
1616      Lisp_Object display;
1618   check_ns ();
1619   return make_number ((int)
1620                      ([ns_get_screen (display) frame].size.height/(92.0/25.4)));
1624 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width,
1625        0, 1, 0,
1626        doc: /* Return the width of Nextstep display server DISPLAY, in millimeters.
1627 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1628 If omitted or nil, the selected frame's display is used.  */)
1629      (display)
1630      Lisp_Object display;
1632   check_ns ();
1633   return make_number ((int)
1634                      ([ns_get_screen (display) frame].size.width/(92.0/25.4)));
1638 DEFUN ("x-display-backing-store", Fx_display_backing_store,
1639        Sx_display_backing_store, 0, 1, 0,
1640        doc: /* Return whether the Nexstep display DISPLAY supports backing store.
1641 The value may be `buffered', `retained', or `non-retained'.
1642 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1643 If omitted or nil, the selected frame's display is used.  */)
1644      (display)
1645      Lisp_Object display;
1647   check_ns ();
1648   switch ([ns_get_window (display) backingType])
1649     {
1650     case NSBackingStoreBuffered:
1651       return intern ("buffered");
1652     case NSBackingStoreRetained:
1653       return intern ("retained");
1654     case NSBackingStoreNonretained:
1655       return intern ("non-retained");
1656     default:
1657       error ("Strange value for backingType parameter of frame");
1658     }
1659   return Qnil;  /* not reached, shut compiler up */
1663 DEFUN ("x-display-visual-class", Fx_display_visual_class,
1664        Sx_display_visual_class, 0, 1, 0,
1665        doc: /* Return the visual class of the Nextstep display server DISPLAY.
1666 The value is one of the symbols `static-gray', `gray-scale',
1667 `static-color', `pseudo-color', `true-color', or `direct-color'.
1668 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1669 If omitted or nil, the selected frame's display is used.  */)
1670      (display)
1671      Lisp_Object display;
1673   NSWindowDepth depth;
1674   check_ns ();
1675   depth = [ns_get_screen (display) depth];
1677   if ( depth == NSBestDepth (NSCalibratedWhiteColorSpace, 2, 2, YES, NULL))
1678     return intern ("static-gray");
1679   else if (depth == NSBestDepth (NSCalibratedWhiteColorSpace, 8, 8, YES, NULL))
1680     return intern ("gray-scale");
1681   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 8, YES, NULL))
1682     return intern ("pseudo-color");
1683   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 4, 12, NO, NULL))
1684     return intern ("true-color");
1685   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 24, NO, NULL))
1686     return intern ("direct-color");
1687   else
1688     /* color mgmt as far as we do it is really handled by Nextstep itself anyway */
1689     return intern ("direct-color");
1693 DEFUN ("x-display-save-under", Fx_display_save_under,
1694        Sx_display_save_under, 0, 1, 0,
1695        doc: /* Non-nil if the Nextstep display server supports the save-under feature.
1696 The optional argument DISPLAY specifies which display to ask about.
1697 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1698 If omitted or nil, the selected frame's display is used.  */)
1699      (display)
1700      Lisp_Object display;
1702   check_ns ();
1703   switch ([ns_get_window (display) backingType])
1704     {
1705     case NSBackingStoreBuffered:
1706       return Qt;
1708     case NSBackingStoreRetained:
1709     case NSBackingStoreNonretained:
1710       return Qnil;
1712     default:
1713       error ("Strange value for backingType parameter of frame");
1714     }
1715   return Qnil;  /* not reached, shut compiler up */
1719 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
1720        1, 3, 0,
1721        doc: /* Open a connection to a Nextstep display server.
1722 DISPLAY is the name of the display to connect to.
1723 Optional arguments XRM-STRING and MUST-SUCCEED are currently ignored.  */)
1724      (display, resource_string, must_succeed)
1725      Lisp_Object display, resource_string, must_succeed;
1727   struct ns_display_info *dpyinfo;
1729   CHECK_STRING (display);
1731   nxatoms_of_nsselect ();
1732   dpyinfo = ns_term_init (display);
1733   if (dpyinfo == 0)
1734     {
1735       if (!NILP (must_succeed))
1736         fatal ("OpenStep on %s not responding.\n",
1737                SDATA (display));
1738       else
1739         error ("OpenStep on %s not responding.\n",
1740                SDATA (display));
1741     }
1743   /* Register our external input/output types, used for determining
1744      applicable services and also drag/drop eligibility. */
1745   ns_send_types = [[NSArray arrayWithObject: NSStringPboardType] retain];
1746   ns_return_types = [[NSArray arrayWithObject: NSStringPboardType] retain];
1747   ns_drag_types = [[NSArray arrayWithObjects:
1748                             NSStringPboardType,
1749                             NSTabularTextPboardType,
1750                             NSFilenamesPboardType,
1751                             NSURLPboardType,
1752                             NSColorPboardType,
1753                             NSFontPboardType, nil] retain];
1755   return Qnil;
1759 DEFUN ("x-close-connection", Fx_close_connection, Sx_close_connection,
1760        1, 1, 0,
1761        doc: /* Close the connection to the current Nextstep display server.
1762 The argument DISPLAY is currently ignored.  */)
1763      (display)
1764      Lisp_Object display;
1766   check_ns ();
1767   /*ns_delete_terminal (dpyinfo->terminal); */
1768   [NSApp terminate: NSApp];
1769   return Qnil;
1773 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
1774        doc: /* Return the list of display names that Emacs has connections to.  */)
1775      ()
1777   Lisp_Object tail, result;
1779   result = Qnil;
1780   for (tail = ns_display_name_list; CONSP (tail); tail = XCDR (tail))
1781     result = Fcons (XCAR (XCAR (tail)), result);
1783   return result;
1787 DEFUN ("ns-hide-others", Fns_hide_others, Sns_hide_others,
1788        0, 0, 0,
1789        doc: /* Hides all applications other than Emacs.  */)
1790      ()
1792   check_ns ();
1793   [NSApp hideOtherApplications: NSApp];
1794   return Qnil;
1797 DEFUN ("ns-hide-emacs", Fns_hide_emacs, Sns_hide_emacs,
1798        1, 1, 0,
1799        doc: /* If ON is non-nil, the entire Emacs application is hidden.
1800 Otherwise if Emacs is hidden, it is unhidden.
1801 If ON is equal to `activate', Emacs is unhidden and becomes
1802 the active application.  */)
1803      (on)
1804      Lisp_Object on;
1806   check_ns ();
1807   if (EQ (on, intern ("activate")))
1808     {
1809       [NSApp unhide: NSApp];
1810       [NSApp activateIgnoringOtherApps: YES];
1811     }
1812   else if (NILP (on))
1813     [NSApp unhide: NSApp];
1814   else
1815     [NSApp hide: NSApp];
1816   return Qnil;
1820 DEFUN ("ns-emacs-info-panel", Fns_emacs_info_panel, Sns_emacs_info_panel,
1821        0, 0, 0,
1822        doc: /* Shows the 'Info' or 'About' panel for Emacs.  */)
1823      ()
1825   check_ns ();
1826   [NSApp orderFrontStandardAboutPanel: nil];
1827   return Qnil;
1831 DEFUN ("ns-font-name", Fns_font_name, Sns_font_name, 1, 1, 0,
1832        doc: /* Determine font postscript or family name for font NAME.
1833 NAME should be a string containing either the font name or an XLFD
1834 font descriptor.  If string contains `fontset' and not
1835 `fontset-startup', it is left alone. */)
1836      (name)
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      (frame)
1856      Lisp_Object frame;
1858   Lisp_Object list = Qnil;
1859   NSEnumerator *colorlists;
1860   NSColorList *clist;
1862   if (!NILP (frame))
1863     {
1864       CHECK_FRAME (frame);
1865       if (! FRAME_NS_P (XFRAME (frame)))
1866         error ("non-Nextstep frame used in `ns-list-colors'");
1867     }
1869   BLOCK_INPUT;
1871   colorlists = [[NSColorList availableColorLists] objectEnumerator];
1872   while (clist = [colorlists nextObject])
1873     {
1874       if ([[clist name] length] < 7 ||
1875           [[clist name] rangeOfString: @"PANTONE"].location == 0)
1876         {
1877           NSEnumerator *cnames = [[clist allKeys] reverseObjectEnumerator];
1878           NSString *cname;
1879           while (cname = [cnames nextObject])
1880             list = Fcons (build_string ([cname UTF8String]), list);
1881 /*           for (i = [[clist allKeys] count] - 1; i >= 0; i--)
1882                list = Fcons (build_string ([[[clist allKeys] objectAtIndex: i]
1883                                              UTF8String]), list); */
1884         }
1885     }
1887   UNBLOCK_INPUT;
1889   return list;
1893 DEFUN ("ns-list-services", Fns_list_services, Sns_list_services, 0, 0, 0,
1894        doc: /* List available Nextstep services by querying NSApp.  */)
1895      ()
1897   Lisp_Object ret = Qnil;
1898   NSMenu *svcs;
1899   id delegate;
1901   check_ns ();
1902   svcs = [[NSMenu alloc] initWithTitle: @"Services"];
1903   [NSApp setServicesMenu: svcs];  /* this and next rebuild on <10.4 */
1904   [NSApp registerServicesMenuSendTypes: ns_send_types
1905                            returnTypes: ns_return_types];
1907 /* On Tiger, services menu updating was made lazier (waits for user to
1908    actually click on the menu), so we have to force things along: */
1909 #ifdef NS_IMPL_COCOA
1910   if (NSAppKitVersionNumber >= 744.0)
1911     {
1912       delegate = [svcs delegate];
1913       if (delegate != nil)
1914         {
1915           if ([delegate respondsToSelector: @selector (menuNeedsUpdate:)])
1916               [delegate menuNeedsUpdate: svcs];
1917           if ([delegate respondsToSelector:
1918                             @selector (menu:updateItem:atIndex:shouldCancel:)])
1919             {
1920               int i, len = [delegate numberOfItemsInMenu: svcs];
1921               for (i =0; i<len; i++)
1922                   [svcs addItemWithTitle: @"" action: NULL keyEquivalent: @""];
1923               for (i =0; i<len; i++)
1924                   if (![delegate menu: svcs
1925                            updateItem: (NSMenuItem *)[svcs itemAtIndex: i]
1926                               atIndex: i shouldCancel: NO])
1927                     break;
1928             }
1929         }
1930     }
1931 #endif
1933   [svcs setAutoenablesItems: NO];
1934 #ifdef NS_IMPL_COCOA
1935   [svcs update]; /* on OS X, converts from '/' structure */
1936 #endif
1938   ret = interpret_services_menu (svcs, Qnil, ret);
1939   return ret;
1943 DEFUN ("ns-perform-service", Fns_perform_service, Sns_perform_service,
1944        2, 2, 0,
1945        doc: /* Perform Nextstep SERVICE on SEND.
1946 SEND should be either a string or nil.
1947 The return value is the result of the service, as string, or nil if
1948 there was no result.  */)
1949      (service, send)
1950      Lisp_Object service, send;
1952   id pb;
1953   NSString *svcName;
1954   char *utfStr;
1955   int len;
1957   CHECK_STRING (service);
1958   check_ns ();
1960   utfStr = SDATA (service);
1961   svcName = [NSString stringWithUTF8String: utfStr];
1963   pb =[NSPasteboard pasteboardWithUniqueName];
1964   ns_string_to_pasteboard (pb, send);
1966   if (NSPerformService (svcName, pb) == NO)
1967     Fsignal (Qquit, Fcons (build_string ("service not available"), Qnil));
1969   if ([[pb types] count] == 0)
1970     return build_string ("");
1971   return ns_string_from_pasteboard (pb);
1975 DEFUN ("ns-convert-utf8-nfd-to-nfc", Fns_convert_utf8_nfd_to_nfc,
1976        Sns_convert_utf8_nfd_to_nfc, 1, 1, 0,
1977        doc: /* Return an NFC string that matches the UTF-8 NFD string STR.  */)
1978     (str)
1979     Lisp_Object str;
1981 /* TODO: If GNUstep ever implements precomposedStringWithCanonicalMapping,
1982          remove this. */
1983   NSString *utfStr;
1985   CHECK_STRING (str);
1986   utfStr = [NSString stringWithUTF8String: SDATA (str)];
1987   if (![utfStr respondsToSelector:
1988                  @selector (precomposedStringWithCanonicalMapping)])
1989     {
1990       message1
1991         ("Warning: ns-convert-utf8-nfd-to-nfc unsupported under GNUstep.\n");
1992       return Qnil;
1993     }
1994   else
1995     utfStr = [utfStr precomposedStringWithCanonicalMapping];
1996   return build_string ([utfStr UTF8String]);
2000 #ifdef NS_IMPL_COCOA
2002 /* Compile and execute the AppleScript SCRIPT and return the error
2003    status as function value.  A zero is returned if compilation and
2004    execution is successful, in which case *RESULT is set to a Lisp
2005    string or a number containing the resulting script value.  Otherwise,
2006    1 is returned. */
2007 static int
2008 ns_do_applescript (script, result)
2009      Lisp_Object script, *result;
2011   NSAppleEventDescriptor *desc;
2012   NSDictionary* errorDict;
2013   NSAppleEventDescriptor* returnDescriptor = NULL;
2015   NSAppleScript* scriptObject =
2016     [[NSAppleScript alloc] initWithSource:
2017                              [NSString stringWithUTF8String: SDATA (script)]];
2019   returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
2020   [scriptObject release];
2022   *result = Qnil;
2024   if (returnDescriptor != NULL)
2025     {
2026       // successful execution
2027       if (kAENullEvent != [returnDescriptor descriptorType])
2028         {
2029           *result = Qt;
2030           // script returned an AppleScript result
2031           if ((typeUnicodeText == [returnDescriptor descriptorType]) ||
2032 #if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_4
2033               (typeUTF16ExternalRepresentation
2034                == [returnDescriptor descriptorType]) ||
2035 #endif
2036               (typeUTF8Text == [returnDescriptor descriptorType]) ||
2037               (typeCString == [returnDescriptor descriptorType]))
2038             {
2039               desc = [returnDescriptor coerceToDescriptorType: typeUTF8Text];
2040               if (desc)
2041                 *result = build_string([[desc stringValue] UTF8String]);
2042             }
2043           else
2044             {
2045               /* use typeUTF16ExternalRepresentation? */
2046               // coerce the result to the appropriate ObjC type
2047               desc = [returnDescriptor coerceToDescriptorType: typeUTF8Text];
2048               if (desc)
2049                 *result = make_number([desc int32Value]);
2050             }
2051         }
2052     }
2053   else
2054     {
2055       // no script result, return error
2056       return 1;
2057     }
2058   return 0;
2061 DEFUN ("ns-do-applescript", Fns_do_applescript, Sns_do_applescript, 1, 1, 0,
2062        doc: /* Execute AppleScript SCRIPT and return the result.
2063 If compilation and execution are successful, the resulting script value
2064 is returned as a string, a number or, in the case of other constructs, t.
2065 In case the execution fails, an error is signaled. */)
2066     (script)
2067     Lisp_Object script;
2069   Lisp_Object result;
2070   long status;
2072   CHECK_STRING (script);
2073   check_ns ();
2075   BLOCK_INPUT;
2076   status = ns_do_applescript (script, &result);
2077   UNBLOCK_INPUT;
2078   if (status == 0)
2079     return result;
2080   else if (!STRINGP (result))
2081     error ("AppleScript error %d", status);
2082   else
2083     error ("%s", SDATA (result));
2085 #endif
2089 /* ==========================================================================
2091     Miscellaneous functions not called through hooks
2093    ========================================================================== */
2096 /* called from image.c */
2097 FRAME_PTR
2098 check_x_frame (Lisp_Object frame)
2100   return check_ns_frame (frame);
2104 /* called from frame.c */
2105 struct ns_display_info *
2106 check_x_display_info (Lisp_Object frame)
2108   return check_ns_display_info (frame);
2112 void
2113 x_set_scroll_bar_default_width (f)
2114      struct frame *f;
2116   int wid = FRAME_COLUMN_WIDTH (f);
2117   FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = NS_SCROLL_BAR_WIDTH_DEFAULT;
2118   FRAME_CONFIG_SCROLL_BAR_COLS (f) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) +
2119                                       wid - 1) / wid;
2123 /* terms impl this instead of x-get-resource directly */
2124 const char *
2125 x_get_string_resource (XrmDatabase rdb, char *name, char *class)
2127   /* remove appname prefix; TODO: allow for !="Emacs" */
2128   char *toCheck = class + (!strncmp (class, "Emacs.", 6) ? 6 : 0);
2129   const char *res;
2130   check_ns ();
2132   if (inhibit_x_resources)
2133     /* --quick was passed, so this is a no-op.  */
2134     return NULL;
2136   res = [[[NSUserDefaults standardUserDefaults] objectForKey:
2137             [NSString stringWithUTF8String: toCheck]] UTF8String];
2138   return !res ? NULL :
2139       (!strncasecmp (res, "YES", 3) ? "true" :
2140           (!strncasecmp (res, "NO", 2) ? "false" : res));
2144 Lisp_Object
2145 x_get_focus_frame (struct frame *frame)
2147   struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (frame);
2148   Lisp_Object nsfocus;
2150   if (!dpyinfo->x_focus_frame)
2151     return Qnil;
2153   XSETFRAME (nsfocus, dpyinfo->x_focus_frame);
2154   return nsfocus;
2159 x_pixel_width (struct frame *f)
2161   return FRAME_PIXEL_WIDTH (f);
2166 x_pixel_height (struct frame *f)
2168   return FRAME_PIXEL_HEIGHT (f);
2173 x_char_width (struct frame *f)
2175   return FRAME_COLUMN_WIDTH (f);
2180 x_char_height (struct frame *f)
2182   return FRAME_LINE_HEIGHT (f);
2187 x_screen_planes (struct frame *f)
2189   return FRAME_NS_DISPLAY_INFO (f)->n_planes;
2193 void
2194 x_sync (Lisp_Object frame)
2196   /* XXX Not implemented XXX */
2197   return;
2202 /* ==========================================================================
2204     Lisp definitions that, for whatever reason, we can't alias as 'ns-XXX'.
2206    ========================================================================== */
2209 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
2210        doc: /* Return t if the current Nextstep display supports the color COLOR.
2211 The optional argument FRAME is currently ignored.  */)
2212      (color, frame)
2213      Lisp_Object color, frame;
2215   NSColor * col;
2216   check_ns ();
2217   return ns_lisp_to_color (color, &col) ? Qnil : Qt;
2221 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
2222        doc: /* Internal function called by `color-values', which see.  */)
2223      (color, frame)
2224      Lisp_Object color, frame;
2226   NSColor * col;
2227   CGFloat red, green, blue, alpha;
2229   check_ns ();
2230   CHECK_STRING (color);
2232   if (ns_lisp_to_color (color, &col))
2233     return Qnil;
2235   [[col colorUsingColorSpaceName: NSCalibratedRGBColorSpace]
2236         getRed: &red green: &green blue: &blue alpha: &alpha];
2237   return list3 (make_number (lrint (red*65280)),
2238                 make_number (lrint (green*65280)),
2239                 make_number (lrint (blue*65280)));
2243 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
2244        doc: /* Return t if the Nextstep display supports color.
2245 The optional argument DISPLAY specifies which display to ask about.
2246 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2247 If omitted or nil, that stands for the selected frame's display.  */)
2248      (display)
2249      Lisp_Object display;
2251   NSWindowDepth depth;
2252   NSString *colorSpace;
2253   check_ns ();
2254   depth = [ns_get_screen (display) depth];
2255   colorSpace = NSColorSpaceFromDepth (depth);
2257   return    [colorSpace isEqualToString: NSDeviceWhiteColorSpace]
2258          || [colorSpace isEqualToString: NSCalibratedWhiteColorSpace]
2259       ? Qnil : Qt;
2263 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p,
2264        Sx_display_grayscale_p, 0, 1, 0,
2265        doc: /* Return t if the Nextstep display supports shades of gray.
2266 Note that color displays do support shades of gray.
2267 The optional argument DISPLAY specifies which display to ask about.
2268 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2269 If omitted or nil, that stands for the selected frame's display. */)
2270      (display)
2271      Lisp_Object display;
2273   NSWindowDepth depth;
2274   check_ns ();
2275   depth = [ns_get_screen (display) depth];
2277   return NSBitsPerPixelFromDepth (depth) > 1 ? Qt : Qnil;
2281 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
2282        0, 1, 0,
2283        doc: /* Return the width in pixels of the Nextstep display DISPLAY.
2284 The optional argument DISPLAY specifies which display to ask about.
2285 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2286 If omitted or nil, that stands for the selected frame's display.  */)
2287      (display)
2288      Lisp_Object display;
2290   check_ns ();
2291   return make_number ((int) [ns_get_screen (display) frame].size.width);
2295 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
2296        Sx_display_pixel_height, 0, 1, 0,
2297        doc: /* Return the height in pixels of the Nextstep display DISPLAY.
2298 The optional argument DISPLAY specifies which display to ask about.
2299 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2300 If omitted or nil, that stands for the selected frame's display.  */)
2301      (display)
2302      Lisp_Object display;
2304   check_ns ();
2305   return make_number ((int) [ns_get_screen (display) frame].size.height);
2309 DEFUN ("display-usable-bounds", Fns_display_usable_bounds,
2310        Sns_display_usable_bounds, 0, 1, 0,
2311        doc: /* Return the bounds of the usable part of the screen.
2312 The return value is a list of integers (LEFT TOP WIDTH HEIGHT), which
2313 are the boundaries of the usable part of the screen, excluding areas
2314 reserved for the Mac menu, dock, and so forth.
2316 The screen queried corresponds to DISPLAY, which should be either a
2317 frame, a display name (a string), or terminal ID.  If omitted or nil,
2318 that stands for the selected frame's display. */)
2319      (display)
2320      Lisp_Object display;
2322   int top;
2323   NSRect vScreen;
2325   check_ns ();
2326   vScreen = [ns_get_screen (display) visibleFrame];
2327   top = vScreen.origin.y == 0.0 ?
2328     (int) [ns_get_screen (display) frame].size.height - vScreen.size.height : 0;
2330   return list4 (make_number ((int) vScreen.origin.x),
2331                 make_number (top),
2332                 make_number ((int) vScreen.size.width),
2333                 make_number ((int) vScreen.size.height));
2337 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
2338        0, 1, 0,
2339        doc: /* Return the number of bitplanes of the Nextstep display DISPLAY.
2340 The optional argument DISPLAY specifies which display to ask about.
2341 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2342 If omitted or nil, that stands for the selected frame's display.  */)
2343      (display)
2344      Lisp_Object display;
2346   check_ns ();
2347   return make_number
2348     (NSBitsPerPixelFromDepth ([ns_get_screen (display) depth]));
2352 DEFUN ("x-display-color-cells", Fx_display_color_cells,
2353        Sx_display_color_cells, 0, 1, 0,
2354        doc: /* Returns the number of color cells of the Nextstep display DISPLAY.
2355 The optional argument DISPLAY specifies which display to ask about.
2356 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2357 If omitted or nil, that stands for the selected frame's display.  */)
2358      (display)
2359      Lisp_Object display;
2361   check_ns ();
2362   struct ns_display_info *dpyinfo = check_ns_display_info (display);
2364   /* We force 24+ bit depths to 24-bit to prevent an overflow.  */
2365   return make_number (1 << min (dpyinfo->n_planes, 24));
2369 /* Unused dummy def needed for compatibility. */
2370 Lisp_Object tip_frame;
2372 /* TODO: move to xdisp or similar */
2373 static void
2374 compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
2375      struct frame *f;
2376      Lisp_Object parms, dx, dy;
2377      int width, height;
2378      int *root_x, *root_y;
2380   Lisp_Object left, top;
2381   EmacsView *view = FRAME_NS_VIEW (f);
2382   NSPoint pt;
2384   /* Start with user-specified or mouse position.  */
2385   left = Fcdr (Fassq (Qleft, parms));
2386   if (INTEGERP (left))
2387     pt.x = XINT (left);
2388   else
2389     pt.x = last_mouse_motion_position.x;
2390   top = Fcdr (Fassq (Qtop, parms));
2391   if (INTEGERP (top))
2392     pt.y = XINT (top);
2393   else
2394     pt.y = last_mouse_motion_position.y;
2396   /* Convert to screen coordinates */
2397   pt = [view convertPoint: pt toView: nil];
2398   pt = [[view window] convertBaseToScreen: pt];
2400   /* Ensure in bounds.  (Note, screen origin = lower left.) */
2401   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 (pt.y - XINT (dy) - height >= 0)
2415     /* It fits below the pointer.  */
2416     *root_y = pt.y - height - XINT (dy);
2417   else if (pt.y + XINT (dy) + height
2418            <= x_display_pixel_height (FRAME_NS_DISPLAY_INFO (f)))
2419     /* It fits above the pointer */
2420       *root_y = pt.y + XINT (dy);
2421   else
2422     /* Put it on the top.  */
2423     *root_y = x_display_pixel_height (FRAME_NS_DISPLAY_INFO (f)) - height;
2427 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
2428        doc: /* Show STRING in a \"tooltip\" window on frame FRAME.
2429 A tooltip window is a small window displaying a string.
2431 FRAME nil or omitted means use the selected frame.
2433 PARMS is an optional list of frame parameters which can be used to
2434 change the tooltip's appearance.
2436 Automatically hide the tooltip after TIMEOUT seconds.  TIMEOUT nil
2437 means use the default timeout of 5 seconds.
2439 If the list of frame parameters PARMS contains a `left' parameter,
2440 the tooltip is displayed at that x-position.  Otherwise it is
2441 displayed at the mouse position, with offset DX added (default is 5 if
2442 DX isn't specified).  Likewise for the y-position; if a `top' frame
2443 parameter is specified, it determines the y-position of the tooltip
2444 window, otherwise it is displayed at the mouse position, with offset
2445 DY added (default is -10).
2447 A tooltip's maximum size is specified by `x-max-tooltip-size'.
2448 Text larger than the specified size is clipped.  */)
2449      (string, frame, parms, timeout, dx, dy)
2450      Lisp_Object string, frame, parms, timeout, dx, dy;
2452   int root_x, root_y;
2453   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2454   int count = SPECPDL_INDEX ();
2455   struct frame *f;
2456   char *str;
2457   NSSize size;
2459   specbind (Qinhibit_redisplay, Qt);
2461   GCPRO4 (string, parms, frame, timeout);
2463   CHECK_STRING (string);
2464   str = SDATA (string);
2465   f = check_x_frame (frame);
2466   if (NILP (timeout))
2467     timeout = make_number (5);
2468   else
2469     CHECK_NATNUM (timeout);
2471   if (NILP (dx))
2472     dx = make_number (5);
2473   else
2474     CHECK_NUMBER (dx);
2476   if (NILP (dy))
2477     dy = make_number (-10);
2478   else
2479     CHECK_NUMBER (dy);
2481   BLOCK_INPUT;
2482   if (ns_tooltip == nil)
2483     ns_tooltip = [[EmacsTooltip alloc] init];
2484   else
2485     Fx_hide_tip ();
2487   [ns_tooltip setText: str];
2488   size = [ns_tooltip frame].size;
2490   /* Move the tooltip window where the mouse pointer is.  Resize and
2491      show it.  */
2492   compute_tip_xy (f, parms, dx, dy, (int)size.width, (int)size.height,
2493                   &root_x, &root_y);
2495   [ns_tooltip showAtX: root_x Y: root_y for: XINT (timeout)];
2496   UNBLOCK_INPUT;
2498   UNGCPRO;
2499   return unbind_to (count, Qnil);
2503 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
2504        doc: /* Hide the current tooltip window, if there is any.
2505 Value is t if tooltip was open, nil otherwise.  */)
2506      ()
2508   if (ns_tooltip == nil || ![ns_tooltip isActive])
2509     return Qnil;
2510   [ns_tooltip hide];
2511   return Qt;
2515 /* ==========================================================================
2517     Class implementations
2519    ========================================================================== */
2522 @implementation EmacsSavePanel
2523 #ifdef NS_IMPL_COCOA
2524 /* --------------------------------------------------------------------------
2525    These are overridden to intercept on OS X: ending panel restarts NSApp
2526    event loop if it is stopped.  Not sure if this is correct behavior,
2527    perhaps should check if running and if so send an appdefined.
2528    -------------------------------------------------------------------------- */
2529 - (void) ok: (id)sender
2531   [super ok: sender];
2532   panelOK = 1;
2533   [NSApp stop: self];
2535 - (void) cancel: (id)sender
2537   [super cancel: sender];
2538   [NSApp stop: self];
2540 #endif
2541 @end
2544 @implementation EmacsOpenPanel
2545 #ifdef NS_IMPL_COCOA
2546 /* --------------------------------------------------------------------------
2547    These are overridden to intercept on OS X: ending panel restarts NSApp
2548    event loop if it is stopped.  Not sure if this is correct behavior,
2549    perhaps should check if running and if so send an appdefined.
2550    -------------------------------------------------------------------------- */
2551 - (void) ok: (id)sender
2553   [super ok: sender];
2554   panelOK = 1;
2555   [NSApp stop: self];
2557 - (void) cancel: (id)sender
2559   [super cancel: sender];
2560   [NSApp stop: self];
2562 #endif
2563 @end
2566 @implementation EmacsFileDelegate
2567 /* --------------------------------------------------------------------------
2568    Delegate methods for Open/Save panels
2569    -------------------------------------------------------------------------- */
2570 - (BOOL)panel: (id)sender isValidFilename: (NSString *)filename
2572   return YES;
2574 - (BOOL)panel: (id)sender shouldShowFilename: (NSString *)filename
2576   return YES;
2578 - (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename
2579           confirmed: (BOOL)okFlag
2581   return filename;
2583 @end
2585 #endif
2588 /* ==========================================================================
2590     Lisp interface declaration
2592    ========================================================================== */
2595 void
2596 syms_of_nsfns ()
2598   int i;
2600   Qnone = intern ("none");
2601   staticpro (&Qnone);
2602   Qfontsize = intern ("fontsize");
2603   staticpro (&Qfontsize);
2605   DEFVAR_LISP ("ns-icon-type-alist", &Vns_icon_type_alist,
2606                doc: /* Alist of elements (REGEXP . IMAGE) for images of icons associated to frames.
2607 If the title of a frame matches REGEXP, then IMAGE.tiff is
2608 selected as the image of the icon representing the frame when it's
2609 miniaturized.  If an element is t, then Emacs tries to select an icon
2610 based on the filetype of the visited file.
2612 The images have to be installed in a folder called English.lproj in the
2613 Emacs folder.  You have to restart Emacs after installing new icons.
2615 Example: Install an icon Gnus.tiff and execute the following code
2617   (setq ns-icon-type-alist
2618         (append ns-icon-type-alist
2619                 '((\"^\\\\*\\\\(Group\\\\*$\\\\|Summary \\\\|Article\\\\*$\\\\)\"
2620                    . \"Gnus\"))))
2622 When you miniaturize a Group, Summary or Article frame, Gnus.tiff will
2623 be used as the image of the icon representing the frame.  */);
2624   Vns_icon_type_alist = Fcons (Qt, Qnil);
2626   DEFVAR_LISP ("ns-version-string", &Vns_version_string,
2627                doc: /* Toolkit version for NS Windowing.  */);
2628   Vns_version_string = ns_appkit_version_str ();
2630   defsubr (&Sns_read_file_name);
2631   defsubr (&Sns_get_resource);
2632   defsubr (&Sns_set_resource);
2633   defsubr (&Sxw_display_color_p); /* this and next called directly by C code */
2634   defsubr (&Sx_display_grayscale_p);
2635   defsubr (&Sns_font_name);
2636   defsubr (&Sns_list_colors);
2637 #ifdef NS_IMPL_COCOA
2638   defsubr (&Sns_do_applescript);
2639 #endif
2640   defsubr (&Sxw_color_defined_p);
2641   defsubr (&Sxw_color_values);
2642   defsubr (&Sx_server_max_request_size);
2643   defsubr (&Sx_server_vendor);
2644   defsubr (&Sx_server_version);
2645   defsubr (&Sx_display_pixel_width);
2646   defsubr (&Sx_display_pixel_height);
2647   defsubr (&Sns_display_usable_bounds);
2648   defsubr (&Sx_display_mm_width);
2649   defsubr (&Sx_display_mm_height);
2650   defsubr (&Sx_display_screens);
2651   defsubr (&Sx_display_planes);
2652   defsubr (&Sx_display_color_cells);
2653   defsubr (&Sx_display_visual_class);
2654   defsubr (&Sx_display_backing_store);
2655   defsubr (&Sx_display_save_under);
2656   defsubr (&Sx_create_frame);
2657   defsubr (&Sx_open_connection);
2658   defsubr (&Sx_close_connection);
2659   defsubr (&Sx_display_list);
2661   defsubr (&Sns_hide_others);
2662   defsubr (&Sns_hide_emacs);
2663   defsubr (&Sns_emacs_info_panel);
2664   defsubr (&Sns_list_services);
2665   defsubr (&Sns_perform_service);
2666   defsubr (&Sns_convert_utf8_nfd_to_nfc);
2667   defsubr (&Sx_focus_frame);
2668   defsubr (&Sns_popup_font_panel);
2669   defsubr (&Sns_popup_color_panel);
2671   defsubr (&Sx_show_tip);
2672   defsubr (&Sx_hide_tip);
2674   /* used only in fontset.c */
2675   check_window_system_func = check_ns;
2679 // arch-tag: dc2a3f74-1123-4daa-8eed-fb78db6a5642