* lisp/version.el (emacs-version): Change '*Step' to 'NS' for consistency with other...
[emacs/old-mirror.git] / src / nsfns.m
blob459c058f7caa760422570272d5cf28d07aacf37f
1 /* Functions for the NeXT/Open/GNUstep and MacOSX window system.
2    Copyright (C) 1989, 1992, 1993, 1994, 2005, 2006, 2008
3      Free Software Foundation, Inc.
5 This file is part of GNU Emacs.
7 GNU Emacs is free software: you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation, either version 3 of the License, or
10 (at your option) any later version.
12 GNU Emacs is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
21 Originally by Carl Edman
22 Updated by Christian Limpach (chris@nice.ch)
23 OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com)
24 MacOSX/Aqua port by Christophe de Dinechin (descubes@earthlink.net)
25 GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
28 #include <signal.h>
29 #include <math.h>
30 #include "config.h"
31 #include "lisp.h"
32 #include "blockinput.h"
33 #include "nsterm.h"
34 #include "window.h"
35 #include "buffer.h"
36 #include "keyboard.h"
37 #include "termhooks.h"
38 #include "fontset.h"
40 #include "character.h"
41 #include "font.h"
43 #if 0
44 int fns_trace_num = 1;
45 #define NSTRACE(x)        fprintf (stderr, "%s:%d: [%d] " #x "\n",        \
46                                   __FILE__, __LINE__, ++fns_trace_num)
47 #else
48 #define NSTRACE(x)
49 #endif
51 #ifdef HAVE_NS
53 extern NSArray *ns_send_types, *ns_return_types, *ns_drag_types;
55 extern Lisp_Object Qforeground_color;
56 extern Lisp_Object Qbackground_color;
57 extern Lisp_Object Qcursor_color;
58 extern Lisp_Object Qinternal_border_width;
59 extern Lisp_Object Qvisibility;
60 extern Lisp_Object Qcursor_type;
61 extern Lisp_Object Qicon_type;
62 extern Lisp_Object Qicon_name;
63 extern Lisp_Object Qicon_left;
64 extern Lisp_Object Qicon_top;
65 extern Lisp_Object Qleft;
66 extern Lisp_Object Qright;
67 extern Lisp_Object Qtop;
68 extern Lisp_Object Qdisplay;
69 extern Lisp_Object Qvertical_scroll_bars;
70 extern Lisp_Object Qauto_raise;
71 extern Lisp_Object Qauto_lower;
72 extern Lisp_Object Qbox;
73 extern Lisp_Object Qscroll_bar_width;
74 extern Lisp_Object Qx_resource_name;
75 extern Lisp_Object Qface_set_after_frame_default;
76 extern Lisp_Object Qunderline, Qundefined;
77 extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
78 extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
80 Lisp_Object Qnone;
81 Lisp_Object Qbuffered;
82 Lisp_Object Qfontsize;
84 /* hack for OS X file panels */
85 char panelOK = 0;
87 /* Alist of elements (REGEXP . IMAGE) for images of icons associated
88    to frames.*/
89 static Lisp_Object Vns_icon_type_alist;
91 /* Toolkit version support. */
92 static Lisp_Object Vns_version_string;
94 EmacsTooltip *ns_tooltip;
96 /* Need forward declaration here to preserve organizational integrity of file */
97 Lisp_Object Fx_open_connection (Lisp_Object, Lisp_Object, Lisp_Object);
99 extern BOOL ns_in_resize;
102 /* ==========================================================================
104     Internal utility functions
106    ========================================================================== */
109 void
110 check_ns (void)
112  if (NSApp == nil)
113    error ("OpenStep is not in use or not initialized");
117 /* Nonzero if we can use mouse menus. */
119 have_menus_p ()
121   return NSApp != nil;
125 /* Extract a frame as a FRAME_PTR, defaulting to the selected frame
126    and checking validity for NS.  */
127 static FRAME_PTR
128 check_ns_frame (Lisp_Object frame)
130   FRAME_PTR f;
132   if (NILP (frame))
133       f = SELECTED_FRAME ();
134   else
135     {
136       CHECK_LIVE_FRAME (frame);
137       f = XFRAME (frame);
138     }
139   if (! FRAME_NS_P (f))
140     error ("non-Nextstep frame used");
141   return f;
145 /* Let the user specify an Nextstep display with a frame.
146    nil stands for the selected frame--or, if that is not an Nextstep frame,
147    the first Nextstep display on the list.  */
148 static struct ns_display_info *
149 check_ns_display_info (Lisp_Object frame)
151   if (NILP (frame))
152     {
153       struct frame *f = SELECTED_FRAME ();
154       if (FRAME_NS_P (f) && FRAME_LIVE_P (f) )
155         return FRAME_NS_DISPLAY_INFO (f);
156       else if (x_display_list != 0)
157         return x_display_list;
158       else
159         error ("Nextstep windows are not in use or not initialized");
160     }
161   else if (INTEGERP (frame))
162     {
163       struct terminal *t = get_terminal (frame, 1);
165       if (t->type != output_ns)
166         error ("Terminal %d is not a Nextstep display", XINT (frame));
168       return t->display_info.ns;
169     }
170   else if (STRINGP (frame))
171     return ns_display_info_for_name (frame);
172   else
173     {
174       FRAME_PTR f;
176       CHECK_LIVE_FRAME (frame);
177       f = XFRAME (frame);
178       if (! FRAME_NS_P (f))
179         error ("non-Nextstep frame used");
180       return FRAME_NS_DISPLAY_INFO (f);
181     }
182   return NULL;  /* shut compiler up */
186 static id
187 ns_get_window (Lisp_Object maybeFrame)
189   id view =nil, window =nil;
191   if (!FRAMEP (maybeFrame) || !FRAME_NS_P (XFRAME (maybeFrame)))
192     maybeFrame = selected_frame;/*wrong_type_argument (Qframep, maybeFrame); */
194   if (!NILP (maybeFrame))
195     view = FRAME_NS_VIEW (XFRAME (maybeFrame));
196   if (view) window =[view window];
198   return window;
202 static NSScreen *
203 ns_get_screen (Lisp_Object anythingUnderTheSun)
205   id window =nil;
206   NSScreen *screen = 0;
208   struct terminal *terminal;
209   struct ns_display_info *dpyinfo;
210   struct frame *f = NULL;
211   Lisp_Object frame;
213   if (INTEGERP (anythingUnderTheSun)) {
214     /* we got a terminal */
215     terminal = get_terminal (anythingUnderTheSun, 1);
216     dpyinfo = terminal->display_info.ns;
217     f = dpyinfo->x_focus_frame;
218     if (!f)
219       f = dpyinfo->x_highlight_frame;
221   } else if (FRAMEP (anythingUnderTheSun) &&
222              FRAME_NS_P (XFRAME (anythingUnderTheSun))) {
223     /* we got a frame */
224     f = XFRAME (anythingUnderTheSun);
226   } else if (STRINGP (anythingUnderTheSun)) { /* FIXME/cl for multi-display */
227   }
229   if (!f)
230     f = SELECTED_FRAME ();
231   if (f)
232     {
233       XSETFRAME (frame, f);
234       window = ns_get_window (frame);
235     }
237   if (window)
238     screen = [window screen];
239   if (!screen)
240     screen = [NSScreen mainScreen];
242   return screen;
246 /* Return the X display structure for the display named NAME.
247    Open a new connection if necessary.  */
248 struct ns_display_info *
249 ns_display_info_for_name (name)
250      Lisp_Object name;
252   Lisp_Object names;
253   struct ns_display_info *dpyinfo;
255   CHECK_STRING (name);
257   for (dpyinfo = x_display_list, names = ns_display_name_list;
258        dpyinfo;
259        dpyinfo = dpyinfo->next, names = XCDR (names))
260     {
261       Lisp_Object tem;
262       tem = Fstring_equal (XCAR (XCAR (names)), name);
263       if (!NILP (tem))
264         return dpyinfo;
265     }
267   error ("Emacs for OpenStep does not yet support multi-display.");
269   Fx_open_connection (name, Qnil, Qnil);
270   dpyinfo = x_display_list;
272   if (dpyinfo == 0)
273     error ("OpenStep on %s not responding.\n", SDATA (name));
275   return dpyinfo;
279 static Lisp_Object
280 interpret_services_menu (NSMenu *menu, Lisp_Object prefix, Lisp_Object old)
281 /* --------------------------------------------------------------------------
282    Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side
283    -------------------------------------------------------------------------- */
285   int i, count;
286   NSMenuItem *item;
287   const char *name;
288   Lisp_Object nameStr;
289   unsigned short key;
290   NSString *keys;
291   Lisp_Object res;
293   count = [menu numberOfItems];
294   for (i = 0; i<count; i++)
295     {
296       item = [menu itemAtIndex: i];
297       name = [[item title] UTF8String];
298       if (!name) continue;
300       nameStr = build_string (name);
302       if ([item hasSubmenu])
303         {
304           old = interpret_services_menu ([item submenu],
305                                         Fcons (nameStr, prefix), old);
306         }
307       else
308         {
309           keys = [item keyEquivalent];
310           if (keys && [keys length] )
311             {
312               key = [keys characterAtIndex: 0];
313               res = make_number (key|super_modifier);
314             }
315           else
316             {
317               res = Qundefined;
318             }
319           old = Fcons (Fcons (res,
320                             Freverse (Fcons (nameStr,
321                                            prefix))),
322                     old);
323         }
324     }
325   return old;
330 /* ==========================================================================
332     Frame parameter setters
334    ========================================================================== */
337 static void
338 ns_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
340   NSColor *col;
342   if (ns_lisp_to_color (arg, &col))
343     {
344       store_frame_param (f, Qforeground_color, oldval);
345       error ("Unknown color");
346     }
348   [col retain];
349   [f->output_data.ns->foreground_color release];
350   f->output_data.ns->foreground_color = col;
352   if (FRAME_NS_VIEW (f))
353     {
354       update_face_from_frame_parameter (f, Qforeground_color, arg);
355       /*recompute_basic_faces (f); */
356       if (FRAME_VISIBLE_P (f))
357         redraw_frame (f);
358     }
362 static void
363 ns_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
365   struct face *face;
366   NSColor *col;
367   NSView *view = FRAME_NS_VIEW (f);
368   float alpha;
370   if (ns_lisp_to_color (arg, &col))
371     {
372       store_frame_param (f, Qbackground_color, oldval);
373       error ("Unknown color");
374     }
376   /* clear the frame; in some instances the NS-internal GC appears not to
377      update, or it does update and cannot clear old text properly */
378   if (FRAME_VISIBLE_P (f))
379     ns_clear_frame (f);
381   [col retain];
382   [f->output_data.ns->background_color release];
383   f->output_data.ns->background_color = col;
384   if (view != nil)
385     {
386       [[view window] setBackgroundColor: col];
387       alpha = [col alphaComponent];
389 #ifdef NS_IMPL_COCOA
390       /* the alpha code below only works on 10.4, so we need to do something
391          else (albeit less good) otherwise.
392          Check NSApplication.h for useful NSAppKitVersionNumber values. */
393       if (NSAppKitVersionNumber < 744.0)
394           [[view window] setAlphaValue: alpha];
395 #endif
397       if (alpha != 1.0)
398           [[view window] setOpaque: NO];
399       else
400           [[view window] setOpaque: YES];
402       face = FRAME_DEFAULT_FACE (f);
403       if (face)
404         {
405           col = ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f);
406           face->background
407              = (EMACS_UINT) [[col colorWithAlphaComponent: alpha] retain];
408           [col release];
410           update_face_from_frame_parameter (f, Qbackground_color, arg);
411         }
413       if (FRAME_VISIBLE_P (f))
414         redraw_frame (f);
415     }
419 static void
420 ns_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
422   NSColor *col;
424   if (ns_lisp_to_color (arg, &col))
425     {
426       store_frame_param (f, Qcursor_color, oldval);
427       error ("Unknown color");
428     }
430   [FRAME_CURSOR_COLOR (f) release];
431   FRAME_CURSOR_COLOR (f) = [col retain];
433   if (FRAME_VISIBLE_P (f))
434     {
435       x_update_cursor (f, 0);
436       x_update_cursor (f, 1);
437     }
438   update_face_from_frame_parameter (f, Qcursor_color, arg);
442 static void
443 ns_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
445   NSView *view = FRAME_NS_VIEW (f);
446   NSTRACE (ns_set_icon_name);
448   if (ns_in_resize)
449     return;
451   /* see if it's changed */
452   if (STRINGP (arg))
453     {
454       if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
455         return;
456     }
457   else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
458     return;
460   f->icon_name = arg;
462   if (NILP (arg))
463     {
464       if (!NILP (f->title))
465         arg = f->title;
466       else
467         /* explicit name and no icon-name -> explicit_name */
468         if (f->explicit_name)
469           arg = f->name;
470         else
471           {
472             /* no explicit name and no icon-name ->
473                name has to be rebuild from icon_title_format */
474             windows_or_buffers_changed++;
475             return;
476           }
477     }
479   /* Don't change the name if it's already NAME.  */
480   if ([[view window] miniwindowTitle] &&
481       ([[[view window] miniwindowTitle]
482              isEqualToString: [NSString stringWithUTF8String:
483                                            SDATA (arg)]]))
484     return;
486   [[view window] setMiniwindowTitle:
487         [NSString stringWithUTF8String: SDATA (arg)]];
491 static void
492 ns_set_name_iconic (struct frame *f, Lisp_Object name, int explicit)
494   NSView *view = FRAME_NS_VIEW (f);
495   NSTRACE (ns_set_name_iconic);
497   if (ns_in_resize)
498     return;
500   /* Make sure that requests from lisp code override requests from
501      Emacs redisplay code.  */
502   if (explicit)
503     {
504       /* If we're switching from explicit to implicit, we had better
505          update the mode lines and thereby update the title.  */
506       if (f->explicit_name && NILP (name))
507         update_mode_lines = 1;
509       f->explicit_name = ! NILP (name);
510     }
511   else if (f->explicit_name)
512     name = f->name;
514   /* title overrides explicit name */
515   if (! NILP (f->title))
516     name = f->title;
518   /* icon_name overrides title and explicit name */
519   if (! NILP (f->icon_name))
520     name = f->icon_name;
522   if (NILP (name))
523     name = build_string
524         ([[[NSProcessInfo processInfo] processName] UTF8String]);
525   else
526     CHECK_STRING (name);
528   /* Don't change the name if it's already NAME.  */
529   if ([[view window] miniwindowTitle] &&
530       ([[[view window] miniwindowTitle]
531              isEqualToString: [NSString stringWithUTF8String:
532                                            SDATA (name)]]))
533     return;
535   [[view window] setMiniwindowTitle:
536         [NSString stringWithUTF8String: SDATA (name)]];
540 static void
541 ns_set_name (struct frame *f, Lisp_Object name, int explicit)
543   NSView *view = FRAME_NS_VIEW (f);
544   NSTRACE (ns_set_name);
546   if (ns_in_resize)
547     return;
549   /* Make sure that requests from lisp code override requests from
550      Emacs redisplay code.  */
551   if (explicit)
552     {
553       /* If we're switching from explicit to implicit, we had better
554          update the mode lines and thereby update the title.  */
555       if (f->explicit_name && NILP (name))
556         update_mode_lines = 1;
558       f->explicit_name = ! NILP (name);
559     }
560   else if (f->explicit_name)
561     return;
563   if (NILP (name))
564     name = build_string
565         ([[[NSProcessInfo processInfo] processName] UTF8String]);
567   f->name = name;
569   /* title overrides explicit name */
570   if (! NILP (f->title))
571     name = f->title;
573   CHECK_STRING (name);
575   /* Don't change the name if it's already NAME.  */
576   if ([[[view window] title]
577             isEqualToString: [NSString stringWithUTF8String:
578                                           SDATA (name)]])
579     return;
580   [[view window] setTitle: [NSString stringWithUTF8String:
581                                         SDATA (name)]];
585 /* This function should be called when the user's lisp code has
586    specified a name for the frame; the name will override any set by the
587    redisplay code.  */
588 static void
589 ns_explicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
591   NSTRACE (ns_explicitly_set_name);
592   ns_set_name_iconic (f, arg, 1);
593   ns_set_name (f, arg, 1);
597 /* This function should be called by Emacs redisplay code to set the
598    name; names set this way will never override names set by the user's
599    lisp code.  */
600 void
601 x_implicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
603   NSTRACE (x_implicitly_set_name);
604   if (FRAME_ICONIFIED_P (f))
605     ns_set_name_iconic (f, arg, 0);
606   else
607     ns_set_name (f, arg, 0);
611 /* Change the title of frame F to NAME.
612    If NAME is nil, use the frame name as the title.
614    If EXPLICIT is non-zero, that indicates that lisp code is setting the
615    name; if NAME is a string, set F's name to NAME and set
616    F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
618    If EXPLICIT is zero, that indicates that Emacs redisplay code is
619    suggesting a new name, which lisp code should override; if
620    F->explicit_name is set, ignore the new name; otherwise, set it.  */
621 static void
622 ns_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
624   NSTRACE (ns_set_title);
625   /* Don't change the title if it's already NAME.  */
626   if (EQ (name, f->title))
627     return;
629   update_mode_lines = 1;
631   f->title = name;
635 void
636 ns_set_name_as_filename (struct frame *f)
638   NSView *view = FRAME_NS_VIEW (f);
639   Lisp_Object name;
640   Lisp_Object buf = XWINDOW (f->selected_window)->buffer;
641   const char *title;
642   NSAutoreleasePool *pool;
643   NSTRACE (ns_set_name_as_filename);
645   if (f->explicit_name || ! NILP (f->title) || ns_in_resize)
646     return;
648   BLOCK_INPUT;
649   pool = [[NSAutoreleasePool alloc] init];
650   name =XBUFFER (buf)->filename;
651   if (NILP (name) || FRAME_ICONIFIED_P (f)) name =XBUFFER (buf)->name;
653   if (FRAME_ICONIFIED_P (f) && !NILP (f->icon_name))
654     name = f->icon_name;
656   if (NILP (name))
657     name = build_string
658         ([[[NSProcessInfo processInfo] processName] UTF8String]);
659   else
660     CHECK_STRING (name);
662   title = FRAME_ICONIFIED_P (f) ? [[[view window] miniwindowTitle] UTF8String]
663                                 : [[[view window] title] UTF8String];
665   if (title && (! strcmp (title, SDATA (name))))
666     {
667       [pool release];
668       UNBLOCK_INPUT;
669       return;
670     }
672   if (! FRAME_ICONIFIED_P (f))
673     {
674 #ifdef NS_IMPL_COCOA
675       /* work around a bug observed on 10.3 where
676          setTitleWithRepresentedFilename does not clear out previous state
677          if given filename does not exist */
678       NSString *str = [NSString stringWithUTF8String: SDATA (name)];
679       if (![[NSFileManager defaultManager] fileExistsAtPath: str])
680         {
681           [[view window] setTitleWithRepresentedFilename: @""];
682           [[view window] setTitle: str];
683         }
684       else
685         {
686           [[view window] setTitleWithRepresentedFilename: str];
687         }
688 #else
689       [[view window] setTitleWithRepresentedFilename:
690                          [NSString stringWithUTF8String: SDATA (name)]];
691 #endif
692       f->name = name;
693     }
694   else
695     {
696       [[view window] setMiniwindowTitle:
697             [NSString stringWithUTF8String: SDATA (name)]];
698     }
699   [pool release];
700   UNBLOCK_INPUT;
704 void
705 ns_set_doc_edited (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
707   NSView *view = FRAME_NS_VIEW (f);
708   NSAutoreleasePool *pool;
709   BLOCK_INPUT;
710   pool = [[NSAutoreleasePool alloc] init];
711   [[view window] setDocumentEdited: !NILP (arg)];
712   [pool release];
713   UNBLOCK_INPUT;
717 void
718 x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
720   int nlines;
721   int olines = FRAME_MENU_BAR_LINES (f);
722   if (FRAME_MINIBUF_ONLY_P (f))
723     return;
725   if (INTEGERP (value))
726     nlines = XINT (value);
727   else
728     nlines = 0;
730   FRAME_MENU_BAR_LINES (f) = 0;
731   if (nlines)
732     {
733       FRAME_EXTERNAL_MENU_BAR (f) = 1;
734       /* does for all frames, whereas we just want for one frame
735          [NSMenu setMenuBarVisible: YES]; */
736     }
737   else
738     {
739       if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
740         free_frame_menubar (f);
741       /*      [NSMenu setMenuBarVisible: NO]; */
742       FRAME_EXTERNAL_MENU_BAR (f) = 0;
743     }
747 /* 23: toolbar support */
748 void
749 x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
751   int nlines;
752   Lisp_Object root_window;
754   if (FRAME_MINIBUF_ONLY_P (f))
755     return;
757   if (INTEGERP (value) && XINT (value) >= 0)
758     nlines = XFASTINT (value);
759   else
760     nlines = 0;
762   if (nlines)
763     {
764       FRAME_EXTERNAL_TOOL_BAR (f) = 1;
765       update_frame_tool_bar (f);
766     }
767   else
768     {
769       if (FRAME_EXTERNAL_TOOL_BAR (f))
770         {
771           free_frame_tool_bar (f);
772           FRAME_EXTERNAL_TOOL_BAR (f) = 0;
773         }
774     }
776   x_set_window_size (f, 0, f->text_cols, f->text_lines);
780 void
781 ns_implicitly_set_icon_type (struct frame *f)
783   Lisp_Object tem;
784   EmacsView *view = FRAME_NS_VIEW (f);
785   id image =nil;
786   Lisp_Object chain, elt;
787   NSAutoreleasePool *pool;
788   BOOL setMini = YES;
790   NSTRACE (ns_implicitly_set_icon_type);
792   BLOCK_INPUT;
793   pool = [[NSAutoreleasePool alloc] init];
794   if (f->output_data.ns->miniimage
795       && [[NSString stringWithUTF8String: SDATA (f->name)]
796                isEqualToString: [(NSImage *)f->output_data.ns->miniimage name]])
797     {
798       [pool release];
799       UNBLOCK_INPUT;
800       return;
801     }
803   tem = assq_no_quit (Qicon_type, f->param_alist);
804   if (CONSP (tem) && ! NILP (XCDR (tem)))
805     {
806       [pool release];
807       UNBLOCK_INPUT;
808       return;
809     }
811   for (chain = Vns_icon_type_alist;
812        (image = nil) && CONSP (chain);
813        chain = XCDR (chain))
814     {
815       elt = XCAR (chain);
816       /* special case: 't' means go by file type */
817       if (SYMBOLP (elt) && EQ (elt, Qt) && SDATA (f->name)[0] == '/')
818         {
819           NSString *str
820              = [NSString stringWithUTF8String: SDATA (f->name)];
821           if ([[NSFileManager defaultManager] fileExistsAtPath: str])
822             image = [[[NSWorkspace sharedWorkspace] iconForFile: str] retain];
823         }
824       else if (CONSP (elt) &&
825                STRINGP (XCAR (elt)) &&
826                STRINGP (XCDR (elt)) &&
827                fast_string_match (XCAR (elt), f->name) >= 0)
828         {
829           image = [EmacsImage allocInitFromFile: XCDR (elt)];
830           if (image == nil)
831             image = [[NSImage imageNamed:
832                                [NSString stringWithUTF8String:
833                                             SDATA (XCDR (elt))]] retain];
834         }
835     }
837   if (image == nil)
838     {
839       image = [[[NSWorkspace sharedWorkspace] iconForFileType: @"text"] retain];
840       setMini = NO;
841     }
843   [f->output_data.ns->miniimage release];
844   f->output_data.ns->miniimage = image;
845   [view setMiniwindowImage: setMini];
846   [pool release];
847   UNBLOCK_INPUT;
851 static void
852 ns_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
854   EmacsView *view = FRAME_NS_VIEW (f);
855   id image = nil;
856   BOOL setMini = YES;
858   NSTRACE (ns_set_icon_type);
860   if (!NILP (arg) && SYMBOLP (arg))
861     {
862       arg =build_string (SDATA (SYMBOL_NAME (arg)));
863       store_frame_param (f, Qicon_type, arg);
864     }
866   /* do it the implicit way */
867   if (NILP (arg))
868     {
869       ns_implicitly_set_icon_type (f);
870       return;
871     }
873   CHECK_STRING (arg);
875   image = [EmacsImage allocInitFromFile: arg];
876   if (image == nil)
877     image =[NSImage imageNamed: [NSString stringWithUTF8String:
878                                             SDATA (arg)]];
880   if (image == nil)
881     {
882       image = [NSImage imageNamed: @"text"];
883       setMini = NO;
884     }
886   f->output_data.ns->miniimage = image;
887   [view setMiniwindowImage: setMini];
891 /* 23: added Xism; we stub out (we do implement this in ns-win.el) */
893 XParseGeometry (char *string, int *x, int *y,
894                 unsigned int *width, unsigned int *height)
896   message1 ("Warning: XParseGeometry not supported under NS.\n");
897   return 0;
901 /* TODO: move to nsterm? */
903 ns_lisp_to_cursor_type (Lisp_Object arg)
905   char *str;
906   if (XTYPE (arg) == Lisp_String)
907     str = SDATA (arg);
908   else if (XTYPE (arg) == Lisp_Symbol)
909     str = SDATA (SYMBOL_NAME (arg));
910   else return -1;
911   if (!strcmp (str, "box"))     return FILLED_BOX_CURSOR;
912   if (!strcmp (str, "hollow"))  return HOLLOW_BOX_CURSOR;
913   if (!strcmp (str, "hbar"))    return HBAR_CURSOR;
914   if (!strcmp (str, "bar"))     return BAR_CURSOR;
915   if (!strcmp (str, "no"))      return NO_CURSOR;
916   return -1;
920 Lisp_Object
921 ns_cursor_type_to_lisp (int arg)
923   switch (arg)
924     {
925     case FILLED_BOX_CURSOR: return Qbox;
926     case HOLLOW_BOX_CURSOR: return intern ("hollow");
927     case HBAR_CURSOR:       return intern ("hbar");
928     case BAR_CURSOR:        return intern ("bar");
929     case NO_CURSOR:
930     default:                return intern ("no");
931     }
934 /* this is like x_set_cursor_type defined in xfns.c */
935 void
936 ns_set_cursor_type (f, arg, oldval)
937      FRAME_PTR f;
938      Lisp_Object arg, oldval;
940   set_frame_cursor_types (f, arg);
942   /* Make sure the cursor gets redrawn.  */
943   cursor_type_changed = 1;
947 /* 23: called to set mouse pointer color, but all other terms use it to
948        initialize pointer types (and don't set the color ;) */
949 static void
950 ns_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
952   /* don't think we can do this on Nextstep */
956 #define Str(x) #x
957 #define Xstr(x) Str(x)
959 static Lisp_Object
960 ns_appkit_version ()
962   char tmp[80];
964 #ifdef NS_IMPL_GNUSTEP
965   sprintf(tmp, "gnustep-gui-%s", Xstr(GNUSTEP_GUI_VERSION));
966 #elif defined(NS_IMPL_COCOA)
967   sprintf(tmp, "apple-appkit-%.2f", NSAppKitVersionNumber);
968 #else
969   tmp = "ns-unknown";
970 #endif
971   return build_string (tmp);
975 static void
976 x_icon (struct frame *f, Lisp_Object parms)
977 /* --------------------------------------------------------------------------
978    Strangely-named function to set icon position parameters in frame.
979    This is irrelevant under OS X, but might be needed under GNUstep,
980    depending on the window manager used.  Note, this is not a standard
981    frame parameter-setter; it is called directly from x-create-frame.
982    -------------------------------------------------------------------------- */
984   Lisp_Object icon_x, icon_y;
985   struct ns_display_info *dpyinfo = check_ns_display_info (Qnil);
987   f->output_data.ns->icon_top = Qnil;
988   f->output_data.ns->icon_left = Qnil;
990   /* Set the position of the icon.  */
991   icon_x = x_get_arg (dpyinfo, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
992   icon_y = x_get_arg (dpyinfo, parms, Qicon_top, 0, 0,  RES_TYPE_NUMBER);
993   if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
994     {
995       CHECK_NUMBER (icon_x);
996       CHECK_NUMBER (icon_y);
997       f->output_data.ns->icon_top = icon_y;
998       f->output_data.ns->icon_left = icon_x;
999     }
1000   else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
1001     error ("Both left and top icon corners of icon must be specified");
1005 /* 23 Note: commented out ns_... entries are no longer used in 23.
1006             commented out x_... entries have not been implemented yet.
1007    see frame.c for template, also where all generic OK functions are impl */
1008 frame_parm_handler ns_frame_parm_handlers[] =
1010   x_set_autoraise, /* generic OK */
1011   x_set_autolower, /* generic OK */
1012   ns_set_background_color,
1013   0, /* x_set_border_color,  may be impossible under Nextstep */
1014   0, /* x_set_border_width,  may be impossible under Nextstep */
1015   ns_set_cursor_color,
1016   ns_set_cursor_type,
1017   x_set_font, /* generic OK */
1018   ns_set_foreground_color,
1019   ns_set_icon_name,
1020   ns_set_icon_type,
1021   x_set_internal_border_width, /* generic OK */
1022   x_set_menu_bar_lines,
1023   ns_set_mouse_color,
1024   ns_explicitly_set_name,
1025   x_set_scroll_bar_width, /* generic OK */
1026   ns_set_title,
1027   x_set_unsplittable, /* generic OK */
1028   x_set_vertical_scroll_bars, /* generic OK */
1029   x_set_visibility, /* generic OK */
1030   x_set_tool_bar_lines,
1031   0, /* x_set_scroll_bar_foreground, will ignore (not possible on NS) */
1032   0, /* x_set_scroll_bar_background,  will ignore (not possible on NS) */
1033   x_set_screen_gamma, /* generic OK */
1034   x_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */
1035   x_set_fringe_width, /* generic OK */
1036   x_set_fringe_width, /* generic OK */
1037   0, /* x_set_wait_for_wm, will ignore */
1038   0,  /* x_set_fullscreen will ignore */
1039   x_set_font_backend, /* generic OK */
1040   0
1045 /* ==========================================================================
1047     Lisp definitions
1049    ========================================================================== */
1051 DEFUN ("x-create-frame", Fx_create_frame, Sx_create_frame,
1052        1, 1, 0,
1053        doc: /* Make a new Nextstep window, called a \"frame\" in Emacs terms.
1054 Return an Emacs frame object.
1055 PARMS is an alist of frame parameters.
1056 If the parameters specify that the frame should not have a minibuffer,
1057 and do not specify a specific minibuffer window to use,
1058 then `default-minibuffer-frame' must be a frame whose minibuffer can
1059 be shared by the new frame.  */)
1060      (parms)
1061      Lisp_Object parms;
1063   static int desc_ctr = 1;
1064   struct frame *f;
1065   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1066   Lisp_Object frame, tem;
1067   Lisp_Object name;
1068   int minibuffer_only = 0;
1069   int count = specpdl_ptr - specpdl;
1070   Lisp_Object display;
1071   struct ns_display_info *dpyinfo = NULL;
1072   Lisp_Object parent;
1073   struct kboard *kb;
1074   Lisp_Object tfont, tfontsize;
1075   int window_prompting = 0;
1076   int width, height;
1078   check_ns ();
1080   /* Seems a little strange, but other terms do it. Perhaps the code below
1081      is modifying something? */
1082   parms = Fcopy_alist (parms);
1084   display = x_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_STRING);
1085   if (EQ (display, Qunbound))
1086     display = Qnil;
1087   dpyinfo = check_ns_display_info (display);
1089   if (!dpyinfo->terminal->name)
1090     error ("Terminal is not live, can't create new frames on it");
1092   kb = dpyinfo->terminal->kboard;
1094   name = x_get_arg (dpyinfo, parms, Qname, 0, 0, RES_TYPE_STRING);
1095   if (!STRINGP (name)
1096       && ! EQ (name, Qunbound)
1097       && ! NILP (name))
1098     error ("Invalid frame name--not a string or nil");
1100   if (STRINGP (name))
1101     Vx_resource_name = name;
1102   else
1103     Vx_resource_name = Vinvocation_name;
1105   parent = x_get_arg (dpyinfo, parms, Qparent_id, 0, 0, RES_TYPE_NUMBER);
1106   if (EQ (parent, Qunbound))
1107     parent = Qnil;
1108   if (! NILP (parent))
1109     CHECK_NUMBER (parent);
1111   frame = Qnil;
1112   GCPRO4 (parms, parent, name, frame);
1114   tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
1115                   RES_TYPE_SYMBOL);
1116   if (EQ (tem, Qnone) || NILP (tem))
1117     {
1118       f = make_frame_without_minibuffer (Qnil, kb, display);
1119     }
1120   else if (EQ (tem, Qonly))
1121     {
1122       f = make_minibuffer_frame ();
1123       minibuffer_only = 1;
1124     }
1125   else if (WINDOWP (tem))
1126     {
1127       f = make_frame_without_minibuffer (tem, kb, display);
1128     }
1129   else
1130     {
1131       f = make_frame (1);
1132     }
1134   /* Set the name; the functions to which we pass f expect the name to
1135      be set.  */
1136   if (EQ (name, Qunbound) || NILP (name) || (XTYPE (name) != Lisp_String))
1137     {
1138       f->name
1139          = build_string ([[[NSProcessInfo processInfo] processName] UTF8String]);
1140       f->explicit_name =0;
1141     }
1142   else
1143     {
1144       f->name = name;
1145       f->explicit_name = 1;
1146       specbind (Qx_resource_name, name);
1147     }
1149   XSETFRAME (frame, f);
1150   FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
1152   f->terminal = dpyinfo->terminal;
1153   f->terminal->reference_count++;
1155   f->output_method = output_ns;
1156   f->output_data.ns = (struct ns_output *)xmalloc (sizeof *(f->output_data.ns));
1157   bzero (f->output_data.ns, sizeof (*(f->output_data.ns)));
1159   FRAME_FONTSET (f) = -1;
1161   /* record_unwind_protect (unwind_create_frame, frame); safety; maybe later? */
1163   f->icon_name = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
1164                             RES_TYPE_STRING);
1165   if (! STRINGP (f->icon_name))
1166     f->icon_name = Qnil;
1168   FRAME_NS_DISPLAY_INFO (f) = dpyinfo;
1170   f->output_data.ns->window_desc = desc_ctr++;
1171   if (!NILP (parent))
1172     {
1173       f->output_data.ns->parent_desc = (Window) XFASTINT (parent);
1174       f->output_data.ns->explicit_parent = 1;
1175     }
1176   else
1177     {
1178       f->output_data.ns->parent_desc = FRAME_NS_DISPLAY_INFO (f)->root_window;
1179       f->output_data.ns->explicit_parent = 0;
1180     }
1182   f->resx = dpyinfo->resx;
1183   f->resy = dpyinfo->resy;
1185   BLOCK_INPUT;
1186   register_font_driver (&nsfont_driver, f);
1187   x_default_parameter (f, parms, Qfont_backend, Qnil,
1188                         "fontBackend", "FontBackend", RES_TYPE_STRING);
1190   {
1191     /* use for default font name */
1192     id font = [NSFont userFixedPitchFontOfSize: -1.0]; /* default */
1193     tfontsize = x_default_parameter (f, parms, Qfontsize,
1194                                     make_number (0 /*(int)[font pointSize]*/),
1195                                     "fontSize", "FontSize", RES_TYPE_NUMBER);
1196     tfont = x_default_parameter (f, parms, Qfont,
1197                                  build_string ([[font fontName] UTF8String]),
1198                                  "font", "Font", RES_TYPE_STRING);
1199   }
1200   UNBLOCK_INPUT;
1202   x_default_parameter (f, parms, Qborder_width, make_number (0),
1203                        "borderwidth", "BorderWidth", RES_TYPE_NUMBER);
1204   x_default_parameter (f, parms, Qinternal_border_width, make_number (2),
1205                       "internalBorderWidth", "InternalBorderWidth",
1206                       RES_TYPE_NUMBER);
1208   /* default scrollbars on right on Mac */
1209   {
1210       Lisp_Object spos
1211 #ifdef NS_IMPL_GNUSTEP
1212           = Qt;
1213 #else
1214           = Qright;
1215 #endif
1216       x_default_parameter (f, parms, Qvertical_scroll_bars, spos,
1217                            "verticalScrollBars", "VerticalScrollBars",
1218                            RES_TYPE_SYMBOL);
1219   }
1220   x_default_parameter (f, parms, Qforeground_color, build_string ("Black"),
1221                       "foreground", "Foreground", RES_TYPE_STRING);
1222   x_default_parameter (f, parms, Qbackground_color, build_string ("White"),
1223                       "background", "Background", RES_TYPE_STRING);
1224   x_default_parameter (f, parms, Qcursor_color, build_string ("grey"),
1225                       "cursorColor", "CursorColor", RES_TYPE_STRING);
1226   /* FIXME: not suppported yet in Nextstep */
1227   x_default_parameter (f, parms, Qline_spacing, Qnil,
1228                        "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
1229   x_default_parameter (f, parms, Qleft_fringe, Qnil,
1230                        "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
1231   x_default_parameter (f, parms, Qright_fringe, Qnil,
1232                        "rightFringe", "RightFringe", RES_TYPE_NUMBER);
1233   /* end PENDING */
1235   init_frame_faces (f);
1237   x_default_parameter (f, parms, Qmenu_bar_lines, make_number (0), "menuBar",
1238                       "menuBar", RES_TYPE_NUMBER);
1239   x_default_parameter (f, parms, Qtool_bar_lines, make_number (0), "toolBar",
1240                       "toolBar", RES_TYPE_NUMBER);
1241   x_default_parameter (f, parms, Qbuffer_predicate, Qnil, "bufferPredicate",
1242                        "BufferPredicate", RES_TYPE_SYMBOL);
1243   x_default_parameter (f, parms, Qtitle, Qnil, "title", "Title",
1244                        RES_TYPE_STRING);
1246 /* TODO: other terms seem to get away w/o this complexity.. */
1247   if (NILP (Fassq (Qwidth, parms)))
1248     {
1249       Lisp_Object value
1250          = x_get_arg (dpyinfo, parms, Qwidth, "width", "Width",
1251                       RES_TYPE_NUMBER);
1252       if (! EQ (value, Qunbound))
1253         parms = Fcons (Fcons (Qwidth, value), parms);
1254     }
1255   if (NILP (Fassq (Qheight, parms)))
1256     {
1257       Lisp_Object value
1258          = x_get_arg (dpyinfo, parms, Qheight, "height", "Height",
1259                       RES_TYPE_NUMBER);
1260       if (! EQ (value, Qunbound))
1261         parms = Fcons (Fcons (Qheight, value), parms);
1262     }
1263   if (NILP (Fassq (Qleft, parms)))
1264     {
1265       Lisp_Object value
1266          = x_get_arg (dpyinfo, parms, Qleft, "left", "Left", RES_TYPE_NUMBER);
1267       if (! EQ (value, Qunbound))
1268         parms = Fcons (Fcons (Qleft, value), parms);
1269     }
1270   if (NILP (Fassq (Qtop, parms)))
1271     {
1272       Lisp_Object value
1273          = x_get_arg (dpyinfo, parms, Qtop, "top", "Top", RES_TYPE_NUMBER);
1274       if (! EQ (value, Qunbound))
1275         parms = Fcons (Fcons (Qtop, value), parms);
1276     }
1278   window_prompting = x_figure_window_size (f, parms, 1);
1280   tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
1281   f->no_split = minibuffer_only || (!EQ (tem, Qunbound) && !EQ (tem, Qnil));
1283   /* NOTE: on other terms, this is done in set_mouse_color, however this
1284      was not getting called under Nextstep */
1285   f->output_data.ns->text_cursor = [NSCursor IBeamCursor];
1286   f->output_data.ns->nontext_cursor = [NSCursor arrowCursor];
1287   f->output_data.ns->modeline_cursor = [NSCursor pointingHandCursor];
1288   f->output_data.ns->hand_cursor = [NSCursor pointingHandCursor];
1289   f->output_data.ns->hourglass_cursor = [NSCursor disappearingItemCursor];
1290   f->output_data.ns->horizontal_drag_cursor = [NSCursor resizeLeftRightCursor];
1291   FRAME_NS_DISPLAY_INFO (f)->vertical_scroll_bar_cursor
1292      = [NSCursor arrowCursor];
1293   f->output_data.ns->current_pointer = f->output_data.ns->text_cursor;
1295   [[EmacsView alloc] initFrameFromEmacs: f];
1297   x_icon (f, parms);
1299   /* It is now ok to make the frame official even if we get an error below.
1300      The frame needs to be on Vframe_list or making it visible won't work. */
1301   Vframe_list = Fcons (frame, Vframe_list);
1302   /*FRAME_NS_DISPLAY_INFO (f)->reference_count++; */
1304   x_default_parameter (f, parms, Qicon_type, Qnil, "bitmapIcon", "BitmapIcon",
1305                       RES_TYPE_SYMBOL);
1306   x_default_parameter (f, parms, Qauto_raise, Qnil, "autoRaise", "AutoRaiseLower",
1307                       RES_TYPE_BOOLEAN);
1308   x_default_parameter (f, parms, Qauto_lower, Qnil, "autoLower", "AutoLower",
1309                       RES_TYPE_BOOLEAN);
1310   x_default_parameter (f, parms, Qcursor_type, Qbox, "cursorType", "CursorType",
1311                       RES_TYPE_SYMBOL);
1312   x_default_parameter (f, parms, Qscroll_bar_width, Qnil, "scrollBarWidth",
1313                       "ScrollBarWidth", RES_TYPE_NUMBER);
1314   x_default_parameter (f, parms, Qalpha, Qnil, "alpha", "Alpha",
1315                       RES_TYPE_NUMBER);
1317   width = FRAME_COLS (f);
1318   height = FRAME_LINES (f);
1320   SET_FRAME_COLS (f, 0);
1321   FRAME_LINES (f) = 0;
1322   change_frame_size (f, height, width, 1, 0, 0);
1324   if (! f->output_data.ns->explicit_parent)
1325     {
1326         tem = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_BOOLEAN);
1327         if (EQ (tem, Qunbound))
1328             tem = Qnil;
1330         x_set_visibility (f, tem, Qnil);
1331         if (EQ (tem, Qt))
1332             [[FRAME_NS_VIEW (f) window] makeKeyWindow];
1333     }
1335   if (FRAME_HAS_MINIBUF_P (f)
1336       && (!FRAMEP (kb->Vdefault_minibuffer_frame)
1337           || !FRAME_LIVE_P (XFRAME (kb->Vdefault_minibuffer_frame))))
1338     kb->Vdefault_minibuffer_frame = frame;
1340   /* All remaining specified parameters, which have not been "used"
1341      by x_get_arg and friends, now go in the misc. alist of the frame.  */
1342   for (tem = parms; CONSP (tem); tem = XCDR (tem))
1343     if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
1344       f->param_alist = Fcons (XCAR (tem), f->param_alist);
1346   UNGCPRO;
1347   Vwindow_list = Qnil;
1349   return unbind_to (count, frame);
1353 DEFUN ("x-focus-frame", Fx_focus_frame, Sx_focus_frame, 1, 1, 0,
1354        doc: /* Set the input focus to FRAME.
1355 FRAME nil means use the selected frame.  */)
1356      (frame)
1357      Lisp_Object frame;
1359   struct frame *f = check_ns_frame (frame);
1360   struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f);
1362   if (dpyinfo->x_focus_frame != f)
1363     {
1364       EmacsView *view = FRAME_NS_VIEW (f);
1365       BLOCK_INPUT;
1366       [[view window] makeKeyAndOrderFront: view];
1367       UNBLOCK_INPUT;
1368     }
1370   return Qnil;
1374 DEFUN ("ns-popup-prefs-panel", Fns_popup_prefs_panel, Sns_popup_prefs_panel,
1375        0, 0, "",
1376        doc: /* Pop up the preferences panel. */)
1377      ()
1379   check_ns ();
1380   [(EmacsApp *)NSApp showPreferencesWindow: NSApp];
1381   return Qnil;
1385 DEFUN ("ns-popup-font-panel", Fns_popup_font_panel, Sns_popup_font_panel,
1386        0, 1, "",
1387        doc: /* Pop up the font panel. */)
1388      (frame)
1389      Lisp_Object frame;
1391   id fm;
1392   struct frame *f;
1394   check_ns ();
1395   fm = [NSFontManager new];
1396   if (NILP (frame))
1397     f = SELECTED_FRAME ();
1398   else
1399     {
1400       CHECK_FRAME (frame);
1401       f = XFRAME (frame);
1402     }
1404   [fm setSelectedFont: ((struct nsfont_info *)f->output_data.ns->font)->nsfont
1405            isMultiple: NO];
1406   [fm orderFrontFontPanel: NSApp];
1407   return Qnil;
1411 DEFUN ("ns-popup-color-panel", Fns_popup_color_panel, Sns_popup_color_panel, 
1412        0, 1, "",
1413        doc: /* Pop up the color panel.  */)
1414      (frame)
1415      Lisp_Object frame;
1417   struct frame *f;
1419   check_ns ();
1420   if (NILP (frame))
1421     f = SELECTED_FRAME ();
1422   else
1423     {
1424       CHECK_FRAME (frame);
1425       f = XFRAME (frame);
1426     }
1428   [NSApp orderFrontColorPanel: NSApp];
1429   return Qnil;
1433 DEFUN ("ns-read-file-name", Fns_read_file_name, Sns_read_file_name, 1, 4, 0,
1434        doc: /* Use a graphical panel to read a file name, using prompt PROMPT.
1435 Optional arg DIR, if non-nil, supplies a default directory.
1436 Optional arg ISLOAD, if non-nil, means read a file name for saving.
1437 Optional arg INIT, if non-nil, provides a default file name to use.  */)
1438      (prompt, dir, isLoad, init)
1439      Lisp_Object prompt, dir, isLoad, init;
1441   static id fileDelegate = nil;
1442   int ret;
1443   id panel;
1444   NSString *fname;
1446   NSString *promptS = NILP (prompt) || !STRINGP (prompt) ? nil :
1447     [NSString stringWithUTF8String: SDATA (prompt)];
1448   NSString *dirS = NILP (dir) || !STRINGP (dir) ?
1449     [NSString stringWithUTF8String: SDATA (current_buffer->directory)] :
1450     [NSString stringWithUTF8String: SDATA (dir)];
1451   NSString *initS = NILP (init) || !STRINGP (init) ? nil :
1452     [NSString stringWithUTF8String: SDATA (init)];
1454   check_ns ();
1456   if (fileDelegate == nil)
1457     fileDelegate = [EmacsFileDelegate new];
1459   [NSCursor setHiddenUntilMouseMoves: NO];
1461   if ([dirS characterAtIndex: 0] == '~')
1462     dirS = [dirS stringByExpandingTildeInPath];
1464   panel = NILP (isLoad) ?
1465     (id)[EmacsSavePanel savePanel] : (id)[EmacsOpenPanel openPanel];
1467   [panel setTitle: promptS];
1469   /* Puma (10.1) does not have */
1470   if ([panel respondsToSelector: @selector (setAllowsOtherFileTypes:)])
1471     [panel setAllowsOtherFileTypes: YES];
1473   [panel setTreatsFilePackagesAsDirectories: YES];
1474   [panel setDelegate: fileDelegate];
1476   panelOK = 0;
1477   if (NILP (isLoad))
1478     {
1479       ret = [panel runModalForDirectory: dirS file: initS];
1480     }
1481   else
1482     {
1483       [panel setCanChooseDirectories: YES];
1484       ret = [panel runModalForDirectory: dirS file: initS types: nil];
1485     }
1487   ret = (ret = NSOKButton) || panelOK;
1489   fname = [panel filename];
1491   [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
1493   return ret ? build_string ([fname UTF8String]) : Qnil;
1497 DEFUN ("ns-get-resource", Fns_get_resource, Sns_get_resource, 2, 2, 0,
1498        doc: /* Return the value of the property NAME of OWNER from the defaults database.
1499 If OWNER is nil, Emacs is assumed.  */)
1500      (owner, name)
1501      Lisp_Object owner, name;
1503   const char *value;
1505   check_ns ();
1506   if (NILP (owner))
1507     owner = build_string
1508         ([[[NSProcessInfo processInfo] processName] UTF8String]);
1509   /* CHECK_STRING (owner);  this should be just "Emacs" */
1510   CHECK_STRING (name);
1511 /*fprintf (stderr, "ns-get-resource checking resource '%s'\n", SDATA (name)); */
1513   value =[[[NSUserDefaults standardUserDefaults]
1514             objectForKey: [NSString stringWithUTF8String: SDATA (name)]]
1515            UTF8String];
1517   if (value)
1518     return build_string (value);
1519   return Qnil;
1523 DEFUN ("ns-set-resource", Fns_set_resource, Sns_set_resource, 3, 3, 0,
1524        doc: /* Set property NAME of OWNER to VALUE, from the defaults database.
1525 If OWNER is nil, Emacs is assumed.
1526 If VALUE is nil, the default is removed.  */)
1527      (owner, name, value)
1528      Lisp_Object owner, name, value;
1530   check_ns ();
1531   if (NILP (owner))
1532     owner
1533        = build_string ([[[NSProcessInfo processInfo] processName] UTF8String]);
1534   CHECK_STRING (owner);
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 ("ns-set-alpha", Fns_set_alpha, Sns_set_alpha, 2, 2, 0,
1555        doc: /* Return a color equivalent to COLOR with alpha setting ALPHA.
1556 The argument ALPHA should be a number between 0 and 1, where 0 is full
1557 transparency and 1 is opaque.  */)
1558      (color, alpha)
1559      Lisp_Object color;
1560      Lisp_Object alpha;
1562   NSColor *col;
1563   float a;
1565   CHECK_STRING (color);
1566   CHECK_NUMBER_OR_FLOAT (alpha);
1568   if (ns_lisp_to_color (color, &col))
1569     error ("Unknown color.");
1571   a = XFLOATINT (alpha);
1572   if (a < 0.0 || a > 1.0)
1573     error ("Alpha value should be between 0 and 1 inclusive.");
1575   col = [col colorWithAlphaComponent: a];
1576   return ns_color_to_lisp (col);
1580 DEFUN ("x-server-max-request-size", Fx_server_max_request_size,
1581        Sx_server_max_request_size,
1582        0, 1, 0,
1583        doc: /* This function is a no-op.  It is only present for completeness.  */)
1584      (display)
1585      Lisp_Object display;
1587   check_ns ();
1588   /* This function has no real equivalent under NeXTstep.  Return nil to
1589      indicate this. */
1590   return Qnil;
1594 DEFUN ("x-server-vendor", Fx_server_vendor, Sx_server_vendor, 0, 1, 0,
1595        doc: /* Return the vendor ID string of Nextstep display server DISPLAY.
1596 DISPLAY should be either a frame or a display name (a string).
1597 If omitted or nil, the selected frame's display is used.  */)
1598      (display)
1599      Lisp_Object display;
1601 #ifdef NS_IMPL_GNUSTEP
1602   return build_string ("GNU");
1603 #else
1604   return build_string ("Apple");
1605 #endif
1609 DEFUN ("x-server-version", Fx_server_version, Sx_server_version, 0, 1, 0,
1610        doc: /* Return the version number of Nextstep display server DISPLAY.
1611 DISPLAY should be either a frame or a display name (a string).
1612 If omitted or nil, the selected frame's display is used.
1613 See also the function `ns-server-vendor'.  */)
1614      (display)
1615      Lisp_Object display;
1617   return ns_appkit_version ();
1621 DEFUN ("x-display-screens", Fx_display_screens, Sx_display_screens, 0, 1, 0,
1622        doc: /* Return the number of screens on Nextstep display server DISPLAY.
1623 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1624 If omitted or nil, the selected frame's display is used.  */)
1625      (display)
1626      Lisp_Object display;
1628   int num;
1630   check_ns ();
1631   num = [[NSScreen screens] count];
1633   return (num != 0) ? make_number (num) : Qnil;
1637 DEFUN ("x-display-mm-height", Fx_display_mm_height, Sx_display_mm_height,
1638        0, 1, 0,
1639        doc: /* Return the height of Nextstep display server DISPLAY, in millimeters.
1640 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1641 If omitted or nil, the selected frame's display is used.  */)
1642      (display)
1643      Lisp_Object display;
1645   check_ns ();
1646   return make_number ((int)
1647                      ([ns_get_screen (display) frame].size.height/(92.0/25.4)));
1651 DEFUN ("x-display-mm-width", Fx_display_mm_width, Sx_display_mm_width,
1652        0, 1, 0,
1653        doc: /* Return the width of Nextstep display server DISPLAY, in millimeters.
1654 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1655 If omitted or nil, the selected frame's display is used.  */)
1656      (display)
1657      Lisp_Object display;
1659   check_ns ();
1660   return make_number ((int)
1661                      ([ns_get_screen (display) frame].size.width/(92.0/25.4)));
1665 DEFUN ("x-display-backing-store", Fx_display_backing_store,
1666        Sx_display_backing_store, 0, 1, 0,
1667        doc: /* Return whether the Nexstep display DISPLAY supports backing store.
1668 The value may be `buffered', `retained', or `non-retained'.
1669 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1670 If omitted or nil, the selected frame's display is used.  */)
1671      (display)
1672      Lisp_Object display;
1674   check_ns ();
1675   switch ([ns_get_window (display) backingType])
1676     {
1677     case NSBackingStoreBuffered:
1678       return intern ("buffered");
1679     case NSBackingStoreRetained:
1680       return intern ("retained");
1681     case NSBackingStoreNonretained:
1682       return intern ("non-retained");
1683     default:
1684       error ("Strange value for backingType parameter of frame");
1685     }
1686   return Qnil;  /* not reached, shut compiler up */
1690 DEFUN ("x-display-visual-class", Fx_display_visual_class,
1691        Sx_display_visual_class, 0, 1, 0,
1692        doc: /* Return the visual class of the Nextstep display server DISPLAY.
1693 The value is one of the symbols `static-gray', `gray-scale',
1694 `static-color', `pseudo-color', `true-color', or `direct-color'.
1695 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1696 If omitted or nil, the selected frame's display is used.  */)
1697      (display)
1698      Lisp_Object display;
1700   NSWindowDepth depth;
1701   check_ns ();
1702   depth = [ns_get_screen (display) depth];
1704   if ( depth == NSBestDepth (NSCalibratedWhiteColorSpace, 2, 2, YES, NULL))
1705     return intern ("static-gray");
1706   else if (depth == NSBestDepth (NSCalibratedWhiteColorSpace, 8, 8, YES, NULL))
1707     return intern ("gray-scale");
1708   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 8, YES, NULL))
1709     return intern ("pseudo-color");
1710   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 4, 12, NO, NULL))
1711     return intern ("true-color");
1712   else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 24, NO, NULL))
1713     return intern ("direct-color");
1714   else
1715     /* color mgmt as far as we do it is really handled by Nextstep itself anyway */
1716     return intern ("direct-color");
1720 DEFUN ("x-display-save-under", Fx_display_save_under,
1721        Sx_display_save_under, 0, 1, 0,
1722        doc: /* Non-nil if the Nextstep display server supports the save-under feature.
1723 The optional argument DISPLAY specifies which display to ask about.
1724 DISPLAY should be a frame, the display name as a string, or a terminal ID.
1725 If omitted or nil, the selected frame's display is used.  */)
1726      (display)
1727      Lisp_Object display;
1729   check_ns ();
1730   switch ([ns_get_window (display) backingType])
1731     {
1732     case NSBackingStoreBuffered:
1733       return Qt;
1735     case NSBackingStoreRetained:
1736     case NSBackingStoreNonretained:
1737       return Qnil;
1739     default:
1740       error ("Strange value for backingType parameter of frame");
1741     }
1742   return Qnil;  /* not reached, shut compiler up */
1746 DEFUN ("x-open-connection", Fx_open_connection, Sx_open_connection,
1747        1, 3, 0,
1748        doc: /* Open a connection to a Nextstep display server.
1749 DISPLAY is the name of the display to connect to.
1750 Optional arguments XRM-STRING and MUST-SUCCEED are currently ignored.  */)
1751      (display, resource_string, must_succeed)
1752      Lisp_Object display, resource_string, must_succeed;
1754   struct ns_display_info *dpyinfo;
1756   CHECK_STRING (display);
1758   nxatoms_of_nsselect ();
1759   dpyinfo = ns_term_init (display);
1760   if (dpyinfo == 0)
1761     {
1762       if (!NILP (must_succeed))
1763         fatal ("OpenStep on %s not responding.\n",
1764                SDATA (display));
1765       else
1766         error ("OpenStep on %s not responding.\n",
1767                SDATA (display));
1768     }
1770   /* Register our external input/output types, used for determining
1771      applicable services and also drag/drop eligibility. */
1772   ns_send_types = [[NSArray arrayWithObject: NSStringPboardType] retain];
1773   ns_return_types = [[NSArray arrayWithObject: NSStringPboardType] retain];
1774   ns_drag_types = [[NSArray arrayWithObjects:
1775                             NSStringPboardType,
1776                             NSTabularTextPboardType,
1777                             NSFilenamesPboardType,
1778                             NSURLPboardType,
1779                             NSColorPboardType,
1780                             NSFontPboardType, nil] retain];
1782   return Qnil;
1786 DEFUN ("x-close-connection", Fx_close_connection, Sx_close_connection,
1787        1, 1, 0,
1788        doc: /* Close the connection to the current Nextstep display server.
1789 The second argument DISPLAY is currently ignored.  */)
1790      (display)
1791      Lisp_Object display;
1793   check_ns ();
1794 #ifdef NS_IMPL_COCOA
1795   PSFlush ();
1796 #endif
1797   /*ns_delete_terminal (dpyinfo->terminal); */
1798   [NSApp terminate: NSApp];
1799   return Qnil;
1803 DEFUN ("x-display-list", Fx_display_list, Sx_display_list, 0, 0, 0,
1804        doc: /* Return the list of display names that Emacs has connections to.  */)
1805      ()
1807   Lisp_Object tail, result;
1809   result = Qnil;
1810   for (tail = ns_display_name_list; CONSP (tail); tail = XCDR (tail))
1811     result = Fcons (XCAR (XCAR (tail)), result);
1813   return result;
1817 DEFUN ("ns-hide-others", Fns_hide_others, Sns_hide_others,
1818        0, 0, 0,
1819        doc: /* Hides all applications other than emacs.  */)
1820      ()
1822   check_ns ();
1823   [NSApp hideOtherApplications: NSApp];
1824   return Qnil;
1827 DEFUN ("ns-hide-emacs", Fns_hide_emacs, Sns_hide_emacs,
1828        1, 1, 0,
1829        doc: /* If ON is non-nil, the entire emacs application is hidden.
1830 Otherwise if emacs is hidden, it is unhidden.
1831 If ON is equal to `activate', emacs is unhidden and becomes
1832 the active application.  */)
1833      (on)
1834      Lisp_Object on;
1836   check_ns ();
1837   if (EQ (on, intern ("activate")))
1838     {
1839       [NSApp unhide: NSApp];
1840       [NSApp activateIgnoringOtherApps: YES];
1841     }
1842   else if (NILP (on))
1843     [NSApp unhide: NSApp];
1844   else
1845     [NSApp hide: NSApp];
1846   return Qnil;
1850 DEFUN ("ns-emacs-info-panel", Fns_emacs_info_panel, Sns_emacs_info_panel,
1851        0, 0, 0,
1852        doc: /* Shows the 'Info' or 'About' panel for Emacs.  */)
1853      ()
1855   check_ns ();
1856   [NSApp orderFrontStandardAboutPanel: nil];
1857   return Qnil;
1861 DEFUN ("ns-font-name", Fns_font_name, Sns_font_name, 1, 1, 0,
1862        doc: /* Determine font postscript or family name for font NAME.
1863 NAME should be a string containing either the font name or an XLFD
1864 font descriptor.  If string contains `fontset' and not
1865 `fontset-startup', it is left alone. */)
1866      (name)
1867      Lisp_Object name;
1869   char *nm;
1870   CHECK_STRING (name);
1871   nm = SDATA (name);
1873   if (nm[0] != '-')
1874     return name;
1875   if (strstr (nm, "fontset") && !strstr (nm, "fontset-startup"))
1876     return name;
1878   return build_string (ns_xlfd_to_fontname (SDATA (name)));
1882 DEFUN ("ns-list-colors", Fns_list_colors, Sns_list_colors, 0, 1, 0,
1883        doc: /* Return a list of all available colors.
1884 The optional argument FRAME is currently ignored.  */)
1885      (frame)
1886      Lisp_Object frame;
1888   Lisp_Object list = Qnil;
1889   NSEnumerator *colorlists;
1890   NSColorList *clist;
1892   if (!NILP (frame))
1893     {
1894       CHECK_FRAME (frame);
1895       if (! FRAME_NS_P (XFRAME (frame)))
1896         error ("non-Nextstep frame used in `ns-list-colors'");
1897     }
1899   BLOCK_INPUT;
1901   colorlists = [[NSColorList availableColorLists] objectEnumerator];
1902   while (clist = [colorlists nextObject])
1903     {
1904       if ([[clist name] length] < 7 ||
1905           [[clist name] rangeOfString: @"PANTONE"].location == 0)
1906         {
1907           NSEnumerator *cnames = [[clist allKeys] reverseObjectEnumerator];
1908           NSString *cname;
1909           while (cname = [cnames nextObject])
1910             list = Fcons (build_string ([cname UTF8String]), list);
1911 /*           for (i = [[clist allKeys] count] - 1; i >= 0; i--)
1912                list = Fcons (build_string ([[[clist allKeys] objectAtIndex: i]
1913                                              UTF8String]), list); */
1914         }
1915     }
1917   UNBLOCK_INPUT;
1919   return list;
1923 DEFUN ("ns-list-services", Fns_list_services, Sns_list_services, 0, 0, 0,
1924        doc: /* List available Nextstep services by querying NSApp.  */)
1925      ()
1927   Lisp_Object ret = Qnil;
1928   NSMenu *svcs;
1929   id delegate;
1931   check_ns ();
1932   svcs = [[NSMenu alloc] initWithTitle: @"Services"];
1933   [NSApp setServicesMenu: svcs];  /* this and next rebuild on <10.4 */
1934   [NSApp registerServicesMenuSendTypes: ns_send_types
1935                            returnTypes: ns_return_types];
1937 /* On Tiger, services menu updating was made lazier (waits for user to
1938    actually click on the menu), so we have to force things along: */
1939 #ifdef NS_IMPL_COCOA
1940   if (NSAppKitVersionNumber >= 744.0)
1941     {
1942       delegate = [svcs delegate];
1943       if (delegate != nil)
1944         {
1945           if ([delegate respondsToSelector: @selector (menuNeedsUpdate:)])
1946               [delegate menuNeedsUpdate: svcs];
1947           if ([delegate respondsToSelector:
1948                             @selector (menu:updateItem:atIndex:shouldCancel:)])
1949             {
1950               int i, len = [delegate numberOfItemsInMenu: svcs];
1951               for (i =0; i<len; i++)
1952                   [svcs addItemWithTitle: @"" action: NULL keyEquivalent: @""];
1953               for (i =0; i<len; i++)
1954                   if (![delegate menu: svcs
1955                            updateItem: (NSMenuItem *)[svcs itemAtIndex: i]
1956                               atIndex: i shouldCancel: NO])
1957                     break;
1958             }
1959         }
1960     }
1961 #endif
1963   [svcs setAutoenablesItems: NO];
1964 #ifdef NS_IMPL_COCOA
1965   [svcs update]; /* on OS X, converts from '/' structure */
1966 #endif
1968   ret = interpret_services_menu (svcs, Qnil, ret);
1969   return ret;
1973 DEFUN ("ns-perform-service", Fns_perform_service, Sns_perform_service,
1974        2, 2, 0,
1975        doc: /* Perform Nextstep SERVICE on SEND.
1976 SEND should be either a string or nil.
1977 The return value is the result of the service, as string, or nil if
1978 there was no result.  */)
1979      (service, send)
1980      Lisp_Object service, send;
1982   id pb;
1983   NSString *svcName;
1984   char *utfStr;
1985   int len;
1987   CHECK_STRING (service);
1988   check_ns ();
1990   utfStr = SDATA (service);
1991   svcName = [NSString stringWithUTF8String: utfStr];
1993   pb =[NSPasteboard pasteboardWithUniqueName];
1994   ns_string_to_pasteboard (pb, send);
1996   if (NSPerformService (svcName, pb) == NO)
1997     Fsignal (Qquit, Fcons (build_string ("service not available"), Qnil));
1999   if ([[pb types] count] == 0)
2000     return build_string ("");
2001   return ns_string_from_pasteboard (pb);
2005 DEFUN ("ns-convert-utf8-nfd-to-nfc", Fns_convert_utf8_nfd_to_nfc,
2006        Sns_convert_utf8_nfd_to_nfc, 1, 1, 0,
2007        doc: /* Return an NFC string that matches  the UTF-8 NFD string STR.  */)
2008     (str)
2009     Lisp_Object str;
2011 /* TODO: If GNUstep ever implements precomposedStringWithCanonicalMapping,
2012          remove this. */
2013   NSString *utfStr;
2015   CHECK_STRING (str);
2016   utfStr = [NSString stringWithUTF8String: SDATA (str)];
2017   if (![utfStr respondsToSelector:
2018                  @selector (precomposedStringWithCanonicalMapping)])
2019     {
2020       message1
2021         ("Warning: ns-convert-utf8-nfd-to-nfc unsupported under GNUstep.\n");
2022       return Qnil;
2023     }
2024   else
2025     utfStr = [utfStr precomposedStringWithCanonicalMapping];
2026   return build_string ([utfStr UTF8String]);
2030 #ifdef NS_IMPL_COCOA
2032 /* Compile and execute the AppleScript SCRIPT and return the error
2033    status as function value.  A zero is returned if compilation and
2034    execution is successful, in which case *RESULT is set to a Lisp
2035    string or a number containing the resulting script value.  Otherwise,
2036    1 is returned. */
2037 static int
2038 ns_do_applescript (script, result)
2039      Lisp_Object script, *result;
2041   NSAppleEventDescriptor *desc;
2042   NSDictionary* errorDict;
2043   NSAppleEventDescriptor* returnDescriptor = NULL;
2045   NSAppleScript* scriptObject =
2046     [[NSAppleScript alloc] initWithSource:
2047                              [NSString stringWithUTF8String: SDATA (script)]];
2049   returnDescriptor = [scriptObject executeAndReturnError: &errorDict];
2050   [scriptObject release];
2051   
2052   *result = Qnil;
2053   
2054   if (returnDescriptor != NULL)
2055     {
2056       // successful execution
2057       if (kAENullEvent != [returnDescriptor descriptorType])
2058         {
2059           *result = Qt;
2060           // script returned an AppleScript result
2061           if ((typeUnicodeText == [returnDescriptor descriptorType]) ||
2062               (typeUTF16ExternalRepresentation 
2063                == [returnDescriptor descriptorType]) ||
2064               (typeUTF8Text == [returnDescriptor descriptorType]) ||
2065               (typeCString == [returnDescriptor descriptorType]))
2066             {
2067               desc = [returnDescriptor coerceToDescriptorType: typeUTF8Text];
2068               if (desc)
2069                 *result = build_string([[desc stringValue] UTF8String]);
2070             }
2071           else
2072             {
2073               /* use typeUTF16ExternalRepresentation? */
2074               // coerce the result to the appropriate ObjC type
2075               desc = [returnDescriptor coerceToDescriptorType: typeUTF8Text];
2076               if (desc)
2077                 *result = make_number([desc int32Value]);
2078             }
2079         }
2080     }
2081   else
2082     {
2083       // no script result, return error
2084       return 1;
2085     }
2086   return 0;
2089 DEFUN ("ns-do-applescript", Fns_do_applescript, Sns_do_applescript, 1, 1, 0,
2090        doc: /* Execute AppleScript SCRIPT and return the result.  If
2091 compilation and execution are successful, the resulting script value
2092 is returned as a string, a number or, in the case of other constructs,
2093 t.  In case the execution fails, an error is signaled. */)
2094     (script)
2095     Lisp_Object script;
2097   Lisp_Object result;
2098   long status;
2100   CHECK_STRING (script);
2101   check_ns ();
2103   BLOCK_INPUT;
2104   status = ns_do_applescript (script, &result);
2105   UNBLOCK_INPUT;
2106   if (status == 0)
2107     return result;
2108   else if (!STRINGP (result))
2109     error ("AppleScript error %d", status);
2110   else
2111     error ("%s", SDATA (result));
2113 #endif
2117 /* ==========================================================================
2119     Miscellaneous functions not called through hooks
2121    ========================================================================== */
2124 /* 23: call in image.c */
2125 FRAME_PTR
2126 check_x_frame (Lisp_Object frame)
2128   return check_ns_frame (frame);
2131 /* 23: added, due to call in frame.c */
2132 struct ns_display_info *
2133 check_x_display_info (Lisp_Object frame)
2135   return check_ns_display_info (frame);
2139 /* 23: new function; we don't have much in the way of flexibility though */
2140 void
2141 x_set_scroll_bar_default_width (f)
2142      struct frame *f;
2144   int wid = FRAME_COLUMN_WIDTH (f);
2145   FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = NS_SCROLL_BAR_WIDTH_DEFAULT;
2146   FRAME_CONFIG_SCROLL_BAR_COLS (f) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) +
2147                                       wid - 1) / wid;
2151 /* 23: terms now impl this instead of x-get-resource directly */
2152 const char *
2153 x_get_string_resource (XrmDatabase rdb, char *name, char *class)
2155   /* remove appname prefix; TODO: allow for !="Emacs" */
2156   char *toCheck = class + (!strncmp (class, "Emacs.", 6) ? 6 : 0);
2157   const char *res;
2158   check_ns ();
2160   /* Support emacs-20-style face resources for backwards compatibility */
2161   if (!strncmp (toCheck, "Face", 4))
2162     toCheck = name + (!strncmp (name, "emacs.", 6) ? 6 : 0);
2164 /*fprintf (stderr, "Checking '%s'\n", toCheck); */
2165   
2166   res = [[[NSUserDefaults standardUserDefaults] objectForKey:
2167                    [NSString stringWithUTF8String: toCheck]] UTF8String];
2168   return !res ? NULL :
2169       (!strncasecmp (res, "YES", 3) ? "true" :
2170           (!strncasecmp (res, "NO", 2) ? "false" : res));
2174 Lisp_Object
2175 x_get_focus_frame (struct frame *frame)
2177   struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (frame);
2178   Lisp_Object nsfocus;
2180   if (!dpyinfo->x_focus_frame)
2181     return Qnil;
2183   XSETFRAME (nsfocus, dpyinfo->x_focus_frame);
2184   return nsfocus;
2189 x_pixel_width (struct frame *f)
2191   return FRAME_PIXEL_WIDTH (f);
2196 x_pixel_height (struct frame *f)
2198   return FRAME_PIXEL_HEIGHT (f);
2203 x_char_width (struct frame *f)
2205   return FRAME_COLUMN_WIDTH (f);
2210 x_char_height (struct frame *f)
2212   return FRAME_LINE_HEIGHT (f);
2217 x_screen_planes (struct frame *f)
2219   return FRAME_NS_DISPLAY_INFO (f)->n_planes;
2223 void
2224 x_sync (Lisp_Object frame)
2226   /* XXX Not implemented XXX */
2227   return;
2232 /* ==========================================================================
2234     Lisp definitions that, for whatever reason, we can't alias as 'ns-XXX'.
2236    ========================================================================== */
2239 DEFUN ("xw-color-defined-p", Fxw_color_defined_p, Sxw_color_defined_p, 1, 2, 0,
2240        doc: /* Return t if the current Nextstep display supports the color COLOR.
2241 The optional argument FRAME is currently ignored.  */)
2242      (color, frame)
2243      Lisp_Object color, frame;
2245   NSColor * col;
2246   check_ns ();
2247   return ns_lisp_to_color (color, &col) ? Qnil : Qt;
2251 DEFUN ("xw-color-values", Fxw_color_values, Sxw_color_values, 1, 2, 0,
2252        doc: /* Return a description of the color named COLOR.
2253 The value is a list of integer RGBA values--(RED GREEN BLUE ALPHA).
2254 These values appear to range from 0 to 65280; white is (65280 65280 65280 0).
2255 The optional argument FRAME is currently ignored.  */)
2256      (color, frame)
2257      Lisp_Object color, frame;
2259   NSColor * col;
2260   float red, green, blue, alpha;
2261   Lisp_Object rgba[4];
2263   check_ns ();
2264   CHECK_STRING (color);
2266   if (ns_lisp_to_color (color, &col))
2267     return Qnil;
2269   [[col colorUsingColorSpaceName: NSCalibratedRGBColorSpace]
2270         getRed: &red green: &green blue: &blue alpha: &alpha];
2271   rgba[0] = make_number (lrint (red*65280));
2272   rgba[1] = make_number (lrint (green*65280));
2273   rgba[2] = make_number (lrint (blue*65280));
2274   rgba[3] = make_number (lrint (alpha*65280));
2276   return Flist (4, rgba);
2280 DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
2281        doc: /* Return t if the Nextstep display supports color.
2282 The optional argument DISPLAY specifies which display to ask about.
2283 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2284 If omitted or nil, that stands for the selected frame's display.  */)
2285      (display)
2286      Lisp_Object display;
2288   NSWindowDepth depth;
2289   NSString *colorSpace;
2290   check_ns ();
2291   depth = [ns_get_screen (display) depth];
2292   colorSpace = NSColorSpaceFromDepth (depth);
2294   return    [colorSpace isEqualToString: NSDeviceWhiteColorSpace]
2295          || [colorSpace isEqualToString: NSCalibratedWhiteColorSpace]
2296       ? Qnil : Qt;
2300 DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p,
2301        Sx_display_grayscale_p, 0, 1, 0,
2302        doc: /* Return t if the Nextstep display supports shades of gray.
2303 Note that color displays do support shades of gray.
2304 The optional argument DISPLAY specifies which display to ask about.
2305 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2306 If omitted or nil, that stands for the selected frame's display. */)
2307      (display)
2308      Lisp_Object display;
2310   NSWindowDepth depth;
2311   check_ns ();
2312   depth = [ns_get_screen (display) depth];
2314   return NSBitsPerPixelFromDepth (depth) > 1 ? Qt : Qnil;
2318 DEFUN ("x-display-pixel-width", Fx_display_pixel_width, Sx_display_pixel_width,
2319        0, 1, 0,
2320        doc: /* Returns the width in pixels of the Nextstep display DISPLAY.
2321 The optional argument DISPLAY specifies which display to ask about.
2322 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2323 If omitted or nil, that stands for the selected frame's display.  */)
2324      (display)
2325      Lisp_Object display;
2327   check_ns ();
2328   return make_number ((int) [ns_get_screen (display) frame].size.width);
2332 DEFUN ("x-display-pixel-height", Fx_display_pixel_height,
2333        Sx_display_pixel_height, 0, 1, 0,
2334        doc: /* Returns the height in pixels of the Nextstep display DISPLAY.
2335 The optional argument DISPLAY specifies which display to ask about.
2336 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2337 If omitted or nil, that stands for the selected frame's display.  */)
2338      (display)
2339      Lisp_Object display;
2341   check_ns ();
2342   return make_number ((int) [ns_get_screen (display) frame].size.height);
2346 DEFUN ("display-usable-bounds", Fns_display_usable_bounds,
2347        Sns_display_usable_bounds, 0, 1, 0,
2348        doc: /*Return the bounds of the usable part of the screen.
2349 The return value is a list of integers (LEFT TOP WIDTH HEIGHT), which
2350 are the boundaries of the usable part of the screen, excluding areas
2351 reserved for the Mac menu, dock, and so forth.
2353 The screen queried corresponds to DISPLAY, which should be either a
2354 frame, a display name (a string), or terminal ID.  If omitted or nil,
2355 that stands for the selected frame's display. */)
2356      (display)
2357      Lisp_Object display;
2359   int top;
2360   NSRect vScreen;
2362   check_ns ();
2363   vScreen = [ns_get_screen (display) visibleFrame];
2364   top = vScreen.origin.y == 0.0 ?
2365     (int) [ns_get_screen (display) frame].size.height - vScreen.size.height : 0;
2367   return list4 (make_number ((int) vScreen.origin.x),
2368                 make_number (top),
2369                 make_number ((int) vScreen.size.width),
2370                 make_number ((int) vScreen.size.height));
2374 DEFUN ("x-display-planes", Fx_display_planes, Sx_display_planes,
2375        0, 1, 0,
2376        doc: /* Returns the number of bitplanes of the Nextstep display DISPLAY.
2377 The optional argument DISPLAY specifies which display to ask about.
2378 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2379 If omitted or nil, that stands for the selected frame's display.  */)
2380      (display)
2381      Lisp_Object display;
2383   check_ns ();
2384   return make_number
2385     (NSBitsPerSampleFromDepth ([ns_get_screen (display) depth]));
2389 DEFUN ("x-display-color-cells", Fx_display_color_cells,
2390        Sx_display_color_cells, 0, 1, 0,
2391        doc: /* Returns the number of color cells of the Nextstep display DISPLAY.
2392 The optional argument DISPLAY specifies which display to ask about.
2393 DISPLAY should be either a frame, a display name (a string), or terminal ID.
2394 If omitted or nil, that stands for the selected frame's display.  */)
2395      (display)
2396      Lisp_Object display;
2398   check_ns ();
2399   struct ns_display_info *dpyinfo = check_ns_display_info (display);
2401   /* We force 24+ bit depths to 24-bit to prevent an overflow.  */
2402   return make_number (1 << min (dpyinfo->n_planes, 24));
2406 /* Unused dummy def needed for compatibility. */
2407 Lisp_Object tip_frame;
2409 /* TODO: move to xdisp or similar */
2410 static void
2411 compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
2412      struct frame *f;
2413      Lisp_Object parms, dx, dy;
2414      int width, height;
2415      int *root_x, *root_y;
2417   Lisp_Object left, top;
2418   EmacsView *view = FRAME_NS_VIEW (f);
2419   NSPoint pt;
2420   
2421   /* Start with user-specified or mouse position.  */
2422   left = Fcdr (Fassq (Qleft, parms));
2423   if (INTEGERP (left))
2424     pt.x = XINT (left);
2425   else
2426     pt.x = last_mouse_motion_position.x;
2427   top = Fcdr (Fassq (Qtop, parms));
2428   if (INTEGERP (top))
2429     pt.y = XINT (top);
2430   else
2431     pt.y = last_mouse_motion_position.y;
2433   /* Convert to screen coordinates */
2434   pt = [view convertPoint: pt toView: nil];
2435   pt = [[view window] convertBaseToScreen: pt];
2437   /* Ensure in bounds.  (Note, screen origin = lower left.) */
2438   if (pt.x + XINT (dx) <= 0)
2439     *root_x = 0; /* Can happen for negative dx */
2440   else if (pt.x + XINT (dx) + width
2441            <= x_display_pixel_width (FRAME_NS_DISPLAY_INFO (f)))
2442     /* It fits to the right of the pointer.  */
2443     *root_x = pt.x + XINT (dx);
2444   else if (width + XINT (dx) <= pt.x)
2445     /* It fits to the left of the pointer.  */
2446     *root_x = pt.x - width - XINT (dx);
2447   else
2448     /* Put it left justified on the screen -- it ought to fit that way.  */
2449     *root_x = 0;
2451   if (pt.y - XINT (dy) - height >= 0)
2452     /* It fits below the pointer.  */
2453     *root_y = pt.y - height - XINT (dy);
2454   else if (pt.y + XINT (dy) + height
2455            <= x_display_pixel_height (FRAME_NS_DISPLAY_INFO (f)))
2456     /* It fits above the pointer */
2457       *root_y = pt.y + XINT (dy);
2458   else
2459     /* Put it on the top.  */
2460     *root_y = x_display_pixel_height (FRAME_NS_DISPLAY_INFO (f)) - height;
2464 DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
2465        doc: /* Show STRING in a "tooltip" window on frame FRAME.
2466 A tooltip window is a small window displaying a string.
2468 FRAME nil or omitted means use the selected frame.
2470 PARMS is an optional list of frame parameters which can be used to
2471 change the tooltip's appearance.
2473 Automatically hide the tooltip after TIMEOUT seconds.  TIMEOUT nil
2474 means use the default timeout of 5 seconds.
2476 If the list of frame parameters PARMS contains a `left' parameter,
2477 the tooltip is displayed at that x-position.  Otherwise it is
2478 displayed at the mouse position, with offset DX added (default is 5 if
2479 DX isn't specified).  Likewise for the y-position; if a `top' frame
2480 parameter is specified, it determines the y-position of the tooltip
2481 window, otherwise it is displayed at the mouse position, with offset
2482 DY added (default is -10).
2484 A tooltip's maximum size is specified by `x-max-tooltip-size'.
2485 Text larger than the specified size is clipped.  */)
2486      (string, frame, parms, timeout, dx, dy)
2487      Lisp_Object string, frame, parms, timeout, dx, dy;
2489   int root_x, root_y;
2490   struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2491   int count = SPECPDL_INDEX ();
2492   struct frame *f;
2493   char *str;
2494   NSSize size;
2496   specbind (Qinhibit_redisplay, Qt);
2498   GCPRO4 (string, parms, frame, timeout);
2500   CHECK_STRING (string);
2501   str = SDATA (string);
2502   f = check_x_frame (frame);
2503   if (NILP (timeout))
2504     timeout = make_number (5);
2505   else
2506     CHECK_NATNUM (timeout);
2508   if (NILP (dx))
2509     dx = make_number (5);
2510   else
2511     CHECK_NUMBER (dx);
2513   if (NILP (dy))
2514     dy = make_number (-10);
2515   else
2516     CHECK_NUMBER (dy);
2518   BLOCK_INPUT;
2519   if (ns_tooltip == nil)
2520     ns_tooltip = [[EmacsTooltip alloc] init];
2521   else
2522     Fx_hide_tip ();
2524   [ns_tooltip setText: str];
2525   size = [ns_tooltip frame].size;
2527   /* Move the tooltip window where the mouse pointer is.  Resize and
2528      show it.  */
2529   compute_tip_xy (f, parms, dx, dy, (int)size.width, (int)size.height,
2530                   &root_x, &root_y);
2532   [ns_tooltip showAtX: root_x Y: root_y for: XINT (timeout)];
2533   UNBLOCK_INPUT;
2535   UNGCPRO;
2536   return unbind_to (count, Qnil);
2540 DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
2541        doc: /* Hide the current tooltip window, if there is any.
2542 Value is t if tooltip was open, nil otherwise.  */)
2543      ()
2545   if (ns_tooltip == nil || ![ns_tooltip isActive])
2546     return Qnil;
2547   [ns_tooltip hide];
2548   return Qt;
2552 /* ==========================================================================
2554     Class implementations
2556    ========================================================================== */
2559 @implementation EmacsSavePanel
2560 #ifdef NS_IMPL_COCOA
2561 /* --------------------------------------------------------------------------
2562    These are overridden to intercept on OS X: ending panel restarts NSApp
2563    event loop if it is stopped.  Not sure if this is correct behavior,
2564    perhaps should check if running and if so send an appdefined.
2565    -------------------------------------------------------------------------- */
2566 - (void) ok: (id)sender
2568   [super ok: sender];
2569   panelOK = 1;
2570   [NSApp stop: self];
2572 - (void) cancel: (id)sender
2574   [super cancel: sender];
2575   [NSApp stop: self];
2577 #endif
2578 @end
2581 @implementation EmacsOpenPanel
2582 #ifdef NS_IMPL_COCOA
2583 /* --------------------------------------------------------------------------
2584    These are overridden to intercept on OS X: ending panel restarts NSApp
2585    event loop if it is stopped.  Not sure if this is correct behavior,
2586    perhaps should check if running and if so send an appdefined.
2587    -------------------------------------------------------------------------- */
2588 - (void) ok: (id)sender
2590   [super ok: sender];
2591   panelOK = 1;
2592   [NSApp stop: self];
2594 - (void) cancel: (id)sender
2596   [super cancel: sender];
2597   [NSApp stop: self];
2599 #endif
2600 @end
2603 @implementation EmacsFileDelegate
2604 /* --------------------------------------------------------------------------
2605    Delegate methods for Open/Save panels
2606    -------------------------------------------------------------------------- */
2607 - (BOOL)panel: (id)sender isValidFilename: (NSString *)filename
2609   return YES;
2611 - (BOOL)panel: (id)sender shouldShowFilename: (NSString *)filename
2613   return YES;
2615 - (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename
2616           confirmed: (BOOL)okFlag
2618   return filename;
2620 @end
2622 #endif
2624 /* ==========================================================================
2626     Lisp interface declaration
2628    ========================================================================== */
2631 void
2632 syms_of_nsfns ()
2634   int i;
2636   Qnone = intern ("none");
2637   staticpro (&Qnone);
2638   Qbuffered = intern ("bufferd");
2639   staticpro (&Qbuffered);
2640   Qfontsize = intern ("fontsize");
2641   staticpro (&Qfontsize);
2643   DEFVAR_LISP ("ns-icon-type-alist", &Vns_icon_type_alist,
2644                doc: /* Alist of elements (REGEXP . IMAGE) for images of icons associated to frames.
2645 If the title of a frame matches REGEXP, then IMAGE.tiff is
2646 selected as the image of the icon representing the frame when it's
2647 miniaturized.  If an element is t, then Emacs tries to select an icon
2648 based on the filetype of the visited file.
2650 The images have to be installed in a folder called English.lproj in the
2651 Emacs folder.  You have to restart Emacs after installing new icons.
2653 Example: Install an icon Gnus.tiff and execute the following code
2655   (setq ns-icon-type-alist
2656         (append ns-icon-type-alist
2657                 '((\"^\\\\*\\\\(Group\\\\*$\\\\|Summary \\\\|Article\\\\*$\\\\)\"
2658                    . \"Gnus\"))))
2660 When you miniaturize a Group, Summary or Article frame, Gnus.tiff will
2661 be used as the image of the icon representing the frame.  */);
2662   Vns_icon_type_alist = Fcons (Qt, Qnil);
2664   DEFVAR_LISP ("ns-version-string", &Vns_version_string,
2665                doc: /* Toolkit version for NS Windowing.  */);
2666   Vns_version_string = ns_appkit_version ();
2668   defsubr (&Sns_read_file_name);
2669   defsubr (&Sns_get_resource);
2670   defsubr (&Sns_set_resource);
2671   defsubr (&Sxw_display_color_p); /* this and next called directly by C code */
2672   defsubr (&Sx_display_grayscale_p);
2673   defsubr (&Sns_font_name);
2674   defsubr (&Sns_list_colors);
2675 #ifdef NS_IMPL_COCOA
2676   defsubr (&Sns_do_applescript);
2677 #endif
2678   defsubr (&Sxw_color_defined_p);
2679   defsubr (&Sxw_color_values);
2680   defsubr (&Sx_server_max_request_size);
2681   defsubr (&Sx_server_vendor);
2682   defsubr (&Sx_server_version);
2683   defsubr (&Sx_display_pixel_width);
2684   defsubr (&Sx_display_pixel_height);
2685   defsubr (&Sns_display_usable_bounds);
2686   defsubr (&Sx_display_mm_width);
2687   defsubr (&Sx_display_mm_height);
2688   defsubr (&Sx_display_screens);
2689   defsubr (&Sx_display_planes);
2690   defsubr (&Sx_display_color_cells);
2691   defsubr (&Sx_display_visual_class);
2692   defsubr (&Sx_display_backing_store);
2693   defsubr (&Sx_display_save_under);
2694   defsubr (&Sx_create_frame);
2695   defsubr (&Sns_set_alpha);
2696   defsubr (&Sx_open_connection);
2697   defsubr (&Sx_close_connection);
2698   defsubr (&Sx_display_list);
2700   defsubr (&Sns_hide_others);
2701   defsubr (&Sns_hide_emacs);
2702   defsubr (&Sns_emacs_info_panel);
2703   defsubr (&Sns_list_services);
2704   defsubr (&Sns_perform_service);
2705   defsubr (&Sns_convert_utf8_nfd_to_nfc);
2706   defsubr (&Sx_focus_frame);
2707   defsubr (&Sns_popup_prefs_panel);
2708   defsubr (&Sns_popup_font_panel);
2709   defsubr (&Sns_popup_color_panel);
2711   defsubr (&Sx_show_tip);
2712   defsubr (&Sx_hide_tip);
2714   /* used only in fontset.c */
2715   check_window_system_func = check_ns;
2719 // arch-tag: dc2a3f74-1123-4daa-8eed-fb78db6a5642