diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/ChangeLog | 131 | ||||
| -rw-r--r-- | src/Makefile.in | 99 | ||||
| -rw-r--r-- | src/blockinput.h | 12 | ||||
| -rw-r--r-- | src/callproc.c | 5 | ||||
| -rw-r--r-- | src/config.in | 52 | ||||
| -rw-r--r-- | src/dispextern.h | 15 | ||||
| -rw-r--r-- | src/dispnew.c | 18 | ||||
| -rw-r--r-- | src/emacs.c | 84 | ||||
| -rw-r--r-- | src/font.c | 16 | ||||
| -rw-r--r-- | src/font.h | 3 | ||||
| -rw-r--r-- | src/fontset.c | 8 | ||||
| -rw-r--r-- | src/frame.c | 41 | ||||
| -rw-r--r-- | src/frame.h | 18 | ||||
| -rw-r--r-- | src/fringe.c | 2 | ||||
| -rw-r--r-- | src/getloadavg.c | 7 | ||||
| -rw-r--r-- | src/image.c | 256 | ||||
| -rw-r--r-- | src/keyboard.c | 55 | ||||
| -rw-r--r-- | src/keyboard.h | 53 | ||||
| -rw-r--r-- | src/keymap.c | 68 | ||||
| -rw-r--r-- | src/lisp.h | 7 | ||||
| -rw-r--r-- | src/lread.c | 4 | ||||
| -rw-r--r-- | src/menu.c | 74 | ||||
| -rw-r--r-- | src/nsfns.m | 2668 | ||||
| -rw-r--r-- | src/nsgui.h | 208 | ||||
| -rw-r--r-- | src/nsimage.m | 480 | ||||
| -rw-r--r-- | src/nsmenu.m | 1948 | ||||
| -rw-r--r-- | src/nsselect.m | 624 | ||||
| -rw-r--r-- | src/nsterm.h | 827 | ||||
| -rw-r--r-- | src/nsterm.m | 6598 | ||||
| -rw-r--r-- | src/process.c | 8 | ||||
| -rw-r--r-- | src/s/darwin.h | 35 | ||||
| -rw-r--r-- | src/syntax.c | 13 | ||||
| -rw-r--r-- | src/sysselect.h | 4 | ||||
| -rw-r--r-- | src/termhooks.h | 3 | ||||
| -rw-r--r-- | src/terminal.c | 2 | ||||
| -rw-r--r-- | src/terminfo.c | 3 | ||||
| -rw-r--r-- | src/w32gui.h | 93 | ||||
| -rw-r--r-- | src/window.c | 3 | ||||
| -rw-r--r-- | src/xdisp.c | 68 | ||||
| -rw-r--r-- | src/xfaces.c | 56 |
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 @@ | |||
| 1 | 2008-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 | |||
| 1 | 2008-07-15 Jason Rumney <jasonr@gnu.org> | 132 | 2008-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. */ | ||
| 239 | FOUNDATION_LIB=gnu | ||
| 240 | GUI_LIB=gnu | ||
| 241 | include $(GNUSTEP_MAKEFILES)/Additional/base.make | ||
| 242 | include $(GNUSTEP_MAKEFILES)/Additional/gui.make | ||
| 243 | shared=no | ||
| 244 | #endif | ||
| 245 | |||
| 232 | #ifdef HAVE_DBUS | 246 | #ifdef HAVE_DBUS |
| 233 | DBUS_CFLAGS = @DBUS_CFLAGS@ | 247 | DBUS_CFLAGS = @DBUS_CFLAGS@ |
| 234 | DBUS_LIBS = @DBUS_LIBS@ | 248 | DBUS_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. */ |
| 251 | ALL_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@ | 265 | ALL_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 | ||
| 265 | XMENU_OBJ = xmenu.o | ||
| 266 | #endif | ||
| 267 | |||
| 268 | #ifdef HAVE_X_WINDOWS | 280 | #ifdef HAVE_X_WINDOWS |
| 269 | 281 | XMENU_OBJ = xmenu.o | |
| 270 | XOBJ= xterm.o xfns.o xselect.o xrdb.o fontset.o xsmfns.o fringe.o image.o | 282 | XOBJ= 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/ | |||
| 518 | emacsappsrc = ${srcdir}/../mac/Emacs.app/ | 530 | emacsappsrc = ${srcdir}/../mac/Emacs.app/ |
| 519 | #endif | 531 | #endif |
| 520 | 532 | ||
| 533 | #ifdef HAVE_NS | ||
| 534 | /* Object files for NeXTstep */ | ||
| 535 | NS_OBJ= nsterm.o nsfns.o nsmenu.o nsselect.o nsimage.o nsfont.o \ | ||
| 536 | fontset.o fringe.o image.o | ||
| 537 | emacsapp = $(PWD)/../nextstep/build/Emacs.app/ | ||
| 538 | FONT_DRIVERS = nsfont.o | ||
| 539 | #ifdef GNUSTEP | ||
| 540 | emacsappsrc = ${srcdir}/../nextstep/GNUstep/Emacs.base | ||
| 541 | emacsbindir = $(emacsapp) | ||
| 542 | #else | ||
| 543 | emacsappsrc = ${srcdir}/../nextstep/Cocoa/Emacs.base | ||
| 544 | emacsbindir = $(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 \ | |||
| 553 | SOME_MACHINE_OBJECTS = dosfns.o msdos.o \ | 580 | SOME_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 | |||
| 879 | LIBES = $(LOADLIBES) $(LIBS) $(LIBX) $(LIBSOUND) $(RSVG_LIBS) $(DBUS_LIBS) \ | 908 | LIBES = $(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 | ||
| 936 | temacs${EXEEXT}: $(LOCALCPP) $(STARTFILES) stamp-oldxmenu ${obj} ${otherobj} OBJECTS_MACHINE prefix-args${EXEEXT} | 968 | temacs${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 \ | |||
| 1080 | getloadavg.o: getloadavg.c $(config_h) | 1116 | getloadavg.o: getloadavg.c $(config_h) |
| 1081 | image.o: image.c frame.h window.h dispextern.h blockinput.h atimer.h \ | 1117 | image.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) |
| 1084 | indent.o: indent.c frame.h window.h indent.h buffer.h $(config_h) termchar.h \ | 1120 | indent.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 \ | |||
| 1089 | keyboard.o: keyboard.c termchar.h termhooks.h termopts.h buffer.h character.h \ | 1125 | keyboard.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) | ||
| 1093 | keymap.o: keymap.c buffer.h commands.h keyboard.h termhooks.h blockinput.h \ | 1130 | keymap.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 \ | |||
| 1155 | window.o: window.c indent.h commands.h frame.h window.h buffer.h termchar.h \ | 1192 | window.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) |
| 1159 | xdisp.o: xdisp.c macros.h commands.h process.h indent.h buffer.h dispextern.h \ | 1196 | xdisp.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 |
| 1164 | xfaces.o: xfaces.c dispextern.h frame.h xterm.h buffer.h blockinput.h \ | 1201 | xfaces.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) |
| 1168 | xfns.o: xfns.c buffer.h frame.h window.h keyboard.h xterm.h dispextern.h \ | 1205 | xfns.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 | ||
| 1319 | abbrev.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 | ||
| 1323 | nsfns.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) | ||
| 1326 | nsmenu.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) | ||
| 1329 | nsterm.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) | ||
| 1333 | nsselect.o: nsselect.m blockinput.h nsterm.h nsgui.h frame.h $(config_h) | ||
| 1334 | nsimage.o: nsimage.m nsterm.h | ||
| 1335 | nsfont.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 | |||
| 1345 | ns-app: ${emacsapp} ${emacsbindir}Emacs | ||
| 1346 | |||
| 1347 | #endif /* HAVE_NS */ | ||
| 1280 | 1348 | ||
| 1281 | mostlyclean: | 1349 | mostlyclean: |
| 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 |
| 1286 | clean: mostlyclean | 1354 | clean: 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 | ||
| 60 | extern int pending_atimers; | 60 | extern 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; | |||
| 69 | typedef XImagePtr XImagePtr_or_DC; | 69 | typedef 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 */ | ||
| 75 | typedef struct ns_display_info Display_Info; | ||
| 76 | typedef Pixmap XImagePtr; | ||
| 77 | typedef 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; | |||
| 193 | extern int inherited_pgroup; | 198 | extern 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. */ |
| 198 | int display_arg; | 203 | int 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. */ |
| 58 | Lisp_Object Qascii_0, Qiso8859_1, Qiso10646_1, Qunicode_bmp, Qunicode_sip; | 62 | Lisp_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. */ |
| 62 | static Lisp_Object null_vector; | 72 | static 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_ (()); | |||
| 4948 | extern void syms_of_bdffont P_ (()); | 4958 | extern void syms_of_bdffont P_ (()); |
| 4949 | extern void syms_of_w32font P_ (()); | 4959 | extern void syms_of_w32font P_ (()); |
| 4950 | extern void syms_of_atmfont P_ (()); | 4960 | extern void syms_of_atmfont P_ (()); |
| 4961 | extern void syms_of_nsfont P_ (()); | ||
| 4951 | 4962 | ||
| 4952 | void | 4963 | void |
| 4953 | syms_of_font () | 4964 | syms_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 |
| 861 | extern struct font_driver atmfont_driver; | 861 | extern struct font_driver atmfont_driver; |
| 862 | #endif /* MAC_OS */ | 862 | #endif /* MAC_OS */ |
| 863 | #ifdef HAVE_NS | ||
| 864 | extern 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; | |||
| 72 | Lisp_Object Qframep, Qframe_live_p; | 75 | Lisp_Object Qframep, Qframe_live_p; |
| 73 | Lisp_Object Qicon, Qmodeline; | 76 | Lisp_Object Qicon, Qmodeline; |
| 74 | Lisp_Object Qonly; | 77 | Lisp_Object Qonly; |
| 75 | Lisp_Object Qx, Qw32, Qmac, Qpc; | 78 | Lisp_Object Qx, Qw32, Qmac, Qpc, Qns; |
| 76 | Lisp_Object Qvisible; | 79 | Lisp_Object Qvisible; |
| 77 | Lisp_Object Qdisplay_type; | 80 | Lisp_Object Qdisplay_type; |
| 78 | Lisp_Object Qbackground_mode; | 81 | Lisp_Object Qbackground_mode; |
| @@ -203,7 +206,8 @@ DEFUN ("framep", Fframep, Sframep, 1, 1, 0, | |||
| 203 | Value is t for a termcap frame (a character-only terminal), | 206 | Value 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. |
| 208 | See also `frame-live-p'. */) | 212 | See 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 | |||
| 4540 | handles focus, since there is no way in general for Emacs to find out | 4569 | handles focus, since there is no way in general for Emacs to find out |
| 4541 | automatically. */); | 4570 | automatically. */); |
| 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 | ||
| 56 | enum vertical_scroll_bar_type | 57 | enum 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; | |||
| 1044 | extern Lisp_Object Qheight, Qwidth; | 1050 | extern Lisp_Object Qheight, Qwidth; |
| 1045 | extern Lisp_Object Qminibuffer, Qmodeline; | 1051 | extern Lisp_Object Qminibuffer, Qmodeline; |
| 1046 | extern Lisp_Object Qonly; | 1052 | extern Lisp_Object Qonly; |
| 1047 | extern Lisp_Object Qx, Qw32, Qmac, Qpc; | 1053 | extern Lisp_Object Qx, Qw32, Qmac, Qpc, Qns; |
| 1048 | extern Lisp_Object Qvisible; | 1054 | extern Lisp_Object Qvisible; |
| 1049 | extern Lisp_Object Qdisplay_type; | 1055 | extern Lisp_Object Qdisplay_type; |
| 1050 | extern Lisp_Object Qbackground_mode; | 1056 | extern 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; | |||
| 482 | static Lisp_Object *fringe_faces; | 482 | static Lisp_Object *fringe_faces; |
| 483 | static int max_fringe_bitmaps; | 483 | static int max_fringe_bitmaps; |
| 484 | 484 | ||
| 485 | static int max_used_fringe_bitmap = MAX_STANDARD_FRINGE_BITMAPS; | 485 | int 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) |
| 471 | static processor_set_t default_set; | 471 | static processor_set_t default_set; |
| 472 | static int getloadavg_initialized; | 472 | static 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 | |||
| 141 | typedef 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 | ||
| 136 | Lisp_Object Vx_bitmap_file_path; | 162 | Lisp_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 | ||
| 433 | XImagePtr | ||
| 434 | XGetImage (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 */ | ||
| 444 | unsigned long | ||
| 445 | XGetPixel (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 */ | ||
| 452 | void | ||
| 453 | XPutPixel (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 | ||
| 3896 | static int xpm_image_p P_ ((Lisp_Object object)); | 4021 | static int xpm_image_p P_ ((Lisp_Object object)); |
| 3897 | static int xpm_load P_ ((struct frame *f, struct image *img)); | 4022 | static int xpm_load P_ ((struct frame *f, struct image *img)); |
| 3898 | static int xpm_valid_color_symbols_p P_ ((Lisp_Object)); | 4023 | static 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 | ||
| 3926 | Lisp_Object Qxpm; | 4051 | Lisp_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) |
| 4253 | int | 4378 | int |
| @@ -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 | ||
| 7063 | static int | ||
| 7064 | png_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 | ||
| 6925 | static int jpeg_image_p P_ ((Lisp_Object object)); | 7083 | static int jpeg_image_p P_ ((Lisp_Object object)); |
| 6926 | static int jpeg_load P_ ((struct frame *f, struct image *img)); | 7084 | static 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 | ||
| 7653 | static int | ||
| 7654 | jpeg_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 | ||
| 7504 | static int tiff_image_p P_ ((Lisp_Object object)); | 7672 | static int tiff_image_p P_ ((Lisp_Object object)); |
| 7505 | static int tiff_load P_ ((struct frame *f, struct image *img)); | 7673 | static 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 | ||
| 8088 | static int | ||
| 8089 | tiff_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 | ||
| 7929 | static int gif_image_p P_ ((Lisp_Object object)); | 8107 | static int gif_image_p P_ ((Lisp_Object object)); |
| 7930 | static int gif_load P_ ((struct frame *f, struct image *img)); | 8108 | static 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 | ||
| 8735 | static int | ||
| 8736 | gif_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" | ||
| 85 | extern Lisp_Object Qsuper; | ||
| 86 | #endif | ||
| 87 | |||
| 83 | #ifndef USE_CRT_DLL | 88 | #ifndef USE_CRT_DLL |
| 84 | extern int errno; | 89 | extern 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, | |||
| 7305 | void | 7312 | void |
| 7306 | handle_async_input () | 7313 | handle_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 | |||
| 330 | typedef void * XtPointer; | ||
| 331 | typedef unsigned char Boolean; | ||
| 332 | |||
| 333 | /* Definitions copied from lwlib.h */ | ||
| 334 | |||
| 335 | enum 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. */ | ||
| 344 | typedef 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 | ||
| 112 | extern Lisp_Object Voverriding_local_map; | 112 | extern Lisp_Object Voverriding_local_map; |
| 113 | 113 | ||
| 114 | #ifdef HAVE_NS | ||
| 115 | extern 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. */ |
| 115 | static Lisp_Object where_is_cache; | 119 | static 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 | ||
| 2629 | int 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. */ | ||
| 2648 | static int | ||
| 2649 | modifier_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 | ||
| 2837 | If optional 3rd arg FIRSTONLY is non-nil, return the first key sequence found, | 2884 | If optional 3rd arg FIRSTONLY is non-nil, return the first key sequence found, |
| 2838 | rather than a list of all possible key sequences. | 2885 | rather than a list of all possible key sequences. |
| 2886 | #ifdef HAVE_NS | ||
| 2887 | If FIRSTONLY is the symbol for a modifier key, return the first binding found, | ||
| 2888 | that is modified by that modifier only. | ||
| 2889 | #endif | ||
| 2839 | If FIRSTONLY is the symbol `non-ascii', return the first binding found, | 2890 | If FIRSTONLY is the symbol `non-ascii', return the first binding found, |
| 2840 | no matter what it is. | 2891 | no matter what it is. |
| 2841 | If FIRSTONLY has another non-nil value, prefer sequences of ASCII characters | 2892 | If 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. */ | ||
| 968 | Lisp_Object | ||
| 969 | find_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 | ||
| 961 | void | 1029 | void |
| 962 | syms_of_menu () | 1030 | syms_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 | |||
| 6 | This file is part of GNU Emacs. | ||
| 7 | |||
| 8 | GNU Emacs is free software; you can redistribute it and/or modify | ||
| 9 | it under the terms of the GNU General Public License as published by | ||
| 10 | the Free Software Foundation; either version 3, or (at your option) | ||
| 11 | any later version. | ||
| 12 | |||
| 13 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 14 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 15 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 16 | GNU General Public License for more details. | ||
| 17 | |||
| 18 | You should have received a copy of the GNU General Public License | ||
| 19 | along with GNU Emacs; see the file COPYING. If not, write to | ||
| 20 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
| 21 | Boston, MA 02110-1301, USA. | ||
| 22 | |||
| 23 | Originally by Carl Edman | ||
| 24 | Updated by Christian Limpach (chris@nice.ch) | ||
| 25 | OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com) | ||
| 26 | MacOSX/Aqua port by Christophe de Dinechin (descubes@earthlink.net) | ||
| 27 | GNUstep 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 | ||
| 47 | int fns_trace_num = 1; | ||
| 48 | #define NSTRACE(x) fprintf (stderr, "%s:%d: [%d] " #x "\n", \ | ||
| 49 | __FILE__, __LINE__, ++fns_trace_num) | ||
| 50 | #else | ||
| 51 | #define NSTRACE(x) | ||
| 52 | #endif | ||
| 53 | |||
| 54 | #ifdef HAVE_NS | ||
| 55 | |||
| 56 | extern NSArray *ns_send_types, *ns_return_types, *ns_drag_types; | ||
| 57 | |||
| 58 | extern Lisp_Object Qforeground_color; | ||
| 59 | extern Lisp_Object Qbackground_color; | ||
| 60 | extern Lisp_Object Qcursor_color; | ||
| 61 | extern Lisp_Object Qinternal_border_width; | ||
| 62 | extern Lisp_Object Qvisibility; | ||
| 63 | extern Lisp_Object Qcursor_type; | ||
| 64 | extern Lisp_Object Qicon_type; | ||
| 65 | extern Lisp_Object Qicon_name; | ||
| 66 | extern Lisp_Object Qicon_left; | ||
| 67 | extern Lisp_Object Qicon_top; | ||
| 68 | extern Lisp_Object Qleft; | ||
| 69 | extern Lisp_Object Qright; | ||
| 70 | extern Lisp_Object Qtop; | ||
| 71 | extern Lisp_Object Qdisplay; | ||
| 72 | extern Lisp_Object Qvertical_scroll_bars; | ||
| 73 | extern Lisp_Object Qauto_raise; | ||
| 74 | extern Lisp_Object Qauto_lower; | ||
| 75 | extern Lisp_Object Qbox; | ||
| 76 | extern Lisp_Object Qscroll_bar_width; | ||
| 77 | extern Lisp_Object Qx_resource_name; | ||
| 78 | extern Lisp_Object Qface_set_after_frame_default; | ||
| 79 | extern Lisp_Object Qunderline, Qundefined; | ||
| 80 | extern Lisp_Object Qheight, Qminibuffer, Qname, Qonly, Qwidth; | ||
| 81 | extern Lisp_Object Qunsplittable, Qmenu_bar_lines, Qbuffer_predicate, Qtitle; | ||
| 82 | |||
| 83 | Lisp_Object Qnone; | ||
| 84 | Lisp_Object Qns_frame_parameter; | ||
| 85 | Lisp_Object Qbuffered; | ||
| 86 | Lisp_Object Qfontsize; | ||
| 87 | |||
| 88 | /* hack for OS X file panels */ | ||
| 89 | char panelOK = 0; | ||
| 90 | |||
| 91 | /* Alist of elements (REGEXP . IMAGE) for images of icons associated | ||
| 92 | to frames.*/ | ||
| 93 | Lisp_Object Vns_icon_type_alist; | ||
| 94 | |||
| 95 | EmacsTooltip *ns_tooltip; | ||
| 96 | |||
| 97 | /* Need forward declaration here to preserve organizational integrity of file */ | ||
| 98 | Lisp_Object Fns_open_connection (Lisp_Object, Lisp_Object, Lisp_Object); | ||
| 99 | |||
| 100 | extern BOOL ns_in_resize; | ||
| 101 | |||
| 102 | |||
| 103 | /* ========================================================================== | ||
| 104 | |||
| 105 | Internal utility functions | ||
| 106 | |||
| 107 | ========================================================================== */ | ||
| 108 | |||
| 109 | |||
| 110 | void | ||
| 111 | check_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. */ | ||
| 119 | int | ||
| 120 | have_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. */ | ||
| 128 | static FRAME_PTR | ||
| 129 | check_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. */ | ||
| 149 | static struct ns_display_info * | ||
| 150 | check_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 | |||
| 187 | static id | ||
| 188 | ns_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 | |||
| 203 | static NSScreen * | ||
| 204 | ns_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. */ | ||
| 249 | struct ns_display_info * | ||
| 250 | ns_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 | |||
| 280 | static Lisp_Object | ||
| 281 | interpret_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 | |||
| 338 | static void | ||
| 339 | ns_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 | |||
| 363 | static void | ||
| 364 | ns_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 | |||
| 420 | static void | ||
| 421 | ns_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 | |||
| 443 | static void | ||
| 444 | ns_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 | |||
| 492 | static void | ||
| 493 | ns_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 | |||
| 541 | static void | ||
| 542 | ns_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. */ | ||
| 589 | static void | ||
| 590 | ns_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. */ | ||
| 601 | void | ||
| 602 | x_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. */ | ||
| 622 | static void | ||
| 623 | ns_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 | |||
| 636 | void | ||
| 637 | ns_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 | |||
| 705 | void | ||
| 706 | ns_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 | |||
| 718 | static void | ||
| 719 | ns_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 */ | ||
| 749 | void | ||
| 750 | x_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 */ | ||
| 757 | static void | ||
| 758 | ns_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 */ | ||
| 790 | void | ||
| 791 | x_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 | |||
| 797 | void | ||
| 798 | ns_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 | |||
| 868 | static void | ||
| 869 | ns_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) */ | ||
| 909 | int | ||
| 910 | XParseGeometry (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? */ | ||
| 919 | int | ||
| 920 | ns_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 | |||
| 937 | Lisp_Object | ||
| 938 | ns_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 | |||
| 952 | static void | ||
| 953 | ns_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 ;) */ | ||
| 975 | static void | ||
| 976 | ns_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 | |||
| 982 | static void | ||
| 983 | ns_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 */ | ||
| 1015 | frame_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 | |||
| 1050 | DEFUN ("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\ | ||
| 1053 | Return an Emacs frame object representing the X window.\n\ | ||
| 1054 | ALIST is an alist of frame parameters.\n\ | ||
| 1055 | If the parameters specify that the frame should not have a minibuffer,\n\ | ||
| 1056 | and do not specify a specific minibuffer window to use,\n\ | ||
| 1057 | then `default-minibuffer-frame' must be a frame whose minibuffer can\n\ | ||
| 1058 | be 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 | |||
| 1351 | DEFUN ("ns-focus-frame", Fns_focus_frame, Sns_focus_frame, 1, 1, 0, | ||
| 1352 | doc: /* Set the input focus to FRAME. | ||
| 1353 | FRAME nil means use the selected frame. */) | ||
| 1354 | (frame) | ||
| 1355 | Lisp_Object frame; | ||
| 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 | |||
| 1372 | DEFUN ("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 | |||
| 1382 | DEFUN ("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 | |||
| 1407 | DEFUN ("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 | |||
| 1428 | DEFUN ("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\ | ||
| 1430 | args are slightly different. Nil returned if no selection made.\n\ | ||
| 1431 | Set 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 | |||
| 1491 | DEFUN ("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\ | ||
| 1493 | If 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 | |||
| 1518 | DEFUN ("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\ | ||
| 1520 | If OWNER is nil, Emacs is assumed.\n\ | ||
| 1521 | If 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 | |||
| 1549 | DEFUN ("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\ | ||
| 1551 | from 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 | |||
| 1574 | DEFUN ("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\ | ||
| 1578 | a 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 | |||
| 1589 | DEFUN ("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\ | ||
| 1591 | The optional argument DISPLAY specifies which display to ask about.\n\ | ||
| 1592 | DISPLAY should be either a frame or a display name (a string).\n\ | ||
| 1593 | If 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 | |||
| 1606 | DEFUN ("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\ | ||
| 1608 | See also the function `ns-server-vendor'.\n\n\ | ||
| 1609 | The optional argument DISPLAY specifies which display to ask about.\n\ | ||
| 1610 | DISPLAY should be either a frame or a display name (a string).\n\ | ||
| 1611 | If 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 | |||
| 1620 | DEFUN ("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\ | ||
| 1622 | The optional argument DISPLAY specifies which display to ask about.\n\ | ||
| 1623 | DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\ | ||
| 1624 | If 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 | |||
| 1637 | DEFUN ("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\ | ||
| 1640 | The optional argument DISPLAY specifies which display to ask about.\n\ | ||
| 1641 | DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\ | ||
| 1642 | If 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 | |||
| 1652 | DEFUN ("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\ | ||
| 1655 | The optional argument DISPLAY specifies which display to ask about.\n\ | ||
| 1656 | DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\ | ||
| 1657 | If 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 | |||
| 1667 | DEFUN ("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\ | ||
| 1670 | The value may be `buffered', `retained', or `non-retained'.\n\ | ||
| 1671 | The optional argument DISPLAY specifies which display to ask about.\n\ | ||
| 1672 | DISPLAY should be either a frame, display name (a string), or terminal ID.\n\ | ||
| 1673 | If omitted or nil, that stands for the selected frame's display.\n\ | ||
| 1674 | Under 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 | |||
| 1694 | DEFUN ("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\ | ||
| 1697 | The value is one of the symbols `static-gray', `gray-scale',\n\ | ||
| 1698 | `static-color', `pseudo-color', `true-color', or `direct-color'.\n\n\ | ||
| 1699 | The optional argument DISPLAY specifies which display to ask about.\n\ | ||
| 1700 | DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\ | ||
| 1701 | If 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 | |||
| 1725 | DEFUN ("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\ | ||
| 1728 | The optional argument DISPLAY specifies which display to ask about.\n\ | ||
| 1729 | DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\ | ||
| 1730 | If omitted or nil, that stands for the selected frame's display.\n\ | ||
| 1731 | Under 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 | |||
| 1752 | DEFUN ("ns-open-connection", Fns_open_connection, Sns_open_connection, | ||
| 1753 | 1, 3, 0, "Open a connection to a NS server.\n\ | ||
| 1754 | DISPLAY is the name of the display to connect to.\n\ | ||
| 1755 | Optional 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 | |||
| 1791 | DEFUN ("ns-close-connection", Fns_close_connection, Sns_close_connection, | ||
| 1792 | 1, 1, 0, "Close the connection to the current NS server.\n\ | ||
| 1793 | The second argument DISPLAY is currently ignored, but nil would stand for\n\ | ||
| 1794 | the 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 | |||
| 1808 | DEFUN ("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 | |||
| 1822 | DEFUN ("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 | |||
| 1831 | DEFUN ("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\ | ||
| 1833 | Otherwise if emacs is hidden, it is unhidden.\n\ | ||
| 1834 | If ON is equal to 'activate, emacs is unhidden and becomes\n\ | ||
| 1835 | the 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 | |||
| 1853 | DEFUN ("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 | |||
| 1863 | DEFUN ("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\ | ||
| 1865 | If optional arguments FACE and FRAME are specified, return only fonts\n\ | ||
| 1866 | the same size as FACE on FRAME.\n\ | ||
| 1867 | If optional argument MAX is specified, return at most MAX matches.\n\ | ||
| 1868 | \n\ | ||
| 1869 | PATTERN is a regular expression; FACE is a face name - a symbol.\n\ | ||
| 1870 | \n\ | ||
| 1871 | The return value is a list of strings, suitable as arguments to\n\ | ||
| 1872 | set-face-font.\n\ | ||
| 1873 | \n\ | ||
| 1874 | The 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 | |||
| 1920 | DEFUN ("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\ | ||
| 1922 | XLFD string. If string contains fontset' and not 'fontset-startup' it is\n\ | ||
| 1923 | left 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 | |||
| 1940 | DEFUN ("ns-list-colors", Fns_list_colors, Sns_list_colors, 0, 1, 0, | ||
| 1941 | "Return a list of all available colors.\n\ | ||
| 1942 | The 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 | |||
| 1981 | DEFUN ("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 | |||
| 2031 | DEFUN ("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\ | ||
| 2033 | Returns 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 | |||
| 2060 | DEFUN ("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 */ | ||
| 2083 | FRAME_PTR | ||
| 2084 | check_x_frame (Lisp_Object frame) | ||
| 2085 | { | ||
| 2086 | return check_ns_frame (frame); | ||
| 2087 | } | ||
| 2088 | |||
| 2089 | /* 23: added, due to call in frame.c */ | ||
| 2090 | struct ns_display_info * | ||
| 2091 | check_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 */ | ||
| 2098 | void | ||
| 2099 | x_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 */ | ||
| 2110 | const char * | ||
| 2111 | x_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 | |||
| 2132 | Lisp_Object | ||
| 2133 | x_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 | |||
| 2146 | int | ||
| 2147 | x_pixel_width (struct frame *f) | ||
| 2148 | { | ||
| 2149 | return FRAME_PIXEL_WIDTH (f); | ||
| 2150 | } | ||
| 2151 | |||
| 2152 | |||
| 2153 | int | ||
| 2154 | x_pixel_height (struct frame *f) | ||
| 2155 | { | ||
| 2156 | return FRAME_PIXEL_HEIGHT (f); | ||
| 2157 | } | ||
| 2158 | |||
| 2159 | |||
| 2160 | int | ||
| 2161 | x_char_width (struct frame *f) | ||
| 2162 | { | ||
| 2163 | return FRAME_COLUMN_WIDTH (f); | ||
| 2164 | } | ||
| 2165 | |||
| 2166 | |||
| 2167 | int | ||
| 2168 | x_char_height (struct frame *f) | ||
| 2169 | { | ||
| 2170 | return FRAME_LINE_HEIGHT (f); | ||
| 2171 | } | ||
| 2172 | |||
| 2173 | |||
| 2174 | int | ||
| 2175 | x_screen_planes (struct frame *f) | ||
| 2176 | { | ||
| 2177 | return FRAME_NS_DISPLAY_INFO (f)->n_planes; | ||
| 2178 | } | ||
| 2179 | |||
| 2180 | |||
| 2181 | void | ||
| 2182 | x_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 | |||
| 2197 | DEFUN ("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\ | ||
| 2199 | The 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 | |||
| 2209 | DEFUN ("xw-color-values", Fns_color_values, Sns_color_values, 1, 2, 0, | ||
| 2210 | "Return a description of the color named COLOR.\n\ | ||
| 2211 | The value is a list of integer RGBA values--(RED GREEN BLUE ALPHA).\n\ | ||
| 2212 | These values appear to range from 0 to 65280; white is (65280 65280 65280 0).\n\ | ||
| 2213 | The 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 | |||
| 2238 | DEFUN ("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\ | ||
| 2240 | The optional argument DISPLAY specifies which display to ask about.\n\ | ||
| 2241 | DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\ | ||
| 2242 | If 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 | |||
| 2258 | DEFUN ("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\ | ||
| 2261 | Note that color displays do support shades of gray.\n\ | ||
| 2262 | The optional argument DISPLAY specifies which display to ask about.\n\ | ||
| 2263 | DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\ | ||
| 2264 | If 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 | |||
| 2276 | DEFUN ("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\ | ||
| 2279 | The optional argument DISPLAY specifies which display to ask about.\n\ | ||
| 2280 | DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\ | ||
| 2281 | If 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 | |||
| 2290 | DEFUN ("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\ | ||
| 2293 | The optional argument DISPLAY specifies which display to ask about.\n\ | ||
| 2294 | DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\ | ||
| 2295 | If 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 | |||
| 2303 | DEFUN ("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 \ | ||
| 2306 | usable screen area excluding reserved areas such as the Mac menu and doc, or \ | ||
| 2307 | the Windows task bar.\n \ | ||
| 2308 | The optional argument DISPLAY specifies which display to ask about.\n\ | ||
| 2309 | DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\ | ||
| 2310 | If 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 | |||
| 2329 | DEFUN ("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\ | ||
| 2332 | The optional argument DISPLAY specifies which display to ask about.\n\ | ||
| 2333 | DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\ | ||
| 2334 | If 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 | |||
| 2344 | DEFUN ("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\ | ||
| 2347 | The optional argument DISPLAY specifies which display to ask about.\n\ | ||
| 2348 | DISPLAY should be either a frame, a display name (a string), or terminal ID.\n\ | ||
| 2349 | If 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. */ | ||
| 2362 | Lisp_Object tip_frame; | ||
| 2363 | |||
| 2364 | /*PENDING: move to xdisp or similar */ | ||
| 2365 | static void | ||
| 2366 | compute_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 | |||
| 2417 | DEFUN ("x-show-tip", Fx_show_tip, Sx_show_tip, 1, 6, 0, | ||
| 2418 | doc: /* Show STRING in a "tooltip" window on frame FRAME. | ||
| 2419 | A tooltip window is a small window displaying a string. | ||
| 2420 | |||
| 2421 | FRAME nil or omitted means use the selected frame. | ||
| 2422 | |||
| 2423 | PARMS is an optional list of frame parameters which can be used to | ||
| 2424 | change the tooltip's appearance. | ||
| 2425 | |||
| 2426 | Automatically hide the tooltip after TIMEOUT seconds. TIMEOUT nil | ||
| 2427 | means use the default timeout of 5 seconds. | ||
| 2428 | |||
| 2429 | If the list of frame parameters PARMS contains a `left' parameter, | ||
| 2430 | the tooltip is displayed at that x-position. Otherwise it is | ||
| 2431 | displayed at the mouse position, with offset DX added (default is 5 if | ||
| 2432 | DX isn't specified). Likewise for the y-position; if a `top' frame | ||
| 2433 | parameter is specified, it determines the y-position of the tooltip | ||
| 2434 | window, otherwise it is displayed at the mouse position, with offset | ||
| 2435 | DY added (default is -10). | ||
| 2436 | |||
| 2437 | A tooltip's maximum size is specified by `x-max-tooltip-size'. | ||
| 2438 | Text 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 | |||
| 2493 | DEFUN ("x-hide-tip", Fx_hide_tip, Sx_hide_tip, 0, 0, 0, | ||
| 2494 | doc: /* Hide the current tooltip window, if there is any. | ||
| 2495 | Value 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 | |||
| 2512 | void | ||
| 2513 | syms_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\ | ||
| 2528 | frames. If the title of a frame matches REGEXP, then IMAGE.tiff is\n\ | ||
| 2529 | selected as the image of the icon representing the frame when it's\n\ | ||
| 2530 | miniaturized. If an element is t, then Emacs tries to select an icon\n\ | ||
| 2531 | based on the filetype of the visited file.\n\ | ||
| 2532 | \n\ | ||
| 2533 | The images have to be installed in a folder called English.lproj in the\n\ | ||
| 2534 | Emacs.app folder. You have to restart Emacs after installing new icons.\n\ | ||
| 2535 | \n\ | ||
| 2536 | Example: 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\ | ||
| 2543 | When you miniaturize a Group, Summary or Article frame, Gnus.tiff will\n\ | ||
| 2544 | be 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 | |||
| 4 | This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | GNU Emacs is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 3, or (at your option) | ||
| 9 | any later version. | ||
| 10 | |||
| 11 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with GNU Emacs; see the file COPYING. If not, write to | ||
| 18 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
| 19 | Boston, 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. */ | ||
| 64 | typedef 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__ | ||
| 75 | typedef unsigned short unichar; | ||
| 76 | #endif | ||
| 77 | typedef 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? */ | ||
| 93 | typedef 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 | |||
| 106 | typedef XGCValues * GC; | ||
| 107 | |||
| 108 | #define GCForeground 0x01 | ||
| 109 | #define GCBackground 0x02 | ||
| 110 | #define GCFont 0x03 | ||
| 111 | |||
| 112 | #ifdef __OBJC__ | ||
| 113 | typedef id Pixmap; | ||
| 114 | #else | ||
| 115 | typedef void *Pixmap; | ||
| 116 | #endif | ||
| 117 | |||
| 118 | #ifdef __OBJC__ | ||
| 119 | typedef NSCursor * Cursor; | ||
| 120 | #else | ||
| 121 | typedef void *Cursor; | ||
| 122 | #endif | ||
| 123 | |||
| 124 | #define No_Cursor (0) | ||
| 125 | |||
| 126 | #ifdef __OBJC__ | ||
| 127 | typedef NSColor * Color; | ||
| 128 | #else | ||
| 129 | typedef void * Color; | ||
| 130 | #endif | ||
| 131 | typedef int Window; | ||
| 132 | typedef int Display; | ||
| 133 | |||
| 134 | /* Xism */ | ||
| 135 | typedef Lisp_Object XrmDatabase; | ||
| 136 | |||
| 137 | |||
| 138 | /* 23: some sort of attempt to normalize rectangle handling.. seems a bit much | ||
| 139 | for what is accomplished */ | ||
| 140 | typedef struct { | ||
| 141 | int x, y; | ||
| 142 | unsigned width, height; | ||
| 143 | } XRectangle; | ||
| 144 | |||
| 145 | #ifndef __OBJC__ | ||
| 146 | typedef struct _NSPoint { float x, y; } NSPoint; | ||
| 147 | typedef struct _NSSize { float width, height; } NSSize; | ||
| 148 | typedef 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 | |||
| 5 | This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | GNU Emacs is free software; you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation; either version 3, or (at your option) | ||
| 10 | any later version. | ||
| 11 | |||
| 12 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with GNU Emacs; see the file COPYING. If not, write to | ||
| 19 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
| 20 | Boston, MA 02110-1301, USA. | ||
| 21 | |||
| 22 | Originally by Carl Edman | ||
| 23 | Updated by Christian Limpach (chris@nice.ch) | ||
| 24 | OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com) | ||
| 25 | MacOSX/Aqua port by Christophe de Dinechin (descubes@earthlink.net) | ||
| 26 | GNUstep 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 | |||
| 36 | extern Lisp_Object QCfile, QCdata; | ||
| 37 | |||
| 38 | /* call tracing */ | ||
| 39 | #if 0 | ||
| 40 | int 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 | |||
| 56 | void * | ||
| 57 | ns_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 | |||
| 65 | void * | ||
| 66 | ns_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 | |||
| 73 | void * | ||
| 74 | ns_image_from_file (Lisp_Object file) | ||
| 75 | { | ||
| 76 | NSTRACE (ns_image_from_bitmap_file); | ||
| 77 | return [EmacsImage allocInitFromFile: file]; | ||
| 78 | } | ||
| 79 | |||
| 80 | int | ||
| 81 | ns_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 | |||
| 117 | int | ||
| 118 | ns_image_width (void *img) | ||
| 119 | { | ||
| 120 | return [(id)img size].width; | ||
| 121 | } | ||
| 122 | |||
| 123 | int | ||
| 124 | ns_image_height (void *img) | ||
| 125 | { | ||
| 126 | return [(id)img size].height; | ||
| 127 | } | ||
| 128 | |||
| 129 | unsigned long | ||
| 130 | ns_get_pixel (void *img, int x, int y) | ||
| 131 | { | ||
| 132 | return [(EmacsImage *)img getPixelAtX: x Y: y]; | ||
| 133 | } | ||
| 134 | |||
| 135 | void | ||
| 136 | ns_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 | |||
| 145 | void | ||
| 146 | ns_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 | |||
| 160 | static 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 | |||
| 4 | This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | GNU Emacs is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 3, or (at your option) | ||
| 9 | any later version. | ||
| 10 | |||
| 11 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with GNU Emacs; see the file COPYING. If not, write to | ||
| 18 | the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. | ||
| 19 | |||
| 20 | By Adrian Robert, based on code from original nsmenu.m (Carl Edman, | ||
| 21 | Christian Limpach, Scott Bender, Christophe de Dinechin) and code in the | ||
| 22 | Carbon 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 | ||
| 43 | int 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 | |||
| 56 | extern struct widget_value; | ||
| 57 | |||
| 58 | extern Lisp_Object Qundefined, Qmenu_enable, Qmenu_bar_update_hook; | ||
| 59 | extern Lisp_Object QCtoggle, QCradio; | ||
| 60 | |||
| 61 | extern Lisp_Object Vmenu_updating_frame; | ||
| 62 | |||
| 63 | Lisp_Object Qdebug_on_next_call; | ||
| 64 | extern Lisp_Object Voverriding_local_map, Voverriding_local_map_menu_flag, | ||
| 65 | Qoverriding_local_map, Qoverriding_terminal_local_map; | ||
| 66 | |||
| 67 | extern long context_menu_value; | ||
| 68 | EmacsMenu *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. */ | ||
| 82 | void | ||
| 83 | x_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. */ | ||
| 92 | void | ||
| 93 | free_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 */ | ||
| 107 | void | ||
| 108 | ns_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. */ | ||
| 491 | void | ||
| 492 | set_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? */ | ||
| 499 | static int | ||
| 500 | name_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 | |||
| 741 | static Lisp_Object | ||
| 742 | cleanup_popup_menu (Lisp_Object arg) | ||
| 743 | { | ||
| 744 | discard_menu_items (); | ||
| 745 | return Qnil; | ||
| 746 | } | ||
| 747 | |||
| 748 | |||
| 749 | static Lisp_Object | ||
| 750 | ns_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 | |||
| 1142 | void | ||
| 1143 | free_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 | |||
| 1151 | void | ||
| 1152 | update_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 | |||
| 1467 | Lisp_Object | ||
| 1468 | ns_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 | |||
| 1657 | void 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 | |||
| 1860 | DEFUN ("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 | |||
| 1869 | DEFUN ("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\ | ||
| 1871 | POSITION is a position specification. This is either a mouse button event\n\ | ||
| 1872 | or a list ((XOFFSET YOFFSET) WINDOW)\n\ | ||
| 1873 | where XOFFSET and YOFFSET are positions in pixels from the top left\n\ | ||
| 1874 | corner of WINDOW's frame. (WINDOW may be a frame object instead of a window.)\n\ | ||
| 1875 | This controls the position of the center of the first line\n\ | ||
| 1876 | in the first pane of the menu, not the top left of the menu as a whole.\n\ | ||
| 1877 | \n\ | ||
| 1878 | MENU is a specifier for a menu. For the simplest case, MENU is a keymap.\n\ | ||
| 1879 | The menu items come from key bindings that have a menu string as well as\n\ | ||
| 1880 | a 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\ | ||
| 1882 | the keymap as a top-level element.\n\n\ | ||
| 1883 | You can also use a list of keymaps as MENU.\n\ | ||
| 1884 | Then each keymap makes a separate pane.\n\ | ||
| 1885 | When MENU is a keymap or a list of keymaps, the return value\n\ | ||
| 1886 | is a list of events.\n\n\ | ||
| 1887 | Alternatively, you can specify a menu of multiple panes\n\ | ||
| 1888 | with a list of the form (TITLE PANE1 PANE2...),\n\ | ||
| 1889 | where each pane is a list of form (TITLE ITEM1 ITEM2...).\n\ | ||
| 1890 | Each ITEM is normally a cons cell (STRING . VALUE);\n\ | ||
| 1891 | but a string can appear as an item--that makes a nonselectable line\n\ | ||
| 1892 | in the menu.\n\ | ||
| 1893 | With 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 | |||
| 1901 | DEFUN ("x-popup-dialog", Fx_popup_dialog, Sx_popup_dialog, 2, 3, 0, | ||
| 1902 | doc: /* Pop up a dialog box and return user's selection. | ||
| 1903 | POSITION specifies which frame to use. | ||
| 1904 | This is normally a mouse button event or a window or frame. | ||
| 1905 | If POSITION is t, it means to use the frame the mouse is on. | ||
| 1906 | The dialog box appears in the middle of the specified frame. | ||
| 1907 | |||
| 1908 | CONTENTS specifies the alternatives to display in the dialog box. | ||
| 1909 | It is a list of the form (DIALOG ITEM1 ITEM2...). | ||
| 1910 | Each ITEM is a cons cell (STRING . VALUE). | ||
| 1911 | The return value is VALUE from the chosen item. | ||
| 1912 | |||
| 1913 | An ITEM may also be just a string--that makes a nonselectable item. | ||
| 1914 | An ITEM may also be nil--that means to put all preceding items | ||
| 1915 | on the left of the dialog box and all following items on the right. | ||
| 1916 | \(By default, approximately half appear on each side.) | ||
| 1917 | |||
| 1918 | If HEADER is non-nil, the frame title for the box is "Information", | ||
| 1919 | otherwise it is "Question". | ||
| 1920 | |||
| 1921 | If the user gets rid of the dialog box without making a valid choice, | ||
| 1922 | for 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 | |||
| 1937 | void | ||
| 1938 | syms_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 | |||
| 5 | This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | GNU Emacs is free software; you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation; either version 3, or (at your option) | ||
| 10 | any later version. | ||
| 11 | |||
| 12 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with GNU Emacs; see the file COPYING. If not, write to | ||
| 19 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
| 20 | Boston, MA 02110-1301, USA. | ||
| 21 | |||
| 22 | Originally by Carl Edman | ||
| 23 | Updated by Christian Limpach (chris@nice.ch) | ||
| 24 | OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com) | ||
| 25 | MacOSX/Aqua port by Christophe de Dinechin (descubes@earthlink.net) | ||
| 26 | GNUstep 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 | |||
| 37 | Lisp_Object QPRIMARY, QSECONDARY, QTEXT, QFILE_NAME; | ||
| 38 | |||
| 39 | static Lisp_Object Vns_sent_selection_hooks; | ||
| 40 | static Lisp_Object Vns_lost_selection_hooks; | ||
| 41 | static Lisp_Object Vselection_alist; | ||
| 42 | static Lisp_Object Vselection_converter_alist; | ||
| 43 | |||
| 44 | /* 23: new */ | ||
| 45 | /* Coding system for communicating with other programs. */ | ||
| 46 | static Lisp_Object Vselection_coding_system; | ||
| 47 | /* Coding system for the next communicating with other programs. */ | ||
| 48 | static Lisp_Object Vnext_selection_coding_system; | ||
| 49 | static Lisp_Object Qforeign_selection; | ||
| 50 | |||
| 51 | NSString *NXSecondaryPboard; | ||
| 52 | |||
| 53 | |||
| 54 | |||
| 55 | /* ========================================================================== | ||
| 56 | |||
| 57 | Internal utility functions | ||
| 58 | |||
| 59 | ========================================================================== */ | ||
| 60 | |||
| 61 | |||
| 62 | static NSString * | ||
| 63 | symbol_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 | |||
| 73 | static Lisp_Object | ||
| 74 | ns_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 | |||
| 90 | static Lisp_Object | ||
| 91 | clean_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 | |||
| 129 | static void | ||
| 130 | ns_declare_pasteboard (id pb) | ||
| 131 | { | ||
| 132 | [pb declareTypes: ns_send_types owner: NSApp]; | ||
| 133 | } | ||
| 134 | |||
| 135 | |||
| 136 | static void | ||
| 137 | ns_undeclare_pasteboard (id pb) | ||
| 138 | { | ||
| 139 | [pb declareTypes: [NSArray array] owner: nil]; | ||
| 140 | } | ||
| 141 | |||
| 142 | |||
| 143 | static void | ||
| 144 | ns_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 | |||
| 176 | static Lisp_Object | ||
| 177 | ns_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 | |||
| 224 | static Lisp_Object | ||
| 225 | ns_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 | |||
| 233 | static void | ||
| 234 | ns_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 | |||
| 265 | static void | ||
| 266 | ns_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 | |||
| 300 | Lisp_Object | ||
| 301 | ns_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 | |||
| 360 | void | ||
| 361 | ns_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 | |||
| 375 | DEFUN ("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 | |||
| 409 | DEFUN ("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 | |||
| 426 | DEFUN ("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\ | ||
| 428 | The arg should be the name of the selection in question, typically one of\n\ | ||
| 429 | the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\ | ||
| 430 | \(Those are literal upper-case symbol names.)\n\ | ||
| 431 | For convenience, the symbol nil is the same as `PRIMARY',\n\ | ||
| 432 | and 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 | |||
| 449 | DEFUN ("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\ | ||
| 452 | The arg should be the name of the selection in question, typically one of\n\ | ||
| 453 | the symbols `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\ | ||
| 454 | \(Those are literal upper-case symbol names.)\n\ | ||
| 455 | For convenience, the symbol nil is the same as `PRIMARY',\n\ | ||
| 456 | and 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 | |||
| 468 | DEFUN ("ns-get-selection-internal", Fns_get_selection_internal, | ||
| 469 | Sns_get_selection_internal, 2, 2, 0, | ||
| 470 | "Return text selected from some pasteboard.\n\ | ||
| 471 | SELECTION is a symbol, typically `PRIMARY', `SECONDARY', or `CLIPBOARD'.\n\ | ||
| 472 | \(Those are literal upper-case symbol names.)\n\ | ||
| 473 | TYPE 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 | ||
| 497 | DEFUN ("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 | |||
| 510 | DEFUN ("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 | |||
| 524 | DEFUN ("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 | |||
| 539 | void | ||
| 540 | nxatoms_of_nsselect (void) | ||
| 541 | { | ||
| 542 | NXSecondaryPboard = @"Selection"; | ||
| 543 | } | ||
| 544 | |||
| 545 | void | ||
| 546 | syms_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\ | ||
| 569 | The 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\ | ||
| 574 | We might have failed (and declined the request) for any number of reasons,\n\ | ||
| 575 | including being asked for a selection that we no longer own, or being asked\n\ | ||
| 576 | to convert into a type that we don't know about or that is inappropriate.\n\ | ||
| 577 | This hook doesn't let you change the behavior of Emacs's selection replies,\n\ | ||
| 578 | it 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\ | ||
| 583 | These functions are called to convert the selection, with three args:\n\ | ||
| 584 | the name of the selection (typically `PRIMARY', `SECONDARY', or `CLIPBOARD');\n\ | ||
| 585 | a desired type to which the selection should be converted;\n\ | ||
| 586 | and the local selection value (whatever was given to `x-own-selection').\n\ | ||
| 587 | \n\ | ||
| 588 | The function should return the value to send to the X server\n\ | ||
| 589 | \(typically a string). A return value of nil\n\ | ||
| 590 | means that the conversion could not be done.\n\ | ||
| 591 | A return value which is the symbol `NULL'\n\ | ||
| 592 | means that a side-effect was executed,\n\ | ||
| 593 | and 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\ | ||
| 599 | or when a Lisp program explicitly clears the selection.)\n\ | ||
| 600 | The 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. | ||
| 607 | When sending or receiving text via cut_buffer, selection, and clipboard, | ||
| 608 | the text is encoded or decoded by this coding system. | ||
| 609 | The 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. | ||
| 614 | Usually, `selection-coding-system' is used for communicating with | ||
| 615 | other programs. But, if this variable is set, it is used for the | ||
| 616 | next communication only. After the communication, this variable is | ||
| 617 | set 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 | |||
| 4 | This file is part of GNU Emacs. | ||
| 5 | |||
| 6 | GNU Emacs is free software; you can redistribute it and/or modify | ||
| 7 | it under the terms of the GNU General Public License as published by | ||
| 8 | the Free Software Foundation; either version 3, or (at your option) | ||
| 9 | any later version. | ||
| 10 | |||
| 11 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 12 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 13 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 14 | GNU General Public License for more details. | ||
| 15 | |||
| 16 | You should have received a copy of the GNU General Public License | ||
| 17 | along with GNU Emacs; see the file COPYING. If not, write to | ||
| 18 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
| 19 | Boston, 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 | |||
| 352 | extern NSArray *ns_send_types, *ns_return_types; | ||
| 353 | extern 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 | |||
| 372 | enum 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" */ | ||
| 384 | struct 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 */ | ||
| 397 | struct 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 */ | ||
| 426 | struct 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 () */ | ||
| 460 | struct 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. */ | ||
| 539 | extern struct ns_display_info *ns_display_list; | ||
| 540 | /* handle Xism */ | ||
| 541 | #define x_display_list ns_display_list | ||
| 542 | |||
| 543 | extern Lisp_Object ns_display_name_list; | ||
| 544 | extern 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 */ | ||
| 548 | struct ns_display_info *check_x_display_info (Lisp_Object frame); | ||
| 549 | FRAME_PTR check_x_frame (Lisp_Object frame); | ||
| 550 | |||
| 551 | |||
| 552 | struct 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 */ | ||
| 614 | struct 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 | |||
| 711 | extern struct ns_display_info *ns_term_init (); | ||
| 712 | extern 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 */ | ||
| 722 | extern void nsfont_make_fontset_for_font (Lisp_Object name, | ||
| 723 | Lisp_Object font_object); | ||
| 724 | |||
| 725 | /* In nsfont, for debugging */ | ||
| 726 | struct glyph_string; | ||
| 727 | void dump_glyphstring (struct glyph_string *s); | ||
| 728 | |||
| 729 | /* Implemented in nsterm, published in or needed from nsfns. */ | ||
| 730 | extern Lisp_Object Qfontsize; | ||
| 731 | extern Lisp_Object ns_list_fonts (FRAME_PTR f, Lisp_Object pattern, | ||
| 732 | int size, int maxnames); | ||
| 733 | extern void ns_clear_frame (struct frame *f); | ||
| 734 | |||
| 735 | #ifdef __OBJC__ | ||
| 736 | extern const char *ns_font_to_xlfd (NSFont *font); | ||
| 737 | #endif | ||
| 738 | extern const char *ns_fontname_to_xlfd (const char *name); | ||
| 739 | extern const char *ns_xlfd_to_fontname (const char *xlfd); | ||
| 740 | |||
| 741 | extern void check_ns (void); | ||
| 742 | extern Lisp_Object ns_map_event_to_object (); | ||
| 743 | extern Lisp_Object ns_string_from_pasteboard (); | ||
| 744 | extern void ns_string_to_pasteboard (); | ||
| 745 | extern void nxatoms_of_nsselect (); | ||
| 746 | extern int ns_lisp_to_cursor_type (); | ||
| 747 | extern Lisp_Object ns_cursor_type_to_lisp (int arg); | ||
| 748 | extern 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__ | ||
| 756 | extern int ns_lisp_to_color (Lisp_Object color, NSColor **col); | ||
| 757 | extern NSColor *ns_lookup_indexed_color (unsigned long idx, struct frame *f); | ||
| 758 | extern unsigned long ns_index_color (NSColor *color, struct frame *f); | ||
| 759 | extern void ns_free_indexed_color (unsigned long idx, struct frame *f); | ||
| 760 | #endif | ||
| 761 | |||
| 762 | /* C access to ObjC functionality */ | ||
| 763 | extern void ns_release_object (void *obj); | ||
| 764 | extern void ns_retain_object (void *obj); | ||
| 765 | extern void *ns_alloc_autorelease_pool (); | ||
| 766 | extern void ns_release_autorelease_pool (); | ||
| 767 | |||
| 768 | /* in nsmenu */ | ||
| 769 | extern void update_frame_tool_bar (FRAME_PTR f); | ||
| 770 | extern void free_frame_tool_bar (FRAME_PTR f); | ||
| 771 | extern void find_and_call_menu_selection (FRAME_PTR f, | ||
| 772 | EMACS_INT menu_bar_items_used, Lisp_Object vector, void *client_data); | ||
| 773 | extern Lisp_Object find_and_return_menu_selection (FRAME_PTR f, | ||
| 774 | int keymaps, | ||
| 775 | void *client_data); | ||
| 776 | extern 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 */ | ||
| 780 | extern void set_frame_menubar (struct frame *f, int first_time, int deep_p); | ||
| 781 | extern 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 */ | ||
| 785 | struct image; | ||
| 786 | extern void *ns_image_from_XBM (unsigned char *bits, int width, int height); | ||
| 787 | extern void *ns_image_for_XPM (int width, int height, int depth); | ||
| 788 | extern void *ns_image_from_file (Lisp_Object file); | ||
| 789 | extern int ns_load_image (struct frame *f, struct image *img, | ||
| 790 | Lisp_Object spec_file, Lisp_Object spec_data); | ||
| 791 | extern int ns_image_width (void *img); | ||
| 792 | extern int ns_image_height (void *img); | ||
| 793 | extern unsigned long ns_get_pixel (void *img, int x, int y); | ||
| 794 | extern void ns_put_pixel (void *img, int x, int y, unsigned long argb); | ||
| 795 | extern void ns_set_alpha (void *img, int x, int y, unsigned char a); | ||
| 796 | |||
| 797 | /* This in nsterm.m */ | ||
| 798 | extern unsigned long ns_get_rgb_color (struct frame *f, | ||
| 799 | float r, float g, float b, float a); | ||
| 800 | extern NSPoint last_mouse_motion_position; | ||
| 801 | |||
| 802 | #ifdef NS_IMPL_GNUSTEP | ||
| 803 | extern 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 | |||
| 5 | This file is part of GNU Emacs. | ||
| 6 | |||
| 7 | GNU Emacs is free software; you can redistribute it and/or modify | ||
| 8 | it under the terms of the GNU General Public License as published by | ||
| 9 | the Free Software Foundation; either version 3, or (at your option) | ||
| 10 | any later version. | ||
| 11 | |||
| 12 | GNU Emacs is distributed in the hope that it will be useful, | ||
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 15 | GNU General Public License for more details. | ||
| 16 | |||
| 17 | You should have received a copy of the GNU General Public License | ||
| 18 | along with GNU Emacs; see the file COPYING. If not, write to | ||
| 19 | the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, | ||
| 20 | Boston, MA 02110-1301, USA. | ||
| 21 | |||
| 22 | Originally by Carl Edman | ||
| 23 | Updated by Christian Limpach (chris@nice.ch) | ||
| 24 | OpenStep/Rhapsody port by Scott Bender (sbender@harmony-ds.com) | ||
| 25 | MacOSX/Aqua port by Christophe de Dinechin (descubes@earthlink.net) | ||
| 26 | GNUstep 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 | ||
| 56 | int 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... */ | ||
| 86 | static 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 */ | ||
| 139 | Lisp_Object ns_input_file, ns_input_font, ns_input_fontsize, ns_input_line; | ||
| 140 | Lisp_Object ns_input_color, ns_input_text, ns_working_text; | ||
| 141 | Lisp_Object ns_input_spi_name, ns_input_spi_arg; | ||
| 142 | Lisp_Object Vx_toolkit_scroll_bars; | ||
| 143 | static Lisp_Object Qmodifier_value; | ||
| 144 | /*PENDING: unsure why these defined in term files, anyway we need in keymap.c */ | ||
| 145 | Lisp_Object Qalt, Qcontrol, Qhyper, Qmeta, Qsuper; | ||
| 146 | extern Lisp_Object Qcursor_color, Qcursor_type, Qns; | ||
| 147 | extern int lisp_to_mod (Lisp_Object lmod); | ||
| 148 | |||
| 149 | |||
| 150 | EmacsPrefsController *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. */ | ||
| 158 | Lisp_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. */ | ||
| 162 | Lisp_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. */ | ||
| 166 | Lisp_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. */ | ||
| 170 | Lisp_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. */ | ||
| 174 | Lisp_Object ns_cursor_blink_rate; | ||
| 175 | |||
| 176 | /* Used for liason with core emacs cursor-blink-mode. */ | ||
| 177 | Lisp_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. */ | ||
| 182 | Lisp_Object ns_expand_space; | ||
| 183 | |||
| 184 | /* Control via default 'GSFontAntiAlias' on OS X and GNUstep. */ | ||
| 185 | int 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. */ | ||
| 190 | float 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. */ | ||
| 194 | int ns_use_qd_smoothing; | ||
| 195 | |||
| 196 | /* Used to pick up AppleHighlightColor on OS X */ | ||
| 197 | int ns_use_system_highlight_color; | ||
| 198 | NSString *ns_selection_color; | ||
| 199 | |||
| 200 | |||
| 201 | NSArray *ns_send_types =0, *ns_return_types =0, *ns_drag_types =0; | ||
| 202 | |||
| 203 | /* Display variables */ | ||
| 204 | struct ns_display_info *ns_display_list; /* Chain of existing displays */ | ||
| 205 | Lisp_Object ns_display_name_list; | ||
| 206 | long context_menu_value = 0; | ||
| 207 | |||
| 208 | /* display update */ | ||
| 209 | NSPoint last_mouse_motion_position; | ||
| 210 | static NSRect last_mouse_glyph; | ||
| 211 | static unsigned long last_mouse_movement_time = 0; | ||
| 212 | static Lisp_Object last_mouse_motion_frame; | ||
| 213 | static EmacsScroller *last_mouse_scroll_bar = nil; | ||
| 214 | static struct frame *ns_updating_frame; | ||
| 215 | static NSView *focus_view = NULL; | ||
| 216 | static int ns_window_num =0; | ||
| 217 | static NSRect uRect; | ||
| 218 | static BOOL gsaved = NO; | ||
| 219 | BOOL ns_in_resize = NO; | ||
| 220 | int ns_tmp_flags; /*PENDING */ | ||
| 221 | struct 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). */ | ||
| 230 | extern void CGContextSetFontRenderingMode (CGContextRef cg, int v); | ||
| 231 | #endif | ||
| 232 | |||
| 233 | |||
| 234 | /* event loop */ | ||
| 235 | static BOOL send_appdefined = YES; | ||
| 236 | static NSEvent *last_appdefined_event = 0; | ||
| 237 | static NSTimer *timed_entry = 0; | ||
| 238 | static NSTimer *fd_entry = nil; | ||
| 239 | static NSTimer *cursor_blink_entry = nil; | ||
| 240 | static NSTimer *scroll_repeat_entry = nil; | ||
| 241 | static fd_set select_readfds, t_readfds; | ||
| 242 | static struct timeval select_timeout; | ||
| 243 | static int select_nfds; | ||
| 244 | static NSAutoreleasePool *outerpool; | ||
| 245 | static BOOL ns_shutdown_properly = NO; | ||
| 246 | static struct input_event *emacs_event = NULL; | ||
| 247 | static struct input_event *q_event_ptr = NULL; | ||
| 248 | static int n_emacs_events_pending = 0; | ||
| 249 | static NSMutableArray *ns_pending_files, *ns_pending_service_names, | ||
| 250 | *ns_pending_service_args; | ||
| 251 | static 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 */ | ||
| 303 | static void ns_condemn_scroll_bars (struct frame *f), | ||
| 304 | ns_judge_scroll_bars (struct frame *f); | ||
| 305 | |||
| 306 | /* unused variables needed for compatibility reasons */ | ||
| 307 | int 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 | |||
| 318 | static Lisp_Object | ||
| 319 | append2 (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 | |||
| 331 | void | ||
| 332 | ns_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 | |||
| 429 | static int | ||
| 430 | timeval_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 | |||
| 460 | static void | ||
| 461 | ns_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 | |||
| 493 | void | ||
| 494 | ns_release_object (void *obj) | ||
| 495 | /* -------------------------------------------------------------------------- | ||
| 496 | Release an object (callable from C) | ||
| 497 | -------------------------------------------------------------------------- */ | ||
| 498 | { | ||
| 499 | [(id)obj release]; | ||
| 500 | } | ||
| 501 | |||
| 502 | |||
| 503 | void | ||
| 504 | ns_retain_object (void *obj) | ||
| 505 | /* -------------------------------------------------------------------------- | ||
| 506 | Retain an object (callable from C) | ||
| 507 | -------------------------------------------------------------------------- */ | ||
| 508 | { | ||
| 509 | [(id)obj retain]; | ||
| 510 | } | ||
| 511 | |||
| 512 | |||
| 513 | void * | ||
| 514 | ns_alloc_autorelease_pool () | ||
| 515 | /* -------------------------------------------------------------------------- | ||
| 516 | Allocate a pool for temporary objects (callable from C) | ||
| 517 | -------------------------------------------------------------------------- */ | ||
| 518 | { | ||
| 519 | return [[NSAutoreleasePool alloc] init]; | ||
| 520 | } | ||
| 521 | |||
| 522 | |||
| 523 | void | ||
| 524 | ns_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 | |||
| 540 | static NSRect | ||
| 541 | ns_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 | |||
| 551 | static void | ||
| 552 | ns_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 | |||
| 571 | static void | ||
| 572 | ns_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 | |||
| 604 | static void | ||
| 605 | ns_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 | |||
| 644 | static void | ||
| 645 | ns_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 | |||
| 674 | static void | ||
| 675 | ns_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 | |||
| 685 | static void | ||
| 686 | ns_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 | |||
| 763 | static void | ||
| 764 | ns_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 | |||
| 790 | static void | ||
| 791 | ns_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 | |||
| 825 | static void | ||
| 826 | ns_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 | |||
| 876 | static void | ||
| 877 | ns_reset_terminal_modes (struct terminal *terminal) | ||
| 878 | /* Externally called as hook */ | ||
| 879 | { | ||
| 880 | NSTRACE (ns_reset_terminal_modes); | ||
| 881 | } | ||
| 882 | |||
| 883 | static void | ||
| 884 | ns_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 | |||
| 899 | static void | ||
| 900 | ns_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 | |||
| 913 | static void | ||
| 914 | ns_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 | |||
| 927 | static void | ||
| 928 | ns_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 | |||
| 942 | static void | ||
| 943 | ns_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 | |||
| 985 | void | ||
| 986 | x_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 | |||
| 1000 | void | ||
| 1001 | x_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 | |||
| 1013 | void | ||
| 1014 | x_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 | |||
| 1043 | void | ||
| 1044 | x_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 | |||
| 1086 | void | ||
| 1087 | x_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 | |||
| 1114 | void | ||
| 1115 | x_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 | |||
| 1246 | NSColor * | ||
| 1247 | ns_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 | |||
| 1254 | unsigned long | ||
| 1255 | ns_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 | |||
| 1309 | void | ||
| 1310 | ns_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 | |||
| 1324 | static int | ||
| 1325 | ns_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 | |||
| 1495 | static NSColor * | ||
| 1496 | ns_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 | |||
| 1510 | int | ||
| 1511 | ns_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 | |||
| 1525 | Lisp_Object | ||
| 1526 | ns_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 | |||
| 1566 | int | ||
| 1567 | ns_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 | |||
| 1603 | unsigned long | ||
| 1604 | ns_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 | |||
| 1631 | void | ||
| 1632 | x_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 | |||
| 1650 | void | ||
| 1651 | x_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 | |||
| 1671 | static int | ||
| 1672 | note_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 | |||
| 1702 | static void | ||
| 1703 | ns_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 | |||
| 1779 | static void | ||
| 1780 | ns_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 | |||
| 1807 | void | ||
| 1808 | ns_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 | |||
| 1831 | static unsigned | ||
| 1832 | ns_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 | |||
| 1850 | char * | ||
| 1851 | x_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 | |||
| 1872 | static void | ||
| 1873 | ns_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 | |||
| 1888 | void | ||
| 1889 | ns_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 | |||
| 1929 | void | ||
| 1930 | ns_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 | |||
| 1980 | static void | ||
| 1981 | ns_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 | |||
| 2043 | static void | ||
| 2044 | ns_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 | |||
| 2096 | static void | ||
| 2097 | ns_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 | |||
| 2124 | static inline void | ||
| 2125 | ns_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 | |||
| 2162 | extern int max_used_fringe_bitmap; | ||
| 2163 | static void | ||
| 2164 | ns_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 | |||
| 2269 | void | ||
| 2270 | ns_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 | |||
| 2395 | static void | ||
| 2396 | ns_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 | |||
| 2415 | void | ||
| 2416 | show_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 | |||
| 2430 | void | ||
| 2431 | hide_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 | |||
| 2451 | static 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 | -------------------------------------------------------------------------- */ | ||
| 2456 | ns_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 | |||
| 2475 | static int | ||
| 2476 | ns_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 | |||
| 2496 | static void | ||
| 2497 | ns_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 | |||
| 2528 | static void | ||
| 2529 | ns_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 | |||
| 2604 | static void | ||
| 2605 | ns_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 | |||
| 2670 | static void | ||
| 2671 | ns_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 | |||
| 2739 | static void | ||
| 2740 | ns_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 | |||
| 2838 | static void | ||
| 2839 | ns_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 | |||
| 2978 | static void | ||
| 2979 | ns_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 | |||
| 3031 | static int | ||
| 3032 | ns_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 | |||
| 3121 | int | ||
| 3122 | ns_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 | |||
| 3253 | static void | ||
| 3254 | ns_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; | ||
| 3268 | static 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 | |||
| 3357 | static void | ||
| 3358 | ns_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 | |||
| 3379 | static void | ||
| 3380 | ns_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 | |||
| 3396 | static void | ||
| 3397 | ns_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 | |||
| 3424 | void | ||
| 3425 | x_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 | |||
| 3437 | static 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 | |||
| 3459 | static 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 | |||
| 3479 | static void | ||
| 3480 | ns_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 | |||
| 3499 | static void | ||
| 3500 | ns_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 | |||
| 3529 | void | ||
| 3530 | ns_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. */ | ||
| 3578 | extern frame_parm_handler ns_frame_parm_handlers[]; | ||
| 3579 | static 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 | |||
| 3609 | static void | ||
| 3610 | ns_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. */ | ||
| 3617 | static void | ||
| 3618 | ns_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 | |||
| 3636 | static struct terminal * | ||
| 3637 | ns_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 | |||
| 3689 | void | ||
| 3690 | ns_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 | |||
| 3700 | struct ns_display_info * | ||
| 3701 | ns_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; | ||
| 3718 | handling_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 | |||
| 3936 | extern Lisp_Object Vauto_save_list_file_name; | ||
| 3937 | void | ||
| 3938 | ns_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 | |||
| 3949 | void | ||
| 3950 | syms_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\ | ||
| 3991 | Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\ | ||
| 3992 | Set to none means that the alternate / option key is not interpreted by Emacs\n\ | ||
| 3993 | at 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\ | ||
| 3997 | Set 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\ | ||
| 4001 | Set 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\ | ||
| 4005 | Set to control, meta, alt, super, or hyper means it is taken to be that key.\n\ | ||
| 4006 | Set to none means that the function key is not interpreted by Emacs at all,\n\ | ||
| 4007 | allowing 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\ | ||
| 4011 | Set 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\ | ||
| 4015 | panel 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\ | ||
| 4019 | or 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. | ||
| 4066 | A value of nil means ignore them. If you encounter fonts with bogus | ||
| 4067 | UNDERLINE_POSITION font properties, for example 7x13 on XFree prior | ||
| 4068 | to 4.1, set this to nil. | ||
| 4069 | |||
| 4070 | NOTE: 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. | ||
| 4077 | A value of nil means to draw the underline according to the value of the | ||
| 4078 | variable `x-use-underline-position-properties', which is usually at the | ||
| 4079 | baseline 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); | ||
| 4216 | fprintf (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 | |||
| 4307 | extern 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 | |||
| 4658 | if (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); | ||
| 4759 | if (NS_KEYLOG) NSLog (@"markedRange request"); | ||
| 4760 | return rng; | ||
| 4761 | } | ||
| 4762 | |||
| 4763 | - (void)unmarkText | ||
| 4764 | { | ||
| 4765 | if (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)); | ||
| 4776 | if (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 | { | ||
| 4824 | if (NS_KEYLOG) NSLog (@"selectedRange request"); | ||
| 4825 | return NSMakeRange (NSNotFound, 0); | ||
| 4826 | } | ||
| 4827 | |||
| 4828 | - (unsigned int)characterIndexForPoint: (NSPoint)thePoint | ||
| 4829 | { | ||
| 4830 | if (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]; | ||
| 4838 | if (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]; */ | ||
| 6106 | static 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 | |||
| 6308 | Lisp_Object | ||
| 6309 | x_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 | |||
| 6352 | Lisp_Object | ||
| 6353 | ns_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 | |||
| 6485 | const char * | ||
| 6486 | ns_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 | |||
| 6520 | const char * | ||
| 6521 | ns_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 | |||
| 6555 | const char * | ||
| 6556 | ns_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 | |||
| 18 | along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */ | 18 | along 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 | ||
| 320 | struct mac_display_info; | 320 | struct mac_display_info; |
| 321 | struct ns_display_info; | ||
| 322 | struct x_display_info; | ||
| 321 | struct w32_display_info; | 323 | struct 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 | ||
| 27 | char *UP, *BC, PC; | 29 | char *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. */ |
| 26 | typedef void * XtPointer; | 27 | typedef struct _XCharStruct |
| 27 | typedef char Boolean; | ||
| 28 | enum 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; |
| 34 | typedef 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 | |||
| 46 | enum 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 | |||
| 55 | typedef 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 | |||
| 67 | typedef 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. */ |
| 93 | typedef struct _XGCValues | 70 | typedef 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 | ||
| 54 | Lisp_Object Qwindowp, Qwindow_live_p, Qwindow_configuration_p; | 57 | Lisp_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) |
| 213 | extern void set_frame_menubar P_ ((struct frame *f, int, int)); | 216 | extern void set_frame_menubar P_ ((struct frame *f, int, int)); |
| 214 | extern int pending_menu_activation; | 217 | extern int pending_menu_activation; |
| 215 | #endif | 218 | #endif |
| @@ -861,7 +864,7 @@ int display_hourglass_p; | |||
| 861 | int hourglass_shown_p; | 864 | int 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. */ |
| 865 | struct atimer *hourglass_atimer; | 868 | struct 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 | ||
| 22542 | static void | 22579 | #ifndef HAVE_NS |
| 22580 | static | ||
| 22581 | #endif | ||
| 22582 | void | ||
| 22543 | update_window_cursor (w, on) | 22583 | update_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)); | |||
| 556 | extern Lisp_Object w32_list_fonts P_ ((struct frame *, Lisp_Object, int, int)); | 567 | extern Lisp_Object w32_list_fonts P_ ((struct frame *, Lisp_Object, int, int)); |
| 557 | #endif /* WINDOWSNT */ | 568 | #endif /* WINDOWSNT */ |
| 558 | 569 | ||
| 570 | #ifdef HAVE_NS | ||
| 571 | extern 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 |
| 560 | static void x_update_menu_appearance P_ ((struct frame *)); | 575 | static 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 | |||
| 787 | static INLINE GC | ||
| 788 | x_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 | |||
| 799 | static INLINE void | ||
| 800 | x_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 | { |