aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/ChangeLog131
-rw-r--r--src/Makefile.in99
-rw-r--r--src/blockinput.h12
-rw-r--r--src/callproc.c5
-rw-r--r--src/config.in52
-rw-r--r--src/dispextern.h15
-rw-r--r--src/dispnew.c18
-rw-r--r--src/emacs.c84
-rw-r--r--src/font.c16
-rw-r--r--src/font.h3
-rw-r--r--src/fontset.c8
-rw-r--r--src/frame.c41
-rw-r--r--src/frame.h18
-rw-r--r--src/fringe.c2
-rw-r--r--src/getloadavg.c7
-rw-r--r--src/image.c256
-rw-r--r--src/keyboard.c55
-rw-r--r--src/keyboard.h53
-rw-r--r--src/keymap.c68
-rw-r--r--src/lisp.h7
-rw-r--r--src/lread.c4
-rw-r--r--src/menu.c74
-rw-r--r--src/nsfns.m2668
-rw-r--r--src/nsgui.h208
-rw-r--r--src/nsimage.m480
-rw-r--r--src/nsmenu.m1948
-rw-r--r--src/nsselect.m624
-rw-r--r--src/nsterm.h827
-rw-r--r--src/nsterm.m6598
-rw-r--r--src/process.c8
-rw-r--r--src/s/darwin.h35
-rw-r--r--src/syntax.c13
-rw-r--r--src/sysselect.h4
-rw-r--r--src/termhooks.h3
-rw-r--r--src/terminal.c2
-rw-r--r--src/terminfo.c3
-rw-r--r--src/w32gui.h93
-rw-r--r--src/window.c3
-rw-r--r--src/xdisp.c68
-rw-r--r--src/xfaces.c56
40 files changed, 14476 insertions, 193 deletions
diff --git a/src/ChangeLog b/src/ChangeLog
index 848046ece79..e8a514d2a50 100644
--- a/src/ChangeLog
+++ b/src/ChangeLog
@@ -1,3 +1,134 @@
12008-07-15 Adrian Robert <Adrian.B.Robert@gmail.com>
2
3 Changes and additions for NeXTstep windowing system (Cocoa and
4 GNUstep) support.
5
6 * Makefile.in
7 * config.in: Support defines and build commands for NS port.
8 * blockinput.h (BLOCK_INPUT, UNBLOCK_INPUT, TOTALLY_UNBLOCK_INPUT)
9 (UNBLOCK_INPUT_TO): Don't use under NS unless EXPERIMENTAL_CONTROL_G.
10 * callproc.c (set_initial_environment): Initialize
11 Vprocess_environment under CANNOT_DUMP (fixes crash when
12 batch-compiling for bootstrap, due to Chris Hall).
13 * dispextern.h: Include nsgui.h and add needed typedefs under NS
14 windowing.
15 (struct face): Add synth_ital field.
16 * dispnew.c: Include nsterm.h when compiling under NS windowing.
17 (init_display): Initialize Vinitial_window_system to "ns" when so
18 compiled.
19 * emacs.c: Include GSConfig.h when compiling under GNUstep.
20 (display_arg): Use under NS.
21 (main): Under NS, allocate autorelease pool and handle command line
22 args. Move syms_of_xmenu() call under #ifdef HAVE_X_WINDOWS.
23 (standard_args): Add NS-specific args.
24 (shut_down_emacs): Shut down NS terminal if compiled under NS.
25 * font.c (DEFAULT_ENCODING): New variable.
26 (font_find_for_lface): Use it.
27 (syms_of_font): Load syms_of_nsfont under NS.
28 * font.h: Declare nsfont_driver when compiled under NS.
29 * fontset.c: When compiling under NS, include nsterm.h.
30 (fontset_from_font): Autoconstruct fontset under NS.
31 * frame.c (various): Under NS, include nsterm.h, add Qns window system
32 symbol, document and use it.
33 (make_initial_frame): Call init_frame_faces(f) in CANNOT_DUMP case --
34 patch to fix crash due to different init order, due to Chris Hall and
35 Yamamoto Mitsuharu.
36 (do_switch_frame): When for_deletion under Cocoa, add
37 Fraise_frame(Qnil).
38 (x_set_frame_parameters): Ensure font attribute changes are picked up.
39 (x_get_arg): Allow "yes" and "no" as boolean values.
40 (syms_of_frame): Declare Qns. Init Vdefault_frame_scroll_bars to
41 Qright under Cocoa.
42 (focus-follows-mouse): Default to 0 under NS.
43 * frame.h (enum output_method): Add output_ns.
44 (external_tool_bar, external_menu_bar, FRAME_EXTERNAL_TOOLBAR)
45 (FRAME_EXTERNAL_MENU_BAR): Use under NS.
46 (FRAME_WINDOW_P): NS-specific definition.
47 * fringe.c (max_used_fringe_bitmap): Make public.
48 * getloadavg.c (mach/mach.h): Include it under NeXT descendant OS's.
49 (getloadavg): Use NeXT code under descendant OS's.
50 * image.c (includes and header section, x_create_bitmap_from_data)
51 (x_create_bitmap_from_file, free_bitmap_record, image_background)
52 (image_background_transparent, x_clear_image_1)
53 (x_create_x_image_and_pixmap, x_destroy_x_image, x_put_x_image)
54 (Create_Pixmap_From_Bitmap_Data, xpm_load_image, lookup_rgb_color)
55 (x_to_xcolors, x_from_xcolors, x_disable_image)
56 (x_build_heuristic_mask, syms_of_image): Add NS support parallel to
57 other GUIs, including XPM support using code originally written for
58 Carbon GUI.
59 (png_load, jpeg_load, tiff_load, gif_load): Added implementations
60 using NS API.
61 (image_ascent): Use font metrics macros instead of direct struct field
62 access.
63 * keyboard.c (includes): Add nsterm.h when compiling under NS.
64 (kbd_buffer_get_event): Handle NS as other GUI windowing systems.
65 Also, handle NS as GTK for menu bar purposes.
66 (make_lispy_event): Handle NS as other GUI windowing systems, and as X
67 toolkit where they differ.
68 (parse_menu_item): Prefer keybindings using 'super' modifier. Also,
69 use cachelist, still needed under NS.
70 * keyboard.h (ENCODE_MENU_STRING, XtPointer, Boolean): Handle as
71 NTGUI.
72 (struct widget_value): Define it here for menu.c.
73 * keymap.c (includes): Include modifier internals.
74 (lisp_to_mod, modifier_sequence_p): New functions, compiled only under
75 NS.
76 (where_is_internal, Fwhere_is_internal): When compiled under NS, add
77 support for preferring sequences using certain modifiers, specified by
78 the FIRSTONLY argument.
79 * lisp.h (hash_remove): Rename to avoid name clash when compiling
80 under NS GNUstep implementation.
81 (USE_LSB_TAG): Use it under Cocoa when compiling under NS.
82 * lread.c (init_lread): Treat NS as HAVE_CARBON for turn_off_warning.
83 * menu.c: Include nsterm.h under NS.
84 (single_menu_item, parse_single_submenu, xmalloc_widget_value)
85 (free_menubar_widget_tree_value, update_submenu_strings)
86 (find_and_call_menu_selection): Treat NS as X and NT.
87 (find_and_return_menu_selection): New function, used for popup menus.
88 * nsgui.h
89 * nsterm.h
90 * nsfns.m
91 * nsimage.m
92 * nsmenu.m
93 * nsselect.m
94 * nsterm.m: New files.
95 * process.c (wait_reading_process_output): Under NS, call ns_select()
96 instead of plain select().
97 * syntax.c (char_quoted): Under NS, avoid a crash when called near
98 beginning of buffer.
99 * sysselect.h (init_process): Rename when compiling under Cocoa to
100 avoid name conflict.
101 * termhooks.h (display_info): Add ns_display_info to union.
102 * terminal.c (Fterminal_live_p): Add ns to terminal types.
103 * terminfo.c (UP, BC, PC): Don't declare when compiling under NS in
104 COCOA environment.
105 * unexnext.c: Update to work with mach API on Mac OS X, and to use new
106 unexec() signature. (Note, this will dump, but the resulting file
107 crashes; unexosx is used instead; keeping around for reference and
108 possible aid in getting dump working under GNUstep.)
109 * w32gui.h (button_type, widget_value): Remove definitions (now in
110 keyboard.h).
111 * window.c: Include nsterm.h when compiling under NS.
112 * xdisp.c (includes): Include nsterm.h when compiling under NS.
113 (set_frame_menubar, update_menu_bar, display_menu_bar): Handle NS as
114 other GUI windowing systems.
115 (update_tool_bar, redisplay_tool_bar, redisplay_window): Handle NS as
116 GTK.
117 (x_consider_frame_title): Under NS, set icon type and frame
118 modified-state indicator; use ns_set_name_as_filename() when using
119 formatted title.
120 (update_window_cursor): Make public when compiling under NS.
121 (display_hourglass_p, syms_of_xdisp, hourglass_shown_p)
122 (hourglass_atimer, Vhourglass_delay
123 * xfaces.c (header section, init_frame_faces, clear_font_table)
124 (defined_color, unload_color, x_face_list_fonts)
125 (prepare_face_for_display): Add NS support parallel to other GUIs)
126 (emulate GCs like other non-X GUIs.
127 (split_font_name): Don't lowercase font name under NS.
128 (merge_face_ref, Finternal_set_lisp_face_attribute): Support stippling
129 under NS.
130 * s/darwin.h: Add support for compilation under NS.
131
12008-07-15 Jason Rumney <jasonr@gnu.org> 1322008-07-15 Jason Rumney <jasonr@gnu.org>
2 133
3 * w32fns.c (Fx_create_frame): Remove duplicate unwind_protect. 134 * w32fns.c (Fx_create_frame): Remove duplicate unwind_protect.
diff --git a/src/Makefile.in b/src/Makefile.in
index 9fc66979f25..123a49fca68 100644
--- a/src/Makefile.in
+++ b/src/Makefile.in
@@ -112,6 +112,11 @@ SHELL=/bin/sh
112#endif 112#endif
113#endif 113#endif
114 114
115/* Under GNUstep, putting libc on the link line causes problems. */
116#ifdef GNUSTEP
117#define LIB_STANDARD
118#endif
119
115/* Unless inhibited or changed, use -lg to link for debugging. */ 120/* Unless inhibited or changed, use -lg to link for debugging. */
116#ifndef LIBS_DEBUG 121#ifndef LIBS_DEBUG
117#define LIBS_DEBUG -lg 122#define LIBS_DEBUG -lg
@@ -229,6 +234,15 @@ STARTFILES = START_FILES
229#endif /* not ORDINARY_LINK */ 234#endif /* not ORDINARY_LINK */
230 235
231 236
237#ifdef GNUSTEP
238/* Pull in stuff from GNUstep-make. */
239FOUNDATION_LIB=gnu
240GUI_LIB=gnu
241include $(GNUSTEP_MAKEFILES)/Additional/base.make
242include $(GNUSTEP_MAKEFILES)/Additional/gui.make
243shared=no
244#endif
245
232#ifdef HAVE_DBUS 246#ifdef HAVE_DBUS
233DBUS_CFLAGS = @DBUS_CFLAGS@ 247DBUS_CFLAGS = @DBUS_CFLAGS@
234DBUS_LIBS = @DBUS_LIBS@ 248DBUS_LIBS = @DBUS_LIBS@
@@ -249,8 +263,11 @@ DBUS_OBJ = dbusbind.o
249/* C_SWITCH_X_SITE must come before C_SWITCH_X_MACHINE and C_SWITCH_X_SYSTEM 263/* C_SWITCH_X_SITE must come before C_SWITCH_X_MACHINE and C_SWITCH_X_SYSTEM
250 since it may have -I options that should override those two. */ 264 since it may have -I options that should override those two. */
251ALL_CFLAGS=-Demacs -DHAVE_CONFIG_H $(MYCPPFLAGS) -I. -I${srcdir} C_SWITCH_MACHINE C_SWITCH_SYSTEM C_SWITCH_SITE C_SWITCH_X_SITE C_SWITCH_X_MACHINE C_SWITCH_X_SYSTEM C_SWITCH_SYSTEM_TEMACS ${CFLAGS_SOUND} ${RSVG_CFLAGS} ${DBUS_CFLAGS} ${CFLAGS} @FREETYPE_CFLAGS@ @FONTCONFIG_CFLAGS@ @LIBOTF_CFLAGS@ @M17N_FLT_CFLAGS@ 265ALL_CFLAGS=-Demacs -DHAVE_CONFIG_H $(MYCPPFLAGS) -I. -I${srcdir} C_SWITCH_MACHINE C_SWITCH_SYSTEM C_SWITCH_SITE C_SWITCH_X_SITE C_SWITCH_X_MACHINE C_SWITCH_X_SYSTEM C_SWITCH_SYSTEM_TEMACS ${CFLAGS_SOUND} ${RSVG_CFLAGS} ${DBUS_CFLAGS} ${CFLAGS} @FREETYPE_CFLAGS@ @FONTCONFIG_CFLAGS@ @LIBOTF_CFLAGS@ @M17N_FLT_CFLAGS@
266.SUFFIXES: .m
252.c.o: 267.c.o:
253 $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $< 268 $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $<
269.m.o:
270 $(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) GNU_OBJC_CFLAGS $<
254 271
255#ifndef LIBX11_SYSTEM 272#ifndef LIBX11_SYSTEM
256#define LIBX11_SYSTEM 273#define LIBX11_SYSTEM
@@ -260,13 +277,8 @@ ALL_CFLAGS=-Demacs -DHAVE_CONFIG_H $(MYCPPFLAGS) -I. -I${srcdir} C_SWITCH_MACHIN
260#define LIB_X11_LIB -lX11 277#define LIB_X11_LIB -lX11
261#endif 278#endif
262 279
263/* xmenu.c should not be compiled on OSX. */
264#ifndef HAVE_CARBON
265XMENU_OBJ = xmenu.o
266#endif
267
268#ifdef HAVE_X_WINDOWS 280#ifdef HAVE_X_WINDOWS
269 281XMENU_OBJ = xmenu.o
270XOBJ= xterm.o xfns.o xselect.o xrdb.o fontset.o xsmfns.o fringe.o image.o 282XOBJ= xterm.o xfns.o xselect.o xrdb.o fontset.o xsmfns.o fringe.o image.o
271 283
272#ifdef HAVE_MENUS 284#ifdef HAVE_MENUS
@@ -518,6 +530,21 @@ emacsapp = $(PWD)/$(mac)Emacs.app/
518emacsappsrc = ${srcdir}/../mac/Emacs.app/ 530emacsappsrc = ${srcdir}/../mac/Emacs.app/
519#endif 531#endif
520 532
533#ifdef HAVE_NS
534/* Object files for NeXTstep */
535NS_OBJ= nsterm.o nsfns.o nsmenu.o nsselect.o nsimage.o nsfont.o \
536 fontset.o fringe.o image.o
537emacsapp = $(PWD)/../nextstep/build/Emacs.app/
538FONT_DRIVERS = nsfont.o
539#ifdef GNUSTEP
540emacsappsrc = ${srcdir}/../nextstep/GNUstep/Emacs.base
541emacsbindir = $(emacsapp)
542#else
543emacsappsrc = ${srcdir}/../nextstep/Cocoa/Emacs.base
544emacsbindir = $(emacsapp)/Contents/MacOS/
545#endif /* GNUSTEP */
546#endif /* HAVE_NS */
547
521#ifdef HAVE_WINDOW_SYSTEM 548#ifdef HAVE_WINDOW_SYSTEM
522#ifdef HAVE_X_WINDOWS 549#ifdef HAVE_X_WINDOWS
523#if defined (HAVE_XFT) 550#if defined (HAVE_XFT)
@@ -545,7 +572,7 @@ obj= dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \
545 process.o callproc.o \ 572 process.o callproc.o \
546 region-cache.o sound.o atimer.o \ 573 region-cache.o sound.o atimer.o \
547 doprnt.o strftime.o intervals.o textprop.o composite.o md5.o \ 574 doprnt.o strftime.o intervals.o textprop.o composite.o md5.o \
548 $(MSDOS_OBJ) $(MAC_OBJ) $(CYGWIN_OBJ) $(FONT_DRIVERS) 575 $(MSDOS_OBJ) $(MAC_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_DRIVERS)
549 576
550/* Object files used on some machine or other. 577/* Object files used on some machine or other.
551 These go in the DOC file on all machines 578 These go in the DOC file on all machines
@@ -553,6 +580,7 @@ obj= dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \
553SOME_MACHINE_OBJECTS = dosfns.o msdos.o \ 580SOME_MACHINE_OBJECTS = dosfns.o msdos.o \
554 xterm.o xfns.o xmenu.o xselect.o xrdb.o xsmfns.o fringe.o image.o \ 581 xterm.o xfns.o xmenu.o xselect.o xrdb.o xsmfns.o fringe.o image.o \
555 mac.o macterm.o macfns.o macmenu.o macselect.o fontset.o \ 582 mac.o macterm.o macfns.o macmenu.o macselect.o fontset.o \
583 nsterm.o nsfns.o nsmenu.o nsselect.o nsimage.o \
556 w32.o w32console.o w32fns.o w32heap.o w32inevt.o \ 584 w32.o w32console.o w32fns.o w32heap.o w32inevt.o \
557 w32menu.o w32proc.o w32reg.o w32select.o w32term.o w32xfns.o $(FONT_DRIVERS) 585 w32menu.o w32proc.o w32reg.o w32select.o w32term.o w32xfns.o $(FONT_DRIVERS)
558 586
@@ -876,6 +904,7 @@ SOME_MACHINE_LISP = ../lisp/mouse.elc \
876 Note that SunOS needs -lm to come before -lc; otherwise, you get 904 Note that SunOS needs -lm to come before -lc; otherwise, you get
877 duplicated symbols. If the standard libraries were compiled 905 duplicated symbols. If the standard libraries were compiled
878 with GCC, we might need gnulib again after them. */ 906 with GCC, we might need gnulib again after them. */
907
879LIBES = $(LOADLIBES) $(LIBS) $(LIBX) $(LIBSOUND) $(RSVG_LIBS) $(DBUS_LIBS) \ 908LIBES = $(LOADLIBES) $(LIBS) $(LIBX) $(LIBSOUND) $(RSVG_LIBS) $(DBUS_LIBS) \
880 LIBGPM LIBRESOLV LIBS_SYSTEM LIBS_MACHINE LIBS_TERMCAP \ 909 LIBGPM LIBRESOLV LIBS_SYSTEM LIBS_MACHINE LIBS_TERMCAP \
881 LIBS_DEBUG $(GETLOADAVG_LIBS) \ 910 LIBS_DEBUG $(GETLOADAVG_LIBS) \
@@ -910,7 +939,10 @@ emacs${EXEEXT}: temacs${EXEEXT} ${etc}DOC ${lisp} ${SOME_MACHINE_LISP}
910 @: bootstrap-emacs, so let us replace it. 939 @: bootstrap-emacs, so let us replace it.
911 -ln -f emacs${EXEEXT} bootstrap-emacs${EXEEXT} 940 -ln -f emacs${EXEEXT} bootstrap-emacs${EXEEXT}
912#endif /* ! defined (CANNOT_DUMP) */ 941#endif /* ! defined (CANNOT_DUMP) */
942/* XXX: not working under NS currently due to path shenanigans.. */
943#ifndef HAVE_NS
913 -./emacs -q -batch -f list-load-path-shadows 944 -./emacs -q -batch -f list-load-path-shadows
945#endif
914 946
915/* We run make-docfile twice because the command line may get too long 947/* We run make-docfile twice because the command line may get too long
916 on some systems. */ 948 on some systems. */
@@ -935,9 +967,13 @@ ${libsrc}make-docfile${EXEEXT}:
935 967
936temacs${EXEEXT}: $(LOCALCPP) $(STARTFILES) stamp-oldxmenu ${obj} ${otherobj} OBJECTS_MACHINE prefix-args${EXEEXT} 968temacs${EXEEXT}: $(LOCALCPP) $(STARTFILES) stamp-oldxmenu ${obj} ${otherobj} OBJECTS_MACHINE prefix-args${EXEEXT}
937 echo "${obj} ${otherobj} " OBJECTS_MACHINE > buildobj.lst 969 echo "${obj} ${otherobj} " OBJECTS_MACHINE > buildobj.lst
970#ifdef GNUSTEP
971 $(CC) -rdynamic YMF_PASS_LDFLAGS (${TEMACS_LDFLAGS}) -o temacs ${obj} ${otherobj} OBJECTS_MACHINE ${LIBES}
972#else
938 $(LD) YMF_PASS_LDFLAGS (${STARTFLAGS} ${TEMACS_LDFLAGS}) $(LDFLAGS) \ 973 $(LD) YMF_PASS_LDFLAGS (${STARTFLAGS} ${TEMACS_LDFLAGS}) $(LDFLAGS) \
939 -o temacs ${STARTFILES} ${obj} ${otherobj} \ 974 -o temacs ${STARTFILES} ${obj} ${otherobj} \
940 OBJECTS_MACHINE ${LIBES} 975 OBJECTS_MACHINE ${LIBES}
976#endif
941 977
942/* We do not use ALL_LDFLAGS because LD_SWITCH_SYSTEM and LD_SWITCH_MACHINE 978/* We do not use ALL_LDFLAGS because LD_SWITCH_SYSTEM and LD_SWITCH_MACHINE
943 often contain options that have to do with using Emacs''s crt0, 979 often contain options that have to do with using Emacs''s crt0,
@@ -1080,7 +1116,7 @@ fontset.o: dispextern.h fontset.h fontset.c ccl.h buffer.h character.h \
1080getloadavg.o: getloadavg.c $(config_h) 1116getloadavg.o: getloadavg.c $(config_h)
1081image.o: image.c frame.h window.h dispextern.h blockinput.h atimer.h \ 1117image.o: image.c frame.h window.h dispextern.h blockinput.h atimer.h \
1082 systime.h xterm.h w32term.h w32gui.h macterm.h macgui.h font.h \ 1118 systime.h xterm.h w32term.h w32gui.h macterm.h macgui.h font.h \
1083 $(config_h) 1119 nsterm.h nsgui.h $(config_h)
1084indent.o: indent.c frame.h window.h indent.h buffer.h $(config_h) termchar.h \ 1120indent.o: indent.c frame.h window.h indent.h buffer.h $(config_h) termchar.h \
1085 termopts.h disptab.h region-cache.h character.h category.h composite.h \ 1121 termopts.h disptab.h region-cache.h character.h category.h composite.h \
1086 dispextern.h keyboard.h 1122 dispextern.h keyboard.h
@@ -1089,7 +1125,8 @@ insdel.o: insdel.c window.h buffer.h $(INTERVAL_SRC) blockinput.h character.h \
1089keyboard.o: keyboard.c termchar.h termhooks.h termopts.h buffer.h character.h \ 1125keyboard.o: keyboard.c termchar.h termhooks.h termopts.h buffer.h character.h \
1090 commands.h frame.h window.h macros.h disptab.h keyboard.h syssignal.h \ 1126 commands.h frame.h window.h macros.h disptab.h keyboard.h syssignal.h \
1091 systime.h dispextern.h syntax.h $(INTERVAL_SRC) blockinput.h \ 1127 systime.h dispextern.h syntax.h $(INTERVAL_SRC) blockinput.h \
1092 atimer.h xterm.h puresize.h msdos.h keymap.h w32term.h macterm.h $(config_h) 1128 atimer.h xterm.h puresize.h msdos.h keymap.h w32term.h macterm.h nsterm.h \
1129 $(config_h)
1093keymap.o: keymap.c buffer.h commands.h keyboard.h termhooks.h blockinput.h \ 1130keymap.o: keymap.c buffer.h commands.h keyboard.h termhooks.h blockinput.h \
1094 atimer.h systime.h puresize.h character.h intervals.h keymap.h window.h \ 1131 atimer.h systime.h puresize.h character.h intervals.h keymap.h window.h \
1095 $(config_h) 1132 $(config_h)
@@ -1155,15 +1192,15 @@ widget.o: widget.c xterm.h frame.h dispextern.h widgetprv.h \
1155window.o: window.c indent.h commands.h frame.h window.h buffer.h termchar.h \ 1192window.o: window.c indent.h commands.h frame.h window.h buffer.h termchar.h \
1156 disptab.h keyboard.h dispextern.h msdos.h composite.h \ 1193 disptab.h keyboard.h dispextern.h msdos.h composite.h \
1157 keymap.h blockinput.h atimer.h systime.h $(INTERVAL_SRC) \ 1194 keymap.h blockinput.h atimer.h systime.h $(INTERVAL_SRC) \
1158 xterm.h w32term.h macterm.h $(config_h) 1195 xterm.h w32term.h macterm.h nsterm.h $(config_h)
1159xdisp.o: xdisp.c macros.h commands.h process.h indent.h buffer.h dispextern.h \ 1196xdisp.o: xdisp.c macros.h commands.h process.h indent.h buffer.h dispextern.h \
1160 coding.h termchar.h frame.h window.h disptab.h termhooks.h character.h \ 1197 coding.h termchar.h frame.h window.h disptab.h termhooks.h character.h \
1161 charset.h $(config_h) keyboard.h $(INTERVAL_SRC) region-cache.h xterm.h \ 1198 charset.h $(config_h) keyboard.h $(INTERVAL_SRC) region-cache.h xterm.h \
1162 w32term.h macterm.h msdos.h composite.h fontset.h blockinput.h atimer.h \ 1199 w32term.h macterm.h nsterm.h msdos.h composite.h fontset.h blockinput.h \
1163 systime.h keymap.h font.h 1200 atimer.h systime.h keymap.h font.h
1164xfaces.o: xfaces.c dispextern.h frame.h xterm.h buffer.h blockinput.h \ 1201xfaces.o: xfaces.c dispextern.h frame.h xterm.h buffer.h blockinput.h \
1165 window.h character.h charset.h msdos.h dosfns.h composite.h atimer.h \ 1202 window.h character.h charset.h msdos.h dosfns.h composite.h atimer.h \
1166 systime.h keyboard.h fontset.h w32term.h macterm.h $(INTERVAL_SRC) \ 1203 systime.h keyboard.h fontset.h w32term.h macterm.h nsterm.h $(INTERVAL_SRC) \
1167 termchar.h termhooks.h font.h $(config_h) 1204 termchar.h termhooks.h font.h $(config_h)
1168xfns.o: xfns.c buffer.h frame.h window.h keyboard.h xterm.h dispextern.h \ 1205xfns.o: xfns.c buffer.h frame.h window.h keyboard.h xterm.h dispextern.h \
1169 $(srcdir)/../lwlib/lwlib.h blockinput.h atimer.h systime.h epaths.h \ 1206 $(srcdir)/../lwlib/lwlib.h blockinput.h atimer.h systime.h epaths.h \
@@ -1276,7 +1313,38 @@ macosx-app: macosx-bundle ${emacsapp}Contents/MacOS/Emacs
1276${emacsapp}Contents/MacOS/Emacs: emacs${EXEEXT} 1313${emacsapp}Contents/MacOS/Emacs: emacs${EXEEXT}
1277 mkdir -p ${emacsapp}Contents/MacOS/; 1314 mkdir -p ${emacsapp}Contents/MacOS/;
1278 cd ${emacsapp}Contents/MacOS/; cp ../../../../src/emacs${EXEEXT} Emacs${EXEEXT} 1315 cd ${emacsapp}Contents/MacOS/; cp ../../../../src/emacs${EXEEXT} Emacs${EXEEXT}
1279#endif 1316#endif /* HAVE_CARBON */
1317
1318#ifdef HAVE_NS
1319abbrev.o buffer.o callint.o cmds.o dispnew.o editfns.o fileio.o frame.o \
1320 fontset.o indent.o insdel.o keyboard.o macros.o minibuf.o msdos.o process.o \
1321 scroll.o sysdep.o term.o widget.o window.o xdisp.o xfaces.o xfns.o \
1322 xterm.o xselect.o sound.o: nsgui.h
1323nsfns.o: nsfns.m charset.h nsterm.h nsgui.h frame.h window.h buffer.h \
1324 dispextern.h nsgui.h fontset.h $(INTERVAL_SRC) keyboard.h blockinput.h \
1325 atimer.h systime.h epaths.h termhooks.h coding.h systime.h $(config_h)
1326nsmenu.o: nsmenu.m termhooks.h frame.h window.h dispextern.h \
1327 nsgui.h keyboard.h blockinput.h atimer.h systime.h buffer.h \
1328 nsterm.h $(config_h)
1329nsterm.o: nsterm.m blockinput.h atimer.h systime.h syssignal.h nsterm.h \
1330 nsgui.h frame.h charset.h ccl.h dispextern.h fontset.h termhooks.h \
1331 termopts.h termchar.h disptab.h buffer.h window.h keyboard.h \
1332 $(INTERVAL_SRC) process.h coding.h $(config_h)
1333nsselect.o: nsselect.m blockinput.h nsterm.h nsgui.h frame.h $(config_h)
1334nsimage.o: nsimage.m nsterm.h
1335nsfont.o: nsterm.h dispextern.h frame.h lisp.h $(config_h)
1336
1337${emacsapp}: ${emacsappsrc}
1338 mkdir -p ${emacsapp}
1339 ( cd ${emacsappsrc} ; tar cfh - . ) | ( cd ${emacsapp} ; tar xf - )
1340
1341${emacsbindir}Emacs: emacs${EXEEXT}
1342 mkdir -p ${emacsbindir}
1343 cp -f emacs${EXEEXT} ${emacsbindir}Emacs
1344
1345ns-app: ${emacsapp} ${emacsbindir}Emacs
1346
1347#endif /* HAVE_NS */
1280 1348
1281mostlyclean: 1349mostlyclean:
1282 rm -f temacs${EXEEXT} prefix-args${EXEEXT} core *.core \#* *.o libXMenu11.a liblw.a 1350 rm -f temacs${EXEEXT} prefix-args${EXEEXT} core *.core \#* *.o libXMenu11.a liblw.a
@@ -1285,6 +1353,9 @@ mostlyclean:
1285 rm -f buildobj.lst 1353 rm -f buildobj.lst
1286clean: mostlyclean 1354clean: mostlyclean
1287 rm -f emacs-*.*.*${EXEEXT} emacs${EXEEXT} 1355 rm -f emacs-*.*.*${EXEEXT} emacs${EXEEXT}
1356#ifdef GNUSTEP
1357 rm -f *.d
1358#endif
1288/* bootstrap-clean is used to clean up just before a bootstrap. 1359/* bootstrap-clean is used to clean up just before a bootstrap.
1289 It should remove all files generated during a compilation/bootstrap, 1360 It should remove all files generated during a compilation/bootstrap,
1290 but not things like config.status or TAGS. */ 1361 but not things like config.status or TAGS. */
diff --git a/src/blockinput.h b/src/blockinput.h
index bcf8d17e870..fb338d9df49 100644
--- a/src/blockinput.h
+++ b/src/blockinput.h
@@ -59,6 +59,16 @@ extern int interrupt_input_pending;
59 59
60extern int pending_atimers; 60extern int pending_atimers;
61 61
62#if defined HAVE_NS && !defined COCOA_EXPERIMENTAL_CTRL_G
63/* NS does not use interrupt-driven input processing (yet), so this is
64 unneeded and moreover was causing problems. */
65#define BLOCK_INPUT
66#define UNBLOCK_INPUT
67#define TOTALLY_UNBLOCK_INPUT
68#define UNBLOCK_INPUT_TO(LEVEL)
69
70#else
71
62/* Begin critical section. */ 72/* Begin critical section. */
63#define BLOCK_INPUT (interrupt_input_blocked++) 73#define BLOCK_INPUT (interrupt_input_blocked++)
64 74
@@ -115,6 +125,8 @@ extern int pending_atimers;
115 } \ 125 } \
116 while (0) 126 while (0)
117 127
128#endif /* defined HAVE_NS && !defined COCOA_EXPERIMENTAL_CTRL_G */
129
118#define UNBLOCK_INPUT_RESIGNAL UNBLOCK_INPUT 130#define UNBLOCK_INPUT_RESIGNAL UNBLOCK_INPUT
119 131
120/* In critical section ? */ 132/* In critical section ? */
diff --git a/src/callproc.c b/src/callproc.c
index 746c78243c4..a6de7668c15 100644
--- a/src/callproc.c
+++ b/src/callproc.c
@@ -1587,8 +1587,11 @@ set_initial_environment ()
1587 register char **envp; 1587 register char **envp;
1588#ifndef CANNOT_DUMP 1588#ifndef CANNOT_DUMP
1589 if (initialized) 1589 if (initialized)
1590#endif
1591 { 1590 {
1591#else
1592 {
1593 Vprocess_environment = Qnil;
1594#endif
1592 for (envp = environ; *envp; envp++) 1595 for (envp = environ; *envp; envp++)
1593 Vprocess_environment = Fcons (build_string (*envp), 1596 Vprocess_environment = Fcons (build_string (*envp),
1594 Vprocess_environment); 1597 Vprocess_environment);
diff --git a/src/config.in b/src/config.in
index ae2a24dc46a..714d1d44f80 100644
--- a/src/config.in
+++ b/src/config.in
@@ -30,6 +30,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
30/* Define to 1 if the mktime function is broken. */ 30/* Define to 1 if the mktime function is broken. */
31#undef BROKEN_MKTIME 31#undef BROKEN_MKTIME
32 32
33/* Define to 1 if you are trying experimental enhanced Ctrl-g support using NS
34 windowing under MacOS X. */
35#undef COCOA_EXPERIMENTAL_CTRL_G
36
33/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP 37/* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP
34 systems. This function is required for `alloca.c' support on those systems. 38 systems. This function is required for `alloca.c' support on those systems.
35 */ 39 */
@@ -472,6 +476,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
472/* Define to 1 if you have the <nlist.h> header file. */ 476/* Define to 1 if you have the <nlist.h> header file. */
473#undef HAVE_NLIST_H 477#undef HAVE_NLIST_H
474 478
479/* Define to 1 if you are using the NeXTstep API, either GNUstep or Cocoa on
480 Mac OS X. */
481#undef HAVE_NS
482
475/* Define to 1 if personality LINUX32 can be set. */ 483/* Define to 1 if personality LINUX32 can be set. */
476#undef HAVE_PERSONALITY_LINUX32 484#undef HAVE_PERSONALITY_LINUX32
477 485
@@ -798,6 +806,12 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
798/* Define to 1 if you don't have struct exception in math.h. */ 806/* Define to 1 if you don't have struct exception in math.h. */
799#undef NO_MATHERR 807#undef NO_MATHERR
800 808
809/* Define to 1 if you are using NS windowing under MacOS X. */
810#undef NS_IMPL_COCOA
811
812/* Define to 1 if you are using NS windowing under GNUstep. */
813#undef NS_IMPL_GNUSTEP
814
801/* Define to the address where bug reports for this package should be sent. */ 815/* Define to the address where bug reports for this package should be sent. */
802#undef PACKAGE_BUGREPORT 816#undef PACKAGE_BUGREPORT
803 817
@@ -965,8 +979,8 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
965#undef volatile 979#undef volatile
966 980
967 981
968/* If we're using any sort of window system, define some consequences. */ 982/* If we're using X11/Carbon/GNUstep, define some consequences. */
969#ifdef HAVE_X_WINDOWS 983#if defined HAVE_X_WINDOWS || defined(HAVE_CARBON) || defined(HAVE_NS)
970#define HAVE_WINDOW_SYSTEM 984#define HAVE_WINDOW_SYSTEM
971#define MULTI_KBOARD 985#define MULTI_KBOARD
972#define HAVE_MOUSE 986#define HAVE_MOUSE
@@ -978,13 +992,15 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
978#define MULTI_KBOARD 992#define MULTI_KBOARD
979#endif 993#endif
980 994
981/* If we're using the Carbon API on Mac OS X, define a few more 995/* Sadly for now, GNUstep dump does not work. */
982 variables as well. */ 996#ifdef NS_IMPL_GNUSTEP
983#ifdef HAVE_CARBON 997#define CANNOT_DUMP
984#define HAVE_WINDOW_SYSTEM
985#define HAVE_MOUSE
986#endif 998#endif
987 999
1000/* PENDING: These are used for the Carbon port only. */
1001#undef MAC_OS
1002#undef MAC_OSX
1003
988/* Define USER_FULL_NAME to return a string 1004/* Define USER_FULL_NAME to return a string
989 that is the user's full name. 1005 that is the user's full name.
990 It can assume that the variable `pw' 1006 It can assume that the variable `pw'
@@ -1037,6 +1053,28 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
1037#include config_opsysfile 1053#include config_opsysfile
1038#include config_machfile 1054#include config_machfile
1039 1055
1056/* Set up some defines, C and LD flags for NeXTstep interface on GNUstep.
1057 (There is probably a better place to do this, but right now the Cocoa
1058 side does this in s/darwin.h, following the Carbon port, and we cannot
1059 parallel this exactly since GNUstep is multi-OS. */
1060#ifdef HAVE_NS
1061# ifdef C_SWITCH_SYSTEM
1062# undef C_SWITCH_SYSTEM
1063# endif
1064# ifdef NS_IMPL_GNUSTEP
1065/* See also .m.o rule in Makefile.in */
1066# define C_SWITCH_X_SYSTEM -MMD -MP -D_REENTRANT -fPIC -fno-strict-aliasing
1067# define LD_SWITCH_SITE -lgnustep-gui -lgnustep-base -lobjc $(CONFIG_SYSTEM_LIBS) -lpthread
1068# define GNU_OBJC_CFLAGS -fgnu-runtime -Wno-import -fconstant-string-class=NSConstantString -DGNUSTEP_BASE_LIBRARY=1 -DGNU_GUI_LIBRARY=1 -DGNU_RUNTIME=1 -DGSWARN -DGSDIAGNOSE
1069# define OTHER_FILES ns-app
1070# else /* COCOA */
1071# define C_SWITCH_X_SYSTEM
1072# define GNU_OBJC_CFLAGS
1073# endif /* COCOA */
1074#endif /* HAVE_NS */
1075
1076
1077
1040/* If no remapping takes place, static variables cannot be dumped as 1078/* If no remapping takes place, static variables cannot be dumped as
1041 pure, so don't worry about the `static' keyword. */ 1079 pure, so don't worry about the `static' keyword. */
1042#ifdef NO_REMAP 1080#ifdef NO_REMAP
diff --git a/src/dispextern.h b/src/dispextern.h
index e6064476d0c..180820d4b80 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -69,6 +69,14 @@ typedef Pixmap XImagePtr;
69typedef XImagePtr XImagePtr_or_DC; 69typedef XImagePtr XImagePtr_or_DC;
70#endif 70#endif
71 71
72#ifdef HAVE_NS
73#include "nsgui.h"
74/* following typedef needed to accomodate the MSDOS port, believe it or not */
75typedef struct ns_display_info Display_Info;
76typedef Pixmap XImagePtr;
77typedef XImagePtr XImagePtr_or_DC;
78#endif
79
72#ifndef NativeRectangle 80#ifndef NativeRectangle
73#define NativeRectangle int 81#define NativeRectangle int
74#endif 82#endif
@@ -1563,6 +1571,13 @@ struct face
1563 /* If non-zero, use overstrike (to simulate bold-face). */ 1571 /* If non-zero, use overstrike (to simulate bold-face). */
1564 unsigned overstrike : 1; 1572 unsigned overstrike : 1;
1565 1573
1574/* NOTE: this is not used yet, but eventually this impl should be done
1575 similarly to overstrike */
1576#ifdef HAVE_NS
1577 /* If non-zero, use geometric rotation (to simulate italic). */
1578 unsigned synth_ital : 1;
1579#endif
1580
1566 /* Next and previous face in hash collision list of face cache. */ 1581 /* Next and previous face in hash collision list of face cache. */
1567 struct face *next, *prev; 1582 struct face *next, *prev;
1568 1583
diff --git a/src/dispnew.c b/src/dispnew.c
index f182af77d3b..d95ce7c39e7 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -63,6 +63,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
63#include "macterm.h" 63#include "macterm.h"
64#endif /* MAC_OS */ 64#endif /* MAC_OS */
65 65
66#ifdef HAVE_NS
67#include "nsterm.h"
68#endif
69
66/* Include systime.h after xterm.h to avoid double inclusion of time.h. */ 70/* Include systime.h after xterm.h to avoid double inclusion of time.h. */
67 71
68#include "systime.h" 72#include "systime.h"
@@ -6895,6 +6899,20 @@ init_display ()
6895 } 6899 }
6896#endif /* MAC_OS */ 6900#endif /* MAC_OS */
6897 6901
6902#ifdef HAVE_NS
6903 if (!inhibit_window_system
6904#ifndef CANNOT_DUMP
6905 && initialized
6906#endif
6907 )
6908 {
6909 Vinitial_window_system = intern("ns");
6910 Vwindow_system_version = make_number(10);
6911 adjust_frame_glyphs_initially ();
6912 return;
6913 }
6914#endif
6915
6898 /* If no window system has been specified, try to use the terminal. */ 6916 /* If no window system has been specified, try to use the terminal. */
6899 if (! isatty (0)) 6917 if (! isatty (0))
6900 { 6918 {
diff --git a/src/emacs.c b/src/emacs.c
index 8dfdf9062a1..a6e59f8c9fe 100644
--- a/src/emacs.c
+++ b/src/emacs.c
@@ -46,6 +46,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
46#include "w32heap.h" /* for prototype of sbrk */ 46#include "w32heap.h" /* for prototype of sbrk */
47#endif 47#endif
48 48
49#ifdef NS_IMPL_GNUSTEP
50/* At least under Debian, GSConfig is in a subdirectory. --Stef */
51#include <GNUstepBase/GSConfig.h>
52#endif
53
49#include "lisp.h" 54#include "lisp.h"
50#include "commands.h" 55#include "commands.h"
51#include "intervals.h" 56#include "intervals.h"
@@ -193,7 +198,7 @@ int running_asynch_code;
193extern int inherited_pgroup; 198extern int inherited_pgroup;
194#endif 199#endif
195 200
196#ifdef HAVE_X_WINDOWS 201#if defined(HAVE_X_WINDOWS) || defined(HAVE_NS)
197/* If non-zero, -d was specified, meaning we're using some window system. */ 202/* If non-zero, -d was specified, meaning we're using some window system. */
198int display_arg; 203int display_arg;
199#endif 204#endif
@@ -838,7 +843,7 @@ main (argc, argv
838 run_time_remap (argv[0]); 843 run_time_remap (argv[0]);
839#endif 844#endif
840 845
841#ifdef MAC_OSX 846#if defined (MAC_OSX) || defined (NS_IMPL_COCOA)
842 if (!initialized) 847 if (!initialized)
843 unexec_init_emacs_zone (); 848 unexec_init_emacs_zone ();
844#endif 849#endif
@@ -1410,6 +1415,38 @@ main (argc, argv
1410 no_loadup 1415 no_loadup
1411 = argmatch (argv, argc, "-nl", "--no-loadup", 6, NULL, &skip_args); 1416 = argmatch (argv, argc, "-nl", "--no-loadup", 6, NULL, &skip_args);
1412 1417
1418#ifdef HAVE_NS
1419 ns_alloc_autorelease_pool();
1420 if (!noninteractive)
1421 {
1422 char *tmp;
1423 display_arg = 4;
1424#ifdef NS_IMPL_COCOA
1425 if (skip_args < argc)
1426 {
1427 if (!strncmp(argv[skip_args], "-psn", 4))
1428 {
1429 skip_args += 1;
1430 }
1431 else
1432 {
1433 if (skip_args+1 < argc && !strncmp(argv[skip_args+1], "-psn", 4))
1434 skip_args += 2;
1435 }
1436 }
1437#endif
1438 /* This used for remote operation.. not fully implemented yet. */
1439 if (argmatch (argv, argc, "-_NSMachLaunch", 0, 3, &tmp, &skip_args))
1440 display_arg = 4;
1441 else if (argmatch (argv, argc, "-MachLaunch", 0, 3, &tmp, &skip_args))
1442 display_arg = 4;
1443 else if (argmatch (argv, argc, "-macosx", 0, 2, NULL, &skip_args))
1444 display_arg = 4;
1445 else if (argmatch (argv, argc, "-NSHost", 0, 3, &tmp, &skip_args))
1446 display_arg = 4;
1447 }
1448#endif /* HAVE_NS */
1449
1413#ifdef HAVE_X_WINDOWS 1450#ifdef HAVE_X_WINDOWS
1414 /* Stupid kludge to catch command-line display spec. We can't 1451 /* Stupid kludge to catch command-line display spec. We can't
1415 handle this argument entirely in window system dependent code 1452 handle this argument entirely in window system dependent code
@@ -1487,6 +1524,13 @@ main (argc, argv
1487 init_mac_osx_environment (); 1524 init_mac_osx_environment ();
1488#endif 1525#endif
1489 1526
1527#ifdef HAVE_NS
1528#ifndef CANNOT_DUMP
1529 if (initialized)
1530#endif
1531 ns_init_paths ();
1532#endif
1533
1490 /* egetenv is a pretty low-level facility, which may get called in 1534 /* egetenv is a pretty low-level facility, which may get called in
1491 many circumstances; it seems flimsy to put off initializing it 1535 many circumstances; it seems flimsy to put off initializing it
1492 until calling init_callproc. */ 1536 until calling init_callproc. */
@@ -1588,6 +1632,7 @@ main (argc, argv
1588#ifdef HAVE_X_WINDOWS 1632#ifdef HAVE_X_WINDOWS
1589 syms_of_xterm (); 1633 syms_of_xterm ();
1590 syms_of_xfns (); 1634 syms_of_xfns ();
1635 syms_of_xmenu ();
1591 syms_of_fontset (); 1636 syms_of_fontset ();
1592#ifdef HAVE_X_SM 1637#ifdef HAVE_X_SM
1593 syms_of_xsmfns (); 1638 syms_of_xsmfns ();
@@ -1599,13 +1644,6 @@ main (argc, argv
1599 1644
1600 syms_of_menu (); 1645 syms_of_menu ();
1601 1646
1602#ifndef HAVE_NTGUI
1603#ifndef MAC_OS
1604 /* Called before init_window_once for Mac OS Classic. */
1605 syms_of_xmenu ();
1606#endif
1607#endif
1608
1609#ifdef HAVE_NTGUI 1647#ifdef HAVE_NTGUI
1610 syms_of_w32term (); 1648 syms_of_w32term ();
1611 syms_of_w32fns (); 1649 syms_of_w32fns ();
@@ -1622,6 +1660,14 @@ main (argc, argv
1622 syms_of_fontset (); 1660 syms_of_fontset ();
1623#endif /* MAC_OSX && HAVE_CARBON */ 1661#endif /* MAC_OSX && HAVE_CARBON */
1624 1662
1663#ifdef HAVE_NS
1664 syms_of_nsterm ();
1665 syms_of_nsfns ();
1666 syms_of_nsmenu ();
1667 syms_of_nsselect ();
1668 syms_of_fontset ();
1669#endif /* HAVE_NS */
1670
1625#ifdef HAVE_DBUS 1671#ifdef HAVE_DBUS
1626 syms_of_dbusbind (); 1672 syms_of_dbusbind ();
1627#endif /* HAVE_DBUS */ 1673#endif /* HAVE_DBUS */
@@ -1843,6 +1889,15 @@ struct standard_args standard_args[] =
1843 { "-color", "--color", 5, 0}, 1889 { "-color", "--color", 5, 0},
1844 { "-no-splash", "--no-splash", 3, 0 }, 1890 { "-no-splash", "--no-splash", 3, 0 },
1845 { "-no-desktop", "--no-desktop", 3, 0 }, 1891 { "-no-desktop", "--no-desktop", 3, 0 },
1892#ifdef HAVE_NS
1893 { "-NSAutoLaunch", 0, 5, 1 },
1894 { "-NXAutoLaunch", 0, 5, 1 },
1895 { "-disable-font-backend", "--disable-font-backend", 65, 0 },
1896 { "-_NSMachLaunch", 0, 85, 1 },
1897 { "-MachLaunch", 0, 85, 1 },
1898 { "-macosx", 0, 85, 0 },
1899 { "-NSHost", 0, 85, 1 },
1900#endif
1846 /* These have the same priority as ordinary file name args, 1901 /* These have the same priority as ordinary file name args,
1847 so they are not reordered with respect to those. */ 1902 so they are not reordered with respect to those. */
1848 { "-L", "--directory", 0, 1 }, 1903 { "-L", "--directory", 0, 1 },
@@ -1862,6 +1917,13 @@ struct standard_args standard_args[] =
1862 { "-visit", "--visit", 0, 1 }, 1917 { "-visit", "--visit", 0, 1 },
1863 { "-file", "--file", 0, 1 }, 1918 { "-file", "--file", 0, 1 },
1864 { "-insert", "--insert", 0, 1 }, 1919 { "-insert", "--insert", 0, 1 },
1920#ifdef HAVE_NS
1921 { "-NXOpen", 0, 0, 1 },
1922 { "-NXOpenTemp", 0, 0, 1 },
1923 { "-NSOpen", 0, 0, 1 },
1924 { "-NSOpenTemp", 0, 0, 1 },
1925 { "-GSFilePath", 0, 0, 1 },
1926#endif
1865 /* This should be processed after ordinary file name args and the like. */ 1927 /* This should be processed after ordinary file name args and the like. */
1866 { "-kill", "--kill", -10, 0 }, 1928 { "-kill", "--kill", -10, 0 },
1867}; 1929};
@@ -2158,6 +2220,10 @@ shut_down_emacs (sig, no_x, stuff)
2158#ifdef MSDOS 2220#ifdef MSDOS
2159 dos_cleanup (); 2221 dos_cleanup ();
2160#endif 2222#endif
2223
2224#ifdef HAVE_NS
2225 ns_term_shutdown (sig);
2226#endif
2161} 2227}
2162 2228
2163 2229
diff --git a/src/font.c b/src/font.c
index 91bb84239ae..26adda26e47 100644
--- a/src/font.c
+++ b/src/font.c
@@ -46,6 +46,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
46#include "w32term.h" 46#include "w32term.h"
47#endif /* HAVE_NTGUI */ 47#endif /* HAVE_NTGUI */
48 48
49#ifdef HAVE_NS
50#include "nsterm.h"
51#endif /* HAVE_NS */
52
49#ifdef MAC_OS 53#ifdef MAC_OS
50#include "macterm.h" 54#include "macterm.h"
51#endif /* MAC_OS */ 55#endif /* MAC_OS */
@@ -57,6 +61,12 @@ Lisp_Object Qopentype;
57/* Important character set strings. */ 61/* Important character set strings. */
58Lisp_Object Qascii_0, Qiso8859_1, Qiso10646_1, Qunicode_bmp, Qunicode_sip; 62Lisp_Object Qascii_0, Qiso8859_1, Qiso10646_1, Qunicode_bmp, Qunicode_sip;
59 63
64#ifdef HAVE_NS
65#define DEFAULT_ENCODING Qiso10646_1
66#else
67#define DEFAULT_ENCODING Qiso8859_1
68#endif
69
60/* Special vector of zero length. This is repeatedly used by (struct 70/* Special vector of zero length. This is repeatedly used by (struct
61 font_driver *)->list when a specified font is not found. */ 71 font_driver *)->list when a specified font is not found. */
62static Lisp_Object null_vector; 72static Lisp_Object null_vector;
@@ -3096,7 +3106,7 @@ font_find_for_lface (f, attrs, spec, c)
3096 registry[0] = AREF (spec, FONT_REGISTRY_INDEX); 3106 registry[0] = AREF (spec, FONT_REGISTRY_INDEX);
3097 if (NILP (registry[0])) 3107 if (NILP (registry[0]))
3098 { 3108 {
3099 registry[0] = Qiso8859_1; 3109 registry[0] = DEFAULT_ENCODING;
3100 registry[1] = Qascii_0; 3110 registry[1] = Qascii_0;
3101 registry[2] = null_vector; 3111 registry[2] = null_vector;
3102 } 3112 }
@@ -4948,6 +4958,7 @@ extern void syms_of_ftxfont P_ (());
4948extern void syms_of_bdffont P_ (()); 4958extern void syms_of_bdffont P_ (());
4949extern void syms_of_w32font P_ (()); 4959extern void syms_of_w32font P_ (());
4950extern void syms_of_atmfont P_ (()); 4960extern void syms_of_atmfont P_ (());
4961extern void syms_of_nsfont P_ (());
4951 4962
4952void 4963void
4953syms_of_font () 4964syms_of_font ()
@@ -5117,6 +5128,9 @@ EMACS_FONT_LOG is set. Otherwise, it is set to t. */);
5117#ifdef WINDOWSNT 5128#ifdef WINDOWSNT
5118 syms_of_w32font (); 5129 syms_of_w32font ();
5119#endif /* WINDOWSNT */ 5130#endif /* WINDOWSNT */
5131#ifdef HAVE_NS
5132 syms_of_nsfont ();
5133#endif /* HAVE_NS */
5120#ifdef MAC_OS 5134#ifdef MAC_OS
5121 syms_of_atmfont (); 5135 syms_of_atmfont ();
5122#endif /* MAC_OS */ 5136#endif /* MAC_OS */
diff --git a/src/font.h b/src/font.h
index c70e87deabc..a6360e1432e 100644
--- a/src/font.h
+++ b/src/font.h
@@ -860,6 +860,9 @@ extern struct font_driver uniscribe_font_driver;
860#ifdef MAC_OS 860#ifdef MAC_OS
861extern struct font_driver atmfont_driver; 861extern struct font_driver atmfont_driver;
862#endif /* MAC_OS */ 862#endif /* MAC_OS */
863#ifdef HAVE_NS
864extern struct font_driver nsfont_driver;
865#endif /* HAVE_NS */
863 866
864#ifndef FONT_DEBUG 867#ifndef FONT_DEBUG
865#define FONT_DEBUG 868#define FONT_DEBUG
diff --git a/src/fontset.c b/src/fontset.c
index e4448537458..edcbaa63070 100644
--- a/src/fontset.c
+++ b/src/fontset.c
@@ -47,6 +47,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
47#ifdef WINDOWSNT 47#ifdef WINDOWSNT
48#include "w32term.h" 48#include "w32term.h"
49#endif 49#endif
50#ifdef HAVE_NS
51#include "nsterm.h"
52#endif
50#ifdef MAC_OS 53#ifdef MAC_OS
51#include "macterm.h" 54#include "macterm.h"
52#endif 55#endif
@@ -1622,6 +1625,11 @@ fontset_from_font (font_object)
1622 ASET (font_spec, i, Qnil); 1625 ASET (font_spec, i, Qnil);
1623 Fset_fontset_font (name, Qlatin, font_spec, Qnil, Qnil); 1626 Fset_fontset_font (name, Qlatin, font_spec, Qnil, Qnil);
1624 Fset_fontset_font (name, Qnil, font_spec, Qnil, Qnil); 1627 Fset_fontset_font (name, Qnil, font_spec, Qnil, Qnil);
1628
1629#ifdef HAVE_NS
1630 nsfont_make_fontset_for_font(name, font_object);
1631#endif
1632
1625 return XINT (FONTSET_ID (fontset)); 1633 return XINT (FONTSET_ID (fontset));
1626} 1634}
1627 1635
diff --git a/src/frame.c b/src/frame.c
index a4fa29bff49..617d9233889 100644
--- a/src/frame.c
+++ b/src/frame.c
@@ -32,6 +32,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
32#ifdef MAC_OS 32#ifdef MAC_OS
33#include "macterm.h" 33#include "macterm.h"
34#endif 34#endif
35#ifdef HAVE_NS
36#include "nsterm.h"
37#endif
35#include "buffer.h" 38#include "buffer.h"
36/* These help us bind and responding to switch-frame events. */ 39/* These help us bind and responding to switch-frame events. */
37#include "commands.h" 40#include "commands.h"
@@ -72,7 +75,7 @@ Lisp_Object Vframe_alpha_lower_limit;
72Lisp_Object Qframep, Qframe_live_p; 75Lisp_Object Qframep, Qframe_live_p;
73Lisp_Object Qicon, Qmodeline; 76Lisp_Object Qicon, Qmodeline;
74Lisp_Object Qonly; 77Lisp_Object Qonly;
75Lisp_Object Qx, Qw32, Qmac, Qpc; 78Lisp_Object Qx, Qw32, Qmac, Qpc, Qns;
76Lisp_Object Qvisible; 79Lisp_Object Qvisible;
77Lisp_Object Qdisplay_type; 80Lisp_Object Qdisplay_type;
78Lisp_Object Qbackground_mode; 81Lisp_Object Qbackground_mode;
@@ -203,7 +206,8 @@ DEFUN ("framep", Fframep, Sframep, 1, 1, 0,
203Value is t for a termcap frame (a character-only terminal), 206Value is t for a termcap frame (a character-only terminal),
204`x' for an Emacs frame that is really an X window, 207`x' for an Emacs frame that is really an X window,
205`w32' for an Emacs frame that is a window on MS-Windows display, 208`w32' for an Emacs frame that is a window on MS-Windows display,
206`mac' for an Emacs frame on a Macintosh display, 209`mac' for an Emacs frame on a Macintosh 8/9 X-Carbon display,
210`ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
207`pc' for a direct-write MS-DOS frame. 211`pc' for a direct-write MS-DOS frame.
208See also `frame-live-p'. */) 212See also `frame-live-p'. */)
209 (object) 213 (object)
@@ -224,6 +228,8 @@ See also `frame-live-p'. */)
224 return Qpc; 228 return Qpc;
225 case output_mac: 229 case output_mac:
226 return Qmac; 230 return Qmac;
231 case output_ns:
232 return Qns;
227 default: 233 default:
228 abort (); 234 abort ();
229 } 235 }
@@ -551,6 +557,11 @@ make_initial_frame (void)
551 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0; 557 FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
552 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none; 558 FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
553 559
560#ifdef CANNOT_DUMP
561 if (!noninteractive)
562 init_frame_faces (f);
563#endif
564
554 return f; 565 return f;
555} 566}
556 567
@@ -880,6 +891,12 @@ do_switch_frame (frame, track, for_deletion)
880 891
881 Fselect_window (XFRAME (frame)->selected_window, Qnil); 892 Fselect_window (XFRAME (frame)->selected_window, Qnil);
882 893
894#ifdef NS_IMPL_COCOA
895 /* term gets no other notification of this */
896 if (for_deletion)
897 Fraise_frame(Qnil);
898#endif
899
883 /* We want to make sure that the next event generates a frame-switch 900 /* We want to make sure that the next event generates a frame-switch
884 event to the appropriate frame. This seems kludgy to me, but 901 event to the appropriate frame. This seems kludgy to me, but
885 before you take it out, make sure that evaluating something like 902 before you take it out, make sure that evaluating something like
@@ -2969,8 +2986,9 @@ x_set_frame_parameters (f, alist)
2969 2986
2970 old_value = get_frame_param (f, prop); 2987 old_value = get_frame_param (f, prop);
2971 fullscreen_is_being_set |= EQ (prop, Qfullscreen); 2988 fullscreen_is_being_set |= EQ (prop, Qfullscreen);
2972 2989#ifndef HAVE_NS /* PENDING: ensure font attrs change goes through */
2973 if (NILP (Fequal (val, old_value))) 2990 if (NILP (Fequal (val, old_value)))
2991#endif
2974 { 2992 {
2975 store_frame_param (f, prop, val); 2993 store_frame_param (f, prop, val);
2976 2994
@@ -3949,6 +3967,9 @@ x_get_arg (dpyinfo, alist, param, attribute, class, type)
3949 case RES_TYPE_BOOLEAN: 3967 case RES_TYPE_BOOLEAN:
3950 tem = Fdowncase (tem); 3968 tem = Fdowncase (tem);
3951 if (!strcmp (SDATA (tem), "on") 3969 if (!strcmp (SDATA (tem), "on")
3970#ifdef HAVE_NS
3971 || !strcmp(SDATA(tem), "yes")
3972#endif
3952 || !strcmp (SDATA (tem), "true")) 3973 || !strcmp (SDATA (tem), "true"))
3953 return Qt; 3974 return Qt;
3954 else 3975 else
@@ -3964,9 +3985,15 @@ x_get_arg (dpyinfo, alist, param, attribute, class, type)
3964 Lisp_Object lower; 3985 Lisp_Object lower;
3965 lower = Fdowncase (tem); 3986 lower = Fdowncase (tem);
3966 if (!strcmp (SDATA (lower), "on") 3987 if (!strcmp (SDATA (lower), "on")
3988#ifdef HAVE_NS
3989 || !strcmp(SDATA(lower), "yes")
3990#endif
3967 || !strcmp (SDATA (lower), "true")) 3991 || !strcmp (SDATA (lower), "true"))
3968 return Qt; 3992 return Qt;
3969 else if (!strcmp (SDATA (lower), "off") 3993 else if (!strcmp (SDATA (lower), "off")
3994#ifdef HAVE_NS
3995 || !strcmp(SDATA(lower), "no")
3996#endif
3970 || !strcmp (SDATA (lower), "false")) 3997 || !strcmp (SDATA (lower), "false"))
3971 return Qnil; 3998 return Qnil;
3972 else 3999 else
@@ -4366,6 +4393,8 @@ syms_of_frame ()
4366 staticpro (&Qpc); 4393 staticpro (&Qpc);
4367 Qmac = intern ("mac"); 4394 Qmac = intern ("mac");
4368 staticpro (&Qmac); 4395 staticpro (&Qmac);
4396 Qns = intern ("ns");
4397 staticpro (&Qns);
4369 Qvisible = intern ("visible"); 4398 Qvisible = intern ("visible");
4370 staticpro (&Qvisible); 4399 staticpro (&Qvisible);
4371 Qbuffer_predicate = intern ("buffer-predicate"); 4400 Qbuffer_predicate = intern ("buffer-predicate");
@@ -4473,8 +4502,8 @@ Setting this variable does not affect existing frames, only new ones. */);
4473 DEFVAR_LISP ("default-frame-scroll-bars", &Vdefault_frame_scroll_bars, 4502 DEFVAR_LISP ("default-frame-scroll-bars", &Vdefault_frame_scroll_bars,
4474 doc: /* Default position of scroll bars on this window-system. */); 4503 doc: /* Default position of scroll bars on this window-system. */);
4475#ifdef HAVE_WINDOW_SYSTEM 4504#ifdef HAVE_WINDOW_SYSTEM
4476#if defined(HAVE_NTGUI) || defined(MAC_OS) 4505#if defined(HAVE_NTGUI) || defined(MAC_OS) || defined(NS_IMPL_COCOA)
4477 /* MS-Windows has scroll bars on the right by default. */ 4506 /* MS-Windows and Mac OS X have scroll bars on the right by default. */
4478 Vdefault_frame_scroll_bars = Qright; 4507 Vdefault_frame_scroll_bars = Qright;
4479#else 4508#else
4480 Vdefault_frame_scroll_bars = Qleft; 4509 Vdefault_frame_scroll_bars = Qleft;
@@ -4540,7 +4569,7 @@ You should set this variable to tell Emacs how your window manager
4540handles focus, since there is no way in general for Emacs to find out 4569handles focus, since there is no way in general for Emacs to find out
4541automatically. */); 4570automatically. */);
4542#ifdef HAVE_WINDOW_SYSTEM 4571#ifdef HAVE_WINDOW_SYSTEM
4543#if defined(HAVE_NTGUI) || defined(MAC_OS) 4572#if defined(HAVE_NTGUI) || defined(MAC_OS) || defined(HAVE_NS)
4544 focus_follows_mouse = 0; 4573 focus_follows_mouse = 0;
4545#else 4574#else
4546 focus_follows_mouse = 1; 4575 focus_follows_mouse = 1;
diff --git a/src/frame.h b/src/frame.h
index 941b9a90a26..b744c9e56b6 100644
--- a/src/frame.h
+++ b/src/frame.h
@@ -50,7 +50,8 @@ enum output_method
50 output_x_window, 50 output_x_window,
51 output_msdos_raw, 51 output_msdos_raw,
52 output_w32, 52 output_w32,
53 output_mac 53 output_mac,
54 output_ns
54}; 55};
55 56
56enum vertical_scroll_bar_type 57enum vertical_scroll_bar_type
@@ -242,7 +243,7 @@ struct frame
242 auto-resize-tool-bar is set to grow-only. */ 243 auto-resize-tool-bar is set to grow-only. */
243 unsigned minimize_tool_bar_window_p : 1; 244 unsigned minimize_tool_bar_window_p : 1;
244 245
245#if defined (USE_GTK) || defined (MAC_OS) 246#if defined (USE_GTK) || defined (HAVE_NS) || defined (MAC_OS)
246 /* Nonzero means using a tool bar that comes from the toolkit. */ 247 /* Nonzero means using a tool bar that comes from the toolkit. */
247 int external_tool_bar; 248 int external_tool_bar;
248#endif 249#endif
@@ -332,6 +333,7 @@ struct frame
332 struct x_output *x; /* xterm.h */ 333 struct x_output *x; /* xterm.h */
333 struct w32_output *w32; /* w32term.h */ 334 struct w32_output *w32; /* w32term.h */
334 struct mac_output *mac; /* macterm.h */ 335 struct mac_output *mac; /* macterm.h */
336 struct ns_output *ns; /* nsterm.h */
335 EMACS_INT nothing; 337 EMACS_INT nothing;
336 } 338 }
337 output_data; 339 output_data;
@@ -359,7 +361,7 @@ struct frame
359 int menu_bar_lines; 361 int menu_bar_lines;
360 362
361#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ 363#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
362 || defined (USE_GTK) 364 || defined (HAVE_NS) || defined (USE_GTK)
363 /* Nonzero means using a menu bar that comes from the X toolkit. */ 365 /* Nonzero means using a menu bar that comes from the X toolkit. */
364 unsigned int external_menu_bar : 1; 366 unsigned int external_menu_bar : 1;
365#endif 367#endif
@@ -519,6 +521,7 @@ typedef struct frame *FRAME_PTR;
519#define FRAME_W32_P(f) ((f)->output_method == output_w32) 521#define FRAME_W32_P(f) ((f)->output_method == output_w32)
520#define FRAME_MSDOS_P(f) ((f)->output_method == output_msdos_raw) 522#define FRAME_MSDOS_P(f) ((f)->output_method == output_msdos_raw)
521#define FRAME_MAC_P(f) ((f)->output_method == output_mac) 523#define FRAME_MAC_P(f) ((f)->output_method == output_mac)
524#define FRAME_NS_P(f) ((f)->output_method == output_ns)
522 525
523/* FRAME_WINDOW_P tests whether the frame is a window, and is 526/* FRAME_WINDOW_P tests whether the frame is a window, and is
524 defined to be the predicate for the window system being used. */ 527 defined to be the predicate for the window system being used. */
@@ -532,6 +535,9 @@ typedef struct frame *FRAME_PTR;
532#ifdef MAC_OS 535#ifdef MAC_OS
533#define FRAME_WINDOW_P(f) FRAME_MAC_P (f) 536#define FRAME_WINDOW_P(f) FRAME_MAC_P (f)
534#endif 537#endif
538#ifdef HAVE_NS
539#define FRAME_WINDOW_P(f) FRAME_NS_P(f)
540#endif
535#ifndef FRAME_WINDOW_P 541#ifndef FRAME_WINDOW_P
536#define FRAME_WINDOW_P(f) (0) 542#define FRAME_WINDOW_P(f) (0)
537#endif 543#endif
@@ -570,7 +576,7 @@ typedef struct frame *FRAME_PTR;
570 576
571/* Nonzero if this frame should display a tool bar 577/* Nonzero if this frame should display a tool bar
572 in a way that does not use any text lines. */ 578 in a way that does not use any text lines. */
573#if defined (USE_GTK) || defined (MAC_OS) 579#if defined (USE_GTK) || defined (HAVE_NS) || defined (MAC_OS)
574#define FRAME_EXTERNAL_TOOL_BAR(f) (f)->external_tool_bar 580#define FRAME_EXTERNAL_TOOL_BAR(f) (f)->external_tool_bar
575#else 581#else
576#define FRAME_EXTERNAL_TOOL_BAR(f) 0 582#define FRAME_EXTERNAL_TOOL_BAR(f) 0
@@ -589,7 +595,7 @@ typedef struct frame *FRAME_PTR;
589/* Nonzero if this frame should display a menu bar 595/* Nonzero if this frame should display a menu bar
590 in a way that does not use any text lines. */ 596 in a way that does not use any text lines. */
591#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ 597#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
592 || defined (USE_GTK) 598 || defined (HAVE_NS) || defined (USE_GTK)
593#define FRAME_EXTERNAL_MENU_BAR(f) (f)->external_menu_bar 599#define FRAME_EXTERNAL_MENU_BAR(f) (f)->external_menu_bar
594#else 600#else
595#define FRAME_EXTERNAL_MENU_BAR(f) 0 601#define FRAME_EXTERNAL_MENU_BAR(f) 0
@@ -1044,7 +1050,7 @@ extern Lisp_Object Qleft_fringe, Qright_fringe;
1044extern Lisp_Object Qheight, Qwidth; 1050extern Lisp_Object Qheight, Qwidth;
1045extern Lisp_Object Qminibuffer, Qmodeline; 1051extern Lisp_Object Qminibuffer, Qmodeline;
1046extern Lisp_Object Qonly; 1052extern Lisp_Object Qonly;
1047extern Lisp_Object Qx, Qw32, Qmac, Qpc; 1053extern Lisp_Object Qx, Qw32, Qmac, Qpc, Qns;
1048extern Lisp_Object Qvisible; 1054extern Lisp_Object Qvisible;
1049extern Lisp_Object Qdisplay_type; 1055extern Lisp_Object Qdisplay_type;
1050extern Lisp_Object Qbackground_mode; 1056extern Lisp_Object Qbackground_mode;
diff --git a/src/fringe.c b/src/fringe.c
index 57a1861446b..ad40df5a2fd 100644
--- a/src/fringe.c
+++ b/src/fringe.c
@@ -482,7 +482,7 @@ static struct fringe_bitmap **fringe_bitmaps;
482static Lisp_Object *fringe_faces; 482static Lisp_Object *fringe_faces;
483static int max_fringe_bitmaps; 483static int max_fringe_bitmaps;
484 484
485static int max_used_fringe_bitmap = MAX_STANDARD_FRINGE_BITMAPS; 485int max_used_fringe_bitmap = MAX_STANDARD_FRINGE_BITMAPS;
486 486
487 487
488/* Lookup bitmap number for symbol BITMAP. 488/* Lookup bitmap number for symbol BITMAP.
diff --git a/src/getloadavg.c b/src/getloadavg.c
index 32d0f41a4a9..c5d78907d82 100644
--- a/src/getloadavg.c
+++ b/src/getloadavg.c
@@ -420,7 +420,7 @@ extern int errno;
420# define host_self mach_host_self 420# define host_self mach_host_self
421# endif 421# endif
422 422
423# ifdef NeXT 423# if defined(NeXT) || defined(RHAPSODY) || defined(DARWIN) || defined(MAC_OSX)
424# ifdef HAVE_MACH_MACH_H 424# ifdef HAVE_MACH_MACH_H
425# include <mach/mach.h> 425# include <mach/mach.h>
426# else 426# else
@@ -467,7 +467,7 @@ extern int errno;
467 467
468/* Avoid static vars inside a function since in HPUX they dump as pure. */ 468/* Avoid static vars inside a function since in HPUX they dump as pure. */
469 469
470# ifdef NeXT 470# if defined(NeXT) || defined(RHAPSODY) || defined(DARWIN) || defined(MAC_OSX)
471static processor_set_t default_set; 471static processor_set_t default_set;
472static int getloadavg_initialized; 472static int getloadavg_initialized;
473# endif /* NeXT */ 473# endif /* NeXT */
@@ -647,7 +647,8 @@ getloadavg (loadavg, nelem)
647 647
648# endif /* __NetBSD__ */ 648# endif /* __NetBSD__ */
649 649
650# if !defined (LDAV_DONE) && defined (NeXT) 650# if !defined (LDAV_DONE) && ( defined (NeXT) || defined(RHAPSODY) \
651 || defined(DARWIN) || defined(MAC_OSX) )
651# define LDAV_DONE 652# define LDAV_DONE
652 /* The NeXT code was adapted from iscreen 3.2. */ 653 /* The NeXT code was adapted from iscreen 3.2. */
653 654
diff --git a/src/image.c b/src/image.c
index 652c738d109..1d73704b388 100644
--- a/src/image.c
+++ b/src/image.c
@@ -131,6 +131,32 @@ typedef struct mac_bitmap_record Bitmap_Record;
131#endif /* MAC_OS */ 131#endif /* MAC_OS */
132 132
133 133
134#ifdef HAVE_NS
135#include "nsterm.h"
136#include <sys/types.h>
137#include <sys/stat.h>
138
139#undef COLOR_TABLE_SUPPORT
140
141typedef struct ns_bitmap_record Bitmap_Record;
142
143#define GET_PIXEL(ximg, x, y) XGetPixel(ximg, x, y)
144#define NO_PIXMAP 0
145
146#define RGB_PIXEL_COLOR unsigned long
147#define ZPixmap 0
148
149#define PIX_MASK_RETAIN 0
150#define PIX_MASK_DRAW 1
151
152#define FRAME_X_VISUAL FRAME_NS_DISPLAY_INFO(f)->visual
153#define x_defined_color(f, name, color_def, alloc) \
154 ns_defined_color (f, name, color_def, alloc, 0)
155#define FRAME_X_SCREEN(f) 0
156#define DefaultDepthOfScreen(screen) ns_display_list->n_planes
157#endif /* HAVE_NS */
158
159
134/* Search path for bitmap files. */ 160/* Search path for bitmap files. */
135 161
136Lisp_Object Vx_bitmap_file_path; 162Lisp_Object Vx_bitmap_file_path;
@@ -403,6 +429,33 @@ mac_create_cg_image_from_image (f, img)
403#endif /* USE_CG_DRAWING */ 429#endif /* USE_CG_DRAWING */
404#endif /* MAC_OS */ 430#endif /* MAC_OS */
405 431
432#ifdef HAVE_NS
433XImagePtr
434XGetImage (Display *display, Pixmap pixmap, int x, int y,
435 unsigned int width, unsigned int height,
436 unsigned long plane_mask, int format)
437{
438 /* PENDING: not sure what this function is supposed to do.. */
439 ns_retain_object(pixmap);
440 return pixmap;
441}
442
443/* use with imgs created by ns_image_for_XPM */
444unsigned long
445XGetPixel (XImagePtr ximage, int x, int y)
446{
447 return ns_get_pixel(ximage, x, y);
448}
449
450/* use with imgs created by ns_image_for_XPM; alpha set to 1;
451 pixel is assumed to be in form RGB */
452void
453XPutPixel (XImagePtr ximage, int x, int y, unsigned long pixel)
454{
455 ns_put_pixel(ximage, x, y, pixel);
456}
457#endif /* HAVE_NS */
458
406 459
407/* Functions to access the contents of a bitmap, given an id. */ 460/* Functions to access the contents of a bitmap, given an id. */
408 461
@@ -519,12 +572,23 @@ x_create_bitmap_from_data (f, bits, width, height)
519 return -1; 572 return -1;
520#endif 573#endif
521 574
575#ifdef HAVE_NS
576 void *bitmap = ns_image_from_XBM(bits, width, height);
577 if (!bitmap)
578 return -1;
579#endif
580
522 id = x_allocate_bitmap_record (f); 581 id = x_allocate_bitmap_record (f);
523#ifdef MAC_OS 582#ifdef MAC_OS
524 dpyinfo->bitmaps[id - 1].bitmap_data = (char *) xmalloc (height * width); 583 dpyinfo->bitmaps[id - 1].bitmap_data = (char *) xmalloc (height * width);
525 bcopy (bits, dpyinfo->bitmaps[id - 1].bitmap_data, height * width); 584 bcopy (bits, dpyinfo->bitmaps[id - 1].bitmap_data, height * width);
526#endif /* MAC_OS */ 585#endif /* MAC_OS */
527 586
587#ifdef HAVE_NS
588 dpyinfo->bitmaps[id - 1].img = bitmap;
589 dpyinfo->bitmaps[id - 1].depth = 1;
590#endif
591
528 dpyinfo->bitmaps[id - 1].file = NULL; 592 dpyinfo->bitmaps[id - 1].file = NULL;
529 dpyinfo->bitmaps[id - 1].height = height; 593 dpyinfo->bitmaps[id - 1].height = height;
530 dpyinfo->bitmaps[id - 1].width = width; 594 dpyinfo->bitmaps[id - 1].width = width;
@@ -552,6 +616,8 @@ x_create_bitmap_from_file (f, file)
552 struct frame *f; 616 struct frame *f;
553 Lisp_Object file; 617 Lisp_Object file;
554{ 618{
619 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
620
555#ifdef MAC_OS 621#ifdef MAC_OS
556 return -1; /* MAC_TODO : bitmap support */ 622 return -1; /* MAC_TODO : bitmap support */
557#endif /* MAC_OS */ 623#endif /* MAC_OS */
@@ -560,8 +626,26 @@ x_create_bitmap_from_file (f, file)
560 return -1; /* W32_TODO : bitmap support */ 626 return -1; /* W32_TODO : bitmap support */
561#endif /* HAVE_NTGUI */ 627#endif /* HAVE_NTGUI */
562 628
629#ifdef HAVE_NS
630 int id;
631 void *bitmap = ns_image_from_file(file);
632
633 if (!bitmap)
634 return -1;
635
636
637 id = x_allocate_bitmap_record (f);
638 dpyinfo->bitmaps[id - 1].img = bitmap;
639 dpyinfo->bitmaps[id - 1].refcount = 1;
640 dpyinfo->bitmaps[id - 1].file = (char *) xmalloc (SBYTES (file) + 1);
641 dpyinfo->bitmaps[id - 1].depth = 1;
642 dpyinfo->bitmaps[id - 1].height = ns_image_width(bitmap);
643 dpyinfo->bitmaps[id - 1].width = ns_image_height(bitmap);
644 strcpy (dpyinfo->bitmaps[id - 1].file, SDATA (file));
645 return id;
646#endif
647
563#ifdef HAVE_X_WINDOWS 648#ifdef HAVE_X_WINDOWS
564 Display_Info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
565 unsigned int width, height; 649 unsigned int width, height;
566 Pixmap bitmap; 650 Pixmap bitmap;
567 int xhot, yhot, result, id; 651 int xhot, yhot, result, id;
@@ -630,6 +714,10 @@ free_bitmap_record (dpyinfo, bm)
630 bm->bitmap_data = NULL; 714 bm->bitmap_data = NULL;
631#endif /* MAC_OS */ 715#endif /* MAC_OS */
632 716
717#ifdef HAVE_NS
718 ns_release_object(bm->img);
719#endif
720
633 if (bm->file) 721 if (bm->file)
634 { 722 {
635 xfree (bm->file); 723 xfree (bm->file);
@@ -1407,7 +1495,8 @@ image_ascent (img, face, slice)
1407 because a typical font is `top-heavy' (due to the presence 1495 because a typical font is `top-heavy' (due to the presence
1408 uppercase letters), so the image placement should err towards 1496 uppercase letters), so the image placement should err towards
1409 being top-heavy too. It also just generally looks better. */ 1497 being top-heavy too. It also just generally looks better. */
1410 ascent = (height + face->font->ascent - face->font->descent + 1) / 2; 1498 ascent = (height + FONT_BASE(face->font)
1499 - FONT_DESCENT(face->font) + 1) / 2;
1411#endif /* HAVE_NTGUI */ 1500#endif /* HAVE_NTGUI */
1412 } 1501 }
1413 else 1502 else
@@ -1476,6 +1565,14 @@ four_corners_best (ximg, corners, width, height)
1476#define Free_Pixmap(display, pixmap) \ 1565#define Free_Pixmap(display, pixmap) \
1477 DeleteObject (pixmap) 1566 DeleteObject (pixmap)
1478 1567
1568#elif defined (HAVE_NS)
1569
1570#define Destroy_Image(ximg, dummy) \
1571 ns_release_object(ximg)
1572
1573#define Free_Pixmap(display, pixmap) \
1574 ns_release_object(pixmap)
1575
1479#else 1576#else
1480 1577
1481#define Destroy_Image(ximg, dummy) \ 1578#define Destroy_Image(ximg, dummy) \
@@ -1484,7 +1581,7 @@ four_corners_best (ximg, corners, width, height)
1484#define Free_Pixmap(display, pixmap) \ 1581#define Free_Pixmap(display, pixmap) \
1485 XFreePixmap (display, pixmap) 1582 XFreePixmap (display, pixmap)
1486 1583
1487#endif /* HAVE_NTGUI */ 1584#endif /* !HAVE_NTGUI && !HAVE_NS */
1488 1585
1489 1586
1490/* Return the `background' field of IMG. If IMG doesn't have one yet, 1587/* Return the `background' field of IMG. If IMG doesn't have one yet,
@@ -1607,6 +1704,10 @@ x_clear_image_1 (f, img, pixmap_p, mask_p, colors_p)
1607 { 1704 {
1608 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap); 1705 Free_Pixmap (FRAME_X_DISPLAY (f), img->pixmap);
1609 img->pixmap = NO_PIXMAP; 1706 img->pixmap = NO_PIXMAP;
1707#ifdef HAVE_NS
1708 if (img->background_valid)
1709 ns_free_indexed_color(img->background);
1710#endif
1610 img->background_valid = 0; 1711 img->background_valid = 0;
1611 } 1712 }
1612 1713
@@ -2387,6 +2488,18 @@ x_create_x_image_and_pixmap (f, width, height, depth, ximg, pixmap)
2387 return 1; 2488 return 1;
2388 2489
2389#endif /* MAC_OS */ 2490#endif /* MAC_OS */
2491
2492#ifdef HAVE_NS
2493 *pixmap = ns_image_for_XPM(width, height, depth);
2494 if (*pixmap == 0)
2495 {
2496 *ximg = NULL;
2497 image_error ("Unable to allocate NSImage for XPM pixmap", Qnil, Qnil);
2498 return 0;
2499 }
2500 *ximg = *pixmap;
2501 return 1;
2502#endif
2390} 2503}
2391 2504
2392 2505
@@ -2412,6 +2525,9 @@ x_destroy_x_image (ximg)
2412#ifdef MAC_OS 2525#ifdef MAC_OS
2413 XDestroyImage (ximg); 2526 XDestroyImage (ximg);
2414#endif /* MAC_OS */ 2527#endif /* MAC_OS */
2528#ifdef HAVE_NS
2529 ns_release_object(ximg);
2530#endif /* HAVE_NS */
2415 } 2531 }
2416} 2532}
2417 2533
@@ -2446,6 +2562,11 @@ x_put_x_image (f, ximg, pixmap, width, height)
2446#ifdef MAC_OS 2562#ifdef MAC_OS
2447 xassert (ximg == pixmap); 2563 xassert (ximg == pixmap);
2448#endif /* MAC_OS */ 2564#endif /* MAC_OS */
2565
2566#ifdef HAVE_NS
2567 xassert (ximg == pixmap);
2568 ns_retain_object(ximg);
2569#endif
2449} 2570}
2450 2571
2451 2572
@@ -3499,6 +3620,10 @@ Create_Pixmap_From_Bitmap_Data (f, img, data, fg, bg, non_default_colors)
3499 /* If colors were specified, transfer the bitmap to a color one. */ 3620 /* If colors were specified, transfer the bitmap to a color one. */
3500 if (non_default_colors) 3621 if (non_default_colors)
3501 convert_mono_to_color_image (f, img, fg, bg); 3622 convert_mono_to_color_image (f, img, fg, bg);
3623
3624#elif defined (HAVE_NS)
3625 img->pixmap = ns_image_from_XBM(data, img->width, img->height);
3626
3502#else 3627#else
3503 img->pixmap 3628 img->pixmap
3504 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f), 3629 = XCreatePixmapFromBitmapData (FRAME_X_DISPLAY (f),
@@ -3507,7 +3632,7 @@ Create_Pixmap_From_Bitmap_Data (f, img, data, fg, bg, non_default_colors)
3507 img->width, img->height, 3632 img->width, img->height,
3508 fg, bg, 3633 fg, bg,
3509 DefaultDepthOfScreen (FRAME_X_SCREEN (f))); 3634 DefaultDepthOfScreen (FRAME_X_SCREEN (f)));
3510#endif /* HAVE_NTGUI */ 3635#endif /* !HAVE_NTGUI && !HAVE_NS */
3511} 3636}
3512 3637
3513 3638
@@ -3891,13 +4016,13 @@ xbm_load (f, img)
3891 XPM images 4016 XPM images
3892 ***********************************************************************/ 4017 ***********************************************************************/
3893 4018
3894#if defined (HAVE_XPM) || defined (MAC_OS) 4019#if defined (HAVE_XPM) || defined (MAC_OS) || defined (HAVE_NS)
3895 4020
3896static int xpm_image_p P_ ((Lisp_Object object)); 4021static int xpm_image_p P_ ((Lisp_Object object));
3897static int xpm_load P_ ((struct frame *f, struct image *img)); 4022static int xpm_load P_ ((struct frame *f, struct image *img));
3898static int xpm_valid_color_symbols_p P_ ((Lisp_Object)); 4023static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
3899 4024
3900#endif /* HAVE_XPM || MAC_OS */ 4025#endif /* HAVE_XPM || MAC_OS || HAVE_NS */
3901 4026
3902#ifdef HAVE_XPM 4027#ifdef HAVE_XPM
3903#ifdef HAVE_NTGUI 4028#ifdef HAVE_NTGUI
@@ -3920,7 +4045,7 @@ static int xpm_valid_color_symbols_p P_ ((Lisp_Object));
3920#endif /* HAVE_NTGUI */ 4045#endif /* HAVE_NTGUI */
3921#endif /* HAVE_XPM */ 4046#endif /* HAVE_XPM */
3922 4047
3923#if defined (HAVE_XPM) || defined (MAC_OS) 4048#if defined (HAVE_XPM) || defined (MAC_OS) || defined (HAVE_NS)
3924/* The symbol `xpm' identifying XPM-format images. */ 4049/* The symbol `xpm' identifying XPM-format images. */
3925 4050
3926Lisp_Object Qxpm; 4051Lisp_Object Qxpm;
@@ -4247,7 +4372,7 @@ xpm_image_p (object)
4247 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value))); 4372 || xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
4248} 4373}
4249 4374
4250#endif /* HAVE_XPM || MAC_OS */ 4375#endif /* HAVE_XPM || MAC_OS || HAVE_NS */
4251 4376
4252#if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS) 4377#if defined (HAVE_XPM) && defined (HAVE_X_WINDOWS)
4253int 4378int
@@ -4526,7 +4651,7 @@ xpm_load (f, img)
4526 4651
4527#endif /* HAVE_XPM */ 4652#endif /* HAVE_XPM */
4528 4653
4529#ifdef MAC_OS 4654#if defined (MAC_OS) || ( defined (HAVE_NS) && !defined (HAVE_XPM) )
4530 4655
4531/* XPM support functions for Mac OS where libxpm is not available. 4656/* XPM support functions for Mac OS where libxpm is not available.
4532 Only XPM version 3 (without any extensions) is supported. */ 4657 Only XPM version 3 (without any extensions) is supported. */
@@ -4884,8 +5009,11 @@ xpm_load_image (f, img, contents, end)
4884 5009
4885 if (!x_create_x_image_and_pixmap (f, width, height, 0, 5010 if (!x_create_x_image_and_pixmap (f, width, height, 0,
4886 &ximg, &img->pixmap) 5011 &ximg, &img->pixmap)
5012#ifndef HAVE_NS
4887 || !x_create_x_image_and_pixmap (f, width, height, 1, 5013 || !x_create_x_image_and_pixmap (f, width, height, 1,
4888 &mask_img, &img->mask)) 5014 &mask_img, &img->mask)
5015#endif
5016 )
4889 { 5017 {
4890 image_error ("Out of memory (%s)", img->spec, Qnil); 5018 image_error ("Out of memory (%s)", img->spec, Qnil);
4891 goto error; 5019 goto error;
@@ -4905,9 +5033,14 @@ xpm_load_image (f, img, contents, end)
4905 XPutPixel (ximg, x, y, 5033 XPutPixel (ximg, x, y,
4906 (INTEGERP (color_val) ? XINT (color_val) 5034 (INTEGERP (color_val) ? XINT (color_val)
4907 : FRAME_FOREGROUND_PIXEL (f))); 5035 : FRAME_FOREGROUND_PIXEL (f)));
5036#ifndef HAVE_NS
4908 XPutPixel (mask_img, x, y, 5037 XPutPixel (mask_img, x, y,
4909 (!EQ (color_val, Qt) ? PIX_MASK_DRAW 5038 (!EQ (color_val, Qt) ? PIX_MASK_DRAW
4910 : (have_mask = 1, PIX_MASK_RETAIN))); 5039 : (have_mask = 1, PIX_MASK_RETAIN)));
5040#else
5041 if (EQ(color_val, Qt))
5042 ns_set_alpha(ximg, x, y, 0);
5043#endif
4911 } 5044 }
4912 if (y + 1 < height) 5045 if (y + 1 < height)
4913 expect (','); 5046 expect (',');
@@ -4922,6 +5055,7 @@ xpm_load_image (f, img, contents, end)
4922 5055
4923 x_put_x_image (f, ximg, img->pixmap, width, height); 5056 x_put_x_image (f, ximg, img->pixmap, width, height);
4924 x_destroy_x_image (ximg); 5057 x_destroy_x_image (ximg);
5058#ifndef HAVE_NS
4925 if (have_mask) 5059 if (have_mask)
4926 { 5060 {
4927 /* Fill in the background_transparent field while we have the 5061 /* Fill in the background_transparent field while we have the
@@ -4937,7 +5071,7 @@ xpm_load_image (f, img, contents, end)
4937 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask); 5071 Free_Pixmap (FRAME_X_DISPLAY (f), img->mask);
4938 img->mask = NO_PIXMAP; 5072 img->mask = NO_PIXMAP;
4939 } 5073 }
4940 5074#endif
4941 return 1; 5075 return 1;
4942 5076
4943 failure: 5077 failure:
@@ -5003,7 +5137,7 @@ xpm_load (f, img)
5003 return success_p; 5137 return success_p;
5004} 5138}
5005 5139
5006#endif /* MAC_OS */ 5140#endif /* MAC_OS || (HAVE_NS && !HAVE_XPM) */
5007 5141
5008 5142
5009 5143
@@ -5273,6 +5407,9 @@ lookup_rgb_color (f, r, g, b)
5273 pixel = PALETTERGB (r >> 8, g >> 8, b >> 8); 5407 pixel = PALETTERGB (r >> 8, g >> 8, b >> 8);
5274#endif /* HAVE_NTGUI */ 5408#endif /* HAVE_NTGUI */
5275 5409
5410#ifdef HAVE_NS
5411 pixel = RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
5412#endif /* HAVE_NS */
5276 return pixel; 5413 return pixel;
5277} 5414}
5278 5415
@@ -5378,7 +5515,7 @@ x_to_xcolors (f, img, rgb_p)
5378 p->pixel = GET_PIXEL (ximg, x, y); 5515 p->pixel = GET_PIXEL (ximg, x, y);
5379 if (rgb_p) 5516 if (rgb_p)
5380 { 5517 {
5381#ifdef MAC_OS 5518#if defined (MAC_OS) || defined (HAVE_NS)
5382 p->red = RED16_FROM_ULONG (p->pixel); 5519 p->red = RED16_FROM_ULONG (p->pixel);
5383 p->green = GREEN16_FROM_ULONG (p->pixel); 5520 p->green = GREEN16_FROM_ULONG (p->pixel);
5384 p->blue = BLUE16_FROM_ULONG (p->pixel); 5521 p->blue = BLUE16_FROM_ULONG (p->pixel);
@@ -5459,8 +5596,8 @@ x_from_xcolors (f, img, colors)
5459 XColor *colors; 5596 XColor *colors;
5460{ 5597{
5461 int x, y; 5598 int x, y;
5462 XImagePtr oimg; 5599 XImagePtr oimg = NULL;
5463 Pixmap pixmap; 5600 Pixmap pixmap = NULL;
5464 XColor *p; 5601 XColor *p;
5465 5602
5466 init_color_table (); 5603 init_color_table ();
@@ -5673,6 +5810,8 @@ x_disable_image (f, img)
5673 Display *dpy = FRAME_X_DISPLAY (f); 5810 Display *dpy = FRAME_X_DISPLAY (f);
5674 GC gc; 5811 GC gc;
5675 5812
5813#ifndef HAVE_NS //TODO: NS support, however this not needed for toolbars
5814
5676#ifdef MAC_OS 5815#ifdef MAC_OS
5677#define MaskForeground(f) PIX_MASK_DRAW 5816#define MaskForeground(f) PIX_MASK_DRAW
5678#else 5817#else
@@ -5697,6 +5836,7 @@ x_disable_image (f, img)
5697 img->width - 1, 0); 5836 img->width - 1, 0);
5698 XFreeGC (dpy, gc); 5837 XFreeGC (dpy, gc);
5699 } 5838 }
5839#endif /* !HAVE_NS */
5700#else 5840#else
5701 HDC hdc, bmpdc; 5841 HDC hdc, bmpdc;
5702 HGDIOBJ prev; 5842 HGDIOBJ prev;
@@ -5762,11 +5902,13 @@ x_build_heuristic_mask (f, img, how)
5762 } 5902 }
5763 5903
5764#ifndef HAVE_NTGUI 5904#ifndef HAVE_NTGUI
5905#ifndef HAVE_NS
5765 /* Create an image and pixmap serving as mask. */ 5906 /* Create an image and pixmap serving as mask. */
5766 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1, 5907 rc = x_create_x_image_and_pixmap (f, img->width, img->height, 1,
5767 &mask_img, &img->mask); 5908 &mask_img, &img->mask);
5768 if (!rc) 5909 if (!rc)
5769 return 0; 5910 return 0;
5911#endif /* !HAVE_NS */
5770 5912
5771 /* Get the X image of IMG->pixmap. */ 5913 /* Get the X image of IMG->pixmap. */
5772 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, 0, 0, 5914 ximg = XGetImage (FRAME_X_DISPLAY (f), img->pixmap, 0, 0,
@@ -5820,16 +5962,21 @@ x_build_heuristic_mask (f, img, how)
5820#ifndef HAVE_NTGUI 5962#ifndef HAVE_NTGUI
5821 for (y = 0; y < img->height; ++y) 5963 for (y = 0; y < img->height; ++y)
5822 for (x = 0; x < img->width; ++x) 5964 for (x = 0; x < img->width; ++x)
5965#ifndef HAVE_NS
5823 XPutPixel (mask_img, x, y, (XGetPixel (ximg, x, y) != bg 5966 XPutPixel (mask_img, x, y, (XGetPixel (ximg, x, y) != bg
5824 ? PIX_MASK_DRAW : PIX_MASK_RETAIN)); 5967 ? PIX_MASK_DRAW : PIX_MASK_RETAIN));
5825 5968#else
5969 if (XGetPixel (ximg, x, y) == bg)
5970 ns_set_alpha(ximg, x, y, 0);
5971#endif /* HAVE_NS */
5972#ifndef HAVE_NS
5826 /* Fill in the background_transparent field while we have the mask handy. */ 5973 /* Fill in the background_transparent field while we have the mask handy. */
5827 image_background_transparent (img, f, mask_img); 5974 image_background_transparent (img, f, mask_img);
5828 5975
5829 /* Put mask_img into img->mask. */ 5976 /* Put mask_img into img->mask. */
5830 x_put_x_image (f, mask_img, img->mask, img->width, img->height); 5977 x_put_x_image (f, mask_img, img->mask, img->width, img->height);
5831 x_destroy_x_image (mask_img); 5978 x_destroy_x_image (mask_img);
5832 5979#endif /* !HAVE_NS */
5833#else 5980#else
5834 for (y = 0; y < img->height; ++y) 5981 for (y = 0; y < img->height; ++y)
5835 for (x = 0; x < img->width; ++x) 5982 for (x = 0; x < img->width; ++x)
@@ -6280,7 +6427,7 @@ pbm_load (f, img)
6280 PNG 6427 PNG
6281 ***********************************************************************/ 6428 ***********************************************************************/
6282 6429
6283#if defined (HAVE_PNG) || defined (MAC_OS) 6430#if defined (HAVE_PNG) || defined (MAC_OS) || defined (HAVE_NS)
6284 6431
6285/* Function prototypes. */ 6432/* Function prototypes. */
6286 6433
@@ -6352,7 +6499,7 @@ png_image_p (object)
6352 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1; 6499 return fmt[PNG_FILE].count + fmt[PNG_DATA].count == 1;
6353} 6500}
6354 6501
6355#endif /* HAVE_PNG || MAC_OS */ 6502#endif /* HAVE_PNG || MAC_OS || HAVE_NS */
6356 6503
6357 6504
6358#ifdef HAVE_PNG 6505#ifdef HAVE_PNG
@@ -6912,6 +7059,17 @@ png_load (f, img)
6912} 7059}
6913#endif /* MAC_OS */ 7060#endif /* MAC_OS */
6914 7061
7062#ifdef HAVE_NS
7063static int
7064png_load (struct frame *f, struct image *img)
7065{
7066 return ns_load_image(f, img,
7067 image_spec_value (img->spec, QCfile, NULL),
7068 image_spec_value (img->spec, QCdata, NULL));
7069}
7070#endif /* HAVE_NS */
7071
7072
6915#endif /* !HAVE_PNG */ 7073#endif /* !HAVE_PNG */
6916 7074
6917 7075
@@ -6920,7 +7078,7 @@ png_load (f, img)
6920 JPEG 7078 JPEG
6921 ***********************************************************************/ 7079 ***********************************************************************/
6922 7080
6923#if defined (HAVE_JPEG) || defined (MAC_OS) 7081#if defined (HAVE_JPEG) || defined (MAC_OS) || defined (HAVE_NS)
6924 7082
6925static int jpeg_image_p P_ ((Lisp_Object object)); 7083static int jpeg_image_p P_ ((Lisp_Object object));
6926static int jpeg_load P_ ((struct frame *f, struct image *img)); 7084static int jpeg_load P_ ((struct frame *f, struct image *img));
@@ -6991,7 +7149,7 @@ jpeg_image_p (object)
6991 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1; 7149 return fmt[JPEG_FILE].count + fmt[JPEG_DATA].count == 1;
6992} 7150}
6993 7151
6994#endif /* HAVE_JPEG || MAC_OS */ 7152#endif /* HAVE_JPEG || MAC_OS || HAVE_NS */
6995 7153
6996#ifdef HAVE_JPEG 7154#ifdef HAVE_JPEG
6997 7155
@@ -7491,6 +7649,16 @@ jpeg_load (f, img)
7491} 7649}
7492#endif /* MAC_OS */ 7650#endif /* MAC_OS */
7493 7651
7652#ifdef HAVE_NS
7653static int
7654jpeg_load (struct frame *f, struct image *img)
7655{
7656 return ns_load_image(f, img,
7657 image_spec_value (img->spec, QCfile, NULL),
7658 image_spec_value (img->spec, QCdata, NULL));
7659}
7660#endif /* HAVE_NS */
7661
7494#endif /* !HAVE_JPEG */ 7662#endif /* !HAVE_JPEG */
7495 7663
7496 7664
@@ -7499,7 +7667,7 @@ jpeg_load (f, img)
7499 TIFF 7667 TIFF
7500 ***********************************************************************/ 7668 ***********************************************************************/
7501 7669
7502#if defined (HAVE_TIFF) || defined (MAC_OS) 7670#if defined (HAVE_TIFF) || defined (MAC_OS) || defined (HAVE_NS)
7503 7671
7504static int tiff_image_p P_ ((Lisp_Object object)); 7672static int tiff_image_p P_ ((Lisp_Object object));
7505static int tiff_load P_ ((struct frame *f, struct image *img)); 7673static int tiff_load P_ ((struct frame *f, struct image *img));
@@ -7569,7 +7737,7 @@ tiff_image_p (object)
7569 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1; 7737 return fmt[TIFF_FILE].count + fmt[TIFF_DATA].count == 1;
7570} 7738}
7571 7739
7572#endif /* HAVE_TIFF || MAC_OS */ 7740#endif /* HAVE_TIFF || MAC_OS || HAVE_NS */
7573 7741
7574#ifdef HAVE_TIFF 7742#ifdef HAVE_TIFF
7575 7743
@@ -7916,6 +8084,16 @@ tiff_load (f, img)
7916} 8084}
7917#endif /* MAC_OS */ 8085#endif /* MAC_OS */
7918 8086
8087#ifdef HAVE_NS
8088static int
8089tiff_load (struct frame *f, struct image *img)
8090{
8091 return ns_load_image(f, img,
8092 image_spec_value (img->spec, QCfile, NULL),
8093 image_spec_value (img->spec, QCdata, NULL));
8094}
8095#endif /* HAVE_NS */
8096
7919#endif /* !HAVE_TIFF */ 8097#endif /* !HAVE_TIFF */
7920 8098
7921 8099
@@ -7924,7 +8102,7 @@ tiff_load (f, img)
7924 GIF 8102 GIF
7925 ***********************************************************************/ 8103 ***********************************************************************/
7926 8104
7927#if defined (HAVE_GIF) || defined (MAC_OS) 8105#if defined (HAVE_GIF) || defined (MAC_OS) || defined (HAVE_NS)
7928 8106
7929static int gif_image_p P_ ((Lisp_Object object)); 8107static int gif_image_p P_ ((Lisp_Object object));
7930static int gif_load P_ ((struct frame *f, struct image *img)); 8108static int gif_load P_ ((struct frame *f, struct image *img));
@@ -8553,6 +8731,16 @@ gif_load (f, img)
8553} 8731}
8554#endif /* MAC_OS */ 8732#endif /* MAC_OS */
8555 8733
8734#ifdef HAVE_NS
8735static int
8736gif_load (struct frame *f, struct image *img)
8737{
8738 return ns_load_image(f, img,
8739 image_spec_value (img->spec, QCfile, NULL),
8740 image_spec_value (img->spec, QCdata, NULL));
8741}
8742#endif /* HAVE_NS */
8743
8556#endif /* HAVE_GIF */ 8744#endif /* HAVE_GIF */
8557 8745
8558 8746
@@ -9335,27 +9523,27 @@ of `image-library-alist', which see). */)
9335 if (CONSP (tested)) 9523 if (CONSP (tested))
9336 return XCDR (tested); 9524 return XCDR (tested);
9337 9525
9338#if defined (HAVE_XPM) || defined (MAC_OS) 9526#if defined (HAVE_XPM) || defined (MAC_OS) || defined (HAVE_NS)
9339 if (EQ (type, Qxpm)) 9527 if (EQ (type, Qxpm))
9340 return CHECK_LIB_AVAILABLE (&xpm_type, init_xpm_functions, libraries); 9528 return CHECK_LIB_AVAILABLE (&xpm_type, init_xpm_functions, libraries);
9341#endif 9529#endif
9342 9530
9343#if defined (HAVE_JPEG) || defined (MAC_OS) 9531#if defined (HAVE_JPEG) || defined (MAC_OS) || defined (HAVE_NS)
9344 if (EQ (type, Qjpeg)) 9532 if (EQ (type, Qjpeg))
9345 return CHECK_LIB_AVAILABLE (&jpeg_type, init_jpeg_functions, libraries); 9533 return CHECK_LIB_AVAILABLE (&jpeg_type, init_jpeg_functions, libraries);
9346#endif 9534#endif
9347 9535
9348#if defined (HAVE_TIFF) || defined (MAC_OS) 9536#if defined (HAVE_TIFF) || defined (MAC_OS) || defined (HAVE_NS)
9349 if (EQ (type, Qtiff)) 9537 if (EQ (type, Qtiff))
9350 return CHECK_LIB_AVAILABLE (&tiff_type, init_tiff_functions, libraries); 9538 return CHECK_LIB_AVAILABLE (&tiff_type, init_tiff_functions, libraries);
9351#endif 9539#endif
9352 9540
9353#if defined (HAVE_GIF) || defined (MAC_OS) 9541#if defined (HAVE_GIF) || defined (MAC_OS) || defined (HAVE_NS)
9354 if (EQ (type, Qgif)) 9542 if (EQ (type, Qgif))
9355 return CHECK_LIB_AVAILABLE (&gif_type, init_gif_functions, libraries); 9543 return CHECK_LIB_AVAILABLE (&gif_type, init_gif_functions, libraries);
9356#endif 9544#endif
9357 9545
9358#if defined (HAVE_PNG) || defined (MAC_OS) 9546#if defined (HAVE_PNG) || defined (MAC_OS) || defined (HAVE_NS)
9359 if (EQ (type, Qpng)) 9547 if (EQ (type, Qpng))
9360 return CHECK_LIB_AVAILABLE (&png_type, init_png_functions, libraries); 9548 return CHECK_LIB_AVAILABLE (&png_type, init_png_functions, libraries);
9361#endif 9549#endif
@@ -9480,31 +9668,31 @@ non-numeric, there is no explicit limit on the size of images. */);
9480 staticpro (&QCpt_height); 9668 staticpro (&QCpt_height);
9481#endif /* HAVE_GHOSTSCRIPT */ 9669#endif /* HAVE_GHOSTSCRIPT */
9482 9670
9483#if defined (HAVE_XPM) || defined (MAC_OS) 9671#if defined (HAVE_XPM) || defined (MAC_OS) || defined (HAVE_NS)
9484 Qxpm = intern ("xpm"); 9672 Qxpm = intern ("xpm");
9485 staticpro (&Qxpm); 9673 staticpro (&Qxpm);
9486 ADD_IMAGE_TYPE (Qxpm); 9674 ADD_IMAGE_TYPE (Qxpm);
9487#endif 9675#endif
9488 9676
9489#if defined (HAVE_JPEG) || defined (MAC_OS) 9677#if defined (HAVE_JPEG) || defined (MAC_OS) || defined (HAVE_NS)
9490 Qjpeg = intern ("jpeg"); 9678 Qjpeg = intern ("jpeg");
9491 staticpro (&Qjpeg); 9679 staticpro (&Qjpeg);
9492 ADD_IMAGE_TYPE (Qjpeg); 9680 ADD_IMAGE_TYPE (Qjpeg);
9493#endif 9681#endif
9494 9682
9495#if defined (HAVE_TIFF) || defined (MAC_OS) 9683#if defined (HAVE_TIFF) || defined (MAC_OS) || defined (HAVE_NS)
9496 Qtiff = intern ("tiff"); 9684 Qtiff = intern ("tiff");
9497 staticpro (&Qtiff); 9685 staticpro (&Qtiff);
9498 ADD_IMAGE_TYPE (Qtiff); 9686 ADD_IMAGE_TYPE (Qtiff);
9499#endif 9687#endif
9500 9688
9501#if defined (HAVE_GIF) || defined (MAC_OS) 9689#if defined (HAVE_GIF) || defined (MAC_OS) || defined (HAVE_NS)
9502 Qgif = intern ("gif"); 9690 Qgif = intern ("gif");
9503 staticpro (&Qgif); 9691 staticpro (&Qgif);
9504 ADD_IMAGE_TYPE (Qgif); 9692 ADD_IMAGE_TYPE (Qgif);
9505#endif 9693#endif
9506 9694
9507#if defined (HAVE_PNG) || defined (MAC_OS) 9695#if defined (HAVE_PNG) || defined (MAC_OS) || defined (HAVE_NS)
9508 Qpng = intern ("png"); 9696 Qpng = intern ("png");
9509 staticpro (&Qpng); 9697 staticpro (&Qpng);
9510 ADD_IMAGE_TYPE (Qpng); 9698 ADD_IMAGE_TYPE (Qpng);
diff --git a/src/keyboard.c b/src/keyboard.c
index e42e17525e6..b908b8ad349 100644
--- a/src/keyboard.c
+++ b/src/keyboard.c
@@ -80,6 +80,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
80#include "macterm.h" 80#include "macterm.h"
81#endif 81#endif
82 82
83#ifdef HAVE_NS
84#include "nsterm.h"
85extern Lisp_Object Qsuper;
86#endif
87
83#ifndef USE_CRT_DLL 88#ifndef USE_CRT_DLL
84extern int errno; 89extern int errno;
85#endif 90#endif
@@ -4147,7 +4152,8 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
4147#endif 4152#endif
4148 } 4153 }
4149 4154
4150#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS) 4155#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS) \
4156 || defined (HAVE_NS)
4151 else if (event->kind == DELETE_WINDOW_EVENT) 4157 else if (event->kind == DELETE_WINDOW_EVENT)
4152 { 4158 {
4153 /* Make an event (delete-frame (FRAME)). */ 4159 /* Make an event (delete-frame (FRAME)). */
@@ -4156,7 +4162,8 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
4156 kbd_fetch_ptr = event + 1; 4162 kbd_fetch_ptr = event + 1;
4157 } 4163 }
4158#endif 4164#endif
4159#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS) 4165#if defined (HAVE_X11) || defined (HAVE_NTGUI) || defined (MAC_OS) \
4166 || defined (HAVE_NS)
4160 else if (event->kind == ICONIFY_EVENT) 4167 else if (event->kind == ICONIFY_EVENT)
4161 { 4168 {
4162 /* Make an event (iconify-frame (FRAME)). */ 4169 /* Make an event (iconify-frame (FRAME)). */
@@ -4179,7 +4186,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
4179 kbd_fetch_ptr = event + 1; 4186 kbd_fetch_ptr = event + 1;
4180 } 4187 }
4181#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ 4188#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
4182 || defined (USE_GTK) 4189 || defined(HAVE_NS) || defined (USE_GTK)
4183 else if (event->kind == MENU_BAR_ACTIVATE_EVENT) 4190 else if (event->kind == MENU_BAR_ACTIVATE_EVENT)
4184 { 4191 {
4185 kbd_fetch_ptr = event + 1; 4192 kbd_fetch_ptr = event + 1;
@@ -4289,7 +4296,7 @@ kbd_buffer_get_event (kbp, used_mouse_menu, end_time)
4289 obj = make_lispy_event (event); 4296 obj = make_lispy_event (event);
4290 4297
4291#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined(MAC_OS) \ 4298#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined(MAC_OS) \
4292 || defined (USE_GTK) 4299 || defined(HAVE_NS) || defined (USE_GTK)
4293 /* If this was a menu selection, then set the flag to inhibit 4300 /* If this was a menu selection, then set the flag to inhibit
4294 writing to last_nonmenu_event. Don't do this if the event 4301 writing to last_nonmenu_event. Don't do this if the event
4295 we're returning is (menu-bar), though; that indicates the 4302 we're returning is (menu-bar), though; that indicates the
@@ -5643,7 +5650,7 @@ make_lispy_event (event)
5643 if (event->kind == MOUSE_CLICK_EVENT) 5650 if (event->kind == MOUSE_CLICK_EVENT)
5644 { 5651 {
5645 struct frame *f = XFRAME (event->frame_or_window); 5652 struct frame *f = XFRAME (event->frame_or_window);
5646#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) 5653#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) && ! defined (HAVE_NS)
5647 int row, column; 5654 int row, column;
5648#endif 5655#endif
5649 5656
@@ -5652,7 +5659,7 @@ make_lispy_event (event)
5652 if (! FRAME_LIVE_P (f)) 5659 if (! FRAME_LIVE_P (f))
5653 return Qnil; 5660 return Qnil;
5654 5661
5655#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) 5662#if ! defined (USE_X_TOOLKIT) && ! defined (USE_GTK) && ! defined (HAVE_NS)
5656 /* EVENT->x and EVENT->y are frame-relative pixel 5663 /* EVENT->x and EVENT->y are frame-relative pixel
5657 coordinates at this place. Under old redisplay, COLUMN 5664 coordinates at this place. Under old redisplay, COLUMN
5658 and ROW are set to frame relative glyph coordinates 5665 and ROW are set to frame relative glyph coordinates
@@ -5712,7 +5719,7 @@ make_lispy_event (event)
5712 5719
5713 return Fcons (item, Fcons (position, Qnil)); 5720 return Fcons (item, Fcons (position, Qnil));
5714 } 5721 }
5715#endif /* not USE_X_TOOLKIT && not USE_GTK */ 5722#endif /* not USE_X_TOOLKIT && not USE_GTK && not HAVE_NS */
5716 5723
5717 position = make_lispy_position (f, &event->x, &event->y, 5724 position = make_lispy_position (f, &event->x, &event->y,
5718 event->timestamp); 5725 event->timestamp);
@@ -6092,7 +6099,7 @@ make_lispy_event (event)
6092#endif /* HAVE_MOUSE */ 6099#endif /* HAVE_MOUSE */
6093 6100
6094#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ 6101#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
6095 || defined (USE_GTK) 6102 || defined(HAVE_NS) || defined (USE_GTK)
6096 case MENU_BAR_EVENT: 6103 case MENU_BAR_EVENT:
6097 if (EQ (event->arg, event->frame_or_window)) 6104 if (EQ (event->arg, event->frame_or_window))
6098 /* This is the prefix key. We translate this to 6105 /* This is the prefix key. We translate this to
@@ -7305,6 +7312,10 @@ tty_read_avail_input (struct terminal *terminal,
7305void 7312void
7306handle_async_input () 7313handle_async_input ()
7307{ 7314{
7315#ifdef BSD4_1
7316 extern int select_alarmed;
7317#endif
7318
7308 interrupt_input_pending = 0; 7319 interrupt_input_pending = 0;
7309 7320
7310 while (1) 7321 while (1)
@@ -7317,6 +7328,9 @@ handle_async_input ()
7317 if (nread <= 0) 7328 if (nread <= 0)
7318 break; 7329 break;
7319 7330
7331#ifdef BSD4_1
7332 select_alarmed = 1; /* Force the select emulator back to life */
7333#endif
7320 } 7334 }
7321} 7335}
7322 7336
@@ -7335,6 +7349,10 @@ input_available_signal (signo)
7335 signal (signo, input_available_signal); 7349 signal (signo, input_available_signal);
7336#endif /* USG */ 7350#endif /* USG */
7337 7351
7352#ifdef BSD4_1
7353 sigisheld (SIGIO);
7354#endif
7355
7338#ifdef SYNC_INPUT 7356#ifdef SYNC_INPUT
7339 interrupt_input_pending = 1; 7357 interrupt_input_pending = 1;
7340#else 7358#else
@@ -7348,6 +7366,9 @@ input_available_signal (signo)
7348 handle_async_input (); 7366 handle_async_input ();
7349#endif 7367#endif
7350 7368
7369#ifdef BSD4_1
7370 sigfree ();
7371#endif
7351 errno = old_errno; 7372 errno = old_errno;
7352} 7373}
7353#endif /* SIGIO */ 7374#endif /* SIGIO */
@@ -7975,10 +7996,15 @@ parse_menu_item (item, notreal, inmenubar)
7975 /* With the introduction of where_is_cache, the computation 7996 /* With the introduction of where_is_cache, the computation
7976 of equivalent key bindings is sufficiently fast that we 7997 of equivalent key bindings is sufficiently fast that we
7977 do not need to cache it here any more. */ 7998 do not need to cache it here any more. */
7978 /* CHECK_IMPURE (start); 7999/*PENDING: under NS this effect does not hold, perhaps due to the
7979 XSETCDR (start, Fcons (Fcons (Qnil, Qnil), XCDR (start))); 8000 modifier-preference changes to where-is-internal.. */
7980 cachelist = XCAR (XCDR (start)); */ 8001#ifdef HAVE_NS
8002 CHECK_IMPURE (start);
8003 XSETCDR (start, Fcons (Fcons (Qnil, Qnil), XCDR (start)));
8004 cachelist = XCAR (XCDR (start));
8005#else
7981 cachelist = Fcons (Qnil, Qnil); 8006 cachelist = Fcons (Qnil, Qnil);
8007#endif
7982 newcache = 1; 8008 newcache = 1;
7983 tem = AREF (item_properties, ITEM_PROPERTY_KEYEQ); 8009 tem = AREF (item_properties, ITEM_PROPERTY_KEYEQ);
7984 if (!NILP (keyhint)) 8010 if (!NILP (keyhint))
@@ -8044,7 +8070,12 @@ parse_menu_item (item, notreal, inmenubar)
8044 && SYMBOLP (XSYMBOL (def)->function) 8070 && SYMBOLP (XSYMBOL (def)->function)
8045 && ! NILP (Fget (def, Qmenu_alias))) 8071 && ! NILP (Fget (def, Qmenu_alias)))
8046 def = XSYMBOL (def)->function; 8072 def = XSYMBOL (def)->function;
8073#ifdef HAVE_NS
8074 /* prefer 'super' bindings */
8075 tem = Fwhere_is_internal (def, Qnil, Qsuper, Qt, Qt);
8076#else
8047 tem = Fwhere_is_internal (def, Qnil, Qt, Qnil, Qt); 8077 tem = Fwhere_is_internal (def, Qnil, Qt, Qnil, Qt);
8078#endif
8048 XSETCAR (cachelist, tem); 8079 XSETCAR (cachelist, tem);
8049 if (NILP (tem)) 8080 if (NILP (tem))
8050 { 8081 {
@@ -8077,7 +8108,7 @@ parse_menu_item (item, notreal, inmenubar)
8077 if (newcache && !NILP (tem)) 8108 if (newcache && !NILP (tem))
8078 { 8109 {
8079 tem = concat2 (build_string (" "), tem); 8110 tem = concat2 (build_string (" "), tem);
8080 // tem = concat3 (build_string (" ("), tem, build_string (")")); 8111 /* tem = concat3 (build_string (" ("), tem, build_string (")")); */
8081 XSETCDR (cachelist, tem); 8112 XSETCDR (cachelist, tem);
8082 } 8113 }
8083 8114
diff --git a/src/keyboard.h b/src/keyboard.h
index 2f0f434909a..e21766273a8 100644
--- a/src/keyboard.h
+++ b/src/keyboard.h
@@ -314,8 +314,7 @@ extern Lisp_Object unuse_menu_items P_ ((Lisp_Object dummy));
314 confined to an extended version of this with sections of code below 314 confined to an extended version of this with sections of code below
315 using it unconditionally. */ 315 using it unconditionally. */
316#ifndef HAVE_NTGUI 316#ifndef HAVE_NTGUI
317#ifdef USE_GTK 317#if defined (USE_GTK) || defined (HAVE_NS)
318/* gtk just uses utf-8. */
319# define ENCODE_MENU_STRING(str) ENCODE_UTF_8 (str) 318# define ENCODE_MENU_STRING(str) ENCODE_UTF_8 (str)
320#elif defined HAVE_X_I18N 319#elif defined HAVE_X_I18N
321#define ENCODE_MENU_STRING(str) ENCODE_SYSTEM (str) 320#define ENCODE_MENU_STRING(str) ENCODE_SYSTEM (str)
@@ -325,6 +324,56 @@ extern Lisp_Object unuse_menu_items P_ ((Lisp_Object dummy));
325#else /* HAVE_NTGUI */ 324#else /* HAVE_NTGUI */
326#define ENCODE_MENU_STRING(str) (str) 325#define ENCODE_MENU_STRING(str) (str)
327#endif 326#endif
327
328#if defined (HAVE_NS) || defined (HAVE_NTGUI)
329
330typedef void * XtPointer;
331typedef unsigned char Boolean;
332
333/* Definitions copied from lwlib.h */
334
335enum button_type
336{
337 BUTTON_TYPE_NONE,
338 BUTTON_TYPE_TOGGLE,
339 BUTTON_TYPE_RADIO
340};
341
342/* This structure is based on the one in ../lwlib/lwlib.h, with unused portions
343 removed. No term uses these. */
344typedef struct _widget_value
345{
346 /* name of widget */
347 Lisp_Object lname;
348 char* name;
349 /* value (meaning depend on widget type) */
350 char* value;
351 /* keyboard equivalent. no implications for XtTranslations */
352 Lisp_Object lkey;
353 char* key;
354 /* Help string or nil if none.
355 GC finds this string through the frame's menu_bar_vector
356 or through menu_items. */
357 Lisp_Object help;
358 /* true if enabled */
359 Boolean enabled;
360 /* true if selected */
361 Boolean selected;
362 /* The type of a button. */
363 enum button_type button_type;
364#if defined (HAVE_NTGUI)
365 /* true if menu title */
366 Boolean title;
367#endif
368 /* Contents of the sub-widgets, also selected slot for checkbox */
369 struct _widget_value* contents;
370 /* data passed to callback */
371 XtPointer call_data;
372 /* next one in the list */
373 struct _widget_value* next;
374} widget_value;
375#endif
376
328 377
329/* Macros for dealing with lispy events. */ 378/* Macros for dealing with lispy events. */
330 379
diff --git a/src/keymap.c b/src/keymap.c
index 7a9b5949151..545ab3de81e 100644
--- a/src/keymap.c
+++ b/src/keymap.c
@@ -111,6 +111,10 @@ extern Lisp_Object meta_prefix_char;
111 111
112extern Lisp_Object Voverriding_local_map; 112extern Lisp_Object Voverriding_local_map;
113 113
114#ifdef HAVE_NS
115extern Lisp_Object Qalt, Qcontrol, Qhyper, Qmeta, Qsuper;
116#endif
117
114/* Hash table used to cache a reverse-map to speed up calls to where-is. */ 118/* Hash table used to cache a reverse-map to speed up calls to where-is. */
115static Lisp_Object where_is_cache; 119static Lisp_Object where_is_cache;
116/* Which keymaps are reverse-stored in the cache. */ 120/* Which keymaps are reverse-stored in the cache. */
@@ -2621,6 +2625,41 @@ ascii_sequence_p (seq)
2621 return 1; 2625 return 1;
2622} 2626}
2623 2627
2628#ifdef HAVE_NS
2629int lisp_to_mod(Lisp_Object lmod)
2630/* -------------------------------------------------------------------------
2631 Convert lisp symbol to emacs modifier code.
2632 ------------------------------------------------------------------------- */
2633{
2634 if (EQ(lmod, Qmeta))
2635 return meta_modifier;
2636 else if (EQ(lmod, Qsuper))
2637 return super_modifier;
2638 else if (EQ(lmod, Qcontrol))
2639 return ctrl_modifier;
2640 else if (EQ(lmod, Qalt))
2641 return alt_modifier;
2642 else if (EQ(lmod, Qhyper))
2643 return hyper_modifier;
2644 return 0;
2645}
2646
2647/* Return non-zero if SEQ starts w/a char modified by given modifier only. */
2648static int
2649modifier_sequence_p (Lisp_Object seq, Lisp_Object modifier)
2650{
2651 Lisp_Object idx, elt;
2652
2653 if (XINT (Flength (seq)) == 0)
2654 return 0;
2655 XSETFASTINT(idx, 0);
2656 elt = Faref(seq, idx);
2657
2658 return (XUINT(elt) & (CHAR_MODIFIER_MASK ^ shift_modifier))
2659 == lisp_to_mod(modifier);
2660}
2661#endif
2662
2624 2663
2625/* where-is - finding a command in a set of keymaps. */ 2664/* where-is - finding a command in a set of keymaps. */
2626 2665
@@ -2803,6 +2842,14 @@ where_is_internal (definition, keymaps, firstonly, noindirect, no_remap)
2803 we find. */ 2842 we find. */
2804 if (EQ (firstonly, Qnon_ascii)) 2843 if (EQ (firstonly, Qnon_ascii))
2805 RETURN_UNGCPRO (sequence); 2844 RETURN_UNGCPRO (sequence);
2845#ifdef HAVE_NS
2846 /* respond to modifier preference */
2847 else if ((EQ (firstonly, Qalt) || EQ (firstonly, Qcontrol)
2848 || EQ (firstonly, Qhyper) || EQ (firstonly, Qmeta)
2849 || EQ (firstonly, Qsuper)))
2850 if (modifier_sequence_p(sequence, firstonly))
2851 RETURN_UNGCPRO (sequence);
2852#endif
2806 else if (!NILP (firstonly) && ascii_sequence_p (sequence)) 2853 else if (!NILP (firstonly) && ascii_sequence_p (sequence))
2807 RETURN_UNGCPRO (sequence); 2854 RETURN_UNGCPRO (sequence);
2808 2855
@@ -2836,6 +2883,10 @@ If KEYMAP is a list of keymaps, search only those keymaps.
2836 2883
2837If optional 3rd arg FIRSTONLY is non-nil, return the first key sequence found, 2884If optional 3rd arg FIRSTONLY is non-nil, return the first key sequence found,
2838rather than a list of all possible key sequences. 2885rather than a list of all possible key sequences.
2886#ifdef HAVE_NS
2887If FIRSTONLY is the symbol for a modifier key, return the first binding found,
2888that is modified by that modifier only.
2889#endif
2839If FIRSTONLY is the symbol `non-ascii', return the first binding found, 2890If FIRSTONLY is the symbol `non-ascii', return the first binding found,
2840no matter what it is. 2891no matter what it is.
2841If FIRSTONLY has another non-nil value, prefer sequences of ASCII characters 2892If FIRSTONLY has another non-nil value, prefer sequences of ASCII characters
@@ -2909,10 +2960,19 @@ remapped command in the returned list. */)
2909 for (i = n - 1; i >= 0; --i) 2960 for (i = n - 1; i >= 0; --i)
2910 if (EQ (shadow_lookup (keymaps, defns[i], Qnil), definition)) 2961 if (EQ (shadow_lookup (keymaps, defns[i], Qnil), definition))
2911 { 2962 {
2912 if (ascii_sequence_p (defns[i])) 2963#ifdef HAVE_NS
2913 break; 2964 if ((EQ (firstonly, Qalt) || EQ (firstonly, Qcontrol)
2914 else if (j < 0) 2965 || EQ (firstonly, Qhyper) || EQ (firstonly, Qmeta)
2915 j = i; 2966 || EQ (firstonly, Qsuper))
2967 && modifier_sequence_p(defns[i], firstonly))
2968 break;
2969 else if (EQ (firstonly, Qt) && ascii_sequence_p (defns[i]))
2970#else
2971 if (ascii_sequence_p (defns[i]))
2972#endif
2973 break;
2974 else if (j < 0)
2975 j = i;
2916 } 2976 }
2917 2977
2918 result = i >= 0 ? defns[i] : (j >= 0 ? defns[j] : Qnil); 2978 result = i >= 0 ? defns[i] : (j >= 0 ? defns[j] : Qnil);
diff --git a/src/lisp.h b/src/lisp.h
index 5216b7a72f8..366a0be146d 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -28,6 +28,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
28#define P_(proto) () 28#define P_(proto) ()
29#endif 29#endif
30 30
31#ifdef NS_IMPL_GNUSTEP
32/* This conflicts with functions in the GNUstep libraries. */
33#define hash_remove emacs_hash_remove
34#endif /* NS_IMPL_GNUSTEP */
35
31#if 0 36#if 0
32/* Define this temporarily to hunt a bug. If defined, the size of 37/* Define this temporarily to hunt a bug. If defined, the size of
33 strings is redundantly recorded in sdata structures so that it can 38 strings is redundantly recorded in sdata structures so that it can
@@ -157,7 +162,7 @@ extern void die P_((const char *, const char *, int)) NO_RETURN;
157#endif 162#endif
158 163
159/* Let's USE_LSB_TAG on systems where we know malloc returns mult-of-8. */ 164/* Let's USE_LSB_TAG on systems where we know malloc returns mult-of-8. */
160#if defined GNU_MALLOC || defined DOUG_LEA_MALLOC || defined __GLIBC__ || defined MAC_OSX 165#if defined GNU_MALLOC || defined DOUG_LEA_MALLOC || defined __GLIBC__ || defined MAC_OSX || defined(NS_IMPL_COCOA)
161/* We also need to be able to specify mult-of-8 alignment on static vars. */ 166/* We also need to be able to specify mult-of-8 alignment on static vars. */
162# if defined DECL_ALIGN 167# if defined DECL_ALIGN
163/* We currently do not support USE_LSB_TAG with a union Lisp_Object. */ 168/* We currently do not support USE_LSB_TAG with a union Lisp_Object. */
diff --git a/src/lread.c b/src/lread.c
index 6415448c0bc..6ec8dff6cfd 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -4095,7 +4095,7 @@ init_lread ()
4095 } 4095 }
4096#endif 4096#endif
4097 4097
4098#if (!(defined(WINDOWSNT) || (defined(HAVE_CARBON)))) 4098#if (!(defined(WINDOWSNT) || (defined(HAVE_CARBON)) || (defined(HAVE_NS))))
4099 /* When Emacs is invoked over network shares on NT, PATH_LOADSEARCH is 4099 /* When Emacs is invoked over network shares on NT, PATH_LOADSEARCH is
4100 almost never correct, thereby causing a warning to be printed out that 4100 almost never correct, thereby causing a warning to be printed out that
4101 confuses users. Since PATH_LOADSEARCH is always overridden by the 4101 confuses users. Since PATH_LOADSEARCH is always overridden by the
@@ -4125,7 +4125,7 @@ init_lread ()
4125 } 4125 }
4126 } 4126 }
4127 } 4127 }
4128#endif /* !(WINDOWSNT || HAVE_CARBON) */ 4128#endif /* !(WINDOWSNT || HAVE_CARBON || HAVE_NS) */
4129 4129
4130 /* If the EMACSLOADPATH environment variable is set, use its value. 4130 /* If the EMACSLOADPATH environment variable is set, use its value.
4131 This doesn't apply if we're dumping. */ 4131 This doesn't apply if we're dumping. */
diff --git a/src/menu.c b/src/menu.c
index e8bc8de1bfc..969225d4c72 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -36,6 +36,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
36#include "xterm.h" 36#include "xterm.h"
37#endif 37#endif
38 38
39#ifdef HAVE_NS
40#include "nsterm.h"
41#endif
42
39#ifdef USE_GTK 43#ifdef USE_GTK
40#include "gtkutil.h" 44#include "gtkutil.h"
41#endif 45#endif
@@ -440,7 +444,7 @@ single_menu_item (key, item, dummy, skp_v)
440 XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED], 444 XVECTOR (item_properties)->contents[ITEM_PROPERTY_SELECTED],
441 XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]); 445 XVECTOR (item_properties)->contents[ITEM_PROPERTY_HELP]);
442 446
443#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI) 447#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (HAVE_NTGUI)
444 /* Display a submenu using the toolkit. */ 448 /* Display a submenu using the toolkit. */
445 if (! (NILP (map) || NILP (enabled))) 449 if (! (NILP (map) || NILP (enabled)))
446 { 450 {
@@ -580,7 +584,7 @@ parse_single_submenu (item_key, item_name, maps)
580} 584}
581 585
582 586
583#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI) 587#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (HAVE_NTGUI)
584 588
585/* Allocate a widget_value, blocking input. */ 589/* Allocate a widget_value, blocking input. */
586 590
@@ -956,7 +960,71 @@ find_and_call_menu_selection (f, menu_bar_items_used, vector, client_data)
956 } 960 }
957} 961}
958 962
959#endif /* USE_X_TOOLKIT || USE_GTK || HAVE_NTGUI */ 963#endif /* USE_X_TOOLKIT || USE_GTK || HAVE_NS || HAVE_NTGUI */
964
965#ifdef HAVE_NS
966/* As above, but return the menu selection instead of storing in kb buffer.
967 If keymaps==1, return full prefixes to selection. */
968Lisp_Object
969find_and_return_menu_selection (FRAME_PTR f, int keymaps, void *client_data)
970{
971 Lisp_Object prefix, entry;
972 int i;
973 Lisp_Object *subprefix_stack;
974 int submenu_depth = 0;
975
976 prefix = entry = Qnil;
977 i = 0;
978 subprefix_stack =
979 (Lisp_Object *)alloca(menu_items_used * sizeof (Lisp_Object));
980
981 while (i < menu_items_used)
982 {
983 if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
984 {
985 subprefix_stack[submenu_depth++] = prefix;
986 prefix = entry;
987 i++;
988 }
989 else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
990 {
991 prefix = subprefix_stack[--submenu_depth];
992 i++;
993 }
994 else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
995 {
996 prefix
997 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
998 i += MENU_ITEMS_PANE_LENGTH;
999 }
1000 /* Ignore a nil in the item list.
1001 It's meaningful only for dialog boxes. */
1002 else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
1003 i += 1;
1004 else
1005 {
1006 entry
1007 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
1008 if ((int) (EMACS_INT)client_data == i)
1009 {
1010 if (keymaps != 0)
1011 {
1012 int j;
1013
1014 entry = Fcons (entry, Qnil);
1015 if (!NILP (prefix))
1016 entry = Fcons (prefix, entry);
1017 for (j = submenu_depth - 1; j >= 0; j--)
1018 if (!NILP (subprefix_stack[j]))
1019 entry = Fcons (subprefix_stack[j], entry);
1020 }
1021 return entry;
1022 }
1023 i += MENU_ITEMS_ITEM_LENGTH;
1024 }
1025 }
1026}
1027#endif
960 1028
961void 1029void
962syms_of_menu () 1030syms_of_menu ()
diff --git a/src/nsfns.m b/src/nsfns.m
new file mode 100644
index 00000000000..a39a8342bf9
--- /dev/null
+++ b/src/nsfns.m
@@ -0,0 +1,2668 @@
1/* Functions for the NeXT/Open/GNUstep and MacOSX window system.
2
3 Copyright (C) 1989, 1992, 1993, 1994, 2005, 2006, 2008
4 Free Software Foundation, Inc..
5
6This file is part of GNU Emacs.
7
8GNU Emacs is free software; you can redistribute it and/or modify
9it under the terms of the GNU General Public License as published by
10the Free Software Foundation; either version 3, or (at your option)
11any later version.
12
13GNU Emacs is distributed in the hope that it will be useful,
14but WITHOUT ANY WARRANTY; without even the implied warranty of
15MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16GNU General Public License for more details.
17
18You should have received a copy of the GNU General Public License
19along with GNU Emacs; see the file COPYING. If not, write to
20the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
21Boston, MA 02110-1301, USA.
22
23Originally by Carl Edman
24Updated by Christian Limpach (chris@nice.ch)
25OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com)
26MacOSX/Aqua port by Christophe de Dinechin (descubes@earthlink.net)
27GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
28
29*/
30
31#include <signal.h>
32#include <math.h>
33#include "config.h"
34#include "lisp.h"
35#include "blockinput.h"
36#include "nsterm.h"
37#include "window.h"
38#include "buffer.h"
39#include "keyboard.h"
40#include "termhooks.h"
41#include "fontset.h"
42
43#include "character.h"
44#include "font.h"
45
46#if 0
47int 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
53
54#ifdef HAVE_NS
55
56extern NSArray *ns_send_types, *ns_return_types, *ns_drag_types;
57
58extern Lisp_Object Qforeground_color;
59extern Lisp_Object Qbackground_color;
60extern Lisp_Object Qcursor_color;
61extern Lisp_Object Qinternal_border_width;
62extern Lisp_Object Qvisibility;
63extern Lisp_Object Qcursor_type;
64extern Lisp_Object Qicon_type;
65extern Lisp_Object Qicon_name;
66extern Lisp_Object Qicon_left;
67extern Lisp_Object Qicon_top;
68extern Lisp_Object Qleft;
69extern Lisp_Object Qright;
70extern Lisp_Object Qtop;
71extern Lisp_Object Qdisplay;
72extern Lisp_Object Qvertical_scroll_bars;
73extern Lisp_Object Qauto_raise;
74extern Lisp_Object Qauto_lower;
75extern Lisp_Object Qbox;
76extern Lisp_Object Qscroll_bar_width;
77extern Lisp_Object Qx_resource_name;
78extern Lisp_Object Qface_set_after_frame_default;
79extern Lisp_Object Qunderline, Qundefined;
80extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth;
81extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle;
82
83Lisp_Object Qnone;
84Lisp_Object Qns_frame_parameter;
85Lisp_Object Qbuffered;
86Lisp_Object Qfontsize;
87
88/* hack for OS X file panels */
89char panelOK = 0;
90
91/* Alist of elements (REGEXP . IMAGE) for images of icons associated
92 to frames.*/
93Lisp_Object Vns_icon_type_alist;
94
95EmacsTooltip *ns_tooltip;
96
97/* Need forward declaration here to preserve organizational integrity of file */
98Lisp_Object Fns_open_connection (Lisp_Object, Lisp_Object, Lisp_Object);
99
100extern BOOL ns_in_resize;
101
102
103/* ==========================================================================
104
105 Internal utility functions
106
107 ========================================================================== */
108
109
110void
111check_ns (void)
112{
113 if (NSApp == nil)
114 error ("OpenStep is not in use or not initialized");
115}
116
117
118/* Nonzero if we can use mouse menus. */
119int
120have_menus_p ()
121{
122 return NSApp != nil;
123}
124
125
126/* Extract a frame as a FRAME_PTR, defaulting to the selected frame
127 and checking validity for NS. */
128static FRAME_PTR
129check_ns_frame (Lisp_Object frame)
130{
131 FRAME_PTR f;
132
133 if (NILP (frame))
134 f = SELECTED_FRAME ();
135 else
136 {
137 CHECK_LIVE_FRAME (frame);
138 f = XFRAME (frame);
139 }
140 if (! FRAME_NS_P (f))
141 error ("non-NS frame used");
142 return f;
143}
144
145
146/* Let the user specify an NS display with a frame.
147 nil stands for the selected frame--or, if that is not an NS frame,
148 the first NS display on the list. */
149static struct ns_display_info *
150check_ns_display_info (Lisp_Object frame)
151{
152 if (NILP (frame))
153 {
154 struct frame *f = SELECTED_FRAME ();
155 if (FRAME_NS_P (f) && FRAME_LIVE_P (f) )
156 return FRAME_NS_DISPLAY_INFO (f);
157 else if (ns_display_list != 0)
158 return ns_display_list;
159 else
160 error ("NS windows are not in use or not initialized");
161 }
162 else if (INTEGERP (frame))
163 {
164 struct terminal *t = get_terminal (frame, 1);
165
166 if (t->type != output_ns)
167 error ("Terminal %d is not an NS display", XINT (frame));
168
169 return t->display_info.ns;
170 }
171 else if (STRINGP (frame))
172 return ns_display_info_for_name (frame);
173 else
174 {
175 FRAME_PTR f;
176
177 CHECK_LIVE_FRAME (frame);
178 f = XFRAME (frame);
179 if (! FRAME_NS_P (f))
180 error ("non-NS frame used");
181 return FRAME_NS_DISPLAY_INFO (f);
182 }
183 return NULL; /* shut compiler up */
184}
185
186
187static id
188ns_get_window (Lisp_Object maybeFrame)
189{
190 id view =nil, window =nil;
191
192 if (!FRAMEP (maybeFrame) || !FRAME_NS_P (XFRAME (maybeFrame)))
193 maybeFrame = selected_frame;/*wrong_type_argument (Qframep, maybeFrame); */
194
195 if (!NILP (maybeFrame))
196 view = FRAME_NS_VIEW (XFRAME (maybeFrame));
197 if (view) window =[view window];
198
199 return window;
200}
201
202
203static NSScreen *
204ns_get_screen (Lisp_Object anythingUnderTheSun)
205{
206 id window =nil;
207 NSScreen *screen = 0;
208
209 struct terminal *terminal;
210 struct ns_display_info *dpyinfo;
211 struct frame *f = NULL;
212 Lisp_Object frame;
213
214 if (INTEGERP (anythingUnderTheSun)) {
215 /* we got a terminal */
216 terminal = get_terminal (anythingUnderTheSun, 1);
217 dpyinfo = terminal->display_info.ns;
218 f = dpyinfo->ns_focus_frame;
219 if (!f)
220 f = dpyinfo->ns_highlight_frame;
221
222 } else if (FRAMEP (anythingUnderTheSun) &&
223 FRAME_NS_P (XFRAME (anythingUnderTheSun))) {
224 /* we got a frame */
225 f = XFRAME (anythingUnderTheSun);
226
227 } else if (STRINGP (anythingUnderTheSun)) { /* FIXME/cl for multi-display */
228 }
229
230 if (!f)
231 f = SELECTED_FRAME ();
232 if (f)
233 {
234 XSETFRAME (frame, f);
235 window = ns_get_window (frame);
236 }
237
238 if (window)
239 screen = [window screen];
240 if (!screen)
241 screen = [NSScreen mainScreen];
242
243 return screen;
244}
245
246
247/* Return the X display structure for the display named NAME.
248 Open a new connection if necessary. */
249struct ns_display_info *
250ns_display_info_for_name (name)
251 Lisp_Object name;
252{
253 Lisp_Object names;
254 struct ns_display_info *dpyinfo;
255
256 CHECK_STRING (name);
257
258 for (dpyinfo = ns_display_list, names = ns_display_name_list;
259 dpyinfo;
260 dpyinfo = dpyinfo->next, names = XCDR (names))
261 {
262 Lisp_Object tem;
263 tem = Fstring_equal (XCAR (XCAR (names)), name);
264 if (!NILP (tem))
265 return dpyinfo;
266 }
267
268 error ("Emacs for OpenStep does not yet support multi-display.");
269
270 Fns_open_connection (name, Qnil, Qnil);
271 dpyinfo = ns_display_list;
272
273 if (dpyinfo == 0)
274 error ("OpenStep on %s not responding.\n", XSTRING (name)->data);
275
276 return dpyinfo;
277}
278
279
280static Lisp_Object
281interpret_services_menu (NSMenu *menu, Lisp_Object prefix, Lisp_Object old)
282/* --------------------------------------------------------------------------
283 Turn the input menu (an NSMenu) into a lisp list for tracking on lisp side
284 -------------------------------------------------------------------------- */
285{
286 int i, count;
287 id<NSMenuItem> item;
288 const char *name;
289 Lisp_Object nameStr;
290 unsigned short key;
291 NSString *keys;
292 Lisp_Object res;
293
294 count = [menu numberOfItems];
295 for (i = 0; i<count; i++)
296 {
297 item = [menu itemAtIndex: i];
298 name = [[item title] UTF8String];
299 if (!name) continue;
300
301 nameStr = build_string (name);
302
303 if ([item hasSubmenu])
304 {
305 old = interpret_services_menu ([item submenu],
306 Fcons (nameStr, prefix), old);
307 }
308 else
309 {
310 keys = [item keyEquivalent];
311 if (keys && [keys length] )
312 {
313 key = [keys characterAtIndex: 0];
314 res = make_number (key|super_modifier);
315 }
316 else
317 {
318 res = Qundefined;
319 }
320 old = Fcons (Fcons (res,
321 Freverse (Fcons (nameStr,
322 prefix))),
323 old);
324 }
325 }
326 return old;
327}
328
329
330
331/* ==========================================================================
332
333 Frame parameter setters
334
335 ========================================================================== */
336
337
338static void
339ns_set_foreground_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
340{
341 NSColor *col;
342
343 if (ns_lisp_to_color (arg, &col))
344 {
345 store_frame_param (f, Qforeground_color, oldval);
346 error ("Unknown color");
347 }
348
349 [col retain];
350 [f->output_data.ns->foreground_color release];
351 f->output_data.ns->foreground_color = col;
352
353 if (FRAME_NS_VIEW (f))
354 {
355 update_face_from_frame_parameter (f, Qforeground_color, arg);
356 /*recompute_basic_faces (f); */
357 if (FRAME_VISIBLE_P (f))
358 redraw_frame (f);
359 }
360}
361
362
363static void
364ns_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
365{
366 struct face *face;
367 NSColor *col;
368 NSView *view = FRAME_NS_VIEW (f);
369 float alpha;
370
371 if (ns_lisp_to_color (arg, &col))
372 {
373 store_frame_param (f, Qbackground_color, oldval);
374 error ("Unknown color");
375 }
376
377 /* clear the frame; in some instances the NS-internal GC appears not to
378 update, or it does update and cannot clear old text properly */
379 if (FRAME_VISIBLE_P (f))
380 ns_clear_frame (f);
381
382 [col retain];
383 [f->output_data.ns->background_color release];
384 f->output_data.ns->background_color = col;
385 if (view != nil)
386 {
387 [[view window] setBackgroundColor: col];
388 alpha = [col alphaComponent];
389
390#ifdef NS_IMPL_COCOA
391 /* the alpha code below only works on 10.4, so we need to do something
392 else (albeit less good) otherwise.
393 Check NSApplication.h for useful NSAppKitVersionNumber values. */
394 if (NSAppKitVersionNumber < 744.0)
395 [[view window] setAlphaValue: alpha];
396#endif
397
398 if (alpha != 1.0)
399 [[view window] setOpaque: NO];
400 else
401 [[view window] setOpaque: YES];
402
403 face = FRAME_DEFAULT_FACE (f);
404 if (face)
405 {
406 col = NS_FACE_BACKGROUND (face);
407 face->background =
408 (EMACS_UINT) [[col colorWithAlphaComponent: alpha] retain];
409 [col release];
410
411 update_face_from_frame_parameter (f, Qbackground_color, arg);
412 }
413
414 if (FRAME_VISIBLE_P (f))
415 redraw_frame (f);
416 }
417}
418
419
420static void
421ns_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
422{
423 NSColor *col;
424
425 if (ns_lisp_to_color (arg, &col))
426 {
427 store_frame_param (f, Qcursor_color, oldval);
428 error ("Unknown color");
429 }
430
431 [f->output_data.ns->desired_cursor_color release];
432 f->output_data.ns->desired_cursor_color = [col retain];
433
434 if (FRAME_VISIBLE_P (f))
435 {
436 x_update_cursor (f, 0);
437 x_update_cursor (f, 1);
438 }
439 update_face_from_frame_parameter (f, Qcursor_color, arg);
440}
441
442
443static void
444ns_set_icon_name (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
445{
446 NSView *view = FRAME_NS_VIEW (f);
447 NSTRACE (ns_set_icon_name);
448
449 if (ns_in_resize)
450 return;
451
452 /* see if it's changed */
453 if (STRINGP (arg))
454 {
455 if (STRINGP (oldval) && EQ (Fstring_equal (oldval, arg), Qt))
456 return;
457 }
458 else if (!STRINGP (oldval) && EQ (oldval, Qnil) == EQ (arg, Qnil))
459 return;
460
461 f->icon_name = arg;
462
463 if (NILP (arg))
464 {
465 if (!NILP (f->title))
466 arg = f->title;
467 else
468 /* explicit name and no icon-name -> explicit_name */
469 if (f->explicit_name)
470 arg = f->name;
471 else
472 {
473 /* no explicit name and no icon-name ->
474 name has to be rebuild from icon_title_format */
475 windows_or_buffers_changed++;
476 return;
477 }
478 }
479
480 /* Don't change the name if it's already NAME. */
481 if ([[view window] miniwindowTitle] &&
482 ([[[view window] miniwindowTitle]
483 isEqualToString: [NSString stringWithUTF8String:
484 XSTRING (arg)->data]]))
485 return;
486
487 [[view window] setMiniwindowTitle:
488 [NSString stringWithUTF8String: XSTRING (arg)->data]];
489}
490
491
492static void
493ns_set_name_iconic (struct frame *f, Lisp_Object name, int explicit)
494{
495 NSView *view = FRAME_NS_VIEW (f);
496 NSTRACE (ns_set_name_iconic);
497
498 if (ns_in_resize)
499 return;
500
501 /* Make sure that requests from lisp code override requests from
502 Emacs redisplay code. */
503 if (explicit)
504 {
505 /* If we're switching from explicit to implicit, we had better
506 update the mode lines and thereby update the title. */
507 if (f->explicit_name && NILP (name))
508 update_mode_lines = 1;
509
510 f->explicit_name = ! NILP (name);
511 }
512 else if (f->explicit_name)
513 name = f->name;
514
515 /* title overrides explicit name */
516 if (! NILP (f->title))
517 name = f->title;
518
519 /* icon_name overrides title and explicit name */
520 if (! NILP (f->icon_name))
521 name = f->icon_name;
522
523 if (NILP (name))
524 name = build_string
525 ([[[NSProcessInfo processInfo] processName] UTF8String]);
526 else
527 CHECK_STRING (name);
528
529 /* Don't change the name if it's already NAME. */
530 if ([[view window] miniwindowTitle] &&
531 ([[[view window] miniwindowTitle]
532 isEqualToString: [NSString stringWithUTF8String:
533 XSTRING (name)->data]]))
534 return;
535
536 [[view window] setMiniwindowTitle:
537 [NSString stringWithUTF8String: XSTRING (name)->data]];
538}
539
540
541static void
542ns_set_name (struct frame *f, Lisp_Object name, int explicit)
543{
544 NSView *view = FRAME_NS_VIEW (f);
545 NSTRACE (ns_set_name);
546
547 if (ns_in_resize)
548 return;
549
550 /* Make sure that requests from lisp code override requests from
551 Emacs redisplay code. */
552 if (explicit)
553 {
554 /* If we're switching from explicit to implicit, we had better
555 update the mode lines and thereby update the title. */
556 if (f->explicit_name && NILP (name))
557 update_mode_lines = 1;
558
559 f->explicit_name = ! NILP (name);
560 }
561 else if (f->explicit_name)
562 return;
563
564 if (NILP (name))
565 name = build_string
566 ([[[NSProcessInfo processInfo] processName] UTF8String]);
567
568 f->name = name;
569
570 /* title overrides explicit name */
571 if (! NILP (f->title))
572 name = f->title;
573
574 CHECK_STRING (name);
575
576 /* Don't change the name if it's already NAME. */
577 if ([[[view window] title]
578 isEqualToString: [NSString stringWithUTF8String:
579 XSTRING (name)->data]])
580 return;
581 [[view window] setTitle: [NSString stringWithUTF8String:
582 XSTRING (name)->data]];
583}
584
585
586/* This function should be called when the user's lisp code has
587 specified a name for the frame; the name will override any set by the
588 redisplay code. */
589static void
590ns_explicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
591{
592 NSTRACE (ns_explicitly_set_name);
593 ns_set_name_iconic (f, arg, 1);
594 ns_set_name (f, arg, 1);
595}
596
597
598/* This function should be called by Emacs redisplay code to set the
599 name; names set this way will never override names set by the user's
600 lisp code. */
601void
602x_implicitly_set_name (FRAME_PTR f, Lisp_Object arg, Lisp_Object oldval)
603{
604 NSTRACE (x_implicitly_set_name);
605 if (FRAME_ICONIFIED_P (f))
606 ns_set_name_iconic (f, arg, 0);
607 else
608 ns_set_name (f, arg, 0);
609}
610
611
612/* Change the title of frame F to NAME.
613 If NAME is nil, use the frame name as the title.
614
615 If EXPLICIT is non-zero, that indicates that lisp code is setting the
616 name; if NAME is a string, set F's name to NAME and set
617 F->explicit_name; if NAME is Qnil, then clear F->explicit_name.
618
619 If EXPLICIT is zero, that indicates that Emacs redisplay code is
620 suggesting a new name, which lisp code should override; if
621 F->explicit_name is set, ignore the new name; otherwise, set it. */
622static void
623ns_set_title (struct frame *f, Lisp_Object name, Lisp_Object old_name)
624{
625 NSTRACE (ns_set_title);
626 /* Don't change the title if it's already NAME. */
627 if (EQ (name, f->title))
628 return;
629
630 update_mode_lines = 1;
631
632 f->title = name;
633}
634
635
636void
637ns_set_name_as_filename (struct frame *f)
638{
639 NSView *view = FRAME_NS_VIEW (f);
640 Lisp_Object name;
641 Lisp_Object buf = XWINDOW (f->selected_window)->buffer;
642 const char *title;
643 NSAutoreleasePool *pool;
644 NSTRACE (ns_set_name_as_filename);
645
646 if (f->explicit_name || ! NILP (f->title) || ns_in_resize)
647 return;
648
649 BLOCK_INPUT;
650 pool = [[NSAutoreleasePool alloc] init];
651 name =XBUFFER (buf)->filename;
652 if (NILP (name) || FRAME_ICONIFIED_P (f)) name =XBUFFER (buf)->name;
653
654 if (FRAME_ICONIFIED_P (f) && !NILP (f->icon_name))
655 name = f->icon_name;
656
657 if (NILP (name))
658 name = build_string
659 ([[[NSProcessInfo processInfo] processName] UTF8String]);
660 else
661 CHECK_STRING (name);
662
663 title = FRAME_ICONIFIED_P (f) ? [[[view window] miniwindowTitle] UTF8String]
664 : [[[view window] title] UTF8String];
665
666 if (title && (! strcmp (title, XSTRING (name)->data)))
667 {
668 [pool release];
669 UNBLOCK_INPUT;
670 return;
671 }
672
673 if (! FRAME_ICONIFIED_P (f))
674 {
675#ifdef NS_IMPL_COCOA
676 /* work around a bug observed on 10.3 where
677 setTitleWithRepresentedFilename does not clear out previous state
678 if given filename does not exist */
679 NSString *str = [NSString stringWithUTF8String: XSTRING (name)->data];
680 if (![[NSFileManager defaultManager] fileExistsAtPath: str])
681 {
682 [[view window] setTitleWithRepresentedFilename: @""];
683 [[view window] setTitle: str];
684 }
685 else
686 {
687 [[view window] setTitleWithRepresentedFilename: str];
688 }
689#else
690 [[view window] setTitleWithRepresentedFilename:
691 [NSString stringWithUTF8String: XSTRING (name)->data]];
692#endif
693 f->name = name;
694 }
695 else
696 {
697 [[view window] setMiniwindowTitle:
698 [NSString stringWithUTF8String: XSTRING (name)->data]];
699 }
700 [pool release];
701 UNBLOCK_INPUT;
702}
703
704
705void
706ns_set_doc_edited (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
707{
708 NSView *view = FRAME_NS_VIEW (f);
709 NSAutoreleasePool *pool;
710 BLOCK_INPUT;
711 pool = [[NSAutoreleasePool alloc] init];
712 [[view window] setDocumentEdited: !NILP (arg)];
713 [pool release];
714 UNBLOCK_INPUT;
715}
716
717
718static void
719ns_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
720{
721 int nlines;
722 int olines = FRAME_MENU_BAR_LINES (f);
723 if (FRAME_MINIBUF_ONLY_P (f))
724 return;
725
726 if (INTEGERP (value))
727 nlines = XINT (value);
728 else
729 nlines = 0;
730
731 FRAME_MENU_BAR_LINES (f) = 0;
732 if (nlines)
733 {
734 FRAME_EXTERNAL_MENU_BAR (f) = 1;
735/* does for all frames, whereas we just want for one frame
736 [NSMenu setMenuBarVisible: YES]; */
737 }
738 else
739 {
740 if (FRAME_EXTERNAL_MENU_BAR (f) == 1)
741 free_frame_menubar (f);
742/* [NSMenu setMenuBarVisible: NO]; */
743 FRAME_EXTERNAL_MENU_BAR (f) = 0;
744 }
745}
746
747
748/* 23: PENDING: there is an erroneous direct call in window.c to this fn */
749void
750x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
751{
752 ns_set_menu_bar_lines (f, value, oldval);
753}
754
755
756/* 23: toolbar support */
757static void
758ns_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
759{
760 int nlines;
761 Lisp_Object root_window;
762
763 if (FRAME_MINIBUF_ONLY_P (f))
764 return;
765
766 if (INTEGERP (value) && XINT (value) >= 0)
767 nlines = XFASTINT (value);
768 else
769 nlines = 0;
770
771 if (nlines)
772 {
773 FRAME_EXTERNAL_TOOL_BAR (f) = 1;
774 update_frame_tool_bar (f);
775 }
776 else
777 {
778 if (FRAME_EXTERNAL_TOOL_BAR (f))
779 {
780 free_frame_tool_bar (f);
781 FRAME_EXTERNAL_TOOL_BAR (f) = 0;
782 }
783 }
784
785 x_set_window_size (f, 0, f->text_cols, f->text_lines);
786}
787
788
789/* 23: PENDING: there is an erroneous direct call in window.c to this fn */
790void
791x_set_tool_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
792{
793 ns_set_tool_bar_lines (f, value, oldval);
794}
795
796
797void
798ns_implicitly_set_icon_type (struct frame *f)
799{
800 Lisp_Object tem;
801 EmacsView *view = FRAME_NS_VIEW (f);
802 id image =nil;
803 Lisp_Object chain, elt;
804 NSAutoreleasePool *pool;
805 BOOL setMini = YES;
806
807 NSTRACE (ns_implicitly_set_icon_type);
808
809 BLOCK_INPUT;
810 pool = [[NSAutoreleasePool alloc] init];
811 if (f->output_data.ns->miniimage
812 && [[NSString stringWithUTF8String: XSTRING (f->name)->data]
813 isEqualToString: [(NSImage *)f->output_data.ns->miniimage name]])
814 {
815 [pool release];
816 UNBLOCK_INPUT;
817 return;
818 }
819
820 tem = assq_no_quit (Qicon_type, f->param_alist);
821 if (CONSP (tem) && ! NILP (XCDR (tem)))
822 {
823 [pool release];
824 UNBLOCK_INPUT;
825 return;
826 }
827
828 for (chain = Vns_icon_type_alist;
829 (image = nil) && CONSP (chain);
830 chain = XCDR (chain))
831 {
832 elt = XCAR (chain);
833 /* special case: 't' means go by file type */
834 if (SYMBOLP (elt) && elt == Qt && XSTRING (f->name)->data[0] == '/')
835 {
836 NSString *str =
837 [NSString stringWithUTF8String: XSTRING (f->name)->data];
838 if ([[NSFileManager defaultManager] fileExistsAtPath: str])
839 image = [[[NSWorkspace sharedWorkspace] iconForFile: str] retain];
840 }
841 else if (CONSP (elt) &&
842 STRINGP (XCAR (elt)) &&
843 STRINGP (XCDR (elt)) &&
844 fast_string_match (XCAR (elt), f->name) >= 0)
845 {
846 image = [EmacsImage allocInitFromFile: XCDR (elt)];
847 if (image == nil)
848 image = [[NSImage imageNamed:
849 [NSString stringWithUTF8String:
850 XSTRING (XCDR (elt))->data]] retain];
851 }
852 }
853
854 if (image == nil)
855 {
856 image = [[[NSWorkspace sharedWorkspace] iconForFileType: @"text"] retain];
857 setMini = NO;
858 }
859
860 [f->output_data.ns->miniimage release];
861 f->output_data.ns->miniimage = image;
862 [view setMiniwindowImage: setMini];
863 [pool release];
864 UNBLOCK_INPUT;
865}
866
867
868static void
869ns_set_icon_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
870{
871 EmacsView *view = FRAME_NS_VIEW (f);
872 id image = nil;
873 BOOL setMini = YES;
874
875 NSTRACE (ns_set_icon_type);
876
877 if (!NILP (arg) && SYMBOLP (arg))
878 {
879 arg =build_string (XSTRING (XSYMBOL (arg)->xname)->data);
880 store_frame_param (f, Qicon_type, arg);
881 }
882
883 /* do it the implicit way */
884 if (NILP (arg))
885 {
886 ns_implicitly_set_icon_type (f);
887 return;
888 }
889
890 CHECK_STRING (arg);
891
892 image = [EmacsImage allocInitFromFile: arg];
893 if (image == nil)
894 image =[NSImage imageNamed: [NSString stringWithUTF8String:
895 XSTRING (arg)->data]];
896
897 if (image == nil)
898 {
899 image = [NSImage imageNamed: @"text"];
900 setMini = NO;
901 }
902
903 f->output_data.ns->miniimage = image;
904 [view setMiniwindowImage: setMini];
905}
906
907
908/* 23: added Xism; we stub out (we do implement this in ns-win.el) */
909int
910XParseGeometry (char *string, int *x, int *y,
911 unsigned int *width, unsigned int *height)
912{
913 message1 ("Warning: XParseGeometry not supported under NS.\n");
914 return 0;
915}
916
917
918/*PENDING: move to nsterm? */
919int
920ns_lisp_to_cursor_type (Lisp_Object arg)
921{
922 char *str;
923 if (XTYPE (arg) == Lisp_String)
924 str =XSTRING (arg)->data;
925 else if (XTYPE (arg) == Lisp_Symbol)
926 str =XSTRING (XSYMBOL (arg)->xname)->data;
927 else return -1;
928 if (!strcmp (str, "box")) return filled_box;
929 if (!strcmp (str, "hollow")) return hollow_box;
930 if (!strcmp (str, "underscore")) return underscore;
931 if (!strcmp (str, "bar")) return bar;
932 if (!strcmp (str, "no")) return no_highlight;
933 return -1;
934}
935
936
937Lisp_Object
938ns_cursor_type_to_lisp (int arg)
939{
940 switch (arg)
941 {
942 case filled_box: return Qbox;
943 case hollow_box: return intern ("hollow");
944 case underscore: return intern ("underscore");
945 case bar: return intern ("bar");
946 case no_highlight:
947 default: return intern ("no");
948 }
949}
950
951
952static void
953ns_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
954{
955 int val;
956
957 val = ns_lisp_to_cursor_type (arg);
958 if (val >= 0)
959 {
960 f->output_data.ns->desired_cursor =val;
961 }
962 else
963 {
964 store_frame_param (f, Qcursor_type, oldval);
965 error ("the `cursor-type' frame parameter should be either `no', `box', \
966`hollow', `underscore' or `bar'.");
967 }
968
969 update_mode_lines++;
970}
971
972
973/* 23: called to set mouse pointer color, but all other terms use it to
974 initialize pointer types (and don't set the color ;) */
975static void
976ns_set_mouse_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval)
977{
978 /* don't think we can do this on NS */
979}
980
981
982static void
983ns_icon (struct frame *f, Lisp_Object parms)
984/* --------------------------------------------------------------------------
985 Strangely-named function to set icon position parameters in frame.
986 This is irrelevant under OS X, but might be needed under GNUstep,
987 depending on the window manager used. Note, this is not a standard
988 frame parameter-setter; it is called directly from x-create-frame.
989 -------------------------------------------------------------------------- */
990{
991 Lisp_Object icon_x, icon_y;
992 struct ns_display_info *dpyinfo = check_ns_display_info (Qnil);
993
994 f->output_data.ns->icon_top = Qnil;
995 f->output_data.ns->icon_left = Qnil;
996
997 /* Set the position of the icon. */
998 icon_x = x_get_arg (dpyinfo, parms, Qicon_left, 0, 0, RES_TYPE_NUMBER);
999 icon_y = x_get_arg (dpyinfo, parms, Qicon_top, 0, 0, RES_TYPE_NUMBER);
1000 if (!EQ (icon_x, Qunbound) && !EQ (icon_y, Qunbound))
1001 {
1002 CHECK_NUMBER (icon_x);
1003 CHECK_NUMBER (icon_y);
1004 f->output_data.ns->icon_top = icon_y;
1005 f->output_data.ns->icon_left = icon_x;
1006 }
1007 else if (!EQ (icon_x, Qunbound) || !EQ (icon_y, Qunbound))
1008 error ("Both left and top icon corners of icon must be specified");
1009}
1010
1011
1012/* 23 Note: commented out ns_... entries are no longer used in 23.
1013 commented out x_... entries have not been implemented yet.
1014 see frame.c for template, also where all generic OK functions are impl */
1015frame_parm_handler ns_frame_parm_handlers[] =
1016{
1017 x_set_autoraise, /* generic OK */
1018 x_set_autolower, /* generic OK */
1019 ns_set_background_color,
1020 0, /* x_set_border_color, may be impossible under NS */
1021 0, /* x_set_border_width, may be impossible under NS */
1022 ns_set_cursor_color,
1023 ns_set_cursor_type,
1024 x_set_font, /* generic OK */
1025 ns_set_foreground_color,
1026 ns_set_icon_name,
1027 ns_set_icon_type,
1028 x_set_internal_border_width, /* generic OK */
1029 ns_set_menu_bar_lines,
1030 ns_set_mouse_color,
1031 ns_explicitly_set_name,
1032 x_set_scroll_bar_width, /* generic OK */
1033 ns_set_title,
1034 x_set_unsplittable, /* generic OK */
1035 x_set_vertical_scroll_bars, /* generic OK */
1036 x_set_visibility, /* generic OK */
1037 ns_set_tool_bar_lines,
1038 0, /* x_set_scroll_bar_foreground, will ignore (not possible on NS) */
1039 0, /* x_set_scroll_bar_background, will ignore (not possible on NS) */
1040 x_set_screen_gamma, /* generic OK */
1041 x_set_line_spacing, /* generic OK, sets f->extra_line_spacing to int */
1042 x_set_fringe_width, /* generic OK */
1043 x_set_fringe_width, /* generic OK */
1044 0, /* x_set_wait_for_wm, will ignore */
1045 0, /* x_set_fullscreen will ignore */
1046 x_set_font_backend /* generic OK */
1047};
1048
1049
1050DEFUN ("x-create-frame", Fns_create_frame, Sns_create_frame,
1051 1, 1, 0,
1052 "Make a new NS window, which is called a \"frame\" in Emacs terms.\n\
1053Return an Emacs frame object representing the X window.\n\
1054ALIST is an alist of frame parameters.\n\
1055If the parameters specify that the frame should not have a minibuffer,\n\
1056and do not specify a specific minibuffer window to use,\n\
1057then `default-minibuffer-frame' must be a frame whose minibuffer can\n\
1058be shared by the new frame.")
1059 (parms)
1060 Lisp_Object parms;
1061{
1062 static int desc_ctr = 1;
1063 struct frame *f;
1064 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
1065 Lisp_Object frame, tem;
1066 Lisp_Object name;
1067 int minibuffer_only = 0;
1068 int count = specpdl_ptr - specpdl;
1069 Lisp_Object display;
1070 struct ns_display_info *dpyinfo = NULL;
1071 Lisp_Object parent;
1072 struct kboard *kb;
1073 Lisp_Object tfont, tfontsize;
1074 int window_prompting = 0;
1075 int width, height;
1076
1077 check_ns ();
1078
1079 display = x_get_arg (dpyinfo, parms, Qterminal, 0, 0, RES_TYPE_STRING);
1080 if (EQ (display, Qunbound))
1081 display = Qnil;
1082 dpyinfo = check_ns_display_info (display);
1083
1084 if (!dpyinfo->terminal->name)
1085 error ("Terminal is not live, can't create new frames on it");
1086
1087 kb = dpyinfo->terminal->kboard;
1088
1089 name = x_get_arg (dpyinfo, parms, Qname, 0, 0, RES_TYPE_STRING);
1090 if (!STRINGP (name)
1091 && ! EQ (name, Qunbound)
1092 && ! NILP (name))
1093 error ("Invalid frame name--not a string or nil");
1094
1095 if (STRINGP (name))
1096 Vx_resource_name = name;
1097
1098 parent = x_get_arg (dpyinfo, parms, Qparent_id, 0, 0, RES_TYPE_NUMBER);
1099 if (EQ (parent, Qunbound))
1100 parent = Qnil;
1101 if (! NILP (parent))
1102 CHECK_NUMBER (parent);
1103
1104 frame = Qnil;
1105 GCPRO4 (parms, parent, name, frame);
1106
1107 tem = x_get_arg (dpyinfo, parms, Qminibuffer, "minibuffer", "Minibuffer",
1108 RES_TYPE_SYMBOL);
1109 if (EQ (tem, Qnone) || NILP (tem))
1110 {
1111 f = make_frame_without_minibuffer (Qnil, kb, display);
1112 }
1113 else if (EQ (tem, Qonly))
1114 {
1115 f = make_minibuffer_frame ();
1116 minibuffer_only = 1;
1117 }
1118 else if (WINDOWP (tem))
1119 {
1120 f = make_frame_without_minibuffer (tem, kb, display);
1121 }
1122 else
1123 {
1124 f = make_frame (1);
1125 }
1126
1127 /* Set the name; the functions to which we pass f expect the name to
1128 be set. */
1129 if (EQ (name, Qunbound) || NILP (name) || (XTYPE (name) != Lisp_String))
1130 {
1131 f->name =
1132 build_string ([[[NSProcessInfo processInfo] processName] UTF8String]);
1133 f->explicit_name =0;
1134 }
1135 else
1136 {
1137 f->name = name;
1138 f->explicit_name = 1;
1139 specbind (Qx_resource_name, name);
1140 }
1141
1142 XSETFRAME (frame, f);
1143 FRAME_CAN_HAVE_SCROLL_BARS (f) = 1;
1144
1145 f->terminal = dpyinfo->terminal;
1146 f->terminal->reference_count++;
1147
1148 f->output_method = output_ns;
1149 f->output_data.ns = (struct ns_output *)xmalloc (sizeof *(f->output_data.ns));
1150 bzero (f->output_data.ns, sizeof (*(f->output_data.ns)));
1151
1152 FRAME_FONTSET (f) = -1;
1153
1154 /* record_unwind_protect (unwind_create_frame, frame); safety; maybe later? */
1155
1156 f->icon_name = x_get_arg (dpyinfo, parms, Qicon_name, "iconName", "Title",
1157 RES_TYPE_STRING);
1158 if (EQ (f->icon_name, Qunbound) || (XTYPE (f->icon_name) != Lisp_String))
1159 f->icon_name = Qnil;
1160
1161 FRAME_NS_DISPLAY_INFO (f) = dpyinfo;
1162
1163 f->output_data.ns->window_desc = desc_ctr++;
1164 if (!NILP (parent))
1165 {
1166 f->output_data.ns->parent_desc = (Window) XFASTINT (parent);
1167 f->output_data.ns->explicit_parent = 1;
1168 }
1169 else
1170 {
1171 f->output_data.ns->parent_desc = FRAME_NS_DISPLAY_INFO (f)->root_window;
1172 f->output_data.ns->explicit_parent = 0;
1173 }
1174
1175 f->resx = dpyinfo->resx;
1176 f->resy = dpyinfo->resy;
1177
1178 BLOCK_INPUT;
1179 register_font_driver (&nsfont_driver, f);
1180 x_default_parameter (f, parms, Qfont_backend, Qnil,
1181 "fontBackend", "FontBackend", RES_TYPE_STRING);
1182
1183 {
1184 /* use for default font name */
1185 id font = [NSFont userFixedPitchFontOfSize: -1.0]; /* default */
1186 tfontsize = x_default_parameter (f, parms, Qfontsize,
1187 make_number (0 /*(int)[font pointSize]*/),
1188 "fontSize", "FontSize", RES_TYPE_NUMBER);
1189 tfont = x_default_parameter (f, parms, Qfont,
1190 build_string ([[font fontName] UTF8String]),
1191 "font", "Font", RES_TYPE_STRING);
1192 }
1193 UNBLOCK_INPUT;
1194
1195 x_default_parameter (f, parms, Qborder_width, make_number (0),
1196 "borderwidth", "BorderWidth", RES_TYPE_NUMBER);
1197 x_default_parameter (f, parms, Qinternal_border_width, make_number (2),
1198 "internalBorderWidth", "InternalBorderWidth",
1199 RES_TYPE_NUMBER);
1200
1201 /* default scrollbars on right on Mac */
1202 {
1203 Lisp_Object spos =
1204#ifdef NS_IMPL_GNUSTEP
1205 Qt;
1206#else
1207 Qright;
1208#endif
1209 x_default_parameter (f, parms, Qvertical_scroll_bars, spos,
1210 "verticalScrollBars", "VerticalScrollBars",
1211 RES_TYPE_SYMBOL);
1212 }
1213 x_default_parameter (f, parms, Qforeground_color, build_string ("Black"),
1214 "foreground", "Foreground", RES_TYPE_STRING);
1215 x_default_parameter (f, parms, Qbackground_color, build_string ("White"),
1216 "background", "Background", RES_TYPE_STRING);
1217 x_default_parameter (f, parms, Qcursor_color, build_string ("grey"),
1218 "cursorColor", "CursorColor", RES_TYPE_STRING);
1219 /*PENDING: not suppported yet in NS */
1220 x_default_parameter (f, parms, Qline_spacing, Qnil,
1221 "lineSpacing", "LineSpacing", RES_TYPE_NUMBER);
1222 x_default_parameter (f, parms, Qleft_fringe, Qnil,
1223 "leftFringe", "LeftFringe", RES_TYPE_NUMBER);
1224 x_default_parameter (f, parms, Qright_fringe, Qnil,
1225 "rightFringe", "RightFringe", RES_TYPE_NUMBER);
1226 /* end PENDING */
1227
1228 init_frame_faces (f);
1229
1230 x_default_parameter (f, parms, Qmenu_bar_lines, make_number (0), "menuBar",
1231 "menuBar", RES_TYPE_NUMBER);
1232 x_default_parameter (f, parms, Qtool_bar_lines, make_number (0), "toolBar",
1233 "toolBar", RES_TYPE_NUMBER);
1234 x_default_parameter (f, parms, Qbuffer_predicate, Qnil, "bufferPredicate",
1235 "BufferPredicate", RES_TYPE_SYMBOL);
1236 x_default_parameter (f, parms, Qtitle, Qnil, "title", "Title",
1237 RES_TYPE_STRING);
1238
1239/*PENDING: other terms seem to get away w/o this complexity.. */
1240 if (NILP (Fassq (Qwidth, parms)))
1241 {
1242 Lisp_Object value =
1243 x_get_arg (dpyinfo, parms, Qwidth, "width", "Width", RES_TYPE_NUMBER);
1244 if (! EQ (value, Qunbound))
1245 parms = Fcons (Fcons (Qwidth, value), parms);
1246 }
1247 if (NILP (Fassq (Qheight, parms)))
1248 {
1249 Lisp_Object value =
1250 x_get_arg (dpyinfo, parms, Qheight, "height", "Height",
1251 RES_TYPE_NUMBER);
1252 if (! EQ (value, Qunbound))
1253 parms = Fcons (Fcons (Qheight, value), parms);
1254 }
1255 if (NILP (Fassq (Qleft, parms)))
1256 {
1257 Lisp_Object value =
1258 x_get_arg (dpyinfo, parms, Qleft, "left", "Left", RES_TYPE_NUMBER);
1259 if (! EQ (value, Qunbound))
1260 parms = Fcons (Fcons (Qleft, value), parms);
1261 }
1262 if (NILP (Fassq (Qtop, parms)))
1263 {
1264 Lisp_Object value =
1265 x_get_arg (dpyinfo, parms, Qtop, "top", "Top", RES_TYPE_NUMBER);
1266 if (! EQ (value, Qunbound))
1267 parms = Fcons (Fcons (Qtop, value), parms);
1268 }
1269
1270 window_prompting = x_figure_window_size (f, parms, 1);
1271
1272 tem = x_get_arg (dpyinfo, parms, Qunsplittable, 0, 0, RES_TYPE_BOOLEAN);
1273 f->no_split = minibuffer_only || (!EQ (tem, Qunbound) && !EQ (tem, Qnil));
1274
1275 /* NOTE: on other terms, this is done in set_mouse_color, however this
1276 was not getting called under NS */
1277 f->output_data.ns->text_cursor = [NSCursor IBeamCursor];
1278 f->output_data.ns->nontext_cursor = [NSCursor arrowCursor];
1279 f->output_data.ns->modeline_cursor = [NSCursor pointingHandCursor];
1280 f->output_data.ns->hand_cursor = [NSCursor pointingHandCursor];
1281 f->output_data.ns->hourglass_cursor = [NSCursor disappearingItemCursor];
1282 f->output_data.ns->horizontal_drag_cursor = [NSCursor resizeLeftRightCursor];
1283 FRAME_NS_DISPLAY_INFO (f)->vertical_scroll_bar_cursor =
1284 [NSCursor arrowCursor];
1285 f->output_data.ns->current_pointer = f->output_data.ns->text_cursor;
1286
1287 [[EmacsView alloc] initFrameFromEmacs: f];
1288
1289 ns_icon (f, parms);
1290
1291 /* It is now ok to make the frame official even if we get an error below.
1292 The frame needs to be on Vframe_list or making it visible won't work. */
1293 Vframe_list = Fcons (frame, Vframe_list);
1294 /*FRAME_NS_DISPLAY_INFO (f)->reference_count++; */
1295
1296 x_default_parameter (f, parms, Qcursor_type, Qbox, "cursorType", "CursorType",
1297 RES_TYPE_SYMBOL);
1298 x_default_parameter (f, parms, Qscroll_bar_width, Qnil, "scrollBarWidth",
1299 "ScrollBarWidth", RES_TYPE_NUMBER);
1300 x_default_parameter (f, parms, Qicon_type, Qnil, "bitmapIcon", "BitmapIcon",
1301 RES_TYPE_SYMBOL);
1302 x_default_parameter (f, parms, Qauto_raise, Qnil, "autoRaise", "AutoRaise",
1303 RES_TYPE_BOOLEAN);
1304 x_default_parameter (f, parms, Qauto_lower, Qnil, "autoLower", "AutoLower",
1305 RES_TYPE_BOOLEAN);
1306 x_default_parameter (f, parms, Qbuffered, Qt, "buffered", "Buffered",
1307 RES_TYPE_BOOLEAN);
1308
1309 width = FRAME_COLS (f);
1310 height = FRAME_LINES (f);
1311
1312 SET_FRAME_COLS (f, 0);
1313 FRAME_LINES (f) = 0;
1314 change_frame_size (f, height, width, 1, 0, 0);
1315
1316 if (! f->output_data.ns->explicit_parent)
1317 {
1318 tem = x_get_arg (dpyinfo, parms, Qvisibility, 0, 0, RES_TYPE_BOOLEAN);
1319 if (EQ (tem, Qunbound))
1320 tem = Qnil;
1321
1322 x_set_visibility (f, tem, Qnil);
1323 if (EQ (tem, Qt))
1324 [[FRAME_NS_VIEW (f) window] makeKeyWindow];
1325 }
1326
1327 if (FRAME_HAS_MINIBUF_P (f)
1328 && (!FRAMEP (kb->Vdefault_minibuffer_frame)
1329 || !FRAME_LIVE_P (XFRAME (kb->Vdefault_minibuffer_frame))))
1330 kb->Vdefault_minibuffer_frame = frame;
1331
1332 /* All remaining specified parameters, which have not been "used"
1333 by x_get_arg and friends, now go in the misc. alist of the frame. */
1334 for (tem = parms; CONSP (tem); tem = XCDR (tem))
1335 if (CONSP (XCAR (tem)) && !NILP (XCAR (XCAR (tem))))
1336 f->param_alist = Fcons (XCAR (tem), f->param_alist);
1337
1338 UNGCPRO;
1339 Vwindow_list = Qnil;
1340
1341 return unbind_to (count, frame);
1342}
1343
1344
1345/* ==========================================================================
1346
1347 Lisp definitions
1348
1349 ========================================================================== */
1350
1351DEFUN ("ns-focus-frame", Fns_focus_frame, Sns_focus_frame, 1, 1, 0,
1352 doc: /* Set the input focus to FRAME.
1353FRAME nil means use the selected frame. */)
1354 (frame)
1355 Lisp_Object frame;
1356{
1357 struct frame *f = check_ns_frame (frame);
1358 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f);
1359
1360 if (dpyinfo->ns_focus_frame != f)
1361 {
1362 EmacsView *view = FRAME_NS_VIEW (f);
1363 BLOCK_INPUT;
1364 [[view window] makeKeyAndOrderFront: view];
1365 UNBLOCK_INPUT;
1366 }
1367
1368 return Qnil;
1369}
1370
1371
1372DEFUN ("ns-popup-prefs-panel", Fns_popup_prefs_panel, Sns_popup_prefs_panel,
1373 0, 0, "", "Pop up the preferences panel.")
1374 ()
1375{
1376 check_ns ();
1377 [(EmacsApp *)NSApp showPreferencesWindow: NSApp];
1378 return Qnil;
1379}
1380
1381
1382DEFUN ("ns-popup-font-panel", Fns_popup_font_panel, Sns_popup_font_panel,
1383 0, 1, "", "Pop up the font panel.")
1384 (frame)
1385 Lisp_Object frame;
1386{
1387 id fm;
1388 struct frame *f;
1389
1390 check_ns ();
1391 fm = [NSFontManager new];
1392 if (NILP (frame))
1393 f = SELECTED_FRAME ();
1394 else
1395 {
1396 CHECK_FRAME (frame);
1397 f = XFRAME (frame);
1398 }
1399
1400 [fm setSelectedFont: ((struct nsfont_info *)f->output_data.ns->font)->nsfont
1401 isMultiple: NO];
1402 [fm orderFrontFontPanel: NSApp];
1403 return Qnil;
1404}
1405
1406
1407DEFUN ("ns-popup-color-panel", Fns_popup_color_panel, Sns_popup_color_panel,
1408 0, 1, "", "Pop up the color panel.")
1409 (frame)
1410 Lisp_Object frame;
1411{
1412 struct frame *f;
1413
1414 check_ns ();
1415 if (NILP (frame))
1416 f = SELECTED_FRAME ();
1417 else
1418 {
1419 CHECK_FRAME (frame);
1420 f = XFRAME (frame);
1421 }
1422
1423 [NSApp orderFrontColorPanel: NSApp];
1424 return Qnil;
1425}
1426
1427
1428DEFUN ("ns-read-file-name", Fns_read_file_name, Sns_read_file_name, 1, 4, 0,
1429 "As read-file-name except that NS panels are used for querying, and\n\
1430args are slightly different. Nil returned if no selection made.\n\
1431Set ISLOAD non-nil if file being read for a save.")
1432 (prompt, dir, isLoad, init)
1433 Lisp_Object prompt, dir, isLoad, init;
1434{
1435 static id fileDelegate = nil;
1436 int ret;
1437 id panel;
1438 NSString *fname;
1439
1440 NSString *promptS = NILP (prompt) || !STRINGP (prompt) ? nil :
1441 [NSString stringWithUTF8String: XSTRING (prompt)->data];
1442 NSString *dirS = NILP (dir) || !STRINGP (dir) ?
1443 [NSString stringWithUTF8String: XSTRING (current_buffer->directory)->data] :
1444 [NSString stringWithUTF8String: XSTRING (dir)->data];
1445 NSString *initS = NILP (init) || !STRINGP (init) ? nil :
1446 [NSString stringWithUTF8String: XSTRING (init)->data];
1447
1448 check_ns ();
1449
1450 if (fileDelegate == nil)
1451 fileDelegate = [EmacsFileDelegate new];
1452
1453 [NSCursor setHiddenUntilMouseMoves: NO];
1454
1455 if ([dirS characterAtIndex: 0] == '~')
1456 dirS = [dirS stringByExpandingTildeInPath];
1457
1458 panel = NILP (isLoad) ?
1459 [EmacsSavePanel savePanel] : [EmacsOpenPanel openPanel];
1460
1461 [panel setTitle: promptS];
1462
1463 /* Puma (10.1) does not have */
1464 if ([panel respondsToSelector: @selector (setAllowsOtherFileTypes:)])
1465 [panel setAllowsOtherFileTypes: YES];
1466
1467 [panel setTreatsFilePackagesAsDirectories: YES];
1468 [panel setDelegate: fileDelegate];
1469
1470 panelOK = 0;
1471 if (NILP (isLoad))
1472 {
1473 ret = [panel runModalForDirectory: dirS file: initS];
1474 }
1475 else
1476 {
1477 [panel setCanChooseDirectories: YES];
1478 ret = [panel runModalForDirectory: dirS file: initS types: nil];
1479 }
1480
1481 ret = (ret = NSOKButton) || panelOK;
1482
1483 fname = [panel filename];
1484
1485 [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
1486
1487 return ret ? build_string ([fname UTF8String]) : Qnil;
1488}
1489
1490
1491DEFUN ("ns-get-resource", Fns_get_resource, Sns_get_resource, 2, 2, 0,
1492 "Return the value of the property NAME of OWNER from the defaults database.\n\
1493If OWNER is nil, Emacs is assumed.")
1494 (owner, name)
1495 Lisp_Object owner, name;
1496{
1497 const char *value;
1498
1499 check_ns ();
1500 if (NILP (owner))
1501 owner = build_string
1502 ([[[NSProcessInfo processInfo] processName] UTF8String]);
1503 /* CHECK_STRING (owner); this should be just "Emacs" */
1504 CHECK_STRING (name);
1505/*fprintf (stderr, "ns-get-resource checking resource '%s'\n", SDATA (name)); */
1506
1507 value =[[[NSUserDefaults standardUserDefaults]
1508 objectForKey: [NSString stringWithUTF8String: XSTRING (name)->data]]
1509 UTF8String];
1510
1511 if (value)
1512 return build_string (value);
1513/*fprintf (stderr, "Nothing found for NS resource '%s'.\n", XSTRING (name)->data); */
1514 return Qnil;
1515}
1516
1517
1518DEFUN ("ns-set-resource", Fns_set_resource, Sns_set_resource, 3, 3, 0,
1519 "Set property NAME of OWNER to VALUE, from the defaults database.\n\
1520If OWNER is nil, Emacs is assumed.\n\
1521If VALUE is nil, the default is removed.")
1522 (owner, name, value)
1523 Lisp_Object owner, name, value;
1524{
1525 check_ns ();
1526 if (NILP (owner))
1527 owner =
1528 build_string ([[[NSProcessInfo processInfo] processName] UTF8String]);
1529 CHECK_STRING (owner);
1530 CHECK_STRING (name);
1531 if (NILP (value))
1532 {
1533 [[NSUserDefaults standardUserDefaults] removeObjectForKey:
1534 [NSString stringWithUTF8String: XSTRING (name)->data]];
1535 }
1536 else
1537 {
1538 CHECK_STRING (value);
1539 [[NSUserDefaults standardUserDefaults] setObject:
1540 [NSString stringWithUTF8String: XSTRING (value)->data]
1541 forKey: [NSString stringWithUTF8String:
1542 XSTRING (name)->data]];
1543 }
1544
1545 return Qnil;
1546}
1547
1548
1549DEFUN ("ns-set-alpha", Fns_set_alpha, Sns_set_alpha, 2, 2, 0,
1550 "Return a color same as given with alpha set to given value\n\
1551from 0 to 1, where 1 is fully opaque.")
1552 (color, alpha)
1553 Lisp_Object color;
1554 Lisp_Object alpha;
1555{
1556 NSColor *col;
1557 float a;
1558
1559 CHECK_STRING (color);
1560 CHECK_NUMBER_OR_FLOAT (alpha);
1561
1562 if (ns_lisp_to_color (color, &col))
1563 error ("Unknown color.");
1564
1565 a = XFLOATINT (alpha);
1566 if (a < 0.0 || a > 1.0)
1567 error ("Alpha value should be between 0 and 1 inclusive.");
1568
1569 col = [col colorWithAlphaComponent: a];
1570 return ns_color_to_lisp (col);
1571}
1572
1573
1574DEFUN ("ns-server-max-request-size", Fns_server_max_request_size,
1575 Sns_server_max_request_size,
1576 0, 1, 0,
1577 "This function is only present for completeness. It does not return\n\
1578a usable result for NS windows.")
1579 (display)
1580 Lisp_Object display;
1581{
1582 check_ns ();
1583 /* This function has no real equivalent under NeXTstep. Return nil to
1584 indicate this. */
1585 return Qnil;
1586}
1587
1588
1589DEFUN ("ns-server-vendor", Fns_server_vendor, Sns_server_vendor, 0, 1, 0,
1590 "Returns the vendor ID string of the NS server of display DISPLAY.\n\
1591The optional argument DISPLAY specifies which display to ask about.\n\
1592DISPLAY should be either a frame or a display name (a string).\n\
1593If omitted or nil, that stands for the selected frame's display.")
1594 (display)
1595 Lisp_Object display;
1596{
1597 check_ns ();
1598#ifdef NS_IMPL_GNUSTEP
1599 return build_string ("GNU");
1600#else
1601 return build_string ("Apple");
1602#endif
1603}
1604
1605
1606DEFUN ("ns-server-version", Fns_server_version, Sns_server_version, 0, 1, 0,
1607 "Returns the version number of the NS release of display DISPLAY.\n\
1608See also the function `ns-server-vendor'.\n\n\
1609The optional argument DISPLAY specifies which display to ask about.\n\
1610DISPLAY should be either a frame or a display name (a string).\n\
1611If omitted or nil, that stands for the selected frame's display.")
1612 (display)
1613 Lisp_Object display;
1614{
1615 /*PENDING: return GUI version on GNUSTEP, ?? on OS X */
1616 return build_string ("1.0");
1617}
1618
1619
1620DEFUN ("ns-display-screens", Fns_display_screens, Sns_display_screens, 0, 1, 0,
1621 "Returns the number of screens on the NS server of display DISPLAY.\n\
1622The optional argument DISPLAY specifies which display to ask about.\n\
1623DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\
1624If omitted or nil, that stands for the selected frame's display.")
1625 (display)
1626 Lisp_Object display;
1627{
1628 int num;
1629
1630 check_ns ();
1631 num = [[NSScreen screens] count];
1632
1633 return (num != 0) ? make_number (num) : Qnil;
1634}
1635
1636
1637DEFUN ("ns-display-mm-height", Fns_display_mm_height, Sns_display_mm_height,
1638 0, 1, 0,
1639 "Returns the height in millimeters of the NS display DISPLAY.\n\
1640The optional argument DISPLAY specifies which display to ask about.\n\
1641DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\
1642If omitted or nil, that stands for the selected frame's display.")
1643 (display)
1644 Lisp_Object display;
1645{
1646 check_ns ();
1647 return make_number ((int)
1648 ([ns_get_screen (display) frame].size.height/(92.0/25.4)));
1649}
1650
1651
1652DEFUN ("ns-display-mm-width", Fns_display_mm_width, Sns_display_mm_width,
1653 0, 1, 0,
1654 "Returns the width in millimeters of the NS display DISPLAY.\n\
1655The optional argument DISPLAY specifies which display to ask about.\n\
1656DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\
1657If omitted or nil, that stands for the selected frame's display.")
1658 (display)
1659 Lisp_Object display;
1660{
1661 check_ns ();
1662 return make_number ((int)
1663 ([ns_get_screen (display) frame].size.width/(92.0/25.4)));
1664}
1665
1666
1667DEFUN ("ns-display-backing-store", Fns_display_backing_store,
1668 Sns_display_backing_store, 0, 1, 0,
1669 "Returns an indication of whether NS display DISPLAY does backing store.\n\
1670The value may be `buffered', `retained', or `non-retained'.\n\
1671The optional argument DISPLAY specifies which display to ask about.\n\
1672DISPLAY should be either a frame, display name (a string), or terminal ID.\n\
1673If omitted or nil, that stands for the selected frame's display.\n\
1674Under NS, this may differ for each frame.")
1675 (display)
1676 Lisp_Object display;
1677{
1678 check_ns ();
1679 switch ([ns_get_window (display) backingType])
1680 {
1681 case NSBackingStoreBuffered:
1682 return intern ("buffered");
1683 case NSBackingStoreRetained:
1684 return intern ("retained");
1685 case NSBackingStoreNonretained:
1686 return intern ("non-retained");
1687 default:
1688 error ("Strange value for backingType parameter of frame");
1689 }
1690 return Qnil; /* not reached, shut compiler up */
1691}
1692
1693
1694DEFUN ("ns-display-visual-class", Fns_display_visual_class,
1695 Sns_display_visual_class, 0, 1, 0,
1696 "Returns the visual class of the NS display DISPLAY.\n\
1697The value is one of the symbols `static-gray', `gray-scale',\n\
1698`static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\
1699The optional argument DISPLAY specifies which display to ask about.\n\
1700DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\
1701If omitted or nil, that stands for the selected frame's display.")
1702 (display)
1703 Lisp_Object display;
1704{
1705 NSWindowDepth depth;
1706 check_ns ();
1707 depth = [ns_get_screen (display) depth];
1708
1709 if ( depth == NSBestDepth (NSCalibratedWhiteColorSpace, 2, 2, YES, NULL))
1710 return intern ("static-gray");
1711 else if (depth == NSBestDepth (NSCalibratedWhiteColorSpace, 8, 8, YES, NULL))
1712 return intern ("gray-scale");
1713 else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 8, YES, NULL))
1714 return intern ("pseudo-color");
1715 else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 4, 12, NO, NULL))
1716 return intern ("true-color");
1717 else if ( depth == NSBestDepth (NSCalibratedRGBColorSpace, 8, 24, NO, NULL))
1718 return intern ("direct-color");
1719 else
1720 /* color mgmt as far as we do it is really handled by NS itself anyway */
1721 return intern ("direct-color");
1722}
1723
1724
1725DEFUN ("ns-display-save-under", Fns_display_save_under,
1726 Sns_display_save_under, 0, 1, 0,
1727 "Returns t if the NS display DISPLAY supports the save-under feature.\n\
1728The optional argument DISPLAY specifies which display to ask about.\n\
1729DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\
1730If omitted or nil, that stands for the selected frame's display.\n\
1731Under NS, this may differ for each frame.")
1732 (display)
1733 Lisp_Object display;
1734{
1735 check_ns ();
1736 switch ([ns_get_window (display) backingType])
1737 {
1738 case NSBackingStoreBuffered:
1739 return Qt;
1740
1741 case NSBackingStoreRetained:
1742 case NSBackingStoreNonretained:
1743 return Qnil;
1744
1745 default:
1746 error ("Strange value for backingType parameter of frame");
1747 }
1748 return Qnil; /* not reached, shut compiler up */
1749}
1750
1751
1752DEFUN ("ns-open-connection", Fns_open_connection, Sns_open_connection,
1753 1, 3, 0, "Open a connection to a NS server.\n\
1754DISPLAY is the name of the display to connect to.\n\
1755Optional arguments XRM-STRING and MUST-SUCCEED are currently ignored.")
1756 (display, resource_string, must_succeed)
1757 Lisp_Object display, resource_string, must_succeed;
1758{
1759 struct ns_display_info *dpyinfo;
1760
1761 CHECK_STRING (display);
1762
1763 nxatoms_of_nsselect ();
1764 dpyinfo = ns_term_init (display);
1765 if (dpyinfo == 0)
1766 {
1767 if (!NILP (must_succeed))
1768 fatal ("OpenStep on %s not responding.\n",
1769 XSTRING (display)->data);
1770 else
1771 error ("OpenStep on %s not responding.\n",
1772 XSTRING (display)->data);
1773 }
1774
1775 /* Register our external input/output types, used for determining
1776 applicable services and also drag/drop eligibility. */
1777 ns_send_types = [[NSArray arrayWithObject: NSStringPboardType] retain];
1778 ns_return_types = [[NSArray arrayWithObject: NSStringPboardType] retain];
1779 ns_drag_types = [[NSArray arrayWithObjects:
1780 NSStringPboardType,
1781 NSTabularTextPboardType,
1782 NSFilenamesPboardType,
1783 NSURLPboardType,
1784 NSColorPboardType,
1785 NSFontPboardType, nil] retain];
1786
1787 return Qnil;
1788}
1789
1790
1791DEFUN ("ns-close-connection", Fns_close_connection, Sns_close_connection,
1792 1, 1, 0, "Close the connection to the current NS server.\n\
1793The second argument DISPLAY is currently ignored, but nil would stand for\n\
1794the selected frame's display.")
1795 (display)
1796 Lisp_Object display;
1797{
1798 check_ns ();
1799#ifdef NS_IMPL_COCOA
1800 PSFlush ();
1801#endif
1802 /*ns_delete_terminal (dpyinfo->terminal); */
1803 [NSApp terminate: NSApp];
1804 return Qnil;
1805}
1806
1807
1808DEFUN ("ns-display-list", Fns_display_list, Sns_display_list, 0, 0, 0,
1809 "Return the list of display names that Emacs has connections to.")
1810 ()
1811{
1812 Lisp_Object tail, result;
1813
1814 result = Qnil;
1815 for (tail = ns_display_name_list; CONSP (tail); tail = XCDR (tail))
1816 result = Fcons (XCAR (XCAR (tail)), result);
1817
1818 return result;
1819}
1820
1821
1822DEFUN ("ns-hide-others", Fns_hide_others, Sns_hide_others,
1823 0, 0, 0, "Hides all applications other than emacs.")
1824 ()
1825{
1826 check_ns ();
1827 [NSApp hideOtherApplications: NSApp];
1828 return Qnil;
1829}
1830
1831DEFUN ("ns-hide-emacs", Fns_hide_emacs, Sns_hide_emacs,
1832 1, 1, 0, "If ON is non-nil, the entire emacs application is hidden.\n\
1833Otherwise if emacs is hidden, it is unhidden.\n\
1834If ON is equal to 'activate, emacs is unhidden and becomes\n\
1835the active application.")
1836 (on)
1837 Lisp_Object on;
1838{
1839 check_ns ();
1840 if (EQ (on, intern ("activate")))
1841 {
1842 [NSApp unhide: NSApp];
1843 [NSApp activateIgnoringOtherApps: YES];
1844 }
1845 else if (NILP (on))
1846 [NSApp unhide: NSApp];
1847 else
1848 [NSApp hide: NSApp];
1849 return Qnil;
1850}
1851
1852
1853DEFUN ("ns-emacs-info-panel", Fns_emacs_info_panel, Sns_emacs_info_panel,
1854 0, 0, 0, "Shows the 'Info' or 'About' panel for Emacs.")
1855 ()
1856{
1857 check_ns ();
1858 [NSApp orderFrontStandardAboutPanel: nil];
1859 return Qnil;
1860}
1861
1862
1863DEFUN ("x-list-fonts", Fns_list_fonts, Sns_list_fonts, 1, 4, 0,
1864 "Return a list of the names of available fonts matching PATTERN.\n\
1865If optional arguments FACE and FRAME are specified, return only fonts\n\
1866the same size as FACE on FRAME.\n\
1867If optional argument MAX is specified, return at most MAX matches.\n\
1868\n\
1869PATTERN is a regular expression; FACE is a face name - a symbol.\n\
1870\n\
1871The return value is a list of strings, suitable as arguments to\n\
1872set-face-font.\n\
1873\n\
1874The font names are _NOT_ X names.")
1875 (pattern, face, frame, max)
1876 Lisp_Object pattern, face, frame, max;
1877{
1878 Lisp_Object flist, olist = Qnil, tem;
1879 struct frame *f;
1880 int maxnames;
1881
1882 /* We can't simply call check_x_frame because this function may be
1883 called before any frame is created. */
1884 if (NILP (frame))
1885 f = SELECTED_FRAME ();
1886 else
1887 {
1888 CHECK_LIVE_FRAME (frame);
1889 f = XFRAME (frame);
1890 }
1891 if (! FRAME_WINDOW_P (f))
1892 {
1893 /* Perhaps we have not yet created any frame. */
1894 f = NULL;
1895 }
1896
1897 if (NILP (max))
1898 maxnames = 4;
1899 else
1900 {
1901 CHECK_NATNUM (max);
1902 maxnames = XFASTINT (max);
1903 }
1904
1905 /* get XLFD names */
1906 flist = ns_list_fonts (f, pattern, 0, maxnames);
1907
1908 /* convert list into regular names */
1909 for (tem = flist; CONSP (tem); tem = XCDR (tem))
1910 {
1911 Lisp_Object fname = XCAR (tem);
1912 olist = Fcons (build_string (ns_xlfd_to_fontname (XSTRING (fname)->data)),
1913 olist);
1914 }
1915
1916 return olist;
1917}
1918
1919
1920DEFUN ("ns-font-name", Fns_font_name, Sns_font_name, 1, 1, 0,
1921 "Determine font postscript or family name from a font name string or\n\
1922XLFD string. If string contains fontset' and not 'fontset-startup' it is\n\
1923left alone.")
1924 (name)
1925 Lisp_Object name;
1926{
1927 char *nm;
1928 CHECK_STRING (name);
1929 nm = SDATA (name);
1930
1931 if (nm[0] != '-')
1932 return name;
1933 if (strstr (nm, "fontset") && !strstr (nm, "fontset-startup"))
1934 return name;
1935
1936 return build_string (ns_xlfd_to_fontname (SDATA (name)));
1937}
1938
1939
1940DEFUN ("ns-list-colors", Fns_list_colors, Sns_list_colors, 0, 1, 0,
1941 "Return a list of all available colors.\n\
1942The optional argument FRAME is currently ignored.")
1943 (frame)
1944 Lisp_Object frame;
1945{
1946 Lisp_Object list = Qnil;
1947 NSEnumerator *colorlists;
1948 NSColorList *clist;
1949
1950 if (!NILP (frame))
1951 {
1952 CHECK_FRAME (frame);
1953 if (! FRAME_NS_P (XFRAME (frame)))
1954 error ("non-NS frame used in `ns-list-colors'");
1955 }
1956
1957 BLOCK_INPUT;
1958
1959 colorlists = [[NSColorList availableColorLists] objectEnumerator];
1960 while (clist = [colorlists nextObject])
1961 {
1962 if ([[clist name] length] < 7 ||
1963 [[clist name] rangeOfString: @"PANTONE"].location == 0)
1964 {
1965 NSEnumerator *cnames = [[clist allKeys] reverseObjectEnumerator];
1966 NSString *cname;
1967 while (cname = [cnames nextObject])
1968 list = Fcons (build_string ([cname UTF8String]), list);
1969/* for (i = [[clist allKeys] count] - 1; i >= 0; i--)
1970 list = Fcons (build_string ([[[clist allKeys] objectAtIndex: i]
1971 UTF8String]), list); */
1972 }
1973 }
1974
1975 UNBLOCK_INPUT;
1976
1977 return list;
1978}
1979
1980
1981DEFUN ("ns-list-services", Fns_list_services, Sns_list_services, 0, 0, 0,
1982 "List NS services by querying NSApp.")
1983 ()
1984{
1985 Lisp_Object ret = Qnil;
1986 NSMenu *svcs;
1987 id delegate;
1988
1989 check_ns ();
1990 svcs = [[NSMenu alloc] initWithTitle: @"Services"];
1991 [NSApp setServicesMenu: svcs]; /* this and next rebuild on <10.4 */
1992 [NSApp registerServicesMenuSendTypes: ns_send_types
1993 returnTypes: ns_return_types];
1994
1995/* On Tiger, services menu updating was made lazier (waits for user to
1996 actually click on the menu), so we have to force things along: */
1997#ifdef NS_IMPL_COCOA
1998 if (NSAppKitVersionNumber >= 744.0)
1999 {
2000 delegate = [svcs delegate];
2001 if (delegate != nil)
2002 {
2003 if ([delegate respondsToSelector: @selector (menuNeedsUpdate:)])
2004 [delegate menuNeedsUpdate: svcs];
2005 if ([delegate respondsToSelector:
2006 @selector (menu:updateItem:atIndex:shouldCancel:)])
2007 {
2008 int i, len = [delegate numberOfItemsInMenu: svcs];
2009 for (i =0; i<len; i++)
2010 [svcs addItemWithTitle: @"" action: NULL keyEquivalent: @""];
2011 for (i =0; i<len; i++)
2012 if (![delegate menu: svcs
2013 updateItem: (NSMenuItem *)[svcs itemAtIndex: i]
2014 atIndex: i shouldCancel: NO])
2015 break;
2016 }
2017 }
2018 }
2019#endif
2020
2021 [svcs setAutoenablesItems: NO];
2022#ifdef NS_IMPL_COCOA
2023 [svcs update]; /* on OS X, converts from '/' structure */
2024#endif
2025
2026 ret = interpret_services_menu (svcs, Qnil, ret);
2027 return ret;
2028}
2029
2030
2031DEFUN ("ns-perform-service", Fns_perform_service, Sns_perform_service,
2032 2, 2, 0, "Perform NS SERVICE on SEND which is either a string or nil.\n\
2033Returns result of service as string or nil if no result.")
2034 (service, send)
2035 Lisp_Object service, send;
2036{
2037 id pb;
2038 NSString *svcName;
2039 char *utfStr;
2040 int len;
2041
2042 CHECK_STRING (service);
2043 check_ns ();
2044
2045 utfStr = XSTRING (service)->data;
2046 svcName = [NSString stringWithUTF8String: utfStr];
2047
2048 pb =[NSPasteboard pasteboardWithUniqueName];
2049 ns_string_to_pasteboard (pb, send);
2050
2051 if (NSPerformService (svcName, pb) == NO)
2052 Fsignal (Qquit, Fcons (build_string ("service not available"), Qnil));
2053
2054 if ([[pb types] count] == 0)
2055 return build_string ("");
2056 return ns_string_from_pasteboard (pb);
2057}
2058
2059
2060DEFUN ("ns-convert-utf8-nfd-to-nfc", Fns_convert_utf8_nfd_to_nfc,
2061 Sns_convert_utf8_nfd_to_nfc, 1, 1, 0,
2062 "Composes character sequences in UTF-8 normal form NFD string STR to produce a normal (composed normal form NFC) string.")
2063 (str)
2064 Lisp_Object str;
2065{
2066 NSString *utfStr;
2067
2068 CHECK_STRING (str);
2069 utfStr = [[NSString stringWithUTF8String: XSTRING (str)->data]
2070 precomposedStringWithCanonicalMapping];
2071 return build_string ([utfStr UTF8String]);
2072}
2073
2074
2075/* ==========================================================================
2076
2077 Miscellaneous functions not called through hooks
2078
2079 ========================================================================== */
2080
2081
2082/* 23: call in image.c */
2083FRAME_PTR
2084check_x_frame (Lisp_Object frame)
2085{
2086 return check_ns_frame (frame);
2087}
2088
2089/* 23: added, due to call in frame.c */
2090struct ns_display_info *
2091check_x_display_info (Lisp_Object frame)
2092{
2093 return check_ns_display_info (frame);
2094}
2095
2096
2097/* 23: new function; we don't have much in the way of flexibility though */
2098void
2099x_set_scroll_bar_default_width (f)
2100 struct frame *f;
2101{
2102 int wid = FRAME_COLUMN_WIDTH (f);
2103 FRAME_CONFIG_SCROLL_BAR_WIDTH (f) = NS_SCROLL_BAR_WIDTH_DEFAULT;
2104 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) +
2105 wid - 1) / wid;
2106}
2107
2108
2109/* 23: terms now impl this instead of x-get-resource directly */
2110const char *
2111x_get_string_resource (XrmDatabase rdb, char *name, char *class)
2112{
2113 /* remove appname prefix; PENDING: allow for !="Emacs" */
2114 char *toCheck = class + (!strncmp (class, "Emacs.", 6) ? 6 : 0);
2115 const char *res;
2116 check_ns ();
2117
2118 /* Support emacs-20-style face resources for backwards compatibility */
2119 if (!strncmp (toCheck, "Face", 4))
2120 toCheck = name + (!strncmp (name, "emacs.", 6) ? 6 : 0);
2121
2122/*fprintf (stderr, "Checking '%s'\n", toCheck); */
2123
2124 res = [[[NSUserDefaults standardUserDefaults] objectForKey:
2125 [NSString stringWithUTF8String: toCheck]] UTF8String];
2126 return !res ? NULL :
2127 (!strncasecmp (res, "YES", 3) ? "true" :
2128 (!strncasecmp (res, "NO", 2) ? "false" : res));
2129}
2130
2131
2132Lisp_Object
2133x_get_focus_frame (struct frame *frame)
2134{
2135 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (frame);
2136 Lisp_Object nsfocus;
2137
2138 if (!dpyinfo->ns_focus_frame)
2139 return Qnil;
2140
2141 XSETFRAME (nsfocus, dpyinfo->ns_focus_frame);
2142 return nsfocus;
2143}
2144
2145
2146int
2147x_pixel_width (struct frame *f)
2148{
2149 return FRAME_PIXEL_WIDTH (f);
2150}
2151
2152
2153int
2154x_pixel_height (struct frame *f)
2155{
2156 return FRAME_PIXEL_HEIGHT (f);
2157}
2158
2159
2160int
2161x_char_width (struct frame *f)
2162{
2163 return FRAME_COLUMN_WIDTH (f);
2164}
2165
2166
2167int
2168x_char_height (struct frame *f)
2169{
2170 return FRAME_LINE_HEIGHT (f);
2171}
2172
2173
2174int
2175x_screen_planes (struct frame *f)
2176{
2177 return FRAME_NS_DISPLAY_INFO (f)->n_planes;
2178}
2179
2180
2181void
2182x_sync (Lisp_Object frame)
2183{
2184 /* XXX Not implemented XXX */
2185 return;
2186}
2187
2188
2189
2190/* ==========================================================================
2191
2192 Lisp definitions that, for whatever reason, we can't alias as 'ns-XXX'.
2193
2194 ========================================================================== */
2195
2196
2197DEFUN ("xw-color-defined-p", Fns_color_defined_p, Sns_color_defined_p, 1, 2, 0,
2198 "Return t if the current NS display supports the color named COLOR.\n\
2199The optional argument FRAME is currently ignored.")
2200 (color, frame)
2201 Lisp_Object color, frame;
2202{
2203 NSColor * col;
2204 check_ns ();
2205 return ns_lisp_to_color (color, &col) ? Qnil : Qt;
2206}
2207
2208
2209DEFUN ("xw-color-values", Fns_color_values, Sns_color_values, 1, 2, 0,
2210 "Return a description of the color named COLOR.\n\
2211The value is a list of integer RGBA values--(RED GREEN BLUE ALPHA).\n\
2212These values appear to range from 0 to 65280; white is (65280 65280 65280 0).\n\
2213The optional argument FRAME is currently ignored.")
2214 (color, frame)
2215 Lisp_Object color, frame;
2216{
2217 NSColor * col;
2218 float red, green, blue, alpha;
2219 Lisp_Object rgba[4];
2220
2221 check_ns ();
2222 CHECK_STRING (color);
2223
2224 if (ns_lisp_to_color (color, &col))
2225 return Qnil;
2226
2227 [[col colorUsingColorSpaceName: NSCalibratedRGBColorSpace]
2228 getRed: &red green: &green blue: &blue alpha: &alpha];
2229 rgba[0] = make_number (lrint (red*65280));
2230 rgba[1] = make_number (lrint (green*65280));
2231 rgba[2] = make_number (lrint (blue*65280));
2232 rgba[3] = make_number (lrint (alpha*65280));
2233
2234 return Flist (4, rgba);
2235}
2236
2237
2238DEFUN ("xw-display-color-p", Fxw_display_color_p, Sxw_display_color_p, 0, 1, 0,
2239 "Return t if the NS display supports color.\n\
2240The optional argument DISPLAY specifies which display to ask about.\n\
2241DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\
2242If omitted or nil, that stands for the selected frame's display.")
2243 (display)
2244 Lisp_Object display;
2245{
2246 NSWindowDepth depth;
2247 NSString *colorSpace;
2248 check_ns ();
2249 depth = [ns_get_screen (display) depth];
2250 colorSpace = NSColorSpaceFromDepth (depth);
2251
2252 return [colorSpace isEqualToString: NSDeviceWhiteColorSpace]
2253 || [colorSpace isEqualToString: NSCalibratedWhiteColorSpace]
2254 ? Qnil : Qt;
2255}
2256
2257
2258DEFUN ("x-display-grayscale-p", Fx_display_grayscale_p,
2259 Sx_display_grayscale_p, 0, 1, 0,
2260 "Return t if the NS display supports shades of gray.\n\
2261Note that color displays do support shades of gray.\n\
2262The optional argument DISPLAY specifies which display to ask about.\n\
2263DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\
2264If omitted or nil, that stands for the selected frame's display.")
2265 (display)
2266 Lisp_Object display;
2267{
2268 NSWindowDepth depth;
2269 check_ns ();
2270 depth = [ns_get_screen (display) depth];
2271
2272 return NSBitsPerPixelFromDepth (depth) > 1 ? Qt : Qnil;
2273}
2274
2275
2276DEFUN ("x-display-pixel-width", Fns_display_pixel_width, Sns_display_pixel_width,
2277 0, 1, 0,
2278 "Returns the width in pixels of the NS display DISPLAY.\n\
2279The optional argument DISPLAY specifies which display to ask about.\n\
2280DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\
2281If omitted or nil, that stands for the selected frame's display.")
2282 (display)
2283 Lisp_Object display;
2284{
2285 check_ns ();
2286 return make_number ((int) [ns_get_screen (display) frame].size.width);
2287}
2288
2289
2290DEFUN ("x-display-pixel-height", Fns_display_pixel_height,
2291 Sns_display_pixel_height, 0, 1, 0,
2292 "Returns the height in pixels of the NS display DISPLAY.\n\
2293The optional argument DISPLAY specifies which display to ask about.\n\
2294DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\
2295If omitted or nil, that stands for the selected frame's display.")
2296 (display)
2297 Lisp_Object display;
2298{
2299 check_ns ();
2300 return make_number ((int) [ns_get_screen (display) frame].size.height);
2301}
2302
2303DEFUN ("display-usable-bounds", Fns_display_usable_bounds,
2304 Sns_display_usable_bounds, 0, 1, 0,
2305 "Returns a list of integers in form (left top width height) describing the \
2306usable screen area excluding reserved areas such as the Mac menu and doc, or \
2307the Windows task bar.\n \
2308The optional argument DISPLAY specifies which display to ask about.\n\
2309DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\
2310If omitted or nil, that stands for the selected frame's display.")
2311 (display)
2312 Lisp_Object display;
2313{
2314 int top;
2315 NSRect vScreen;
2316
2317 check_ns ();
2318 vScreen = [ns_get_screen (display) visibleFrame];
2319 top = vScreen.origin.y == 0.0 ?
2320 (int) [ns_get_screen (display) frame].size.height - vScreen.size.height : 0;
2321
2322 return list4 (make_number ((int) vScreen.origin.x),
2323 make_number (top),
2324 make_number ((int) vScreen.size.width),
2325 make_number ((int) vScreen.size.height));
2326}
2327
2328
2329DEFUN ("x-display-planes", Fx_display_planes, Sns_display_planes,
2330 0, 1, 0,
2331 "Returns the number of bitplanes of the NS display DISPLAY.\n\
2332The optional argument DISPLAY specifies which display to ask about.\n\
2333DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\
2334If omitted or nil, that stands for the selected frame's display.")
2335 (display)
2336 Lisp_Object display;
2337{
2338 check_ns ();
2339 return make_number
2340 (NSBitsPerSampleFromDepth ([ns_get_screen (display) depth]));
2341}
2342
2343
2344DEFUN ("x-display-color-cells", Fns_display_color_cells,
2345 Sns_display_color_cells, 0, 1, 0,
2346 "Returns the number of color cells of the NS display DISPLAY.\n\
2347The optional argument DISPLAY specifies which display to ask about.\n\
2348DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\
2349If omitted or nil, that stands for the selected frame's display.")
2350 (display)
2351 Lisp_Object display;
2352{
2353 check_ns ();
2354 struct ns_display_info *dpyinfo = check_ns_display_info (display);
2355
2356 /* We force 24+ bit depths to 24-bit to prevent an overflow. */
2357 return make_number (1 << min (dpyinfo->n_planes, 24));
2358}
2359
2360
2361/* Unused dummy def needed for compatibility. */
2362Lisp_Object tip_frame;
2363
2364/*PENDING: move to xdisp or similar */
2365static void
2366compute_tip_xy (f, parms, dx, dy, width, height, root_x, root_y)
2367 struct frame *f;
2368 Lisp_Object parms, dx, dy;
2369 int width, height;
2370 int *root_x, *root_y;
2371{
2372 Lisp_Object left, top;
2373 EmacsView *view = FRAME_NS_VIEW (f);
2374 NSPoint pt;
2375
2376 /* Start with user-specified or mouse position. */
2377 left = Fcdr (Fassq (Qleft, parms));
2378 if (INTEGERP (left))
2379 pt.x = XINT (left);
2380 else
2381 pt.x = last_mouse_motion_position.x;
2382 top = Fcdr (Fassq (Qtop, parms));
2383 if (INTEGERP (top))
2384 pt.y = XINT (top);
2385 else
2386 pt.y = last_mouse_motion_position.y;
2387
2388 /* Convert to screen coordinates */
2389 pt = [view convertPoint: pt toView: nil];
2390 pt = [[view window] convertBaseToScreen: pt];
2391
2392 /* Ensure in bounds. (Note, screen origin = lower left.) */
2393 if (pt.x + XINT (dx) <= 0)
2394 *root_x = 0; /* Can happen for negative dx */
2395 else if (pt.x + XINT (dx) + width <= FRAME_NS_DISPLAY_INFO (f)->width)
2396 /* It fits to the right of the pointer. */
2397 *root_x = pt.x + XINT (dx);
2398 else if (width + XINT (dx) <= pt.x)
2399 /* It fits to the left of the pointer. */
2400 *root_x = pt.x - width - XINT (dx);
2401 else
2402 /* Put it left justified on the screen -- it ought to fit that way. */
2403 *root_x = 0;
2404
2405 if (pt.y - XINT (dy) - height >= 0)
2406 /* It fits below the pointer. */
2407 *root_y = pt.y - height - XINT (dy);
2408 else if (pt.y + XINT (dy) + height <= FRAME_NS_DISPLAY_INFO (f)->height)
2409 /* It fits above the pointer */
2410 *root_y = pt.y + XINT (dy);
2411 else
2412 /* Put it on the top. */
2413 *root_y = FRAME_NS_DISPLAY_INFO (f)->height - height;
2414}
2415
2416
2417DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0,
2418 doc: /* Show STRING in a "tooltip" window on frame FRAME.
2419A tooltip window is a small window displaying a string.
2420
2421FRAME nil or omitted means use the selected frame.
2422
2423PARMS is an optional list of frame parameters which can be used to
2424change the tooltip's appearance.
2425
2426Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil
2427means use the default timeout of 5 seconds.
2428
2429If the list of frame parameters PARMS contains a `left' parameter,
2430the tooltip is displayed at that x-position. Otherwise it is
2431displayed at the mouse position, with offset DX added (default is 5 if
2432DX isn't specified). Likewise for the y-position; if a `top' frame
2433parameter is specified, it determines the y-position of the tooltip
2434window, otherwise it is displayed at the mouse position, with offset
2435DY added (default is -10).
2436
2437A tooltip's maximum size is specified by `x-max-tooltip-size'.
2438Text larger than the specified size is clipped. */)
2439 (string, frame, parms, timeout, dx, dy)
2440 Lisp_Object string, frame, parms, timeout, dx, dy;
2441{
2442 int root_x, root_y;
2443 struct gcpro gcpro1, gcpro2, gcpro3, gcpro4;
2444 int count = SPECPDL_INDEX ();
2445 struct frame *f;
2446 char *str;
2447 NSSize size;
2448
2449 specbind (Qinhibit_redisplay, Qt);
2450
2451 GCPRO4 (string, parms, frame, timeout);
2452
2453 CHECK_STRING (string);
2454 str = XSTRING (string)->data;
2455 f = check_x_frame (frame);
2456 if (NILP (timeout))
2457 timeout = make_number (5);
2458 else
2459 CHECK_NATNUM (timeout);
2460
2461 if (NILP (dx))
2462 dx = make_number (5);
2463 else
2464 CHECK_NUMBER (dx);
2465
2466 if (NILP (dy))
2467 dy = make_number (-10);
2468 else
2469 CHECK_NUMBER (dy);
2470
2471 BLOCK_INPUT;
2472 if (ns_tooltip == nil)
2473 ns_tooltip = [[EmacsTooltip alloc] init];
2474 else
2475 Fx_hide_tip ();
2476
2477 [ns_tooltip setText: str];
2478 size = [ns_tooltip frame].size;
2479
2480 /* Move the tooltip window where the mouse pointer is. Resize and
2481 show it. */
2482 compute_tip_xy (f, parms, dx, dy, (int)size.width, (int)size.height,
2483 &root_x, &root_y);
2484
2485 [ns_tooltip showAtX: root_x Y: root_y for: XINT (timeout)];
2486 UNBLOCK_INPUT;
2487
2488 UNGCPRO;
2489 return unbind_to (count, Qnil);
2490}
2491
2492
2493DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0,
2494 doc: /* Hide the current tooltip window, if there is any.
2495Value is t if tooltip was open, nil otherwise. */)
2496 ()
2497{
2498 if (ns_tooltip == nil || ![ns_tooltip isActive])
2499 return Qnil;
2500 [ns_tooltip hide];
2501 return Qt;
2502}
2503
2504
2505/* ==========================================================================
2506
2507 Lisp interface declaration
2508
2509 ========================================================================== */
2510
2511
2512void
2513syms_of_nsfns ()
2514{
2515 int i;
2516
2517 Qns_frame_parameter = intern ("ns-frame-parameter");
2518 staticpro (&Qns_frame_parameter);
2519 Qnone = intern ("none");
2520 staticpro (&Qnone);
2521 Qbuffered = intern ("bufferd");
2522 staticpro (&Qbuffered);
2523 Qfontsize = intern ("fontsize");
2524 staticpro (&Qfontsize);
2525
2526 DEFVAR_LISP ("ns-icon-type-alist", &Vns_icon_type_alist,
2527 "Alist of elements (REGEXP . IMAGE) for images of icons associated to\n\
2528frames. If the title of a frame matches REGEXP, then IMAGE.tiff is\n\
2529selected as the image of the icon representing the frame when it's\n\
2530miniaturized. If an element is t, then Emacs tries to select an icon\n\
2531based on the filetype of the visited file.\n\
2532\n\
2533The images have to be installed in a folder called English.lproj in the\n\
2534Emacs.app folder. You have to restart Emacs after installing new icons.\n\
2535\n\
2536Example: Install an icon Gnus.tiff and execute the following code\n\
2537\n\
2538 (setq ns-icon-type-alist\n\
2539 (append ns-icon-type-alist\n\
2540 '((\"^\\\\*\\\\(Group\\\\*$\\\\|Summary \\\\|Article\\\\*$\\\\)\"\n\
2541 . \"Gnus\"))))\n\
2542\n\
2543When you miniaturize a Group, Summary or Article frame, Gnus.tiff will\n\
2544be used as the image of the icon representing the frame.");
2545 Vns_icon_type_alist = Fcons (Qt, Qnil);
2546
2547 defsubr (&Sns_read_file_name);
2548 defsubr (&Sns_get_resource);
2549 defsubr (&Sns_set_resource);
2550 defsubr (&Sxw_display_color_p); /* this and next called directly by C code */
2551 defsubr (&Sx_display_grayscale_p);
2552 defsubr (&Sns_list_fonts);
2553 defsubr (&Sns_font_name);
2554 defsubr (&Sns_list_colors);
2555 defsubr (&Sns_color_defined_p);
2556 defsubr (&Sns_color_values);
2557 defsubr (&Sns_server_max_request_size);
2558 defsubr (&Sns_server_vendor);
2559 defsubr (&Sns_server_version);
2560 defsubr (&Sns_display_pixel_width);
2561 defsubr (&Sns_display_pixel_height);
2562 defsubr (&Sns_display_usable_bounds);
2563 defsubr (&Sns_display_mm_width);
2564 defsubr (&Sns_display_mm_height);
2565 defsubr (&Sns_display_screens);
2566 defsubr (&Sns_display_planes);
2567 defsubr (&Sns_display_color_cells);
2568 defsubr (&Sns_display_visual_class);
2569 defsubr (&Sns_display_backing_store);
2570 defsubr (&Sns_display_save_under);
2571 defsubr (&Sns_create_frame);
2572 defsubr (&Sns_set_alpha);
2573 defsubr (&Sns_open_connection);
2574 defsubr (&Sns_close_connection);
2575 defsubr (&Sns_display_list);
2576
2577 defsubr (&Sns_hide_others);
2578 defsubr (&Sns_hide_emacs);
2579 defsubr (&Sns_emacs_info_panel);
2580 defsubr (&Sns_list_services);
2581 defsubr (&Sns_perform_service);
2582 defsubr (&Sns_convert_utf8_nfd_to_nfc);
2583 defsubr (&Sns_focus_frame);
2584 defsubr (&Sns_popup_prefs_panel);
2585 defsubr (&Sns_popup_font_panel);
2586 defsubr (&Sns_popup_color_panel);
2587
2588 defsubr (&Sx_show_tip);
2589 defsubr (&Sx_hide_tip);
2590
2591 /* used only in fontset.c */
2592 check_window_system_func = check_ns;
2593
2594}
2595
2596
2597
2598/* ==========================================================================
2599
2600 Class implementations
2601
2602 ========================================================================== */
2603
2604
2605@implementation EmacsSavePanel
2606#ifdef NS_IMPL_COCOA
2607/* --------------------------------------------------------------------------
2608 These are overridden to intercept on OS X: ending panel restarts NSApp
2609 event loop if it is stopped. Not sure if this is correct behavior,
2610 perhaps should check if running and if so send an appdefined.
2611 -------------------------------------------------------------------------- */
2612- (void) ok: (id)sender
2613{
2614 [super ok: sender];
2615 panelOK = 1;
2616 [NSApp stop: self];
2617}
2618- (void) cancel: (id)sender
2619{
2620 [super cancel: sender];
2621 [NSApp stop: self];
2622}
2623#endif
2624@end
2625
2626
2627@implementation EmacsOpenPanel
2628#ifdef NS_IMPL_COCOA
2629/* --------------------------------------------------------------------------
2630 These are overridden to intercept on OS X: ending panel restarts NSApp
2631 event loop if it is stopped. Not sure if this is correct behavior,
2632 perhaps should check if running and if so send an appdefined.
2633 -------------------------------------------------------------------------- */
2634- (void) ok: (id)sender
2635{
2636 [super ok: sender];
2637 panelOK = 1;
2638 [NSApp stop: self];
2639}
2640- (void) cancel: (id)sender
2641{
2642 [super cancel: sender];
2643 [NSApp stop: self];
2644}
2645#endif
2646@end
2647
2648
2649@implementation EmacsFileDelegate
2650/* --------------------------------------------------------------------------
2651 Delegate methods for Open/Save panels
2652 -------------------------------------------------------------------------- */
2653- (BOOL)panel: (id)sender isValidFilename: (NSString *)filename
2654{
2655 return YES;
2656}
2657- (BOOL)panel: (id)sender shouldShowFilename: (NSString *)filename
2658{
2659 return YES;
2660}
2661- (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename
2662 confirmed: (BOOL)okFlag
2663{
2664 return filename;
2665}
2666@end
2667
2668#endif
diff --git a/src/nsgui.h b/src/nsgui.h
new file mode 100644
index 00000000000..df38db84ade
--- /dev/null
+++ b/src/nsgui.h
@@ -0,0 +1,208 @@
1/* Definitions and headers for communication on the NeXT/Open/GNUstep API.
2 Copyright (C) 1995, 2005, 2008 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 3, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19Boston, MA 02110-1301, USA. */
20
21#ifndef __NSGUI_H__
22#define __NSGUI_H__
23
24/* this gets included from a couple of the plain (non-NS) .c files */
25#ifdef __OBJC__
26
27#ifdef NS_IMPL_COCOA
28#ifdef Z
29#warning "Z is defined. If you get a later parse error in a header, check that buffer.h or other files #define-ing Z are not included."
30#endif /* Z */
31#define Cursor FooFoo
32#undef init_process
33#endif /* NS_IMPL_COCOA */
34
35#ifdef NS_IMPL_GNUSTEP
36#undef hash_remove
37#endif
38
39#import <AppKit/AppKit.h>
40
41#ifdef NS_IMPL_GNUSTEP
42#define hash_remove emacs_hash_remove
43#endif
44
45#ifdef NS_IMPL_COCOA
46#undef Cursor
47#define init_process emacs_init_process
48#endif /* NS_IMPL_COCOA */
49#import <Foundation/NSDistantObject.h>
50
51#ifdef NS_IMPL_COCOA
52#include <AvailabilityMacros.h>
53#endif /* NS_IMPL_COCOA */
54
55#endif /* __OBJC__ */
56
57
58/* menu-related */
59#define free_widget_value(wv) xfree (wv)
60#define malloc_widget_value() ((widget_value *) memset (xmalloc \
61 (sizeof (widget_value)), 0, sizeof (widget_value)))
62
63/* Emulate XCharStruct. */
64typedef struct _XCharStruct
65{
66 int rbearing;
67 int lbearing;
68 int width;
69 int ascent;
70 int descent;
71} XCharStruct;
72
73/* 23: Fake tructure from Xlib.h to represent two-byte characters. */
74#ifndef __OBJC__
75typedef unsigned short unichar;
76#endif
77typedef unichar XChar2b;
78
79#define STORE_XCHAR2B(chp, b1, b2) \
80 (*(chp) = ((XChar2b)((((b1) & 0x00ff) << 8) | ((b2) & 0x00ff))))
81
82#define XCHAR2B_BYTE1(chp) \
83 (((*chp) & 0xff00) >> 8)
84
85#define XCHAR2B_BYTE2(chp) \
86 ((*chp) & 0x00ff)
87
88#define FACE_DEFAULT (~0)
89
90
91/* PENDING: xfaces requires these structures, but the question is are we
92 forced to use them? */
93typedef struct _XGCValues
94{
95#ifdef __OBJC__
96 NSColor *foreground;
97 NSColor *background;
98 struct ns_font *font;
99#else
100 void *foreground;
101 void *background;
102 void *font;
103#endif
104} XGCValues;
105
106typedef XGCValues * GC;
107
108#define GCForeground 0x01
109#define GCBackground 0x02
110#define GCFont 0x03
111
112#ifdef __OBJC__
113typedef id Pixmap;
114#else
115typedef void *Pixmap;
116#endif
117
118#ifdef __OBJC__
119typedef NSCursor * Cursor;
120#else
121typedef void *Cursor;
122#endif
123
124#define No_Cursor (0)
125
126#ifdef __OBJC__
127typedef NSColor * Color;
128#else
129typedef void * Color;
130#endif
131typedef int Window;
132typedef int Display;
133
134/* Xism */
135typedef Lisp_Object XrmDatabase;
136
137
138/* 23: some sort of attempt to normalize rectangle handling.. seems a bit much
139 for what is accomplished */
140typedef struct {
141 int x, y;
142 unsigned width, height;
143} XRectangle;
144
145#ifndef __OBJC__
146typedef struct _NSPoint { float x, y; } NSPoint;
147typedef struct _NSSize { float width, height; } NSSize;
148typedef struct _NSRect { NSPoint origin; NSSize size; } NSRect;
149#endif
150
151#define NativeRectangle struct _NSRect
152
153#define CONVERT_TO_XRECT(xr, nr) \
154 ((xr).x = (nr).origin.x, \
155 (xr).y = (nr).origin.y, \
156 (xr).width = (nr).size.width, \
157 (xr).height = (nr).size.height)
158
159#define CONVERT_FROM_XRECT(xr, nr) \
160 ((nr).origin.x = (xr).x, \
161 (nr).origin.y = (xr).y, \
162 (nr).size.width = (xr).width, \
163 (nr).size.height = (xr).height)
164
165#define STORE_NATIVE_RECT(nr, px, py, pwidth, pheight) \
166 ((nr).origin.x = (px), \
167 (nr).origin.y = (py), \
168 (nr).size.width = (pwidth), \
169 (nr).size.height = (pheight))
170
171
172
173
174/* This stuff needed by frame.c. */
175#define ForgetGravity 0
176#define NorthWestGravity 1
177#define NorthGravity 2
178#define NorthEastGravity 3
179#define WestGravity 4
180#define CenterGravity 5
181#define EastGravity 6
182#define SouthWestGravity 7
183#define SouthGravity 8
184#define SouthEastGravity 9
185#define StaticGravity 10
186
187#define NoValue 0x0000
188#define XValue 0x0001
189#define YValue 0x0002
190#define WidthValue 0x0004
191#define HeightValue 0x0008
192#define AllValues 0x000F
193#define XNegative 0x0010
194#define YNegative 0x0020
195
196#define USPosition (1L << 0) /* user specified x, y */
197#define USSize (1L << 1) /* user specified width, height */
198
199#define PPosition (1L << 2) /* program specified position */
200#define PSize (1L << 3) /* program specified size */
201#define PMinSize (1L << 4) /* program specified minimum size */
202#define PMaxSize (1L << 5) /* program specified maximum size */
203#define PResizeInc (1L << 6) /* program specified resize increments */
204#define PAspect (1L << 7) /* program specified min, max aspect ratios */
205#define PBaseSize (1L << 8) /* program specified base for incrementing */
206#define PWinGravity (1L << 9) /* program specified window gravity */
207
208#endif /* __NSGUI_H__ */
diff --git a/src/nsimage.m b/src/nsimage.m
new file mode 100644
index 00000000000..692190280dc
--- /dev/null
+++ b/src/nsimage.m
@@ -0,0 +1,480 @@
1/* Image support for the NeXT/Open/GNUstep and MacOSX window system.
2 Copyright (C) 1989, 1992, 1993, 1994, 2005, 2006, 2008,
3 Free Software Foundation, Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, USA.
21
22Originally by Carl Edman
23Updated by Christian Limpach (chris@nice.ch)
24OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com)
25MacOSX/Aqua port by Christophe de Dinechin (descubes@earthlink.net)
26GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
27
28*/
29
30#include "config.h"
31#include "lisp.h"
32#include "dispextern.h"
33#include "nsterm.h"
34#include "frame.h"
35
36extern Lisp_Object QCfile, QCdata;
37
38/* call tracing */
39#if 0
40int image_trace_num = 0;
41#define NSTRACE(x) fprintf (stderr, "%s:%d: [%d] " #x "\n", \
42 __FILE__, __LINE__, ++image_trace_num)
43#else
44#define NSTRACE(x)
45#endif
46
47
48/* ==========================================================================
49
50 C interface. This allows easy calling from C files. We could just
51 compile everything as Objective-C, but that might mean slower
52 compilation and possible difficulties on some platforms..
53
54 ========================================================================== */
55
56void *
57ns_image_from_XBM (unsigned char *bits, int width, int height)
58{
59 NSTRACE (ns_image_from_XBM);
60 return [[EmacsImage alloc] initFromXBM: bits
61 width: width height: height
62 flip: YES];
63}
64
65void *
66ns_image_for_XPM (int width, int height, int depth)
67{
68 NSTRACE (ns_image_for_XPM);
69 return [[EmacsImage alloc] initForXPMWithDepth: depth
70 width: width height: height];
71}
72
73void *
74ns_image_from_file (Lisp_Object file)
75{
76 NSTRACE (ns_image_from_bitmap_file);
77 return [EmacsImage allocInitFromFile: file];
78}
79
80int
81ns_load_image (struct frame *f, struct image *img,
82 Lisp_Object spec_file, Lisp_Object spec_data)
83{
84 NSTRACE (ns_load_image);
85
86 EmacsImage *eImg;
87 NSSize size;
88
89 if (NILP (spec_data))
90 {
91 eImg = [EmacsImage allocInitFromFile: spec_file];
92 }
93 else
94 {
95 NSData *data = [NSData dataWithBytes: XSTRING (spec_data)->data
96 length: SBYTES (spec_data)];
97 eImg = [[EmacsImage alloc] initWithData: data];
98 [eImg setPixmapData];
99 }
100
101 if (eImg == nil)
102 {
103 add_to_log ("Unable to load image %s", img->spec, Qnil);
104 return 0;
105 }
106
107 size = [eImg size];
108 img->width = size.width;
109 img->height = size.height;
110
111 /* 4) set img->pixmap = emacsimage */
112 img->pixmap = eImg;
113 return 1;
114}
115
116
117int
118ns_image_width (void *img)
119{
120 return [(id)img size].width;
121}
122
123int
124ns_image_height (void *img)
125{
126 return [(id)img size].height;
127}
128
129unsigned long
130ns_get_pixel (void *img, int x, int y)
131{
132 return [(EmacsImage *)img getPixelAtX: x Y: y];
133}
134
135void
136ns_put_pixel (void *img, int x, int y, unsigned long argb)
137{
138 unsigned char alpha = (argb >> 24) & 0xFF;
139 if (alpha == 0)
140 alpha = 0xFF;
141 [(EmacsImage *)img setPixelAtX: x Y: y toRed: (argb >> 16) & 0xFF
142 green: (argb >> 8) & 0xFF blue: (argb & 0xFF) alpha: alpha];
143}
144
145void
146ns_set_alpha (void *img, int x, int y, unsigned char a)
147{
148 [(EmacsImage *)img setAlphaAtX: x Y: y to: a];
149}
150
151
152/* ==========================================================================
153
154 Class supporting bitmaps and images of various sorts.
155
156 ========================================================================== */
157
158@implementation EmacsImage
159
160static EmacsImage *ImageList = nil;
161
162+ allocInitFromFile: (Lisp_Object)file
163{
164 EmacsImage *image = ImageList;
165 Lisp_Object found;
166
167 /* look for an existing image of the same name */
168 while (image != nil &&
169 [[image name] compare: [NSString stringWithUTF8String: SDATA (file)]]
170 != NSOrderedSame)
171 image = [image imageListNext];
172
173 if (image != nil)
174 {
175 [image reference];
176 return image;
177 }
178
179 /* Search bitmap-file-path for the file, if appropriate. */
180 found = x_find_image_file (file);
181 if (!STRINGP (found))
182 return nil;
183
184 image = [[EmacsImage alloc] initByReferencingFile:
185 [NSString stringWithUTF8String: SDATA (found)]];
186
187 if ([image bestRepresentationForDevice: nil] == nil)
188 {
189 [image release];
190 return nil;
191 }
192
193 [image setName: [NSString stringWithUTF8String: SDATA (file)]];
194 [image reference];
195 ImageList = [image imageListSetNext: ImageList];
196
197 return image;
198}
199
200
201- reference
202{
203 refCount++;
204 return self;
205}
206
207
208- imageListSetNext: (id)arg
209{
210 imageListNext = arg;
211 return self;
212}
213
214
215- imageListNext
216{
217 return imageListNext;
218}
219
220
221- (void)dealloc
222{
223 id list = ImageList;
224
225 if (refCount > 1)
226 {
227 refCount--;
228 return;
229 }
230
231 [stippleMask release];
232
233 if (list == self)
234 ImageList = imageListNext;
235 else
236 {
237 while (list != nil && [list imageListNext] != self)
238 list = [list imageListNext];
239 [list imageListSetNext: imageListNext];
240 }
241
242 [super dealloc];
243}
244
245
246- initFromXBM: (unsigned char *)bits width: (int)w height: (int)h
247 flip: (BOOL)flip
248{
249 return [self initFromSkipXBM: bits width: w height: h flip: flip length: 0];
250}
251
252
253- initFromSkipXBM: (unsigned char *)bits width: (int)w height: (int)h
254 flip: (BOOL)flip length: (int)length;
255{
256 int bpr = (w + 7) / 8;
257 unsigned char *planes[5];
258
259 [self initWithSize: NSMakeSize (w, h)];
260
261 bmRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: NULL
262 pixelsWide: w pixelsHigh: h
263 bitsPerSample: 8 samplesPerPixel: 4
264 hasAlpha: YES isPlanar: YES
265 colorSpaceName: NSCalibratedRGBColorSpace
266 bytesPerRow: w bitsPerPixel: 0];
267
268 [bmRep getBitmapDataPlanes: planes];
269 {
270 /* pull bits out to set the (bytewise) alpha mask */
271 int i, j, k;
272 unsigned char *s = bits;
273 unsigned char *alpha = planes[3];
274 unsigned char swt[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13,
275 3, 11, 7, 15};
276 unsigned char c, bitPat;
277
278 for (j = 0; j < h; j++)
279 for (i = 0; i < bpr; i++)
280 {
281 if (length)
282 {
283 unsigned char s1, s2;
284 while (*s++ != 'x' && s < bits + length);
285 if (s >= bits + length)
286 {
287 [bmRep release];
288 return nil;
289 }
290#define hexchar(x) (isdigit (x) ? x - '0' : x - 'a' + 10)
291 s1 = *s++;
292 s2 = *s++;
293 c = hexchar (s1) * 0x10 + hexchar (s2);
294 }
295 else
296 c = *s++;
297
298 bitPat = flip ? swt[c >> 4] | (swt[c & 0xf] << 4) : c ^ 255;
299 for (k =0; k<8; k++)
300 {
301 *alpha++ = (bitPat & 0x80) ? 0xff : 0;
302 bitPat <<= 1;
303 }
304 }
305 }
306
307 [self addRepresentation: bmRep];
308
309 bzero (planes[0], w*h);
310 bzero (planes[1], w*h);
311 bzero (planes[2], w*h);
312 [self setXBMColor: [NSColor blackColor]];
313 return self;
314}
315
316
317/* Set color for a bitmap image (see initFromSkipXBM). Note that the alpha
318 is used as a mask, so we just memset the entire array. */
319- setXBMColor: (NSColor *)color
320{
321 NSSize s = [self size];
322 int len = (int) s.width * s.height;
323 unsigned char *planes[5];
324 float r, g, b, a;
325 NSColor *rgbColor;
326
327 if (bmRep == nil || color == nil)
328 return;
329
330 if ([color colorSpaceName] != NSCalibratedRGBColorSpace)
331 rgbColor = [color colorUsingColorSpaceName: NSCalibratedRGBColorSpace];
332 else
333 rgbColor = color;
334
335 [rgbColor getRed: &r green: &g blue: &b alpha: &a];
336
337 [bmRep getBitmapDataPlanes: planes];
338
339 /* we used to just do this, but Cocoa seems to have a bug when rendering
340 an alpha-masked image onto a dark background where it bloats the mask */
341 /* memset (planes[0..2], r, g, b*0xff, len); */
342 {
343 int i, len = s.width*s.height;
344 int rr = r * 0xff, gg = g * 0xff, bb = b * 0xff;
345 for (i =0; i<len; i++)
346 if (planes[3][i] != 0)
347 {
348 planes[0][i] = rr;
349 planes[1][i] = gg;
350 planes[2][i] = bb;
351 }
352 }
353}
354
355
356- initForXPMWithDepth: (int)depth width: (int)width height: (int)height
357{
358 NSSize s = {width, height};
359 int i;
360
361 [self initWithSize: s];
362
363 bmRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: NULL
364 pixelsWide: width pixelsHigh: height
365 /* keep things simple for now */
366 bitsPerSample: 8 samplesPerPixel: 4 /*RGB+A*/
367 hasAlpha: YES isPlanar: YES
368 colorSpaceName: NSCalibratedRGBColorSpace
369 bytesPerRow: width bitsPerPixel: 0];
370
371 [bmRep getBitmapDataPlanes: pixmapData];
372 for (i =0; i<4; i++)
373 bzero (pixmapData[i], width*height);
374 [self addRepresentation: bmRep];
375 return self;
376}
377
378
379/* attempt to pull out pixmap data from a BitmapImageRep; returns NO if fails */
380- (void) setPixmapData
381{
382 NSEnumerator *reps;
383 NSImageRep *rep;
384
385 reps = [[self representations] objectEnumerator];
386 while (rep = (NSImageRep *) [reps nextObject])
387 {
388 if ([rep respondsToSelector: @selector (getBitmapDataPlanes:)])
389 {
390 bmRep = (NSBitmapImageRep *) rep;
391 onTiger = [bmRep respondsToSelector: @selector (colorAtX:y:)];
392
393 if ([bmRep numberOfPlanes] >= 3)
394 [bmRep getBitmapDataPlanes: pixmapData];
395 break;
396 }
397 }
398}
399
400
401/* note; this and next work only for image created with initForXPMWithDepth,
402 initFromSkipXBM, or where setPixmapData was called successfully */
403/* return ARGB */
404- (unsigned long) getPixelAtX: (int)x Y: (int)y
405{
406 if (bmRep == nil)
407 return 0;
408
409 /* this method is faster but won't work for bitmaps */
410 if (pixmapData[0] != NULL)
411 {
412 int loc = x + y * [self size].width;
413 return (pixmapData[3][loc] << 24) /* alpha */
414 | (pixmapData[0][loc] << 16) | (pixmapData[1][loc] << 8)
415 | (pixmapData[2][loc]);
416 }
417 else if (onTiger)
418 {
419 NSColor *color = [bmRep colorAtX: x y: y];
420 float r, g, b, a;
421 [color getRed: &r green: &g blue: &b alpha: &a];
422 return ((int)(a * 255.0) << 24)
423 | ((int)(r * 255.0) << 16) | ((int)(g * 255.0) << 8)
424 | ((int)(b * 255.0));
425
426 }
427 return 0;
428}
429
430- (void) setPixelAtX: (int)x Y: (int)y toRed: (unsigned char)r
431 green: (unsigned char)g blue: (unsigned char)b
432 alpha:(unsigned char)a;
433{
434 if (bmRep == nil)
435 return;
436
437 if (pixmapData[0] != NULL)
438 {
439 int loc = x + y * [self size].width;
440 pixmapData[0][loc] = r;
441 pixmapData[1][loc] = g;
442 pixmapData[2][loc] = b;
443 pixmapData[3][loc] = a;
444 }
445 else if (onTiger)
446 {
447 [bmRep setColor:
448 [NSColor colorWithCalibratedRed: r green: g blue: b alpha: a]
449 atX: x y: y];
450 }
451}
452
453- (void) setAlphaAtX: (int) x Y: (int) y to: (unsigned char) a
454{
455 if (bmRep == nil)
456 return;
457
458 if (pixmapData[0] != NULL)
459 {
460 int loc = x + y * [self size].width;
461
462 pixmapData[3][loc] = a;
463 }
464 else if (onTiger)
465 {
466 NSColor *color = [bmRep colorAtX: x y: y];
467 color = [color colorWithAlphaComponent: (a / 255.0)];
468 [bmRep setColor: color atX: x y: y];
469 }
470}
471
472/* returns a pattern color, which is cached here */
473- (NSColor *)stippleMask
474{
475 if (stippleMask == nil)
476 stippleMask = [[NSColor colorWithPatternImage: self] retain];
477 return stippleMask;
478}
479
480@end
diff --git a/src/nsmenu.m b/src/nsmenu.m
new file mode 100644
index 00000000000..d59732b02e4
--- /dev/null
+++ b/src/nsmenu.m
@@ -0,0 +1,1948 @@
1/* NeXT/Open/GNUstep and MacOSX Cocoa menu and toolbar module.
2 Copyright (C) 2007, 2008 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 3, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
19
20By Adrian Robert, based on code from original nsmenu.m (Carl Edman,
21Christian Limpach, Scott Bender, Christophe de Dinechin) and code in the
22Carbon version by Yamamoto Mitsuharu. */
23
24#include "config.h"
25#include "lisp.h"
26#include "window.h"
27#include "buffer.h"
28#include "keymap.h"
29#include "coding.h"
30#include "commands.h"
31#include "blockinput.h"
32#include "nsterm.h"
33#include "termhooks.h"
34#include "keyboard.h"
35
36/* for profiling */
37#include <sys/timeb.h>
38#include <sys/types.h>
39
40#define MenuStagger 10.0
41
42#if 0
43int menu_trace_num = 0;
44#define NSTRACE(x) fprintf (stderr, "%s:%d: [%d] " #x "\n", \
45 __FILE__, __LINE__, ++menu_trace_num)
46#else
47#define NSTRACE(x)
48#endif
49
50#if 0
51/* Include lisp -> C common menu parsing code */
52#define ENCODE_MENU_STRING(str) ENCODE_UTF_8 (str)
53#include "nsmenu_common.c"
54#endif
55
56extern struct widget_value;
57
58extern Lisp_Object Qundefined, Qmenu_enable, Qmenu_bar_update_hook;
59extern Lisp_Object QCtoggle, QCradio;
60
61extern Lisp_Object Vmenu_updating_frame;
62
63Lisp_Object Qdebug_on_next_call;
64extern Lisp_Object Voverriding_local_map, Voverriding_local_map_menu_flag,
65 Qoverriding_local_map, Qoverriding_terminal_local_map;
66
67extern long context_menu_value;
68EmacsMenu *mainMenu, *svcsMenu;
69
70/* NOTE: toolbar implementation is at end,
71 following complete menu implementation. */
72
73
74/* ==========================================================================
75
76 Menu: Externally-called functions
77
78 ========================================================================== */
79
80
81/*23: PENDING: not currently used, but should normalize with other terms. */
82void
83x_activate_menubar (struct frame *f)
84{
85 fprintf (stderr, "XXX: Received x_activate_menubar event.\n");
86}
87
88
89/* Supposed to discard menubar and free storage. Since we share the
90 menubar among frames and update its context for the focused window,
91 there is nothing to do here. */
92void
93free_frame_menubar (struct frame *f)
94{
95 return;
96}
97
98
99/* --------------------------------------------------------------------------
100 Update menubar. Three cases:
101 1) deep_p = 0, submenu = nil: Fresh switch onto a frame -- either set up
102 just top-level menu strings (OS X), or goto case (2) (GNUstep).
103 2) deep_p = 1, submenu = nil: Recompute all submenus.
104 3) deep_p = 1, submenu = non-nil: Update contents of a single submenu.
105 -------------------------------------------------------------------------- */
106/*#define NSMENUPROFILE 1 */
107void
108ns_update_menubar (struct frame *f, int deep_p, EmacsMenu *submenu)
109{
110 NSAutoreleasePool *pool;
111 id menu = [NSApp mainMenu];
112 static EmacsMenu *last_submenu = nil;
113 BOOL needsSet = NO;
114 const char *submenuTitle = [[submenu title] UTF8String];
115 extern int waiting_for_input;
116 int owfi;
117 Lisp_Object items;
118 widget_value *wv, *first_wv, *prev_wv = 0;
119 int i;
120
121#ifdef NSMENUPROFILE
122 struct timeb tb;
123 long t;
124#endif
125
126 NSTRACE (set_frame_menubar);
127
128 if (f != SELECTED_FRAME ())
129 return;
130 XSETFRAME (Vmenu_updating_frame, f);
131/*fprintf (stderr, "ns_update_menubar: frame: %p\tdeep: %d\tsub: %p\n", f, deep_p, submenu); */
132
133 BLOCK_INPUT;
134 pool = [[NSAutoreleasePool alloc] init];
135
136 /* Menu may have been created automatically; if so, discard it. */
137 if ([menu isKindOfClass: [EmacsMenu class]] == NO)
138 {
139 [menu release];
140 menu = nil;
141 }
142
143 if (menu == nil)
144 {
145 menu = [[EmacsMenu alloc] initWithTitle: @"Emacs"];
146 needsSet = YES;
147 }
148 else
149 { /* close up anything on there */
150 id attMenu = [menu attachedMenu];
151 if (attMenu != nil)
152 [attMenu close];
153 }
154
155#ifdef NSMENUPROFILE
156 ftime (&tb);
157 t = -(1000*tb.time+tb.millitm);
158#endif
159
160 /* widget_value is a straightforward object translation of emacs's
161 Byzantine lisp menu structures */
162 wv = xmalloc_widget_value ();
163 wv->name = "Emacs";
164 wv->value = 0;
165 wv->enabled = 1;
166 wv->button_type = BUTTON_TYPE_NONE;
167 wv->help = Qnil;
168 first_wv = wv;
169
170#ifdef NS_IMPL_GNUSTEP
171 deep_p = 1; /* until GNUstep NSMenu implements the Panther delegation model */
172#endif
173
174 if (deep_p)
175 {
176 /* Fully parse one or more of the submenus. */
177 int n = 0;
178 int *submenu_start, *submenu_end;
179 int *submenu_top_level_items, *submenu_n_panes;
180 struct buffer *prev = current_buffer;
181 Lisp_Object buffer;
182 int specpdl_count = SPECPDL_INDEX ();
183 int previous_menu_items_used = f->menu_bar_items_used;
184 Lisp_Object *previous_items
185 = (Lisp_Object *) alloca (previous_menu_items_used
186 * sizeof (Lisp_Object));
187
188 /* lisp preliminaries */
189 buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->buffer;
190 specbind (Qinhibit_quit, Qt);
191 specbind (Qdebug_on_next_call, Qnil);
192 record_unwind_save_match_data ();
193 if (NILP (Voverriding_local_map_menu_flag))
194 {
195 specbind (Qoverriding_terminal_local_map, Qnil);
196 specbind (Qoverriding_local_map, Qnil);
197 }
198 set_buffer_internal_1 (XBUFFER (buffer));
199
200 /* PENDING: for some reason this is not needed in other terms,
201 but some menu updates call Info-extract-pointer which causes
202 abort-on-error if waiting-for-input. Needs further investigation. */
203 owfi = waiting_for_input;
204 waiting_for_input = 0;
205
206 /* lucid hook and possible reset */
207 safe_run_hooks (Qactivate_menubar_hook);
208 if (! NILP (Vlucid_menu_bar_dirty_flag))
209 call0 (Qrecompute_lucid_menubar);
210 safe_run_hooks (Qmenu_bar_update_hook);
211 FRAME_MENU_BAR_ITEMS (f) = menu_bar_items (FRAME_MENU_BAR_ITEMS (f));
212
213 /* Now ready to go */
214 items = FRAME_MENU_BAR_ITEMS (f);
215
216 /* Save the frame's previous menu bar contents data */
217 if (previous_menu_items_used)
218 bcopy (XVECTOR (f->menu_bar_vector)->contents, previous_items,
219 previous_menu_items_used * sizeof (Lisp_Object));
220
221 /* parse stage 1: extract from lisp */
222 save_menu_items ();
223
224 menu_items = f->menu_bar_vector;
225 menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
226 submenu_start = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
227 submenu_end = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
228 submenu_n_panes = (int *) alloca (XVECTOR (items)->size * sizeof (int));
229 submenu_top_level_items
230 = (int *) alloca (XVECTOR (items)->size * sizeof (int *));
231 init_menu_items ();
232 for (i = 0; i < XVECTOR (items)->size; i += 4)
233 {
234 Lisp_Object key, string, maps;
235
236 key = XVECTOR (items)->contents[i];
237 string = XVECTOR (items)->contents[i + 1];
238 maps = XVECTOR (items)->contents[i + 2];
239 if (NILP (string))
240 break;
241
242 /* PENDING: we'd like to only parse the needed submenu, but this
243 was causing crashes in the _common parsing code.. need to make
244 sure proper initialization done.. */
245/* if (submenu && strcmp (submenuTitle, SDATA (string)))
246 continue; */
247
248 submenu_start[i] = menu_items_used;
249
250 menu_items_n_panes = 0;
251 submenu_top_level_items[i] = parse_single_submenu (key, string, maps);
252 submenu_n_panes[i] = menu_items_n_panes;
253 submenu_end[i] = menu_items_used;
254 n++;
255 }
256
257 finish_menu_items ();
258 waiting_for_input = owfi;
259
260
261 if (submenu && n == 0)
262 {
263 /* should have found a menu for this one but didn't */
264 fprintf (stderr, "ERROR: did not find lisp menu for submenu '%s'.\n",
265 submenuTitle);
266 discard_menu_items ();
267 unbind_to (specpdl_count, Qnil);
268 [pool release];
269 UNBLOCK_INPUT;
270 return;
271 }
272
273 /* parse stage 2: insert into lucid 'widget_value' structures
274 [comments in other terms say not to evaluate lisp code here] */
275 wv = xmalloc_widget_value ();
276 wv->name = "menubar";
277 wv->value = 0;
278 wv->enabled = 1;
279 wv->button_type = BUTTON_TYPE_NONE;
280 wv->help = Qnil;
281 first_wv = wv;
282
283 for (i = 0; i < 4*n; i += 4)
284 {
285 menu_items_n_panes = submenu_n_panes[i];
286 wv = digest_single_submenu (submenu_start[i], submenu_end[i],
287 submenu_top_level_items[i]);
288 if (prev_wv)
289 prev_wv->next = wv;
290 else
291 first_wv->contents = wv;
292 /* Don't set wv->name here; GC during the loop might relocate it. */
293 wv->enabled = 1;
294 wv->button_type = BUTTON_TYPE_NONE;
295 prev_wv = wv;
296 }
297
298 set_buffer_internal_1 (prev);
299
300 /* Compare the new menu items with previous, and leave off if no change */
301 /* PENDING: following other terms here, but seems like this should be
302 done before parse stage 2 above, since its results aren't used */
303 if (previous_menu_items_used
304 && (!submenu || (submenu && submenu == last_submenu))
305 && menu_items_used == previous_menu_items_used)
306 {
307 for (i = 0; i < previous_menu_items_used; i++)
308 /* PENDING: this ALWAYS fails on Buffers menu items.. something
309 about their strings causes them to change every time, so we
310 double-check failures */
311 if (!EQ (previous_items[i], XVECTOR (menu_items)->contents[i]))
312 if (!(STRINGP (previous_items[i])
313 && STRINGP (XVECTOR (menu_items)->contents[i])
314 && !strcmp (SDATA (previous_items[i]),
315 SDATA (XVECTOR (menu_items)->contents[i]))))
316 break;
317 if (i == previous_menu_items_used)
318 {
319 /* No change.. */
320
321#ifdef NSMENUPROFILE
322 ftime (&tb);
323 t += 1000*tb.time+tb.millitm;
324 fprintf (stderr, "NO CHANGE! CUTTING OUT after %ld msec.\n", t);
325#endif
326
327 free_menubar_widget_value_tree (first_wv);
328 discard_menu_items ();
329 unbind_to (specpdl_count, Qnil);
330 [pool release];
331 UNBLOCK_INPUT;
332 return;
333 }
334 }
335 /* The menu items are different, so store them in the frame */
336 /* PENDING: this is not correct for single-submenu case */
337 f->menu_bar_vector = menu_items;
338 f->menu_bar_items_used = menu_items_used;
339
340 /* Calls restore_menu_items, etc., as they were outside */
341 unbind_to (specpdl_count, Qnil);
342
343 /* Parse stage 2a: now GC cannot happen during the lifetime of the
344 widget_value, so it's safe to store data from a Lisp_String */
345 wv = first_wv->contents;
346 for (i = 0; i < XVECTOR (items)->size; i += 4)
347 {
348 Lisp_Object string;
349 string = XVECTOR (items)->contents[i + 1];
350 if (NILP (string))
351 break;
352/* if (submenu && strcmp (submenuTitle, SDATA (string)))
353 continue; */
354
355 wv->name = (char *) SDATA (string);
356 update_submenu_strings (wv->contents);
357 wv = wv->next;
358 }
359
360 /* Now, update the NS menu; if we have a submenu, use that, otherwise
361 create a new menu for each sub and fill it. */
362 if (submenu)
363 {
364 for (wv = first_wv->contents; wv; wv = wv->next)
365 {
366 if (!strcmp (submenuTitle, wv->name))
367 {
368 [submenu fillWithWidgetValue: wv->contents];
369 last_submenu = submenu;
370 break;
371 }
372 }
373 }
374 else
375 {
376 [menu fillWithWidgetValue: first_wv->contents];
377 }
378
379 }
380 else
381 {
382 static int n_previous_strings = 0;
383 static char previous_strings[100][10];
384 static struct frame *last_f = NULL;
385 int n;
386 Lisp_Object string;
387
388 /* Make widget-value tree w/ just the top level menu bar strings */
389 items = FRAME_MENU_BAR_ITEMS (f);
390 if (NILP (items))
391 {
392 [pool release];
393 UNBLOCK_INPUT;
394 return;
395 }
396
397
398 /* check if no change.. this mechanism is a bit rough, but ready */
399 n = XVECTOR (items)->size / 4;
400 if (f == last_f && n_previous_strings == n)
401 {
402 for (i = 0; i<n; i++)
403 {
404 string = XVECTOR (items)->contents[4*i+1];
405
406 if (!string)
407 continue;
408 if (NILP (string))
409 if (previous_strings[i][0])
410 break;
411 else
412 continue;
413 if (strncmp (previous_strings[i], SDATA (string), 10))
414 break;
415 }
416
417 if (i == n)
418 {
419 [pool release];
420 UNBLOCK_INPUT;
421 return;
422 }
423 }
424
425 [menu clear];
426 for (i = 0; i < XVECTOR (items)->size; i += 4)
427 {
428 string = XVECTOR (items)->contents[i + 1];
429 if (NILP (string))
430 break;
431
432 if (n < 100)
433 strncpy (previous_strings[i/4], SDATA (string), 10);
434
435 wv = xmalloc_widget_value ();
436 wv->name = (char *) SDATA (string);
437 wv->value = 0;
438 wv->enabled = 1;
439 wv->button_type = BUTTON_TYPE_NONE;
440 wv->help = Qnil;
441 wv->call_data = (void *) (EMACS_INT) (-1);
442
443#ifdef NS_IMPL_COCOA
444 /* we'll update the real copy under app menu when time comes */
445 if (!strcmp ("Services", wv->name))
446 {
447 /* but we need to make sure it will update on demand */
448 [svcsMenu setFrame: f];
449 [svcsMenu setDelegate: svcsMenu];
450 }
451 else
452#endif
453 [menu addSubmenuWithTitle: wv->name forFrame: f];
454
455 if (prev_wv)
456 prev_wv->next = wv;
457 else
458 first_wv->contents = wv;
459 prev_wv = wv;
460 }
461
462 last_f = f;
463 if (n < 100)
464 n_previous_strings = n;
465 else
466 n_previous_strings = 0;
467
468 }
469 free_menubar_widget_value_tree (first_wv);
470
471
472#ifdef NSMENUPROFILE
473 ftime (&tb);
474 t += 1000*tb.time+tb.millitm;
475 fprintf (stderr, "Menu update took %ld msec.\n", t);
476#endif
477
478 /* set main menu */
479 if (needsSet)
480 [NSApp setMainMenu: menu];
481
482 [pool release];
483 UNBLOCK_INPUT;
484
485}
486
487
488/* Main emacs core entry point for menubar menus: called to indicate that the
489 frame's menus have changed, and the *step representation should be updated
490 from Lisp. */
491void
492set_frame_menubar (struct frame *f, int first_time, int deep_p)
493{
494 ns_update_menubar (f, deep_p, nil);
495}
496
497
498/* Utility (from macmenu.c): is this item a separator? */
499static int
500name_is_separator (name)
501 const char *name;
502{
503 const char *start = name;
504
505 /* Check if name string consists of only dashes ('-'). */
506 while (*name == '-') name++;
507 /* Separators can also be of the form "--:TripleSuperMegaEtched"
508 or "--deep-shadow". We don't implement them yet, se we just treat
509 them like normal separators. */
510 return (*name == '\0' || start + 2 == name);
511}
512
513
514/* ==========================================================================
515
516 Menu: class implementation
517
518 ========================================================================== */
519
520
521/* Menu that can define itself from Emacs "widget_value"s and will lazily
522 update itself when user clicked. Based on Carbon/AppKit implementation
523 by Yamamoto Mitsuharu. */
524@implementation EmacsMenu
525
526/* override designated initializer */
527- initWithTitle: (NSString *)title
528{
529 if (self = [super initWithTitle: title])
530 [self setAutoenablesItems: NO];
531 return self;
532}
533
534
535/* used for top-level */
536- initWithTitle: (NSString *)title frame: (struct frame *)f
537{
538 [self initWithTitle: title];
539 frame = f;
540#ifdef NS_IMPL_COCOA
541 [self setDelegate: self];
542#endif
543 return self;
544}
545
546
547- (void)setFrame: (struct frame *)f
548{
549 frame = f;
550}
551
552
553/* delegate method called when a submenu is being opened: run a 'deep' call
554 to set_frame_menubar */
555- (void)menuNeedsUpdate: (NSMenu *)menu
556{
557 NSEvent *event = [[FRAME_NS_VIEW (frame) window] currentEvent];
558 /* HACK: Cocoa/Carbon will request update on every keystroke
559 via IsMenuKeyEvent -> CheckMenusForKeyEvent. These are not needed
560 since key equivalents are handled through emacs.
561 On Leopard, even keystroke events generate SystemDefined events, but
562 their subtype is 8. */
563 if ([event type] != NSSystemDefined || [event subtype] == 8)
564 return;
565/*fprintf (stderr, "Updating menu '%s'\n", [[self title] UTF8String]); NSLog (@"%@\n", event); */
566 ns_update_menubar (frame, 1, self);
567}
568
569
570- (BOOL)performKeyEquivalent: (NSEvent *)theEvent
571{
572 if (SELECTED_FRAME () && FRAME_NS_P (SELECTED_FRAME ())
573 && FRAME_NS_VIEW (SELECTED_FRAME ()))
574 [FRAME_NS_VIEW (SELECTED_FRAME ()) keyDown: theEvent];
575 return YES;
576}
577
578
579/* parse a wdiget_value's key rep (examples: 's-p', 's-S', '(C-x C-s)', '<f13>')
580 into an accelerator string */
581-(NSString *)parseKeyEquiv: (char *)key
582{
583 char *tpos = key;
584 keyEquivModMask = 0;
585 /* currently we just parse 'super' combinations;
586 later we'll set keyEquivModMask */
587 if (!key || !strlen (key))
588 return @"";
589
590 while (*tpos == ' ' || *tpos == '(')
591 tpos++;
592 if (*tpos != 's'/* || tpos[3] != ')'*/)
593 return @"";
594 return [NSString stringWithFormat: @"%c", tpos[2]];
595}
596
597- (id <NSMenuItem>)addItemWithWidgetValue: (void *)wvptr
598{
599 id <NSMenuItem> item;
600 widget_value *wv = (widget_value *)wvptr;
601
602 if (name_is_separator (wv->name))
603 {
604 item = [NSMenuItem separatorItem];
605 [self addItem: item];
606 }
607 else
608 {
609 NSString *title, *keyEq;
610 title = [NSString stringWithUTF8String: wv->name];
611 if (title == nil)
612 title = @"< ? >"; /* (get out in the open so we know about it) */
613
614 keyEq = [self parseKeyEquiv: wv->key];
615
616 item = [self addItemWithTitle: (NSString *)title
617 action: @selector (menuDown:)
618 keyEquivalent: keyEq];
619 if (keyEquivModMask)
620 [item setKeyEquivalentModifierMask: keyEquivModMask];
621
622 [item setEnabled: wv->enabled];
623
624 /* Draw radio buttons and tickboxes */
625 if (wv->selected && (wv->button_type == BUTTON_TYPE_TOGGLE ||
626 wv->button_type == BUTTON_TYPE_RADIO))
627 [item setState: NSOnState];
628 else
629 [item setState: NSOffState];
630
631 [item setTag: (int)wv->call_data];
632 }
633
634 return item;
635}
636
637
638/* convenience */
639-(void) clear
640{
641 int n;
642
643 for (n = [self numberOfItems]-1; n >= 0; n--)
644 {
645 NSMenuItem *item = [self itemAtIndex: n];
646 NSString *title = [item title];
647 if (([title length] == 0 || [@"Apple" isEqualToString: title])
648 && ![item isSeparatorItem])
649 continue;
650 [self removeItemAtIndex: n];
651 }
652}
653
654
655- (void)fillWithWidgetValue: (void *)wvptr
656{
657 widget_value *wv = (widget_value *)wvptr;
658
659 /* clear existing contents */
660 [self setMenuChangedMessagesEnabled: NO];
661 [self clear];
662
663 /* add new contents */
664 for (; wv != NULL; wv = wv->next)
665 {
666 id <NSMenuItem> item = [self addItemWithWidgetValue: wv];
667
668 if (wv->contents)
669 {
670 EmacsMenu *submenu = [[EmacsMenu alloc] initWithTitle: @"Submenu"];
671
672 [self setSubmenu: submenu forItem: item];
673 [submenu fillWithWidgetValue: wv->contents];
674 [submenu release];
675 [item setAction: nil];
676 }
677 }
678
679 [self setMenuChangedMessagesEnabled: YES];
680#ifdef NS_IMPL_GNUSTEP
681 if ([[self window] isVisible])
682 [self sizeToFit];
683#else
684 if ([self supermenu] == nil)
685 [self sizeToFit];
686#endif
687}
688
689
690/* adds an empty submenu and returns it */
691- (EmacsMenu *)addSubmenuWithTitle: (char *)title forFrame: (struct frame *)f
692{
693 NSString *titleStr = [NSString stringWithUTF8String: title];
694 id <NSMenuItem> item =
695 [self addItemWithTitle: titleStr
696 action: nil /*@selector (menuDown:) */
697 keyEquivalent: @""];
698 EmacsMenu *submenu = [[EmacsMenu alloc] initWithTitle: titleStr frame: f];
699 [self setSubmenu: submenu forItem: item];
700 [submenu release];
701 return submenu;
702}
703
704/* run a menu in popup mode */
705- (Lisp_Object)runMenuAt: (NSPoint)p forFrame: (struct frame *)f
706 keymaps: (int)keymaps
707{
708 EmacsView *view = FRAME_NS_VIEW (f);
709/* p = [view convertPoint:p fromView: nil]; */
710 p.y = NSHeight ([view frame]) - p.y;
711 NSEvent *e = [[view window] currentEvent];
712 NSEvent *event = [NSEvent mouseEventWithType: NSRightMouseDown
713 location: p
714 modifierFlags: 0
715 timestamp: [e timestamp]
716 windowNumber: [[view window] windowNumber]
717 context: [e context]
718 eventNumber: 0/*[e eventNumber] */
719 clickCount: 1
720 pressure: 0];
721 long retVal;
722
723 context_menu_value = -1;
724 [NSMenu popUpContextMenu: self withEvent: event forView: view];
725 retVal = context_menu_value;
726 context_menu_value = 0;
727 return retVal > 0 ?
728 find_and_return_menu_selection (f, keymaps, (void *)retVal) : Qnil;
729}
730
731@end /* EmacsMenu */
732
733
734
735/* ==========================================================================
736
737 Context Menu: implementing functions
738
739 ========================================================================== */
740
741static Lisp_Object
742cleanup_popup_menu (Lisp_Object arg)
743{
744 discard_menu_items ();
745 return Qnil;
746}
747
748
749static Lisp_Object
750ns_popup_menu (Lisp_Object position, Lisp_Object menu)
751{
752 EmacsMenu *pmenu;
753 struct frame *f = NULL;
754 NSPoint p;
755 Lisp_Object window, x, y, tem, keymap, title;
756 struct gcpro gcpro1;
757 int specpdl_count = SPECPDL_INDEX (), specpdl_count2;
758 char *error_name = NULL;
759 int keymaps = 0;
760 widget_value *wv, *first_wv = 0;
761
762 NSTRACE (ns_popup_menu);
763
764 if (!NILP (position))
765 {
766 check_ns ();
767
768 if (EQ (position, Qt)
769 || (CONSP (position) && (EQ (XCAR (position), Qmenu_bar)
770 || EQ (XCAR (position), Qtool_bar))))
771 {
772 /* Use the mouse's current position. */
773 struct frame *new_f = SELECTED_FRAME ();
774
775 if (FRAME_TERMINAL (new_f)->mouse_position_hook)
776 (*FRAME_TERMINAL (new_f)->mouse_position_hook)
777 (&new_f, 0, 0, 0, &x, &y, 0);
778 if (new_f != 0)
779 XSETFRAME (window, new_f);
780 else
781 {
782 window = selected_window;
783 x = make_number (0);
784 y = make_number (0);
785 }
786 }
787 else
788 {
789 CHECK_CONS (position);
790 tem = Fcar (position);
791 if (XTYPE (tem) == Lisp_Cons)
792 {
793 window = Fcar (Fcdr (position));
794 x = Fcar (tem);
795 y = Fcar (Fcdr (tem));
796 }
797 else
798 {
799 tem = Fcar (Fcdr (position));
800 window = Fcar (tem);
801 tem = Fcar (Fcdr (Fcdr (tem)));
802 x = Fcar (tem);
803 y = Fcdr (tem);
804 }
805 }
806
807 CHECK_NUMBER (x);
808 CHECK_NUMBER (y);
809
810 if (FRAMEP (window))
811 {
812 f = XFRAME (window);
813
814 p.x = 0;
815 p.y = 0;
816 }
817 else
818 {
819 struct window *win = XWINDOW (window);
820 CHECK_LIVE_WINDOW (window);
821 f = XFRAME (WINDOW_FRAME (win));
822 p.x = FRAME_COLUMN_WIDTH (f) * WINDOW_LEFT_EDGE_COL (win);
823 p.y = FRAME_LINE_HEIGHT (f) * WINDOW_TOP_EDGE_LINE (win);
824 }
825
826 p.x += XINT (x); p.y += XINT (y);
827
828 XSETFRAME (Vmenu_updating_frame, f);
829 }
830 else
831 { /* no position given */
832 /* PENDING: if called during dump, we need to stop precomputation of
833 key equivalents (see below) because the keydefs in ns-win.el have
834 not been loaded yet. */
835 if (noninteractive)
836 return Qnil;
837 Vmenu_updating_frame = Qnil;
838 }
839
840 /* now parse the lisp menus */
841 record_unwind_protect (unuse_menu_items, Qnil);
842 title = Qnil;
843 GCPRO1 (title);
844
845 /* Decode the menu items from what was specified. */
846
847 keymap = get_keymap (menu, 0, 0);
848 if (CONSP (keymap))
849 {
850 /* We were given a keymap. Extract menu info from the keymap. */
851 Lisp_Object prompt;
852
853 /* Extract the detailed info to make one pane. */
854 keymap_panes (&menu, 1, NILP (position));
855
856 /* Search for a string appearing directly as an element of the keymap.
857 That string is the title of the menu. */
858 prompt = Fkeymap_prompt (keymap);
859 title = NILP (prompt) ? build_string ("Select") : prompt;
860
861 /* Make that be the pane title of the first pane. */
862 if (!NILP (prompt) && menu_items_n_panes >= 0)
863 XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = prompt;
864
865 keymaps = 1;
866 }
867 else if (CONSP (menu) && KEYMAPP (XCAR (menu)))
868 {
869 /* We were given a list of keymaps. */
870 int nmaps = XFASTINT (Flength (menu));
871 Lisp_Object *maps
872 = (Lisp_Object *) alloca (nmaps * sizeof (Lisp_Object));
873 int i;
874
875 title = Qnil;
876
877 /* The first keymap that has a prompt string
878 supplies the menu title. */
879 for (tem = menu, i = 0; CONSP (tem); tem = XCDR (tem))
880 {
881 Lisp_Object prompt;
882
883 maps[i++] = keymap = get_keymap (XCAR (tem), 1, 0);
884
885 prompt = Fkeymap_prompt (keymap);
886 if (NILP (title) && !NILP (prompt))
887 title = prompt;
888 }
889
890 /* Extract the detailed info to make one pane. */
891 keymap_panes (maps, nmaps, NILP (position));
892
893 /* Make the title be the pane title of the first pane. */
894 if (!NILP (title) && menu_items_n_panes >= 0)
895 XVECTOR (menu_items)->contents[MENU_ITEMS_PANE_NAME] = title;
896
897 keymaps = 1;
898 }
899 else
900 {
901 /* We were given an old-fashioned menu. */
902 title = Fcar (menu);
903 CHECK_STRING (title);
904
905 list_of_panes (Fcdr (menu));
906
907 keymaps = 0;
908 }
909
910 unbind_to (specpdl_count, Qnil);
911
912 /* If no position given, that was a signal to just precompute and cache
913 key equivalents, which was a side-effect of what we just did. */
914 if (NILP (position))
915 {
916 discard_menu_items ();
917 UNGCPRO;
918 return Qnil;
919 }
920
921 record_unwind_protect (cleanup_popup_menu, Qnil);
922 BLOCK_INPUT;
923
924 /* now parse stage 2 as in ns_update_menubar */
925 wv = xmalloc_widget_value ();
926 wv->name = "contextmenu";
927 wv->value = 0;
928 wv->enabled = 1;
929 wv->button_type = BUTTON_TYPE_NONE;
930 wv->help = Qnil;
931 first_wv = wv;
932
933 specpdl_count2 = SPECPDL_INDEX ();
934
935#if 0
936 /*PENDING: a couple of one-line differences prevent reuse */
937 wv = digest_single_submenu (0, menu_items_used, Qnil);
938#else
939 {
940 widget_value *save_wv = 0, *prev_wv = 0;
941 widget_value **submenu_stack
942 = (widget_value **) alloca (menu_items_used * sizeof (widget_value *));
943/* Lisp_Object *subprefix_stack
944 = (Lisp_Object *) alloca (menu_items_used * sizeof (Lisp_Object)); */
945 int submenu_depth = 0;
946 int first_pane = 1;
947 int i;
948
949 /* Loop over all panes and items, filling in the tree. */
950 i = 0;
951 while (i < menu_items_used)
952 {
953 if (EQ (XVECTOR (menu_items)->contents[i], Qnil))
954 {
955 submenu_stack[submenu_depth++] = save_wv;
956 save_wv = prev_wv;
957 prev_wv = 0;
958 first_pane = 1;
959 i++;
960 }
961 else if (EQ (XVECTOR (menu_items)->contents[i], Qlambda))
962 {
963 prev_wv = save_wv;
964 save_wv = submenu_stack[--submenu_depth];
965 first_pane = 0;
966 i++;
967 }
968 else if (EQ (XVECTOR (menu_items)->contents[i], Qt)
969 && submenu_depth != 0)
970 i += MENU_ITEMS_PANE_LENGTH;
971 /* Ignore a nil in the item list.
972 It's meaningful only for dialog boxes. */
973 else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
974 i += 1;
975 else if (EQ (XVECTOR (menu_items)->contents[i], Qt))
976 {
977 /* Create a new pane. */
978 Lisp_Object pane_name, prefix;
979 char *pane_string;
980
981 pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
982 prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
983
984#ifndef HAVE_MULTILINGUAL_MENU
985 if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
986 {
987 pane_name = ENCODE_MENU_STRING (pane_name);
988 ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
989 }
990#endif
991 pane_string = (NILP (pane_name)
992 ? "" : (char *) SDATA (pane_name));
993 /* If there is just one top-level pane, put all its items directly
994 under the top-level menu. */
995 if (menu_items_n_panes == 1)
996 pane_string = "";
997
998 /* If the pane has a meaningful name,
999 make the pane a top-level menu item
1000 with its items as a submenu beneath it. */
1001 if (!keymaps && strcmp (pane_string, ""))
1002 {
1003 wv = xmalloc_widget_value ();
1004 if (save_wv)
1005 save_wv->next = wv;
1006 else
1007 first_wv->contents = wv;
1008 wv->name = pane_string;
1009 if (keymaps && !NILP (prefix))
1010 wv->name++;
1011 wv->value = 0;
1012 wv->enabled = 1;
1013 wv->button_type = BUTTON_TYPE_NONE;
1014 wv->help = Qnil;
1015 save_wv = wv;
1016 prev_wv = 0;
1017 }
1018 else if (first_pane)
1019 {
1020 save_wv = wv;
1021 prev_wv = 0;
1022 }
1023 first_pane = 0;
1024 i += MENU_ITEMS_PANE_LENGTH;
1025 }
1026 else
1027 {
1028 /* Create a new item within current pane. */
1029 Lisp_Object item_name, enable, descrip, def, type, selected, help;
1030 item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
1031 enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
1032 descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
1033 def = AREF (menu_items, i + MENU_ITEMS_ITEM_DEFINITION);
1034 type = AREF (menu_items, i + MENU_ITEMS_ITEM_TYPE);
1035 selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED);
1036 help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
1037
1038#ifndef HAVE_MULTILINGUAL_MENU
1039 if (STRINGP (item_name) && STRING_MULTIBYTE (item_name))
1040 {
1041 item_name = ENCODE_MENU_STRING (item_name);
1042 ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
1043 }
1044
1045 if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
1046 {
1047 descrip = ENCODE_MENU_STRING (descrip);
1048 ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
1049 }
1050#endif /* not HAVE_MULTILINGUAL_MENU */
1051
1052 wv = xmalloc_widget_value ();
1053 if (prev_wv)
1054 prev_wv->next = wv;
1055 else
1056 save_wv->contents = wv;
1057 wv->name = (char *) SDATA (item_name);
1058 if (!NILP (descrip))
1059 wv->key = (char *) SDATA (descrip);
1060 wv->value = 0;
1061 /* If this item has a null value,
1062 make the call_data null so that it won't display a box
1063 when the mouse is on it. */
1064 wv->call_data =
1065 !NILP (def) ? (void *) &XVECTOR (menu_items)->contents[i] : 0;
1066 wv->enabled = !NILP (enable);
1067
1068 if (NILP (type))
1069 wv->button_type = BUTTON_TYPE_NONE;
1070 else if (EQ (type, QCtoggle))
1071 wv->button_type = BUTTON_TYPE_TOGGLE;
1072 else if (EQ (type, QCradio))
1073 wv->button_type = BUTTON_TYPE_RADIO;
1074 else
1075 abort ();
1076
1077 wv->selected = !NILP (selected);
1078
1079 if (! STRINGP (help))
1080 help = Qnil;
1081
1082 wv->help = help;
1083
1084 prev_wv = wv;
1085
1086 i += MENU_ITEMS_ITEM_LENGTH;
1087 }
1088 }
1089 }
1090#endif
1091
1092 if (!NILP (title))
1093 {
1094 widget_value *wv_title = xmalloc_widget_value ();
1095 widget_value *wv_sep = xmalloc_widget_value ();
1096
1097 /* Maybe replace this separator with a bitmap or owner-draw item
1098 so that it looks better. Having two separators looks odd. */
1099 wv_sep->name = "--";
1100 wv_sep->next = first_wv->contents;
1101 wv_sep->help = Qnil;
1102
1103#ifndef HAVE_MULTILINGUAL_MENU
1104 if (STRING_MULTIBYTE (title))
1105 title = ENCODE_MENU_STRING (title);
1106#endif
1107
1108 wv_title->name = (char *) SDATA (title);
1109 wv_title->enabled = NULL;
1110 wv_title->button_type = BUTTON_TYPE_NONE;
1111 wv_title->help = Qnil;
1112 wv_title->next = wv_sep;
1113 first_wv->contents = wv_title;
1114 }
1115
1116 pmenu = [[EmacsMenu alloc] initWithTitle:
1117 [NSString stringWithUTF8String: SDATA (title)]];
1118 [pmenu fillWithWidgetValue: first_wv->contents];
1119 free_menubar_widget_value_tree (first_wv);
1120 unbind_to (specpdl_count2, Qnil);
1121
1122 tem = [pmenu runMenuAt: p forFrame: f keymaps: keymaps];
1123 [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
1124
1125 UNBLOCK_INPUT;
1126 unbind_to (specpdl_count, Qnil);
1127 UNGCPRO;
1128
1129 if (error_name) error (error_name);
1130 return tem;
1131}
1132
1133
1134
1135
1136/* ==========================================================================
1137
1138 Toolbar: externally-called functions
1139
1140 ========================================================================== */
1141
1142void
1143free_frame_tool_bar (FRAME_PTR f)
1144/* --------------------------------------------------------------------------
1145 Under NS we just hide the toolbar until it might be needed again.
1146 -------------------------------------------------------------------------- */
1147{
1148 [[FRAME_NS_VIEW (f) toolbar] setVisible: NO];
1149}
1150
1151void
1152update_frame_tool_bar (FRAME_PTR f)
1153/* --------------------------------------------------------------------------
1154 Update toolbar contents
1155 -------------------------------------------------------------------------- */
1156{
1157 int i;
1158 EmacsToolbar *toolbar = [FRAME_NS_VIEW (f) toolbar];
1159
1160 if (NILP (f->tool_bar_lines) || !INTEGERP (f->tool_bar_lines))
1161 return;
1162
1163 [toolbar clearActive];
1164
1165 /* update EmacsToolbar as in GtkUtils, build items list */
1166 for (i = 0; i < f->n_tool_bar_items; ++i)
1167 {
1168#define TOOLPROP(IDX) AREF (f->tool_bar_items, \
1169 i * TOOL_BAR_ITEM_NSLOTS + (IDX))
1170
1171 BOOL enabled_p = !NILP (TOOLPROP (TOOL_BAR_ITEM_ENABLED_P));
1172 BOOL selected_p = !NILP (TOOLPROP (TOOL_BAR_ITEM_SELECTED_P));
1173 int idx;
1174 int img_id;
1175 struct image *img;
1176 Lisp_Object image;
1177 Lisp_Object helpObj;
1178 char *helpText;
1179
1180 /* If image is a vector, choose the image according to the
1181 button state. */
1182 image = TOOLPROP (TOOL_BAR_ITEM_IMAGES);
1183 if (VECTORP (image))
1184 {
1185 /* NS toolbar auto-computes disabled and selected images */
1186 idx = TOOL_BAR_IMAGE_ENABLED_SELECTED;
1187 xassert (ASIZE (image) >= idx);
1188 image = AREF (image, idx);
1189 }
1190 else
1191 {
1192 idx = -1;
1193 }
1194 /* Ignore invalid image specifications. */
1195 if (!valid_image_p (image))
1196 {
1197 NSLog (@"Invalid image for toolbar item");
1198 continue;
1199 }
1200
1201 img_id = lookup_image (f, image);
1202 img = IMAGE_FROM_ID (f, img_id);
1203 prepare_image_for_display (f, img);
1204
1205 if (img->load_failed_p || img->pixmap == nil)
1206 {
1207 NSLog (@"Could not prepare toolbar image for display.");
1208 continue;
1209 }
1210
1211 helpObj = TOOLPROP (TOOL_BAR_ITEM_HELP);
1212 if (NILP (helpObj))
1213 helpObj = TOOLPROP (TOOL_BAR_ITEM_CAPTION);
1214 helpText = NILP (helpObj) ? "" : (char *)SDATA (helpObj);
1215
1216 [toolbar addDisplayItemWithImage: img->pixmap idx: i helpText: helpText
1217 enabled: enabled_p];
1218#undef TOOLPROP
1219 }
1220
1221 if (![toolbar isVisible])
1222 [toolbar setVisible: YES];
1223
1224 if ([toolbar changed])
1225 {
1226 /* inform app that toolbar has changed */
1227 NSDictionary *dict = [toolbar configurationDictionary];
1228 NSMutableDictionary *newDict = [dict mutableCopy];
1229 NSEnumerator *keys = [[dict allKeys] objectEnumerator];
1230 NSObject *key;
1231 while ((key = [keys nextObject]) != nil)
1232 {
1233 NSObject *val = [dict objectForKey: key];
1234 if ([val isKindOfClass: [NSArray class]])
1235 {
1236 [newDict setObject:
1237 [toolbar toolbarDefaultItemIdentifiers: toolbar]
1238 forKey: key];
1239 break;
1240 }
1241 }
1242 [toolbar setConfigurationFromDictionary: newDict];
1243 [newDict release];
1244 }
1245
1246}
1247
1248
1249/* ==========================================================================
1250
1251 Toolbar: class implementation
1252
1253 ========================================================================== */
1254
1255@implementation EmacsToolbar
1256
1257- initForView: (EmacsView *)view withIdentifier: (NSString *)identifier
1258{
1259 self = [super initWithIdentifier: identifier];
1260 emacsView = view;
1261 [self setDisplayMode: NSToolbarDisplayModeIconOnly];
1262 [self setSizeMode: NSToolbarSizeModeSmall];
1263 [self setDelegate: self];
1264 identifierToItem = [[NSMutableDictionary alloc] initWithCapacity: 10];
1265 activeIdentifiers = [[NSMutableArray alloc] initWithCapacity: 8];
1266 prevEnablement = enablement = 0L;
1267 return self;
1268}
1269
1270- (void)dealloc
1271{
1272 [prevIdentifiers release];
1273 [activeIdentifiers release];
1274 [identifierToItem release];
1275 [super dealloc];
1276}
1277
1278- (void) clearActive
1279{
1280 [prevIdentifiers release];
1281 prevIdentifiers = [activeIdentifiers copy];
1282 [activeIdentifiers removeAllObjects];
1283 prevEnablement = enablement;
1284 enablement = 0L;
1285}
1286
1287- (BOOL) changed
1288{
1289 return [activeIdentifiers isEqualToArray: prevIdentifiers] &&
1290 enablement == prevEnablement ? NO : YES;
1291}
1292
1293- (void) addDisplayItemWithImage: (EmacsImage *)img idx: (int)idx
1294 helpText: (char *)help enabled: (BOOL)enabled
1295{
1296 /* 1) come up w/identifier */
1297 NSString *identifier =
1298 [NSString stringWithFormat: @"%u", [img hash]];
1299
1300 /* 2) create / reuse item */
1301 NSToolbarItem *item = [identifierToItem objectForKey: identifier];
1302 if (item == nil)
1303 {
1304 item = [[[NSToolbarItem alloc] initWithItemIdentifier: identifier]
1305 autorelease];
1306 [item setImage: img];
1307 [item setToolTip: [NSString stringWithCString: help]];
1308 [item setTarget: emacsView];
1309 [item setAction: @selector (toolbarClicked:)];
1310 }
1311
1312 [item setTag: idx];
1313 [item setEnabled: enabled];
1314
1315 /* 3) update state */
1316 [identifierToItem setObject: item forKey: identifier];
1317 [activeIdentifiers addObject: identifier];
1318 enablement = (enablement << 1) | (enabled == YES);
1319}
1320
1321/* This overrides super's implementation, which automatically sets
1322 all items to enabled state (for some reason). */
1323- (void)validateVisibleItems { }
1324
1325
1326/* delegate methods */
1327
1328- (NSToolbarItem *)toolbar: (NSToolbar *)toolbar
1329 itemForItemIdentifier: (NSString *)itemIdentifier
1330 willBeInsertedIntoToolbar: (BOOL)flag
1331{
1332 /* look up NSToolbarItem by identifier and return... */
1333 return [identifierToItem objectForKey: itemIdentifier];
1334}
1335
1336- (NSArray *)toolbarDefaultItemIdentifiers: (NSToolbar *)toolbar
1337{
1338 /* return entire set.. */
1339 return activeIdentifiers;
1340}
1341
1342/* for configuration palette (not yet supported) */
1343- (NSArray *)toolbarAllowedItemIdentifiers: (NSToolbar *)toolbar
1344{
1345 /* return entire set... */
1346 return [identifierToItem allKeys];
1347}
1348
1349/* optional and unneeded */
1350/* - toolbarWillAddItem: (NSNotification *)notification { } */
1351/* - toolbarDidRemoveItem: (NSNotification *)notification { } */
1352/* - (NSArray *)toolbarSelectableItemIdentifiers: (NSToolbar *)toolbar */
1353
1354@end /* EmacsToolbar */
1355
1356
1357
1358/* ==========================================================================
1359
1360 Tooltip: class implementation
1361
1362 ========================================================================== */
1363
1364/* Needed because NeXTstep does not provide enough control over tooltip
1365 display. */
1366@implementation EmacsTooltip
1367
1368- init
1369{
1370 NSColor *col = [NSColor colorWithCalibratedRed: 1.0 green: 1.0
1371 blue: 0.792 alpha: 0.95];
1372 NSFont *font = [NSFont toolTipsFontOfSize: 0];
1373 NSFont *sfont = [font screenFont];
1374 int height = [sfont ascender] - [sfont descender];
1375/*[font boundingRectForFont].size.height; */
1376 NSRect r = NSMakeRect (0, 0, 100, height+6);
1377
1378 textField = [[NSTextField alloc] initWithFrame: r];
1379 [textField setFont: font];
1380 [textField setBackgroundColor: col];
1381
1382 [textField setEditable: NO];
1383 [textField setSelectable: NO];
1384 [textField setBordered: YES];
1385 [textField setBezeled: YES];
1386 [textField setDrawsBackground: YES];
1387
1388 win = [[NSWindow alloc]
1389 initWithContentRect: [textField frame]
1390 styleMask: 0
1391 backing: NSBackingStoreBuffered
1392 defer: YES];
1393 [win setReleasedWhenClosed: NO];
1394 [win setDelegate: self];
1395 [[win contentView] addSubview: textField];
1396/* [win setBackgroundColor: col]; */
1397 [win setOpaque: NO];
1398
1399 return self;
1400}
1401
1402- (void) dealloc
1403{
1404 [win close];
1405 [win release];
1406 [textField release];
1407 [super dealloc];
1408}
1409
1410- (void) setText: (char *)text
1411{
1412 NSString *str = [NSString stringWithUTF8String: text];
1413 NSRect r = [textField frame];
1414 r.size.width = [[[textField font] screenFont] widthOfString: str] + 8;
1415 [textField setFrame: r];
1416 [textField setStringValue: str];
1417}
1418
1419- (void) showAtX: (int)x Y: (int)y for: (int)seconds
1420{
1421 NSRect wr = [win frame];
1422
1423 wr.origin = NSMakePoint (x, y);
1424 wr.size = [textField frame].size;
1425
1426 [win setFrame: wr display: YES];
1427 [win orderFront: self];
1428 [win display];
1429 timer = [NSTimer scheduledTimerWithTimeInterval: (float)seconds target: self
1430 selector: @selector (hide)
1431 userInfo: nil repeats: NO];
1432 [timer retain];
1433}
1434
1435- (void) hide
1436{
1437 [win close];
1438 if (timer != nil)
1439 {
1440 if ([timer isValid])
1441 [timer invalidate];
1442 [timer release];
1443 timer = nil;
1444 }
1445}
1446
1447- (BOOL) isActive
1448{
1449 return timer != nil;
1450}
1451
1452- (NSRect) frame
1453{
1454 return [textField frame];
1455}
1456
1457@end /* EmacsTooltip */
1458
1459
1460
1461/* ==========================================================================
1462
1463 Popup Dialog: implementing functions
1464
1465 ========================================================================== */
1466
1467Lisp_Object
1468ns_popup_dialog (Lisp_Object position, Lisp_Object contents, Lisp_Object header)
1469{
1470 id dialog;
1471 Lisp_Object window, tem;
1472 struct frame *f;
1473 NSPoint p;
1474 BOOL isQ;
1475
1476 NSTRACE (x-popup-dialog);
1477
1478 check_ns ();
1479
1480 isQ = NILP (header);
1481
1482 if (EQ (position, Qt))
1483 {
1484 window = selected_window;
1485 }
1486 else if (CONSP (position))
1487 {
1488 Lisp_Object tem;
1489 tem = Fcar (position);
1490 if (XTYPE (tem) == Lisp_Cons)
1491 window = Fcar (Fcdr (position));
1492 else
1493 {
1494 tem = Fcar (Fcdr (position)); /* EVENT_START (position) */
1495 window = Fcar (tem); /* POSN_WINDOW (tem) */
1496 }
1497 }
1498 else if (FRAMEP (position))
1499 {
1500 window = position;
1501 }
1502 else
1503 {
1504 CHECK_LIVE_WINDOW (position);
1505 window = position;
1506 }
1507
1508 if (FRAMEP (window))
1509 f = XFRAME (window);
1510 else
1511 {
1512 CHECK_LIVE_WINDOW (window);
1513 f = XFRAME (WINDOW_FRAME (XWINDOW (window)));
1514 }
1515 p.x = (int)f->left_pos + ((int)FRAME_COLUMN_WIDTH (f) * f->text_cols)/2;
1516 p.y = (int)f->top_pos + (FRAME_LINE_HEIGHT (f) * f->text_lines)/2;
1517 dialog = [[EmacsDialogPanel alloc] initFromContents: contents
1518 isQuestion: isQ];
1519
1520 tem = [dialog runDialogAt: p];
1521
1522 [dialog close];
1523
1524 [[FRAME_NS_VIEW (SELECTED_FRAME ()) window] makeKeyWindow];
1525 return tem;
1526}
1527
1528
1529/* ==========================================================================
1530
1531 Popup Dialog: class implementation
1532
1533 ========================================================================== */
1534
1535@interface FlippedView : NSView
1536{
1537}
1538@end
1539
1540@implementation FlippedView
1541- (BOOL)isFlipped
1542{
1543 return YES;
1544}
1545@end
1546
1547@implementation EmacsDialogPanel
1548
1549#define SPACER 8.0
1550#define ICONSIZE 64.0
1551#define TEXTHEIGHT 20.0
1552#define MINCELLWIDTH 90.0
1553
1554- initWithContentRect: (NSRect)contentRect styleMask: (unsigned int)aStyle
1555 backing: (NSBackingStoreType)backingType defer: (BOOL)flag
1556{
1557 NSSize spacing = {SPACER, SPACER};
1558 NSRect area;
1559 char this_cmd_name[80];
1560 id cell, tem;
1561 static NSImageView *imgView;
1562 static FlippedView *contentView;
1563
1564 if (imgView == nil)
1565 {
1566 NSImage *img;
1567 area.origin.x = 3*SPACER;
1568 area.origin.y = 2*SPACER;
1569 area.size.width = ICONSIZE;
1570 area.size.height= ICONSIZE;
1571 img = [[NSImage imageNamed: @"NSApplicationIcon"] copy];
1572 [img setScalesWhenResized: YES];
1573 [img setSize: NSMakeSize (ICONSIZE, ICONSIZE)];
1574 imgView = [[NSImageView alloc] initWithFrame: area];
1575 [imgView setImage: img];
1576 [imgView setEditable: NO];
1577 [img release];
1578 }
1579
1580 aStyle = NSTitledWindowMask;
1581 flag = YES;
1582 rows = 0;
1583 cols = 1;
1584 [super initWithContentRect: contentRect styleMask: aStyle
1585 backing: backingType defer: flag];
1586 contentView = [[FlippedView alloc] initWithFrame: [[self contentView] frame]];
1587 [self setContentView: contentView];
1588
1589 [[self contentView] setAutoresizesSubviews: YES];
1590
1591 [[self contentView] addSubview: imgView];
1592 [self setTitle: @""];
1593
1594 area.origin.x += ICONSIZE+2*SPACER;
1595/* area.origin.y = TEXTHEIGHT; ICONSIZE/2-10+SPACER; */
1596 area.size.width = 400;
1597 area.size.height= TEXTHEIGHT;
1598 command = [[[NSTextField alloc] initWithFrame: area] autorelease];
1599 [[self contentView] addSubview: command];
1600 [command setStringValue: @"Emacs"];
1601 [command setDrawsBackground: NO];
1602 [command setBezeled: NO];
1603 [command setSelectable: NO];
1604 [command setFont: [NSFont boldSystemFontOfSize: 13.0]];
1605
1606/* area.origin.x = ICONSIZE+2*SPACER;
1607 area.origin.y = TEXTHEIGHT + 2*SPACER;
1608 area.size.width = 400;
1609 area.size.height= 2;
1610 tem = [[[NSBox alloc] initWithFrame: area] autorelease];
1611 [[self contentView] addSubview: tem];
1612 [tem setTitlePosition: NSNoTitle];
1613 [tem setAutoresizingMask: NSViewWidthSizable];*/
1614
1615/* area.origin.x = ICONSIZE+2*SPACER; */
1616 area.origin.y += TEXTHEIGHT+SPACER;
1617 area.size.width = 400;
1618 area.size.height= TEXTHEIGHT;
1619 title = [[[NSTextField alloc] initWithFrame: area] autorelease];
1620 [[self contentView] addSubview: title];
1621 [title setDrawsBackground: NO];
1622 [title setBezeled: NO];
1623 [title setSelectable: NO];
1624 [title setFont: [NSFont systemFontOfSize: 11.0]];
1625
1626 cell = [[[NSButtonCell alloc] initTextCell: @""] autorelease];
1627 [cell setBordered: NO];
1628 [cell setEnabled: NO];
1629 [cell setCellAttribute: NSCellIsInsetButton to: 8];
1630 [cell setBezelStyle: NSRoundedBezelStyle];
1631
1632 matrix = [[NSMatrix alloc] initWithFrame: contentRect
1633 mode: NSHighlightModeMatrix
1634 prototype: cell
1635 numberOfRows: 0
1636 numberOfColumns: 1];
1637 [[self contentView] addSubview: matrix];
1638 [matrix release];
1639 [matrix setFrameOrigin: NSMakePoint (area.origin.x,
1640 area.origin.y + (TEXTHEIGHT+3*SPACER))];
1641 [matrix setIntercellSpacing: spacing];
1642
1643 [self setOneShot: YES];
1644 [self setReleasedWhenClosed: YES];
1645 [self setHidesOnDeactivate: YES];
1646 return self;
1647}
1648
1649
1650- (BOOL)windowShouldClose: (id)sender
1651{
1652 [NSApp stopModalWithCode: Qnil];
1653 return NO;
1654}
1655
1656
1657void process_dialog (id window, Lisp_Object list)
1658{
1659 Lisp_Object item;
1660 int row = 0;
1661
1662 for (; XTYPE (list) == Lisp_Cons; list = XCDR (list))
1663 {
1664 item = XCAR (list);
1665 if (XTYPE (item) == Lisp_String)
1666 {
1667 [window addString: XSTRING (item)->data row: row++];
1668 }
1669 else if (XTYPE (item) == Lisp_Cons)
1670 {
1671 [window addButton: XSTRING (XCAR (item))->data
1672 value: XCDR (item) row: row++];
1673 }
1674 else if (NILP (item))
1675 {
1676 [window addSplit];
1677 row = 0;
1678 }
1679 }
1680}
1681
1682
1683- addButton: (char *)str value: (Lisp_Object)val row: (int)row
1684{
1685 id cell;
1686
1687 if (row >= rows)
1688 {
1689 [matrix addRow];
1690 rows++;
1691 }
1692 cell = [matrix cellAtRow: row column: cols-1];
1693 [cell setTarget: self];
1694 [cell setAction: @selector (clicked: )];
1695 [cell setTitle: [NSString stringWithUTF8String: str]];
1696 [cell setTag: (int)val];
1697 [cell setBordered: YES];
1698 [cell setEnabled: YES];
1699
1700 return self;
1701}
1702
1703
1704- addString: (char *)str row: (int)row
1705{
1706 id cell;
1707
1708 if (row >= rows)
1709 {
1710 [matrix addRow];
1711 rows++;
1712 }
1713 cell = [matrix cellAtRow: row column: cols-1];
1714 [cell setTitle: [NSString stringWithUTF8String: str]];
1715 [cell setBordered: YES];
1716 [cell setEnabled: NO];
1717
1718 return self;
1719}
1720
1721
1722- addSplit
1723{
1724 [matrix addColumn];
1725 cols++;
1726 return self;
1727}
1728
1729
1730- clicked: sender
1731{
1732 NSArray *sellist = nil;
1733 Lisp_Object seltag;
1734
1735 sellist = [sender selectedCells];
1736 if ([sellist count]<1)
1737 return self;
1738
1739 seltag = (Lisp_Object)[[sellist objectAtIndex: 0] tag];
1740 if (! EQ (seltag, Qundefined))
1741 [NSApp stopModalWithCode: seltag];
1742 return self;
1743}
1744
1745
1746- initFromContents: (Lisp_Object)contents isQuestion: (BOOL)isQ
1747{
1748 Lisp_Object head;
1749 [super init];
1750
1751 if (XTYPE (contents) == Lisp_Cons)
1752 {
1753 head = Fcar (contents);
1754 process_dialog (self, Fcdr (contents));
1755 }
1756 else
1757 head = contents;
1758
1759 if (XTYPE (head) == Lisp_String)
1760 [title setStringValue:
1761 [NSString stringWithUTF8String: XSTRING (head)->data]];
1762 else if (isQ == YES)
1763 [title setStringValue: @"Question"];
1764 else
1765 [title setStringValue: @"Information"];
1766
1767 {
1768 int i;
1769 NSRect r, s, t;
1770
1771 if (cols == 1 && rows > 1) /* Never told where to split */
1772 {
1773 [matrix addColumn];
1774 for (i = 0; i<rows/2; i++)
1775 {
1776 [matrix putCell: [matrix cellAtRow: (rows+1)/2 column: 0]
1777 atRow: i column: 1];
1778 [matrix removeRow: (rows+1)/2];
1779 }
1780 }
1781
1782 [matrix sizeToFit];
1783 {
1784 NSSize csize = [matrix cellSize];
1785 if (csize.width < MINCELLWIDTH)
1786 {
1787 csize.width = MINCELLWIDTH;
1788 [matrix setCellSize: csize];
1789 [matrix sizeToCells];
1790 }
1791 }
1792
1793 [title sizeToFit];
1794 [command sizeToFit];
1795
1796 t = [matrix frame];
1797 r = [title frame];
1798 if (r.size.width+r.origin.x > t.size.width+t.origin.x)
1799 {
1800 t.origin.x = r.origin.x;
1801 t.size.width = r.size.width;
1802 }
1803 r = [command frame];
1804 if (r.size.width+r.origin.x > t.size.width+t.origin.x)
1805 {
1806 t.origin.x = r.origin.x;
1807 t.size.width = r.size.width;
1808 }
1809
1810 r = [self frame];
1811 s = [(NSView *)[self contentView] frame];
1812 r.size.width += t.origin.x+t.size.width +2*SPACER-s.size.width;
1813 r.size.height += t.origin.y+t.size.height+SPACER-s.size.height;
1814 [self setFrame: r display: NO];
1815 }
1816
1817 return self;
1818}
1819
1820
1821- (void)dealloc
1822{
1823 { [super dealloc]; return; };
1824}
1825
1826
1827- (Lisp_Object)runDialogAt: (NSPoint)p
1828{
1829 NSEvent *e;
1830 NSModalSession session;
1831 int ret;
1832
1833 [self center]; /*XXX p ignored? */
1834 [self orderFront: NSApp];
1835
1836 session = [NSApp beginModalSessionForWindow: self];
1837 while ((ret = [NSApp runModalSession: session]) == NSRunContinuesResponse)
1838 {
1839 (e = [NSApp nextEventMatchingMask: NSAnyEventMask
1840 untilDate: [NSDate distantFuture]
1841 inMode: NSEventTrackingRunLoopMode
1842 dequeue: NO]);
1843/*fprintf (stderr, "ret = %d\te = %p\n", ret, e); */
1844 }
1845 [NSApp endModalSession: session];
1846
1847 return (Lisp_Object)ret;
1848}
1849
1850@end
1851
1852
1853
1854/* ==========================================================================
1855
1856 Lisp definitions
1857
1858 ========================================================================== */
1859
1860DEFUN ("ns-reset-menu", Fns_reset_menu, Sns_reset_menu, 0, 0, 0,
1861 "Cause the NS menu to be re-calculated.")
1862 ()
1863{
1864 set_frame_menubar (SELECTED_FRAME (), 1, 0);
1865 return Qnil;
1866}
1867
1868
1869DEFUN ("x-popup-menu", Fx_popup_menu, Sx_popup_menu, 2, 2, 0,
1870 "Pop up a deck-of-cards menu and return user's selection.\n\
1871POSITION is a position specification. This is either a mouse button event\n\
1872or a list ((XOFFSET YOFFSET) WINDOW)\n\
1873where XOFFSET and YOFFSET are positions in pixels from the top left\n\
1874corner of WINDOW's frame. (WINDOW may be a frame object instead of a window.)\n\
1875This controls the position of the center of the first line\n\
1876in the first pane of the menu, not the top left of the menu as a whole.\n\
1877\n\
1878MENU is a specifier for a menu. For the simplest case, MENU is a keymap.\n\
1879The menu items come from key bindings that have a menu string as well as\n\
1880a definition; actually, the \"definition\" in such a key binding looks like\n\
1881\(STRING . REAL-DEFINITION). To give the menu a title, put a string into\n\
1882the keymap as a top-level element.\n\n\
1883You can also use a list of keymaps as MENU.\n\
1884 Then each keymap makes a separate pane.\n\
1885When MENU is a keymap or a list of keymaps, the return value\n\
1886is a list of events.\n\n\
1887Alternatively, you can specify a menu of multiple panes\n\
1888 with a list of the form (TITLE PANE1 PANE2...),\n\
1889where each pane is a list of form (TITLE ITEM1 ITEM2...).\n\
1890Each ITEM is normally a cons cell (STRING . VALUE);\n\
1891but a string can appear as an item--that makes a nonselectable line\n\
1892in the menu.\n\
1893With this form of menu, the return value is VALUE from the chosen item.")
1894 (position, menu)
1895 Lisp_Object position, menu;
1896{
1897 return ns_popup_menu (position, menu);
1898}
1899
1900
1901DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0,
1902 doc: /* Pop up a dialog box and return user's selection.
1903POSITION specifies which frame to use.
1904This is normally a mouse button event or a window or frame.
1905If POSITION is t, it means to use the frame the mouse is on.
1906The dialog box appears in the middle of the specified frame.
1907
1908CONTENTS specifies the alternatives to display in the dialog box.
1909It is a list of the form (DIALOG ITEM1 ITEM2...).
1910Each ITEM is a cons cell (STRING . VALUE).
1911The return value is VALUE from the chosen item.
1912
1913An ITEM may also be just a string--that makes a nonselectable item.
1914An ITEM may also be nil--that means to put all preceding items
1915on the left of the dialog box and all following items on the right.
1916\(By default, approximately half appear on each side.)
1917
1918If HEADER is non-nil, the frame title for the box is "Information",
1919otherwise it is "Question".
1920
1921If the user gets rid of the dialog box without making a valid choice,
1922for instance using the window manager, then this produces a quit and
1923`x-popup-dialog' does not return. */)
1924 (position, contents, header)
1925 Lisp_Object position, contents, header;
1926{
1927 return ns_popup_dialog (position, contents, header);
1928}
1929
1930
1931/* ==========================================================================
1932
1933 Lisp interface declaration
1934
1935 ========================================================================== */
1936
1937void
1938syms_of_nsmenu ()
1939{
1940 defsubr (&Sx_popup_menu);
1941 defsubr (&Sx_popup_dialog);
1942 defsubr (&Sns_reset_menu);
1943 staticpro (&menu_items);
1944 menu_items = Qnil;
1945
1946 Qdebug_on_next_call = intern ("debug-on-next-call");
1947 staticpro (&Qdebug_on_next_call);
1948}
diff --git a/src/nsselect.m b/src/nsselect.m
new file mode 100644
index 00000000000..a999fc38365
--- /dev/null
+++ b/src/nsselect.m
@@ -0,0 +1,624 @@
1/* NeXT/Open/GNUstep / MacOSX Cocoa selection processing for emacs.
2 Copyright (C) 1993, 1994, 2005, 2006, 2008,
3 Free Software Foundation, Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, USA.
21
22Originally by Carl Edman
23Updated by Christian Limpach (chris@nice.ch)
24OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com)
25MacOSX/Aqua port by Christophe de Dinechin (descubes@earthlink.net)
26GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
27
28*/
29
30#include "config.h"
31#include "lisp.h"
32#include "nsterm.h"
33#include "termhooks.h"
34
35#define CUT_BUFFER_SUPPORT
36
37Lisp_Object QPRIMARY, QSECONDARY, QTEXT, QFILE_NAME;
38
39static Lisp_Object Vns_sent_selection_hooks;
40static Lisp_Object Vns_lost_selection_hooks;
41static Lisp_Object Vselection_alist;
42static Lisp_Object Vselection_converter_alist;
43
44/* 23: new */
45/* Coding system for communicating with other programs. */
46static Lisp_Object Vselection_coding_system;
47/* Coding system for the next communicating with other programs. */
48static Lisp_Object Vnext_selection_coding_system;
49static Lisp_Object Qforeign_selection;
50
51NSString *NXSecondaryPboard;
52
53
54
55/* ==========================================================================
56
57 Internal utility functions
58
59 ========================================================================== */
60
61
62static NSString *
63symbol_to_nsstring (Lisp_Object sym)
64{
65 CHECK_SYMBOL (sym);
66 if (EQ (sym, QPRIMARY)) return NSGeneralPboard;
67 if (EQ (sym, QSECONDARY)) return NXSecondaryPboard;
68 if (EQ (sym, QTEXT)) return NSStringPboardType;
69 return [NSString stringWithUTF8String: XSTRING (XSYMBOL (sym)->xname)->data];
70}
71
72
73static Lisp_Object
74ns_string_to_symbol (NSString *t)
75{
76 if ([t isEqualToString: NSGeneralPboard])
77 return QPRIMARY;
78 if ([t isEqualToString: NXSecondaryPboard])
79 return QSECONDARY;
80 if ([t isEqualToString: NSStringPboardType])
81 return QTEXT;
82 if ([t isEqualToString: NSFilenamesPboardType])
83 return QFILE_NAME;
84 if ([t isEqualToString: NSTabularTextPboardType])
85 return QTEXT;
86 return intern ([t UTF8String]);
87}
88
89
90static Lisp_Object
91clean_local_selection_data (Lisp_Object obj)
92{
93 if (CONSP (obj)
94 && INTEGERP (XCAR (obj))
95 && CONSP (XCDR (obj))
96 && INTEGERP (XCAR (XCDR (obj)))
97 && NILP (XCDR (XCDR (obj))))
98 obj = Fcons (XCAR (obj), XCDR (obj));
99
100 if (CONSP (obj)
101 && INTEGERP (XCAR (obj))
102 && INTEGERP (XCDR (obj)))
103 {
104 if (XINT (XCAR (obj)) == 0)
105 return XCDR (obj);
106 if (XINT (XCAR (obj)) == -1)
107 return make_number (- XINT (XCDR (obj)));
108 }
109
110 if (VECTORP (obj))
111 {
112 int i;
113 int size = XVECTOR (obj)->size;
114 Lisp_Object copy;
115
116 if (size == 1)
117 return clean_local_selection_data (XVECTOR (obj)->contents [0]);
118 copy = Fmake_vector (size, Qnil);
119 for (i = 0; i < size; i++)
120 XVECTOR (copy)->contents [i]
121 = clean_local_selection_data (XVECTOR (obj)->contents [i]);
122 return copy;
123 }
124
125 return obj;
126}
127
128
129static void
130ns_declare_pasteboard (id pb)
131{
132 [pb declareTypes: ns_send_types owner: NSApp];
133}
134
135
136static void
137ns_undeclare_pasteboard (id pb)
138{
139 [pb declareTypes: [NSArray array] owner: nil];
140}
141
142
143static void
144ns_string_to_pasteboard_internal (id pb, Lisp_Object str, NSString *gtype)
145{
146 if (EQ (str, Qnil))
147 {
148 [pb declareTypes: [NSArray array] owner: nil];
149 }
150 else
151 {
152 char *utfStr;
153 NSString *type, *nsStr;
154 NSEnumerator *tenum;
155
156 CHECK_STRING (str);
157
158 utfStr = XSTRING (str)->data;
159 nsStr = [NSString stringWithUTF8String: utfStr];
160
161 if (gtype == nil)
162 {
163 [pb declareTypes: ns_send_types owner: nil];
164 tenum = [ns_send_types objectEnumerator];
165 while ( (type = [tenum nextObject]) )
166 [pb setString: nsStr forType: type];
167 }
168 else
169 {
170 [pb setString: nsStr forType: gtype];
171 }
172 }
173}
174
175
176static Lisp_Object
177ns_get_local_selection (Lisp_Object selection_name,
178 Lisp_Object target_type)
179{
180 Lisp_Object local_value;
181 Lisp_Object handler_fn, value, type, check;
182 int count;
183
184 local_value = assq_no_quit (selection_name, Vselection_alist);
185
186 if (NILP (local_value)) return Qnil;
187
188 count = specpdl_ptr - specpdl;
189 specbind (Qinhibit_quit, Qt);
190 CHECK_SYMBOL (target_type);
191 handler_fn = Fcdr (Fassq (target_type, Vselection_converter_alist));
192 if (!NILP (handler_fn))
193 value =call3 (handler_fn, selection_name, target_type,
194 XCAR (XCDR (local_value)));
195 else
196 value =Qnil;
197 unbind_to (count, Qnil);
198
199 check =value;
200 if (CONSP (value) && SYMBOLP (XCAR (value)))
201 {
202 type = XCAR (value);
203 check = XCDR (value);
204 }
205
206 if (STRINGP (check) || VECTORP (check) || SYMBOLP (check)
207 || INTEGERP (check) || NILP (value))
208 return value;
209
210 if (CONSP (check)
211 && INTEGERP (XCAR (check))
212 && (INTEGERP (XCDR (check))||
213 (CONSP (XCDR (check))
214 && INTEGERP (XCAR (XCDR (check)))
215 && NILP (XCDR (XCDR (check))))))
216 return value;
217
218 Fsignal (Qquit, Fcons (build_string (
219 "invalid data returned by selection-conversion function"),
220 Fcons (handler_fn, Fcons (value, Qnil))));
221}
222
223
224static Lisp_Object
225ns_get_foreign_selection (Lisp_Object symbol, Lisp_Object target)
226{
227 id pb;
228 pb =[NSPasteboard pasteboardWithName: symbol_to_nsstring (symbol)];
229 return ns_string_from_pasteboard (pb);
230}
231
232
233static void
234ns_handle_selection_request (struct input_event *event)
235{
236 id pb =(id)event->x;
237 NSString *type =(NSString *)event->y;
238 Lisp_Object selection_name, selection_data, target_symbol, data;
239 Lisp_Object successful_p, rest;
240
241 selection_name =ns_string_to_symbol ([(NSPasteboard *)pb name]);
242 target_symbol =ns_string_to_symbol (type);
243 selection_data = assq_no_quit (selection_name, Vselection_alist);
244 successful_p =Qnil;
245
246 if (!NILP (selection_data))
247 {
248 data = ns_get_local_selection (selection_name, target_symbol);
249 if (!NILP (data))
250 {
251 if (STRINGP (data))
252 ns_string_to_pasteboard_internal (pb, data, type);
253 successful_p =Qt;
254 }
255 }
256
257 if (!EQ (Vns_sent_selection_hooks, Qunbound))
258 {
259 for (rest =Vns_sent_selection_hooks;CONSP (rest); rest =Fcdr (rest))
260 call3 (Fcar (rest), selection_name, target_symbol, successful_p);
261 }
262}
263
264
265static void
266ns_handle_selection_clear (struct input_event *event)
267{
268 id pb = (id)event->x;
269 Lisp_Object selection_name, selection_data, rest;
270
271 selection_name =ns_string_to_symbol ([(NSPasteboard *)pb name]);
272 selection_data =assq_no_quit (selection_name, Vselection_alist);
273 if (NILP (selection_data)) return;
274
275 if (EQ (selection_data, Fcar (Vselection_alist)))
276 Vselection_alist = Fcdr (Vselection_alist);
277 else
278 {
279 for (rest = Vselection_alist; !NILP (rest); rest = Fcdr (rest))
280 if (EQ (selection_data, Fcar (Fcdr (rest))))
281 Fsetcdr (rest, Fcdr (Fcdr (rest)));
282 }
283
284 if (!EQ (Vns_lost_selection_hooks, Qunbound))
285 {
286 for (rest =Vns_lost_selection_hooks;CONSP (rest); rest =Fcdr (rest))
287 call1 (Fcar (rest), selection_name);
288 }
289}
290
291
292
293/* ==========================================================================
294
295 Functions used externally
296
297 ========================================================================== */
298
299
300Lisp_Object
301ns_string_from_pasteboard (id pb)
302{
303 NSString *type, *str;
304 const char *utfStr;
305
306 type = [pb availableTypeFromArray: ns_return_types];
307 if (type == nil)
308 {
309 Fsignal (Qquit,
310 Fcons (build_string ("empty or unsupported pasteboard type"),
311 Qnil));
312 return Qnil;
313 }
314
315 /* get the string */
316 if (! (str = [pb stringForType: type]))
317 {
318 NSData *data = [pb dataForType: type];
319 if (data != nil)
320 str = [[NSString alloc] initWithData: data
321 encoding: NSUTF8StringEncoding];
322 if (str != nil)
323 {
324 [str autorelease];
325 }
326 else
327 {
328 Fsignal (Qquit,
329 Fcons (build_string ("pasteboard doesn't contain valid data"),
330 Qnil));
331 return Qnil;
332 }
333 }
334
335 /* assume UTF8 */
336 NS_DURING
337 {
338 /* EOL conversion: PENDING- is this too simple? */
339 NSMutableString *mstr = [[str mutableCopy] autorelease];
340 [mstr replaceOccurrencesOfString: @"\r\n" withString: @"\n"
341 options: NSLiteralSearch range: NSMakeRange (0, [mstr length])];
342 [mstr replaceOccurrencesOfString: @"\r" withString: @"\n"
343 options: NSLiteralSearch range: NSMakeRange (0, [mstr length])];
344
345 utfStr = [mstr UTF8String];
346 if (!utfStr)
347 utfStr = [mstr cString];
348 }
349 NS_HANDLER
350 {
351 message1 ("ns_string_from_pasteboard: UTF8String failed\n");
352 utfStr = [str lossyCString];
353 }
354 NS_ENDHANDLER
355
356 return build_string (utfStr);
357}
358
359
360void
361ns_string_to_pasteboard (id pb, Lisp_Object str)
362{
363 ns_string_to_pasteboard_internal (pb, str, nil);
364}
365
366
367
368/* ==========================================================================
369
370 Lisp Defuns
371
372 ========================================================================== */
373
374
375DEFUN ("ns-own-selection-internal", Fns_own_selection_internal,
376 Sns_own_selection_internal, 2, 2, 0, "Assert a selection.")
377 (selection_name, selection_value)
378 Lisp_Object selection_name, selection_value;
379{
380 id pb;
381 Lisp_Object old_value, new_value;
382
383 check_ns ();
384 CHECK_SYMBOL (selection_name);
385 if (NILP (selection_value))
386 error ("selection-value may not be nil.");
387 pb =[NSPasteboard pasteboardWithName: symbol_to_nsstring (selection_name)];
388 ns_declare_pasteboard (pb);
389 old_value =assq_no_quit (selection_name, Vselection_alist);
390 new_value = Fcons (selection_name, Fcons (selection_value, Qnil));
391 if (NILP (old_value))
392 Vselection_alist =Fcons (new_value, Vselection_alist);
393 else
394 Fsetcdr (old_value, Fcdr (new_value));
395 /* XXX An evil hack, but a necessary one I fear XXX */
396 {
397 struct input_event ev;
398 ev.kind = SELECTION_REQUEST_EVENT;
399 ev.modifiers = 0;
400 ev.code = 0;
401 ev.x = (int)pb;
402 ev.y = (int)NSStringPboardType;
403 ns_handle_selection_request (&ev);
404 }
405 return selection_value;
406}
407
408
409DEFUN ("ns-disown-selection-internal", Fns_disown_selection_internal,
410 Sns_disown_selection_internal, 1, 2, 0,
411 "If we own the selection SELECTION, disown it.")
412 (selection_name, time)
413 Lisp_Object selection_name, time;
414{
415 id pb;
416 check_ns ();
417 CHECK_SYMBOL (selection_name);
418 if (NILP (assq_no_quit (selection_name, Vselection_alist))) return Qnil;
419
420 pb =[NSPasteboard pasteboardWithName: symbol_to_nsstring (selection_name)];
421 ns_undeclare_pasteboard (pb);
422 return Qt;
423}
424
425
426DEFUN ("ns-selection-exists-p", Fns_selection_exists_p, Sns_selection_exists_p,
427 0, 1, 0, "Whether there is an owner for the given selection.\n\
428The arg should be the name of the selection in question, typically one of\n\
429the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
430\(Those are literal upper-case symbol names.)\n\
431For convenience, the symbol nil is the same as `PRIMARY',\n\
432and t is the same as `SECONDARY'.)")
433 (selection)
434 Lisp_Object selection;
435{
436 id pb;
437 NSArray *types;
438
439 check_ns ();
440 CHECK_SYMBOL (selection);
441 if (EQ (selection, Qnil)) selection = QPRIMARY;
442 if (EQ (selection, Qt)) selection = QSECONDARY;
443 pb =[NSPasteboard pasteboardWithName: symbol_to_nsstring (selection)];
444 types =[pb types];
445 return ([types count] == 0) ? Qnil : Qt;
446}
447
448
449DEFUN ("ns-selection-owner-p", Fns_selection_owner_p, Sns_selection_owner_p,
450 0, 1, 0,
451 "Whether the current Emacs process owns the given selection.\n\
452The arg should be the name of the selection in question, typically one of\n\
453the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
454\(Those are literal upper-case symbol names.)\n\
455For convenience, the symbol nil is the same as `PRIMARY',\n\
456and t is the same as `SECONDARY'.)")
457 (selection)
458 Lisp_Object selection;
459{
460 check_ns ();
461 CHECK_SYMBOL (selection);
462 if (EQ (selection, Qnil)) selection = QPRIMARY;
463 if (EQ (selection, Qt)) selection = QSECONDARY;
464 return (NILP (Fassq (selection, Vselection_alist))) ? Qnil : Qt;
465}
466
467
468DEFUN ("ns-get-selection-internal", Fns_get_selection_internal,
469 Sns_get_selection_internal, 2, 2, 0,
470 "Return text selected from some pasteboard.\n\
471SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\
472\(Those are literal upper-case symbol names.)\n\
473TYPE is the type of data desired, typically `STRING'.")
474 (selection_name, target_type)
475 Lisp_Object selection_name, target_type;
476{
477 Lisp_Object val;
478
479 check_ns ();
480 CHECK_SYMBOL (selection_name);
481 CHECK_SYMBOL (target_type);
482 val = ns_get_local_selection (selection_name, target_type);
483 if (NILP (val))
484 val = ns_get_foreign_selection (selection_name, target_type);
485 if (CONSP (val) && SYMBOLP (Fcar (val)))
486 {
487 val = Fcdr (val);
488 if (CONSP (val) && NILP (Fcdr (val)))
489 val = Fcar (val);
490 }
491 val = clean_local_selection_data (val);
492 return val;
493}
494
495
496#ifdef CUT_BUFFER_SUPPORT
497DEFUN ("ns-get-cut-buffer-internal", Fns_get_cut_buffer_internal,
498 Sns_get_cut_buffer_internal, 1, 1, 0,
499 "Returns the value of the named cut buffer.")
500 (buffer)
501 Lisp_Object buffer;
502{
503 id pb;
504 check_ns ();
505 pb =[NSPasteboard pasteboardWithName: symbol_to_nsstring (buffer)];
506 return ns_string_from_pasteboard (pb);
507}
508
509
510DEFUN ("ns-rotate-cut-buffers-internal", Fns_rotate_cut_buffers_internal,
511 Sns_rotate_cut_buffers_internal, 1, 1, 0,
512 "Rotate the values of the cut buffers by the given number of steps;\n\
513 positive means move values forward, negative means backward. CURRENTLY NOT IMPLEMENTED UNDER NeXTstep.")
514 (n)
515 Lisp_Object n;
516{
517 /* XXX This function is unimplemented under NeXTstep XXX */
518 Fsignal (Qquit, Fcons (build_string (
519 "Warning: ns-rotate-cut-buffers-internal not implemented\n"), Qnil));
520 return Qnil;
521}
522
523
524DEFUN ("ns-store-cut-buffer-internal", Fns_store_cut_buffer_internal,
525 Sns_store_cut_buffer_internal, 2, 2, 0,
526 "Sets the value of the named cut buffer (typically CUT_BUFFER0).")
527 (buffer, string)
528 Lisp_Object buffer, string;
529{
530 id pb;
531 check_ns ();
532 pb =[NSPasteboard pasteboardWithName: symbol_to_nsstring (buffer)];
533 ns_string_to_pasteboard (pb, string);
534 return Qnil;
535}
536#endif
537
538
539void
540nxatoms_of_nsselect (void)
541{
542 NXSecondaryPboard = @"Selection";
543}
544
545void
546syms_of_nsselect (void)
547{
548 QPRIMARY = intern ("PRIMARY"); staticpro (&QPRIMARY);
549 QSECONDARY = intern ("SECONDARY"); staticpro (&QSECONDARY);
550 QTEXT = intern ("TEXT"); staticpro (&QTEXT);
551 QFILE_NAME = intern ("FILE_NAME"); staticpro (&QFILE_NAME);
552
553 defsubr (&Sns_disown_selection_internal);
554 defsubr (&Sns_get_selection_internal);
555 defsubr (&Sns_own_selection_internal);
556 defsubr (&Sns_selection_exists_p);
557 defsubr (&Sns_selection_owner_p);
558#ifdef CUT_BUFFER_SUPPORT
559 defsubr (&Sns_get_cut_buffer_internal);
560 defsubr (&Sns_rotate_cut_buffers_internal);
561 defsubr (&Sns_store_cut_buffer_internal);
562#endif
563
564 Vselection_alist = Qnil;
565 staticpro (&Vselection_alist);
566
567 DEFVAR_LISP ("ns-sent-selection-hooks", &Vns_sent_selection_hooks,
568 "A list of functions to be called when Emacs answers a selection request.\n\
569The functions are called with four arguments:\n\
570 - the selection name (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');\n\
571 - the selection-type which Emacs was asked to convert the\n\
572 selection into before sending (for example, `STRING' or `LENGTH');\n\
573 - a flag indicating success or failure for responding to the request.\n\
574We might have failed (and declined the request) for any number of reasons,\n\
575including being asked for a selection that we no longer own, or being asked\n\
576to convert into a type that we don't know about or that is inappropriate.\n\
577This hook doesn't let you change the behavior of Emacs's selection replies,\n\
578it merely informs you that they have happened.");
579 Vns_sent_selection_hooks = Qnil;
580
581 DEFVAR_LISP ("selection-converter-alist", &Vselection_converter_alist,
582 "An alist associating X Windows selection-types with functions.\n\
583These functions are called to convert the selection, with three args:\n\
584the name of the selection (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');\n\
585a desired type to which the selection should be converted;\n\
586and the local selection value (whatever was given to `x-own-selection').\n\
587\n\
588The function should return the value to send to the X server\n\
589\(typically a string). A return value of nil\n\
590means that the conversion could not be done.\n\
591A return value which is the symbol `NULL'\n\
592means that a side-effect was executed,\n\
593and there is no meaningful selection value.");
594 Vselection_converter_alist = Qnil;
595
596 DEFVAR_LISP ("ns-lost-selection-hooks", &Vns_lost_selection_hooks,
597 "A list of functions to be called when Emacs loses an X selection.\n\
598\(This happens when some other X client makes its own selection\n\
599or when a Lisp program explicitly clears the selection.)\n\
600The functions are called with one argument, the selection type\n\
601\(a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD').");
602 Vns_lost_selection_hooks = Qnil;
603
604/* 23: { */
605 DEFVAR_LISP ("selection-coding-system", &Vselection_coding_system,
606 doc: /* Coding system for communicating with other programs.
607When sending or receiving text via cut_buffer, selection, and clipboard,
608the text is encoded or decoded by this coding system.
609The default value is determined by the system script code. */);
610 Vselection_coding_system = Qnil;
611
612 DEFVAR_LISP ("next-selection-coding-system", &Vnext_selection_coding_system,
613 doc: /* Coding system for the next communication with other programs.
614Usually, `selection-coding-system' is used for communicating with
615other programs. But, if this variable is set, it is used for the
616next communication only. After the communication, this variable is
617set to nil. */);
618 Vnext_selection_coding_system = Qnil;
619
620 Qforeign_selection = intern ("foreign-selection");
621 staticpro (&Qforeign_selection);
622/* } */
623
624}
diff --git a/src/nsterm.h b/src/nsterm.h
new file mode 100644
index 00000000000..26036a83a71
--- /dev/null
+++ b/src/nsterm.h
@@ -0,0 +1,827 @@
1/* Definitions and headers for communication with NeXT/Open/GNUstep API.
2 Copyright (C) 1989, 1993, 2005, 2008 Free Software Foundation, Inc.
3
4This file is part of GNU Emacs.
5
6GNU Emacs is free software; you can redistribute it and/or modify
7it under the terms of the GNU General Public License as published by
8the Free Software Foundation; either version 3, or (at your option)
9any later version.
10
11GNU Emacs is distributed in the hope that it will be useful,
12but WITHOUT ANY WARRANTY; without even the implied warranty of
13MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14GNU General Public License for more details.
15
16You should have received a copy of the GNU General Public License
17along with GNU Emacs; see the file COPYING. If not, write to
18the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19Boston, MA 02110-1301, USA. */
20
21#include "dispextern.h"
22#include "frame.h"
23#include "character.h"
24#include "font.h"
25
26#ifdef HAVE_NS
27
28#ifdef __OBJC__
29
30/* ==========================================================================
31
32 The Emacs application
33
34 ========================================================================== */
35
36/* We override sendEvent: as a means to stop/start the event loop */
37@interface EmacsApp : NSApplication
38{
39}
40- (void)sendEvent: (NSEvent *)theEvent;
41- (void)showPreferencesWindow: (id)sender;
42@end
43
44
45/* ==========================================================================
46
47 The main Emacs view
48
49 ========================================================================== */
50
51@class EmacsToolbar;
52
53@interface EmacsView : NSView <NSTextInput>
54 {
55 char *old_title;
56 BOOL windowClosing;
57 NSString *workingText;
58 BOOL processingCompose;
59@public
60 struct frame *emacsframe;
61 int rows, cols;
62 int scrollbarsNeedingUpdate;
63 EmacsToolbar *toolbar;
64 }
65
66/* AppKit-side interface */
67- menuDown: sender;
68- toolbarClicked: (id)item;
69- toggleToolbar: (id)sender;
70- (void)keyDown: (NSEvent *)theEvent;
71- (void)mouseDown: (NSEvent *)theEvent;
72- (void)mouseUp: (NSEvent *)theEvent;
73- setMiniwindowImage: (BOOL)setMini;
74
75/* Emacs-side interface */
76- initFrameFromEmacs: (struct frame *) f;
77- (void) setRows: (int) r andColumns: (int) c;
78- (void) setWindowClosing: (BOOL)closing;
79- (EmacsToolbar *) toolbar;
80- (void) deleteWorkingText;
81@end
82
83
84/* Small utility used for processing resize events under Cocoa. */
85@interface EmacsWindow : NSWindow
86{
87 NSPoint grabOffset;
88}
89@end
90
91
92/* ==========================================================================
93
94 The main menu implementation
95
96 ========================================================================== */
97
98@interface EmacsMenu : NSMenu
99{
100 struct frame *frame;
101 unsigned long keyEquivModMask;
102}
103
104- initWithTitle: (NSString *)title frame: (struct frame *)f;
105- (void)setFrame: (struct frame *)f;
106- (void)menuNeedsUpdate: (NSMenu *)menu; /* (delegate method) */
107- (NSString *)parseKeyEquiv: (char *)key;
108- (id <NSMenuItem>)addItemWithWidgetValue: (void *)wvptr;
109- (void)fillWithWidgetValue: (void *)wvptr;
110- (EmacsMenu *)addSubmenuWithTitle: (char *)title forFrame: (struct frame *)f;
111- (void) clear;
112- (Lisp_Object)runMenuAt: (NSPoint)p forFrame: (struct frame *)f
113 keymaps: (int)keymaps;
114@end
115
116
117/* ==========================================================================
118
119 Toolbar
120
121 ========================================================================== */
122
123@class EmacsImage;
124
125@interface EmacsToolbar : NSToolbar
126 {
127 EmacsView *emacsView;
128 NSMutableDictionary *identifierToItem;
129 NSMutableArray *activeIdentifiers;
130 NSArray *prevIdentifiers;
131 unsigned long enablement, prevEnablement;
132 }
133- initForView: (EmacsView *)view withIdentifier: (NSString *)identifier;
134- (void) clearActive;
135- (BOOL) changed;
136- (void) addDisplayItemWithImage: (EmacsImage *)img idx: (int)idx
137 helpText: (char *)help
138 enabled: (BOOL)enabled;
139/* delegate methods */
140- (NSToolbarItem *)toolbar: (NSToolbar *)toolbar
141 itemForItemIdentifier: (NSString *)itemIdentifier
142 willBeInsertedIntoToolbar: (BOOL)flag;
143- (NSArray *)toolbarDefaultItemIdentifiers: (NSToolbar *)toolbar;
144- (NSArray *)toolbarAllowedItemIdentifiers: (NSToolbar *)toolbar;
145@end
146
147
148/* ==========================================================================
149
150 Message / question windows
151
152 ========================================================================== */
153
154@interface EmacsDialogPanel : NSPanel
155 {
156 NSTextField *command;
157 NSTextField *title;
158 NSMatrix *matrix;
159 int rows, cols;
160 }
161- initFromContents: (Lisp_Object)menu isQuestion: (BOOL)isQ;
162- addButton: (char *)str value: (Lisp_Object)val row: (int)row;
163- addString: (char *)str row: (int)row;
164- addSplit;
165- (Lisp_Object)runDialogAt: (NSPoint)p;
166@end
167
168@interface EmacsTooltip : NSObject
169 {
170 NSWindow *win;
171 NSTextField *textField;
172 NSTimer *timer;
173 }
174- init;
175- (void) setText: (char *)text;
176- (void) showAtX: (int)x Y: (int)y for: (int)seconds;
177- (void) hide;
178- (BOOL) isActive;
179- (NSRect) frame;
180@end
181
182
183/* ==========================================================================
184
185 File open/save panels
186 This and next override methods to work around OS X behavior of
187 restarting application loop when user dismisses panel.
188
189 ========================================================================== */
190
191@interface EmacsSavePanel : NSSavePanel
192{
193}
194@end
195@interface EmacsOpenPanel : NSOpenPanel
196{
197}
198@end
199
200@interface EmacsFileDelegate : NSObject
201{
202}
203- (BOOL)panel: (id)sender isValidFilename: (NSString *)filename;
204- (BOOL)panel: (id)sender shouldShowFilename: (NSString *)filename;
205- (NSString *)panel: (id)sender userEnteredFilename: (NSString *)filename
206 confirmed: (BOOL)okFlag;
207@end
208
209
210/* ==========================================================================
211
212 Images and stippling
213
214 ========================================================================== */
215
216@interface EmacsImage : NSImage
217{
218 id imageListNext;
219 int refCount;
220 NSBitmapImageRep *bmRep; /* used for accessing pixel data */
221 unsigned char *pixmapData[5]; /* shortcut to access pixel data */
222 BOOL onTiger;
223 NSColor *stippleMask;
224}
225+ allocInitFromFile: (Lisp_Object)file;
226- reference;
227- imageListSetNext: (id)arg;
228- imageListNext;
229- (void)dealloc;
230- initFromXBM: (unsigned char *)bits width: (int)w height: (int)h
231 flip: (BOOL)flip;
232- initFromSkipXBM: (unsigned char *)bits width: (int)w height: (int)h
233 flip: (BOOL)flip length: (int)length;
234- setXBMColor: (NSColor *)color;
235- initForXPMWithDepth: (int)depth width: (int)width height: (int)height;
236- (void)setPixmapData;
237- (unsigned long)getPixelAtX: (int)x Y: (int)y;
238- (void)setPixelAtX: (int)x Y: (int)y toRed: (unsigned char)r
239 green: (unsigned char)g blue: (unsigned char)b
240 alpha:(unsigned char)a;
241- (void)setAlphaAtX: (int)x Y: (int)y to: (unsigned char)a;
242- (NSColor *)stippleMask;
243@end
244
245
246/* ==========================================================================
247
248 Scrollbars
249
250 ========================================================================== */
251
252@interface EmacsScroller : NSScroller
253 {
254 Lisp_Object win;
255 struct frame *frame;
256 NSResponder *prevResponder;
257
258 /* offset to the bottom of knob of last mouse down */
259 float last_mouse_offset;
260 float min_portion;
261 int pixel_height;
262 int last_hit_part;
263
264 BOOL condemned;
265
266 /* optimize against excessive positioning calls generated by emacs */
267 int em_position;
268 int em_portion;
269 int em_whole;
270 }
271
272- initFrame: (NSRect )r window: (Lisp_Object)win;
273- (void)setFrame: (NSRect)r;
274- (void)dealloc;
275
276- setPosition: (int) position portion: (int) portion whole: (int) whole;
277- (int) checkSamePosition: (int)position portion: (int)portion
278 whole: (int)whole;
279- (void) getMouseMotionPart: (int *)part window: (Lisp_Object *)window
280 x: (Lisp_Object *)x y: ( Lisp_Object *)y;
281- (void) sendScrollEventAtLoc: (float)loc fromEvent: (NSEvent *)e;
282- repeatScroll: (NSTimer *)sender;
283- condemn;
284- reprieve;
285- judge;
286@end
287
288
289/* ==========================================================================
290
291 Rendering on Panther and above
292
293 ========================================================================== */
294
295#ifdef NS_IMPL_COCOA
296/* rendering util */
297@interface EmacsGlyphStorage : NSObject <NSGlyphStorage>
298{
299@public
300 NSAttributedString *attrStr;
301 NSMutableDictionary *dict;
302 CGGlyph *cglyphs;
303 unsigned long maxChar, maxGlyph;
304 long i, len;
305}
306- initWithCapacity: (unsigned long) c;
307- (void) setString: (NSString *)str font: (NSFont *)font;
308@end
309#endif /* NS_IMPL_COCOA */
310
311
312/* ==========================================================================
313
314 Running the preferences window
315
316 ========================================================================== */
317
318@interface EmacsPrefsController : NSObject
319{
320 struct frame *frame;
321 IBOutlet NSWindow *prefsWindow;
322 IBOutlet NSPopUpButton *alternateModMenu;
323 IBOutlet NSPopUpButton *commandModMenu;
324#ifdef NS_IMPL_COCOA
325 IBOutlet NSPopUpButton *controlModMenu;
326 IBOutlet NSPopUpButton *functionModMenu;
327#endif
328 IBOutlet NSMatrix *cursorTypeMatrix;
329 IBOutlet NSSlider *cursorBlinkSlider;
330 IBOutlet NSSlider *expandSpaceSlider;
331#ifdef NS_IMPL_COCOA
332 IBOutlet NSButton *smoothFontsCheck;
333 IBOutlet NSButton *useQuickdrawCheck;
334 IBOutlet NSButton *useSysHiliteCheck;
335 BOOL prevUseHighlightColor;
336#endif
337 float prevExpandSpace;
338 float prevBlinkRate;
339}
340- (IBAction)cancel: (id)sender;
341- (IBAction)ok: (id)sender;
342- (IBAction)resetToDefaults: (id)sender;
343- (IBAction)runHelp: (id)sender;
344- (IBAction)setColors: (id)sender;
345- (IBAction)setDefaultFont: (id)sender;
346
347- (void) showForFrame: (struct frame *)f;
348- (void) setPanelFromValues;
349- (void) setValuesFromPanel;
350@end
351
352extern NSArray *ns_send_types, *ns_return_types;
353extern EmacsMenu *mainMenu, *svcsMenu;
354
355/* Apple removed the declaration, but kept the implementation */
356#if defined (NS_IMPL_COCOA) && MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4
357@interface NSApplication (EmacsApp)
358- (void)setAppleMenu: (NSMenu *)menu;
359@end
360#endif
361
362#endif /* __OBJC__ */
363
364
365
366/* ==========================================================================
367
368 Non-OO stuff
369
370 ========================================================================== */
371
372enum ns_cursor_types
373{
374 no_highlight =0,
375 filled_box,
376 hollow_box,
377 underscore,
378 bar
379};
380
381
382/* could use list to store these, but rest of emacs has a big infrastructure
383 for managing a table of bitmap "records" */
384struct ns_bitmap_record
385{
386#ifdef __OBJC__
387 EmacsImage *img;
388#else
389 void *img;
390#endif
391 char *file;
392 int refcount;
393 int height, width, depth;
394};
395
396/* this to map between emacs color indices and NSColor objects */
397struct ns_color_table
398{
399 unsigned int size;
400 unsigned int avail;
401#ifdef __OBJC__
402 NSColor **colors;
403 NSMutableSet *empty_indices;
404#else
405 void **items;
406 void *availIndices;
407#endif
408};
409#define NS_COLOR_CAPACITY 256
410
411#define RGB_TO_ULONG(r, g, b) (((r) << 16) | ((g) << 8) | (b))
412#define ARGB_TO_ULONG(a, r, g, b) (((a) << 24) | ((r) << 16) | ((g) << 8) | (b))
413
414#define ALPHA_FROM_ULONG(color) ((color) >> 24)
415#define RED_FROM_ULONG(color) (((color) >> 16) & 0xff)
416#define GREEN_FROM_ULONG(color) (((color) >> 8) & 0xff)
417#define BLUE_FROM_ULONG(color) ((color) & 0xff)
418
419/* Do not change `* 0x101' in the following lines to `<< 8'. If
420 changed, image masks in 1-bit depth will not work. */
421#define RED16_FROM_ULONG(color) (RED_FROM_ULONG(color) * 0x101)
422#define GREEN16_FROM_ULONG(color) (GREEN_FROM_ULONG(color) * 0x101)
423#define BLUE16_FROM_ULONG(color) (BLUE_FROM_ULONG(color) * 0x101)
424
425/* this extends font backend font */
426struct nsfont_info
427{
428 struct font font;
429
430 char *name; /* postscript name, uniquely identifies on NS systems */
431 float width; /* this and following metrics stored as float rather than int */
432 float height;
433 float underpos;
434 float underwidth;
435 float size;
436#ifdef __OBJC__
437 NSFont *nsfont;
438 /* cgfont and synthItal are used only on OS X 10.3+ */
439#if defined (NS_IMPL_COCOA) && (MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_3)
440 CGFontRef cgfont;
441#else /* GNUstep or OS X < 10.3 */
442 void *cgfont;
443#endif
444#else /* ! OBJC */
445 void *nsfont;
446 void *cgfont;
447#endif
448 char bold, ital; /* convenience flags */
449 char synthItal;
450 float voffset; /* mean of ascender/descender offsets */
451 XCharStruct max_bounds; /* 23 */
452 /* we compute glyph codes and metrics on-demand in blocks of 256 indexed
453 by hibyte, lobyte */
454 unsigned short **glyphs; /* map unicode index to glyph */
455 struct font_metrics **metrics;
456};
457
458
459/* init'd in ns_initialize_display_info () */
460struct ns_display_info
461{
462 /* Chain of all ns_display_info structures. */
463 struct ns_display_info *next;
464
465 /* The generic display parameters corresponding to this NS display. */
466 struct terminal *terminal;
467
468 /* This is a cons cell of the form (NAME . FONT-LIST-CACHE).
469 The same cons cell also appears in ns_display_name_list. */
470 Lisp_Object name_list_element;
471
472 /* The number of fonts loaded. */
473 int n_fonts;
474
475 /* Minimum width over all characters in all fonts in font_table. */
476 int smallest_char_width;
477
478 /* Minimum font height over all fonts in font_table. */
479 int smallest_font_height;
480
481 struct kboard *kboard;
482
483 /*/23 */
484 struct ns_bitmap_record *bitmaps;
485 int bitmaps_size;
486 int bitmaps_last;
487
488 /* 23 */
489 struct image_cache *image_cache;
490
491 struct ns_color_table *color_table;
492
493 /* 23: Dimensions and DPI resolution of this screen */
494 int height, width;
495 double resx, resy;
496
497 /* 23: Mask of things that cause the mouse to be grabbed */
498 int grabbed;
499
500 /* 23 */
501 int n_planes;
502
503 /* 23 */
504 int color_p;
505
506 /* 23 */
507 Window root_window;
508
509 /* 23: Xism */
510 XrmDatabase xrdb;
511
512 /* 23: The cursor to use for vertical scroll bars. */
513 Cursor vertical_scroll_bar_cursor;
514
515 /* 23: most mouse face stuff moved in here (and reasonably so) */
516 int mouse_face_beg_row, mouse_face_beg_col;
517 int mouse_face_end_row, mouse_face_end_col;
518 int mouse_face_beg_x, mouse_face_beg_y;
519 int mouse_face_end_x, mouse_face_end_y;
520 int mouse_face_past_end;
521 Lisp_Object mouse_face_window;
522 int mouse_face_face_id;
523 int mouse_face_deferred_gc;
524 Lisp_Object mouse_face_overlay;
525 FRAME_PTR mouse_face_mouse_frame;
526 int mouse_face_mouse_x, mouse_face_mouse_y;
527 int mouse_face_defer;
528 int mouse_face_hidden;
529 int mouse_face_image_state;
530
531 /* these are general, but we redefine due to Xism */
532 struct frame *ns_highlight_frame;
533 struct frame *ns_focus_frame;
534#define x_highlight_frame ns_highlight_frame
535#define x_focus_frame ns_focus_frame
536};
537
538/* This is a chain of structures for all the NS displays currently in use. */
539extern struct ns_display_info *ns_display_list;
540/* handle Xism */
541#define x_display_list ns_display_list
542
543extern Lisp_Object ns_display_name_list;
544extern struct ns_display_info *ns_display_info_for_name ();
545
546/* 23: PENDING: these functions (we defined in nsfns) are used in various
547 places, but no prototypes are provided */
548struct ns_display_info *check_x_display_info (Lisp_Object frame);
549FRAME_PTR check_x_frame (Lisp_Object frame);
550
551
552struct ns_output
553{
554#ifdef __OBJC__
555 EmacsView *view;
556 id miniimage;
557 NSColor *current_cursor_color;
558 NSColor *desired_cursor_color;
559 NSColor *foreground_color;
560 NSColor *background_color;
561 EmacsToolbar *toolbar;
562#else
563 void *view;
564 void *miniimage;
565 void *current_cursor_color;
566 void *desired_cursor_color;
567 void *foreground_color;
568 void *background_color;
569 void *toolbar;
570#endif
571
572 /* 23: NSCursors init'ed in initFrameFromEmacs */
573 Cursor text_cursor;
574 Cursor nontext_cursor;
575 Cursor modeline_cursor;
576 Cursor hand_cursor;
577 Cursor hourglass_cursor;
578 Cursor horizontal_drag_cursor;
579
580 /* 23: NS-specific */
581 Cursor current_pointer;
582
583 /* 23: lord knows why Emacs needs to know about our Window ids.. */
584 Window window_desc, parent_desc;
585 char explicit_parent;
586
587 struct font *font;
588 int baseline_offset;
589
590 /* If a fontset is specified for this frame instead of font, this
591 value contains an ID of the fontset, else -1. */
592 int fontset; /* only used with font_backend */
593
594 Lisp_Object icon_top;
595 Lisp_Object icon_left;
596 enum ns_cursor_types current_cursor, desired_cursor;
597 unsigned char last_inactive;
598
599 /* The size of the extra width currently allotted for vertical
600 scroll bars, in pixels. */
601 int vertical_scroll_bar_extra;
602
603 /* The height of the titlebar decoration (included in NSWindow's frame). */
604 int titlebar_height;
605
606 /* The height of the toolbar if displayed, else 0. */
607 int toolbar_height;
608
609 /* This is the Emacs structure for the NS display this frame is on. */
610 struct ns_display_info *display_info;
611};
612
613/* 23: this dummy decl now needed to support TTYs */
614struct x_output
615{
616 unsigned long background_pixel;
617 unsigned long foreground_pixel;
618};
619
620
621/* This gives the ns_display_info structure for the display F is on. */
622#define FRAME_NS_DISPLAY_INFO(f) ((f)->output_data.ns->display_info)
623/* the primacy of X must be constantly worked with... */
624#define FRAME_X_DISPLAY_INFO(f) ((f)->output_data.ns->display_info)
625#define FRAME_X_OUTPUT(f) ((f)->output_data.ns)
626#define FRAME_NS_WINDOW(f) ((f)->output_data.ns->window_desc)
627#define FRAME_X_WINDOW(f) ((f)->output_data.ns->window_desc)
628
629/* This is the `Display *' which frame F is on. */
630#define FRAME_NS_DISPLAY(f) (0)
631#define FRAME_X_DISPLAY(f) (0)
632
633#define FRAME_FOREGROUND_COLOR(f) ((f)->output_data.ns->foreground_color)
634#define FRAME_BACKGROUND_COLOR(f) ((f)->output_data.ns->background_color)
635
636#define FRAME_X_IMAGE_CACHE(F) FRAME_NS_DISPLAY_INFO ((F))->image_cache
637
638#define NS_FACE_FOREGROUND(f) ((f)->foreground)
639#define NS_FACE_BACKGROUND(f) ((f)->background)
640#define FRAME_NS_TITLEBAR_HEIGHT(f) ((f)->output_data.ns->titlebar_height)
641#define FRAME_NS_TOOLBAR_HEIGHT(f) ((f)->output_data.ns->toolbar_height)
642
643#define FONT_WIDTH(f) ((f)->max_width)
644#define FONT_HEIGHT(f) ((f)->height)
645/*#define FONT_BASE(f) ((f)->ascent) */
646#define FONT_BASE(f) (((struct nsfont_info *)f)->max_bounds.ascent)
647/*#define FONT_DESCENT(f) ((f)->descent) */
648#define FONT_DESCENT(f) (((struct nsfont_info *)f)->max_bounds.descent)
649
650#define FRAME_DEFAULT_FACE(f) FACE_FROM_ID (f, DEFAULT_FACE_ID)
651
652#define FRAME_NS_VIEW(f) ((f)->output_data.ns->view)
653#define FRAME_CURSOR(f) ((f)->output_data.ns->current_cursor)
654#define FRAME_CURSOR_COLOR(f) ((f)->output_data.ns->current_cursor_color)
655#define FRAME_NEW_CURSOR_COLOR(f) ((f)->output_data.ns->desired_cursor_color)
656#define FRAME_NEW_CURSOR(f) ((f)->output_data.ns->desired_cursor)
657#define FRAME_POINTER_TYPE(f) ((f)->output_data.ns->current_pointer)
658#define FRAME_LAST_INACTIVE(f) ((f)->output_data.ns->last_inactive)
659
660#define FRAME_FONT(f) ((f)->output_data.ns->font)
661
662#ifdef __OBJC__
663#define XNS_SCROLL_BAR(vec) ((id) XSAVE_VALUE (vec)->pointer)
664#else
665#define XNS_SCROLL_BAR(vec) XSAVE_VALUE (vec)->pointer
666#endif
667
668/* Compute pixel size for vertical scroll bars */
669#define NS_SCROLL_BAR_WIDTH(f) \
670(FRAME_HAS_VERTICAL_SCROLL_BARS (f) \
671 ? rint (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0 \
672 ? FRAME_CONFIG_SCROLL_BAR_WIDTH (f) \
673 : (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f))) \
674 : 0)
675
676/* Difference btwn char-column-calculated and actual SB widths.
677 This is only a concern for rendering when SB on left. */
678#define NS_SCROLL_BAR_ADJUST(w, f) \
679(WINDOW_HAS_VERTICAL_SCROLL_BAR_ON_LEFT (w) ? \
680 (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f) \
681 - NS_SCROLL_BAR_WIDTH (f)) : 0)
682
683/*PENDING: fix for GNUstep inconsistent accounting for titlebar */
684#ifdef NS_IMPL_GNUSTEP
685#define NS_TOP_POS(f) ((f)->top_pos + 18)
686#else
687#define NS_TOP_POS(f) ((f)->top_pos)
688#endif
689
690#define FRAME_NS_FONT_TABLE(f) (FRAME_NS_DISPLAY_INFO (f)->font_table)
691
692#define FRAME_FONTSET(f) ((f)->output_data.ns->fontset)
693
694/* 23 */
695#define FRAME_SMALLEST_CHAR_WIDTH(f) \
696 (FRAME_NS_DISPLAY_INFO (f)->smallest_char_width)
697#define FRAME_SMALLEST_FONT_HEIGHT(f) \
698 (FRAME_NS_DISPLAY_INFO (f)->smallest_font_height)
699#define FONT_TYPE_FOR_UNIBYTE(font, ch) 0
700#define FONT_TYPE_FOR_MULTIBYTE(font, ch) 0
701#define FRAME_BASELINE_OFFSET(f) ((f)->output_data.ns->baseline_offset)
702#define BLACK_PIX_DEFAULT(f) 0x000000
703#define WHITE_PIX_DEFAULT(f) 0xFFFFFF
704
705/* First position where characters can be shown (instead of scrollbar, if
706 it is on left. */
707#define FIRST_CHAR_POSITION(f) \
708 (! (FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)) ? 0 \
709 : FRAME_SCROLL_BAR_COLS (f))
710
711extern struct ns_display_info *ns_term_init ();
712extern void ns_term_shutdown (int sig);
713
714/* constants for text rendering */
715#define NS_DUMPGLYPH_NORMAL 0
716#define NS_DUMPGLYPH_CURSOR 1
717#define NS_DUMPGLYPH_FOREGROUND 2
718#define NS_DUMPGLYPH_MOUSEFACE 3
719
720
721/* In nsfont, called from fontset.c */
722extern void nsfont_make_fontset_for_font (Lisp_Object name,
723 Lisp_Object font_object);
724
725/* In nsfont, for debugging */
726struct glyph_string;
727void dump_glyphstring (struct glyph_string *s);
728
729/* Implemented in nsterm, published in or needed from nsfns. */
730extern Lisp_Object Qfontsize;
731extern Lisp_Object ns_list_fonts (FRAME_PTR f, Lisp_Object pattern,
732 int size, int maxnames);
733extern void ns_clear_frame (struct frame *f);
734
735#ifdef __OBJC__
736extern const char *ns_font_to_xlfd (NSFont *font);
737#endif
738extern const char *ns_fontname_to_xlfd (const char *name);
739extern const char *ns_xlfd_to_fontname (const char *xlfd);
740
741extern void check_ns (void);
742extern Lisp_Object ns_map_event_to_object ();
743extern Lisp_Object ns_string_from_pasteboard ();
744extern void ns_string_to_pasteboard ();
745extern void nxatoms_of_nsselect ();
746extern int ns_lisp_to_cursor_type ();
747extern Lisp_Object ns_cursor_type_to_lisp (int arg);
748extern Lisp_Object Qnone;
749
750/* XColor defined in dispextern.h (we use color_def->pixel = NSColor id), but
751 this causes an #include snafu, so we can't declare it.
752 extern int ns_defined_color (struct frame *f, char *name, XColor *color_def,
753 int alloc); */
754
755#ifdef __OBJC__
756extern int ns_lisp_to_color (Lisp_Object color, NSColor **col);
757extern NSColor *ns_lookup_indexed_color (unsigned long idx, struct frame *f);
758extern unsigned long ns_index_color (NSColor *color, struct frame *f);
759extern void ns_free_indexed_color (unsigned long idx, struct frame *f);
760#endif
761
762/* C access to ObjC functionality */
763extern void ns_release_object (void *obj);
764extern void ns_retain_object (void *obj);
765extern void *ns_alloc_autorelease_pool ();
766extern void ns_release_autorelease_pool ();
767
768/* in nsmenu */
769extern void update_frame_tool_bar (FRAME_PTR f);
770extern void free_frame_tool_bar (FRAME_PTR f);
771extern void find_and_call_menu_selection (FRAME_PTR f,
772 EMACS_INT menu_bar_items_used, Lisp_Object vector, void *client_data);
773extern Lisp_Object find_and_return_menu_selection (FRAME_PTR f,
774 int keymaps,
775 void *client_data);
776extern Lisp_Object ns_popup_dialog (Lisp_Object position, Lisp_Object contents,
777 Lisp_Object header);
778
779/* two more prototypes that should be moved to a more general include file */
780extern void set_frame_menubar (struct frame *f, int first_time, int deep_p);
781extern void x_set_window_size (struct frame *f, int change_grav,
782 int cols, int rows);
783
784/* From nsimage.m, needed in image.c */
785struct image;
786extern void *ns_image_from_XBM (unsigned char *bits, int width, int height);
787extern void *ns_image_for_XPM (int width, int height, int depth);
788extern void *ns_image_from_file (Lisp_Object file);
789extern int ns_load_image (struct frame *f, struct image *img,
790 Lisp_Object spec_file, Lisp_Object spec_data);
791extern int ns_image_width (void *img);
792extern int ns_image_height (void *img);
793extern unsigned long ns_get_pixel (void *img, int x, int y);
794extern void ns_put_pixel (void *img, int x, int y, unsigned long argb);
795extern void ns_set_alpha (void *img, int x, int y, unsigned char a);
796
797/* This in nsterm.m */
798extern unsigned long ns_get_rgb_color (struct frame *f,
799 float r, float g, float b, float a);
800extern NSPoint last_mouse_motion_position;
801
802#ifdef NS_IMPL_GNUSTEP
803extern char gnustep_base_version[]; /* version tracking */
804#endif
805
806#define MINWIDTH 10
807#define MINHEIGHT 10
808
809/* Screen max coordinate
810 Using larger coordinates causes movewindow/placewindow to abort */
811#define SCREENMAX 16000
812
813#define NS_SCROLL_BAR_WIDTH_DEFAULT [EmacsScroller scrollerWidth]
814/* This is to match emacs on other platforms, ugly though it is. */
815#define NS_SELECTION_COLOR_DEFAULT @"LightGoldenrod2";
816#define RESIZE_HANDLE_SIZE 12
817
818/* Little utility macros */
819#define IN_BOUND(min, x, max) (((x) < (min)) \
820 ? (min) : (((x)>(max)) ? (max) : (x)))
821#define SCREENMAXBOUND(x) (IN_BOUND (-SCREENMAX, x, SCREENMAX))
822
823/* 23: needed somewhere... */
824#define VERTICAL_SCROLL_BAR_WIDTH_TRIM (0)
825
826
827#endif /* HAVE_NS */
diff --git a/src/nsterm.m b/src/nsterm.m
new file mode 100644
index 00000000000..fcf98749f09
--- /dev/null
+++ b/src/nsterm.m
@@ -0,0 +1,6598 @@
1/* NeXT/Open/GNUstep / MacOSX communication module.
2 Copyright (C) 1989, 1993, 1994, 2005, 2006, 2008,
3 Free Software Foundation, Inc.
4
5This file is part of GNU Emacs.
6
7GNU Emacs is free software; you can redistribute it and/or modify
8it under the terms of the GNU General Public License as published by
9the Free Software Foundation; either version 3, or (at your option)
10any later version.
11
12GNU Emacs is distributed in the hope that it will be useful,
13but WITHOUT ANY WARRANTY; without even the implied warranty of
14MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15GNU General Public License for more details.
16
17You should have received a copy of the GNU General Public License
18along with GNU Emacs; see the file COPYING. If not, write to
19the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
20Boston, MA 02110-1301, USA.
21
22Originally by Carl Edman
23Updated by Christian Limpach (chris@nice.ch)
24OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com)
25MacOSX/Aqua port by Christophe de Dinechin (descubes@earthlink.net)
26GNUstep port and post-20 update by Adrian Robert (arobert@cogsci.ucsd.edu)
27*/
28
29#include <math.h>
30#include <sys/types.h>
31#include <time.h>
32#include <unistd.h>
33
34#include "config.h"
35#include "lisp.h"
36#include "blockinput.h"
37#include "sysselect.h"
38#include "nsterm.h"
39#include "systime.h"
40#include "character.h"
41#include "fontset.h"
42#include "composite.h"
43#include "ccl.h"
44
45#include "termhooks.h"
46#include "termopts.h"
47#include "termchar.h"
48
49#include "window.h"
50#include "keyboard.h"
51
52#include "font.h"
53
54/* call tracing */
55#if 0
56int term_trace_num = 0;
57#define NSTRACE(x) fprintf (stderr, "%s:%d: [%d] " #x "\n", \
58 __FILE__, __LINE__, ++term_trace_num)
59#else
60#define NSTRACE(x)
61#endif
62
63
64/* ==========================================================================
65
66 Local declarations
67
68 ========================================================================== */
69
70/* Special keycodes that we pass down the event chain */
71#define KEY_NS_POWER_OFF ((1<<28)|(0<<16)|1)
72#define KEY_NS_OPEN_FILE ((1<<28)|(0<<16)|2)
73#define KEY_NS_OPEN_TEMP_FILE ((1<<28)|(0<<16)|3)
74#define KEY_NS_DRAG_FILE ((1<<28)|(0<<16)|4)
75#define KEY_NS_DRAG_COLOR ((1<<28)|(0<<16)|5)
76#define KEY_NS_DRAG_TEXT ((1<<28)|(0<<16)|6)
77#define KEY_NS_CHANGE_FONT ((1<<28)|(0<<16)|7)
78#define KEY_NS_OPEN_FILE_LINE ((1<<28)|(0<<16)|8)
79#define KEY_NS_INSERT_WORKING_TEXT ((1<<28)|(0<<16)|9)
80#define KEY_NS_DELETE_WORKING_TEXT ((1<<28)|(0<<16)|10)
81#define KEY_NS_SPI_SERVICE_CALL ((1<<28)|(0<<16)|11)
82
83/* Convert a symbol indexed with an NSxxx value to a value as defined
84 in keyboard.c (lispy_function_key). I hope this is a correct way
85 of doing things... */
86static unsigned convert_ns_to_X_keysym[] =
87{
88 NSHomeFunctionKey, 0x50,
89 NSLeftArrowFunctionKey, 0x51,
90 NSUpArrowFunctionKey, 0x52,
91 NSRightArrowFunctionKey, 0x53,
92 NSDownArrowFunctionKey, 0x54,
93 NSPageUpFunctionKey, 0x55,
94 NSPageDownFunctionKey, 0x56,
95 NSEndFunctionKey, 0x57,
96 NSBeginFunctionKey, 0x58,
97 NSSelectFunctionKey, 0x60,
98 NSPrintFunctionKey, 0x61,
99 NSExecuteFunctionKey, 0x62,
100 NSInsertFunctionKey, 0x63,
101 NSUndoFunctionKey, 0x65,
102 NSRedoFunctionKey, 0x66,
103 NSMenuFunctionKey, 0x67,
104 NSFindFunctionKey, 0x68,
105 NSHelpFunctionKey, 0x6A,
106 NSBreakFunctionKey, 0x6B,
107
108 NSF1FunctionKey, 0xBE,
109 NSF2FunctionKey, 0xBF,
110 NSF3FunctionKey, 0xC0,
111 NSF4FunctionKey, 0xC1,
112 NSF5FunctionKey, 0xC2,
113 NSF6FunctionKey, 0xC3,
114 NSF7FunctionKey, 0xC4,
115 NSF8FunctionKey, 0xC5,
116 NSF9FunctionKey, 0xC6,
117 NSF10FunctionKey, 0xC7,
118 NSF11FunctionKey, 0xC8,
119 NSF12FunctionKey, 0xC9,
120 NSF13FunctionKey, 0xCA,
121 NSF14FunctionKey, 0xCB,
122 NSF15FunctionKey, 0xCC,
123
124 NSBackspaceCharacter, 0x08, /* 8: Not on some KBs. */
125 NSDeleteCharacter, 0xFF, /* 127: Big 'delete' key upper right. */
126 NSDeleteFunctionKey, 0x9F, /* 63272: Del forw key off main array. */
127
128 NSTabCharacter, 0x09,
129 0x19, 0x09, /* left tab->regular since pass shift */
130 NSCarriageReturnCharacter, 0x0D,
131 NSNewlineCharacter, 0x0D,
132 NSEnterCharacter, 0x8D,
133
134 0x1B, 0x1B /* escape */
135};
136
137
138/* Lisp communications */
139Lisp_Object ns_input_file, ns_input_font, ns_input_fontsize, ns_input_line;
140Lisp_Object ns_input_color, ns_input_text, ns_working_text;
141Lisp_Object ns_input_spi_name, ns_input_spi_arg;
142Lisp_Object Vx_toolkit_scroll_bars;
143static Lisp_Object Qmodifier_value;
144/*PENDING: unsure why these defined in term files, anyway we need in keymap.c */
145Lisp_Object Qalt, Qcontrol, Qhyper, Qmeta, Qsuper;
146extern Lisp_Object Qcursor_color, Qcursor_type, Qns;
147extern int lisp_to_mod (Lisp_Object lmod);
148
149
150EmacsPrefsController *prefsController;
151
152/* Defaults managed through the OpenStep defaults system. These pertain to
153 the NS interface specifically. Although a customization group could be
154 created, it's more natural to manage them via defaults. */
155
156/* Specifies which emacs modifier should be generated when NS receives
157 the Alternate modifer. May be Qnone or any of the modifier lisp symbols. */
158Lisp_Object ns_alternate_modifier;
159
160/* Specifies which emacs modifier should be generated when NS receives
161 the Command modifer. May be any of the modifier lisp symbols. */
162Lisp_Object ns_command_modifier;
163
164/* Specifies which emacs modifier should be generated when NS receives
165 the Control modifer. May be any of the modifier lisp symbols. */
166Lisp_Object ns_control_modifier;
167
168/* Specifies which emacs modifier should be generated when NS receives
169 the Function modifer (laptops). May be any of the modifier lisp symbols. */
170Lisp_Object ns_function_modifier;
171
172/* A floating point value specifying the rate at which to blink the cursor.
173 YES indicates 0.5, NO indicates no blinking. */
174Lisp_Object ns_cursor_blink_rate;
175
176/* Used for liason with core emacs cursor-blink-mode. */
177Lisp_Object ns_cursor_blink_mode;
178
179/* A floating point value specifying vertical stretch (positive) or shrink
180 (negative) of text line spacing. Zero means default spacing.
181 YES indicates 0.5, NO indicates 0.0. */
182Lisp_Object ns_expand_space;
183
184/* Control via default 'GSFontAntiAlias' on OS X and GNUstep. */
185int ns_antialias_text;
186
187/* On OS X picks up the default NSGlobalDomain AppleAntiAliasingThreshold,
188 the maximum font size to NOT antialias. On GNUstep there is currently
189 no way to control this behavior. */
190float ns_antialias_threshold;
191
192/* Controls use of an undocumented CG function to do Quickdraw-style font
193 smoothing (less heavy) instead of regular Quartz smoothing. */
194int ns_use_qd_smoothing;
195
196/* Used to pick up AppleHighlightColor on OS X */
197int ns_use_system_highlight_color;
198NSString *ns_selection_color;
199
200
201NSArray *ns_send_types =0, *ns_return_types =0, *ns_drag_types =0;
202
203/* Display variables */
204struct ns_display_info *ns_display_list; /* Chain of existing displays */
205Lisp_Object ns_display_name_list;
206long context_menu_value = 0;
207
208/* display update */
209NSPoint last_mouse_motion_position;
210static NSRect last_mouse_glyph;
211static unsigned long last_mouse_movement_time = 0;
212static Lisp_Object last_mouse_motion_frame;
213static EmacsScroller *last_mouse_scroll_bar = nil;
214static struct frame *ns_updating_frame;
215static NSView *focus_view = NULL;
216static int ns_window_num =0;
217static NSRect uRect;
218static BOOL gsaved = NO;
219BOOL ns_in_resize = NO;
220int ns_tmp_flags; /*PENDING */
221struct nsfont_info *ns_tmp_font; /*PENDING */
222/*static int debug_lock = 0; */
223
224#ifdef NS_IMPL_COCOA
225/* This undocumented Quartz function controls how fonts are anti-aliased.
226 (Found from code in Mac wxWindows impl, discovered by running `nm' on
227 the "QD" framework.)
228 Mode 0 is normal anti-aliasing, mode 1 is no anti-aliasing, and mode 2 is
229 4-bit pixel-aligned anti-aliasing (the old QuickDraw standard). */
230extern void CGContextSetFontRenderingMode (CGContextRef cg, int v);
231#endif
232
233
234/* event loop */
235static BOOL send_appdefined = YES;
236static NSEvent *last_appdefined_event = 0;
237static NSTimer *timed_entry = 0;
238static NSTimer *fd_entry = nil;
239static NSTimer *cursor_blink_entry = nil;
240static NSTimer *scroll_repeat_entry = nil;
241static fd_set select_readfds, t_readfds;
242static struct timeval select_timeout;
243static int select_nfds;
244static NSAutoreleasePool *outerpool;
245static BOOL ns_shutdown_properly = NO;
246static struct input_event *emacs_event = NULL;
247static struct input_event *q_event_ptr = NULL;
248static int n_emacs_events_pending = 0;
249static NSMutableArray *ns_pending_files, *ns_pending_service_names,
250 *ns_pending_service_args;
251static BOOL inNsSelect = 0;
252
253/* Convert modifiers in a NeXTSTEP event to emacs style modifiers. */
254#define NS_FUNCTION_KEY_MASK 0x800000
255#define EV_MODIFIERS(e) \
256 ((([e modifierFlags] & NSHelpKeyMask) ? \
257 hyper_modifier : 0) \
258 | (([e modifierFlags] & NSAlternateKeyMask) ? \
259 lisp_to_mod (ns_alternate_modifier) : 0) \
260 | (([e modifierFlags] & NSShiftKeyMask) ? \
261 shift_modifier : 0) \
262 | (([e modifierFlags] & NSControlKeyMask) ? \
263 lisp_to_mod (ns_control_modifier) : 0) \
264 | (([e modifierFlags] & NS_FUNCTION_KEY_MASK) ? \
265 lisp_to_mod (ns_function_modifier) : 0) \
266 | (([e modifierFlags] & NSCommandKeyMask) ? \
267 lisp_to_mod (ns_command_modifier):0))
268
269#define EV_UDMODIFIERS(e) \
270 ((([e type] == NSLeftMouseDown) ? down_modifier : 0) \
271 | (([e type] == NSRightMouseDown) ? down_modifier : 0) \
272 | (([e type] == NSLeftMouseDragged) ? down_modifier : 0) \
273 | (([e type] == NSRightMouseDragged) ? down_modifier : 0) \
274 | (([e type] == NSLeftMouseUp) ? up_modifier : 0) \
275 | (([e type] == NSRightMouseUp) ? up_modifier : 0))
276
277#define EV_BUTTON(e) \
278 ((([e type] == NSLeftMouseDown) || ([e type] == NSLeftMouseUp)) ? 0 : \
279 (([e type] == NSRightMouseDown) || ([e type] == NSRightMouseUp)) ? 2 : 1)
280
281/* Convert the time field to a timestamp in milliseconds. */
282#ifdef NS_IMPL_GNUSTEP
283/* Apple says timestamp is in seconds, but GNUstep seems to be returning msec */
284#define EV_TIMESTAMP(e) ([e timestamp])
285#else
286#define EV_TIMESTAMP(e) ([e timestamp] * 1000)
287#endif /* not gnustep */
288
289/* This is a piece of code which is common to all the event handling
290 methods. Maybe it should even be a function. */
291#define EV_TRAILER(e) \
292 { \
293 XSETFRAME (emacs_event->frame_or_window, [NSApp isActive] ? \
294 emacsframe : SELECTED_FRAME ()); \
295 if (e) emacs_event->timestamp = EV_TIMESTAMP (e); \
296 n_emacs_events_pending++; \
297 kbd_buffer_store_event_hold (emacs_event, q_event_ptr); \
298 EVENT_INIT (*emacs_event); \
299 ns_send_appdefined (-1); \
300 }
301
302/*PENDING: get rid of need for these forward declarations */
303static void ns_condemn_scroll_bars (struct frame *f),
304 ns_judge_scroll_bars (struct frame *f);
305
306/* unused variables needed for compatibility reasons */
307int x_use_underline_position_properties, x_underline_at_descent_line;
308/* PENDING: figure out what to do with underline_minimum_offset. */
309
310
311/* ==========================================================================
312
313 Utilities
314
315 ========================================================================== */
316
317
318static Lisp_Object
319append2 (Lisp_Object list, Lisp_Object item)
320/* --------------------------------------------------------------------------
321 Utility to append to a list
322 -------------------------------------------------------------------------- */
323{
324 Lisp_Object array[2];
325 array[0] = list;
326 array[1] = Fcons (item, Qnil);
327 return Fnconc (2, &array[0]);
328}
329
330
331void
332ns_init_paths ()
333/* --------------------------------------------------------------------------
334 Used to allow emacs to find its resources under Emacs.app
335 Called from emacs.c at startup.
336 -------------------------------------------------------------------------- */
337{
338 NSBundle *bundle = [NSBundle mainBundle];
339 NSString *binDir = [bundle bundlePath], *resourceDir = [bundle resourcePath];
340 NSString *resourcePath, *resourcePaths;
341 NSRange range;
342 BOOL onWindows = NO; /* how do I determine this? */
343 NSString *pathSeparator = onWindows ? @";" : @":";
344 NSFileManager *fileManager = [NSFileManager defaultManager];
345 BOOL isDir;
346/*NSLog (@"ns_init_paths: '%@'\n%@\n", [[NSBundle mainBundle] bundlePath], [[NSBundle mainBundle] resourcePath]); */
347
348 /* get bindir from base */
349 range = [resourceDir rangeOfString: @"Contents"];
350 if (range.location != NSNotFound)
351 {
352 binDir = [binDir stringByAppendingPathComponent: @"Contents"];
353#ifdef NS_IMPL_COCOA
354 binDir = [binDir stringByAppendingPathComponent: @"MacOS"];
355#endif
356 }
357
358 /* the following based on Andrew Choi's init_mac_osx_environment () */
359 if (!getenv ("EMACSLOADPATH"))
360 {
361 NSArray *paths = [resourceDir stringsByAppendingPaths:
362 [NSArray arrayWithObjects:
363 @"site-lisp", @"lisp", @"leim", nil]];
364 NSEnumerator *pathEnum = [paths objectEnumerator];
365 resourcePaths = @"";
366 while (resourcePath = [pathEnum nextObject])
367 {
368 if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir])
369 if (isDir)
370 {
371 if ([resourcePaths length] > 0)
372 resourcePaths =
373 [resourcePaths stringByAppendingString: pathSeparator];
374 resourcePaths =
375 [resourcePaths stringByAppendingString: resourcePath];
376 }
377 }
378 if ([resourcePaths length] > 0)
379 setenv ("EMACSLOADPATH", [resourcePaths UTF8String], 1);
380/*NSLog (@"loadPath: '%s'\n", resourcePaths); */
381 }
382
383 if (!getenv ("EMACSPATH"))
384 {
385 NSArray *paths = [binDir stringsByAppendingPaths:
386 [NSArray arrayWithObjects: @"bin",
387 @"lib-exec", nil]];
388 NSEnumerator *pathEnum = [paths objectEnumerator];
389 resourcePaths = @"";
390 while (resourcePath = [pathEnum nextObject])
391 {
392 if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir])
393 if (isDir)
394 {
395 if ([resourcePaths length] > 0)
396 resourcePaths =
397 [resourcePaths stringByAppendingString: pathSeparator];
398 resourcePaths =
399 [resourcePaths stringByAppendingString: resourcePath];
400 }
401 }
402 if ([resourcePaths length] > 0)
403 setenv ("EMACSPATH", [resourcePaths UTF8String], 1);
404 }
405
406 resourcePath = [resourceDir stringByAppendingPathComponent: @"etc"];
407 if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir])
408 {
409 if (isDir)
410 {
411 if (!getenv ("EMACSDATA"))
412 setenv ("EMACSDATA", [resourcePath UTF8String], 1);
413 if (!getenv ("EMACSDOC"))
414 setenv ("EMACSDOC", [resourcePath UTF8String], 1);
415 }
416 }
417
418 /*PENDING: append to INFOPATH... */
419 if (!getenv ("INFOPATH"))
420 {
421 resourcePath = [resourceDir stringByAppendingPathComponent: @"info"];
422 if ([fileManager fileExistsAtPath: resourcePath isDirectory: &isDir])
423 if (isDir)
424 setenv ("INFOPATH", [resourcePath UTF8String], 1);
425 }
426}
427
428
429static int
430timeval_subtract (struct timeval *result, struct timeval x, struct timeval y)
431/* --------------------------------------------------------------------------
432 Subtract the `struct timeval' values X and Y, storing the result in RESULT.
433 Return 1 if the difference is negative, otherwise 0.
434 -------------------------------------------------------------------------- */
435{
436 /* Perform the carry for the later subtraction by updating y.
437 This is safer because on some systems
438 the tv_sec member is unsigned. */
439 if (x.tv_usec < y.tv_usec)
440 {
441 int nsec = (y.tv_usec - x.tv_usec) / 1000000 + 1;
442 y.tv_usec -= 1000000 * nsec;
443 y.tv_sec += nsec;
444 }
445 if (x.tv_usec - y.tv_usec > 1000000)
446 {
447 int nsec = (y.tv_usec - x.tv_usec) / 1000000;
448 y.tv_usec += 1000000 * nsec;
449 y.tv_sec -= nsec;
450 }
451
452 /* Compute the time remaining to wait. tv_usec is certainly positive. */
453 result->tv_sec = x.tv_sec - y.tv_sec;
454 result->tv_usec = x.tv_usec - y.tv_usec;
455
456 /* Return indication of whether the result should be considered negative. */
457 return x.tv_sec < y.tv_sec;
458}
459
460static void
461ns_timeout (int usecs)
462/* --------------------------------------------------------------------------
463 Blocking timer utility used by ns_ring_bell
464 -------------------------------------------------------------------------- */
465{
466 struct timeval wakeup;
467
468 EMACS_GET_TIME (wakeup);
469
470 /* Compute time to wait until, propagating carry from usecs. */
471 wakeup.tv_usec += usecs;
472 wakeup.tv_sec += (wakeup.tv_usec / 1000000);
473 wakeup.tv_usec %= 1000000;
474
475 /* Keep waiting until past the time wakeup. */
476 while (1)
477 {
478 struct timeval timeout;
479
480 EMACS_GET_TIME (timeout);
481
482 /* In effect, timeout = wakeup - timeout.
483 Break if result would be negative. */
484 if (timeval_subtract (&timeout, wakeup, timeout))
485 break;
486
487 /* Try to wait that long--but we might wake up sooner. */
488 select (0, NULL, NULL, NULL, &timeout);
489 }
490}
491
492
493void
494ns_release_object (void *obj)
495/* --------------------------------------------------------------------------
496 Release an object (callable from C)
497 -------------------------------------------------------------------------- */
498{
499 [(id)obj release];
500}
501
502
503void
504ns_retain_object (void *obj)
505/* --------------------------------------------------------------------------
506 Retain an object (callable from C)
507 -------------------------------------------------------------------------- */
508{
509 [(id)obj retain];
510}
511
512
513void *
514ns_alloc_autorelease_pool ()
515/* --------------------------------------------------------------------------
516 Allocate a pool for temporary objects (callable from C)
517 -------------------------------------------------------------------------- */
518{
519 return [[NSAutoreleasePool alloc] init];
520}
521
522
523void
524ns_release_autorelease_pool (void *pool)
525/* --------------------------------------------------------------------------
526 Free a pool and temporary objects it refers to (callable from C)
527 -------------------------------------------------------------------------- */
528{
529 ns_release_object (pool);
530}
531
532
533
534/* ==========================================================================
535
536 Focus (clipping) and screen update
537
538 ========================================================================== */
539
540static NSRect
541ns_resize_handle_rect (NSWindow *window)
542{
543 NSRect r = [window frame];
544 r.origin.x = r.size.width - RESIZE_HANDLE_SIZE;
545 r.origin.y = 0;
546 r.size.width = r.size.height = RESIZE_HANDLE_SIZE;
547 return r;
548}
549
550
551static void
552ns_update_begin (struct frame *f)
553/* --------------------------------------------------------------------------
554 Prepare for a grouped sequence of drawing calls
555 23: external (RIF) call; now split w/ and called before update_window_begin
556 -------------------------------------------------------------------------- */
557{
558 NSView *view = FRAME_NS_VIEW (f);
559 NSTRACE (ns_update_begin);
560/*fprintf (stderr, "\\%p\n", f); */
561
562 ns_updating_frame = f;
563 [view lockFocus];
564
565#ifdef NS_IMPL_GNUSTEP
566 uRect = NSMakeRect (0, 0, 0, 0);
567#endif
568}
569
570
571static void
572ns_update_window_begin (struct window *w)
573/* --------------------------------------------------------------------------
574 Prepare for a grouped sequence of drawing calls
575 23: external (RIF) call; now split with and called after update_begin
576 -------------------------------------------------------------------------- */
577{
578 struct frame *f = XFRAME (WINDOW_FRAME (w));
579 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f);
580 NSTRACE (ns_update_window_begin);
581
582 updated_window = w;
583 set_output_cursor (&w->cursor);
584
585 BLOCK_INPUT;
586
587 if (f == dpyinfo->mouse_face_mouse_frame)
588 {
589 /* Don't do highlighting for mouse motion during the update. */
590 dpyinfo->mouse_face_defer = 1;
591
592 /* If the frame needs to be redrawn,
593 simply forget about any prior mouse highlighting. */
594 if (FRAME_GARBAGED_P (f))
595 dpyinfo->mouse_face_window = Qnil;
596
597 /* (further code for mouse faces ifdef'd out in other terms elided) */
598 }
599
600 UNBLOCK_INPUT;
601}
602
603
604static void
605ns_update_window_end (struct window *w, int cursor_on_p,
606 int mouse_face_overwritten_p)
607/* --------------------------------------------------------------------------
608 Finished a grouped sequence of drawing calls
609 23: external (RIF) call; now split with and called before update_window_end
610 -------------------------------------------------------------------------- */
611{
612 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (XFRAME (w->frame));
613
614 /* note: this fn is nearly identical in all terms */
615 if (!w->pseudo_window_p)
616 {
617 BLOCK_INPUT;
618
619 if (cursor_on_p)
620 display_and_set_cursor (w, 1,
621 output_cursor.hpos, output_cursor.vpos,
622 output_cursor.x, output_cursor.y);
623
624 if (draw_window_fringes (w, 1))
625 x_draw_vertical_border (w);
626
627 UNBLOCK_INPUT;
628 }
629
630 /* If a row with mouse-face was overwritten, arrange for
631 frame_up_to_date to redisplay the mouse highlight. */
632 if (mouse_face_overwritten_p)
633 {
634 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
635 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
636 dpyinfo->mouse_face_window = Qnil;
637 }
638
639 updated_window = NULL;
640 NSTRACE (update_window_end);
641}
642
643
644static void
645ns_update_end (struct frame *f)
646/* --------------------------------------------------------------------------
647 Finished a grouped sequence of drawing calls
648 23: external (RIF) call; now split with and called after update_window_end
649 -------------------------------------------------------------------------- */
650{
651 NSView *view = FRAME_NS_VIEW (f);
652
653/* if (f == FRAME_NS_DISPLAY_INFO (f)->mouse_face_mouse_frame) */
654 FRAME_NS_DISPLAY_INFO (f)->mouse_face_defer = 0;
655
656 BLOCK_INPUT;
657
658#ifdef NS_IMPL_GNUSTEP
659 /* trigger flush only in the rectangle we tracked as being drawn */
660 [view unlockFocusNeedsFlush: NO];
661/*fprintf (stderr, " (%.0f, %.0f : %.0f x %.0f)", uRect.origin.x, uRect.origin.y, uRect.size.width, uRect.size.height); */
662 [view lockFocusInRect: uRect];
663#endif
664
665 [view unlockFocus];
666 [[view window] flushWindow];
667
668 UNBLOCK_INPUT;
669 ns_updating_frame = NULL;
670 NSTRACE (ns_update_end);
671}
672
673
674static void
675ns_flush (struct frame *f)
676/* --------------------------------------------------------------------------
677 23: external (RIF) call
678 NS impl is no-op since currently we flush in ns_update_end and elsewhere
679 -------------------------------------------------------------------------- */
680{
681 NSTRACE (ns_flush);
682}
683
684
685static void
686ns_focus (struct frame *f, NSRect *r, int n)
687/* --------------------------------------------------------------------------
688 Internal: Focus on given frame. During small local updates this is used to
689 draw, however during large updates, ns_update_begin and ns_update_end are
690 called to wrap the whole thing, in which case these calls are stubbed out.
691 Except, on GNUstep, we accumulate the rectangle being drawn into, because
692 the back end won't do this automatically, and will just end up flushing
693 the entire window.
694 -------------------------------------------------------------------------- */
695{
696 NSTRACE (ns_focus);
697#ifdef NS_IMPL_GNUSTEP
698 NSRect u;
699 if (n == 2)
700 u = NSUnionRect (r[0], r[1]);
701 else if (r)
702 u = *r;
703#endif
704/* static int c =0;
705 fprintf (stderr, "focus: %d", c++);
706 if (r) fprintf (stderr, " (%.0f, %.0f : %.0f x %.0f)", r->origin.x, r->origin.y, r->size.width, r->size.height);
707 fprintf (stderr, "\n"); */
708
709 if (f != ns_updating_frame)
710 {
711 NSView *view = FRAME_NS_VIEW (f);
712 if (view != focus_view)
713 {
714 if (focus_view != NULL)
715 {
716 [focus_view unlockFocus];
717 [[focus_view window] flushWindow];
718/*debug_lock--; */
719 }
720
721 if (view)
722#ifdef NS_IMPL_GNUSTEP
723 r ? [view lockFocusInRect: u] : [view lockFocus];
724#else
725 [view lockFocus];
726#endif
727 focus_view = view;
728/*if (view) debug_lock++; */
729 }
730#ifdef NS_IMPL_GNUSTEP
731 else
732 {
733 /* more than one rect being drawn into */
734 if (view && r)
735 {
736 [view unlockFocus]; /* add prev rect to redraw list */
737 [view lockFocusInRect: u]; /* focus for draw in new rect */
738 }
739 }
740#endif
741 }
742#ifdef NS_IMPL_GNUSTEP
743 else
744 {
745 /* in batch mode, but in GNUstep must still track rectangles explicitly */
746 uRect = (r ? NSUnionRect (uRect, u) : [FRAME_NS_VIEW (f) visibleRect]);
747 }
748#endif
749
750 /*23: clipping */
751 if (r)
752 {
753 [[NSGraphicsContext currentContext] saveGraphicsState];
754 if (n == 2)
755 NSRectClipList (r, 2);
756 else
757 NSRectClip (*r);
758 gsaved = YES;
759 }
760}
761
762
763static void
764ns_unfocus (struct frame *f)
765/* --------------------------------------------------------------------------
766 Internal: Remove focus on given frame
767 -------------------------------------------------------------------------- */
768{
769 NSTRACE (ns_unfocus);
770
771 if (gsaved)
772 {
773 [[NSGraphicsContext currentContext] restoreGraphicsState];
774 gsaved = NO;
775 }
776
777 if (f != ns_updating_frame)
778 {
779 if (focus_view != NULL)
780 {
781 [focus_view unlockFocus];
782 [[focus_view window] flushWindow];
783 focus_view = NULL;
784/*debug_lock--; */
785 }
786 }
787}
788
789
790static void
791ns_clip_to_row (struct window *w, struct glyph_row *row, int area, GC gc)
792/* --------------------------------------------------------------------------
793 23: Internal (but parallels other terms): Focus drawing on given row
794 -------------------------------------------------------------------------- */
795{
796 struct frame *f = XFRAME (WINDOW_FRAME (w));
797 NSRect clip_rect;
798 int window_x, window_y, window_width;
799
800 window_box (w, area, &window_x, &window_y, &window_width, 0);
801
802 clip_rect.origin.x = window_x - FRAME_INTERNAL_BORDER_WIDTH (f);
803 clip_rect.origin.y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, row->y));
804 clip_rect.origin.y = max (clip_rect.origin.y, window_y);
805 clip_rect.size.width = window_width + 2 * FRAME_INTERNAL_BORDER_WIDTH (f);
806 clip_rect.size.height = row->visible_height;
807
808 /* allow a full-height row at the top when requested
809 (used to draw fringe all the way through internal border area) */
810 if (gc && clip_rect.origin.y < 5)
811 {
812 clip_rect.origin.y -= FRAME_INTERNAL_BORDER_WIDTH (f);
813 clip_rect.size.height += FRAME_INTERNAL_BORDER_WIDTH (f);
814 }
815
816 /* likewise at bottom */
817 if (gc &&
818 FRAME_PIXEL_HEIGHT (f) - (clip_rect.origin.y + clip_rect.size.height) < 5)
819 clip_rect.size.height += FRAME_INTERNAL_BORDER_WIDTH (f);
820
821 ns_focus (f, &clip_rect, 1);
822}
823
824
825static void
826ns_ring_bell ()
827/* --------------------------------------------------------------------------
828 "Beep" routine
829 -------------------------------------------------------------------------- */
830{
831 NSTRACE (ns_ring_bell);
832 if (visible_bell)
833 {
834 NSAutoreleasePool *pool;
835 struct frame *frame = SELECTED_FRAME ();
836 NSView *view;
837
838 BLOCK_INPUT;
839 pool = [[NSAutoreleasePool alloc] init];
840
841 view = FRAME_NS_VIEW (frame);
842 if (view != nil)
843 {
844 NSRect r, surr;
845 NSPoint dim = NSMakePoint (128, 128);
846
847 r = [view bounds];
848 r.origin.x += (r.size.width - dim.x) / 2;
849 r.origin.y += (r.size.height - dim.y) / 2;
850 r.size.width = dim.x;
851 r.size.height = dim.y;
852 /* PENDING: cacheImageInRect under GNUSTEP does not account for
853 offset in x_set_window_size, so overestimate (4 fine on Cocoa) */
854 surr = NSInsetRect (r, -10, -10);
855 ns_focus (frame, &surr, 1);
856 [[view window] cacheImageInRect: surr];
857 [ns_lookup_indexed_color (NS_FACE_FOREGROUND
858 (FRAME_DEFAULT_FACE (frame)), frame) set];
859 NSRectFill (r);
860 [[view window] flushWindow];
861 ns_timeout (150000);
862 [[view window] restoreCachedImage];
863 [[view window] flushWindow];
864 ns_unfocus (frame);
865 }
866 [pool release];
867 UNBLOCK_INPUT;
868 }
869 else
870 {
871 NSBeep ();
872 }
873}
874
875
876static void
877ns_reset_terminal_modes (struct terminal *terminal)
878/* Externally called as hook */
879{
880 NSTRACE (ns_reset_terminal_modes);
881}
882
883static void
884ns_set_terminal_modes (struct terminal *terminal)
885/* Externally called as hook */
886{
887 NSTRACE (ns_set_terminal_modes);
888}
889
890
891
892/* ==========================================================================
893
894 Frame / window manager related functions
895
896 ========================================================================== */
897
898
899static void
900ns_raise_frame (struct frame *f)
901/* --------------------------------------------------------------------------
902 Bring window to foreground and make it active
903 -------------------------------------------------------------------------- */
904{
905 NSView *view = FRAME_NS_VIEW (f);
906 check_ns ();
907 BLOCK_INPUT;
908 [[view window] makeKeyAndOrderFront: NSApp];
909 UNBLOCK_INPUT;
910}
911
912
913static void
914ns_lower_frame (struct frame *f)
915/* --------------------------------------------------------------------------
916 Send window to back
917 -------------------------------------------------------------------------- */
918{
919 NSView *view = FRAME_NS_VIEW (f);
920 check_ns ();
921 BLOCK_INPUT;
922 [[view window] orderBack: NSApp];
923 UNBLOCK_INPUT;
924}
925
926
927static void
928ns_frame_raise_lower (struct frame *f, int raise)
929/* --------------------------------------------------------------------------
930 External (hook)
931 -------------------------------------------------------------------------- */
932{
933 NSTRACE (ns_frame_raise_lower);
934
935 if (raise)
936 ns_raise_frame (f);
937 else
938 ns_lower_frame (f);
939}
940
941
942static void
943ns_frame_rehighlight (struct frame *frame)
944/* --------------------------------------------------------------------------
945 External (hook): called on things like window switching within frame
946 -------------------------------------------------------------------------- */
947{
948 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (frame);
949 struct frame *old_highlight = dpyinfo->ns_highlight_frame;
950
951 NSTRACE (ns_frame_rehighlight);
952 if (dpyinfo->ns_focus_frame)
953 {
954 dpyinfo->ns_highlight_frame =
955 (FRAMEP (FRAME_FOCUS_FRAME (dpyinfo->ns_focus_frame))
956 ? XFRAME (FRAME_FOCUS_FRAME (dpyinfo->ns_focus_frame))
957 : dpyinfo->ns_focus_frame);
958 if (!FRAME_LIVE_P (dpyinfo->ns_highlight_frame))
959 {
960 FRAME_FOCUS_FRAME (dpyinfo->ns_focus_frame) = Qnil;
961 dpyinfo->ns_highlight_frame = dpyinfo->ns_focus_frame;
962 }
963 }
964 else
965 dpyinfo->ns_highlight_frame = 0;
966
967 if (dpyinfo->ns_highlight_frame &&
968 dpyinfo->ns_highlight_frame != old_highlight)
969 {
970 /* as of 20080602 the lower and raise are superfluous */
971 if (old_highlight)
972 {
973 /*ns_lower_frame (old_highlight); */
974 x_update_cursor (old_highlight, 1);
975 }
976 if (dpyinfo->ns_highlight_frame)
977 {
978 /*ns_raise_frame (dpyinfo->ns_highlight_frame); */
979 x_update_cursor (dpyinfo->ns_highlight_frame, 1);
980 }
981 }
982}
983
984
985void
986x_make_frame_visible (struct frame *f)
987/* --------------------------------------------------------------------------
988 External: Show the window (X11 semantics)
989 -------------------------------------------------------------------------- */
990{
991 NSTRACE (x_make_frame_visible);
992 /* PENDING: at some points in past this was not needed, as the only place that
993 called this (frame.c:Fraise_frame ()) also called raise_lower;
994 if this ends up the case again, comment this out again. */
995 if (!FRAME_VISIBLE_P (f))
996 ns_raise_frame (f);
997}
998
999
1000void
1001x_make_frame_invisible (struct frame *f)
1002/* --------------------------------------------------------------------------
1003 External: Hide the window (X11 semantics)
1004 -------------------------------------------------------------------------- */
1005{
1006 NSView * view = FRAME_NS_VIEW (f);
1007 NSTRACE (x_make_frame_invisible);
1008 check_ns ();
1009 [[view window] orderOut: NSApp];
1010}
1011
1012
1013void
1014x_iconify_frame (struct frame *f)
1015/* --------------------------------------------------------------------------
1016 External: Iconify window
1017 -------------------------------------------------------------------------- */
1018{
1019 NSView * view = FRAME_NS_VIEW (f);
1020 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f);
1021 NSTRACE (x_iconify_frame);
1022 check_ns ();
1023
1024 if (dpyinfo->ns_highlight_frame == f)
1025 dpyinfo->ns_highlight_frame = 0;
1026
1027 if ([[view window] windowNumber] <= 0)
1028 {
1029 /* the window is still deferred. Make it very small, bring it
1030 on screen and order it out. */
1031 NSRect s = { { 100, 100}, {0, 0} };
1032 NSRect t;
1033 t = [[view window] frame];
1034 [[view window] setFrame: s display: NO];
1035 [[view window] orderBack: NSApp];
1036 [[view window] orderOut: NSApp];
1037 [[view window] setFrame: t display: NO];
1038 }
1039 [[view window] miniaturize: NSApp];
1040}
1041
1042
1043void
1044x_destroy_window (struct frame *f)
1045/* --------------------------------------------------------------------------
1046 External: Delete the window
1047 -------------------------------------------------------------------------- */
1048{
1049 NSView *view = FRAME_NS_VIEW (f);
1050 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f);
1051 NSTRACE (x_destroy_window);
1052 check_ns ();
1053
1054 [(EmacsView *)view setWindowClosing: YES]; /* may not have been informed */
1055
1056 BLOCK_INPUT;
1057
1058 free_frame_menubar (f);
1059
1060 if (FRAME_FACE_CACHE (f))
1061 free_frame_faces (f);
1062
1063 if (f == dpyinfo->ns_focus_frame)
1064 dpyinfo->ns_focus_frame = 0;
1065 if (f == dpyinfo->ns_highlight_frame)
1066 dpyinfo->ns_highlight_frame = 0;
1067 if (f == dpyinfo->mouse_face_mouse_frame)
1068 {
1069 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
1070 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
1071 dpyinfo->mouse_face_window = Qnil;
1072 dpyinfo->mouse_face_deferred_gc = 0;
1073 dpyinfo->mouse_face_mouse_frame = 0;
1074 }
1075
1076 xfree (f->output_data.ns);
1077
1078 [[view window] close];
1079 [view release];
1080
1081 ns_window_num--;
1082 UNBLOCK_INPUT;
1083}
1084
1085
1086void
1087x_set_offset (struct frame *f, int xoff, int yoff, int change_grav)
1088/* --------------------------------------------------------------------------
1089 External: Position the window
1090 -------------------------------------------------------------------------- */
1091{
1092 NSScreen *screen;
1093 NSView *view = FRAME_NS_VIEW (f);
1094
1095 NSTRACE (x_set_offset);
1096
1097 BLOCK_INPUT;
1098
1099 f->left_pos = xoff;
1100 f->top_pos = yoff;
1101#ifdef NS_IMPL_GNUSTEP
1102 if (xoff < 100)
1103 f->left_pos = 100; /* don't overlap menu */
1104#endif
1105 if (view != nil && (screen = [[view window] screen]))
1106 [[view window] setFrameTopLeftPoint:
1107 NSMakePoint (SCREENMAXBOUND (f->left_pos),
1108 SCREENMAXBOUND ([screen frame].size.height
1109 - NS_TOP_POS (f)))];
1110 UNBLOCK_INPUT;
1111}
1112
1113
1114void
1115x_set_window_size (struct frame *f, int change_grav, int cols, int rows)
1116/* --------------------------------------------------------------------------
1117 Adjust window pixel size based on given character grid size
1118 Impl is a bit more complex than other terms, need to do some
1119 internal clipping and also pay attention to screen constraints.
1120 -------------------------------------------------------------------------- */
1121{
1122 EmacsView *view = FRAME_NS_VIEW (f);
1123 EmacsToolbar *toolbar = [view toolbar];
1124 NSWindow *window = [view window];
1125 NSScreen *screen = [window screen];
1126 NSRect wr = [window frame];
1127 int tb = FRAME_EXTERNAL_TOOL_BAR (f);
1128 int pixelwidth, pixelheight;
1129 static int oldRows, oldCols, oldFontWidth, oldFontHeight;
1130 static int oldTB;
1131 static struct frame *oldF;
1132
1133 NSTRACE (x_set_window_size);
1134
1135 if (view == nil ||
1136 (f == oldF
1137 && rows == oldRows && cols == oldCols
1138 && oldFontWidth == FRAME_COLUMN_WIDTH (f)
1139 && oldFontHeight == FRAME_LINE_HEIGHT (f)
1140 && oldTB == tb))
1141 return;
1142
1143/*fprintf (stderr, "\tsetWindowSize: %d x %d, font size %d x %d\n", cols, rows, FRAME_COLUMN_WIDTH (f), FRAME_LINE_HEIGHT (f)); */
1144
1145 BLOCK_INPUT;
1146
1147 check_frame_size (f, &rows, &cols);
1148 oldF = f;
1149 oldRows = rows;
1150 oldCols = cols;
1151 oldFontWidth = FRAME_COLUMN_WIDTH (f);
1152 oldFontHeight = FRAME_LINE_HEIGHT (f);
1153 oldTB = tb;
1154
1155 f->scroll_bar_actual_width = NS_SCROLL_BAR_WIDTH (f);
1156 compute_fringe_widths (f, 0);
1157
1158 pixelwidth = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, cols);
1159 pixelheight = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, rows);
1160
1161 /* If we have a change in toolbar display, calculate height */
1162 if (tb)
1163 /* PENDING: GNUstep has not yet implemented the first method below, added
1164 in Panther, however the second is incorrect under Cocoa. */
1165#ifdef NS_IMPL_GNUSTEP
1166 FRAME_NS_TOOLBAR_HEIGHT (f) =
1167 NSHeight ([NSWindow frameRectForContentRect: NSMakeRect (0, 0, 0, 0)
1168 styleMask: [window styleMask]])
1169 - FRAME_NS_TITLEBAR_HEIGHT (f);
1170#else
1171 FRAME_NS_TOOLBAR_HEIGHT (f) = 32;
1172 /* actually get wrong result here if toolbar not yet displayed
1173 NSHeight ([window frameRectForContentRect: NSMakeRect (0, 0, 0, 0)])
1174 - FRAME_NS_TITLEBAR_HEIGHT (f); */
1175#endif
1176 else
1177 FRAME_NS_TOOLBAR_HEIGHT (f) = 0;
1178
1179 wr.size.width = pixelwidth + f->border_width;
1180 wr.size.height = pixelheight + FRAME_NS_TITLEBAR_HEIGHT (f)
1181 + FRAME_NS_TOOLBAR_HEIGHT (f);
1182
1183 /* constrain to screen if we can */
1184 if (screen)
1185 {
1186 NSSize sz = [screen visibleFrame].size;
1187 NSSize ez = { wr.size.width - sz.width, wr.size.height - sz.height };
1188 if (ez.width > 0)
1189 {
1190 int cr = ez.width / FRAME_COLUMN_WIDTH (f) + 1;
1191 cols -= cr;
1192 oldCols = cols;
1193 wr.size.width -= cr * FRAME_COLUMN_WIDTH (f);
1194 pixelwidth -= cr * FRAME_COLUMN_WIDTH (f);
1195 }
1196 if (ez.height > 0)
1197 {
1198 int rr = ez.height / FRAME_LINE_HEIGHT (f) + 1;
1199 rows -= rr;
1200 oldRows = rows;
1201 wr.size.height -= rr * FRAME_LINE_HEIGHT (f);
1202 pixelheight -= rr * FRAME_LINE_HEIGHT (f);
1203 }
1204 wr.origin.x = f->left_pos;
1205 wr.origin.y = [screen frame].size.height - NS_TOP_POS (f)
1206 - wr.size.height;
1207 }
1208
1209 [view setRows: rows andColumns: cols];
1210 [window setFrame: wr display: YES];
1211
1212/*fprintf (stderr, "\tx_set_window_size %d, %d\t%d, %d\n", cols, rows, pixelwidth, pixelheight); */
1213
1214 /* This is a trick to compensate for Emacs' managing the scrollbar area
1215 as a fixed number of standard character columns. Instead of leaving
1216 blank space for the extra, we chopped it off above. Now for
1217 left-hand scrollbars, we shift all rendering to the left by the
1218 difference between the real width and Emacs' imagined one. For
1219 right-hand bars, don't worry about it since the extra is never used.
1220 (Obviously doesn't work for vertically split windows tho..) */
1221 NSPoint origin = FRAME_HAS_VERTICAL_SCROLL_BARS_ON_LEFT (f)
1222 ? NSMakePoint (FRAME_SCROLL_BAR_COLS (f) * FRAME_COLUMN_WIDTH (f)
1223 - NS_SCROLL_BAR_WIDTH (f), 0)
1224 : NSMakePoint (0, 0);
1225 [view setFrame: NSMakeRect (0, 0, pixelwidth, pixelheight)];
1226 [view setBoundsOrigin: origin];
1227
1228 change_frame_size (f, rows, cols, 0, 1, 0); /* pretend, delay, safe */
1229 FRAME_PIXEL_WIDTH (f) = pixelwidth;
1230 FRAME_PIXEL_HEIGHT (f) = pixelheight;
1231/* SET_FRAME_GARBAGED (f); // this short-circuits expose call in drawRect */
1232
1233 mark_window_cursors_off (XWINDOW (f->root_window));
1234 cancel_mouse_face (f);
1235
1236 UNBLOCK_INPUT;
1237}
1238
1239
1240/* ==========================================================================
1241
1242 Color management
1243
1244 ========================================================================== */
1245
1246NSColor *
1247ns_lookup_indexed_color (unsigned long idx, struct frame *f)
1248{
1249 struct ns_color_table *color_table = FRAME_NS_DISPLAY_INFO (f)->color_table;
1250 return color_table->colors[idx];
1251}
1252
1253
1254unsigned long
1255ns_index_color (NSColor *color, struct frame *f)
1256{
1257 struct ns_color_table *color_table = FRAME_NS_DISPLAY_INFO (f)->color_table;
1258 int idx;
1259 NSNumber *index;
1260
1261 if (!color_table->colors)
1262 {
1263 color_table->size = NS_COLOR_CAPACITY;
1264 color_table->avail = 1; /* skip idx=0 as marker */
1265 color_table->colors =
1266 (NSColor **)xmalloc (color_table->size * sizeof (NSColor *));
1267 color_table->empty_indices = [[NSMutableSet alloc] init];
1268 }
1269
1270 /* do we already have this color ? */
1271 {
1272 int i;
1273 for (i = 1; i < color_table->avail; i++)
1274 {
1275 if (color_table->colors[i] && [color_table->colors[i] isEqual: color])
1276 {
1277 [color_table->colors[i] retain];
1278 return i;
1279 }
1280 }
1281 }
1282
1283 if ([color_table->empty_indices count] > 0)
1284 {
1285 index = [color_table->empty_indices anyObject];
1286 [color_table->empty_indices removeObject: index];
1287 idx = [index unsignedIntValue];
1288 }
1289 else
1290 {
1291 if (color_table->avail == color_table->size)
1292 {
1293 color_table->size += NS_COLOR_CAPACITY;
1294 color_table->colors =
1295 (NSColor **)xrealloc (color_table->colors,
1296 color_table->size * sizeof (NSColor *));
1297 }
1298 idx = color_table->avail++;
1299 index = [NSNumber numberWithUnsignedInt: idx];
1300 }
1301
1302 color_table->colors[idx] = color;
1303 [color retain];
1304/*fprintf(stderr, "color_table: allocated %d\n",idx);*/
1305 return idx;
1306}
1307
1308
1309void
1310ns_free_indexed_color (unsigned long idx, struct frame *f)
1311{
1312 struct ns_color_table *color_table = FRAME_NS_DISPLAY_INFO (f)->color_table;
1313 NSColor *color;
1314 if (!idx)
1315 return;
1316 color = color_table->colors[idx];
1317 [color release];
1318 color_table->colors[idx] = nil;
1319 [color_table->empty_indices addObject: [NSNumber numberWithUnsignedInt: idx]];
1320/*fprintf(stderr, "color_table: FREED %d\n",idx);*/
1321}
1322
1323
1324static int
1325ns_get_color (const char *name, NSColor **col)
1326/* --------------------------------------------------------------------------
1327 Parse a color name
1328/* --------------------------------------------------------------------------
1329/* On *Step, we recognize several color formats, in addition to a catalog
1330 of colors found in the file Emacs.clr. Color formats include:
1331 - #rrggbb or RGBrrggbb where rr, gg, bb specify red, green and blue in hex
1332 - ARGBaarrggbb is similar, with aa being the alpha channel (FF = opaque)
1333 - HSVhhssvv and AHSVaahhssvv are similar for hue, saturation, value
1334 - CMYKccmmyykk is similar for cyan, magenta, yellow, black. */
1335{
1336 NSColor * new = nil;
1337 const char *hex = NULL;
1338 enum { rgb, argb, hsv, ahsv, cmyk, gray } color_space;
1339 NSString *nsname = [NSString stringWithUTF8String: name];
1340
1341/*fprintf (stderr, "ns_get_color: '%s'\n", name); */
1342 BLOCK_INPUT;
1343
1344 if ([nsname isEqualToString: @"ns_selection_color"])
1345 {
1346 nsname = ns_selection_color;
1347 name = [ns_selection_color UTF8String];
1348 }
1349
1350 if (name[0] == '0' || name[0] == '1' || name[0] == '.')
1351 {
1352 /* RGB decimal */
1353 NSScanner *scanner = [NSScanner scannerWithString: nsname];
1354 float r, g, b;
1355 [scanner scanFloat: &r];
1356 [scanner scanFloat: &g];
1357 [scanner scanFloat: &b];
1358 *col = [NSColor colorWithCalibratedRed: r green: g blue: b alpha: 1.0];
1359 UNBLOCK_INPUT;
1360 return 0;
1361 }
1362
1363 /* 23: PENDING: emacs seems to downcase everything before passing it here,
1364 which we can work around, except for GRAY, since gray##, where ## is
1365 decimal between 0 and 99, is also an X11 colorname. */
1366 if (name[0] == '#') /* X11 format */
1367 {
1368 hex = name + 1;
1369 color_space = rgb;
1370 }
1371 else if (!memcmp (name, "RGB", 3) || !memcmp (name, "rgb", 3))
1372 {
1373 hex = name + 3;
1374 color_space = rgb;
1375 }
1376 else if (!memcmp (name, "ARGB", 4) || !memcmp (name, "argb", 4))
1377 {
1378 hex = name + 4;
1379 color_space = argb;
1380 }
1381 else if (!memcmp (name, "HSV", 3) || !memcmp (name, "hsv", 3))
1382 {
1383 hex = name + 3;
1384 color_space = hsv;
1385 }
1386 else if (!memcmp (name, "AHSV", 4) || !memcmp (name, "ahsv", 4))
1387 {
1388 hex = name + 4;
1389 color_space = ahsv;
1390 }
1391 else if (!memcmp (name, "CMYK", 4) || !memcmp (name, "cmyk", 4))
1392 {
1393 hex = name + 4;
1394 color_space = cmyk;
1395 }
1396 else if (!memcmp (name, "GRAY", 4) /*|| !memcmp (name, "gray", 4)*/)
1397 {
1398 hex = name + 4;
1399 color_space = gray;
1400 }
1401
1402 /* Direct colors (hex values) */
1403 if (hex)
1404 {
1405 unsigned int color = 0;
1406 if (sscanf (hex, "%x", &color))
1407 {
1408 float f1 = ((color >> 24) & 0xff) / 255.0;
1409 float f2 = ((color >> 16) & 0xff) / 255.0;
1410 float f3 = ((color >> 8) & 0xff) / 255.0;
1411 float f4 = ((color ) & 0xff) / 255.0;
1412
1413 switch (color_space)
1414 {
1415 case rgb:
1416 *col = [NSColor colorWithCalibratedRed: f2
1417 green: f3
1418 blue: f4
1419 alpha: 1.0];
1420 break;
1421 case argb:
1422 *col = [NSColor colorWithCalibratedRed: f2
1423 green: f3
1424 blue: f4
1425 alpha: f1];
1426 break;
1427 case hsv:
1428 *col = [NSColor colorWithCalibratedHue: f2
1429 saturation: f3
1430 brightness: f4
1431 alpha: 1.0];
1432 break;
1433 case ahsv:
1434 *col = [NSColor colorWithCalibratedHue: f2
1435 saturation: f3
1436 brightness: f4
1437 alpha: f1];
1438 break;
1439 case gray:
1440 *col = [NSColor colorWithCalibratedWhite: f3 alpha: f4];
1441 break;
1442 case cmyk:
1443 *col = [NSColor colorWithDeviceCyan: f1
1444 magenta: f2
1445 yellow: f3
1446 black: f4
1447 alpha: 1.0];
1448 break;
1449 }
1450 *col = [*col colorUsingColorSpaceName: NSCalibratedRGBColorSpace];
1451 UNBLOCK_INPUT;
1452 return 0;
1453 }
1454 }
1455
1456 /* Otherwise, color is expected to be from a list */
1457 {
1458 NSEnumerator *lenum, *cenum;
1459 NSString *name;
1460 NSColorList *clist;
1461#ifdef NS_IMPL_GNUSTEP
1462 /* PENDING: who is wrong, the requestor or the implementation? */
1463 if ([nsname compare: @"Highlight" options: NSCaseInsensitiveSearch]
1464 == NSOrderedSame)
1465 nsname = @"highlightColor";
1466#endif
1467 if ([nsname compare: @"dark blue" options: NSCaseInsensitiveSearch]
1468 == NSOrderedSame
1469 || [nsname compare: @"darkblue" options: NSCaseInsensitiveSearch]
1470 == NSOrderedSame)
1471 nsname = @"navy blue";
1472
1473 lenum = [[NSColorList availableColorLists] objectEnumerator];
1474 while ( (clist = [lenum nextObject]) && new == nil)
1475 {
1476 cenum = [[clist allKeys] objectEnumerator];
1477 while ( (name = [cenum nextObject]) && new == nil )
1478 {
1479 if ([name compare: nsname
1480 options: NSCaseInsensitiveSearch] == NSOrderedSame )
1481 new = [clist colorWithKey: name];
1482 }
1483 }
1484 }
1485
1486 if ( new )
1487 *col = [new colorUsingColorSpaceName: NSCalibratedRGBColorSpace];
1488/* else
1489 NSLog (@"Failed to find color '%@'", nsname); */
1490 UNBLOCK_INPUT;
1491 return new ? 0 : 1;
1492}
1493
1494
1495static NSColor *
1496ns_get_color_default (const char *name, NSColor *dflt)
1497/* --------------------------------------------------------------------------
1498 Parse a color or use a default value
1499 -------------------------------------------------------------------------- */
1500{
1501 NSColor * col;
1502
1503 if (ns_get_color (name, &col))
1504 return dflt;
1505 else
1506 return col;
1507}
1508
1509
1510int
1511ns_lisp_to_color (Lisp_Object color, NSColor **col)
1512/* --------------------------------------------------------------------------
1513 Convert a Lisp string object to a NS color
1514 -------------------------------------------------------------------------- */
1515{
1516 NSTRACE (ns_lisp_to_color);
1517 if (XTYPE (color) == Lisp_String)
1518 return ns_get_color (XSTRING (color)->data, col);
1519 else if (XTYPE (color) == Lisp_Symbol)
1520 return ns_get_color (XSTRING (XSYMBOL (color)->xname)->data, col);
1521 return 1;
1522}
1523
1524
1525Lisp_Object
1526ns_color_to_lisp (NSColor *col)
1527/* --------------------------------------------------------------------------
1528 Convert a color to a lisp string with the RGB equivalent
1529 -------------------------------------------------------------------------- */
1530{
1531 float red, green, blue, alpha, gray;
1532 char buf[1024];
1533 const char *str;
1534 NSTRACE (ns_color_to_lisp);
1535
1536 BLOCK_INPUT;
1537 if ([[col colorSpaceName] isEqualToString: NSNamedColorSpace])
1538
1539 if ((str =[[col colorNameComponent] UTF8String]))
1540 {
1541 UNBLOCK_INPUT;
1542 return build_string ((char *)str);
1543 }
1544
1545 [[col colorUsingColorSpaceName: NSCalibratedRGBColorSpace]
1546 getRed: &red green: &green blue: &blue alpha: &alpha];
1547 if (red ==green && red ==blue)
1548 {
1549 [[col colorUsingColorSpaceName: NSCalibratedWhiteColorSpace]
1550 getWhite: &gray alpha: &alpha];
1551 snprintf (buf, sizeof (buf), "GRAY%02.2lx%02.2lx",
1552 lrint (gray * 0xff), lrint (alpha * 0xff));
1553 UNBLOCK_INPUT;
1554 return build_string (buf);
1555 }
1556
1557 snprintf (buf, sizeof (buf), "ARGB%02.2lx%02.2lx%02.2lx%02.2lx",
1558 lrint (alpha*0xff),
1559 lrint (red*0xff), lrint (green*0xff), lrint (blue*0xff));
1560
1561 UNBLOCK_INPUT;
1562 return build_string (buf);
1563}
1564
1565
1566int
1567ns_defined_color (struct frame *f, char *name, XColor *color_def, int alloc,
1568 char makeIndex)
1569/* --------------------------------------------------------------------------
1570 23: Return 1 if named color found, and set color_def rgb accordingly.
1571 If makeIndex and alloc are nonzero put the color in the color_table,
1572 and set color_def pixel to the resulting index.
1573 If makeIndex is zero, set color_def pixel to ARGB.
1574 Return 0 if not found
1575 -------------------------------------------------------------------------- */
1576{
1577 NSColor *temp;
1578 float r, g, b, a;
1579 int notFound = ns_get_color (name, &temp);
1580
1581 NSTRACE (ns_defined_color);
1582
1583 if (notFound)
1584 return 0;
1585
1586 if (makeIndex && alloc)
1587 color_def->pixel = ns_index_color(temp, f);//[temp retain];
1588
1589 [temp getRed: &r green: &g blue: &b alpha: &a];
1590 color_def->red = r * 256;
1591 color_def->green = g * 256;
1592 color_def->blue = b * 256;
1593
1594 if (!makeIndex)
1595 color_def->pixel =
1596 ARGB_TO_ULONG((int)(a*256),
1597 color_def->red, color_def->green, color_def->blue);
1598
1599 return 1;
1600}
1601
1602
1603unsigned long
1604ns_get_rgb_color (struct frame *f, float r, float g, float b, float a)
1605/* --------------------------------------------------------------------------
1606 return an autoreleased RGB color
1607 -------------------------------------------------------------------------- */
1608{
1609/*static int c = 1; fprintf (stderr, "color request %d\n", c++); */
1610 if (r < 0.0) r = 0.0;
1611 else if (r > 1.0) r = 1.0;
1612 if (g < 0.0) g = 0.0;
1613 else if (g > 1.0) g = 1.0;
1614 if (b < 0.0) b = 0.0;
1615 else if (b > 1.0) b = 1.0;
1616 if (a < 0.0) a = 0.0;
1617 else if (a > 1.0) a = 1.0;
1618 return (unsigned long) ns_index_color(
1619 [NSColor colorWithCalibratedRed: r green: g blue: b alpha: a], f);
1620}
1621
1622
1623
1624/* ==========================================================================
1625
1626 Mouse handling
1627
1628 ========================================================================== */
1629
1630
1631void
1632x_set_mouse_pixel_position (struct frame *f, int pix_x, int pix_y)
1633/* --------------------------------------------------------------------------
1634 Programmatically reposition mouse pointer in pixel coordinates
1635 -------------------------------------------------------------------------- */
1636{
1637 NSTRACE (x_set_mouse_pixel_position);
1638 ns_raise_frame (f);
1639#if 0
1640 /*PENDING: this does not work, and what about GNUstep? */
1641#ifdef NS_IMPL_COCOA
1642 [FRAME_NS_VIEW (f) lockFocus];
1643 PSsetmouse ((float)pix_x, (float)pix_y);
1644 [FRAME_NS_VIEW (f) unlockFocus];
1645#endif
1646#endif
1647}
1648
1649
1650void
1651x_set_mouse_position (struct frame *f, int h, int v)
1652/* --------------------------------------------------------------------------
1653 Programmatically reposition mouse pointer in character coordinates
1654 -------------------------------------------------------------------------- */
1655{
1656 int pix_x, pix_y;
1657
1658 pix_x = FRAME_COL_TO_PIXEL_X (f, h) + FRAME_COLUMN_WIDTH (f) / 2;
1659 pix_y = FRAME_LINE_TO_PIXEL_Y (f, v) + FRAME_LINE_HEIGHT (f) / 2;
1660
1661 if (pix_x < 0) pix_x = 0;
1662 if (pix_x > FRAME_PIXEL_WIDTH (f)) pix_x = FRAME_PIXEL_WIDTH (f);
1663
1664 if (pix_y < 0) pix_y = 0;
1665 if (pix_y > FRAME_PIXEL_HEIGHT (f)) pix_y = FRAME_PIXEL_HEIGHT (f);
1666
1667 x_set_mouse_pixel_position (f, pix_x, pix_y);
1668}
1669
1670
1671static int
1672note_mouse_movement (struct frame *frame, float x, float y)
1673/* ------------------------------------------------------------------------
1674 Called by EmacsView on mouseMovement events. Passes on
1675 to emacs mainstream code if we moved off of a rect of interest
1676 known as last_mouse_glyph.
1677 ------------------------------------------------------------------------ */
1678{
1679 NSTRACE (note_mouse_movement);
1680
1681 XSETFRAME (last_mouse_motion_frame, frame);
1682
1683 /* Note, this doesn't get called for enter/leave, since we don't have a
1684 position. Those are taken care of in the corresponding NSView methods. */
1685
1686 /* has movement gone beyond last rect we were tracking? */
1687 if (x < last_mouse_glyph.origin.x ||
1688 x >= (last_mouse_glyph.origin.x + last_mouse_glyph.size.width) ||
1689 y < last_mouse_glyph.origin.y ||
1690 y >= (last_mouse_glyph.origin.y + last_mouse_glyph.size.height))
1691 {
1692 frame->mouse_moved = 1;
1693 note_mouse_highlight (frame, x, y);
1694 remember_mouse_glyph (frame, x, y, &last_mouse_glyph);
1695 return 1;
1696 }
1697
1698 return 0;
1699}
1700
1701
1702static void
1703ns_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
1704 enum scroll_bar_part *part, Lisp_Object *x, Lisp_Object *y,
1705 unsigned long *time)
1706/* --------------------------------------------------------------------------
1707 External (hook): inform emacs about mouse position and hit parts.
1708 If a scrollbar is being dragged, set bar_window, part, x, y, time.
1709 x & y should be position in the scrollbar (the whole bar, not the handle)
1710 and length of scrollbar respectively
1711 -------------------------------------------------------------------------- */
1712{
1713 id view;
1714 NSPoint position;
1715 int xchar, ychar;
1716 Lisp_Object frame, tail;
1717 struct frame *f;
1718 struct ns_display_info *dpyinfo;
1719
1720 NSTRACE (ns_mouse_position);
1721
1722 if (*fp == NULL)
1723 {
1724 fprintf (stderr, "Warning: ns_mouse_position () called with null *fp.\n");
1725 return;
1726 }
1727
1728 dpyinfo = FRAME_NS_DISPLAY_INFO (*fp);
1729
1730 BLOCK_INPUT;
1731
1732 if (last_mouse_scroll_bar != nil && insist == 0)
1733 {
1734 /* PENDING: we do not use this path at the moment because drag events will
1735 go directly to the EmacsScroller. Leaving code in for now. */
1736 [last_mouse_scroll_bar getMouseMotionPart: (int *)part window: bar_window
1737 x: x y: y];
1738 if (time) *time = last_mouse_movement_time;
1739 last_mouse_scroll_bar = nil;
1740 }
1741 else
1742 {
1743 /* Clear the mouse-moved flag for every frame on this display. */
1744 FOR_EACH_FRAME (tail, frame)
1745 if (FRAME_NS_P (XFRAME (frame))
1746 && FRAME_NS_DISPLAY (XFRAME (frame)) == FRAME_NS_DISPLAY (*fp))
1747 XFRAME (frame)->mouse_moved = 0;
1748
1749 last_mouse_scroll_bar = nil;
1750 if (last_mouse_frame && FRAME_LIVE_P (last_mouse_frame))
1751 f = last_mouse_frame;
1752 else
1753 f = dpyinfo->ns_focus_frame ? dpyinfo->ns_focus_frame
1754 : SELECTED_FRAME ();
1755
1756 if (f && f->output_data.ns) /*PENDING: 2nd check no longer needed? */
1757 {
1758 view = FRAME_NS_VIEW (*fp);
1759
1760 position = [[view window] mouseLocationOutsideOfEventStream];
1761 position = [view convertPoint: position fromView: nil];
1762 remember_mouse_glyph (f, position.x, position.y, &last_mouse_glyph);
1763/*fprintf (stderr, "ns_mouse_position: %.0f, %.0f\n", position.x, position.y); */
1764
1765 if (bar_window) *bar_window = Qnil;
1766 if (part) *part = 0; /*scroll_bar_handle; */
1767
1768 if (x) XSETINT (*x, lrint (position.x));
1769 if (y) XSETINT (*y, lrint (position.y));
1770 if (time) *time = last_mouse_movement_time;
1771 *fp = f;
1772 }
1773 }
1774
1775 UNBLOCK_INPUT;
1776}
1777
1778
1779static void
1780ns_frame_up_to_date (struct frame *f)
1781/* --------------------------------------------------------------------------
1782 External (hook): Fix up mouse highlighting right after a full update.
1783 Some highlighting was deferred if GC was happening during
1784 note_mouse_highlight (), while other highlighting was deferred for update.
1785 -------------------------------------------------------------------------- */
1786{
1787 NSTRACE (ns_frame_up_to_date);
1788
1789 if (FRAME_NS_P (f))
1790 {
1791 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (f);
1792 if ((dpyinfo->mouse_face_deferred_gc||f ==dpyinfo->mouse_face_mouse_frame)
1793 /*&& dpyinfo->mouse_face_mouse_frame*/)
1794 {
1795 BLOCK_INPUT;
1796 if (dpyinfo->mouse_face_mouse_frame)
1797 note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
1798 dpyinfo->mouse_face_mouse_x,
1799 dpyinfo->mouse_face_mouse_y);
1800 dpyinfo->mouse_face_deferred_gc = 0;
1801 UNBLOCK_INPUT;
1802 }
1803 }
1804}
1805
1806
1807void
1808ns_define_frame_cursor (struct frame *f, Cursor cursor)
1809/* --------------------------------------------------------------------------
1810 External (RIF): set frame mouse pointer type.
1811 -------------------------------------------------------------------------- */
1812{
1813 NSTRACE (ns_define_frame_cursor);
1814 if (FRAME_POINTER_TYPE (f) != cursor)
1815 {
1816 EmacsView *view = FRAME_NS_VIEW (f);
1817 FRAME_POINTER_TYPE (f) = cursor;
1818 [[view window] invalidateCursorRectsForView: view];
1819 }
1820}
1821
1822
1823
1824/* ==========================================================================
1825
1826 Keyboard handling
1827
1828 ========================================================================== */
1829
1830
1831static unsigned
1832ns_convert_key (unsigned code)
1833/* --------------------------------------------------------------------------
1834 Internal call used by NSView-keyDown.
1835 -------------------------------------------------------------------------- */
1836{
1837 const unsigned last_keysym = (sizeof (convert_ns_to_X_keysym)
1838 / sizeof (convert_ns_to_X_keysym[0]));
1839 unsigned keysym;
1840 /* An array would be faster, but less easy to read. */
1841 for (keysym = 0; keysym < last_keysym; keysym += 2)
1842 if (code == convert_ns_to_X_keysym[keysym])
1843 return 0xFF00 | convert_ns_to_X_keysym[keysym+1];
1844 return 0;
1845/* if decide to use keyCode and Carbon table, use this line:
1846 return code > 0xff ? 0 : 0xFF00 | ns_keycode_to_xkeysym_table[code]; */
1847}
1848
1849
1850char *
1851x_get_keysym_name (int keysym)
1852/* --------------------------------------------------------------------------
1853 Called by keyboard.c. Not sure if the return val is important, except
1854 that it be unique.
1855 -------------------------------------------------------------------------- */
1856{
1857 static char value[16];
1858 NSTRACE (x_get_keysym_name);
1859 sprintf (value, "%d", keysym);
1860 return value;
1861}
1862
1863
1864
1865/* ==========================================================================
1866
1867 Block drawing operations
1868
1869 ========================================================================== */
1870
1871
1872static void
1873ns_redraw_scroll_bars (struct frame *f)
1874{
1875 int i;
1876 id view;
1877 NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews];
1878 NSTRACE (ns_judge_scroll_bars);
1879 for (i =[subviews count]-1; i >= 0; i--)
1880 {
1881 view = [subviews objectAtIndex: i];
1882 if (![view isKindOfClass: [EmacsScroller class]]) continue;
1883 [view display];
1884 }
1885}
1886
1887
1888void
1889ns_clear_frame (struct frame *f)
1890/* --------------------------------------------------------------------------
1891 External (hook): Erase the entire frame
1892 -------------------------------------------------------------------------- */
1893{
1894 NSView *view = FRAME_NS_VIEW (f);
1895 NSRect r;
1896
1897 NSTRACE (ns_clear_frame);
1898 if (ns_in_resize)
1899 return;
1900
1901 /* comes on initial frame because we have
1902 after-make-frame-functions = select-frame */
1903 if (!FRAME_DEFAULT_FACE (f))
1904 return;
1905
1906 mark_window_cursors_off (XWINDOW (FRAME_ROOT_WINDOW (f)));
1907
1908 output_cursor.hpos = output_cursor.vpos = 0;
1909 output_cursor.x = -1;
1910
1911 r = [view bounds];
1912
1913 BLOCK_INPUT;
1914 ns_focus (f, &r, 1);
1915 [ns_lookup_indexed_color (NS_FACE_BACKGROUND (FRAME_DEFAULT_FACE (f)), f) set];
1916 NSRectFill (r);
1917 ns_unfocus (f);
1918
1919#ifdef NS_IMPL_COCOA
1920 [[view window] display]; /* redraw resize handle */
1921#endif
1922
1923 /* as of 2006/11 or so this is now needed */
1924 ns_redraw_scroll_bars (f);
1925 UNBLOCK_INPUT;
1926}
1927
1928
1929void
1930ns_clear_frame_area (struct frame *f, int x, int y, int width, int height)
1931/* --------------------------------------------------------------------------
1932 23: External (RIF): Clear section of frame
1933 -------------------------------------------------------------------------- */
1934{
1935 NSRect r = NSMakeRect (x, y, width, height);
1936 NSView *view = FRAME_NS_VIEW (f);
1937 struct face *face = FRAME_DEFAULT_FACE (f);
1938
1939 if (!view || !face)
1940 return;
1941
1942 r = NSIntersectionRect (r, [view frame]);
1943 ns_focus (f, &r, 1);
1944 [ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), f) set];
1945
1946#ifdef NS_IMPL_COCOA
1947 {
1948 /* clip out the resize handle */
1949 NSWindow *window = [FRAME_NS_VIEW (f) window];
1950 NSRect ir =
1951 [view convertRect: ns_resize_handle_rect (window) fromView: nil];
1952
1953 ir = NSIntersectionRect (r, ir);
1954 if (NSIsEmptyRect (ir))
1955 {
1956#endif
1957
1958 NSRectFill (r);
1959
1960#ifdef NS_IMPL_COCOA
1961 }
1962 else
1963 {
1964 NSRect r1 = r, r2 = r; /* upper and lower non-intersecting */
1965 r1.size.height -= ir.size.height;
1966 r2.origin.y += r1.size.height;
1967 r2.size.width -= ir.size.width;
1968 r2.size.height = ir.size.height;
1969 NSRectFill (r1);
1970 NSRectFill (r2);
1971 }
1972 }
1973#endif
1974
1975 ns_unfocus (f);
1976 return;
1977}
1978
1979
1980static void
1981ns_scroll_run (struct window *w, struct run *run)
1982/* --------------------------------------------------------------------------
1983 23: External (RIF): Insert or delete n lines at line vpos
1984 -------------------------------------------------------------------------- */
1985{
1986 struct frame *f = XFRAME (w->frame);
1987 int x, y, width, height, from_y, to_y, bottom_y;
1988
1989 NSTRACE (ns_scroll_run);
1990
1991 /* begin copy from other terms */
1992 /* Get frame-relative bounding box of the text display area of W,
1993 without mode lines. Include in this box the left and right
1994 fringe of W. */
1995 window_box (w, -1, &x, &y, &width, &height);
1996
1997 from_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->current_y);
1998 to_y = WINDOW_TO_FRAME_PIXEL_Y (w, run->desired_y);
1999 bottom_y = y + height;
2000
2001 if (to_y < from_y)
2002 {
2003 /* Scrolling up. Make sure we don't copy part of the mode
2004 line at the bottom. */
2005 if (from_y + run->height > bottom_y)
2006 height = bottom_y - from_y;
2007 else
2008 height = run->height;
2009 }
2010 else
2011 {
2012 /* Scolling down. Make sure we don't copy over the mode line.
2013 at the bottom. */
2014 if (to_y + run->height > bottom_y)
2015 height = bottom_y - to_y;
2016 else
2017 height = run->height;
2018 }
2019 /* end copy from other terms */
2020
2021 if (height == 0)
2022 return;
2023
2024 BLOCK_INPUT;
2025
2026 updated_window = w;
2027 x_clear_cursor (w);
2028
2029 {
2030 NSRect srcRect = NSMakeRect (x, from_y, width, height);
2031 NSRect dstRect = NSMakeRect (x, to_y, width, height);
2032 NSPoint dstOrigin = NSMakePoint (x, to_y);
2033
2034 ns_focus (f, &dstRect, 1);
2035 NSCopyBits (0, srcRect , dstOrigin);
2036 ns_unfocus (f);
2037 }
2038
2039 UNBLOCK_INPUT;
2040}
2041
2042
2043static void
2044ns_after_update_window_line (struct glyph_row *desired_row)
2045/* --------------------------------------------------------------------------
2046 23: External (RIF): preparatory to fringe update after text was updated
2047 -------------------------------------------------------------------------- */
2048{
2049 struct window *w = updated_window;
2050 struct frame *f;
2051 int width, height;
2052
2053 NSTRACE (ns_after_update_window_line);
2054
2055 /* begin copy from other terms */
2056 xassert (w);
2057
2058 if (!desired_row->mode_line_p && !w->pseudo_window_p)
2059 desired_row->redraw_fringe_bitmaps_p = 1;
2060
2061 /* When a window has disappeared, make sure that no rest of
2062 full-width rows stays visible in the internal border.
2063 Under NS this is drawn inside the fringes. */
2064 if (windows_or_buffers_changed
2065 && (f = XFRAME (w->frame),
2066 width = FRAME_INTERNAL_BORDER_WIDTH (f),
2067 width != 0)
2068 && (height = desired_row->visible_height,
2069 height > 0))
2070 {
2071 int y = WINDOW_TO_FRAME_PIXEL_Y (w, max (0, desired_row->y));
2072
2073 /* Internal border is drawn below the tool bar. */
2074 if (WINDOWP (f->tool_bar_window)
2075 && w == XWINDOW (f->tool_bar_window))
2076 y -= width;
2077 /* end copy from other terms */
2078
2079 BLOCK_INPUT;
2080 if (!desired_row->full_width_p)
2081 {
2082 int x1 = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w)
2083 + WINDOW_LEFT_FRINGE_WIDTH (w);
2084 int x2 = WINDOW_LEFT_SCROLL_BAR_AREA_WIDTH (w)
2085 + FRAME_PIXEL_WIDTH (f) - NS_SCROLL_BAR_WIDTH (f)
2086 - WINDOW_RIGHT_FRINGE_WIDTH (w)
2087 - FRAME_INTERNAL_BORDER_WIDTH (f);
2088 ns_clear_frame_area (f, x1, y, width, height);
2089 ns_clear_frame_area (f, x2, y, width, height);
2090 }
2091 UNBLOCK_INPUT;
2092 }
2093}
2094
2095
2096static void
2097ns_shift_glyphs_for_insert (struct frame *f,
2098 int x, int y, int width, int height,
2099 int shift_by)
2100/* --------------------------------------------------------------------------
2101 23: External (RIF): copy an area horizontally, don't worry about clearing src
2102 -------------------------------------------------------------------------- */
2103{
2104 NSRect srcRect = NSMakeRect (x, y, width, height);
2105 NSRect dstRect = NSMakeRect (x+shift_by, y, width, height);
2106 NSPoint dstOrigin = dstRect.origin;
2107
2108 NSTRACE (ns_shift_glyphs_for_insert);
2109
2110 ns_focus (f, &dstRect, 1);
2111 NSCopyBits (0, srcRect, dstOrigin);
2112 ns_unfocus (f);
2113}
2114
2115
2116
2117/* ==========================================================================
2118
2119 Character encoding and metrics
2120
2121 ========================================================================== */
2122
2123
2124static inline void
2125ns_compute_glyph_string_overhangs (struct glyph_string *s)
2126/* --------------------------------------------------------------------------
2127 23: External (RIF); compute left/right overhang of whole string and set in s
2128 -------------------------------------------------------------------------- */
2129{
2130 struct face *face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
2131 struct font *font = s->font; /*face->font; */
2132
2133 if (s->char2b)
2134 {
2135 struct font_metrics metrics;
2136 unsigned int codes[2];
2137 codes[0] = *(s->char2b);
2138 codes[1] = *(s->char2b + s->nchars - 1);
2139
2140 font->driver->text_extents (font, codes, 2, &metrics);
2141 s->left_overhang = -metrics.lbearing;
2142 s->right_overhang =
2143 metrics.rbearing > metrics.width ? metrics.rbearing - metrics.width : 0;
2144 }
2145 else
2146 {
2147 s->left_overhang = 0;
2148 s->right_overhang = ((struct nsfont_info *)font)->ital ?
2149 FONT_HEIGHT (font) * 0.2 : 0;
2150 }
2151}
2152
2153
2154
2155/* ==========================================================================
2156
2157 Fringe and cursor drawing
2158
2159 ========================================================================== */
2160
2161
2162extern int max_used_fringe_bitmap;
2163static void
2164ns_draw_fringe_bitmap (struct window *w, struct glyph_row *row,
2165 struct draw_fringe_bitmap_params *p)
2166/* --------------------------------------------------------------------------
2167 23: External (RIF); fringe-related
2168 -------------------------------------------------------------------------- */
2169{
2170 struct frame *f = XFRAME (WINDOW_FRAME (w));
2171 struct face *face = p->face;
2172 int rowY;
2173 static EmacsImage **bimgs = NULL;
2174 static int nBimgs = 0;
2175 /* NS-specific: move internal border inside fringe */
2176 int x = p->bx < 0 ? p->x : p->bx;
2177 int wd = p->bx < 0 ? p->wd : p->nx;
2178 BOOL fringeOnVeryLeft =
2179 x - WINDOW_LEFT_SCROLL_BAR_COLS (w) * WINDOW_FRAME_COLUMN_WIDTH (w)
2180 - FRAME_INTERNAL_BORDER_WIDTH (f) < 10;
2181 BOOL fringeOnVeryRight =
2182 FRAME_PIXEL_WIDTH (f) - x - wd - FRAME_INTERNAL_BORDER_WIDTH (f)
2183 - WINDOW_RIGHT_SCROLL_BAR_COLS (w) * WINDOW_FRAME_COLUMN_WIDTH (w) < 10;
2184 int xAdjust = FRAME_INTERNAL_BORDER_WIDTH (f) *
2185 (fringeOnVeryLeft ? -1 : (fringeOnVeryRight ? 1 : 0));
2186
2187 /* grow bimgs if needed */
2188 if (nBimgs < max_used_fringe_bitmap)
2189 {
2190 EmacsImage **newBimgs =
2191 xmalloc (max_used_fringe_bitmap * sizeof (EmacsImage *));
2192 bzero (newBimgs, max_used_fringe_bitmap * sizeof (EmacsImage *));
2193
2194 if (nBimgs)
2195 {
2196 bcopy (bimgs, newBimgs, nBimgs * sizeof (EmacsImage *));
2197 xfree (bimgs);
2198 }
2199
2200 bimgs = newBimgs;
2201 nBimgs = max_used_fringe_bitmap;
2202 }
2203
2204 /* Must clip because of partially visible lines. */
2205 rowY = WINDOW_TO_FRAME_PIXEL_Y (w, row->y);
2206 if (p->y < rowY)
2207 {
2208 /* Adjust position of "bottom aligned" bitmap on partially
2209 visible last row. */
2210 int oldY = row->y;
2211 int oldVH = row->visible_height;
2212 row->visible_height = p->h;
2213 row->y -= rowY - p->y;
2214 ns_clip_to_row (w, row, -1, NULL);
2215 row->y = oldY;
2216 row->visible_height = oldVH;
2217 }
2218 else
2219 ns_clip_to_row (w, row, -1, YES);
2220
2221 if (p->bx >= 0 && !p->overlay_p)
2222 {
2223 int yAdjust = rowY - FRAME_INTERNAL_BORDER_WIDTH (f) < 5 ?
2224 -FRAME_INTERNAL_BORDER_WIDTH (f) : 0;
2225 int yIncr = FRAME_PIXEL_HEIGHT (f) - (p->by+yAdjust + p->ny) < 5 ?
2226 FRAME_INTERNAL_BORDER_WIDTH (f) : 0;
2227 if (yAdjust)
2228 yIncr += FRAME_INTERNAL_BORDER_WIDTH (f);
2229 NSRect r = NSMakeRect (p->bx+xAdjust, p->by+yAdjust, p->nx, p->ny+yIncr);
2230 NSRectClip (r);
2231 [ns_lookup_indexed_color(face->background, f) set];
2232 NSRectFill (r);
2233 }
2234
2235 if (p->which)
2236 {
2237 NSRect r = NSMakeRect (p->x+xAdjust, p->y, p->wd, p->h);
2238 NSPoint pt = r.origin;
2239 EmacsImage *img = bimgs[p->which - 1];
2240
2241 if (!img)
2242 {
2243 unsigned short *bits = p->bits + p->dh;
2244 int len = 8 * p->h/8;
2245 int i;
2246 unsigned char *cbits = xmalloc (len);
2247
2248 for (i =0; i<len; i++)
2249 cbits[i] = ~(bits[i] & 0xff);
2250 img = [[EmacsImage alloc] initFromXBM: cbits width: 8 height: p->h
2251 flip: NO];
2252 bimgs[p->which - 1] = img;
2253 xfree (cbits);
2254 }
2255
2256 NSRectClip (r);
2257 /* Since we composite the bitmap instead of just blitting it, we need
2258 to erase the whole background. */
2259 [ns_lookup_indexed_color(face->background, f) set];
2260 NSRectFill (r);
2261 pt.y += p->h;
2262 [img setXBMColor: ns_lookup_indexed_color(face->foreground, f)];
2263 [img compositeToPoint: pt operation: NSCompositeSourceOver];
2264 }
2265 ns_unfocus (f);
2266}
2267
2268
2269void
2270ns_draw_window_cursor (struct window *w, struct glyph_row *glyph_row,
2271 int x, int y, int cursor_type, int cursor_width,
2272 int on_p, int active_p)
2273/* --------------------------------------------------------------------------
2274 External call (RIF): draw cursor
2275 -------------------------------------------------------------------------- */
2276{
2277 NSRect r, s;
2278 int fx, fy, h;
2279 struct frame *f = WINDOW_XFRAME (w);
2280 struct glyph *phys_cursor_glyph;
2281 int overspill;
2282 unsigned char drawGlyph = 0, cursorType, oldCursorType;
2283
2284 NSTRACE (dumpcursor);
2285
2286 if (!on_p)
2287 return;
2288
2289 w->phys_cursor_type = cursor_type;
2290 w->phys_cursor_on_p = 1;
2291
2292 if (cursor_type == NO_CURSOR)
2293 {
2294 w->phys_cursor_width = 0;
2295 return;
2296 }
2297
2298 if ((phys_cursor_glyph = get_phys_cursor_glyph (w)) == NULL)
2299 {
2300 if (glyph_row->exact_window_width_line_p
2301 && w->phys_cursor.hpos >= glyph_row->used[TEXT_AREA])
2302 {
2303 glyph_row->cursor_in_fringe_p = 1;
2304 draw_fringe_bitmap (w, glyph_row, 0);
2305 }
2306 return;
2307 }
2308
2309 get_phys_cursor_geometry (w, glyph_row, phys_cursor_glyph, &fx, &fy, &h);
2310
2311 r.origin.x = fx, r.origin.y = fy;
2312 r.size.height = h;
2313 r.size.width = w->phys_cursor_width;
2314
2315 /* PENDING: if we overwrite the internal border area, it does not get erased;
2316 fix by truncating cursor, but better would be to erase properly */
2317 overspill = r.origin.x + r.size.width -
2318 WINDOW_TEXT_TO_FRAME_PIXEL_X (w, WINDOW_BOX_RIGHT_EDGE_X (w)
2319 - WINDOW_TOTAL_FRINGE_WIDTH (w) - FRAME_INTERNAL_BORDER_WIDTH (f));
2320 if (overspill > 0)
2321 r.size.width -= overspill;
2322
2323 /* PENDING: 23: use emacs stored f->cursor_type instead of ns-specific */
2324 oldCursorType = FRAME_CURSOR (f);
2325 cursorType = FRAME_CURSOR (f) = FRAME_NEW_CURSOR (f);
2326 f->output_data.ns->current_cursor_color =
2327 f->output_data.ns->desired_cursor_color;
2328
2329 /* PENDING: only needed in rare cases with last-resort font in HELLO..
2330 should we do this more efficiently? */
2331 ns_clip_to_row (w, glyph_row, -1, NULL);
2332/* ns_focus (f, &r, 1); */
2333
2334 if (FRAME_LAST_INACTIVE (f))
2335 {
2336 /* previously hollow box; clear entire area */
2337 [FRAME_BACKGROUND_COLOR (f) set];
2338 NSRectFill (r);
2339 drawGlyph = 1;
2340 FRAME_LAST_INACTIVE (f) = NO;
2341 }
2342
2343 /* prepare to draw */
2344 if (cursorType == no_highlight || cursor_type == NO_CURSOR)
2345 {
2346 /* clearing for blink: erase the cursor itself */
2347 [FRAME_BACKGROUND_COLOR (f) set];
2348 cursorType = oldCursorType; /* just clear what we had before */
2349 }
2350 else
2351 [FRAME_CURSOR_COLOR (f) set];
2352
2353 if (!active_p)
2354 {
2355 /* inactive window: ignore what we just set and use a hollow box */
2356 cursorType = hollow_box;
2357 [FRAME_CURSOR_COLOR (f) set];
2358 }
2359
2360 switch (cursorType)
2361 {
2362 case no_highlight:
2363 break;
2364 case filled_box:
2365 NSRectFill (r);
2366 drawGlyph = 1;
2367 break;
2368 case hollow_box:
2369 NSRectFill (r);
2370 [FRAME_BACKGROUND_COLOR (f) set];
2371 NSRectFill (NSInsetRect (r, 1, 1));
2372 [FRAME_CURSOR_COLOR (f) set];
2373 drawGlyph = 1;
2374 break;
2375 case underscore:
2376 s = r;
2377 s.origin.y += lrint (0.75 * s.size.height);
2378 s.size.height = lrint (s.size.height * 0.25);
2379 NSRectFill (s);
2380 break;
2381 case bar:
2382 s = r;
2383 s.size.width = 1;
2384 NSRectFill (s);
2385 break;
2386 }
2387 ns_unfocus (f);
2388
2389 /* if needed, draw the character under the cursor */
2390 if (drawGlyph)
2391 draw_phys_cursor_glyph (w, glyph_row, DRAW_CURSOR);
2392}
2393
2394
2395static void
2396ns_draw_vertical_window_border (struct window *w, int x, int y0, int y1)
2397/* --------------------------------------------------------------------------
2398 External (RIF): Draw a vertical line.
2399 -------------------------------------------------------------------------- */
2400{
2401 struct frame *f = XFRAME (WINDOW_FRAME (w));
2402 struct face *face;
2403 NSRect r = NSMakeRect (x, y0, 2, y1-y0);
2404
2405 face = FACE_FROM_ID (f, VERTICAL_BORDER_FACE_ID);
2406 if (face)
2407 [ns_lookup_indexed_color(face->foreground, f) set];
2408
2409 ns_focus (f, &r, 1);
2410 NSDrawGroove (r, r);
2411 ns_unfocus (f);
2412}
2413
2414
2415void
2416show_hourglass (struct atimer *timer)
2417{
2418 if (hourglass_shown_p)
2419 return;
2420
2421 BLOCK_INPUT;
2422
2423 /*PENDING: add NSProgressIndicator to selected frame (see macfns.c) */
2424
2425 hourglass_shown_p = 1;
2426 UNBLOCK_INPUT;
2427}
2428
2429
2430void
2431hide_hourglass ()
2432{
2433 if (!hourglass_shown_p)
2434 return;
2435
2436 /*PENDING: remove NSProgressIndicator from all frames */
2437
2438 hourglass_shown_p = 0;
2439 UNBLOCK_INPUT;
2440}
2441
2442
2443
2444/* ==========================================================================
2445
2446 Glyph drawing operations
2447
2448 ========================================================================== */
2449
2450
2451static inline NSRect
2452/* --------------------------------------------------------------------------
2453 Under NS we draw internal borders inside fringes, and want full-width
2454 rendering to go all the way to edge. This function makes that correction.
2455 -------------------------------------------------------------------------- */
2456ns_fix_rect_ibw (NSRect r, int fibw, int frame_pixel_width)
2457{
2458 if (r.origin.y <= fibw+1)
2459 {
2460 r.size.height += r.origin.y;
2461 r.origin.y = 0;
2462 }
2463 if (r.origin.x <= fibw+1)
2464 {
2465 r.size.width += r.origin.x;
2466 r.origin.x = 0;
2467 }
2468 if (frame_pixel_width - (r.origin.x+r.size.width) <= fibw+1)
2469 r.size.width += fibw;
2470
2471 return r;
2472}
2473
2474
2475static int
2476ns_get_glyph_string_clip_rect (struct glyph_string *s, NativeRectangle *nr)
2477/* --------------------------------------------------------------------------
2478 Wrapper utility to account for internal border width on full-width lines,
2479 and allow top full-width rows to hit the frame top. nr should be pointer
2480 to two successive NSRects. Number of rects actually used is returned.
2481 -------------------------------------------------------------------------- */
2482{
2483 int n = get_glyph_string_clip_rects (s, nr, 2);
2484 if (s->row->full_width_p)
2485 {
2486 *nr = ns_fix_rect_ibw (*nr, FRAME_INTERNAL_BORDER_WIDTH (s->f),
2487 FRAME_PIXEL_WIDTH (s->f));
2488 if (n == 2)
2489 *nr = ns_fix_rect_ibw (*(nr+1), FRAME_INTERNAL_BORDER_WIDTH (s->f),
2490 FRAME_PIXEL_WIDTH (s->f));
2491 }
2492 return n;
2493}
2494
2495
2496static void
2497ns_draw_box (NSRect r, float thickness, NSColor *col, char left_p, char right_p)
2498/* --------------------------------------------------------------------------
2499 Draw an unfilled rect inside r, optionally leaving left and/or right open.
2500 Note we can't just use an NSDrawRect command, because of the possibility
2501 of some sides not being drawn, and because the rect will be filled.
2502 -------------------------------------------------------------------------- */
2503{
2504 NSRect s = r;
2505 [col set];
2506
2507 /* top, bottom */
2508 s.size.height = thickness;
2509 NSRectFill (s);
2510 s.origin.y += r.size.height - thickness;
2511 NSRectFill (s);
2512
2513 s.size.height = r.size.height;
2514 s.origin.y = r.origin.y;
2515
2516 /* left, right (optional) */
2517 s.size.width = thickness;
2518 if (left_p)
2519 NSRectFill (s);
2520 if (right_p)
2521 {
2522 s.origin.x += r.size.width - thickness;
2523 NSRectFill (s);
2524 }
2525}
2526
2527
2528static void
2529ns_draw_relief (NSRect r, int thickness, char raised_p,
2530 char top_p, char bottom_p, char left_p, char right_p,
2531 struct glyph_string *s)
2532/* --------------------------------------------------------------------------
2533 Draw a relief rect inside r, optionally leaving some sides open.
2534 Note we can't just use an NSDrawBezel command, because of the possibility
2535 of some sides not being drawn, and because the rect will be filled.
2536 -------------------------------------------------------------------------- */
2537{
2538 static NSColor *baseCol = nil, *lightCol = nil, *darkCol = nil;
2539 NSColor *newBaseCol = nil;
2540 NSRect sr = r;
2541
2542 NSTRACE (ns_draw_relief);
2543
2544 /* set up colors */
2545
2546 if (s->face->use_box_color_for_shadows_p)
2547 {
2548 newBaseCol = ns_lookup_indexed_color (s->face->box_color, s->f);
2549 }
2550/* else if (s->first_glyph->type == IMAGE_GLYPH
2551 && s->img->pixmap
2552 && !IMAGE_BACKGROUND_TRANSPARENT (s->img, s->f, 0))
2553 {
2554 newBaseCol = IMAGE_BACKGROUND (s->img, s->f, 0);
2555 } */
2556 else
2557 {
2558 newBaseCol = ns_lookup_indexed_color (s->face->background, s->f);
2559 }
2560
2561 if (newBaseCol == nil)
2562 newBaseCol = [NSColor grayColor];
2563
2564 if (newBaseCol != baseCol) /* PENDING: better check */
2565 {
2566 [baseCol release];
2567 baseCol = [newBaseCol retain];
2568 [lightCol release];
2569 lightCol = [[baseCol highlightWithLevel: 0.2] retain];
2570 [darkCol release];
2571 darkCol = [[baseCol shadowWithLevel: 0.3] retain];
2572 }
2573
2574 [(raised_p ? lightCol : darkCol) set];
2575
2576 /* TODO: mitering. Using NSBezierPath doesn't work because of color switch. */
2577
2578 /* top */
2579 sr.size.height = thickness;
2580 if (top_p) NSRectFill (sr);
2581
2582 /* left */
2583 sr.size.height = r.size.height;
2584 sr.size.width = thickness;
2585 if (left_p) NSRectFill (sr);
2586
2587 [(raised_p ? darkCol : lightCol) set];
2588
2589 /* bottom */
2590 sr.size.width = r.size.width;
2591 sr.size.height = thickness;
2592 sr.origin.y += r.size.height - thickness;
2593 if (bottom_p) NSRectFill (sr);
2594
2595 /* right */
2596 sr.size.height = r.size.height;
2597 sr.origin.y = r.origin.y;
2598 sr.size.width = thickness;
2599 sr.origin.x += r.size.width - thickness;
2600 if (right_p) NSRectFill (sr);
2601}
2602
2603
2604static void
2605ns_dumpglyphs_box_or_relief (struct glyph_string *s)
2606/* --------------------------------------------------------------------------
2607 Function modeled after x_draw_glyph_string_box ().
2608 Sets up parameters for drawing.
2609 -------------------------------------------------------------------------- */
2610{
2611 int right_x, last_x;
2612 char left_p, right_p;
2613 struct glyph *last_glyph;
2614 NSRect r;
2615 int thickness;
2616 struct face *face;
2617
2618 if (s->hl == DRAW_MOUSE_FACE)
2619 {
2620 face = FACE_FROM_ID
2621 (s->f, FRAME_NS_DISPLAY_INFO (s->f)->mouse_face_face_id);
2622 if (!face)
2623 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2624 }
2625 else
2626 face = s->face;
2627
2628 thickness = face->box_line_width;
2629
2630 NSTRACE (ns_dumpglyphs_box_or_relief);
2631
2632 last_x = ((s->row->full_width_p && !s->w->pseudo_window_p)
2633 ? WINDOW_RIGHT_EDGE_X (s->w)
2634 : window_box_right (s->w, s->area));
2635 last_glyph = (s->cmp || s->img
2636 ? s->first_glyph : s->first_glyph + s->nchars-1);
2637
2638 right_x = ((s->row->full_width_p && s->extends_to_end_of_line_p
2639 ? last_x - 1 : min (last_x, s->x + s->background_width) - 1));
2640
2641 left_p = (s->first_glyph->left_box_line_p
2642 || (s->hl == DRAW_MOUSE_FACE
2643 && (s->prev == NULL || s->prev->hl != s->hl)));
2644 right_p = (last_glyph->right_box_line_p
2645 || (s->hl == DRAW_MOUSE_FACE
2646 && (s->next == NULL || s->next->hl != s->hl)));
2647
2648 r = NSMakeRect (s->x, s->y, right_x - s->x + 1, s->height);
2649
2650 /* expand full-width row over internal borders */
2651 if (s->row->full_width_p)
2652 r = ns_fix_rect_ibw (r, FRAME_INTERNAL_BORDER_WIDTH (s->f),
2653 FRAME_PIXEL_WIDTH (s->f));
2654
2655 if (s->face->box == FACE_SIMPLE_BOX)
2656 {
2657 xassert (s->face->box_color != nil);
2658 ns_draw_box (r, abs (thickness),
2659 ns_lookup_indexed_color (face->box_color, s->f),
2660 left_p, right_p);
2661 }
2662 else
2663 {
2664 ns_draw_relief (r, abs (thickness), s->face->box == FACE_RAISED_BOX,
2665 1, 1, left_p, right_p, s);
2666 }
2667}
2668
2669
2670static void
2671ns_maybe_dumpglyphs_background (struct glyph_string *s, char force_p)
2672/* --------------------------------------------------------------------------
2673 Modeled after x_draw_glyph_string_background, which draws BG in
2674 certain cases. Others are left to the text rendering routine.
2675 -------------------------------------------------------------------------- */
2676{
2677 NSTRACE (ns_maybe_dumpglyphs_background);
2678
2679 if (!s->background_filled_p/* || s->hl == DRAW_MOUSE_FACE*/)
2680 {
2681 int box_line_width = max (s->face->box_line_width, 0);
2682 if (FONT_HEIGHT (s->font) < s->height - 2 * box_line_width
2683 || s->font_not_found_p || s->extends_to_end_of_line_p || force_p)
2684 {
2685 struct face *face;
2686 if (s->hl == DRAW_MOUSE_FACE)
2687 {
2688 face = FACE_FROM_ID
2689 (s->f, FRAME_NS_DISPLAY_INFO (s->f)->mouse_face_face_id);
2690 if (!face)
2691 face = FACE_FROM_ID (s->f, MOUSE_FACE_ID);
2692 }
2693 else
2694 face = FACE_FROM_ID (s->f, s->first_glyph->face_id);
2695 if (!face->stipple)
2696 [(NS_FACE_BACKGROUND (face) != nil
2697 ? ns_lookup_indexed_color (NS_FACE_BACKGROUND (face), s->f)
2698 : FRAME_BACKGROUND_COLOR (s->f)) set];
2699 else
2700 {
2701 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (s->f);
2702 [[dpyinfo->bitmaps[face->stipple-1].img stippleMask] set];
2703 }
2704
2705 if (s->hl != DRAW_CURSOR)
2706 {
2707 NSRect r = NSMakeRect (s->x, s->y + box_line_width,
2708 s->background_width,
2709 s->height-2*box_line_width);
2710
2711 /* expand full-width row over internal borders */
2712 if (s->row->full_width_p)
2713 {
2714 int fibw = FRAME_INTERNAL_BORDER_WIDTH (s->f);
2715 if (r.origin.y <= fibw+1 + box_line_width)
2716 {
2717 r.size.height += r.origin.y;
2718 r.origin.y = 0;
2719 }
2720 if (r.origin.x <= fibw+1)
2721 {
2722 r.size.width += 2*r.origin.x;
2723 r.origin.x = 0;
2724 }
2725 if (FRAME_PIXEL_WIDTH (s->f) - (r.origin.x + r.size.width)
2726 <= fibw+1)
2727 r.size.width += fibw;
2728 }
2729
2730 NSRectFill (r);
2731 }
2732
2733 s->background_filled_p = 1;
2734 }
2735 }
2736}
2737
2738
2739static void
2740ns_dumpglyphs_image (struct glyph_string *s, NSRect r)
2741/* --------------------------------------------------------------------------
2742 Renders an image and associated borders.
2743 -------------------------------------------------------------------------- */
2744{
2745 EmacsImage *img = s->img->pixmap;
2746 int box_line_vwidth = max (s->face->box_line_width, 0);
2747 int x = s->x, y = s->ybase - image_ascent (s->img, s->face, &s->slice);
2748 int bg_x, bg_y, bg_height;
2749 int th;
2750 char raised_p;
2751 NSRect br;
2752
2753 NSTRACE (ns_dumpglyphs_image);
2754
2755 if (s->face->box != FACE_NO_BOX
2756 && s->first_glyph->left_box_line_p && s->slice.x == 0)
2757 x += abs (s->face->box_line_width);
2758
2759 bg_x = x;
2760 bg_y = s->slice.y == 0 ? s->y : s->y + box_line_vwidth;
2761 bg_height = s->height;
2762 /* other terms have this, but was causing problems w/tabbar mode */
2763 /* - 2 * box_line_vwidth; */
2764
2765 if (s->slice.x == 0) x += s->img->hmargin;
2766 if (s->slice.y == 0) y += s->img->vmargin;
2767
2768 /* Draw BG: if we need larger area than image itself cleared, do that,
2769 otherwise, since we composite the image under NS (instead of mucking
2770 with its background color), we must clear just the image area. */
2771 [ns_lookup_indexed_color (NS_FACE_BACKGROUND
2772 (FACE_FROM_ID (s->f, s->first_glyph->face_id)), s->f) set];
2773
2774 if (bg_height > s->slice.height || s->img->hmargin || s->img->vmargin
2775 || s->img->mask || s->img->pixmap == 0 || s->width != s->background_width)
2776 {
2777 br = NSMakeRect (bg_x, bg_y, s->background_width, bg_height);
2778 s->background_filled_p = 1;
2779 }
2780 else
2781 {
2782 br = NSMakeRect (x, y, s->slice.width, s->slice.height);
2783 }
2784
2785 /* expand full-width row over internal borders */
2786 if (s->row->full_width_p)
2787 {
2788 int fibw = FRAME_INTERNAL_BORDER_WIDTH (s->f);
2789 if (br.origin.y <= fibw+1 + box_line_vwidth)
2790 {
2791 br.size.height += br.origin.y;
2792 br.origin.y = 0;
2793 }
2794 if (br.origin.x <= fibw+1 + box_line_vwidth)
2795 {
2796 br.size.width += br.origin.x;
2797 br.origin.x = 0;
2798 }
2799 if (FRAME_PIXEL_WIDTH (s->f) - (br.origin.x + br.size.width) <= fibw+1)
2800 br.size.width += fibw;
2801 }
2802
2803 NSRectFill (br);
2804
2805 /* Draw the image.. do we need to draw placeholder if img ==nil? */
2806 if (img != nil)
2807 [img compositeToPoint: NSMakePoint (x, y + s->slice.height)
2808 operation: NSCompositeSourceOver];
2809
2810 /* Draw relief, if requested */
2811 if (s->img->relief || s->hl ==DRAW_IMAGE_RAISED || s->hl ==DRAW_IMAGE_SUNKEN)
2812 {
2813 if (s->hl == DRAW_IMAGE_SUNKEN || s->hl == DRAW_IMAGE_RAISED)
2814 {
2815 th = tool_bar_button_relief >= 0 ?
2816 tool_bar_button_relief : DEFAULT_TOOL_BAR_BUTTON_RELIEF;
2817 raised_p = (s->hl == DRAW_IMAGE_RAISED);
2818 }
2819 else
2820 {
2821 th = abs (s->img->relief);
2822 raised_p = (s->img->relief > 0);
2823 }
2824
2825 r.origin.x = x - th;
2826 r.origin.y = y - th;
2827 r.size.width = s->slice.width + 2*th-1;
2828 r.size.height = s->slice.height + 2*th-1;
2829 ns_draw_relief (r, th, raised_p,
2830 s->slice.y == 0,
2831 s->slice.y + s->slice.height == s->img->height,
2832 s->slice.x == 0,
2833 s->slice.x + s->slice.width == s->img->width, s);
2834 }
2835}
2836
2837
2838static void
2839ns_draw_glyph_string (struct glyph_string *s)
2840/* --------------------------------------------------------------------------
2841 External (RIF): Main draw-text call.
2842 -------------------------------------------------------------------------- */
2843{
2844 /*PENDING (optimize): focus for box and contents draw */
2845 NSRect r[2];
2846 int n;
2847 char box_drawn_p = 0;
2848
2849 NSTRACE (ns_draw_glyph_string);
2850
2851 if (s->next && s->right_overhang && !s->for_overlaps && s->hl != DRAW_CURSOR)
2852 {
2853 xassert (s->next->img == NULL);
2854 n = ns_get_glyph_string_clip_rect (s->next, r);
2855 ns_focus (s->f, r, n);
2856 ns_maybe_dumpglyphs_background (s->next, 1);
2857 ns_unfocus (s->f);
2858 }
2859
2860 if (!s->for_overlaps && s->face->box != FACE_NO_BOX
2861 && (s->first_glyph->type == CHAR_GLYPH
2862 || s->first_glyph->type == COMPOSITE_GLYPH))
2863 {
2864 n = ns_get_glyph_string_clip_rect (s, r);
2865 ns_focus (s->f, r, n);
2866 ns_maybe_dumpglyphs_background (s, 1);
2867 ns_dumpglyphs_box_or_relief (s);
2868 ns_unfocus (s->f);
2869 box_drawn_p = 1;
2870 }
2871
2872 switch (s->first_glyph->type)
2873 {
2874
2875 case IMAGE_GLYPH:
2876 n = ns_get_glyph_string_clip_rect (s, r);
2877 ns_focus (s->f, r, n);
2878 ns_dumpglyphs_image (s, r[0]);
2879 ns_unfocus (s->f);
2880 break;
2881
2882 case STRETCH_GLYPH:
2883 if (!s->background_filled_p)
2884 {
2885 *r = NSMakeRect (s->x, s->y, s->background_width, s->height);
2886
2887 if (!s->row->full_width_p)
2888 {
2889 /* truncate to avoid overwriting fringe and/or scrollbar */
2890 int overrun = max (0, (s->x + s->background_width)
2891 - (WINDOW_BOX_RIGHT_EDGE_X (s->w)
2892 - WINDOW_RIGHT_FRINGE_WIDTH (s->w)));
2893 r[0].size.width -= overrun;
2894
2895 /* PENDING: Try to work between problem where a stretch glyph on
2896 a partially-visible bottom row will clear part of the
2897 modeline, and another where list-buffers headers and similar
2898 rows erroneously have visible_height set to 0. Not sure
2899 where this is coming from as other terms seem not to show. */
2900 r[0].size.height = min (s->height, s->row->visible_height);
2901 }
2902
2903 /* expand full-width rows over internal borders */
2904 else
2905 {
2906 r[0] = ns_fix_rect_ibw (r[0], FRAME_INTERNAL_BORDER_WIDTH (s->f),
2907 FRAME_PIXEL_WIDTH (s->f));
2908 }
2909
2910 /* NOTE: under NS this is NOT used to draw cursors, but we must avoid
2911 overwriting cursor (usually when cursor on a tab) */
2912 if (s->hl == DRAW_CURSOR)
2913 {
2914 r[0].origin.x += s->width;
2915 r[0].size.width -= s->width;
2916 }
2917
2918 ns_focus (s->f, r, 1);
2919 [ns_lookup_indexed_color (NS_FACE_BACKGROUND
2920 (FACE_FROM_ID (s->f, s->first_glyph->face_id)), s->f) set];
2921 NSRectFill (r[0]);
2922 ns_unfocus (s->f);
2923 s->background_filled_p = 1;
2924 }
2925 break;
2926
2927 case CHAR_GLYPH:
2928 case COMPOSITE_GLYPH:
2929 n = ns_get_glyph_string_clip_rect (s, r);
2930 ns_focus (s->f, r, n);
2931
2932 if (s->for_overlaps || s->gidx > 0)
2933 s->background_filled_p = 1;
2934 else /* 1 */
2935 ns_maybe_dumpglyphs_background
2936 (s, s->first_glyph->type == COMPOSITE_GLYPH);
2937
2938 ns_tmp_flags = s->hl == DRAW_CURSOR ? NS_DUMPGLYPH_CURSOR :
2939 (s->hl == DRAW_MOUSE_FACE ? NS_DUMPGLYPH_MOUSEFACE :
2940 (s->for_overlaps ? NS_DUMPGLYPH_FOREGROUND :
2941 NS_DUMPGLYPH_NORMAL));
2942 ns_tmp_font = (struct nsfont_info *)s->face->font;
2943 if (ns_tmp_font == ~0 || ns_tmp_font == NULL)
2944 ns_tmp_font = FRAME_FONT (s->f);
2945
2946 ns_tmp_font->font.driver->draw
2947 (s, 0, s->nchars, s->x, s->y,
2948 (ns_tmp_flags == NS_DUMPGLYPH_NORMAL && !s->background_filled_p)
2949 || ns_tmp_flags == NS_DUMPGLYPH_MOUSEFACE);
2950
2951 ns_unfocus (s->f);
2952 break;
2953
2954 default:
2955 abort ();
2956 }
2957
2958 /* Draw box if not done already. */
2959 if (!s->for_overlaps && !box_drawn_p && s->face->box != FACE_NO_BOX)
2960 {
2961 n = ns_get_glyph_string_clip_rect (s, r);
2962 ns_focus (s->f, r, n);
2963 ns_dumpglyphs_box_or_relief (s);
2964 ns_unfocus (s->f);
2965 }
2966
2967}
2968
2969
2970
2971/* ==========================================================================
2972
2973 Event loop
2974
2975 ========================================================================== */
2976
2977
2978static void
2979ns_send_appdefined (int value)
2980/* --------------------------------------------------------------------------
2981 Internal: post an appdefined event which EmacsApp-sendEvent will
2982 recognize and take as a command to halt the event loop.
2983 -------------------------------------------------------------------------- */
2984{
2985 /*NSTRACE (ns_send_appdefined); */
2986
2987 /* Only post this event if we haven't already posted one. This will end
2988 the [NXApp run] main loop after having processed all events queued at
2989 this moment. */
2990 if (send_appdefined)
2991 {
2992 NSEvent *nxev;
2993
2994 /* We only need one NX_APPDEFINED event to stop NXApp from running. */
2995 send_appdefined = NO;
2996
2997 /* Don't need wakeup timer any more */
2998 if (timed_entry)
2999 {
3000 [timed_entry invalidate];
3001 [timed_entry release];
3002 timed_entry = nil;
3003 }
3004
3005 /* Ditto for file descriptor poller */
3006 if (fd_entry)
3007 {
3008 [fd_entry invalidate];
3009 [fd_entry release];
3010 fd_entry = nil;
3011 }
3012
3013 nxev = [NSEvent otherEventWithType: NSApplicationDefined
3014 location: NSMakePoint (0, 0)
3015 modifierFlags: 0
3016 timestamp: 0
3017 windowNumber: [[NSApp mainWindow] windowNumber]
3018 context: [NSApp context]
3019 subtype: 0
3020 data1: value
3021 data2: 0];
3022
3023 /* Post an application defined event on the event queue. When this is
3024 received the [NXApp run] will return, thus having processed all
3025 events which are currently queued. */
3026 [NSApp postEvent: nxev atStart: NO];
3027 }
3028}
3029
3030
3031static int
3032ns_read_socket (struct terminal *terminal, int expected,
3033 struct input_event *hold_quit)
3034/* --------------------------------------------------------------------------
3035 External (hook): Post an event to ourself and keep reading events until
3036 we read it back again. In effect process all events which were waiting.
3037 23: Now we have to manage the event buffer ourselves.
3038 -------------------------------------------------------------------------- */
3039{
3040 struct input_event ev;
3041 int nevents;
3042 static NSDate *lastCheck = nil;
3043/* NSTRACE (ns_read_socket); */
3044
3045 if (interrupt_input_blocked)
3046 {
3047 interrupt_input_pending = 1;
3048 return -1;
3049 }
3050
3051 interrupt_input_pending = 0;
3052 BLOCK_INPUT;
3053
3054#ifdef COCOA_EXPERIMENTAL_CTRL_G
3055 /* causes Feval to abort; unclear on why this isn't in calling code */
3056 ++handling_signal;
3057#endif
3058
3059 n_emacs_events_pending = 0;
3060 EVENT_INIT (ev);
3061 emacs_event = &ev;
3062 q_event_ptr = hold_quit;
3063
3064 /* we manage autorelease pools by allocate/reallocate each time around
3065 the loop; strict nesting is occasionally violated but seems not to
3066 matter.. earlier methods using full nesting caused major memory leaks */
3067 [outerpool release];
3068 outerpool = [[NSAutoreleasePool alloc] init];
3069
3070 /* If have pending open-file requests, attend to the next one of those. */
3071 if (ns_pending_files && [ns_pending_files count] != 0
3072 && [NSApp openFile: [ns_pending_files objectAtIndex: 0]])
3073 {
3074 [ns_pending_files removeObjectAtIndex: 0];
3075 }
3076 /* Deal with pending service requests. */
3077 else if (ns_pending_service_names && [ns_pending_service_names count] != 0
3078 && [NSApp fulfillService: [ns_pending_service_names objectAtIndex: 0]
3079 withArg: [ns_pending_service_args objectAtIndex: 0]])
3080 {
3081 [ns_pending_service_names removeObjectAtIndex: 0];
3082 [ns_pending_service_args removeObjectAtIndex: 0];
3083 }
3084 else
3085 {
3086 /* Run and wait for events. We must always send one NX_APPDEFINED event
3087 to ourself, otherwise [NXApp run] will never exit. */
3088 send_appdefined = YES;
3089
3090 /*PENDING: from termhooks.h: */
3091 /* XXX Please note that a non-zero value of EXPECTED only means that
3092 there is available input on at least one of the currently opened
3093 terminal devices -- but not necessarily on this device.
3094 Therefore, in most cases EXPECTED should be simply ignored. */
3095 /* However, if in ns_select, this is called from gobble_input, which
3096 appears to set it correctly for our purposes, and always assuming
3097 !expected causes 100% CPU usage. */
3098 if (!inNsSelect || !expected)
3099 {
3100 /* Post an application defined event on the event queue. When this is
3101 received the [NXApp run] will return, thus having processed all
3102 events which are currently queued, if any. */
3103 ns_send_appdefined (-1);
3104 }
3105
3106 [NSApp run];
3107 }
3108
3109 nevents = n_emacs_events_pending;
3110 n_emacs_events_pending = 0;
3111 emacs_event = q_event_ptr = NULL;
3112
3113#ifdef COCOA_EXPERIMENTAL_CTRL_G
3114 --handling_signal;
3115#endif
3116 UNBLOCK_INPUT;
3117 return nevents;
3118}
3119
3120
3121int
3122ns_select (int nfds, fd_set *readfds, fd_set *writefds,
3123 fd_set *exceptfds, struct timeval *timeout)
3124/* --------------------------------------------------------------------------
3125 Replacement for select, checking for events
3126 -------------------------------------------------------------------------- */
3127{
3128 int result;
3129 double time;
3130 NSEvent *ev;
3131/* NSTRACE (ns_select); */
3132
3133 if (NSApp == nil /* || ([NSApp isActive] == NO &&
3134 [NSApp nextEventMatchingMask:NSAnyEventMask untilDate:nil
3135 inMode:NSDefaultRunLoopMode dequeue:NO] == nil) */)
3136 return select (nfds, readfds, writefds, exceptfds, timeout);
3137
3138 /* Save file descriptor set, which gets overwritten in calls to select ()
3139 Note, this is called from process.c, and only readfds is ever set */
3140 if (readfds)
3141 {
3142 memcpy (&select_readfds, readfds, sizeof (fd_set));
3143 select_nfds = nfds;
3144 }
3145 else
3146 select_nfds = 0;
3147
3148 /* Try an initial select for pending data on input files */
3149 select_timeout.tv_sec = select_timeout.tv_usec = 0;
3150 result = select (nfds, readfds, writefds, exceptfds, &select_timeout);
3151 if (result)
3152 return result;
3153
3154 /* if (!timeout || timed_entry || fd_entry)
3155 fprintf (stderr, "assertion failed: timeout null or timed_entry/fd_entry non-null in ns_select\n"); */
3156
3157 /* set a timeout and run the main AppKit event loop while continuing
3158 to monitor the files */
3159 time = ((double) timeout->tv_sec) + ((double) timeout->tv_usec)/1000000.0;
3160 timed_entry = [[NSTimer scheduledTimerWithTimeInterval: time
3161 target: NSApp
3162 selector: @selector (timeout_handler:)
3163 userInfo: 0
3164 repeats: YES] /* for safe removal */
3165 retain];
3166
3167 /* set a periodic task to try the select () again */
3168 fd_entry = [[NSTimer scheduledTimerWithTimeInterval: 0.1
3169 target: NSApp
3170 selector: @selector (fd_handler:)
3171 userInfo: 0
3172 repeats: YES]
3173 retain];
3174
3175 if (!NILP (ns_cursor_blink_mode) && !cursor_blink_entry)
3176 {
3177 if (!NUMBERP (ns_cursor_blink_rate))
3178 ns_cursor_blink_rate = make_float (0.5);
3179 cursor_blink_entry = [[NSTimer
3180 scheduledTimerWithTimeInterval: XFLOATINT (ns_cursor_blink_rate)
3181 target: NSApp
3182 selector: @selector (cursor_blink_handler:)
3183 userInfo: 0
3184 repeats: YES]
3185 retain];
3186 }
3187 else if (NILP (ns_cursor_blink_mode) && cursor_blink_entry)
3188 {
3189 if (NUMBERP (ns_cursor_blink_rate))
3190 ns_cursor_blink_rate = Qnil;
3191 struct ns_display_info *dpyinfo = ns_display_list; /* HACK */
3192 [cursor_blink_entry invalidate];
3193 [cursor_blink_entry release];
3194 cursor_blink_entry = 0;
3195 if (dpyinfo->ns_highlight_frame)
3196 {
3197 Lisp_Object tem =
3198 get_frame_param (dpyinfo->ns_highlight_frame, Qcursor_type);
3199 dpyinfo->ns_highlight_frame->output_data.ns->desired_cursor =
3200 ns_lisp_to_cursor_type (tem);
3201 }
3202 }
3203
3204 /* Let Application dispatch events until it receives an event of the type
3205 NX_APPDEFINED, which should only be sent by timeout_handler. */
3206 inNsSelect = 1;
3207 gobble_input (timeout ? 1 : 0);
3208 ev = last_appdefined_event;
3209 inNsSelect = 0;
3210
3211 if (ev)
3212 {
3213 int t;
3214 if ([ev type] != NSApplicationDefined)
3215 abort ();
3216
3217 t = [ev data1];
3218 last_appdefined_event = 0;
3219
3220 if (t == -2)
3221 {
3222 /* The NX_APPDEFINED event we received was a timeout. */
3223 return 0;
3224 }
3225 else if (t == -1)
3226 {
3227 /* The NX_APPDEFINED event we received was the result of
3228 at least one real input event arriving. */
3229 errno = EINTR;
3230 return -1;
3231 }
3232 else
3233 {
3234 /* Received back from select () in fd_handler; copy the results */
3235 if (readfds)
3236 memcpy (readfds, &select_readfds, sizeof (fd_set));
3237 return t;
3238 }
3239 }
3240 /* never reached, shut compiler up */
3241 return 0;
3242}
3243
3244
3245
3246/* ==========================================================================
3247
3248 Scrollbar handling
3249
3250 ========================================================================== */
3251
3252
3253static void
3254ns_set_vertical_scroll_bar (struct window *window,
3255 int portion, int whole, int position)
3256/* --------------------------------------------------------------------------
3257 External (hook): Update or add scrollbar
3258 -------------------------------------------------------------------------- */
3259{
3260 Lisp_Object win;
3261 NSRect r, v;
3262 struct frame *f = XFRAME (WINDOW_FRAME (window));
3263 EmacsView *view = FRAME_NS_VIEW (f);
3264 int window_y, window_height;
3265 BOOL barOnVeryLeft, barOnVeryRight;
3266 int top, left, height, width, sb_width, sb_left;
3267 EmacsScroller *bar;
3268static int count = 0;
3269
3270 /* optimization; display engine sends WAY too many of these.. */
3271 if (!NILP (window->vertical_scroll_bar))
3272 {
3273 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
3274 if ([bar checkSamePosition: position portion: portion whole: whole])
3275 {
3276 if (view->scrollbarsNeedingUpdate == 0)
3277 {
3278 if (!windows_or_buffers_changed)
3279 return;
3280 }
3281 else
3282 view->scrollbarsNeedingUpdate--;
3283 }
3284 }
3285
3286 NSTRACE (ns_set_vertical_scroll_bar);
3287
3288 /* Get dimensions. */
3289 window_box (window, -1, 0, &window_y, 0, &window_height);
3290 top = window_y;
3291 height = window_height;
3292 width = WINDOW_CONFIG_SCROLL_BAR_COLS (window) * FRAME_COLUMN_WIDTH (f);
3293 left = WINDOW_SCROLL_BAR_AREA_X (window);
3294
3295 if (top < 5) /* top scrollbar adjustment */
3296 {
3297 top -= FRAME_INTERNAL_BORDER_WIDTH (f);
3298 height += FRAME_INTERNAL_BORDER_WIDTH (f);
3299 }
3300
3301 /* allow for displaying a skinnier scrollbar than char area allotted */
3302 sb_width = (WINDOW_CONFIG_SCROLL_BAR_WIDTH (window) > 0) ?
3303 WINDOW_CONFIG_SCROLL_BAR_WIDTH (window) : width;
3304
3305 barOnVeryLeft = left < 5;
3306 barOnVeryRight = FRAME_PIXEL_WIDTH (f) - left - width < 5;
3307 sb_left = left + FRAME_INTERNAL_BORDER_WIDTH (f)
3308 * (barOnVeryLeft ? -1 : (barOnVeryRight ? 1 : 0));
3309
3310 r = NSMakeRect (sb_left, top, sb_width, height);
3311 /* the parent view is flipped, so we need to flip y value */
3312 v = [view frame];
3313 r.origin.y = (v.size.height - r.size.height - r.origin.y);
3314
3315 XSETWINDOW (win, window);
3316 BLOCK_INPUT;
3317
3318 /* we want at least 5 lines to display a scrollbar */
3319 if (WINDOW_TOTAL_LINES (window) < 5)
3320 {
3321 if (!NILP (window->vertical_scroll_bar))
3322 {
3323 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
3324 [bar removeFromSuperview];
3325 window->vertical_scroll_bar = Qnil;
3326 }
3327 ns_clear_frame_area (f, sb_left, top, width, height);
3328 UNBLOCK_INPUT;
3329 return;
3330 }
3331
3332 if (NILP (window->vertical_scroll_bar))
3333 {
3334 ns_clear_frame_area (f, sb_left, top, width, height);
3335 bar = [[EmacsScroller alloc] initFrame: r window: win];
3336 window->vertical_scroll_bar = make_save_value (bar, 0);
3337 }
3338 else
3339 {
3340 NSRect oldRect;
3341 bar = XNS_SCROLL_BAR (window->vertical_scroll_bar);
3342 oldRect = [bar frame];
3343 r.size.width = oldRect.size.width;
3344 if (FRAME_LIVE_P (f) && !NSEqualRects (oldRect, r))
3345 {
3346 if (oldRect.origin.x != r.origin.x)
3347 ns_clear_frame_area (f, sb_left, top, width, height);
3348 [bar setFrame: r];
3349 }
3350 }
3351
3352 [bar setPosition: position portion: portion whole: whole];
3353 UNBLOCK_INPUT;
3354}
3355
3356
3357static void
3358ns_condemn_scroll_bars (struct frame *f)
3359/* --------------------------------------------------------------------------
3360 External (hook): arrange for all frame's scrollbars to be removed
3361 at next call to judge_scroll_bars, except for those redeemed.
3362 -------------------------------------------------------------------------- */
3363{
3364 int i;
3365 id view;
3366 NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews];
3367
3368 NSTRACE (ns_condemn_scroll_bars);
3369
3370 for (i =[subviews count]-1; i >= 0; i--)
3371 {
3372 view = [subviews objectAtIndex: i];
3373 if ([view isKindOfClass: [EmacsScroller class]])
3374 [view condemn];
3375 }
3376}
3377
3378
3379static void
3380ns_redeem_scroll_bar (struct window *window)
3381/* --------------------------------------------------------------------------
3382 External (hook): arrange to spare this window's scrollbar
3383 at next call to judge_scroll_bars.
3384 -------------------------------------------------------------------------- */
3385{
3386 id bar;
3387 NSTRACE (ns_redeem_scroll_bar);
3388 if (!NILP (window->vertical_scroll_bar))
3389 {
3390 bar =XNS_SCROLL_BAR (window->vertical_scroll_bar);
3391 [bar reprieve];
3392 }
3393}
3394
3395
3396static void
3397ns_judge_scroll_bars (struct frame *f)
3398/* --------------------------------------------------------------------------
3399 External (hook): destroy all scrollbars on frame that weren't
3400 redeemed after call to condemn_scroll_bars.
3401 -------------------------------------------------------------------------- */
3402{
3403 int i;
3404 id view;
3405 NSArray *subviews = [[FRAME_NS_VIEW (f) superview] subviews];
3406 NSTRACE (ns_judge_scroll_bars);
3407 for (i =[subviews count]-1; i >= 0; i--)
3408 {
3409 view = [subviews objectAtIndex: i];
3410 if (![view isKindOfClass: [EmacsScroller class]]) continue;
3411 [view judge];
3412 }
3413}
3414
3415
3416
3417/* ==========================================================================
3418
3419 Miscellaneous, mainly stubbed-out functions added in 23
3420
3421 ========================================================================== */
3422
3423
3424void
3425x_wm_set_icon_position (struct frame *f, int icon_x, int icon_y)
3426{
3427}
3428
3429
3430
3431/* ==========================================================================
3432
3433 Initialization
3434
3435 ========================================================================== */
3436
3437static Lisp_Object ns_string_to_lispmod (char *s)
3438/* --------------------------------------------------------------------------
3439 Convert modifier name to lisp symbol
3440 -------------------------------------------------------------------------- */
3441{
3442 if (!strncmp (SDATA (SYMBOL_NAME (Qmeta)), s, 10))
3443 return Qmeta;
3444 else if (!strncmp (SDATA (SYMBOL_NAME (Qsuper)), s, 10))
3445 return Qsuper;
3446 else if (!strncmp (SDATA (SYMBOL_NAME (Qcontrol)), s, 10))
3447 return Qcontrol;
3448 else if (!strncmp (SDATA (SYMBOL_NAME (Qalt)), s, 10))
3449 return Qalt;
3450 else if (!strncmp (SDATA (SYMBOL_NAME (Qhyper)), s, 10))
3451 return Qhyper;
3452 else if (!strncmp (SDATA (SYMBOL_NAME (Qnone)), s, 10))
3453 return Qnone;
3454 else
3455 return Qnil;
3456}
3457
3458
3459static Lisp_Object ns_mod_to_lisp (int m)
3460/* --------------------------------------------------------------------------
3461 Convert modifier code (see lisp.h) to lisp symbol
3462 -------------------------------------------------------------------------- */
3463{
3464 if (m == CHAR_META)
3465 return Qmeta;
3466 else if (m == CHAR_SUPER)
3467 return Qsuper;
3468 else if (m == CHAR_CTL)
3469 return Qcontrol;
3470 else if (m == CHAR_ALT)
3471 return Qalt;
3472 else if (m == CHAR_HYPER)
3473 return Qhyper;
3474 else /* if (m == 0) */
3475 return Qnone;
3476}
3477
3478
3479static void
3480ns_set_default_prefs ()
3481/* --------------------------------------------------------------------------
3482 Initialize preference variables to defaults
3483 -------------------------------------------------------------------------- */
3484{
3485 ns_alternate_modifier = Qmeta;
3486 ns_command_modifier = Qsuper;
3487 ns_control_modifier = Qcontrol;
3488 ns_function_modifier = Qnone;
3489 ns_cursor_blink_rate = Qnil;
3490 ns_cursor_blink_mode = Qnil;
3491 ns_expand_space = make_float (0.0);
3492 ns_antialias_text = YES;
3493 ns_antialias_threshold = 10.0;
3494 ns_use_qd_smoothing = NO;
3495 ns_use_system_highlight_color = YES;
3496}
3497
3498
3499static void
3500ns_default (const char *parameter, Lisp_Object *result,
3501 Lisp_Object yesval, Lisp_Object noval,
3502 BOOL is_float, BOOL is_modstring)
3503/* --------------------------------------------------------------------------
3504 Check a parameter value in user's preferences
3505 -------------------------------------------------------------------------- */
3506{
3507 const char *value;
3508
3509 if ( (value =[[[NSUserDefaults standardUserDefaults]
3510 stringForKey: [NSString stringWithUTF8String: parameter]]
3511 UTF8String]) )
3512 {
3513 double f;
3514 char *pos;
3515 if (strcasecmp (value, "YES") == 0)
3516 *result = yesval;
3517 else if (strcasecmp (value, "NO") == 0)
3518 *result = noval;
3519 else if (is_float && (f = strtod (value, &pos), pos != value))
3520 *result = make_float (f);
3521 else if (is_modstring && value)
3522 *result = ns_string_to_lispmod (value);
3523 else fprintf (stderr,
3524 "Bad value for default \"%s\": \"%s\"\n", parameter, value);
3525 }
3526}
3527
3528
3529void
3530ns_initialize_display_info (struct ns_display_info *dpyinfo)
3531/* --------------------------------------------------------------------------
3532 Initialize global info and storage for display.
3533 -------------------------------------------------------------------------- */
3534{
3535 NSScreen *screen = [NSScreen mainScreen];
3536 NSWindowDepth depth = [screen depth];
3537
3538 dpyinfo->width = [screen frame].size.width;
3539 dpyinfo->height = [screen frame].size.height;
3540 dpyinfo->resx = 72.27; /* used 75.0, but this makes pt == pixel, expected */
3541 dpyinfo->resy = 72.27;
3542 dpyinfo->color_p = ![NSDeviceWhiteColorSpace isEqualToString:
3543 NSColorSpaceFromDepth (depth)]
3544 && ![NSCalibratedWhiteColorSpace isEqualToString:
3545 NSColorSpaceFromDepth (depth)];
3546 dpyinfo->n_planes = NSBitsPerPixelFromDepth (depth);
3547 dpyinfo->image_cache = make_image_cache ();
3548 dpyinfo->color_table =
3549 (struct ns_color_table *)xmalloc (sizeof (struct ns_color_table));
3550 dpyinfo->color_table->colors = NULL;
3551 dpyinfo->root_window = 42; /* a placeholder.. */
3552
3553 dpyinfo->mouse_face_mouse_frame = NULL;
3554 dpyinfo->mouse_face_deferred_gc = 0;
3555 dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
3556 dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
3557 dpyinfo->mouse_face_face_id = DEFAULT_FACE_ID;
3558 dpyinfo->mouse_face_window = dpyinfo->mouse_face_overlay = Qnil;
3559 dpyinfo->mouse_face_hidden = 0;
3560
3561 dpyinfo->mouse_face_mouse_x = dpyinfo->mouse_face_mouse_y = 0;
3562 dpyinfo->mouse_face_defer = 0;
3563
3564 dpyinfo->ns_highlight_frame = dpyinfo->ns_focus_frame = NULL;
3565
3566 dpyinfo->n_fonts = 0;
3567 dpyinfo->smallest_font_height = 1;
3568 dpyinfo->smallest_char_width = 1;
3569}
3570
3571
3572/* 23: Needed as new part of display engine; this and next define public
3573 functions in this file (well, many of them, anyway). */
3574/* x_... are generic versions in xdisp.c that we, and other terms, get away
3575 with using despite presence in the "system dependent" redisplay
3576 interface. In addition, many of the ns_ methods have code that is
3577 shared with all terms, indicating need for further refactoring. */
3578extern frame_parm_handler ns_frame_parm_handlers[];
3579static struct redisplay_interface ns_redisplay_interface =
3580{
3581 ns_frame_parm_handlers,
3582 x_produce_glyphs, /*generic OK */
3583 x_write_glyphs, /*generic OK */
3584 x_insert_glyphs, /*generic OK */
3585 x_clear_end_of_line, /*generic OK */
3586 ns_scroll_run, /*23 */
3587 ns_after_update_window_line, /*23: added */
3588 ns_update_window_begin, /*23: split from update_begin */
3589 ns_update_window_end, /*23: split from update_end */
3590 x_cursor_to, /*generic OK */
3591 ns_flush,
3592 0, /* flush_display_optional */
3593 x_clear_window_mouse_face, /*generic OK */
3594 x_get_glyph_overhangs, /*23: generic OK */
3595 x_fix_overlapping_area, /*generic OK */
3596 ns_draw_fringe_bitmap, /*23 */
3597 0, /* define_fringe_bitmap */ /*PENDING: simplify ns_draw_fringe_bitmap? */
3598 0, /* destroy_fringe_bitmap */
3599 ns_compute_glyph_string_overhangs, /*23 */
3600 ns_draw_glyph_string, /*23: interface to nsfont.m */
3601 ns_define_frame_cursor, /*23 */
3602 ns_clear_frame_area, /*23 */
3603 ns_draw_window_cursor, /*23: revamped ns_dumpcursor */
3604 ns_draw_vertical_window_border,
3605 ns_shift_glyphs_for_insert
3606};
3607
3608
3609static void
3610ns_delete_display (struct ns_display_info *dpyinfo)
3611{
3612 /*PENDING... */
3613}
3614
3615
3616/* This function is called when the last frame on a display is deleted. */
3617static void
3618ns_delete_terminal (struct terminal *terminal)
3619{
3620 struct ns_display_info *dpyinfo = terminal->display_info.ns;
3621 int i;
3622
3623 /* Protect against recursive calls. Fdelete_frame in
3624 delete_terminal calls us back when it deletes our last frame. */
3625 if (!terminal->name)
3626 return;
3627
3628 BLOCK_INPUT;
3629
3630 x_destroy_all_bitmaps (dpyinfo);
3631 ns_delete_display (dpyinfo);
3632 UNBLOCK_INPUT;
3633}
3634
3635
3636static struct terminal *
3637ns_create_terminal (struct ns_display_info *dpyinfo)
3638/* --------------------------------------------------------------------------
3639 Set up use of NS before we make the first connection.
3640 -------------------------------------------------------------------------- */
3641{
3642 struct terminal *terminal;
3643
3644 NSTRACE (ns_create_terminal);
3645
3646 terminal = create_terminal ();
3647
3648 terminal->type = output_ns;
3649 terminal->display_info.ns = dpyinfo;
3650 dpyinfo->terminal = terminal;
3651
3652 terminal->rif = &ns_redisplay_interface;
3653
3654 terminal->clear_frame_hook = ns_clear_frame;
3655 terminal->ins_del_lines_hook = 0; /* 23: vestigial? */
3656 terminal->delete_glyphs_hook = 0; /* 23: vestigial? */
3657 terminal->ring_bell_hook = ns_ring_bell;
3658 terminal->reset_terminal_modes_hook = ns_reset_terminal_modes;
3659 terminal->set_terminal_modes_hook = ns_set_terminal_modes;
3660 terminal->update_begin_hook = ns_update_begin;
3661 terminal->update_end_hook = ns_update_end;
3662 terminal->set_terminal_window_hook = NULL; /* 23: vestigial? */
3663 terminal->read_socket_hook = ns_read_socket;
3664 terminal->frame_up_to_date_hook = ns_frame_up_to_date;
3665 terminal->mouse_position_hook = ns_mouse_position;
3666 terminal->frame_rehighlight_hook = ns_frame_rehighlight;
3667 terminal->frame_raise_lower_hook = ns_frame_raise_lower;
3668
3669 terminal->fullscreen_hook = 0; /*XTfullscreen_hook;//23.50 */
3670
3671 terminal->set_vertical_scroll_bar_hook = ns_set_vertical_scroll_bar;
3672 terminal->condemn_scroll_bars_hook = ns_condemn_scroll_bars;
3673 terminal->redeem_scroll_bar_hook = ns_redeem_scroll_bar;
3674 terminal->judge_scroll_bars_hook = ns_judge_scroll_bars;
3675
3676 terminal->delete_frame_hook = x_destroy_window;
3677 terminal->delete_terminal_hook = ns_delete_terminal;
3678
3679 terminal->scroll_region_ok = 1;
3680 terminal->char_ins_del_ok = 1;
3681 terminal->line_ins_del_ok = 1;
3682 terminal->fast_clear_end_of_line = 1;
3683 terminal->memory_below_frame = 0;
3684
3685 return terminal;
3686}
3687
3688
3689void
3690ns_initialize ()
3691/* --------------------------------------------------------------------------
3692 Mainly vestigial under NS now that ns_create_terminal () does most things.
3693 -------------------------------------------------------------------------- */
3694{
3695 baud_rate = 38400;
3696 Fset_input_interrupt_mode (Qt);
3697}
3698
3699
3700struct ns_display_info *
3701ns_term_init (Lisp_Object display_name)
3702/* --------------------------------------------------------------------------
3703 Start the Application and get things rolling.
3704 -------------------------------------------------------------------------- */
3705{
3706 extern Lisp_Object Fset_input_mode (Lisp_Object, Lisp_Object,
3707 Lisp_Object, Lisp_Object);
3708 struct terminal *terminal;
3709 struct ns_display_info *dpyinfo;
3710 static int ns_initialized = 0;
3711 Lisp_Object tmp;
3712
3713 NSTRACE (ns_term_init);
3714
3715 /* count object allocs (About, click icon); on OS X use ObjectAlloc tool */
3716 /*GSDebugAllocationActive (YES); */
3717 BLOCK_INPUT;
3718handling_signal = 0;
3719
3720 if (!ns_initialized)
3721 {
3722 ns_initialize ();
3723 ns_initialized = 1;
3724 }
3725
3726 ns_pending_files = [[NSMutableArray alloc] init];
3727 ns_pending_service_names = [[NSMutableArray alloc] init];
3728 ns_pending_service_args = [[NSMutableArray alloc] init];
3729
3730 /* Start app and create the main menu, window, view.
3731 Needs to be here because ns_initialize_display_info () uses AppKit classes.
3732 The view will then ask the NSApp to stop and return to Emacs. */
3733 [EmacsApp sharedApplication];
3734 if (NSApp == nil)
3735 return NULL;
3736 [NSApp setDelegate: NSApp];
3737
3738 /* debugging: log all notifications */
3739 /* [[NSNotificationCenter defaultCenter] addObserver: NSApp
3740 selector: @selector (logNotification:)
3741 name: nil object: nil]; */
3742
3743 dpyinfo = (struct ns_display_info *)xmalloc (sizeof (struct ns_display_info));
3744 bzero (dpyinfo, sizeof (struct ns_display_info));
3745
3746 ns_initialize_display_info (dpyinfo);
3747 terminal = ns_create_terminal (dpyinfo);
3748
3749 terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
3750 init_kboard (terminal->kboard);
3751 terminal->kboard->Vwindow_system = Qns;
3752 terminal->kboard->next_kboard = all_kboards;
3753 all_kboards = terminal->kboard;
3754 /* Don't let the initial kboard remain current longer than necessary.
3755 That would cause problems if a file loaded on startup tries to
3756 prompt in the mini-buffer. */
3757 if (current_kboard == initial_kboard)
3758 current_kboard = terminal->kboard;
3759 terminal->kboard->reference_count++;
3760
3761 dpyinfo->next = ns_display_list;
3762 ns_display_list = dpyinfo;
3763
3764 /* Put it on ns_display_name_list */
3765 ns_display_name_list = Fcons (Fcons (display_name, Qnil),
3766 ns_display_name_list);
3767/* ns_display_name_list = Fcons (Fcons (display_name,
3768 Fcons (Qnil, dpyinfo->xrdb)),
3769 ns_display_name_list); */
3770 dpyinfo->name_list_element = XCAR (ns_display_name_list);
3771
3772 /* Set the name of the terminal. */
3773 terminal->name = (char *) xmalloc (SBYTES (display_name) + 1);
3774 strncpy (terminal->name, SDATA (display_name), SBYTES (display_name));
3775 terminal->name[SBYTES (display_name)] = 0;
3776
3777 UNBLOCK_INPUT;
3778
3779 /* Read various user defaults. */
3780 ns_set_default_prefs ();
3781 ns_default ("AlternateModifier", &ns_alternate_modifier,
3782 Qnil, Qnil, NO, YES);
3783 if (NILP (ns_alternate_modifier))
3784 ns_alternate_modifier = Qmeta;
3785 ns_default ("CommandModifier", &ns_command_modifier,
3786 Qnil, Qnil, NO, YES);
3787 if (NILP (ns_command_modifier))
3788 ns_command_modifier = Qsuper;
3789 ns_default ("ControlModifier", &ns_control_modifier,
3790 Qnil, Qnil, NO, YES);
3791 if (NILP (ns_control_modifier))
3792 ns_control_modifier = Qcontrol;
3793 ns_default ("FunctionModifier", &ns_function_modifier,
3794 Qnil, Qnil, NO, YES);
3795 if (NILP (ns_function_modifier))
3796 ns_function_modifier = Qnone;
3797 ns_default ("CursorBlinkRate", &ns_cursor_blink_rate,
3798 make_float (0.5), Qnil, YES, NO);
3799 if (NUMBERP (ns_cursor_blink_rate))
3800 ns_cursor_blink_mode = Qt;
3801 ns_default ("ExpandSpace", &ns_expand_space,
3802 make_float (0.5), make_float (0.0), YES, NO);
3803 ns_default ("GSFontAntiAlias", &ns_antialias_text,
3804 YES, NO, NO, NO);
3805 tmp = Qnil;
3806 ns_default ("AppleAntiAliasingThreshold", &tmp,
3807 make_float (10.0), make_float (6.0), YES, NO);
3808 ns_antialias_threshold = NILP (tmp) ? 10.0 : XFLOATINT (tmp);
3809 ns_default ("UseQuickdrawSmoothing", &ns_use_qd_smoothing,
3810 YES, NO, NO, NO);
3811 ns_default ("UseSystemHighlightColor", &ns_use_system_highlight_color,
3812 YES, NO, NO, NO);
3813 if (ns_use_system_highlight_color == YES)
3814 {
3815 ns_selection_color = [[NSUserDefaults standardUserDefaults]
3816 stringForKey: @"AppleHighlightColor"];
3817 if (ns_selection_color == nil)
3818 ns_selection_color = NS_SELECTION_COLOR_DEFAULT;
3819 }
3820 else
3821 ns_selection_color = NS_SELECTION_COLOR_DEFAULT;
3822
3823 {
3824 id cl;
3825 Lisp_Object tem, tem1;
3826 extern Lisp_Object Vsource_directory;
3827
3828 cl = [NSColorList colorListNamed: @"Emacs"];
3829
3830 if ( cl == nil )
3831 {
3832 /* first try data_dir, then invocation-dir
3833 and finally source-directory/etc */
3834 tem1 = tem =
3835 Fexpand_file_name (build_string ("Emacs.clr"), Vdata_directory);
3836 if (NILP (Ffile_exists_p (tem)))
3837 {
3838 tem = Fexpand_file_name (build_string ("Emacs.clr"),
3839 Vinvocation_directory);
3840 if (NILP (Ffile_exists_p (tem)))
3841 {
3842 Lisp_Object newdir =
3843 Fexpand_file_name (build_string ("etc/"),
3844 Vsource_directory);
3845 tem = Fexpand_file_name (build_string ("Emacs.clr"),
3846 newdir);
3847 }
3848 }
3849
3850 cl = [[NSColorList alloc]
3851 initWithName: @"Emacs"
3852 fromFile: [NSString stringWithCString: XSTRING (tem)->data]];
3853 if (cl ==nil)
3854 fatal ("Could not find %s.\n", XSTRING (tem1)->data);
3855 [cl writeToFile: nil];
3856 }
3857 }
3858
3859 {
3860 char c[128];
3861#ifdef NS_IMPL_GNUSTEP
3862 strncpy (c, gnustep_base_version, sizeof (c));
3863#else
3864 /*PSnextrelease (128, c); */
3865 snprintf (c, sizeof (c), "%g", NSAppKitVersionNumber);
3866#endif
3867 Vwindow_system_version = build_string (c);
3868 }
3869
3870 delete_keyboard_wait_descriptor (0);
3871
3872/* Set up OS X app menu */
3873#ifdef NS_IMPL_COCOA
3874 {
3875 NSMenu *appMenu;
3876 id<NSMenuItem> item;
3877 /* set up the application menu */
3878 svcsMenu = [[EmacsMenu alloc] initWithTitle: @"Services"];
3879 [svcsMenu setAutoenablesItems: NO];
3880 appMenu = [[EmacsMenu alloc] initWithTitle: @"Emacs"];
3881 [appMenu setAutoenablesItems: NO];
3882 mainMenu = [[EmacsMenu alloc] initWithTitle: @""];
3883
3884 [appMenu insertItemWithTitle: @"About Emacs"
3885 action: @selector (orderFrontStandardAboutPanel:)
3886 keyEquivalent: @""
3887 atIndex: 0];
3888 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 1];
3889 [appMenu insertItemWithTitle: @"Preferences..."
3890 action: @selector (showPreferencesWindow:)
3891 keyEquivalent: @","
3892 atIndex: 2];
3893 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 3];
3894 item = [appMenu insertItemWithTitle: @"Services"
3895 action: @selector (menuDown:)
3896 keyEquivalent: @""
3897 atIndex: 4];
3898 [appMenu setSubmenu: svcsMenu forItem: item];
3899/* [svcsMenu setSupercell: item]; */
3900 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 5];
3901 [appMenu insertItemWithTitle: @"Hide Emacs"
3902 action: @selector (hide:)
3903 keyEquivalent: @"h"
3904 atIndex: 6];
3905 item = [appMenu insertItemWithTitle: @"Hide Others"
3906 action: @selector (hideOtherApplications:)
3907 keyEquivalent: @"h"
3908 atIndex: 7];
3909 [item setKeyEquivalentModifierMask: NSCommandKeyMask | NSAlternateKeyMask];
3910 [appMenu insertItem: [NSMenuItem separatorItem] atIndex: 8];
3911 [appMenu insertItemWithTitle: @"Quit Emacs"
3912 action: @selector (terminate:)
3913 keyEquivalent: @"q"
3914 atIndex: 9];
3915
3916 item = [mainMenu insertItemWithTitle: @"Emacs"
3917 action: @selector (menuDown:)
3918 keyEquivalent: @""
3919 atIndex: 0];
3920 [mainMenu setSubmenu: appMenu forItem: item];
3921
3922 [NSApp setMainMenu: mainMenu];
3923 [NSApp setAppleMenu: appMenu];
3924 [NSApp setServicesMenu: svcsMenu];
3925 /* Needed at least on Cocoa, to get dock menu to show windows */
3926 [NSApp setWindowsMenu: [[NSMenu alloc] init]];
3927 }
3928#endif /* MAC OS X menu setup */
3929
3930 [NSApp run];
3931
3932 return dpyinfo;
3933}
3934
3935
3936extern Lisp_Object Vauto_save_list_file_name;
3937void
3938ns_term_shutdown (int sig)
3939{
3940 /* code not reached in emacs.c after this is called by shut_down_emacs: */
3941 if (STRINGP (Vauto_save_list_file_name))
3942 unlink (XSTRING (Vauto_save_list_file_name)->data);
3943
3944 ns_shutdown_properly = YES;
3945 [NSApp terminate: NSApp];
3946}
3947
3948
3949void
3950syms_of_nsterm ()
3951{
3952 NSTRACE (syms_of_nsterm);
3953 DEFVAR_LISP ("ns-input-file", &ns_input_file,
3954 "The file specified in the last NS event.");
3955 ns_input_file =Qnil;
3956
3957 DEFVAR_LISP ("ns-input-text", &ns_input_text,
3958 "The data received in the last NS text drag event.");
3959 ns_input_text =Qnil;
3960
3961 DEFVAR_LISP ("ns-working-text", &ns_working_text,
3962 "String for visualizing working composition sequence.");
3963 ns_working_text =Qnil;
3964
3965 DEFVAR_LISP ("ns-input-font", &ns_input_font,
3966 "The font specified in the last NS event.");
3967 ns_input_font =Qnil;
3968
3969 DEFVAR_LISP ("ns-input-fontsize", &ns_input_fontsize,
3970 "The fontsize specified in the last NS event.");
3971 ns_input_fontsize =Qnil;
3972
3973 DEFVAR_LISP ("ns-input-line", &ns_input_line,
3974 "The line specified in the last NS event.");
3975 ns_input_line =Qnil;
3976
3977 DEFVAR_LISP ("ns-input-color", &ns_input_color,
3978 "The color specified in the last NS event.");
3979 ns_input_color =Qnil;
3980
3981 DEFVAR_LISP ("ns-input-spi-name", &ns_input_spi_name,
3982 "The service name specified in the last NS event.");
3983 ns_input_spi_name =Qnil;
3984
3985 DEFVAR_LISP ("ns-input-spi-arg", &ns_input_spi_arg,
3986 "The service argument specified in the last NS event.");
3987 ns_input_spi_arg =Qnil;
3988
3989 DEFVAR_LISP ("ns-alternate-modifier", &ns_alternate_modifier,
3990 "This variable describes the behavior of the alternate or option key.\n\
3991Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
3992Set to none means that the alternate / option key is not interpreted by Emacs\n\
3993at all, allowing it to be used at a lower level for accented character entry.");
3994
3995 DEFVAR_LISP ("ns-command-modifier", &ns_command_modifier,
3996 "This variable describes the behavior of the command key.\n\
3997Set to control, meta, alt, super, or hyper means it is taken to be that key.");
3998
3999 DEFVAR_LISP ("ns-control-modifier", &ns_control_modifier,
4000 "This variable describes the behavior of the control key.\n\
4001Set to control, meta, alt, super, or hyper means it is taken to be that key.");
4002
4003 DEFVAR_LISP ("ns-function-modifier", &ns_function_modifier,
4004 "This variable describes the behavior of the function key (on laptops).\n\
4005Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\
4006Set to none means that the function key is not interpreted by Emacs at all,\n\
4007allowing it to be used at a lower level for accented character entry.");
4008
4009 DEFVAR_LISP ("ns-cursor-blink-rate", &ns_cursor_blink_rate,
4010 "Rate at which the Emacs cursor blinks (in seconds).\n\
4011Set to nil to disable blinking.");
4012
4013 DEFVAR_LISP ("ns-cursor-blink-mode", &ns_cursor_blink_mode,
4014 "Internal variable -- use M-x blink-cursor-mode or preferences\n\
4015panel to control this setting.");
4016
4017 DEFVAR_LISP ("ns-expand-space", &ns_expand_space,
4018 "Amount by which spacing between lines is expanded (positive)\n\
4019or shrunk (negative). Zero (the default) means standard line height.\n\
4020(This variable should only be read, never set.)");
4021
4022 DEFVAR_BOOL ("ns-antialias-text", &ns_antialias_text,
4023 "Non-nil (the default) means to render text antialiased. Only has an effect on OS X Panther and above.");
4024
4025 DEFVAR_BOOL ("ns-use-qd-smoothing", &ns_use_qd_smoothing,
4026 "Whether to render text using QuickDraw (less heavy) antialiasing. Only has an effect on OS X Panther and above. Default is nil (use Quartz smoothing).");
4027
4028 DEFVAR_BOOL ("ns-use-system-highlight-color",
4029 &ns_use_system_highlight_color,
4030 "Whether to use the system default (on OS X only) for the highlight color. Nil means to use standard emacs (prior to version 21) 'grey'.");
4031
4032 staticpro (&ns_display_name_list);
4033 ns_display_name_list = Qnil;
4034
4035 staticpro (&last_mouse_motion_frame);
4036 last_mouse_motion_frame = Qnil;
4037
4038/*23: now apparently we need to tell emacs what modifiers there are.. */
4039 Qmodifier_value = intern ("modifier-value");
4040 Qalt = intern ("alt");
4041 Fput (Qalt, Qmodifier_value, make_number (alt_modifier));
4042 Qhyper = intern ("hyper");
4043 Fput (Qhyper, Qmodifier_value, make_number (hyper_modifier));
4044 Qmeta = intern ("meta");
4045 Fput (Qmeta, Qmodifier_value, make_number (meta_modifier));
4046 Qsuper = intern ("super");
4047 Fput (Qsuper, Qmodifier_value, make_number (super_modifier));
4048 Qcontrol = intern ("control");
4049 Fput (Qcontrol, Qmodifier_value, make_number (ctrl_modifier));
4050
4051 /*PENDING: move to common code */
4052 DEFVAR_LISP ("x-toolkit-scroll-bars", &Vx_toolkit_scroll_bars,
4053 doc: /* If not nil, Emacs uses toolkit scroll bars. */);
4054#ifdef USE_TOOLKIT_SCROLL_BARS
4055 Vx_toolkit_scroll_bars = Qt;
4056#else
4057 Vx_toolkit_scroll_bars = Qnil;
4058#endif
4059
4060 /* these are unsupported but we need the declarations to avoid whining
4061 messages from cus-start.el */
4062 DEFVAR_BOOL ("x-use-underline-position-properties",
4063 &x_use_underline_position_properties,
4064 doc: /* NOT SUPPORTED UNDER NS.
4065*Non-nil means make use of UNDERLINE_POSITION font properties.
4066A value of nil means ignore them. If you encounter fonts with bogus
4067UNDERLINE_POSITION font properties, for example 7x13 on XFree prior
4068to 4.1, set this to nil.
4069
4070NOTE: Not supported on Mac yet. */);
4071 x_use_underline_position_properties = 0;
4072
4073 DEFVAR_BOOL ("x-underline-at-descent-line",
4074 &x_underline_at_descent_line,
4075 doc: /* NOT SUPPORTED UNDER NS.
4076*Non-nil means to draw the underline at the same place as the descent line.
4077A value of nil means to draw the underline according to the value of the
4078variable `x-use-underline-position-properties', which is usually at the
4079baseline level. The default value is nil. */);
4080 x_underline_at_descent_line = 0;
4081
4082 /* Tell emacs about this window system. */
4083 Fprovide (intern ("ns-windowing"), Qnil);
4084 /* PENDING: try to move this back into lisp (ns-win.el loaded too late
4085 right now */
4086 {
4087 Lisp_Object args[3] = { intern ("ns-version-string"), build_string ("9.0"),
4088 build_string ("NS Window system port version number.") };
4089 Fdefconst (Flist (3, args));
4090 }
4091}
4092
4093
4094
4095/* ==========================================================================
4096
4097 EmacsApp implementation
4098
4099 ========================================================================== */
4100
4101
4102@implementation EmacsApp
4103
4104- (void)logNotification: (NSNotification *)notification
4105{
4106 const char *name = [[notification name] UTF8String];
4107 if (!strstr (name, "Update") && !strstr (name, "NSMenu")
4108 && !strstr (name, "WindowNumber"))
4109 NSLog (@"notification: '%@'", [notification name]);
4110}
4111
4112
4113- (void)sendEvent: (NSEvent *)theEvent
4114/* --------------------------------------------------------------------------
4115 Events posted by ns_send_appdefined interrupt the run loop here
4116 -------------------------------------------------------------------------- */
4117{
4118 int type = [theEvent type];
4119 NSWindow *window = [theEvent window];
4120/* NSTRACE (sendEvent); */
4121/*fprintf (stderr, "received event of type %d\n", [theEvent type]); */
4122
4123 if (type == NSCursorUpdate && window == nil)
4124 {
4125 fprintf (stderr, "Dropping external cursor update event.\n");
4126 return;
4127 }
4128
4129#ifdef NS_IMPL_COCOA
4130 /* pass mouse down in resize handle and subsequent drags directly to
4131 EmacsWindow so we can generate continuous redisplays */
4132 if (ns_in_resize)
4133 {
4134 if (type == NSLeftMouseDragged)
4135 {
4136 [window mouseDragged: theEvent];
4137 return;
4138 }
4139 else if (type == NSLeftMouseUp)
4140 {
4141 [window mouseUp: theEvent];
4142 return;
4143 }
4144 }
4145 else if (type == NSLeftMouseDown)
4146 {
4147 NSRect r = ns_resize_handle_rect (window);
4148 if (NSPointInRect ([theEvent locationInWindow], r))
4149 {
4150 ns_in_resize = YES;
4151 [window mouseDown: theEvent];
4152 return;
4153 }
4154 }
4155#endif
4156
4157 if (type == NSApplicationDefined)
4158 {
4159 last_appdefined_event = theEvent;
4160 [self stop: self];
4161 }
4162
4163 [super sendEvent: theEvent];
4164}
4165
4166
4167- (void)showPreferencesWindow: (id)sender
4168{
4169 if (prefsController == nil)
4170 prefsController = [[EmacsPrefsController alloc] init];
4171 [prefsController showForFrame: SELECTED_FRAME ()];
4172}
4173
4174
4175/* **************************************************************************
4176
4177 EmacsApp delegate implementation
4178
4179 ************************************************************************** */
4180
4181- (void)applicationDidFinishLaunching: (NSNotification *)notification
4182/* --------------------------------------------------------------------------
4183 When application is loaded, terminate event loop in ns_term_init
4184 -------------------------------------------------------------------------- */
4185{
4186 NSTRACE (applicationDidFinishLaunching);
4187 [NSApp setServicesProvider: NSApp];
4188 ns_send_appdefined (-2);
4189}
4190
4191
4192- (void) terminate: (id)sender
4193{
4194 BLOCK_INPUT;
4195 if (ns_shutdown_properly)
4196 [super terminate: sender];
4197 else
4198 {
4199/* Fkill_emacs (Qnil); */
4200 ns_shutdown_properly = YES;
4201 Feval (Fcons (intern ("save-buffers-kill-emacs"), Qnil));
4202 }
4203 UNBLOCK_INPUT;
4204}
4205
4206
4207- (NSApplicationTerminateReply)applicationShouldTerminate: (id)sender
4208{
4209 if (ns_shutdown_properly)
4210 return NSTerminateNow;
4211
4212 Lisp_Object contents = list3 (build_string ("Exit requested. Would you like to Save Buffers and Exit, or Cancel the request?"),
4213 Fcons (build_string ("Cancel"), Qnil),
4214 Fcons (build_string ("Save and Exit"), Qt));
4215 Lisp_Object res = ns_popup_dialog (Qt, contents, Qnil);
4216fprintf (stderr, "res = %d\n", res ==Qt);
4217 if (res == Qt)
4218 {
4219 Feval (Fcons (intern ("save-buffers-kill-emacs"), Qnil));
4220 return NSTerminateNow;
4221 }
4222 return NSTerminateCancel;
4223}
4224
4225
4226/* Open a file (used by below, after going into queue read by ns_read_socket) */
4227-(BOOL) openFile: (NSString *)fileName
4228{
4229 struct frame *emacsframe = SELECTED_FRAME ();
4230 NSEvent *theEvent = [NSApp currentEvent];
4231
4232 if (!emacs_event)
4233 return NO;
4234
4235 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
4236 emacs_event->code = KEY_NS_OPEN_FILE_LINE;
4237 ns_input_file = append2 (ns_input_file, build_string ([fileName UTF8String]));
4238 ns_input_line = Qnil; /* can be start or cons start,end */
4239 emacs_event->modifiers =0;
4240 EV_TRAILER (theEvent);
4241
4242 return YES;
4243}
4244
4245
4246/* Notification from the Workspace to open a file */
4247- (BOOL)application: sender openFile: (NSString *)file
4248{
4249 [ns_pending_files addObject: file];
4250 return YES;
4251}
4252
4253
4254/* Open a file as a temporary file */
4255- (BOOL)application: sender openTempFile: (NSString *)file
4256{
4257 [ns_pending_files addObject: file];
4258 return YES;
4259}
4260
4261
4262/* Notification from the Workspace to open a file noninteractively (?) */
4263- (BOOL)application: sender openFileWithoutUI: (NSString *)file
4264{
4265 [ns_pending_files addObject: file];
4266 return YES;
4267}
4268
4269
4270/* Notification from the Workspace to open multiple files */
4271- (void)application: sender openFiles: (NSArray *)fileList
4272{
4273 NSEnumerator *files = [fileList objectEnumerator];
4274 NSString *file;
4275 while ((file = [files nextObject]) != nil)
4276 [ns_pending_files addObject: file];
4277 return YES;
4278}
4279
4280/*PENDING: these may help w/IO switching btwn terminal and NSApp */
4281- (void)applicationDidBecomeActive: (NSNotification *)notification
4282{
4283}
4284- (void)applicationDidResignActive: (NSNotification *)notification
4285{
4286 ns_send_appdefined (-1);
4287}
4288
4289
4290
4291/* ==========================================================================
4292
4293 EmacsApp aux handlers for managing event loop
4294
4295 ========================================================================== */
4296
4297
4298- (void)timeout_handler: (NSTimer *)timedEntry
4299/* --------------------------------------------------------------------------
4300 The timeout specified to ns_select has passed.
4301 -------------------------------------------------------------------------- */
4302{
4303 /*NSTRACE (timeout_handler); */
4304 ns_send_appdefined (-2);
4305}
4306
4307extern void update_window_cursor (struct window *w, int on);
4308
4309- (void)cursor_blink_handler: (NSTimer *)cursorEntry
4310/* --------------------------------------------------------------------------
4311 Flash the cursor
4312 -------------------------------------------------------------------------- */
4313{
4314 struct ns_display_info *dpyinfo = ns_display_list; /*HACK, but OK for now */
4315 struct frame *f = dpyinfo->ns_highlight_frame;
4316 NSTRACE (cursor_blink_handler);
4317
4318 if (!f)
4319 return;
4320 if (f->output_data.ns->current_cursor == no_highlight)
4321 {
4322 Lisp_Object tem = get_frame_param (f, Qcursor_type);
4323 f->output_data.ns->desired_cursor = ns_lisp_to_cursor_type (tem);
4324 }
4325 else
4326 {
4327 f->output_data.ns->desired_cursor = no_highlight;
4328 }
4329 update_window_cursor (XWINDOW (FRAME_SELECTED_WINDOW (f)), 1);
4330 /*x_update_cursor (f, 1); */
4331}
4332
4333
4334- (void)fd_handler: (NSTimer *) fdEntry
4335/* --------------------------------------------------------------------------
4336 Check data waiting on file descriptors and terminate if so
4337 -------------------------------------------------------------------------- */
4338{
4339 int result;
4340 /* NSTRACE (fd_handler); */
4341
4342 if (select_nfds == 0)
4343 return;
4344
4345 memcpy (&t_readfds, &select_readfds, sizeof (fd_set));
4346
4347 select_timeout.tv_sec = select_timeout.tv_usec = 0;
4348 result = select (select_nfds, &t_readfds, (SELECT_TYPE *)0, (SELECT_TYPE *)0,
4349 &select_timeout);
4350 if (result)
4351 {
4352 memcpy (&select_readfds, &t_readfds, sizeof (fd_set));
4353 ns_send_appdefined (result);
4354 }
4355}
4356
4357
4358
4359/* ==========================================================================
4360
4361 Service provision
4362
4363 ========================================================================== */
4364
4365/* called from system: queue for next pass through event loop */
4366- (void)requestService: (NSPasteboard *)pboard
4367 userData: (NSString *)userData
4368 error: (NSString **)error
4369{
4370 [ns_pending_service_names addObject: userData];
4371 [ns_pending_service_args addObject: [NSString stringWithUTF8String:
4372 SDATA (ns_string_from_pasteboard (pboard))]];
4373}
4374
4375
4376/* called from ns_read_socket to clear queue */
4377- (BOOL)fulfillService: (NSString *)name withArg: (NSString *)arg
4378{
4379 struct frame *emacsframe = SELECTED_FRAME ();
4380 NSEvent *theEvent = [NSApp currentEvent];
4381
4382 if (!emacs_event)
4383 return NO;
4384
4385 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
4386 emacs_event->code = KEY_NS_SPI_SERVICE_CALL;
4387 ns_input_spi_name = build_string ([name UTF8String]);
4388 ns_input_spi_arg = build_string ([arg UTF8String]);
4389 emacs_event->modifiers = EV_MODIFIERS (theEvent);
4390 EV_TRAILER (theEvent);
4391
4392 return YES;
4393}
4394
4395
4396@end /* EmacsApp */
4397
4398
4399
4400/* ==========================================================================
4401
4402 EmacsView implementation
4403
4404 ========================================================================== */
4405
4406
4407@implementation EmacsView
4408
4409/* needed to inform when window closed from LISP */
4410- (void) setWindowClosing: (BOOL)closing
4411{
4412 windowClosing = closing;
4413}
4414
4415
4416- (void)dealloc
4417{
4418 NSTRACE (EmacsView_dealloc);
4419 [toolbar release];
4420 [super dealloc];
4421}
4422
4423
4424/* called on font panel selection */
4425- (void)changeFont: (id)sender
4426{
4427 NSEvent *e =[[self window] currentEvent];
4428 struct face *face =FRAME_DEFAULT_FACE (emacsframe);
4429 id newFont;
4430 float size;
4431
4432 NSTRACE (changeFont);
4433 if (!emacs_event)
4434 return;
4435
4436 if (newFont = [sender convertFont:
4437 ((struct nsfont_info *)face->font)->nsfont])
4438 {
4439 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
4440 emacs_event->modifiers = 0;
4441 emacs_event->code = KEY_NS_CHANGE_FONT;
4442
4443 size = [newFont pointSize];
4444 /* PENDING: stick w/integer sizes for now. */
4445/* if (size == lrint (size)) */
4446 ns_input_fontsize = make_number (lrint (size));
4447/* else
4448 ns_input_fontsize = make_float (size); */
4449 ns_input_font = build_string ([[newFont familyName] UTF8String]);
4450 EV_TRAILER (e);
4451 }
4452}
4453
4454
4455- (BOOL)acceptsFirstResponder
4456{
4457 NSTRACE (acceptsFirstResponder);
4458 return YES;
4459}
4460
4461
4462- (void)resetCursorRects
4463{
4464 NSRect visible = [self visibleRect];
4465 NSCursor *currentCursor = FRAME_POINTER_TYPE (emacsframe);
4466 NSTRACE (resetCursorRects);
4467
4468 if (currentCursor == nil)
4469 currentCursor = [NSCursor arrowCursor];
4470
4471 if (!NSIsEmptyRect (visible))
4472 [self addCursorRect: visible cursor: currentCursor];
4473 [currentCursor setOnMouseEntered: YES];
4474}
4475
4476
4477/*****************************************************************************/
4478/* Keyboard handling. */
4479#define NS_KEYLOG 0
4480
4481- (void)keyDown: (NSEvent *)theEvent
4482{
4483 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe);
4484 int code;
4485 unsigned fnKeysym = 0;
4486 int flags;
4487 static NSMutableArray *nsEvArray;
4488 static BOOL firstTime = YES;
4489
4490 NSTRACE (keyDown);
4491
4492 /* Rhapsody and OS X give up and down events for the arrow keys */
4493 if ([theEvent type] != NSKeyDown)
4494 return;
4495
4496 if (!emacs_event)
4497 return;
4498
4499/*#if defined (COCOA_EXPERIMENTAL_CTRL_G) */
4500 if (![[self window] isKeyWindow])
4501 {
4502 /* PENDING: Using NO_SOCK_SIGIO like Carbon causes a condition in which,
4503 when Emacs display updates a different frame from the current one,
4504 and temporarily selects it, then processes some interrupt-driven
4505 input (dispnew.c:3878), OS will send the event to the correct NSWindow,
4506 but for some reason that window has its first responder set to the
4507 NSView most recently updated (I guess), which is not the correct one.
4508 UPDATE: After multi-TTY merge this happens even w/o NO_SOCK_SIGIO */
4509 if ([[theEvent window] isKindOfClass: [EmacsWindow class]])
4510 [[(EmacsView *)[theEvent window] delegate] keyDown: theEvent];
4511 return;
4512 }
4513/*#endif */
4514
4515 if (nsEvArray == nil)
4516 nsEvArray = [[NSMutableArray alloc] initWithCapacity: 1];
4517
4518 [NSCursor setHiddenUntilMouseMoves: YES];
4519
4520 if (dpyinfo->mouse_face_hidden && INTEGERP (Vmouse_highlight))
4521 {
4522 clear_mouse_face (dpyinfo);
4523 dpyinfo->mouse_face_hidden = 1;
4524 }
4525
4526 if (!processingCompose)
4527 {
4528 code = ([[theEvent charactersIgnoringModifiers] length] == 0) ?
4529 0 : [[theEvent charactersIgnoringModifiers] characterAtIndex: 0];
4530 /* (Carbon way: [theEvent keyCode]) */
4531
4532 /* is it a "function key"? */
4533 fnKeysym = ns_convert_key (code);
4534 if (fnKeysym)
4535 {
4536 /* COUNTERHACK: map 'Delete' on upper-right main KB to 'Backspace',
4537 because Emacs treats Delete and KP-Delete same (in simple.el). */
4538 if (fnKeysym == 0xFFFF && [theEvent keyCode] == 0x33)
4539 code = 0xFF08; /* backspace */
4540 else
4541 code = fnKeysym;
4542 }
4543
4544 /* are there modifiers? */
4545 emacs_event->modifiers = 0;
4546 flags = [theEvent modifierFlags];
4547
4548 if (flags & NSHelpKeyMask)
4549 emacs_event->modifiers |= hyper_modifier;
4550
4551 if (flags & NSShiftKeyMask)
4552 emacs_event->modifiers |= shift_modifier;
4553
4554 if (flags & NSCommandKeyMask)
4555 {
4556 emacs_event->modifiers |= lisp_to_mod (ns_command_modifier);
4557 /* if super (default), take input manager's word so things like
4558 dvorak / qwerty layout work */
4559 if (EQ (ns_command_modifier, Qsuper)
4560 && !fnKeysym
4561 && [[theEvent characters] length] != 0)
4562 {
4563 /* PENDING: the code we get will be unshifted, so if we have
4564 a shift modifier, must convert ourselves */
4565 if (!(flags & NSShiftKeyMask))
4566 code = [[theEvent characters] characterAtIndex: 0];
4567#if 0
4568 /* this is ugly and also requires linking w/Carbon framework
4569 (for LMGetKbdType) so for now leave this rare (?) case
4570 undealt with.. in future look into CGEvent methods */
4571 else
4572 {
4573 long smv = GetScriptManagerVariable (smKeyScript);
4574 Handle uchrHandle = GetResource
4575 ('uchr', GetScriptVariable (smv, smScriptKeys));
4576 UInt32 dummy = 0;
4577 UCKeyTranslate ((UCKeyboardLayout*)*uchrHandle,
4578 [[theEvent characters] characterAtIndex: 0],
4579 kUCKeyActionDisplay,
4580 (flags & ~NSCommandKeyMask) >> 8,
4581 LMGetKbdType (), kUCKeyTranslateNoDeadKeysMask,
4582 &dummy, 1, &dummy, &code);
4583 code &= 0xFF;
4584 }
4585#endif
4586 }
4587 }
4588
4589 if (flags & NSControlKeyMask)
4590 emacs_event->modifiers |= lisp_to_mod (ns_control_modifier);
4591
4592 if (flags & NS_FUNCTION_KEY_MASK && !fnKeysym)
4593 emacs_event->modifiers |= lisp_to_mod (ns_function_modifier);
4594
4595 if (flags & NSAlternateKeyMask) /* default = meta */
4596 {
4597 if (EQ (ns_alternate_modifier, Qnone) && !fnKeysym)
4598 { /* accept pre-interp alt comb */
4599 if ([[theEvent characters] length] > 0)
4600 code = [[theEvent characters] characterAtIndex: 0];
4601 /*HACK: clear lone shift modifier to stop next if from firing */
4602 if (emacs_event->modifiers == shift_modifier)
4603 emacs_event->modifiers = 0;
4604 }
4605 else
4606 emacs_event->modifiers |= lisp_to_mod (ns_alternate_modifier);
4607 }
4608
4609/*fprintf (stderr,"code =%x\tfnKey =%x\tflags = %x\tmods = %x\n",code,fnKeysym,flags,emacs_event->modifiers); */
4610
4611 /* if it was a function key or had modifiers, pass it directly to emacs */
4612 if (fnKeysym || (emacs_event->modifiers
4613 && [[theEvent charactersIgnoringModifiers] length] > 0))
4614/*[[theEvent characters] length] */
4615 {
4616 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
4617 if (code < 0x20)
4618 code |= (1<<28)|(3<<16);
4619 else if (code == 0x7f)
4620 code |= (1<<28)|(3<<16);
4621 else if (!fnKeysym)
4622 emacs_event->kind = code > 0xFF
4623 ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT;
4624
4625 emacs_event->code = code;
4626 EV_TRAILER (theEvent);
4627 return;
4628 }
4629 }
4630
4631 /* if we get here we should send the key for input manager processing */
4632 if (firstTime && [[NSInputManager currentInputManager]
4633 wantsToDelayTextChangeNotifications] == NO)
4634 fprintf (stderr,
4635 "Emacs: WARNING: TextInput mgr wants marked text to be permanent!\n");
4636 firstTime = NO;
4637
4638 if (NS_KEYLOG && !processingCompose)
4639 fprintf (stderr, "Begin compose sequence.\n");
4640
4641 processingCompose = YES;
4642 [nsEvArray addObject: theEvent];
4643 [self interpretKeyEvents: nsEvArray];
4644 [nsEvArray removeObject: theEvent];
4645}
4646
4647
4648/* <NSTextInput> implementation (called through super interpretKeyEvents:]). */
4649
4650
4651/* <NSTextInput>: called through when done composing */
4652- (void)insertText: (id)aString
4653{
4654 int code;
4655 int len = [(NSString *)aString length];
4656 int i;
4657
4658if (NS_KEYLOG) NSLog (@"insertText '%@'\tlen = %d", aString, len);
4659 processingCompose = NO;
4660
4661 if (!emacs_event)
4662 return;
4663
4664 /* first, clear any working text */
4665 if (workingText != nil)
4666 [self deleteWorkingText];
4667
4668 /* now insert the string as keystrokes */
4669 for (i =0; i<len; i++)
4670 {
4671 code = [aString characterAtIndex: i];
4672 /* PENDING: still need this? */
4673 if (code == 0x2DC)
4674 code = '~'; /* 0x7E */
4675 emacs_event->modifiers = 0;
4676 emacs_event->kind =
4677 code > 0xFF ? MULTIBYTE_CHAR_KEYSTROKE_EVENT : ASCII_KEYSTROKE_EVENT;
4678 emacs_event->code = code;
4679 EV_TRAILER ((id)nil);
4680 }
4681}
4682
4683
4684/* <NSTextInput>: inserts display of composing characters */
4685- (void)setMarkedText: (id)aString selectedRange: (NSRange)selRange
4686{
4687 NSString *str = [aString respondsToSelector: @selector (string)] ?
4688 [aString string] : aString;
4689 if (NS_KEYLOG)
4690 NSLog (@"setMarkedText '%@' len =%d range %d from %d", str, [str length],
4691 selRange.length, selRange.location);
4692
4693 if (workingText != nil)
4694 [self deleteWorkingText];
4695 if ([str length] == 0)
4696 return;
4697
4698 if (!emacs_event)
4699 return;
4700
4701 processingCompose = YES;
4702 workingText = [str copy];
4703 ns_working_text = build_string ([workingText UTF8String]);
4704
4705 /* if in "echo area", not true minibuffer, can't show chars in interactive
4706 mode, so call using eval; otherwise we send a key event, which was the
4707 original way this was done */
4708 if (!EQ (Feval (Fcons (intern ("ns-in-echo-area"), Qnil)), Qnil))
4709 {
4710 Feval (Fcons (intern ("ns-echo-working-text"), Qnil));
4711 ns_send_appdefined (-1);
4712 }
4713 else
4714 {
4715 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
4716 emacs_event->code = KEY_NS_INSERT_WORKING_TEXT;
4717 EV_TRAILER ((id)nil);
4718 }
4719}
4720
4721
4722/* delete display of composing characters [not in <NSTextInput>] */
4723- (void)deleteWorkingText
4724{
4725 if (workingText == nil)
4726 return;
4727 if (NS_KEYLOG)
4728 fprintf (stderr, "deleteWorkingText len =%d\n", [workingText length]);
4729 [workingText release];
4730 workingText = nil;
4731 processingCompose = NO;
4732
4733 if (!emacs_event)
4734 return;
4735
4736 if (!EQ (Feval (Fcons (intern ("ns-in-echo-area"), Qnil)), Qnil))
4737 {
4738 Feval (Fcons (intern ("ns-unecho-working-text"), Qnil));
4739 ns_send_appdefined (-1);
4740 }
4741 else
4742 {
4743 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
4744 emacs_event->code = KEY_NS_DELETE_WORKING_TEXT;
4745 EV_TRAILER ((id)nil);
4746 }
4747 }
4748
4749
4750- (BOOL)hasMarkedText
4751{
4752 return workingText != nil;
4753}
4754
4755- (NSRange)markedRange
4756{
4757 NSRange rng = workingText != nil
4758 ? NSMakeRange (0, [workingText length]) : NSMakeRange (NSNotFound, 0);
4759if (NS_KEYLOG) NSLog (@"markedRange request");
4760 return rng;
4761}
4762
4763- (void)unmarkText
4764{
4765if (NS_KEYLOG) NSLog (@"unmark (accept) text");
4766 [self deleteWorkingText];
4767 processingCompose = NO;
4768}
4769
4770/* used to position char selection windows, etc. */
4771- (NSRect)firstRectForCharacterRange: (NSRange)theRange
4772{
4773 NSRect rect;
4774 NSPoint pt;
4775 struct window *win = XWINDOW (FRAME_SELECTED_WINDOW (emacsframe));
4776if (NS_KEYLOG) NSLog (@"firstRectForCharRange request");
4777
4778 rect.size.width = theRange.length * FRAME_COLUMN_WIDTH (emacsframe);
4779 rect.size.height = FRAME_LINE_HEIGHT (emacsframe);
4780 pt.x = WINDOW_TEXT_TO_FRAME_PIXEL_X (win, win->phys_cursor.x);
4781 pt.y = WINDOW_TO_FRAME_PIXEL_Y (win, win->phys_cursor.y
4782 +FRAME_LINE_HEIGHT (emacsframe));
4783
4784 pt = [self convertPoint: pt toView: nil];
4785 pt = [[self window] convertBaseToScreen: pt];
4786 rect.origin = pt;
4787 return rect;
4788}
4789
4790- (long)conversationIdentifier
4791{
4792 return (long)self;
4793}
4794
4795/*PENDING: below here not yet implemented correctly, but may not be needed */
4796
4797- (void)doCommandBySelector: (SEL)aSelector
4798{
4799 if (NS_KEYLOG) NSLog (@"Do command by selector: %@",
4800 NSStringFromSelector (aSelector));
4801
4802 if (aSelector == @selector (deleteBackward:))
4803 {
4804 /* happens when user backspaces over an ongoing composition:
4805 throw a 'delete' into the event queue */
4806 if (!emacs_event)
4807 return;
4808 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
4809 emacs_event->code = 0xFF08;
4810 EV_TRAILER ((id)nil);
4811 }
4812}
4813
4814- (NSArray *)validAttributesForMarkedText
4815{
4816 static NSArray *arr = nil;
4817 if (arr == nil) arr = [NSArray new];
4818 /* [[NSArray arrayWithObject: NSUnderlineStyleAttributeName] retain]; */
4819 return arr;
4820}
4821
4822- (NSRange)selectedRange
4823{
4824if (NS_KEYLOG) NSLog (@"selectedRange request");
4825 return NSMakeRange (NSNotFound, 0);
4826}
4827
4828- (unsigned int)characterIndexForPoint: (NSPoint)thePoint
4829{
4830if (NS_KEYLOG) NSLog (@"characterIndexForPoint request");
4831 return 0;
4832}
4833
4834- (NSAttributedString *)attributedSubstringFromRange: (NSRange)theRange
4835{
4836 static NSAttributedString *str = nil;
4837 if (str == nil) str = [NSAttributedString new];
4838if (NS_KEYLOG) NSLog (@"attributedSubstringFromRange request");
4839 return str;
4840}
4841
4842/* End <NSTextInput> impl. */
4843/*****************************************************************************/
4844
4845
4846/* This is what happens when the user presses a mouse button. */
4847- (void)mouseDown: (NSEvent *)theEvent
4848{
4849 NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil];
4850 Lisp_Object window;
4851
4852 NSTRACE (mouseDown);
4853
4854 [self deleteWorkingText];
4855
4856 if (!emacs_event)
4857 return;
4858
4859 last_mouse_frame = emacsframe;
4860 /* appears to be needed to prevent spurious movement events generated on
4861 button clicks */
4862 last_mouse_frame->mouse_moved = 0;
4863
4864 if ([theEvent type] == NSScrollWheel)
4865 {
4866 float delta = [theEvent deltaY];
4867 /* Mac notebooks send wheel events w/delta =0 when trackpad scrolling */
4868 if (delta == 0)
4869 return;
4870 emacs_event->kind = WHEEL_EVENT;
4871 emacs_event->code = 0;
4872 emacs_event->modifiers = EV_MODIFIERS (theEvent) |
4873 ((delta > 0) ? up_modifier : down_modifier);
4874 }
4875 else
4876 {
4877 emacs_event->kind = MOUSE_CLICK_EVENT;
4878 emacs_event->code = EV_BUTTON (theEvent);
4879 emacs_event->modifiers = EV_MODIFIERS (theEvent)
4880 | EV_UDMODIFIERS (theEvent);
4881 }
4882 XSETINT (emacs_event->x, lrint (p.x));
4883 XSETINT (emacs_event->y, lrint (p.y));
4884 EV_TRAILER (theEvent);
4885}
4886
4887
4888- (void)mouseUp: (NSEvent *)theEvent
4889{
4890 NSTRACE (mouseUp);
4891 [self mouseDown: theEvent];
4892}
4893
4894
4895- (void)rightMouseDown: (NSEvent *)theEvent
4896{
4897 NSTRACE (rightMouseDown);
4898 [self mouseDown: theEvent];
4899}
4900
4901
4902- (void)rightMouseUp: (NSEvent *)theEvent
4903{
4904 NSTRACE (rightMouseUp);
4905 [self mouseDown: theEvent];
4906}
4907
4908
4909- (void) scrollWheel: (NSEvent *)theEvent
4910{
4911 NSTRACE (scrollWheel);
4912 [self mouseDown: theEvent];
4913}
4914
4915
4916/* Tell emacs the mouse has moved. */
4917- (void)mouseMoved: (NSEvent *)e
4918{
4919 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe);
4920 Lisp_Object frame;
4921
4922 NSTRACE (mouseMoved);
4923
4924 last_mouse_movement_time = EV_TIMESTAMP (e);
4925 last_mouse_motion_position =
4926 [self convertPoint: [e locationInWindow] fromView: nil];
4927
4928 /* update any mouse face */
4929 if (dpyinfo->mouse_face_hidden)
4930 {
4931 dpyinfo->mouse_face_hidden = 0;
4932 clear_mouse_face (dpyinfo);
4933 }
4934
4935 /* tooltip handling */
4936 previous_help_echo_string = help_echo_string;
4937 help_echo_string = Qnil;
4938
4939 if (!note_mouse_movement (emacsframe, last_mouse_motion_position.x,
4940 last_mouse_motion_position.y))
4941 help_echo_string = previous_help_echo_string;
4942
4943 XSETFRAME (frame, emacsframe);
4944 if (!NILP (help_echo_string) || !NILP (previous_help_echo_string))
4945 {
4946 /* NOTE: help_echo_{window,pos,object} are set in xdisp.c
4947 (note_mouse_highlight), which is called through the
4948 note_mouse_movement () call above */
4949 gen_help_event (help_echo_string, frame, help_echo_window,
4950 help_echo_object, help_echo_pos);
4951 }
4952 else
4953 {
4954 help_echo_string = Qnil;
4955 gen_help_event (Qnil, frame, Qnil, Qnil, 0);
4956 }
4957
4958 if (emacsframe->mouse_moved && send_appdefined)
4959 ns_send_appdefined (-1);
4960}
4961
4962
4963- (void)mouseDragged: (NSEvent *)e
4964{
4965 NSTRACE (mouseDragged);
4966 [self mouseMoved: e];
4967}
4968
4969
4970- (void)rightMouseDragged: (NSEvent *)e
4971{
4972 NSTRACE (rightMouseDragged);
4973 [self mouseMoved: e];
4974}
4975
4976
4977- (BOOL)windowShouldClose: (id)sender
4978{
4979 NSEvent *e =[[self window] currentEvent];
4980
4981 NSTRACE (windowShouldClose);
4982 windowClosing = YES;
4983 if (ns_window_num <= 1)
4984 return NO;
4985 if (!emacs_event)
4986 return NO;
4987 emacs_event->kind = DELETE_WINDOW_EVENT;
4988 emacs_event->modifiers = 0;
4989 emacs_event->code = 0;
4990 EV_TRAILER (e);
4991 /* Don't close this window, let this be done from lisp code. */
4992 return NO;
4993}
4994
4995
4996- (NSSize)windowWillResize: (NSWindow *)sender toSize: (NSSize)frameSize
4997/* normalize frame to gridded text size */
4998{
4999 NSTRACE (windowWillResize);
5000/*fprintf (stderr,"Window will resize: %.0f x %.0f\n",frameSize.width,frameSize.height); */
5001
5002 cols = FRAME_PIXEL_WIDTH_TO_TEXT_COLS (emacsframe,
5003#ifdef NS_IMPL_GNUSTEP
5004 frameSize.width + 3);
5005#else
5006 frameSize.width);
5007#endif
5008 if (cols < MINWIDTH)
5009 cols = MINWIDTH;
5010 frameSize.width = FRAME_TEXT_COLS_TO_PIXEL_WIDTH (emacsframe, cols);
5011
5012 rows = FRAME_PIXEL_HEIGHT_TO_TEXT_LINES (emacsframe, frameSize.height
5013#ifdef NS_IMPL_GNUSTEP
5014 - FRAME_NS_TITLEBAR_HEIGHT (emacsframe) + 3
5015 - FRAME_NS_TOOLBAR_HEIGHT (emacsframe));
5016#else
5017 - FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
5018 - FRAME_NS_TOOLBAR_HEIGHT (emacsframe));
5019#endif
5020 if (rows < MINHEIGHT)
5021 rows = MINHEIGHT;
5022 frameSize.height = FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (emacsframe, rows)
5023 + FRAME_NS_TITLEBAR_HEIGHT (emacsframe)
5024 + FRAME_NS_TOOLBAR_HEIGHT (emacsframe);
5025#ifdef NS_IMPL_COCOA
5026 {
5027 /* this sets window title to have size in it; the wm does this under GS */
5028 NSRect r = [[self window] frame];
5029 if (r.size.height == frameSize.height && r.size.width == frameSize.width)
5030 {
5031 if (old_title != 0)
5032 {
5033 xfree (old_title);
5034 old_title = 0;
5035 }
5036 }
5037 else
5038 {
5039 char *size_title;
5040 NSWindow *window = [self window];
5041 if (old_title == 0)
5042 {
5043 const char *t = [[[self window] title] UTF8String];
5044 char *pos = strstr (t, " — ");
5045 if (pos)
5046 *pos = '\0';
5047 old_title = (char *) xmalloc (strlen (t) + 1);
5048 strcpy (old_title, t);
5049 }
5050 size_title = xmalloc (strlen (old_title) + 40);
5051 sprintf (size_title, "%s — (%d x %d)", old_title, cols, rows);
5052 [window setTitle: [NSString stringWithUTF8String: size_title]];
5053 [window display];
5054 xfree (size_title);
5055 }
5056 }
5057#endif /* NS_IMPL_COCOA */
5058/*fprintf (stderr," ...size became %.0f x %.0f (%d x %d)\n",frameSize.width,frameSize.height,cols,rows); */
5059
5060 return frameSize;
5061}
5062
5063
5064- (void)windowDidResize: (NSNotification *)notification
5065{
5066 NSWindow *theWindow = [notification object];
5067
5068#ifdef NS_IMPL_GNUSTEP
5069 /* in GNUstep, at least currently, it's possible to get a didResize
5070 without getting a willResize.. therefore we need to act as if we got
5071 the willResize now */
5072 NSSize sz = [theWindow frame].size;
5073 sz = [self windowWillResize: theWindow toSize: sz];
5074#endif /* NS_IMPL_GNUSTEP */
5075
5076 NSTRACE (windowDidResize);
5077/*fprintf (stderr,"windowDidResize: %.0f\n",[theWindow frame].size.height); */
5078
5079#ifdef NS_IMPL_COCOA
5080 if (old_title != 0)
5081 {
5082 xfree (old_title);
5083 old_title = 0;
5084 }
5085#endif /* NS_IMPL_COCOA */
5086
5087 if (cols > 0 && rows > 0)
5088 x_set_window_size (emacsframe, 0, cols, rows);
5089
5090 ns_send_appdefined (-1);
5091 [NSApp stopModal];
5092}
5093
5094
5095- (void)windowDidBecomeKey: (NSNotification *)notification
5096{
5097 int val = ns_lisp_to_cursor_type (get_frame_param (emacsframe, Qcursor_type));
5098 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe);
5099 struct frame *old_focus = dpyinfo->ns_focus_frame;
5100
5101 NSTRACE (windowDidBecomeKey);
5102
5103 if (emacsframe != old_focus)
5104 dpyinfo->ns_focus_frame = emacsframe;
5105 /*/last_mouse_frame = emacsframe;? */
5106
5107 if (val >= 0)
5108 {
5109 FRAME_NEW_CURSOR (emacsframe) = val;
5110/* x_update_cursor (emacsframe, 1); // will happen in ns_frame_rehighlight */
5111 }
5112
5113 ns_frame_rehighlight (emacsframe);
5114
5115 if (emacs_event)
5116 {
5117 emacs_event->kind = FOCUS_IN_EVENT;
5118 EV_TRAILER ((id)nil);
5119 }
5120}
5121
5122
5123- (void)windowDidResignKey: (NSNotification *)notification
5124{
5125 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe);
5126 NSTRACE (windowDidResignKey);
5127
5128 if (!windowClosing && [[self window] isVisible] == YES)
5129 {
5130 FRAME_NEW_CURSOR (emacsframe) = hollow_box;
5131 x_update_cursor (emacsframe, 1);
5132 FRAME_LAST_INACTIVE (emacsframe) = YES;
5133 }
5134
5135 if (dpyinfo->ns_highlight_frame == emacsframe)
5136 dpyinfo->ns_highlight_frame = 0;
5137 if (dpyinfo->ns_focus_frame == emacsframe)
5138 dpyinfo->ns_focus_frame = 0;
5139
5140 if (dpyinfo->mouse_face_mouse_frame == emacsframe)
5141 {
5142 clear_mouse_face (dpyinfo);
5143 dpyinfo->mouse_face_mouse_frame = 0;
5144 }
5145
5146 if (emacs_event)
5147 {
5148 [self deleteWorkingText];
5149 emacs_event->kind = FOCUS_IN_EVENT;
5150 EV_TRAILER ((id)nil);
5151 }
5152}
5153
5154
5155- (void)windowWillMiniaturize: sender
5156{
5157 NSTRACE (windowWillMiniaturize);
5158}
5159
5160
5161- (BOOL)isFlipped
5162{
5163 return YES;
5164}
5165
5166
5167- (BOOL)isOpaque
5168{
5169 return NO;
5170}
5171
5172
5173- initFrameFromEmacs: (struct frame *)f
5174{
5175 NSRect r, wr;
5176 Lisp_Object tem;
5177 NSWindow *win;
5178 NSButton *toggleButton;
5179 int vbextra = NS_SCROLL_BAR_WIDTH (f);
5180 NSSize sz;
5181 NSColor *col;
5182 NSString *name;
5183
5184 NSTRACE (initFrameFromEmacs);
5185
5186 windowClosing = NO;
5187 processingCompose = NO;
5188 scrollbarsNeedingUpdate = 0;
5189
5190/*fprintf (stderr,"init with %d, %d\n",f->text_cols, f->text_lines); */
5191
5192 r = NSMakeRect (0, 0, FRAME_TEXT_COLS_TO_PIXEL_WIDTH (f, f->text_cols),
5193 FRAME_TEXT_LINES_TO_PIXEL_HEIGHT (f, f->text_lines));
5194 [self initWithFrame: r];
5195
5196 FRAME_NS_VIEW (f) = self;
5197 emacsframe = f;
5198 old_title = 0;
5199
5200 win = [[EmacsWindow alloc]
5201 initWithContentRect: r
5202 styleMask: (NSResizableWindowMask |
5203 NSMiniaturizableWindowMask |
5204 NSClosableWindowMask)
5205 backing: NSBackingStoreBuffered
5206 defer: YES];
5207
5208 wr = [win frame];
5209 f->border_width = wr.size.width - r.size.width;
5210 FRAME_NS_TITLEBAR_HEIGHT (f) = wr.size.height - r.size.height;
5211
5212 [win setAcceptsMouseMovedEvents: YES];
5213 [win setDelegate: self];
5214 [win useOptimizedDrawing: YES];
5215
5216 sz.width = FRAME_COLUMN_WIDTH (f);
5217 sz.height = FRAME_LINE_HEIGHT (f);
5218 [win setResizeIncrements: sz];
5219
5220 [[win contentView] addSubview: self];
5221
5222 if (ns_drag_types)
5223 [self registerForDraggedTypes: ns_drag_types];
5224
5225 tem = f->name;
5226 name = [NSString stringWithUTF8String:
5227 NILP (tem) ? (unsigned char *)"Emacs" : XSTRING (tem)->data];
5228 [win setTitle: name];
5229
5230 /* toolbar support */
5231 toolbar = [[EmacsToolbar alloc] initForView: self withIdentifier:
5232 [NSString stringWithFormat: @"Emacs Frame %d",
5233 ns_window_num]];
5234 [win setToolbar: toolbar];
5235 [toolbar setVisible: NO];
5236#ifdef NS_IMPL_COCOA
5237 toggleButton = [win standardWindowButton: NSWindowToolbarButton];
5238 [toggleButton setTarget: self];
5239 [toggleButton setAction: @selector (toggleToolbar: )];
5240#endif
5241 FRAME_NS_TOOLBAR_HEIGHT (f) = 0;
5242
5243 tem = f->icon_name;
5244 if (!NILP (tem))
5245 [win setMiniwindowTitle:
5246 [NSString stringWithUTF8String: XSTRING (tem)->data]];
5247
5248 {
5249 NSScreen *screen = [win screen];
5250
5251 if (screen != 0)
5252 [win setFrameTopLeftPoint: NSMakePoint
5253 (IN_BOUND (-SCREENMAX, f->left_pos, SCREENMAX),
5254 IN_BOUND (-SCREENMAX,
5255 [screen frame].size.height - NS_TOP_POS (f), SCREENMAX))];
5256 }
5257
5258 [win makeFirstResponder: self];
5259
5260 col = ns_lookup_indexed_color (NS_FACE_BACKGROUND
5261 (FRAME_DEFAULT_FACE (emacsframe)), emacsframe);
5262 [win setBackgroundColor: col];
5263 if ([col alphaComponent] != 1.0)
5264 [win setOpaque: NO];
5265
5266 [self allocateGState];
5267
5268 ns_window_num++;
5269 return self;
5270}
5271
5272
5273- (void)windowDidMove: sender
5274{
5275 NSWindow *win = [self window];
5276 NSRect r = [win frame];
5277 NSScreen *screen = [win screen];
5278 NSRect sr = [screen frame];
5279
5280 NSTRACE (windowDidMove);
5281
5282 if (!emacsframe->output_data.ns)
5283 return;
5284 if (screen != nil)
5285 {
5286 emacsframe->left_pos = r.origin.x; /* - sr.origin.x; */
5287 emacsframe->top_pos = sr.size.height -
5288 (r.origin.y + r.size.height); /* + sr.origin.y; */
5289 }
5290}
5291
5292#ifdef NS_IMPL_COCOA
5293/* if we don't do this manually, the window will resize but not move */
5294- (BOOL)windowShouldZoom: (NSWindow *)sender toFrame: (NSRect)newFrame
5295{
5296 [[self window] setFrame: newFrame display: NO];
5297 return YES;
5298}
5299#endif
5300
5301/* Implement this to control size of frame on zoom.
5302- (NSRect)windowWillUseStandardFrame:(NSWindow *)sender
5303 defaultFrame:(NSRect)defaultFrame; */
5304
5305
5306- (void)windowDidDeminiaturize: sender
5307{
5308 NSTRACE (windowDidDeminiaturize);
5309 if (!emacsframe->output_data.ns)
5310 return;
5311 emacsframe->async_visible = 1;
5312 emacsframe->async_iconified = 0;
5313 windows_or_buffers_changed++;
5314
5315 if (emacs_event)
5316 {
5317 emacs_event->kind = ICONIFY_EVENT;
5318 EV_TRAILER ((id)nil);
5319 }
5320}
5321
5322
5323- (void)windowDidExpose: sender
5324{
5325 NSTRACE (windowDidExpose);
5326 if (!emacsframe->output_data.ns)
5327 return;
5328 emacsframe->async_visible = 1;
5329 SET_FRAME_GARBAGED (emacsframe);
5330
5331 if (send_appdefined)
5332 ns_send_appdefined (-1);
5333}
5334
5335
5336- (void)windowDidMiniaturize: sender
5337{
5338 NSTRACE (windowDidMiniaturize);
5339 if (!emacsframe->output_data.ns)
5340 return;
5341
5342 emacsframe->async_iconified = 1;
5343
5344 if (emacs_event)
5345 {
5346 emacs_event->kind = ICONIFY_EVENT;
5347 EV_TRAILER ((id)nil);
5348 }
5349}
5350
5351
5352- (void)mouseEntered: (NSEvent *)theEvent
5353{
5354 NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil];
5355 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (emacsframe);
5356 NSTRACE (mouseEntered);
5357
5358 last_mouse_movement_time = EV_TIMESTAMP (theEvent);
5359}
5360
5361
5362- (void)mouseExited: (NSEvent *)theEvent
5363{
5364 NSPoint p = [self convertPoint: [theEvent locationInWindow] fromView: nil];
5365 NSRect r;
5366 struct ns_display_info *dpyinfo =
5367 emacsframe ? FRAME_NS_DISPLAY_INFO (emacsframe) : NULL;
5368
5369 NSTRACE (mouseExited);
5370
5371 if (dpyinfo || !emacsframe)
5372 return;
5373
5374 last_mouse_movement_time = EV_TIMESTAMP (theEvent);
5375
5376 if (emacsframe == dpyinfo->mouse_face_mouse_frame)
5377 {
5378 clear_mouse_face (dpyinfo);
5379 dpyinfo->mouse_face_mouse_frame = 0;
5380 }
5381}
5382
5383
5384- menuDown: sender
5385{
5386 NSTRACE (menuDown);
5387 if (context_menu_value == -1)
5388 context_menu_value = [sender tag];
5389 else
5390 find_and_call_menu_selection (emacsframe, emacsframe->menu_bar_items_used,
5391 emacsframe->menu_bar_vector, [sender tag]);
5392 ns_send_appdefined (-1);
5393 return self;
5394}
5395
5396
5397- (EmacsToolbar *)toolbar
5398{
5399 return toolbar;
5400}
5401
5402
5403/* this gets called on toolbar button click */
5404- toolbarClicked: (id)item
5405{
5406 NSEvent *theEvent;
5407 int idx = [item tag] * TOOL_BAR_ITEM_NSLOTS;
5408
5409 NSTRACE (toolbarClicked);
5410
5411 if (!emacs_event)
5412 return self;
5413
5414 /* send first event (for some reason two needed) */
5415 theEvent =[[self window] currentEvent];
5416 emacs_event->kind = TOOL_BAR_EVENT;
5417 XSETFRAME (emacs_event->arg, emacsframe);
5418 EV_TRAILER (theEvent);
5419
5420 emacs_event->kind = TOOL_BAR_EVENT;
5421/* XSETINT (emacs_event->code, 0); */
5422 emacs_event->arg = AREF (emacsframe->tool_bar_items,
5423 idx + TOOL_BAR_ITEM_KEY);
5424 emacs_event->modifiers = EV_MODIFIERS (theEvent);
5425 EV_TRAILER (theEvent);
5426 return self;
5427}
5428
5429
5430- toggleToolbar: (id)sender
5431{
5432 Lisp_Object lispFrame;
5433 XSETFRAME (lispFrame, emacsframe);
5434 Feval (Fcons (intern ("ns-toggle-toolbar"), Fcons (lispFrame, Qnil)));
5435 SET_FRAME_GARBAGED (emacsframe);
5436 ns_send_appdefined (-1);
5437}
5438
5439
5440- (void)drawRect: (NSRect)rect
5441{
5442 int x = NSMinX (rect), y = NSMinY (rect);
5443 int width = NSWidth (rect), height = NSHeight (rect);
5444
5445 NSTRACE (drawRect);
5446
5447 if (!emacsframe || !emacsframe->output_data.ns)
5448 return;
5449
5450 if (!ns_in_resize)
5451 ns_clear_frame_area (emacsframe, x, y, width, height);
5452 expose_frame (emacsframe, x, y, width, height);
5453
5454 emacsframe->async_visible = 1;
5455 emacsframe->async_iconified = 0;
5456
5457/* SET_FRAME_GARBAGED (emacsframe);
5458 ns_send_appdefined (-1); */
5459}
5460
5461
5462/* NSDraggingDestination protocol methods. Actually this is not really a
5463 protocol, but a category of Object. O well... */
5464
5465-(unsigned int) draggingEntered: (id <NSDraggingInfo>) sender
5466{
5467 NSTRACE (draggingEntered);
5468 return NSDragOperationGeneric;
5469}
5470
5471
5472-(BOOL)prepareForDragOperation: (id <NSDraggingInfo>) sender
5473{
5474 return YES;
5475}
5476
5477
5478-(BOOL)performDragOperation: (id <NSDraggingInfo>) sender
5479{
5480 id pb;
5481 int x, y;
5482 NSString *type;
5483 NSEvent *theEvent = [[self window] currentEvent];
5484 NSPoint position;
5485
5486 NSTRACE (performDragOperation);
5487
5488 if (!emacs_event)
5489 return;
5490
5491 position = [self convertPoint: [sender draggingLocation] fromView: nil];
5492 x = lrint (position.x); y = lrint (position.y);
5493
5494 pb = [sender draggingPasteboard];
5495 type = [pb availableTypeFromArray: ns_drag_types];
5496 if (type == 0)
5497 {
5498 return NO;
5499 }
5500 else if ([type isEqualToString: NSFilenamesPboardType])
5501 {
5502 NSArray *files;
5503 NSEnumerator *fenum;
5504 NSString *file;
5505
5506 if (!(files = [pb propertyListForType: type]))
5507 return NO;
5508
5509 fenum = [files objectEnumerator];
5510 while ( (file = [fenum nextObject]) )
5511 {
5512 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
5513 emacs_event->code = KEY_NS_DRAG_FILE;
5514 XSETINT (emacs_event->x, x);
5515 XSETINT (emacs_event->y, y);
5516 ns_input_file = append2 (ns_input_file,
5517 build_string ([file UTF8String]));
5518 emacs_event->modifiers = EV_MODIFIERS (theEvent);
5519 EV_TRAILER (theEvent);
5520 }
5521 return YES;
5522 }
5523 else if ([type isEqualToString: NSURLPboardType])
5524 {
5525 NSString *file;
5526 NSURL *fileURL;
5527
5528 if (!(fileURL = [NSURL URLFromPasteboard: pb]) ||
5529 [fileURL isFileURL] == NO)
5530 return NO;
5531
5532 file = [fileURL path];
5533 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
5534 emacs_event->code = KEY_NS_DRAG_FILE;
5535 XSETINT (emacs_event->x, x);
5536 XSETINT (emacs_event->y, y);
5537 ns_input_file = append2 (ns_input_file, build_string ([file UTF8String]));
5538 emacs_event->modifiers = EV_MODIFIERS (theEvent);
5539 EV_TRAILER (theEvent);
5540 return YES;
5541 }
5542 else if ([type isEqualToString: NSStringPboardType]
5543 || [type isEqualToString: NSTabularTextPboardType])
5544 {
5545 NSString *data;
5546
5547 if (! (data = [pb stringForType: type]))
5548 return NO;
5549
5550 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
5551 emacs_event->code = KEY_NS_DRAG_TEXT;
5552 XSETINT (emacs_event->x, x);
5553 XSETINT (emacs_event->y, y);
5554 ns_input_text = build_string ([data UTF8String]);
5555 emacs_event->modifiers = EV_MODIFIERS (theEvent);
5556 EV_TRAILER (theEvent);
5557 return YES;
5558 }
5559 else if ([type isEqualToString: NSColorPboardType])
5560 {
5561 NSColor *c = [NSColor colorFromPasteboard: pb];
5562 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
5563 emacs_event->code = KEY_NS_DRAG_COLOR;
5564 XSETINT (emacs_event->x, x);
5565 XSETINT (emacs_event->y, y);
5566 ns_input_color = ns_color_to_lisp (c);
5567 emacs_event->modifiers = EV_MODIFIERS (theEvent);
5568 EV_TRAILER (theEvent);
5569 return YES;
5570 }
5571 else if ([type isEqualToString: NSFontPboardType])
5572 {
5573 /* impl based on GNUstep NSTextView.m */
5574 NSData *data = [pb dataForType: NSFontPboardType];
5575 NSDictionary *dict = [NSUnarchiver unarchiveObjectWithData: data];
5576 NSFont *font = [dict objectForKey: NSFontAttributeName];
5577 char fontSize[10];
5578
5579 if (font == nil)
5580 return NO;
5581
5582 emacs_event->kind = NON_ASCII_KEYSTROKE_EVENT;
5583 emacs_event->code = KEY_NS_CHANGE_FONT;
5584 XSETINT (emacs_event->x, x);
5585 XSETINT (emacs_event->y, y);
5586 ns_input_font = build_string ([[font fontName] UTF8String]);
5587 snprintf (fontSize, 10, "%f", [font pointSize]);
5588 ns_input_fontsize = build_string (fontSize);
5589 emacs_event->modifiers = EV_MODIFIERS (theEvent);
5590 EV_TRAILER (theEvent);
5591 return YES;
5592 }
5593 else
5594 {
5595 error ("Invalid data type in dragging pasteboard.");
5596 return NO;
5597 }
5598}
5599
5600
5601- validRequestorForSendType: (NSString *)typeSent
5602 returnType: (NSString *)typeReturned
5603{
5604 NSTRACE (validRequestorForSendType);
5605 if ([ns_send_types indexOfObjectIdenticalTo: typeSent] != NSNotFound &&
5606 [ns_return_types indexOfObjectIdenticalTo: typeSent] != NSNotFound)
5607 return self;
5608
5609 return [super validRequestorForSendType: typeSent
5610 returnType: typeReturned];
5611}
5612
5613
5614/* setMini =YES means set from internal (gives a finder icon), NO means set nil
5615 (gives a miniaturized version of the window); currently we use the latter for
5616 frames whose active buffer doesn't correspond to any file
5617 (e.g., '*scratch*') */
5618- setMiniwindowImage: (BOOL) setMini
5619{
5620 id image = [[self window] miniwindowImage];
5621 NSTRACE (setMiniwindowImage);
5622
5623 /* NOTE: under Cocoa miniwindowImage always returns nil, documentation
5624 about "AppleDockIconEnabled" notwithstanding, however the set message
5625 below has its effect nonetheless. */
5626 if (image != emacsframe->output_data.ns->miniimage)
5627 {
5628 if (image && [image isKindOfClass: [EmacsImage class]])
5629 [image release];
5630 [[self window] setMiniwindowImage:
5631 setMini ? emacsframe->output_data.ns->miniimage : nil];
5632 }
5633
5634 return self;
5635}
5636
5637
5638- (void) setRows: (int) r andColumns: (int) c
5639{
5640 rows = r;
5641 cols = c;
5642}
5643
5644@end /* EmacsView */
5645
5646
5647
5648/* ==========================================================================
5649
5650 EmacsWindow implementation
5651
5652 ========================================================================== */
5653
5654@implementation EmacsWindow
5655
5656/* called only on resize clicks by special case in EmacsApp-sendEvent */
5657- (void)mouseDown: (NSEvent *)theEvent
5658{
5659 if (ns_in_resize)
5660 {
5661 NSSize size = [[theEvent window] frame].size;
5662 grabOffset = [theEvent locationInWindow];
5663 grabOffset.x = size.width - grabOffset.x;
5664 }
5665 else
5666 [super mouseDown: theEvent];
5667}
5668
5669
5670/* stop resizing */
5671- (void)mouseUp: (NSEvent *)theEvent
5672{
5673 if (ns_in_resize)
5674 {
5675 struct frame *f = ((EmacsView *)[self delegate])->emacsframe;
5676 ns_in_resize = NO;
5677 ns_set_name_as_filename (f);
5678 [self display];
5679 ns_send_appdefined (-1);
5680 }
5681 else
5682 [super mouseUp: theEvent];
5683}
5684
5685
5686/* send resize events */
5687- (void)mouseDragged: (NSEvent *)theEvent
5688{
5689 if (ns_in_resize)
5690 {
5691 NSPoint p = [theEvent locationInWindow];
5692 NSSize size, vettedSize, origSize = [self frame].size;
5693
5694 size.width = p.x + grabOffset.x;
5695 size.height = origSize.height - p.y + grabOffset.y;
5696
5697 if (size.width == origSize.width && size.height == origSize.height)
5698 return;
5699
5700 vettedSize = [[self delegate] windowWillResize: self toSize: size];
5701 if (vettedSize.width != size.width || vettedSize.height != size.height)
5702 {
5703 [[NSNotificationCenter defaultCenter]
5704 postNotificationName: NSWindowDidResizeNotification
5705 object: self];
5706 }
5707 }
5708 else
5709 [super mouseDragged: theEvent];
5710}
5711
5712@end /* EmacsWindow */
5713
5714
5715/* ==========================================================================
5716
5717 EmacsScroller implementation
5718
5719 ========================================================================== */
5720
5721
5722@implementation EmacsScroller
5723
5724/* for repeat button push */
5725#define SCROLL_BAR_FIRST_DELAY 0.5
5726#define SCROLL_BAR_CONTINUOUS_DELAY (1.0 / 15)
5727
5728+ (float) scrollerWidth
5729{
5730 /* PENDING: if we want to allow variable widths, this is the place to do it,
5731 however neither GNUstep nor Cocoa support it very well */
5732 return [NSScroller scrollerWidth];
5733}
5734
5735
5736- initFrame: (NSRect )r window: (Lisp_Object)nwin
5737{
5738 NSTRACE (EmacsScroller_initFrame);
5739
5740 r.size.width = [EmacsScroller scrollerWidth];
5741 [super initWithFrame: r/*NSMakeRect (0, 0, 0, 0)*/];
5742 [self setContinuous: YES];
5743 [self setEnabled: YES];
5744
5745 /* Ensure auto resizing of scrollbars occurs within the emacs frame's view
5746 locked against the right, top and bottom edges. */
5747 [self setAutoresizingMask: NSViewMinXMargin | NSViewHeightSizable];
5748
5749 win = nwin;
5750 condemned = NO;
5751 pixel_height = NSHeight (r);
5752 min_portion = 20 / pixel_height;
5753
5754 frame = XFRAME (XWINDOW (win)->frame);
5755 if (FRAME_LIVE_P (frame))
5756 {
5757 int i;
5758 EmacsView *view = FRAME_NS_VIEW (frame);
5759 NSView *sview = [[view window] contentView];
5760 NSArray *subs = [sview subviews];
5761
5762 /* disable optimization stopping redraw of other scrollbars */
5763 view->scrollbarsNeedingUpdate = 0;
5764 for (i =[subs count]-1; i >= 0; i--)
5765 if ([[subs objectAtIndex: i] isKindOfClass: [EmacsScroller class]])
5766 view->scrollbarsNeedingUpdate++;
5767 [sview addSubview: self];
5768 }
5769
5770/* [self setFrame: r]; */
5771
5772 return self;
5773}
5774
5775
5776- (void)setFrame: (NSRect)newRect
5777{
5778 NSTRACE (EmacsScroller_setFrame);
5779/* BLOCK_INPUT; */
5780 pixel_height = NSHeight (newRect);
5781 min_portion = 20 / pixel_height;
5782 [super setFrame: newRect];
5783 [self display];
5784/* UNBLOCK_INPUT; */
5785}
5786
5787
5788- (void)dealloc
5789{
5790 NSTRACE (EmacsScroller_dealloc);
5791 if (!NILP (win))
5792 XWINDOW (win)->vertical_scroll_bar = Qnil;
5793 [super dealloc];
5794}
5795
5796
5797- condemn
5798{
5799 NSTRACE (condemn);
5800 condemned =YES;
5801 return self;
5802}
5803
5804
5805- reprieve
5806{
5807 NSTRACE (reprieve);
5808 condemned =NO;
5809 return self;
5810}
5811
5812
5813- judge
5814{
5815 NSTRACE (judge);
5816 if (condemned)
5817 {
5818 BLOCK_INPUT;
5819 /* ensure other scrollbar updates after deletion */
5820 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (frame);
5821 if (view != nil)
5822 view->scrollbarsNeedingUpdate++;
5823 [self removeFromSuperview];
5824 [self release];
5825 UNBLOCK_INPUT;
5826 }
5827 return self;
5828}
5829
5830
5831- (void)resetCursorRects
5832{
5833 NSRect visible = [self visibleRect];
5834 NSTRACE (resetCursorRects);
5835
5836 if (!NSIsEmptyRect (visible))
5837 [self addCursorRect: visible cursor: [NSCursor arrowCursor]];
5838 [[NSCursor arrowCursor] setOnMouseEntered: YES];
5839}
5840
5841
5842- (int) checkSamePosition: (int) position portion: (int) portion
5843 whole: (int) whole
5844{
5845 return em_position ==position && em_portion ==portion && em_whole ==whole
5846 && portion != whole; /* needed for resize empty buf */
5847}
5848
5849
5850- setPosition: (int)position portion: (int)portion whole: (int)whole
5851{
5852 NSTRACE (setPosition);
5853
5854 em_position = position;
5855 em_portion = portion;
5856 em_whole = whole;
5857
5858 if (portion >= whole)
5859 [self setFloatValue: 0.0 knobProportion: 1.0];
5860 else
5861 {
5862 float pos, por;
5863 portion = max ((float)whole*min_portion/pixel_height, portion);
5864 pos = (float)position / (whole - portion);
5865 por = (float)portion/whole;
5866 [self setFloatValue: pos knobProportion: por];
5867 }
5868#ifdef NS_IMPL_GNUSTEP
5869 [self display];
5870#endif
5871 return self;
5872}
5873
5874/* PENDING: unused at moment (see ns_mouse_position) at the moment because
5875 drag events will go directly to the EmacsScroller. Leaving in for now. */
5876-(void)getMouseMotionPart: (int *)part window: (Lisp_Object *)window
5877 x: (Lisp_Object *)x y: ( Lisp_Object *)y
5878{
5879 *part = last_hit_part;
5880 *window = win;
5881 XSETINT (*y, pixel_height);
5882 if ([self floatValue] > 0.999)
5883 XSETINT (*x, pixel_height);
5884 else
5885 XSETINT (*x, pixel_height * [self floatValue]);
5886}
5887
5888
5889/* set up emacs_event */
5890- (void) sendScrollEventAtLoc: (float)loc fromEvent: (NSEvent *)e
5891{
5892 if (!emacs_event)
5893 return;
5894
5895 emacs_event->part = last_hit_part;
5896 emacs_event->code = 0;
5897 emacs_event->modifiers = EV_MODIFIERS (e) | down_modifier;
5898 emacs_event->frame_or_window = win;
5899 emacs_event->timestamp = EV_TIMESTAMP (e);
5900 emacs_event->kind = SCROLL_BAR_CLICK_EVENT;
5901 emacs_event->arg = Qnil;
5902 XSETINT (emacs_event->x, loc * pixel_height);
5903 XSETINT (emacs_event->y, pixel_height-20);
5904
5905 n_emacs_events_pending++;
5906 kbd_buffer_store_event_hold (emacs_event, q_event_ptr);
5907 EVENT_INIT (*emacs_event);
5908 ns_send_appdefined (-1);
5909}
5910
5911
5912/* called manually thru timer to implement repeated button action w/hold-down */
5913- repeatScroll: (NSTimer *)scrollEntry
5914{
5915 NSEvent *e = [[self window] currentEvent];
5916 NSPoint p = [[self window] mouseLocationOutsideOfEventStream];
5917 BOOL inKnob = [self testPart: p] == NSScrollerKnob;
5918
5919 /* clear timer if need be */
5920 if (inKnob || [scroll_repeat_entry timeInterval] == SCROLL_BAR_FIRST_DELAY)
5921 {
5922 [scroll_repeat_entry invalidate];
5923 [scroll_repeat_entry release];
5924 scroll_repeat_entry = nil;
5925
5926 if (inKnob)
5927 return self;
5928
5929 scroll_repeat_entry =
5930 [[NSTimer scheduledTimerWithTimeInterval:
5931 SCROLL_BAR_CONTINUOUS_DELAY
5932 target: self
5933 selector: @selector (repeatScroll:)
5934 userInfo: 0
5935 repeats: YES]
5936 retain];
5937 }
5938
5939 [self sendScrollEventAtLoc: 0 fromEvent: e];
5940 return self;
5941}
5942
5943
5944/* Asynchronous mouse tracking for scroller. This allows us to dispatch
5945 mouseDragged events without going into a modal loop. */
5946- (void)mouseDown: (NSEvent *)e
5947{
5948 NSRect sr, kr;
5949 /* hitPart is only updated AFTER event is passed on */
5950 NSScrollerPart part = [self testPart: [e locationInWindow]];
5951 double inc = 0.0, loc, kloc, pos;
5952 int edge = 0;
5953
5954 NSTRACE (EmacsScroller_mouseDown);
5955
5956 switch (part)
5957 {
5958 case NSScrollerDecrementPage:
5959 last_hit_part = scroll_bar_above_handle; inc = -1.0; break;
5960 case NSScrollerIncrementPage:
5961 last_hit_part = scroll_bar_below_handle; inc = 1.0; break;
5962 case NSScrollerDecrementLine:
5963 last_hit_part = scroll_bar_up_arrow; inc = -0.1; break;
5964 case NSScrollerIncrementLine:
5965 last_hit_part = scroll_bar_down_arrow; inc = 0.1; break;
5966 case NSScrollerKnob:
5967 last_hit_part = scroll_bar_handle; break;
5968 case NSScrollerKnobSlot: /* GNUstep-only */
5969 last_hit_part = scroll_bar_move_ratio; break;
5970 default: /* NSScrollerNoPart? */
5971 fprintf (stderr, "EmacsScoller-mouseDown: unexpected part %d\n", part);
5972 return;
5973 }
5974
5975 if (inc != 0.0)
5976 {
5977 pos = 0; /* ignored */
5978
5979 /* set a timer to repeat, as we can't let superclass do this modally */
5980 scroll_repeat_entry =
5981 [[NSTimer scheduledTimerWithTimeInterval: 0.5
5982 target: self
5983 selector: @selector (repeatScroll:)
5984 userInfo: 0
5985 repeats: YES]
5986 retain];
5987 }
5988 else
5989 {
5990 /* handle, or on GNUstep possibly slot */
5991 NSEvent *fake_event;
5992
5993 /* compute float loc in slot and mouse offset on knob */
5994 sr = [self convertRect: [self rectForPart: NSScrollerKnobSlot]
5995 toView: nil];
5996 loc = NSHeight (sr) - ([e locationInWindow].y - NSMinY (sr));
5997 if (loc <= 0.0)
5998 {
5999 loc = 0.0;
6000 edge = -1;
6001 }
6002 else if (loc >= NSHeight (sr))
6003 {
6004 loc = NSHeight (sr);
6005 edge = 1;
6006 }
6007
6008 if (edge)
6009 kloc = 0.5 * edge;
6010 else
6011 {
6012 kr = [self convertRect: [self rectForPart: NSScrollerKnob]
6013 toView: nil];
6014 kloc = NSHeight (kr) - ([e locationInWindow].y - NSMinY (kr));
6015 }
6016 last_mouse_offset = kloc;
6017
6018 /* if knob, tell emacs a location offset by knob pos
6019 (to indicate top of handle) */
6020 if (part == NSScrollerKnob)
6021 pos = (loc - last_mouse_offset) / NSHeight (sr);
6022 else
6023 /* else this is a slot click on GNUstep: go straight there */
6024 pos = loc / NSHeight (sr);
6025
6026 /* send a fake mouse-up to super to preempt modal -trackKnob: mode */
6027 fake_event = [NSEvent mouseEventWithType: NSLeftMouseUp
6028 location: [e locationInWindow]
6029 modifierFlags: [e modifierFlags]
6030 timestamp: [e timestamp]
6031 windowNumber: [e windowNumber]
6032 context: [e context]
6033 eventNumber: [e eventNumber]
6034 clickCount: [e clickCount]
6035 pressure: [e pressure]];
6036 [super mouseUp: fake_event];
6037 }
6038
6039 if (part != NSScrollerKnob)
6040 [self sendScrollEventAtLoc: pos fromEvent: e];
6041}
6042
6043
6044/* Called as we manually track scroller drags, rather than superclass. */
6045- (void)mouseDragged: (NSEvent *)e
6046{
6047 NSRect sr;
6048 double loc, pos;
6049 int edge = 0;
6050
6051 NSTRACE (EmacsScroller_mouseDragged);
6052
6053 sr = [self convertRect: [self rectForPart: NSScrollerKnobSlot]
6054 toView: nil];
6055 loc = NSHeight (sr) - ([e locationInWindow].y - NSMinY (sr));
6056
6057 if (loc <= 0.0)
6058 {
6059 loc = 0.0;
6060 edge = -1;
6061 }
6062 else if (loc >= NSHeight (sr) + last_mouse_offset)
6063 {
6064 loc = NSHeight (sr) + last_mouse_offset;
6065 edge = 1;
6066 }
6067
6068 pos = /*(edge ? loc :*/ (loc - last_mouse_offset) / NSHeight (sr);
6069 [self sendScrollEventAtLoc: pos fromEvent: e];
6070}
6071
6072
6073- (void)mouseUp: (NSEvent *)e
6074{
6075 if (scroll_repeat_entry)
6076 {
6077 [scroll_repeat_entry invalidate];
6078 [scroll_repeat_entry release];
6079 scroll_repeat_entry = nil;
6080 }
6081 last_hit_part = 0;
6082}
6083
6084
6085/* treat scrollwheel events in the bar as though they were in the main window */
6086- (void) scrollWheel: (NSEvent *)theEvent
6087{
6088 EmacsView *view = (EmacsView *)FRAME_NS_VIEW (frame);
6089 [view mouseDown: theEvent];
6090}
6091
6092@end /* EmacsScroller */
6093
6094
6095
6096/* ==========================================================================
6097
6098 EmacsPrefsController implementation
6099
6100 ========================================================================== */
6101
6102
6103@implementation EmacsPrefsController
6104
6105/* in Tiger+, can just do [popup selectItemWithTag: tag]; */
6106static void selectItemWithTag (NSPopUpButton *popup, int tag)
6107{
6108 NSEnumerator *items = [[popup itemArray] objectEnumerator];
6109 NSMenuItem *item;
6110 while (item = [items nextObject])
6111 {
6112 if ([item tag] == tag)
6113 {
6114 [popup selectItem: item];
6115 return;
6116 }
6117 }
6118}
6119
6120- init
6121{
6122 [NSBundle loadNibNamed: @"preferences" owner: self];
6123 return self;
6124}
6125
6126
6127- (void) showForFrame: (struct frame *)f
6128{
6129 frame = f;
6130 [self setPanelFromValues];
6131 [prefsWindow makeKeyAndOrderFront: self];
6132 [prefsWindow display];
6133}
6134
6135
6136- (void) setPanelFromValues
6137{
6138 int cursorType =
6139 ns_lisp_to_cursor_type (get_frame_param (frame, Qcursor_type));
6140 prevExpandSpace = XFLOATINT (ns_expand_space);
6141 prevBlinkRate = NILP (ns_cursor_blink_rate)
6142 ? 0 : XFLOATINT (ns_cursor_blink_rate);
6143
6144#ifdef NS_IMPL_COCOA
6145 prevUseHighlightColor = ns_use_system_highlight_color;
6146#endif
6147
6148 [expandSpaceSlider setFloatValue: prevExpandSpace];
6149 [cursorBlinkSlider setFloatValue: prevBlinkRate];
6150 [cursorTypeMatrix selectCellWithTag: (cursorType == filled_box ? 1 :
6151 (cursorType == bar ? 2 :
6152 (cursorType == underscore ? 3 : 4)))];
6153 selectItemWithTag (alternateModMenu, lisp_to_mod (ns_alternate_modifier));
6154 selectItemWithTag (commandModMenu, lisp_to_mod (ns_command_modifier));
6155#ifdef NS_IMPL_COCOA
6156 selectItemWithTag (controlModMenu, lisp_to_mod (ns_control_modifier));
6157 selectItemWithTag (functionModMenu, lisp_to_mod (ns_function_modifier));
6158 [smoothFontsCheck setState: ns_antialias_text ? YES : NO];
6159 [useQuickdrawCheck setState: ns_use_qd_smoothing ? YES : NO];
6160 [useSysHiliteCheck setState: prevUseHighlightColor ? YES : NO];
6161#endif
6162}
6163
6164
6165- (void) setValuesFromPanel
6166{
6167 int cursorTag = [[cursorTypeMatrix selectedCell] tag];
6168 int altTag = [[alternateModMenu selectedItem] tag];
6169 int cmdTag = [[commandModMenu selectedItem] tag];
6170#ifdef NS_IMPL_COCOA
6171 int ctrlTag = [[controlModMenu selectedItem] tag];
6172 int fnTag = [[functionModMenu selectedItem] tag];
6173#endif
6174 float blinkRate = [cursorBlinkSlider floatValue];
6175 float expandSpace = [expandSpaceSlider floatValue];
6176 Lisp_Object old_cursor_blink_mode;
6177
6178 if (expandSpace != prevExpandSpace)
6179 {
6180 ns_expand_space = make_float (expandSpace);
6181 /* PENDING: more needed: store needed metrics in nsfont_info, update
6182 frame default font max_bounds and fontp, recompute faces */
6183/* FRAME_LINE_HEIGHT (frame) *= (expandSpace / prevExpandSpace);
6184 x_set_window_size (frame, 0, frame->text_cols, frame->text_lines); */
6185 prevExpandSpace = expandSpace;
6186 }
6187 if (blinkRate != prevBlinkRate)
6188 {
6189 old_cursor_blink_mode = ns_cursor_blink_mode;
6190 if (blinkRate == 0.0)
6191 {
6192 ns_cursor_blink_rate = Qnil;
6193 ns_cursor_blink_mode = Qnil;
6194 }
6195 else
6196 {
6197 ns_cursor_blink_rate = make_float (blinkRate);
6198 ns_cursor_blink_mode = Qt;
6199 }
6200 if (ns_cursor_blink_mode != old_cursor_blink_mode)
6201 Feval (Fcons (intern ("blink-cursor-mode"), Qnil));
6202
6203 if (blinkRate != 0.0 && prevBlinkRate != 0.0)
6204 { /* if changed rates, remove blink handler so change picked up */
6205 struct ns_display_info *dpyinfo = FRAME_NS_DISPLAY_INFO (frame);
6206 [cursor_blink_entry invalidate];
6207 [cursor_blink_entry release];
6208 cursor_blink_entry = 0;
6209 if (dpyinfo->ns_highlight_frame)
6210 {
6211 Lisp_Object tem =
6212 get_frame_param (dpyinfo->ns_highlight_frame, Qcursor_type);
6213 dpyinfo->ns_highlight_frame->output_data.ns->desired_cursor =
6214 ns_lisp_to_cursor_type (tem);
6215 }
6216 }
6217 prevBlinkRate = blinkRate;
6218 }
6219 FRAME_NEW_CURSOR (frame) =
6220 (cursorTag == 1 ? filled_box :
6221 (cursorTag == 2 ? bar :
6222 (cursorTag == 3 ? underscore : hollow_box)));
6223 store_frame_param (frame, Qcursor_type,
6224 ns_cursor_type_to_lisp (FRAME_NEW_CURSOR (frame)));
6225 ns_alternate_modifier = ns_mod_to_lisp (altTag);
6226 ns_command_modifier = ns_mod_to_lisp (cmdTag);
6227#ifdef NS_IMPL_COCOA
6228 ns_control_modifier = ns_mod_to_lisp (ctrlTag);
6229 ns_function_modifier = ns_mod_to_lisp (fnTag);
6230 ns_antialias_text = [smoothFontsCheck state];
6231 ns_use_qd_smoothing = [useQuickdrawCheck state];
6232 ns_use_system_highlight_color = [useSysHiliteCheck state];
6233 if (ns_use_system_highlight_color != prevUseHighlightColor)
6234 {
6235 prevUseHighlightColor = ns_use_system_highlight_color;
6236 if (ns_use_system_highlight_color == YES)
6237 {
6238 ns_selection_color = [[NSUserDefaults standardUserDefaults]
6239 stringForKey: @"AppleHighlightColor"];
6240 if (ns_selection_color == nil)
6241 ns_selection_color = NS_SELECTION_COLOR_DEFAULT;
6242 }
6243 else
6244 ns_selection_color = NS_SELECTION_COLOR_DEFAULT;
6245 }
6246#endif /* NS_IMPL_COCOA */
6247 Fcall_interactively (intern ("ns-save-preferences"), Qnil, Qnil);
6248}
6249
6250
6251/* buttons */
6252- (IBAction)cancel: (id)sender
6253{
6254 [prefsWindow close];
6255}
6256
6257
6258- (IBAction)ok: (id)sender
6259{
6260 [self setValuesFromPanel];
6261 [prefsWindow close];
6262}
6263
6264
6265- (IBAction)resetToDefaults: (id)sender
6266{
6267 ns_set_default_prefs ();
6268 [self setPanelFromValues];
6269}
6270
6271
6272- (IBAction)runHelp: (id)sender
6273{
6274 Feval (Fcons (intern ("info"),
6275 Fcons (build_string ("(ns-emacs)Preferences Panel"), Qnil)));
6276 SET_FRAME_GARBAGED (frame);
6277 ns_send_appdefined (-1);
6278}
6279
6280
6281- (IBAction)setColors: (id)sender
6282{
6283 Lisp_Object lispFrame;
6284 XSETFRAME (lispFrame, frame);
6285 Fns_popup_color_panel (lispFrame);
6286}
6287
6288
6289- (IBAction)setDefaultFont: (id)sender
6290{
6291 Lisp_Object lispFrame;
6292 XSETFRAME (lispFrame, frame);
6293 Fns_popup_font_panel (lispFrame);
6294}
6295
6296@end /* EmacsPrefsController */
6297
6298
6299
6300
6301/* ==========================================================================
6302
6303 Font-related functions; these used to be in nsfaces.m
6304
6305 ========================================================================== */
6306
6307
6308Lisp_Object
6309x_new_font (struct frame *f, Lisp_Object font_object, int fontset)
6310{
6311 struct font *font = XFONT_OBJECT (font_object);
6312
6313 if (fontset < 0)
6314 fontset = fontset_from_font (font_object);
6315 FRAME_FONTSET (f) = fontset;
6316
6317 if (FRAME_FONT (f) == font)
6318 /* This font is already set in frame F. There's nothing more to
6319 do. */
6320 return font_object;
6321
6322 FRAME_FONT (f) = font;
6323
6324 FRAME_BASELINE_OFFSET (f) = font->baseline_offset;
6325 FRAME_COLUMN_WIDTH (f) = font->average_width;
6326 FRAME_SPACE_WIDTH (f) = font->space_width;
6327 FRAME_LINE_HEIGHT (f) = font->height;
6328
6329 compute_fringe_widths (f, 1);
6330
6331 /* Compute the scroll bar width in character columns. */
6332 if (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) > 0)
6333 {
6334 int wid = FRAME_COLUMN_WIDTH (f);
6335 FRAME_CONFIG_SCROLL_BAR_COLS (f)
6336 = (FRAME_CONFIG_SCROLL_BAR_WIDTH (f) + wid - 1) / wid;
6337 }
6338 else
6339 {
6340 int wid = FRAME_COLUMN_WIDTH (f);
6341 FRAME_CONFIG_SCROLL_BAR_COLS (f) = (14 + wid - 1) / wid;
6342 }
6343
6344 /* Now make the frame display the given font. */
6345 if (FRAME_NS_WINDOW (f) != 0)
6346 x_set_window_size (f, 0, FRAME_COLS (f), FRAME_LINES (f));
6347
6348 return font_object;
6349}
6350
6351
6352Lisp_Object
6353ns_list_fonts (FRAME_PTR f, Lisp_Object pattern, int size, int maxnames)
6354/* --------------------------------------------------------------------------
6355 This is used by the xfaces system. It is expected to speak XLFD.
6356 -------------------------------------------------------------------------- */
6357{
6358 Lisp_Object list = Qnil,
6359 rpattern,
6360 key,
6361 tem,
6362 args[2];
6363 struct re_pattern_buffer *bufp;
6364 id fm = [NSFontManager sharedFontManager];
6365 NSEnumerator *fenum, *senum;
6366 NSArray *membInfo;
6367 NSString *fontname;
6368 const char *xlfdName;
6369 char *pattFam;
6370 char *patt;
6371 NSString *famName;
6372
6373 NSTRACE (ns_list_fonts);
6374
6375 CHECK_STRING (pattern);
6376 patt = XSTRING (pattern)->data;
6377
6378#if 0
6379/* temporary: for font_backend, we use fontsets, and when these are defined,
6380 the old XLFD-based system is used; eventually this will be replaced by
6381 backend code, but for now we allow specs that are just family names */
6382 /* if pattern is not XLFD, panic now */
6383 if (patt[0] != '-')
6384 error ("ns_list_fonts: X font name (XLFD) expected.");
6385
6386 /* if unicode encoding not requested, also die */
6387 if (!strstr (patt, "iso10646") && patt[strlen (patt)-3] != '*')
6388 return Qnil;
6389#endif /* 0 */
6390
6391 key = f ? Fcons (pattern, make_number (maxnames)) : Qnil;
6392 tem = f ? XCDR (FRAME_NS_DISPLAY_INFO (f)->name_list_element) : Qnil;
6393
6394 /* See if we cached the result for this particular query.
6395 The cache is an alist of the form:
6396 ((((PATTERN . MAXNAMES) FONTNAME) ...) ...)
6397 */
6398 if (f && !NILP (list = Fassoc (key, tem)))
6399 {
6400 list = Fcdr_safe (list);
6401 /* We have a cached list. Don't have to get the list again. */
6402 if (!NILP (list))
6403 return list;
6404 }
6405
6406 if (patt[0] != '-')
6407 pattFam = patt;
6408 else
6409 pattFam = ns_xlfd_to_fontname (patt);
6410 /*PENDING: '*' at beginning matches literally.. */
6411 if (pattFam[0] == '*')
6412 pattFam[0] = '.';
6413
6414 /* must start w/family name, but can have other stuff afterwards
6415 (usually bold and italic specifiers) */
6416 args[0] = build_string ("^");
6417 args[1] = build_string (pattFam);
6418 rpattern = Fconcat (2, args);
6419 bufp = compile_pattern (rpattern, 0, Vascii_canon_table, 0, 0);
6420
6421 list = Qnil;
6422 fenum = [[fm availableFontFamilies] objectEnumerator];
6423 while ( (famName = [fenum nextObject]) )
6424 {
6425 NSMutableString *tmp = [famName mutableCopy];
6426 const char *fname;
6427 NSRange r;
6428
6429 /* remove spaces, to look like postscript name */
6430 while ((r = [tmp rangeOfString: @" "]).location != NSNotFound)
6431 [tmp deleteCharactersInRange: r];
6432
6433 fname = [tmp UTF8String];
6434 int len = strlen (fname);
6435 BOOL foundItal;
6436 const char *synthItalFont;
6437
6438 if (re_search (bufp, fname, len, 0, len, 0) >= 0)
6439 {
6440 /* Found a family. Add all variants. If we have no italic variant,
6441 add a synthItal. */
6442 senum =[[fm availableMembersOfFontFamily: famName] objectEnumerator];
6443 foundItal = NO;
6444 synthItalFont = NULL;
6445 while (membInfo = [senum nextObject])
6446 {
6447 xlfdName =
6448 ns_fontname_to_xlfd ([[membInfo objectAtIndex: 0] UTF8String]);
6449 list = Fcons (build_string (xlfdName), list);
6450 if (!synthItalFont)
6451 {
6452 NSString *synthName =
6453 [[membInfo objectAtIndex: 0]
6454 stringByAppendingString: @"-synthItal"];
6455 synthItalFont = [synthName UTF8String];
6456 }
6457 else if ([[membInfo objectAtIndex: 3] intValue]
6458 & NSItalicFontMask)
6459 foundItal = YES;
6460 }
6461 if (foundItal == NO)
6462 {
6463 xlfdName = ns_fontname_to_xlfd (synthItalFont);
6464 list = Fcons (build_string (xlfdName), list);
6465 }
6466 }
6467 [tmp release];
6468 }
6469
6470 /* fallback */
6471 if (XFASTINT (Flength (list)) == 0)
6472 list = Fcons (build_string (ns_fontname_to_xlfd ("Monaco")), list);
6473
6474 /* store result in cache */
6475 if (f != NULL)
6476 XCDR_AS_LVALUE (FRAME_NS_DISPLAY_INFO (f)->name_list_element)
6477 = Fcons (Fcons (key, list),
6478 XCDR (FRAME_NS_DISPLAY_INFO (f)->name_list_element));
6479 return list;
6480}
6481
6482
6483/* XLFD: -foundry-family-weight-slant-swidth-adstyle-pxlsz-ptSz-resx-resy-spc-avgWidth-rgstry-encoding */
6484
6485const char *
6486ns_font_to_xlfd (NSFont *nsfont)
6487/* --------------------------------------------------------------------------
6488 Convert an NS font name to an X font name (XLFD).
6489 The string returned is temporarily allocated.
6490 -------------------------------------------------------------------------- */
6491{
6492 NSFontManager *mgr = [NSFontManager sharedFontManager];
6493 NSString *sname = [nsfont /*familyName*/fontName];
6494 char *famName = [sname UTF8String];
6495 char *weightStr = [mgr fontNamed: sname hasTraits: NSBoldFontMask] ?
6496 "bold" : "medium";
6497 char *slantStr = [mgr fontNamed: sname hasTraits: NSItalicFontMask] ?
6498 "i" : "r";
6499 int size = [nsfont pointSize];
6500 int aWidth = lrint (10.0 * [nsfont widthOfString: @"a"]);
6501 const char *xlfd;
6502 int i, len;
6503
6504 /* change '-' to '$' to avoid messing w/XLFD separator */
6505 for (len =strlen (famName), i =0; i<len; i++)
6506 if (famName[i] == '-')
6507 {
6508 famName[i] = '\0';
6509 break;
6510 }
6511
6512 xlfd = [[NSString stringWithFormat:
6513 @"-apple-%s-%s-%s-normal--%d-%d-75-75-m-%d-iso10646-1",
6514 famName, weightStr, slantStr, size, 10*size, aWidth]
6515 UTF8String];
6516/*fprintf (stderr, "converted '%s' to '%s'\n",name,xlfd); */
6517 return xlfd;
6518}
6519
6520const char *
6521ns_fontname_to_xlfd (const char *name)
6522/* --------------------------------------------------------------------------
6523 Convert an NS font name to an X font name (XLFD).
6524 Sizes are set to 0.
6525 The string returned is temporarily allocated.
6526 -------------------------------------------------------------------------- */
6527{
6528 char famName[180];
6529 char *weightStr = strcasestr (name, "bold") ? "bold" : "medium";
6530 char *slantStr = strcasestr (name, "italic") || strcasestr (name, "oblique")
6531 || strcasestr (name, "synthital") ? "i" : "r";
6532 int i, len;
6533 const char *xlfd;
6534
6535 /* change '-' to '$' to avoid messing w/XLFD separator, and ' ' to '_' */
6536 bzero (famName, 180);
6537 bcopy (name, famName, max (strlen (name), 179));
6538 for (len =strlen (famName), i =0; i<len; i++)
6539 {
6540 if (famName[i] == '-')
6541 famName[i] = '$';
6542 else if (famName[i] == ' ')
6543 famName[i] = '_';
6544 }
6545
6546 xlfd = [[NSString stringWithFormat:
6547 @"-apple-%s-%s-%s-normal--0-0-75-75-m-0-iso10646-1",
6548 famName, weightStr, slantStr]
6549 UTF8String];
6550/*fprintf (stderr, "converted '%s' to '%s'\n",name,xlfd); */
6551 return xlfd;
6552}
6553
6554
6555const char *
6556ns_xlfd_to_fontname (const char *xlfd)
6557/* --------------------------------------------------------------------------
6558 Convert an X font name (XLFD) to an NS font name.
6559 Only family is used.
6560 The string returned is temporarily allocated.
6561 -------------------------------------------------------------------------- */
6562{
6563 char *name = xmalloc (180);
6564 int i, len;
6565 const char *ret;
6566
6567 if (!strncmp (xlfd, "--", 2))
6568 sscanf (xlfd, "--%*[^-]-%[^-]179-", name);
6569 else
6570 sscanf (xlfd, "-%*[^-]-%[^-]179-", name);
6571
6572 /* stopgap for malformed XLFD input */
6573 if (strlen (name) == 0)
6574 strcpy (name, "Monaco");
6575
6576 /* undo hack in ns_fontname_to_xlfd, converting '$' to '-', '_' to ' '
6577 also uppercase after '-' or ' ' */
6578 name[0] = toupper (name[0]);
6579 for (len =strlen (name), i =0; i<len; i++)
6580 {
6581 if (name[i] == '$')
6582 {
6583 name[i] = '-';
6584 if (i+1<len)
6585 name[i+1] = toupper (name[i+1]);
6586 }
6587 else if (name[i] == '_')
6588 {
6589 name[i] = ' ';
6590 if (i+1<len)
6591 name[i+1] = toupper (name[i+1]);
6592 }
6593 }
6594/*fprintf (stderr, "converted '%s' to '%s'\n",xlfd,name); */
6595 ret = [[NSString stringWithUTF8String: name] UTF8String];
6596 xfree (name);
6597 return ret;
6598}
diff --git a/src/process.c b/src/process.c
index c2a20b92db1..87772f34f75 100644
--- a/src/process.c
+++ b/src/process.c
@@ -4877,8 +4877,12 @@ wait_reading_process_output (time_limit, microsecs, read_kbd, do_display,
4877 process_output_skip = 0; 4877 process_output_skip = 0;
4878 } 4878 }
4879#endif 4879#endif
4880 4880#ifdef HAVE_NS
4881 nfds = select (max (max (max_process_desc, max_keyboard_desc), 4881 nfds = ns_select
4882#else
4883 nfds = select
4884#endif
4885 (max (max (max_process_desc, max_keyboard_desc),
4882 max_gpm_desc) + 1, 4886 max_gpm_desc) + 1,
4883 &Available, 4887 &Available,
4884#ifdef NON_BLOCKING_CONNECT 4888#ifdef NON_BLOCKING_CONNECT
diff --git a/src/s/darwin.h b/src/s/darwin.h
index 4e282e99a9d..a290188d337 100644
--- a/src/s/darwin.h
+++ b/src/s/darwin.h
@@ -221,7 +221,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
221/* In Carbon, asynchronous I/O (using SIGIO) can't be used for window 221/* In Carbon, asynchronous I/O (using SIGIO) can't be used for window
222 events because they don't come from sockets, even though it works 222 events because they don't come from sockets, even though it works
223 fine on tty's. */ 223 fine on tty's. */
224#ifdef HAVE_CARBON 224/* This seems to help in Ctrl-G detection under Cocoa, however at the cost
225 of some quirks that may or may not bother a given user. */
226#if defined (HAVE_CARBON) || defined (COCOA_EXPERIMENTAL_CTRL_G)
225#define NO_SOCK_SIGIO 227#define NO_SOCK_SIGIO
226#endif 228#endif
227 229
@@ -247,8 +249,21 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
247 249
248/* Definitions for how to compile & link. */ 250/* Definitions for how to compile & link. */
249 251
250/* Indicate that we are compiling for Mac OS X. */ 252/* This is for the Carbon port. Under the NeXTstep port, this is still picked
253 up during preprocessing, but is undone in config.in. */
254#ifndef HAVE_NS
251#define C_SWITCH_SYSTEM -fpascal-strings -DMAC_OSX 255#define C_SWITCH_SYSTEM -fpascal-strings -DMAC_OSX
256#endif
257
258/* Link in the Carbon or AppKit lib. */
259#ifdef HAVE_NS
260/* PENDING: lresolv is here because configure when testing #undefs res_init,
261 a macro in /usr/include/resolv.h for res_9_init, not in stdc lib. */
262#define LIBS_MACGUI -framework AppKit -lresolv
263#define SYSTEM_PURESIZE_EXTRA 200000
264#define HEADERPAD_EXTRA 6C8
265#else
266#define HEADERPAD_EXTRA 690
252 267
253#ifdef HAVE_CARBON 268#ifdef HAVE_CARBON
254 269
@@ -274,16 +289,17 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
274 289
275/* Link in the Carbon lib. */ 290/* Link in the Carbon lib. */
276#ifdef HAVE_CARBON 291#ifdef HAVE_CARBON
277#define LIBS_CARBON -framework Carbon LIBS_IMAGE 292#define LIBS_MACGUI -framework Carbon LIBS_IMAGE
278#else 293#else
279#define LIBS_CARBON 294#define LIBS_MACGUI
280#endif 295#endif /* !HAVE_CARBON */
296#endif /* !HAVE_NS */
281 297
282/* The -headerpad option tells ld (see man page) to leave room at the 298/* The -headerpad option tells ld (see man page) to leave room at the
283 end of the header for adding load commands. Needed for dumping. 299 end of the header for adding load commands. Needed for dumping.
284 0x690 is the total size of 30 segment load commands (at 56 300 0x690 is the total size of 30 segment load commands (at 56
285 each). */ 301 each); under Cocoa 31 commands are required. */
286#define LD_SWITCH_SYSTEM_TEMACS -prebind LIBS_CARBON -Xlinker -headerpad -Xlinker 690 302#define LD_SWITCH_SYSTEM_TEMACS -prebind LIBS_MACGUI -Xlinker -headerpad -Xlinker HEADERPAD_EXTRA
287 303
288#define C_SWITCH_SYSTEM_TEMACS -Dtemacs 304#define C_SWITCH_SYSTEM_TEMACS -Dtemacs
289 305
@@ -312,6 +328,11 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
312#define OTHER_FILES macosx-app 328#define OTHER_FILES macosx-app
313#endif 329#endif
314 330
331/* PENDING: can this target be specified in a clearer way? */
332#ifdef HAVE_NS
333#define OTHER_FILES ns-app
334#endif
335
315 336
316/* Define the following so emacs symbols will not conflict with those 337/* Define the following so emacs symbols will not conflict with those
317 in the System framework. Otherwise -prebind will not work. */ 338 in the System framework. Otherwise -prebind will not work. */
diff --git a/src/syntax.c b/src/syntax.c
index 6dc63c25537..0c547c724c9 100644
--- a/src/syntax.c
+++ b/src/syntax.c
@@ -1,3 +1,4 @@
1#include <stdio.h>
1/* GNU Emacs routines to deal with syntax tables; also word and list parsing. 2/* GNU Emacs routines to deal with syntax tables; also word and list parsing.
2 Copyright (C) 1985, 1987, 1993, 1994, 1995, 1997, 1998, 1999, 2001, 3 Copyright (C) 1985, 1987, 1993, 1994, 1995, 1997, 1998, 1999, 2001,
3 2002, 2003, 2004, 2005, 2006, 2007, 2008 4 2002, 2003, 2004, 2005, 2006, 2007, 2008
@@ -298,6 +299,18 @@ char_quoted (charpos, bytepos)
298 register int quoted = 0; 299 register int quoted = 0;
299 int orig = charpos; 300 int orig = charpos;
300 301
302#ifdef HAVE_NS
303 /* For some reason keeps getting called w/both 1, then segfaulting
304 due to the definitions of DEC_BOTH and DEC_POS in character.h,
305 which lead to decrementing below initial address and then examining
306 character there. Need to investigate further.. */
307 if (charpos < 2 || bytepos < 2)
308 {
309 //fprintf(stderr,"Returning because charpos = %d, bytepos = %d\n",charpos, bytepos);
310 return 0;
311 }
312#endif
313
301 DEC_BOTH (charpos, bytepos); 314 DEC_BOTH (charpos, bytepos);
302 315
303 while (charpos >= beg) 316 while (charpos >= beg)
diff --git a/src/sysselect.h b/src/sysselect.h
index 24731e56f1f..e11d5ce04ac 100644
--- a/src/sysselect.h
+++ b/src/sysselect.h
@@ -18,11 +18,11 @@ You should have received a copy of the GNU General Public License
18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ 18along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
19 19
20#ifdef HAVE_SYS_SELECT_H 20#ifdef HAVE_SYS_SELECT_H
21#if defined (DARWIN) || defined (MAC_OSX) 21#if defined (DARWIN) || defined (MAC_OSX) || defined (NS_IMPL_COCOA)
22#undef init_process 22#undef init_process
23#endif 23#endif
24#include <sys/select.h> 24#include <sys/select.h>
25#if defined (DARWIN) || defined (MAC_OSX) 25#if defined (DARWIN) || defined (MAC_OSX) || defined (NS_IMPL_COCOA)
26#define init_process emacs_init_process 26#define init_process emacs_init_process
27#endif 27#endif
28#endif 28#endif
diff --git a/src/termhooks.h b/src/termhooks.h
index ae4fb361e36..1be9a1b45b9 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -318,6 +318,8 @@ extern struct tty_display_info *gpm_tty;
318 318
319 319
320struct mac_display_info; 320struct mac_display_info;
321struct ns_display_info;
322struct x_display_info;
321struct w32_display_info; 323struct w32_display_info;
322 324
323/* Terminal-local parameters. */ 325/* Terminal-local parameters. */
@@ -368,6 +370,7 @@ struct terminal
368 struct x_display_info *x; /* xterm.h */ 370 struct x_display_info *x; /* xterm.h */
369 struct w32_display_info *w32; /* w32term.h */ 371 struct w32_display_info *w32; /* w32term.h */
370 struct mac_display_info *mac; /* macterm.h */ 372 struct mac_display_info *mac; /* macterm.h */
373 struct ns_display_info *ns; /* nsterm.h */
371 } display_info; 374 } display_info;
372 375
373 376
diff --git a/src/terminal.c b/src/terminal.c
index afb350ba310..9ec14ca3c1f 100644
--- a/src/terminal.c
+++ b/src/terminal.c
@@ -397,6 +397,8 @@ possible return values. */)
397 return Qpc; 397 return Qpc;
398 case output_mac: 398 case output_mac:
399 return Qmac; 399 return Qmac;
400 case output_ns:
401 return Qns;
400 default: 402 default:
401 abort (); 403 abort ();
402 } 404 }
diff --git a/src/terminfo.c b/src/terminfo.c
index c1e1a36a833..968d338279b 100644
--- a/src/terminfo.c
+++ b/src/terminfo.c
@@ -24,7 +24,10 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
24 so that we do not need to conditionalize the places in Emacs 24 so that we do not need to conditionalize the places in Emacs
25 that set them. */ 25 that set them. */
26 26
27/* Causes a conflict on OS X 10.3 .*/
28#ifndef NS_IMPL_COCOA
27char *UP, *BC, PC; 29char *UP, *BC, PC;
30#endif
28 31
29/* Interface to curses/terminfo library. 32/* Interface to curses/terminfo library.
30 Turns out that all of the terminfo-level routines look 33 Turns out that all of the terminfo-level routines look
diff --git a/src/w32gui.h b/src/w32gui.h
index aea3582b3ef..d9f09e33134 100644
--- a/src/w32gui.h
+++ b/src/w32gui.h
@@ -21,66 +21,19 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
21#define EMACS_W32GUI_H 21#define EMACS_W32GUI_H
22#include <windows.h> 22#include <windows.h>
23 23
24#include "w32bdf.h"
24 25
25/* Emulate widget_value from ../lwlib/lwlib.h, modified for Windows. */ 26/* Emulate XCharStruct. */
26typedef void * XtPointer; 27typedef struct _XCharStruct
27typedef char Boolean;
28enum button_type
29{ 28{
30 BUTTON_TYPE_NONE, 29 short rbearing;
31 BUTTON_TYPE_TOGGLE, 30 short lbearing;
32 BUTTON_TYPE_RADIO 31 short width;
33}; 32 short ascent;
34typedef struct _widget_value 33 short descent;
35{ 34} XCharStruct;
36 /* name of widget */ 35
37 Lisp_Object lname; 36
38 char* name;
39 /* value (meaning depend on widget type) */
40 char* value;
41 /* keyboard equivalent. no implications for XtTranslations */
42 Lisp_Object lkey;
43 char* key;
44 /* Help string or nil if none.
45 GC finds this string through the frame's menu_bar_vector
46 or through menu_items. */
47 Lisp_Object help;
48 /* true if enabled */
49 Boolean enabled;
50 /* true if selected */
51 Boolean selected;
52 /* The type of a button. */
53 enum button_type button_type;
54 /* true if menu title */
55 Boolean title;
56#if 0
57 /* true if was edited (maintained by get_value) */
58 Boolean edited;
59 /* true if has changed (maintained by lw library) */
60 change_type change;
61 /* true if this widget itself has changed,
62 but not counting the other widgets found in the `next' field. */
63 change_type this_one_change;
64#endif
65 /* Contents of the sub-widgets, also selected slot for checkbox */
66 struct _widget_value* contents;
67 /* data passed to callback */
68 XtPointer call_data;
69 /* next one in the list */
70 struct _widget_value* next;
71#if 0
72 /* slot for the toolkit dependent part. Always initialize to NULL. */
73 void* toolkit_data;
74 /* tell us if we should free the toolkit data slot when freeing the
75 widget_value itself. */
76 Boolean free_toolkit_data;
77
78 /* we resource the widget_value structures; this points to the next
79 one on the free list if this one has been deallocated.
80 */
81 struct _widget_value *free_list;
82#endif
83} widget_value;
84/* Local memory management for menus. */ 37/* Local memory management for menus. */
85#define local_heap (GetProcessHeap ()) 38#define local_heap (GetProcessHeap ())
86#define local_alloc(n) (HeapAlloc (local_heap, HEAP_ZERO_MEMORY, (n))) 39#define local_alloc(n) (HeapAlloc (local_heap, HEAP_ZERO_MEMORY, (n)))
@@ -89,6 +42,30 @@ typedef struct _widget_value
89#define malloc_widget_value() ((widget_value *) local_alloc (sizeof (widget_value))) 42#define malloc_widget_value() ((widget_value *) local_alloc (sizeof (widget_value)))
90#define free_widget_value(wv) (local_free ((wv))) 43#define free_widget_value(wv) (local_free ((wv)))
91 44
45
46enum w32_char_font_type
47{
48 UNKNOWN_FONT = 0 /* FONT_TYPE_UNKNOWN */,
49 ANSI_FONT,
50 UNICODE_FONT,
51 BDF_1D_FONT,
52 BDF_2D_FONT
53};
54
55typedef struct W32FontStruct {
56 enum w32_char_font_type font_type;
57 TEXTMETRIC tm;
58 HFONT hfont;
59 bdffont *bdf;
60 int double_byte_p;
61 XCharStruct max_bounds;
62 XCharStruct scratch;
63 /* Only store info for ascii chars, if not fixed pitch. */
64 XCharStruct * per_char;
65} W32FontStruct;
66
67typedef struct W32FontStruct XFontStruct;
68
92/* Emulate X GC's by keeping color and font info in a structure. */ 69/* Emulate X GC's by keeping color and font info in a structure. */
93typedef struct _XGCValues 70typedef struct _XGCValues
94{ 71{
diff --git a/src/window.c b/src/window.c
index 43b96534427..753ed50a20f 100644
--- a/src/window.c
+++ b/src/window.c
@@ -49,6 +49,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
49#ifdef MAC_OS 49#ifdef MAC_OS
50#include "macterm.h" 50#include "macterm.h"
51#endif 51#endif
52#ifdef HAVE_NS
53#include "nsterm.h"
54#endif
52 55
53 56
54Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p; 57Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p;
diff --git a/src/xdisp.c b/src/xdisp.c
index d6a96c4a72f..43cfaee767b 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -199,6 +199,9 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
199#ifdef MAC_OS 199#ifdef MAC_OS
200#include "macterm.h" 200#include "macterm.h"
201#endif 201#endif
202#ifdef HAVE_NS
203#include "nsterm.h"
204#endif
202 205
203#include "font.h" 206#include "font.h"
204 207
@@ -209,7 +212,7 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
209#define INFINITY 10000000 212#define INFINITY 10000000
210 213
211#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ 214#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
212 || defined (USE_GTK) 215 || defined(HAVE_NS) || defined (USE_GTK)
213extern void set_frame_menubar P_ ((struct frame *f, int, int)); 216extern void set_frame_menubar P_ ((struct frame *f, int, int));
214extern int pending_menu_activation; 217extern int pending_menu_activation;
215#endif 218#endif
@@ -861,7 +864,7 @@ int display_hourglass_p;
861int hourglass_shown_p; 864int hourglass_shown_p;
862 865
863/* If non-null, an asynchronous timer that, when it expires, displays 866/* If non-null, an asynchronous timer that, when it expires, displays
864 an hourglass cursor on all frames. */ 867 an hourglass cursor on all frames. */
865struct atimer *hourglass_atimer; 868struct atimer *hourglass_atimer;
866 869
867/* Number of seconds to wait before displaying an hourglass cursor. */ 870/* Number of seconds to wait before displaying an hourglass cursor. */
@@ -9462,7 +9465,32 @@ x_consider_frame_title (frame)
9462 if (! STRINGP (f->name) 9465 if (! STRINGP (f->name)
9463 || SBYTES (f->name) != len 9466 || SBYTES (f->name) != len
9464 || bcmp (title, SDATA (f->name), len) != 0) 9467 || bcmp (title, SDATA (f->name), len) != 0)
9465 x_implicitly_set_name (f, make_string (title, len), Qnil); 9468 {
9469#ifdef HAVE_NS
9470 if (FRAME_NS_P (f))
9471 {
9472 if (!MINI_WINDOW_P(XWINDOW(f->selected_window)))
9473 {
9474 if (EQ (fmt, Qt))
9475 ns_set_name_as_filename (f);
9476 else
9477 x_implicitly_set_name (f, make_string(title, len),
9478 Qnil);
9479 }
9480 }
9481 else
9482#endif
9483 x_implicitly_set_name (f, make_string (title, len), Qnil);
9484 }
9485#ifdef HAVE_NS
9486 if (FRAME_NS_P (f))
9487 {
9488 /* do this also for frames with explicit names */
9489 ns_implicitly_set_icon_type(f);
9490 ns_set_doc_edited(f, Fbuffer_modified_p
9491 (XWINDOW (f->selected_window)->buffer), Qnil);
9492 }
9493#endif
9466 } 9494 }
9467} 9495}
9468 9496
@@ -9627,7 +9655,7 @@ update_menu_bar (f, save_match_data, hooks_run)
9627 if (FRAME_WINDOW_P (f) 9655 if (FRAME_WINDOW_P (f)
9628 ? 9656 ?
9629#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ 9657#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
9630 || defined (USE_GTK) 9658 || defined (HAVE_NS) || defined (USE_GTK)
9631 FRAME_EXTERNAL_MENU_BAR (f) 9659 FRAME_EXTERNAL_MENU_BAR (f)
9632#else 9660#else
9633 FRAME_MENU_BAR_LINES (f) > 0 9661 FRAME_MENU_BAR_LINES (f) > 0
@@ -9686,10 +9714,10 @@ update_menu_bar (f, save_match_data, hooks_run)
9686 9714
9687 /* Redisplay the menu bar in case we changed it. */ 9715 /* Redisplay the menu bar in case we changed it. */
9688#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ 9716#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
9689 || defined (USE_GTK) 9717 || defined (HAVE_NS) || defined (USE_GTK)
9690 if (FRAME_WINDOW_P (f)) 9718 if (FRAME_WINDOW_P (f))
9691 { 9719 {
9692#ifdef MAC_OS 9720#if defined (MAC_OS) || defined (HAVE_NS)
9693 /* All frames on Mac OS share the same menubar. So only 9721 /* All frames on Mac OS share the same menubar. So only
9694 the selected frame should be allowed to set it. */ 9722 the selected frame should be allowed to set it. */
9695 if (f == SELECTED_FRAME ()) 9723 if (f == SELECTED_FRAME ())
@@ -9700,11 +9728,11 @@ update_menu_bar (f, save_match_data, hooks_run)
9700 /* On a terminal screen, the menu bar is an ordinary screen 9728 /* On a terminal screen, the menu bar is an ordinary screen
9701 line, and this makes it get updated. */ 9729 line, and this makes it get updated. */
9702 w->update_mode_line = Qt; 9730 w->update_mode_line = Qt;
9703#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */ 9731#else /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || HAVE_NS || USE_GTK) */
9704 /* In the non-toolkit version, the menu bar is an ordinary screen 9732 /* In the non-toolkit version, the menu bar is an ordinary screen
9705 line, and this makes it get updated. */ 9733 line, and this makes it get updated. */
9706 w->update_mode_line = Qt; 9734 w->update_mode_line = Qt;
9707#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || USE_GTK) */ 9735#endif /* ! (USE_X_TOOLKIT || HAVE_NTGUI || MAC_OS || HAVE_NS || USE_GTK) */
9708 9736
9709 unbind_to (count, Qnil); 9737 unbind_to (count, Qnil);
9710 set_buffer_internal_1 (prev); 9738 set_buffer_internal_1 (prev);
@@ -9815,7 +9843,7 @@ update_tool_bar (f, save_match_data)
9815 struct frame *f; 9843 struct frame *f;
9816 int save_match_data; 9844 int save_match_data;
9817{ 9845{
9818#if defined (USE_GTK) || USE_MAC_TOOLBAR 9846#if defined (USE_GTK) || defined (HAVE_NS) || USE_MAC_TOOLBAR
9819 int do_update = FRAME_EXTERNAL_TOOL_BAR (f); 9847 int do_update = FRAME_EXTERNAL_TOOL_BAR (f);
9820#else 9848#else
9821 int do_update = WINDOWP (f->tool_bar_window) 9849 int do_update = WINDOWP (f->tool_bar_window)
@@ -10281,7 +10309,7 @@ redisplay_tool_bar (f)
10281 struct it it; 10309 struct it it;
10282 struct glyph_row *row; 10310 struct glyph_row *row;
10283 10311
10284#if defined (USE_GTK) || USE_MAC_TOOLBAR 10312#if defined (USE_GTK) || defined (HAVE_NS) || USE_MAC_TOOLBAR
10285 if (FRAME_EXTERNAL_TOOL_BAR (f)) 10313 if (FRAME_EXTERNAL_TOOL_BAR (f))
10286 update_frame_tool_bar (f); 10314 update_frame_tool_bar (f);
10287 return 0; 10315 return 0;
@@ -11501,6 +11529,10 @@ redisplay_internal (preserve_echo_area)
11501 /* Resized active mini-window to fit the size of what it is 11529 /* Resized active mini-window to fit the size of what it is
11502 showing if its contents might have changed. */ 11530 showing if its contents might have changed. */
11503 must_finish = 1; 11531 must_finish = 1;
11532/* PENDING: this causes all frames to be updated, which seems unnecessary
11533 since only the current frame needs to be considered. This function needs
11534 to be rewritten with two variables, consider_all_windows and
11535 consider_all_frames. */
11504 consider_all_windows_p = 1; 11536 consider_all_windows_p = 1;
11505 ++windows_or_buffers_changed; 11537 ++windows_or_buffers_changed;
11506 ++update_mode_lines; 11538 ++update_mode_lines;
@@ -13913,7 +13945,7 @@ redisplay_window (window, just_this_one_p)
13913 if (FRAME_WINDOW_P (f)) 13945 if (FRAME_WINDOW_P (f))
13914 { 13946 {
13915#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \ 13947#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) || defined (MAC_OS) \
13916 || defined (USE_GTK) 13948 || defined (HAVE_NS) || defined (USE_GTK)
13917 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f); 13949 redisplay_menu_p = FRAME_EXTERNAL_MENU_BAR (f);
13918#else 13950#else
13919 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0; 13951 redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0;
@@ -13928,7 +13960,7 @@ redisplay_window (window, just_this_one_p)
13928#ifdef HAVE_WINDOW_SYSTEM 13960#ifdef HAVE_WINDOW_SYSTEM
13929 if (FRAME_WINDOW_P (f)) 13961 if (FRAME_WINDOW_P (f))
13930 { 13962 {
13931#if defined (USE_GTK) || USE_MAC_TOOLBAR 13963#if defined (USE_GTK) || defined (HAVE_NS) || USE_MAC_TOOLBAR
13932 redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f); 13964 redisplay_tool_bar_p = FRAME_EXTERNAL_TOOL_BAR (f);
13933#else 13965#else
13934 redisplay_tool_bar_p = WINDOWP (f->tool_bar_window) 13966 redisplay_tool_bar_p = WINDOWP (f->tool_bar_window)
@@ -17072,6 +17104,11 @@ display_menu_bar (w)
17072 return; 17104 return;
17073#endif 17105#endif
17074 17106
17107#ifdef HAVE_NS
17108 if (FRAME_NS_P (f))
17109 return;
17110#endif /* HAVE_NS */
17111
17075#ifdef USE_X_TOOLKIT 17112#ifdef USE_X_TOOLKIT
17076 xassert (!FRAME_WINDOW_P (f)); 17113 xassert (!FRAME_WINDOW_P (f));
17077 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID); 17114 init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
@@ -22539,7 +22576,10 @@ display_and_set_cursor (w, on, hpos, vpos, x, y)
22539/* Switch the display of W's cursor on or off, according to the value 22576/* Switch the display of W's cursor on or off, according to the value
22540 of ON. */ 22577 of ON. */
22541 22578
22542static void 22579#ifndef HAVE_NS
22580static
22581#endif
22582void
22543update_window_cursor (w, on) 22583update_window_cursor (w, on)
22544 struct window *w; 22584 struct window *w;
22545 int on; 22585 int on;
diff --git a/src/xfaces.c b/src/xfaces.c
index 87a9006ae22..4bdcd1e406e 100644
--- a/src/xfaces.c
+++ b/src/xfaces.c
@@ -244,6 +244,17 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
244#define check_x check_mac 244#define check_x check_mac
245#endif /* MAC_OS */ 245#endif /* MAC_OS */
246 246
247#ifdef HAVE_NS
248#include "nsterm.h"
249#undef FRAME_X_DISPLAY_INFO
250#define FRAME_X_DISPLAY_INFO FRAME_NS_DISPLAY_INFO
251#define x_display_info ns_display_info
252#define FRAME_X_FONT_TABLE FRAME_NS_FONT_TABLE
253#define check_x check_ns
254#define x_list_fonts ns_list_fonts
255#define GCGraphicsExposures 0
256#endif /* HAVE_NS */
257
247#include "buffer.h" 258#include "buffer.h"
248#include "dispextern.h" 259#include "dispextern.h"
249#include "blockinput.h" 260#include "blockinput.h"
@@ -556,6 +567,10 @@ static void x_free_gc P_ ((struct frame *, GC));
556extern Lisp_Object w32_list_fonts P_ ((struct frame *, Lisp_Object, int, int)); 567extern Lisp_Object w32_list_fonts P_ ((struct frame *, Lisp_Object, int, int));
557#endif /* WINDOWSNT */ 568#endif /* WINDOWSNT */
558 569
570#ifdef HAVE_NS
571extern Lisp_Object ns_list_fonts P_ ((struct frame *, Lisp_Object, int, int));
572#endif /* HAVE_NS */
573
559#ifdef USE_X_TOOLKIT 574#ifdef USE_X_TOOLKIT
560static void x_update_menu_appearance P_ ((struct frame *)); 575static void x_update_menu_appearance P_ ((struct frame *));
561 576
@@ -766,6 +781,31 @@ x_free_gc (f, gc)
766 781
767#endif /* WINDOWSNT */ 782#endif /* WINDOWSNT */
768 783
784#ifdef HAVE_NS
785/* NS emulation of GCs */
786
787static INLINE GC
788x_create_gc (f, mask, xgcv)
789 struct frame *f;
790 unsigned long mask;
791 XGCValues *xgcv;
792{
793 GC gc = xmalloc (sizeof (*gc));
794 if (gc)
795 bcopy(xgcv, gc, sizeof(XGCValues));
796 return gc;
797}
798
799static INLINE void
800x_free_gc (f, gc)
801 struct frame *f;
802 GC gc;
803{
804 if (gc)
805 xfree (gc);
806}
807#endif /* HAVE_NS */
808
769#ifdef MAC_OS 809#ifdef MAC_OS
770/* Mac OS emulation of GCs */ 810/* Mac OS emulation of GCs */
771 811
@@ -872,8 +912,11 @@ init_frame_faces (f)
872#ifdef MAC_OS 912#ifdef MAC_OS
873 if (!FRAME_MAC_P (f) || FRAME_MAC_WINDOW (f)) 913 if (!FRAME_MAC_P (f) || FRAME_MAC_WINDOW (f))
874#endif 914#endif
915#ifdef HAVE_NS
916 if (!FRAME_NS_P (f) || FRAME_NS_WINDOW (f))
917#endif
875 if (!realize_basic_faces (f)) 918 if (!realize_basic_faces (f))
876 abort (); 919 abort ();
877} 920}
878 921
879 922
@@ -1269,6 +1312,10 @@ defined_color (f, color_name, color_def, alloc)
1269 else if (FRAME_MAC_P (f)) 1312 else if (FRAME_MAC_P (f))
1270 return mac_defined_color (f, color_name, color_def, alloc); 1313 return mac_defined_color (f, color_name, color_def, alloc);
1271#endif 1314#endif
1315#ifdef HAVE_NS
1316 else if (FRAME_NS_P (f))
1317 return ns_defined_color (f, color_name, color_def, alloc, 1);
1318#endif
1272 else 1319 else
1273 abort (); 1320 abort ();
1274} 1321}
@@ -1558,6 +1605,7 @@ free_face_colors (f, face)
1558 struct frame *f; 1605 struct frame *f;
1559 struct face *face; 1606 struct face *face;
1560{ 1607{
1608/* PENDING(NS): need to do something here? */
1561#ifdef HAVE_X_WINDOWS 1609#ifdef HAVE_X_WINDOWS
1562 if (face->colors_copied_bitwise_p) 1610 if (face->colors_copied_bitwise_p)
1563 return; 1611 return;
@@ -2754,7 +2802,7 @@ merge_face_ref (f, face_ref, to, err_msgs, named_merge_points)
2754 } 2802 }
2755 else if (EQ (keyword, QCstipple)) 2803 else if (EQ (keyword, QCstipple))
2756 { 2804 {
2757#ifdef HAVE_X_WINDOWS 2805#if defined(HAVE_X_WINDOWS) || defined(HAVE_NS)
2758 Lisp_Object pixmap_p = Fbitmap_spec_p (value); 2806 Lisp_Object pixmap_p = Fbitmap_spec_p (value);
2759 if (!NILP (pixmap_p)) 2807 if (!NILP (pixmap_p))
2760 to[LFACE_STIPPLE_INDEX] = value; 2808 to[LFACE_STIPPLE_INDEX] = value;
@@ -3262,14 +3310,14 @@ FRAME 0 means change the face on all frames, and change the default
3262 } 3310 }
3263 else if (EQ (attr, QCstipple)) 3311 else if (EQ (attr, QCstipple))
3264 { 3312 {
3265#ifdef HAVE_X_WINDOWS 3313#if defined(HAVE_X_WINDOWS) || defined(HAVE_NS)
3266 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value) 3314 if (!UNSPECIFIEDP (value) && !IGNORE_DEFFACE_P (value)
3267 && !NILP (value) 3315 && !NILP (value)
3268 && NILP (Fbitmap_spec_p (value))) 3316 && NILP (Fbitmap_spec_p (value)))
3269 signal_error ("Invalid stipple attribute", value); 3317 signal_error ("Invalid stipple attribute", value);
3270 old_value = LFACE_STIPPLE (lface); 3318 old_value = LFACE_STIPPLE (lface);
3271 LFACE_STIPPLE (lface) = value; 3319 LFACE_STIPPLE (lface) = value;
3272#endif /* HAVE_X_WINDOWS */ 3320#endif /* HAVE_X_WINDOWS || HAVE_NS */
3273 } 3321 }
3274 else if (EQ (attr, QCwidth)) 3322 else if (EQ (attr, QCwidth))
3275 { 3323 {