Add support for the Haiku operating system and its window system

* .gitignore: Add binaries specific to Haiku.

* Makefie.in (HAVE_BE_APP): New variable.
(install-arch-dep): Install Emacs and Emacs.pdmp when
using Haiku.

* configure.ac: Detect and configure for Haiku and
various related configurations.
(be-app, be-freetype, be-cairo): New options.
(HAVE_BE_APP, HAIKU_OBJ, HAIKU_CXX_OBJ)
(HAIKU_LIBS, HAIKU_CFLAGS): New variables.
(HAIKU, HAVE_TINY_SPEED_T): New define.
(emacs_config_features): Add BE_APP.

* doc/emacs/Makefile.in (EMACSSOURCES): Add Haiku
appendix.

* doc/emacs/emacs.texi: Add Haiku appendix to menus and
include it.

* doc/emacs/haiku.texi: New Haiku appendix.

* doc/lispref/display.texi (Defining Faces, Window Systems):
Explain meaning of `haiku' as a window system identifier.
(haiku-use-system-tooltips): Explain meaning of system
tooltips on
Haiku.

* doc/lispref/frames.texi (Multiple Terminals): Explain
meaning of haiku as a display type.
(Frame Layout): Clarify section for Haiku frames.
(Size Parameters): Explain limitations of fullwidth and
fullheight on Haiku.
(Management Parameters): Explain limitations of
inhibiting double buffering on builds with Cairo,
and the inability of frames with no-accept-focus to
receive keyboard input on Haiku.
(Font and Color Parameters): Explain the different font
backends available on Haiku.
(Raising and Lowering): Explain that lowering and
restacking frames doesn't work on Haiku.
(Child Frames): Explain oddities of child frame
visibility on Haiku.

* doc/lispref/os.texi (System Environment): Explain
meaning of haiku.
* etc/MACHINES: Add appropriate notices for Haiku.
* etc/NEWS: Document changes.
* etc/PROBLEMS: Document font spacing bug on Haiku.

* lib-src/Makefile.in: Build be-resources binary on
Haiku.
(CXX, CXXFLAGS, NON_CXX_FLAGS, ALL_CXXFLAGS)
(HAVE_BE_APP, HAIKU_LIBS, HAIKU_CFLAGS): New variables.
(DONT_INSTALL): Add be-resources binary if on Haiku.
(be-resources): New target.

* lib-src/be_resources: Add helper binary for setting
resources on the Emacs application.

* lib-src/emacsclient.c (decode_options): Set
alt_display to "be" on Haiku.

* lisp/cus-edit.el (custom-button, custom-button-mouse)
(custom-button-unraised, custom-button-pressed): Update
face definitions for Haiku.

* lisp/cus-start.el: Add haiku-debug-on-fatal-error and
haiku-use-system-tooltips.

* lisp/faces.el (face-valid-attribute-values): Clarify
attribute comment for Haiku.
(tool-bar): Add appropriate toolbar color for Haiku.

* lisp/frame.el (haiku-frame-geometry)
(haiku-mouse-absolute-pixel-position)
(haiku-set-mouse-absolute-pixel-position)
(haiku-frame-edges)
(haiku-frame-list-z-order): New function declarations.

(frame-geometry, frame-edges)
(mouse-absolute-pixel-position)
(set-mouse-absolute-pixel-position)
(frame-list-z-order): Call appropriate window system
functions on Haiku.

(display-mouse-p, display-graphic-p)
(display-images-p, display-pixel-height)
(display-pixel-width, display-mm-height)
(display-mm-width, display-backing-store)
(display-save-under, display-planes)
(display-color-cells, display-visual-class): Update type
tests for Haiku.

* lisp/international/mule-cmds.el
(set-coding-system-map): Also
prevent set-terminal-coding-system from appearing in the menu
bar on Haiku.

* lisp/loadup.el: Load Haiku-specific files when built
with Haiku, and don't rename newly built Emacs on Haiku as BFS
doesn't support hard links.

* lisp/menu-bar.el (menu-bar-open): Add for Haiku.

* lisp/mwheel.el (mouse-wheel-down-event): Expect
wheel-up on Haiku.
(mouse-wheel-up-event): Expect wheel-down on Haiku.
(mouse-wheel-left-event): Expect wheel-left on Haiku.
(mouse-wheel-right-event): Expect wheel-right on Haiku.

* lisp/net/browse-url.el
(browse-url--browser-defcustom-type):
Add option for WebPositive.
(browse-url-webpositive-program): New variable.
(browse-url-default-program): Search for WebPositive.
(browse-url-webpositive): New function.

* lisp/net/eww.el (eww-form-submit, eww-form-file)
(eww-form-checkbox, eww-form-select): Define faces
appropriately for Haiku.

* lisp/term/haiku-win.el: New file.

* lisp/tooltip.el (menu-or-popup-active-p): New function
declaration.
(tooltip-show-help): Don't use tooltips on Haiku when a
menu is active.

* lisp/version.el (haiku-get-version-string): New
function declaration.
(emacs-version): Add Haiku version string if
appropriate.

* src/Makefile.in: Also produce binary named "Emacs"
with Haiku resources set.

(CXX, HAIKU_OBJ, HAIKU_CXX_OBJ, HAIKU_LIBS)
(HAIKU_CFLAGS, HAVE_BE_APP, NON_CXX_FLAGS)
(ALL_CXX_FLAGS): New variables.

(.SUFFIXES): Add .cc.
(.cc.o): New target.
(base_obj): Add Haiku C objects.
(doc_obj, obj): Split objects that should scanned for
documentation into doc_obj.
(SOME_MACHINE_OBJECTS): Add appropriate Haiku C objects.
(all): Depend on Emacs and Emacs.pdmp on Haiku.
(LIBES): Add Haiku libraries.
(gl-stamp)
($(etc)/DOC): Scan doc_obj instead of obj
(temacs$(EXEEXT): Use C++ linker on Haiku.
(ctagsfiles3): New variable.
(TAGS): Scan C++ files.

* src/alloc.c (garbage_collect): Mark Haiku display.

* src/dispextern.h (HAVE_NATIVE_TRANSFORMS): Also enable
on Haiku.
(struct image): Add fields for Haiku transforms.
(RGB_PIXEL_COLOR): Define to unsigned long on Haiku as
well.
(sit_for): Also check USABLE_SIGPOLL.
(init_display_interactive): Set initial window system to
Haiku on Haiku builds.

* src/emacs.c (main): Define Haiku syms and init haiku
clipboard.
(shut_down_emacs): Quit BApplication on Haiku and
trigger debug
on aborts if haiku_debug_on_fatal_error.
(Vsystem_type): Update docstring.

* src/fileio.c (next-read-file-uses-dialog-p): Enable on
Haiku.

* src/filelock.c (WTMP_FILE): Only define if BOOT_TIME
is also defined.

* src/floatfns.c (double_integer_scale): Work around
Haiku libroot brain damage.

* src/font.c (syms_of_font): Define appropriate font
driver symbols for Haiku builds with various options.

* src/font.h: Also enable ftcrfont on Haiku builds with
Cairo.
(font_data_structures_may_be_ill_formed): Also enable on
Haiku builds that have Cairo.

* src/frame.c (Fframep): Update doc-string for Haiku
builds and return haiku if appropriate.
(syms_of_frame): New symbol `haiku'.

* src/frame.h (struct frame): Add output data for Haiku.
(FRAME_HAIKU_P): New macro.
(FRAME_WINDOW_P): Test for Haiku frames as well.

* src/ftcrfont.c (RED_FROM_ULONG, GREEN_FROM_ULONG)
(BLUE_FROM_ULONG): New macros.
(ftcrfont_draw): Add haiku specific code for Haiku
builds with Cairo.

* src/ftfont.c (ftfont_open): Set face.
(ftfont_has_char, ftfont_text_extents): Work around
crash.
(syms_of_ftfont): New symbol `mono'.

* src/ftfont.h (struct font_info): Enable Cairo-specific
fields for Cairo builds on Haiku.

* src/haiku_draw_support.cc:
* src/haiku_font_support.cc:
* src/haiku_io.c:
* src/haiku_select.cc:
* src/haiku_support.cc:
* src/haiku_support.h:
* src/haikufns.c:
* src/haikufont.c:
* src/haikugui.h:
* src/haikuimage.c:
* src/haikumenu.c:
* src/haikuselect.c:
* src/haikuselect.h:
* src/haikuterm.c:
* src/haikuterm.h: Add new files for Haiku windowing
support.

* src/haiku.c: Add new files for Haiku operating system
support.

* src/image.c: Implement image transforms and native XPM
support
on Haiku.

(GET_PIXEL, PUT_PIXEL, NO_PIXMAP)
(PIX_MASK_RETAIN, PIX_MASK_DRAW)
(RGB_TO_ULONG, RED_FROM_ULONG, GREEN_FROM_ULONG)
(BLUE_FROM_ULONG, RED16_FROM_ULONG, GREEN16_FROM_ULONG)
(BLUE16_FROM_ULONG): Define to appropriate values on
Haiku.

(image_create_bitmap_from_data): Add Haiku support.
(image_create_bitmap_from_file): Add TODO on Haiku.
(free_bitmap_record): Free bitmap on Haiku.
(image_size_in_bytes): Implement for Haiku bitmaps.
(image_set_transform): Implement on Haiku.
(image_create_x_image_and_pixmap_1): Implement on Haiku,
24-bit or 1-bit only.
(image_destroy_x_image, image_get_x_image): Use correct
img and pixmap values on Haiku.
(lookup_rgb_color): Use correct macro on Haiku.
(image_to_emacs_colors): Implement on Haiku.
(image_disable_image): Disable on Haiku.
(image_can_use_native_api): Test for translator presence
on Haiku.
(native_image_load): Use translator on Haiku.
(imagemagick_load_image): Add Haiku-specific quirks.
(Fimage_transforms_p): Allow rotate90 on Haiku.
(image_types): Enable native XPM support on Haiku.
(syms_of_image): Enable XPM images on Haiku.

* src/keyboard.c (kbd_buffer_get_event)
(handle_async_input, handle_input_available_signal)
(handle_user_signal, Fset_input_interrupt_mode)
(init_keyboard): Check for USABLE_SIGPOLL along with
USABLE_SIGIO.

* src/lisp.h (pD): Work around broken Haiku headers.
(HAVE_EXT_MENU_BAR): Define on Haiku.
(handle_input_available_signal): Enable if we just have
SIGPOLL as well.

* src/menu.c (have_boxes): Return true on Haiku.
(single_menu_item): Enable toolkit menus on Haiku.
(find_and_call_menu_selection): Also enable on Haiku.

* src/process.c (keyboard_bit_set): Enable with only
usable SIGPOLL.
(wait_reading_process_output): Test for SIGPOLL as well
as SIGIO availability.

* src/sound.c (sound_perror, vox_open)
(vox_configure, vox_close): Enable for usable SIGPOLL as
well.

* src/sysdep.c (sys_subshell): Enable for usable SIGPOLL.
(reset_sigio): Make conditional on F_SETOWN.
(request_sigio, unrequest_sigio)
(emacs_sigaction_init): Also handle SIGPOLLs.
(init_sys_modes): Disable TCXONC usage on Haiku, as it
doesn't have any ttys other than pseudo ttys, which don't
support C-s/C-q flow control, and causes compiler warnings.
(speeds): Disable high speeds if HAVE_TINY_SPEED_T.

* src/termhooks.h (enum output_method): Add output_haiku.
(struct terminal): Add Haiku display info.
(TERMINAL_FONT_CACHE): Enable for Haiku.

* src/terminal.c (Fterminal_live_p): Return `haiku' if
appropriate.
* src/verbose.mk.in (AM_V_CXX, AM_V_CXXLD): New logging
variables.

* src/xdisp.c (redisplay_internal)
(note_mouse_highlight): Return on Haiku if a popup is activated.
(display_menu_bar): Return on Haiku if frame is a Haiku
frame.

* src/xfaces.c (GCGraphicsExposures): Enable correctly on Haiku.
(x_create_gc): Enable dummy GC code on Haiku.

* src/xfns.c (x-server-version, x-file-dialog): Add
Haiku specifics to doc strings.

* src/xterm.c (syms_of_xterm): Add Haiku information to
doc string.
This commit is contained in:
Po Lu 2021-11-20 21:30:08 +08:00
parent bfcc59371b
commit 85a078e785
73 changed files with 15344 additions and 138 deletions

2
.gitignore vendored
View file

@ -182,6 +182,7 @@ ID
# Executables.
*.exe
a.out
lib-src/be-resources
lib-src/blessmail
lib-src/ctags
lib-src/ebrowse
@ -203,6 +204,7 @@ nextstep/GNUstep/Emacs.base/Resources/Info-gnustep.plist
src/bootstrap-emacs
src/emacs
src/emacs-[0-9]*
src/Emacs
src/temacs
src/dmpstruct.h
src/*.pdmp

View file

@ -102,6 +102,8 @@ HAVE_NATIVE_COMP = @HAVE_NATIVE_COMP@
USE_STARTUP_NOTIFICATION = @USE_STARTUP_NOTIFICATION@
HAVE_BE_APP = @HAVE_BE_APP@
# ==================== Where To Install Things ====================
# Location to install Emacs.app under GNUstep / macOS.
@ -521,7 +523,13 @@ install-arch-dep: src install-arch-indep install-etcdoc install-$(NTDIR)
$(MAKE) -C lib-src install
ifeq (${ns_self_contained},no)
${INSTALL_PROGRAM} $(INSTALL_STRIP) src/emacs${EXEEXT} "$(DESTDIR)${bindir}/$(EMACSFULL)"
ifeq (${HAVE_BE_APP},yes)
${INSTALL_PROGRAM} $(INSTALL_STRIP) src/Emacs "$(DESTDIR)${prefix}/apps/Emacs"
endif
ifeq (${DUMPING},pdumper)
ifeq (${HAVE_BE_APP},yes)
${INSTALL_DATA} src/Emacs.pdmp "$(DESTDIR)${libexecdir}/emacs/${version}/${configuration}"/Emacs.pdmp
endif
${INSTALL_DATA} src/emacs.pdmp "$(DESTDIR)${libexecdir}/emacs/${version}/${configuration}"/emacs-${EMACS_PDMP}
endif
-chmod 755 "$(DESTDIR)${bindir}/$(EMACSFULL)"

View file

@ -511,6 +511,12 @@ otherwise for the first of 'inotify', 'kqueue' or 'gfile' that is usable.])
OPTION_DEFAULT_OFF([xwidgets],
[enable use of xwidgets in Emacs buffers (requires gtk3 or macOS Cocoa)])
OPTION_DEFAULT_OFF([be-app],
[enable use of Haiku's Application Kit as a window system])
OPTION_DEFAULT_OFF([be-cairo],
[enable use of cairo under Haiku's Application Kit])
## Makefile.in needs the cache file name.
AC_SUBST(cache_file)
@ -787,6 +793,10 @@ case "${canonical}" in
LDFLAGS="-N2M $LDFLAGS"
;;
*-haiku )
opsys=haiku
;;
## Intel 386 machines where we don't care about the manufacturer.
i[3456]86-*-* )
case "${canonical}" in
@ -908,7 +918,9 @@ if test "$ac_test_CFLAGS" != set; then
if test $emacs_cv_prog_cc_g3 != yes; then
CFLAGS=$emacs_save_CFLAGS
fi
if test $opsys = mingw32; then
# Haiku also needs -gdwarf-2 because its GDB is too old
# to understand newer formats.
if test $opsys = mingw32 || test $opsys = haiku; then
CFLAGS="$CFLAGS -gdwarf-2"
fi
fi
@ -1575,6 +1587,8 @@ case "$opsys" in
## Motif needs -lgen.
unixware) LIBS_SYSTEM="-lsocket -lnsl -lelf -lgen" ;;
haiku) LIBS_SYSTEM="-lnetwork" ;;
esac
AC_SUBST(LIBS_SYSTEM)
@ -2080,6 +2094,22 @@ if test "${HAVE_NS}" = yes; then
fi
fi
HAVE_BE_APP=no
if test "${opsys}" = "haiku" && test "${with_be_app}" = "yes"; then
dnl Only GCC is supported. Clang might work, but it's
dnl not reliable, so don't check for it here.
AC_PROG_CXX([gcc g++])
CXXFLAGS="$CXXFLAGS $emacs_g3_CFLAGS"
AC_LANG_PUSH([C++])
AC_CHECK_HEADER([app/Application.h], [HAVE_BE_APP=yes],
[AC_MSG_ERROR([The Application Kit headers required for building
with the Application Kit were not found or cannot be compiled. Either fix this, or
re-configure with the option '--without-be-app'.])])
AC_LANG_POP([C++])
fi
AC_SUBST(HAVE_BE_APP)
HAVE_W32=no
W32_OBJ=
W32_LIBS=
@ -2201,6 +2231,39 @@ if test "${HAVE_W32}" = "yes"; then
with_xft=no
fi
HAIKU_OBJ=
HAIKU_CXX_OBJ=
HAIKU_LIBS=
HAIKU_CFLAGS=
if test "$opsys" = "haiku"; then
HAIKU_OBJ="$HAIKU_OBJ haiku.o"
fi
if test "${HAVE_BE_APP}" = "yes"; then
AC_DEFINE([HAVE_HAIKU], 1,
[Define if Emacs will be built with Haiku windowing support])
fi
if test "${HAVE_BE_APP}" = "yes"; then
window_system=haiku
with_xft=no
HAIKU_OBJ="$HAIKU_OBJ haikufns.o haikuterm.o haikumenu.o haikufont.o haikuselect.o haiku_io.o"
HAIKU_CXX_OBJ="haiku_support.o haiku_font_support.o haiku_draw_support.o haiku_select.o"
HAIKU_LIBS="-lbe -lgame -ltranslation -ltracker" # -lgame is needed for set_mouse_position.
if test "${with_native_image_api}" = yes; then
AC_DEFINE(HAVE_NATIVE_IMAGE_API, 1, [Define to use native OS APIs for images.])
NATIVE_IMAGE_API="yes (haiku)"
HAIKU_OBJ="$HAIKU_OBJ haikuimage.o"
fi
fi
AC_SUBST(HAIKU_LIBS)
AC_SUBST(HAIKU_OBJ)
AC_SUBST(HAIKU_CXX_OBJ)
AC_SUBST(HAIKU_CFLAGS)
## $window_system is now set to the window system we will
## ultimately use.
@ -2240,6 +2303,9 @@ dnl use the toolkit if we have gtk, or X11R5 or newer.
w32 )
term_header=w32term.h
;;
haiku )
term_header=haikuterm.h
;;
esac
if test "$window_system" = none && test "X$with_x" != "Xno"; then
@ -2571,7 +2637,8 @@ fi
### Use -lrsvg-2 if available, unless '--with-rsvg=no' is specified.
HAVE_RSVG=no
if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" || test "${opsys}" = "mingw32"; then
if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" \
|| test "${opsys}" = "mingw32" || test "${HAVE_BE_APP}" = "yes"; then
if test "${with_rsvg}" != "no"; then
RSVG_REQUIRED=2.14.0
RSVG_MODULE="librsvg-2.0 >= $RSVG_REQUIRED"
@ -2595,7 +2662,8 @@ fi
HAVE_WEBP=no
if test "${with_webp}" != "no"; then
if test "${HAVE_X11}" = "yes" || test "${opsys}" = "mingw32" \
|| test "${HAVE_W32}" = "yes" || test "${HAVE_NS}" = "yes"; then
|| test "${HAVE_W32}" = "yes" || test "${HAVE_NS}" = "yes" \
|| test "${HAVE_BE_APP}" = "yes"; then
WEBP_REQUIRED=0.6.0
WEBP_MODULE="libwebp >= $WEBP_REQUIRED"
@ -2614,7 +2682,8 @@ if test "${with_webp}" != "no"; then
fi
HAVE_IMAGEMAGICK=no
if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" || test "${HAVE_W32}" = "yes"; then
if test "${HAVE_X11}" = "yes" || test "${HAVE_NS}" = "yes" || test "${HAVE_W32}" = "yes" || \
test "${HAVE_BE_APP}" = "yes"; then
if test "${with_imagemagick}" != "no"; then
if test -n "$BREW"; then
# Homebrew doesn't link ImageMagick 6 by default, so make sure
@ -3264,6 +3333,9 @@ if test "${with_toolkit_scroll_bars}" != "no"; then
elif test "${HAVE_W32}" = "yes"; then
AC_DEFINE(USE_TOOLKIT_SCROLL_BARS)
USE_TOOLKIT_SCROLL_BARS=yes
elif test "${HAVE_BE_APP}" = "yes"; then
AC_DEFINE(USE_TOOLKIT_SCROLL_BARS)
USE_TOOLKIT_SCROLL_BARS=yes
fi
fi
@ -3353,6 +3425,22 @@ if test "${HAVE_X11}" = "yes"; then
fi
fi
fi
if test "${HAVE_BE_APP}" = "yes"; then
if test "${with_be_cairo}" != "no"; then
CAIRO_REQUIRED=1.8.0
CAIRO_MODULE="cairo >= $CAIRO_REQUIRED"
EMACS_CHECK_MODULES(CAIRO, $CAIRO_MODULE)
if test $HAVE_CAIRO = yes; then
AC_DEFINE(USE_BE_CAIRO, 1, [Define to 1 if using cairo on Haiku.])
CFLAGS="$CFLAGS $CAIRO_CFLAGS"
LIBS="$LIBS $CAIRO_LIBS"
AC_SUBST(CAIRO_CFLAGS)
AC_SUBST(CAIRO_LIBS)
else
AC_MSG_WARN([cairo requested but not found.])
fi
fi
fi
### Start of font-backend (under any platform) section.
# (nothing here yet -- this is a placeholder)
@ -3502,6 +3590,58 @@ if test "${HAVE_X11}" = "yes" && test "${HAVE_FREETYPE}" = "yes" \
fi
fi
### Start of font-backend (under Haiku) selectionn.
if test "${HAVE_BE_APP}" = "yes"; then
if test $HAVE_CAIRO = "yes"; then
EMACS_CHECK_MODULES([FREETYPE], [freetype2 >= 2.5.0])
test "$HAVE_FREETYPE" = "no" && AC_MSG_ERROR(cairo on Haiku requires libfreetype)
EMACS_CHECK_MODULES([FONTCONFIG], [fontconfig >= 2.2.0])
test "$HAVE_FONTCONFIG" = "no" && AC_MSG_ERROR(cairo on Haiku requires libfontconfig)
fi
HAVE_LIBOTF=no
if test "${HAVE_FREETYPE}" = "yes"; then
AC_DEFINE(HAVE_FREETYPE, 1,
[Define to 1 if using the freetype and fontconfig libraries.])
OLD_CFLAGS=$CFLAGS
OLD_LIBS=$LIBS
CFLAGS="$CFLAGS $FREETYPE_CFLAGS"
LIBS="$FREETYPE_LIBS $LIBS"
AC_CHECK_FUNCS(FT_Face_GetCharVariantIndex)
CFLAGS=$OLD_CFLAGS
LIBS=$OLD_LIBS
if test "${with_libotf}" != "no"; then
EMACS_CHECK_MODULES([LIBOTF], [libotf])
if test "$HAVE_LIBOTF" = "yes"; then
AC_DEFINE(HAVE_LIBOTF, 1, [Define to 1 if using libotf.])
AC_CHECK_LIB(otf, OTF_get_variation_glyphs,
HAVE_OTF_GET_VARIATION_GLYPHS=yes,
HAVE_OTF_GET_VARIATION_GLYPHS=no)
if test "${HAVE_OTF_GET_VARIATION_GLYPHS}" = "yes"; then
AC_DEFINE(HAVE_OTF_GET_VARIATION_GLYPHS, 1,
[Define to 1 if libotf has OTF_get_variation_glyphs.])
fi
if ! $PKG_CONFIG --atleast-version=0.9.16 libotf; then
AC_DEFINE(HAVE_OTF_KANNADA_BUG, 1,
[Define to 1 if libotf is affected by https://debbugs.gnu.org/28110.])
fi
fi
fi
dnl FIXME should there be an error if HAVE_FREETYPE != yes?
dnl Does the new font backend require it, or can it work without it?
fi
fi
if test "${HAVE_BE_APP}" = "yes" && test "${HAVE_FREETYPE}" = "yes"; then
if test "${with_harfbuzz}" != "no"; then
EMACS_CHECK_MODULES([HARFBUZZ], [harfbuzz >= $harfbuzz_required_ver])
if test "$HAVE_HARFBUZZ" = "yes"; then
AC_DEFINE(HAVE_HARFBUZZ, 1, [Define to 1 if using HarfBuzz.])
fi
fi
fi
### End of font-backend section.
AC_SUBST(FREETYPE_CFLAGS)
@ -3623,7 +3763,7 @@ AC_SUBST(LIBXPM)
HAVE_JPEG=no
LIBJPEG=
if test "${HAVE_X11}" = "yes" || test "${HAVE_W32}" = "yes" \
|| test "${HAVE_NS}" = "yes"; then
|| test "${HAVE_NS}" = "yes" || test "${HAVE_BE_APP}" = "yes"; then
if test "${with_jpeg}" != "no"; then
AC_CACHE_CHECK([for jpeglib 6b or later],
[emacs_cv_jpeglib],
@ -3941,7 +4081,7 @@ if test "${with_png}" != no; then
if test "$opsys" = mingw32; then
AC_CHECK_HEADER([png.h], [HAVE_PNG=yes])
elif test "${HAVE_X11}" = "yes" || test "${HAVE_W32}" = "yes" \
|| test "${HAVE_NS}" = "yes"; then
|| test "${HAVE_NS}" = "yes" || test "${HAVE_BE_APP}" = "yes"; then
EMACS_CHECK_MODULES([PNG], [libpng >= 1.0.0])
if test $HAVE_PNG = yes; then
LIBPNG=$PNG_LIBS
@ -4016,7 +4156,7 @@ if test "${opsys}" = "mingw32"; then
AC_DEFINE(HAVE_TIFF, 1, [Define to 1 if you have the tiff library (-ltiff).])
fi
elif test "${HAVE_X11}" = "yes" || test "${HAVE_W32}" = "yes" \
|| test "${HAVE_NS}" = "yes"; then
|| test "${HAVE_NS}" = "yes" || test "${HAVE_BE_APP}" = "yes"; then
if test "${with_tiff}" != "no"; then
AC_CHECK_HEADER(tiffio.h,
[tifflibs="-lz -lm"
@ -4045,7 +4185,8 @@ if test "${opsys}" = "mingw32"; then
AC_DEFINE(HAVE_GIF, 1, [Define to 1 if you have a gif (or ungif) library.])
fi
elif test "${HAVE_X11}" = "yes" && test "${with_gif}" != "no" \
|| test "${HAVE_W32}" = "yes" || test "${HAVE_NS}" = "yes"; then
|| test "${HAVE_W32}" = "yes" || test "${HAVE_NS}" = "yes" \
|| test "${HAVE_BE_APP}" = "yes"; then
AC_CHECK_HEADER(gif_lib.h,
# EGifPutExtensionLast only exists from version libungif-4.1.0b1.
# Earlier versions can crash Emacs, but version 5.0 removes EGifPutExtensionLast.
@ -4482,6 +4623,13 @@ case $with_unexec,$canonical in
[AC_MSG_ERROR([Non-ELF systems are not supported on this platform.])]);;
esac
if test "$with_unexec" = yes && test "$opsys" = "haiku"; then
dnl A serious attempt was actually made to port unexec to Haiku.
dnl Something in libstdc++ seems to prevent it from working.
AC_MSG_ERROR([Haiku is not supported by the legacy unexec dumper.
Please use the portable dumper instead.])
fi
# Dump loading
AC_CHECK_FUNCS([posix_madvise])
@ -4835,7 +4983,7 @@ CFLAGS="$OLDCFLAGS"
LIBS="$OLDLIBS"])
if test "${emacs_cv_links_glib}" = "yes"; then
AC_DEFINE(HAVE_GLIB, 1, [Define to 1 if GLib is linked in.])
if test "$HAVE_NS" = no;then
if test "$HAVE_NS" = no ; then
XGSELOBJ=xgselect.o
fi
fi
@ -5090,7 +5238,7 @@ dnl It would have Emacs fork off a separate process
dnl to read the input and send it to the true Emacs process
dnl through a pipe.
case $opsys in
darwin | gnu-linux | gnu-kfreebsd )
darwin | gnu-linux | gnu-kfreebsd)
AC_DEFINE(INTERRUPT_INPUT, 1, [Define to read input using SIGIO.])
;;
esac
@ -5186,6 +5334,14 @@ case $opsys in
AC_DEFINE(PTY_OPEN, [fd = open (pty_name, O_RDWR | O_NONBLOCK)])
AC_DEFINE(PTY_TTY_NAME_SPRINTF, [{ char *ptsname (int), *ptyname; int grantpt_result; sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); grantpt_result = grantpt (fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 0); if (grantpt_result == -1) fatal("could not grant slave pty"); if (unlockpt(fd) == -1) fatal("could not unlock slave pty"); if (!(ptyname = ptsname(fd))) fatal ("could not enable slave pty"); snprintf (pty_name, PTY_NAME_SIZE, "%s", ptyname); }])
;;
haiku*)
AC_DEFINE(FIRST_PTY_LETTER, ['s'])
AC_DEFINE(PTY_NAME_SPRINTF, [])
dnl on Haiku pty names aren't distinctive, thus the use of posix_openpt
AC_DEFINE(PTY_OPEN, [fd = posix_openpt (O_RDWR | O_NONBLOCK)])
AC_DEFINE(PTY_TTY_NAME_SPRINTF, [{ char *ptyname; int grantpt_result; sigset_t blocked; sigemptyset (&blocked); sigaddset (&blocked, SIGCHLD); pthread_sigmask (SIG_BLOCK, &blocked, 0); grantpt_result = grantpt (fd); pthread_sigmask (SIG_UNBLOCK, &blocked, 0); if (grantpt_result == -1) fatal("could not grant slave pty"); if (unlockpt(fd) == -1) fatal("could not unlock slave pty"); if (!(ptyname = ptsname(fd))) fatal ("could not enable slave pty"); snprintf (pty_name, PTY_NAME_SIZE, "%s", ptyname); }])
;;
esac
@ -5407,8 +5563,25 @@ case $opsys in
AC_DEFINE(USG, [])
AC_DEFINE(USG5_4, [])
;;
haiku)
AC_DEFINE(HAIKU, [], [Define if the system is Haiku.])
;;
esac
AC_SYS_POSIX_TERMIOS
if test $ac_cv_sys_posix_termios = yes; then
AC_CHECK_SIZEOF([speed_t], [], [#include <termios.h>])
dnl on Haiku, and possibly other platforms, speed_t is defined to
dnl unsigned char, even when speeds greater than 200 baud are
dnl defined.
if test ${ac_cv_sizeof_speed_t} -lt 2; then
AC_DEFINE([HAVE_TINY_SPEED_T], [1],
[Define to 1 if speed_t has some sort of nonsensically tiny size.])
fi
fi
AC_CACHE_CHECK([for usable FIONREAD], [emacs_cv_usable_FIONREAD],
[case $opsys in
aix4-2 | nacl)
@ -5451,6 +5624,22 @@ if test $emacs_cv_usable_FIONREAD = yes; then
AC_DEFINE([USABLE_SIGIO], [1], [Define to 1 if SIGIO is usable.])
fi
fi
if test $emacs_broken_SIGIO = no && test $emacs_cv_usable_SIGIO = no; then
AC_CACHE_CHECK([for usable SIGPOLL], [emacs_cv_usable_SIGPOLL],
[AC_COMPILE_IFELSE(
[AC_LANG_PROGRAM([[#include <fcntl.h>
#include <signal.h>
]],
[[int foo = SIGPOLL | F_SETFL;]])],
[emacs_cv_usable_SIGPOLL=yes],
[emacs_cv_usable_SIGPOLL=no])],
[emacs_cv_usable_SIGPOLL=yes],
[emacs_cv_usable_SIGPOLL=no])
if test $emacs_cv_usable_SIGPOLL = yes; then
AC_DEFINE([USABLE_SIGPOLL], [1], [Define to 1 if SIGPOLL is usable but SIGIO is not.])
fi
fi
fi
case $opsys in
@ -5563,6 +5752,17 @@ if test "${HAVE_X_WINDOWS}" = "yes" ; then
FONT_OBJ="$FONT_OBJ ftfont.o"
fi
fi
if test "${HAVE_BE_APP}" = "yes" ; then
if test "${HAVE_FREETYPE}" = "yes" || \
test "${HAVE_CAIRO}" = "yes"; then
FONT_OBJ="$FONT_OBJ ftfont.o"
fi
if test "${HAVE_CAIRO}" = "yes"; then
FONT_OBJ="$FONT_OBJ ftcrfont.o"
fi
fi
if test "${HAVE_HARFBUZZ}" = "yes" ; then
FONT_OBJ="$FONT_OBJ hbfont.o"
fi
@ -5951,7 +6151,7 @@ Configured for '${canonical}'.
#### Please respect alphabetical ordering when making additions.
optsep=
emacs_config_features=
for opt in ACL CAIRO DBUS FREETYPE GCONF GIF GLIB GMP GNUTLS GPM GSETTINGS \
for opt in ACL BE_APP CAIRO DBUS FREETYPE GCONF GIF GLIB GMP GNUTLS GPM GSETTINGS \
HARFBUZZ IMAGEMAGICK JPEG JSON LCMS2 LIBOTF LIBSELINUX LIBSYSTEMD LIBXML2 \
M17N_FLT MODULES NATIVE_COMP NOTIFY NS OLDXMENU PDUMPER PNG RSVG SECCOMP \
SOUND THREADS TIFF TOOLKIT_SCROLL_BARS \

View file

@ -140,6 +140,7 @@ EMACSSOURCES= \
${srcdir}/xresources.texi \
${srcdir}/anti.texi \
${srcdir}/macos.texi \
$(srcdir)/haiku.texi \
${srcdir}/msdos.texi \
${srcdir}/gnu.texi \
${srcdir}/glossary.texi \

View file

@ -221,6 +221,7 @@ Appendices
* X Resources:: X resources for customizing Emacs.
* Antinews:: Information about Emacs version 27.
* Mac OS / GNUstep:: Using Emacs under macOS and GNUstep.
* Haiku:: Using Emacs on Haiku.
* Microsoft Windows:: Using Emacs on Microsoft Windows and MS-DOS.
* Manifesto:: What's GNU? Gnu's Not Unix!
@ -1249,6 +1250,11 @@ Emacs and macOS / GNUstep
* Mac / GNUstep Events:: How window system events are handled.
* GNUstep Support:: Details on status of GNUstep support.
Emacs and Haiku
* Haiku Basics:: Basic Emacs usage and installation under Haiku.
* Haiku Fonts:: The various options for displaying fonts on Haiku.
Emacs and Microsoft Windows/MS-DOS
* Windows Startup:: How to start Emacs on Windows.
@ -1618,6 +1624,7 @@ Lisp programming.
@include anti.texi
@include macos.texi
@include haiku.texi
@c Includes msdos-xtra.
@include msdos.texi
@include gnu.texi

136
doc/emacs/haiku.texi Normal file
View file

@ -0,0 +1,136 @@
@c This is part of the Emacs manual.
@c Copyright (C) 2021 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Haiku
@appendix Emacs and Haiku
@cindex Haiku
Haiku is a Unix-like operating system that originated as a
re-implementation of the operating system BeOS.
This section describes the peculiarities of using Emacs built with
the Application Kit, the windowing system native to Haiku. The
oddities described here do not apply to using Emacs on Haiku built
without windowing support, or built with X11.
@menu
* Haiku Basics:: Basic Emacs usage and installation under Haiku.
* Haiku Fonts:: The various options for displaying fonts on Haiku.
@end menu
@node Haiku Basics
@section Installation and usage peculiarities under Haiku
@cindex haiku application
@cindex haiku installation
Emacs installs two separate executables under Haiku; it is up to the
user to decide which one suits him best: A regular executable, with
the lowercase name @code{emacs}, and a binary containing
Haiku-specific application metadata, with the name @code{Emacs}.
@cindex launching Emacs from the tracker
@cindex tty Emacs in haiku
If you are launching Emacs from the Tracker, or want to make the
Tracker open files using Emacs, you should use the binary named
@code{Emacs}; ff you are going to use Emacs in the terminal, or wish
to launch separate instances of Emacs, or do not care for the
aforementioned system integration features, use the binary named
@code{emacs} instead.
@cindex modifier keys and system keymap (Haiku)
@cindex haiku keymap
On Haiku, unusual modifier keys such as the Hyper key are
unsupported. By default, the super key corresponds with the option
key defined by the operating system, the meta key with the command
key, the control key with the system control key, and the shift key
with the system shift key. On a standard PC keyboard, Haiku should
map these keys to positions familiar to those using a GNU system, but
this may require some adjustment to your system's configuration to
work.
It is impossible to type accented characters using the system super
key map.
You can customize the correspondence between modifier keys known to
the system, and those known to Emacs. The variables that allow for
that are described below.
@cindex modifier key customization (Haiku)
You can customize which Emacs modifiers the various system modifier
keys correspond to through the following variables:
@table @code
@vindex haiku-meta-keysym
@item haiku-meta-keysym
The system modifier key that will be treated as the Meta key by Emacs.
It defaults to @code{command}.
@vindex haiku-control-keysym
@item haiku-control-keysym
The system modifier key that will be treated as the Control key by
Emacs. It defaults to @code{control}.
@vindex haiku-super-keysym
@item haiku-super-keysym
The system modifier key that will be treated as the Super key by
Emacs. It defaults to @code{option}.
@vindex haiku-shift-keysym
@item haiku-shift-keysym
The system modifier key that will be treated as the Shift key by
Emacs. It defaults to @code{shift}.
@end table
The value of each variable can be one of the symbols @code{command},
@code{control}, @code{option}, @code{shift}, or @code{nil}.
@code{nil} or any other value will cause the default value to be used
instead.
@cindex tooltips (haiku)
@cindex haiku tooltips
@vindex haiku-use-system-tooltips
On Haiku, Emacs defaults to using the system tooltip mechanism.
This usually leads to more responsive tooltips, but the tooltips will
not be able to display text properties or faces. If you need those
features, customize the variable @code{haiku-use-system-tooltips} to
the nil value, and Emacs will use its own implementation of tooltips.
Both system tooltips and Emacs's own tooltips cannot display above
the menu bar, so help text in the menu bar will display in the echo
area instead.
@subsection What to do when Emacs crashes
@cindex crashes, Haiku
@cindex haiku debugger
@vindex haiku-debug-on-fatal-error
If the variable @code{haiku-debug-on-fatal-error} is non-nil, Emacs
will launch the system debugger when a fatal signal is received. It
defaults to @code{t}. If GDB cannot be used on your system, please
attach the report generated by the system debugger when reporting a
bug.
@table @code
@vindex haiku-use-system-debugger
@item haiku-use-system-debugger
When non-nil, Emacs will ask the system to launch the system debugger
whenever it experiences a fatal error. This behaviour is standard
among Haiku applications.
@end table
@node Haiku Fonts
@section Font and font backend selection on Haiku
@cindex font backend selection (Haiku)
Emacs, when built with Haiku windowing support, can be built with
several different font backends. You can specify font backends by
specifying @kbd{-xrm Emacs.fontBackend:BACKEND} on the command line
used to invoke Emacs, where @kbd{BACKEND} is one of the backends
specified below, or on a per-frame basis by changing the
@code{font-backend} frame parameter. (@pxref{Parameter Access,,,
elisp, The Emacs Lisp Reference Manual}).
Two of these backends, @code{ftcr} and @code{ftcrhb} are identical
to their counterparts on the X Window System. There is also a
Haiku-specific backend named @code{haiku}, that uses the App Server to
draw fonts, but does not at present support display of color font and
emoji.

View file

@ -2767,8 +2767,9 @@ apply to. Here are the possible values of @var{characteristic}:
@item type
The kind of window system the terminal uses---either @code{graphic}
(any graphics-capable display), @code{x}, @code{pc} (for the MS-DOS
console), @code{w32} (for MS Windows 9X/NT/2K/XP), or @code{tty} (a
non-graphics-capable display). @xref{Window Systems, window-system}.
console), @code{w32} (for MS Windows 9X/NT/2K/XP), @code{haiku} (for
Haiku), or @code{tty} (a non-graphics-capable display).
@xref{Window Systems, window-system}.
@item class
What kinds of colors the terminal supports---either @code{color},
@ -8274,6 +8275,8 @@ Emacs is displaying the frame using the Nextstep interface (used on
GNUstep and macOS).
@item pc
Emacs is displaying the frame using MS-DOS direct screen writes.
@item haiku
Emacs is displaying the frame using the Application Kit on Haiku.
@item nil
Emacs is displaying the frame on a character-based terminal.
@end table
@ -8320,6 +8323,7 @@ area. On text-mode (a.k.a.@: ``TTY'') frames, tooltips are always
displayed in the echo area.
@end defun
@cindex system tooltips
@vindex x-gtk-use-system-tooltips
When Emacs is built with GTK+ support, it by default displays tooltips
using GTK+ functions, and the appearance of the tooltips is then

View file

@ -214,7 +214,8 @@ The terminal and keyboard coding systems used on the terminal.
@item
The kind of display associated with the terminal. This is the symbol
returned by the function @code{terminal-live-p} (i.e., @code{x},
@code{t}, @code{w32}, @code{ns}, or @code{pc}). @xref{Frames}.
@code{t}, @code{w32}, @code{ns}, @code{pc}, or @code{haiku}).
@xref{Frames}.
@item
A list of terminal parameters. @xref{Terminal Parameters}.
@ -680,7 +681,7 @@ indicate that position for the various builds:
@itemize @w{}
@item (1) non-toolkit and terminal frames
@item (2) Lucid, Motif and MS-Windows frames
@item (2) Lucid, Motif, MS-Windows, and Haiku frames
@item (3) GTK+ and NS frames
@end itemize
@ -1729,7 +1730,9 @@ fit will be clipped by the window manager.
@item fullscreen
This parameter specifies whether to maximize the frame's width, height
or both. Its value can be @code{fullwidth}, @code{fullheight},
@code{fullboth}, or @code{maximized}. A @dfn{fullwidth} frame is as
@code{fullboth}, or @code{maximized}.@footnote{On Haiku, setting
@code{fullscreen} to @code{fullwidth} or @code{fullheight} has no
effect.} A @dfn{fullwidth} frame is as
wide as possible, a @dfn{fullheight} frame is as tall as possible, and
a @dfn{fullboth} frame is both as wide and as tall as possible. A
@dfn{maximized} frame is like a ``fullboth'' frame, except that it usually
@ -2191,7 +2194,10 @@ either via @code{focus-follows-mouse} (@pxref{Input Focus}) or
@code{mouse-autoselect-window} (@pxref{Mouse Window Auto-selection}).
This may have the unwanted side-effect that a user cannot scroll a
non-selected frame with the mouse. Some window managers may not honor
this parameter.
this parameter. On Haiku, it also has the side-effect that the window
will not be able to receive any keyboard input from the user, not even
if the user switches to the frame using the key combination
@kbd{Alt-@key{TAB}}.
@vindex undecorated@r{, a frame parameter}
@item undecorated
@ -2352,7 +2358,10 @@ driver for OTF and TTF fonts with text shaping by the Uniscribe
engine), and @code{harfbuzz} (font driver for OTF and TTF fonts with
HarfBuzz text shaping) (@pxref{Windows Fonts,,, emacs, The GNU Emacs
Manual}). The @code{harfbuzz} driver is similarly recommended. On
other systems, there is only one available font backend, so it does
Haiku, there can be several font drivers (@pxref{Haiku Fonts,,, emacs,
The GNU Emacs Manual}).
On other systems, there is only one available font backend, so it does
not make sense to modify this frame parameter.
@vindex background-mode@r{, a frame parameter}
@ -3141,8 +3150,10 @@ raises @var{frame} above all other child frames of its parent.
@deffn Command lower-frame &optional frame
This function lowers frame @var{frame} (default, the selected frame)
below all other frames belonging to the same or a higher z-group as
@var{frame}. If @var{frame} is a child frame (@pxref{Child Frames}),
this lowers @var{frame} below all other child frames of its parent.
@var{frame}.@footnote{Lowering frames is not supported on Haiku, due
to limitations imposed by the system.} If @var{frame} is a child
frame (@pxref{Child Frames}), this lowers @var{frame} below all other
child frames of its parent.
@end deffn
@defun frame-restack frame1 frame2 &optional above
@ -3152,7 +3163,8 @@ that if both frames are visible and their display areas overlap,
third argument @var{above} is non-@code{nil}, this function restacks
@var{frame1} above @var{frame2}. This means that if both frames are
visible and their display areas overlap, @var{frame1} will (partially)
obscure @var{frame2}.
obscure @var{frame2}.@footnote{Restacking frames is not supported on
Haiku, due to limitations imposed by the system.}
Technically, this function may be thought of as an atomic action
performed in two steps: The first step removes @var{frame1}'s
@ -3247,12 +3259,16 @@ parent frame's window-system window.
@cindex reparent frame
@cindex nest frame
The @code{parent-frame} parameter can be changed at any time. Setting
it to another frame @dfn{reparents} the child frame. Setting it to
another child frame makes the frame a @dfn{nested} child frame. Setting
it to @code{nil} restores the frame's status as a top-level frame---a
frame whose window-system window is a child of its display's root
window.
The @code{parent-frame} parameter can be changed at any time.
Setting it to another frame @dfn{reparents} the child frame. Setting
it to another child frame makes the frame a @dfn{nested} child frame.
Setting it to @code{nil} restores the frame's status as a top-level
frame---a frame whose window-system window is a child of its display's
root window.@footnote{On Haiku, child frames are only visible when a
parent frame is active, owing to a limitation of the Haiku windowing
system. Owing to the same limitation, child frames are only
guaranteed to appear above their top-level parent; that is to say, the
top-most frame in the hierarchy, which does not have a parent frame.}
Since child frames can be arbitrarily nested, a frame can be both a
child and a parent frame. Also, the relative roles of child and parent

View file

@ -947,6 +947,9 @@ actually Linux is just the kernel, not the whole system.)
@item gnu/kfreebsd
A GNU (glibc-based) system with a FreeBSD kernel.
@item haiku
The Haiku operating system, a derivative of the Be Operating System.
@item hpux
Hewlett-Packard HPUX operating system.

View file

@ -103,6 +103,34 @@ the list at the end of this file.
./configure CC='gcc -m64' # GCC
./configure CC='cc -m64' # Oracle Developer Studio
** Haiku
On 32-bit Haiku it is required that the newer GCC 8 be used, instead
of the legacy GCC 2 used by default. This can be achieved by
invoking configure inside a shell launched by the 'setarch' program
invoked as 'setarch x86'.
When building with packages discovered through pkg-config, such as
libpng, on a GCC 2/GCC 8 hybrid system, simply evaluating 'setarch
x86' is insufficient to ensure that all required libraries are found
at their correct locations. To avoid this problem, set the
environment variable 'PKG_CONFIG_PATH' to the GCC 8 pkg-config
directory at '/system/develop/lib/x86/pkgconfig/' before configuring
Emacs.
If GCC complains about not being able to resolve symbols such as
"BHandler::LockLooper", you are almost certainly experiencing this
problem.
Haiku running on non-x86 systems has not been tested. It is
anticipated that Haiku running on big-endian systems will experience
problems when Emacs is built with Haiku windowing support, but there
doesn't seem to be any reliable way to get Haiku running on a
big-endian system at present.
The earliest release of Haiku that will successfully compile Emacs
is R1/Beta2. For windowing support, R1/Beta3 or later is required.
* Obsolete platforms

View file

@ -24,6 +24,27 @@ applies, and please also update docstrings as needed.
* Installation Changes in Emacs 29.1
** Emacs has been ported to the Haiku operating system.
The configuration process should automatically detect and build for
Haiku. There is also an optional window-system port to Haiku, which
can be enabled by configuring Emacs with the option '--with-be-app',
which will require the Haiku Application Kit development headers and a
C++ compiler to be present on your system. If Emacs is not built with
the option '--with-be-app', the resulting Emacs will only run in
text-mode terminals.
+++
*** Cairo drawing support has been enabled for Haiku builds.
To enable Cairo support, ensure that the Cairo and FreeType
development files are present on your system, and configure Emacs with
'--with-be-cairo'.
---
*** Double buffering is now enabled on the Haiku operating system.
Unlike X, there is no compile-time option to enable or disable
double-buffering. If you wish to disable double-buffering, change the
frame parameter `inhibit-double-buffering' instead.
** Emacs now installs the ".pdmp" file using a unique fingerprint in the name.
The file is typically installed using a file name akin to
"...dir/libexec/emacs/29.1/x86_64-pc-linux-gnu/emacs-<fingerprint>.pdmp".

View file

@ -1022,6 +1022,15 @@ modern fonts are used, such as Noto Emoji or Ebrima.
The solution is to switch to a configuration that uses HarfBuzz as its
shaping engine, where these problems don't exist.
** On Haiku, some proportionally-spaced fonts display with artifacting.
This is a Haiku bug: https://dev.haiku-os.org/ticket/17229, which can
be remedied by using a different font that does not exhibit this
problem, or by configuring Emacs '--with-be-cairo'.
So far, Bitstream Charter and Noto Sans have been known to exhibit
this problem, while Noto Sans Display is known to not do so.
* Internationalization problems
** M-{ does not work on a Spanish PC keyboard.
@ -1105,6 +1114,13 @@ In your ~/.Xresources file, then run
And restart Emacs.
** On Haiku, BeCJK doesn't work properly with Emacs
Some popular Haiku input methods such BeCJK are known to behave badly
when interacting with Emacs, in ways such as stealing input focus and
displaying popup windows that don't disappear. If you are affected,
you should use an Emacs input method instead.
* X runtime problems
** X keyboard problems

View file

@ -27,7 +27,9 @@ EMACSOPT = -batch --no-site-file --no-site-lisp
# ==================== Things 'configure' will edit ====================
CC=@CC@
CXX=@CXX@
CFLAGS=@CFLAGS@
CXXFLAGS=@CXXFLAGS@
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
@ -130,6 +132,11 @@ MKDIR_P = @MKDIR_P@
# ========================== Lists of Files ===========================
## Haiku build-time support
HAVE_BE_APP=@HAVE_BE_APP@
HAIKU_LIBS=@HAIKU_LIBS@
HAIKU_CFLAGS=@HAIKU_CFLAGS@
# emacsclientw.exe for MinGW, empty otherwise
CLIENTW = @CLIENTW@
@ -143,7 +150,11 @@ UTILITIES = hexl${EXEEXT} \
$(if $(with_mailutils), , movemail${EXEEXT}) \
$(and $(use_gamedir), update-game-score${EXEEXT})
ifeq ($(HAVE_BE_APP),yes)
DONT_INSTALL= make-docfile${EXEEXT} make-fingerprint${EXEEXT} be-resources
else
DONT_INSTALL= make-docfile${EXEEXT} make-fingerprint${EXEEXT}
endif
# Like UTILITIES, but they're not system-dependent, and should not be
# deleted by the distclean target.
@ -230,6 +241,10 @@ WINDRES = @WINDRES@
## Some systems define this to request special libraries.
LIBS_SYSTEM = @LIBS_SYSTEM@
# Flags that could be in WARN_CFLAGS, but are invalid for C++.
NON_CXX_CFLAGS = -Wmissing-prototypes -Wnested-externs -Wold-style-definition \
-Wstrict-prototypes -Wno-override-init
BASE_CFLAGS = $(C_SWITCH_SYSTEM) $(C_SWITCH_MACHINE) \
$(WARN_CFLAGS) $(WERROR_CFLAGS) \
-I. -I../src -I../lib \
@ -238,6 +253,9 @@ BASE_CFLAGS = $(C_SWITCH_SYSTEM) $(C_SWITCH_MACHINE) \
ALL_CFLAGS = ${BASE_CFLAGS} ${PROFILING_CFLAGS} ${LDFLAGS} ${CPPFLAGS} ${CFLAGS}
CPP_CFLAGS = ${BASE_CFLAGS} ${PROFILING_CFLAGS} ${CPPFLAGS} ${CFLAGS}
ALL_CXXFLAGS = $(filter-out ${NON_CXX_CFLAGS},${BASE_CFLAGS}) \
${PROFILING_CFLAGS} ${LDFLAGS} ${CPPFLAGS} ${CFLAGS} ${CXXFLAGS} ${HAIKU_CFLAGS}
# Configuration files for .o files to depend on.
config_h = ../src/config.h $(srcdir)/../src/conf_post.h
@ -407,6 +425,9 @@ emacsclientw${EXEEXT}: ${srcdir}/emacsclient.c $(NTLIB) $(CLIENTRES) $(config_h)
$(LOADLIBES) \
$(LIB_WSOCK32) $(LIB_EACCESS) $(LIBS_ECLIENT) -o $@
be-resources: ${srcdir}/be_resources.cc ${config_h}
$(AM_V_CXXLD)$(CXX) ${ALL_CXXFLAGS} ${HAIKU_LIBS} $< -o $@
NTINC = ${srcdir}/../nt/inc
NTDEPS = $(NTINC)/ms-w32.h $(NTINC)/sys/stat.h $(NTINC)/inttypes.h \
$(NTINC)/stdint.h $(NTINC)/pwd.h $(NTINC)/sys/time.h $(NTINC)/stdbool.h \

144
lib-src/be_resources.cc Normal file
View file

@ -0,0 +1,144 @@
/* Haiku window system support
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <SupportDefs.h>
#include <Path.h>
#include <AppFileInfo.h>
#include <TranslationUtils.h>
#include <Application.h>
#include <Catalog.h>
#include <Roster.h>
using namespace std;
static void
be_perror (status_t code, char *arg)
{
if (code != B_OK)
{
switch (code)
{
case B_BAD_VALUE:
fprintf (stderr, "%s: Bad value\n", arg);
break;
case B_ENTRY_NOT_FOUND:
fprintf (stderr, "%s: Not found\n", arg);
break;
case B_PERMISSION_DENIED:
fprintf (stderr, "%s: Permission denied\n", arg);
break;
case B_NO_MEMORY:
fprintf (stderr, "%s: No memory\n", arg);
break;
case B_LINK_LIMIT:
fprintf (stderr, "%s: Link limit reached\n", arg);
break;
case B_BUSY:
fprintf (stderr, "%s: Busy\n", arg);
break;
case B_NO_MORE_FDS:
fprintf (stderr, "%s: No more file descriptors\n", arg);
break;
case B_FILE_ERROR:
fprintf (stderr, "%s: File error\n", arg);
break;
default:
fprintf (stderr, "%s: Unknown error\n", arg);
}
}
else
{
abort ();
}
}
int
main (int argc, char **argv)
{
BApplication app ("application/x-vnd.GNU-emacs-resource-helper");
BFile file;
BBitmap *icon;
BAppFileInfo info;
status_t code;
struct version_info vinfo;
char *v = strdup (PACKAGE_VERSION);
if (argc != 3)
{
printf ("be-resources ICON FILE: make FILE appropriate for Emacs.\n");
return EXIT_FAILURE;
}
code = file.SetTo (argv[2], B_READ_WRITE);
if (code != B_OK)
{
be_perror (code, argv[2]);
return EXIT_FAILURE;
}
code = info.SetTo (&file);
if (code != B_OK)
{
be_perror (code, argv[2]);
return EXIT_FAILURE;
}
code = info.SetAppFlags (B_EXCLUSIVE_LAUNCH | B_ARGV_ONLY);
if (code != B_OK)
{
be_perror (code, argv[2]);
return EXIT_FAILURE;
}
icon = BTranslationUtils::GetBitmapFile (argv[1], NULL);
if (!icon)
{
be_perror (B_ERROR, argv[1]);
return EXIT_FAILURE;
}
info.SetIcon (icon, B_MINI_ICON);
info.SetIcon (icon, B_LARGE_ICON);
info.SetSignature ("application/x-vnd.GNU-emacs");
v = strtok (v, ".");
vinfo.major = atoi (v);
v = strtok (NULL, ".");
vinfo.middle = atoi (v);
v = strtok (NULL, ".");
vinfo.minor = v ? atoi (v) : 0;
vinfo.variety = 0;
vinfo.internal = 0;
strncpy ((char *) &vinfo.short_info, PACKAGE_VERSION,
sizeof vinfo.short_info - 1);
strncpy ((char *) &vinfo.long_info, PACKAGE_STRING,
sizeof vinfo.long_info - 1);
info.SetVersionInfo (&vinfo, B_APP_VERSION_KIND);
return EXIT_SUCCESS;
}

View file

@ -603,6 +603,8 @@ decode_options (int argc, char **argv)
alt_display = "ns";
#elif defined (HAVE_NTGUI)
alt_display = "w32";
#elif defined (HAVE_HAIKU)
alt_display = "be";
#endif
display = egetenv ("DISPLAY");

View file

@ -2176,7 +2176,7 @@ and `face'."
;;; The `custom' Widget.
(defface custom-button
'((((type x w32 ns) (class color)) ; Like default mode line
'((((type x w32 ns haiku) (class color)) ; Like default mode line
:box (:line-width 2 :style released-button)
:background "lightgrey" :foreground "black"))
"Face for custom buffer buttons if `custom-raised-buttons' is non-nil."
@ -2184,7 +2184,7 @@ and `face'."
:group 'custom-faces)
(defface custom-button-mouse
'((((type x w32 ns) (class color))
'((((type x w32 ns haiku) (class color))
:box (:line-width 2 :style released-button)
:background "grey90" :foreground "black")
(t
@ -2209,7 +2209,7 @@ and `face'."
(if custom-raised-buttons 'custom-button-mouse 'highlight))
(defface custom-button-pressed
'((((type x w32 ns) (class color))
'((((type x w32 ns haiku) (class color))
:box (:line-width 2 :style pressed-button)
:background "lightgrey" :foreground "black")
(t :inverse-video t))

View file

@ -829,7 +829,11 @@ since it could result in memory overflow and make Emacs crash."
;; xselect.c
(x-select-enable-clipboard-manager killing boolean "24.1")
;; xsettings.c
(font-use-system-font font-selection boolean "23.2")))
(font-use-system-font font-selection boolean "23.2")
;; haikuterm.c
(haiku-debug-on-fatal-error debug boolean "29.1")
;; haikufns.c
(haiku-use-system-tooltips tooltip boolean "29.1")))
(setq ;; If we did not specify any standard value expression above,
;; use the current value as the standard value.
standard (if (setq prop (memq :standard rest))
@ -846,6 +850,8 @@ since it could result in memory overflow and make Emacs crash."
(eq system-type 'windows-nt))
((string-match "\\`ns-" (symbol-name symbol))
(featurep 'ns))
((string-match "\\`haiku-" (symbol-name symbol))
(featurep 'haiku))
((string-match "\\`x-.*gtk" (symbol-name symbol))
(featurep 'gtk))
((string-match "clipboard-manager" (symbol-name symbol))

View file

@ -1172,7 +1172,7 @@ an integer value."
(:height
'integerp)
(:stipple
(and (memq (window-system frame) '(x ns)) ; No stipple on w32
(and (memq (window-system frame) '(x ns)) ; No stipple on w32 or haiku
(mapcar #'list
(apply #'nconc
(mapcar (lambda (dir)
@ -2822,7 +2822,7 @@ Note: Other faces cannot inherit from the cursor face."
'((default
:box (:line-width 1 :style released-button)
:foreground "black")
(((type x w32 ns) (class color))
(((type x w32 ns haiku) (class color))
:background "grey75")
(((type x) (class mono))
:background "grey"))

View file

@ -1633,6 +1633,7 @@ live frame and defaults to the selected one."
(declare-function x-frame-geometry "xfns.c" (&optional frame))
(declare-function w32-frame-geometry "w32fns.c" (&optional frame))
(declare-function ns-frame-geometry "nsfns.m" (&optional frame))
(declare-function haiku-frame-geometry "haikufns.c" (&optional frame))
(defun frame-geometry (&optional frame)
"Return geometric attributes of FRAME.
@ -1682,6 +1683,8 @@ and width values are in pixels.
(w32-frame-geometry frame))
((eq frame-type 'ns)
(ns-frame-geometry frame))
((eq frame-type 'haiku)
(haiku-frame-geometry frame))
(t
(list
'(outer-position 0 . 0)
@ -1806,6 +1809,7 @@ of frames like calls to map a frame or change its visibility."
(declare-function x-frame-edges "xfns.c" (&optional frame type))
(declare-function w32-frame-edges "w32fns.c" (&optional frame type))
(declare-function ns-frame-edges "nsfns.m" (&optional frame type))
(declare-function haiku-frame-edges "haikufns.c" (&optional frame type))
(defun frame-edges (&optional frame type)
"Return coordinates of FRAME's edges.
@ -1829,12 +1833,15 @@ FRAME."
(w32-frame-edges frame type))
((eq frame-type 'ns)
(ns-frame-edges frame type))
((eq frame-type 'haiku)
(haiku-frame-edges frame type))
(t
(list 0 0 (frame-width frame) (frame-height frame))))))
(declare-function w32-mouse-absolute-pixel-position "w32fns.c")
(declare-function x-mouse-absolute-pixel-position "xfns.c")
(declare-function ns-mouse-absolute-pixel-position "nsfns.m")
(declare-function haiku-mouse-absolute-pixel-position "haikufns.c")
(defun mouse-absolute-pixel-position ()
"Return absolute position of mouse cursor in pixels.
@ -1849,12 +1856,15 @@ position (0, 0) of the selected frame's terminal."
(w32-mouse-absolute-pixel-position))
((eq frame-type 'ns)
(ns-mouse-absolute-pixel-position))
((eq frame-type 'haiku)
(haiku-mouse-absolute-pixel-position))
(t
(cons 0 0)))))
(declare-function ns-set-mouse-absolute-pixel-position "nsfns.m" (x y))
(declare-function w32-set-mouse-absolute-pixel-position "w32fns.c" (x y))
(declare-function x-set-mouse-absolute-pixel-position "xfns.c" (x y))
(declare-function haiku-set-mouse-absolute-pixel-position "haikufns.c" (x y))
(defun set-mouse-absolute-pixel-position (x y)
"Move mouse pointer to absolute pixel position (X, Y).
@ -1867,7 +1877,9 @@ position (0, 0) of the selected frame's terminal."
((eq frame-type 'x)
(x-set-mouse-absolute-pixel-position x y))
((eq frame-type 'w32)
(w32-set-mouse-absolute-pixel-position x y)))))
(w32-set-mouse-absolute-pixel-position x y))
((eq frame-type 'haiku)
(haiku-set-mouse-absolute-pixel-position x y)))))
(defun frame-monitor-attributes (&optional frame)
"Return the attributes of the physical monitor dominating FRAME.
@ -1960,6 +1972,7 @@ workarea attribute."
(declare-function x-frame-list-z-order "xfns.c" (&optional display))
(declare-function w32-frame-list-z-order "w32fns.c" (&optional display))
(declare-function ns-frame-list-z-order "nsfns.m" (&optional display))
(declare-function haiku-frame-list-z-order "haikufns.c" (&optional display))
(defun frame-list-z-order (&optional display)
"Return list of Emacs' frames, in Z (stacking) order.
@ -1979,7 +1992,9 @@ Return nil if DISPLAY contains no Emacs frame."
((eq frame-type 'w32)
(w32-frame-list-z-order display))
((eq frame-type 'ns)
(ns-frame-list-z-order display)))))
(ns-frame-list-z-order display))
((eq frame-type 'haiku)
(haiku-frame-list-z-order display)))))
(declare-function x-frame-restack "xfns.c" (frame1 frame2 &optional above))
(declare-function w32-frame-restack "w32fns.c" (frame1 frame2 &optional above))
@ -2060,8 +2075,8 @@ frame's display)."
((eq frame-type 'w32)
(with-no-warnings
(> w32-num-mouse-buttons 0)))
((memq frame-type '(x ns))
t) ;; We assume X and NeXTstep *always* have a pointing device
((memq frame-type '(x ns haiku))
t) ;; We assume X, NeXTstep and Haiku *always* have a pointing device
(t
(or (and (featurep 'xt-mouse)
xterm-mouse-mode)
@ -2086,7 +2101,7 @@ frames and several different fonts at once. This is true for displays
that use a window system such as X, and false for text-only terminals.
DISPLAY can be a display name, a frame, or nil (meaning the selected
frame's display)."
(not (null (memq (framep-on-display display) '(x w32 ns)))))
(not (null (memq (framep-on-display display) '(x w32 ns haiku)))))
(defun display-images-p (&optional display)
"Return non-nil if DISPLAY can display images.
@ -2137,7 +2152,7 @@ DISPLAY should be either a frame or a display name (a string).
If DISPLAY is omitted or nil, it defaults to the selected frame's display."
(let ((frame-type (framep-on-display display)))
(cond
((memq frame-type '(x w32 ns))
((memq frame-type '(x w32 ns haiku))
(x-display-screens display))
(t
1))))
@ -2157,7 +2172,7 @@ with DISPLAY. To get information for each physical monitor, use
`display-monitor-attributes-list'."
(let ((frame-type (framep-on-display display)))
(cond
((memq frame-type '(x w32 ns))
((memq frame-type '(x w32 ns haiku))
(x-display-pixel-height display))
(t
(frame-height (if (framep display) display (selected-frame)))))))
@ -2177,7 +2192,7 @@ with DISPLAY. To get information for each physical monitor, use
`display-monitor-attributes-list'."
(let ((frame-type (framep-on-display display)))
(cond
((memq frame-type '(x w32 ns))
((memq frame-type '(x w32 ns haiku))
(x-display-pixel-width display))
(t
(frame-width (if (framep display) display (selected-frame)))))))
@ -2215,7 +2230,7 @@ For graphical terminals, note that on \"multi-monitor\" setups this
refers to the height in millimeters for all physical monitors
associated with DISPLAY. To get information for each physical
monitor, use `display-monitor-attributes-list'."
(and (memq (framep-on-display display) '(x w32 ns))
(and (memq (framep-on-display display) '(x w32 ns haiku))
(or (cddr (assoc (or display (frame-parameter nil 'display))
display-mm-dimensions-alist))
(cddr (assoc t display-mm-dimensions-alist))
@ -2236,7 +2251,7 @@ For graphical terminals, note that on \"multi-monitor\" setups this
refers to the width in millimeters for all physical monitors
associated with DISPLAY. To get information for each physical
monitor, use `display-monitor-attributes-list'."
(and (memq (framep-on-display display) '(x w32 ns))
(and (memq (framep-on-display display) '(x w32 ns haiku))
(or (cadr (assoc (or display (frame-parameter nil 'display))
display-mm-dimensions-alist))
(cadr (assoc t display-mm-dimensions-alist))
@ -2254,7 +2269,7 @@ DISPLAY can be a display name or a frame.
If DISPLAY is omitted or nil, it defaults to the selected frame's display."
(let ((frame-type (framep-on-display display)))
(cond
((memq frame-type '(x w32 ns))
((memq frame-type '(x w32 ns haiku))
(x-display-backing-store display))
(t
'not-useful))))
@ -2267,7 +2282,7 @@ DISPLAY can be a display name or a frame.
If DISPLAY is omitted or nil, it defaults to the selected frame's display."
(let ((frame-type (framep-on-display display)))
(cond
((memq frame-type '(x w32 ns))
((memq frame-type '(x w32 ns haiku))
(x-display-save-under display))
(t
'not-useful))))
@ -2280,7 +2295,7 @@ DISPLAY can be a display name or a frame.
If DISPLAY is omitted or nil, it defaults to the selected frame's display."
(let ((frame-type (framep-on-display display)))
(cond
((memq frame-type '(x w32 ns))
((memq frame-type '(x w32 ns haiku))
(x-display-planes display))
((eq frame-type 'pc)
4)
@ -2295,7 +2310,7 @@ DISPLAY can be a display name or a frame.
If DISPLAY is omitted or nil, it defaults to the selected frame's display."
(let ((frame-type (framep-on-display display)))
(cond
((memq frame-type '(x w32 ns))
((memq frame-type '(x w32 ns haiku))
(x-display-color-cells display))
((eq frame-type 'pc)
16)
@ -2312,7 +2327,7 @@ DISPLAY can be a display name or a frame.
If DISPLAY is omitted or nil, it defaults to the selected frame's display."
(let ((frame-type (framep-on-display display)))
(cond
((memq frame-type '(x w32 ns))
((memq frame-type '(x w32 ns haiku))
(x-display-visual-class display))
((and (memq frame-type '(pc t))
(tty-display-color-p display))

View file

@ -88,7 +88,7 @@
(bindings--define-key map [separator-3] menu-bar-separator)
(bindings--define-key map [set-terminal-coding-system]
'(menu-item "For Terminal" set-terminal-coding-system
:enable (null (memq initial-window-system '(x w32 ns)))
:enable (null (memq initial-window-system '(x w32 ns haiku)))
:help "How to encode terminal output"))
(bindings--define-key map [set-keyboard-coding-system]
'(menu-item "For Keyboard" set-keyboard-coding-system

View file

@ -303,6 +303,11 @@
(load "term/common-win")
(load "term/x-win")))
(if (featurep 'haiku)
(progn
(load "term/common-win")
(load "term/haiku-win")))
(if (or (eq system-type 'windows-nt)
(featurep 'w32))
(progn
@ -558,6 +563,7 @@ lost after dumping")))
(delete-file output)))))
;; Recompute NAME now, so that it isn't set when we dump.
(if (not (or (eq system-type 'ms-dos)
(eq system-type 'haiku) ;; BFS doesn't support hard links
;; Don't bother adding another name if we're just
;; building bootstrap-emacs.
(member dump-mode '("pbootstrap" "bootstrap"))))

View file

@ -2540,6 +2540,7 @@ See `menu-bar-mode' for more information."
(declare-function x-menu-bar-open "term/x-win" (&optional frame))
(declare-function w32-menu-bar-open "term/w32-win" (&optional frame))
(declare-function haiku-menu-bar-open "haikumenu.c" (&optional frame))
(defun lookup-key-ignore-too-long (map key)
"Call `lookup-key' and convert numeric values to nil."
@ -2665,9 +2666,10 @@ first TTY menu-bar menu to be dropped down. Interactively,
this is the numeric argument to the command.
This function decides which method to use to access the menu
depending on FRAME's terminal device. On X displays, it calls
`x-menu-bar-open'; on Windows, `w32-menu-bar-open'; otherwise it
calls either `popup-menu' or `tmm-menubar' depending on whether
`tty-menu-open-use-tmm' is nil or not.
`x-menu-bar-open'; on Windows, `w32-menu-bar-open'; on Haiku,
`haiku-menu-bar-open'; otherwise it calls either `popup-menu'
or `tmm-menubar' depending on whether `tty-menu-open-use-tmm'
is nil or not.
If FRAME is nil or not given, use the selected frame."
(interactive
@ -2676,6 +2678,7 @@ If FRAME is nil or not given, use the selected frame."
(cond
((eq type 'x) (x-menu-bar-open frame))
((eq type 'w32) (w32-menu-bar-open frame))
((eq type 'haiku) (haiku-menu-bar-open frame))
((and (null tty-menu-open-use-tmm)
(not (zerop (or (frame-parameter nil 'menu-bar-lines) 0))))
;; Make sure the menu bar is up to date. One situation where

View file

@ -55,7 +55,8 @@
(mouse-wheel-mode 1)))
(defcustom mouse-wheel-down-event
(if (or (featurep 'w32-win) (featurep 'ns-win))
(if (or (featurep 'w32-win) (featurep 'ns-win)
(featurep 'haiku-win))
'wheel-up
'mouse-4)
"Event used for scrolling down."
@ -71,7 +72,8 @@
:set 'mouse-wheel-change-button)
(defcustom mouse-wheel-up-event
(if (or (featurep 'w32-win) (featurep 'ns-win))
(if (or (featurep 'w32-win) (featurep 'ns-win)
(featurep 'haiku-win))
'wheel-down
'mouse-5)
"Event used for scrolling up."
@ -235,7 +237,8 @@ Also see `mouse-wheel-tilt-scroll'."
"Function that does the job of scrolling right.")
(defvar mouse-wheel-left-event
(if (or (featurep 'w32-win) (featurep 'ns-win))
(if (or (featurep 'w32-win) (featurep 'ns-win)
(featurep 'haiku-win))
'wheel-left
'mouse-6)
"Event used for scrolling left.")
@ -245,7 +248,8 @@ Also see `mouse-wheel-tilt-scroll'."
"Alternative wheel left event to consider.")
(defvar mouse-wheel-right-event
(if (or (featurep 'w32-win) (featurep 'ns-win))
(if (or (featurep 'w32-win) (featurep 'ns-win)
(featurep 'haiku-win))
'wheel-right
'mouse-7)
"Event used for scrolling right.")

View file

@ -39,6 +39,7 @@
;; browse-url-chrome Chrome 47.0.2526.111
;; browse-url-chromium Chromium 3.0
;; browse-url-epiphany Epiphany Don't know
;; browse-url-webpositive WebPositive 1.2-alpha (Haiku R1/beta3)
;; browse-url-w3 w3 0
;; browse-url-text-* Any text browser 0
;; browse-url-generic arbitrary
@ -156,6 +157,7 @@
(function-item :tag "Google Chrome" :value browse-url-chrome)
(function-item :tag "Chromium" :value browse-url-chromium)
(function-item :tag "Epiphany" :value browse-url-epiphany)
(function-item :tag "WebPositive" :value browse-url-webpositive)
(function-item :tag "Text browser in an xterm window"
:value browse-url-text-xterm)
(function-item :tag "Text browser in an Emacs window"
@ -366,6 +368,11 @@ Defaults to the value of `browse-url-epiphany-arguments' at the time
`browse-url' is loaded."
:type '(repeat (string :tag "Argument")))
(defcustom browse-url-webpositive-program "WebPositive"
"The name by which to invoke WebPositive."
:type 'string
:version "28.1")
;; GNOME means of invoking either Mozilla or Netscape.
(defvar browse-url-gnome-moz-program "gnome-moz-remote")
@ -1050,6 +1057,7 @@ instead of `browse-url-new-window-flag'."
((executable-find browse-url-kde-program) 'browse-url-kde)
;;; ((executable-find browse-url-netscape-program) 'browse-url-netscape)
((executable-find browse-url-chrome-program) 'browse-url-chrome)
((executable-find browse-url-webpositive-program) 'browse-url-webpositive)
((executable-find browse-url-xterm-program) 'browse-url-text-xterm)
((locate-library "w3") 'browse-url-w3)
(t
@ -1376,6 +1384,18 @@ used instead of `browse-url-new-window-flag'."
(defvar url-handler-regexp)
;;;###autoload
(defun browse-url-webpositive (url &optional _new-window)
"Ask the WebPositive WWW browser to load URL.
Default to the URL around or before point.
The optional argument NEW-WINDOW is not used."
(interactive (browse-url-interactive-arg "URL: "))
(setq url (browse-url-encode-url url))
(let* ((process-environment (browse-url-process-environment)))
(start-process (concat "WebPositive " url) nil "WebPositive" url)))
(function-put 'browse-url-webpositive 'browse-url-browser-kind 'external)
;;;###autoload
(defun browse-url-emacs (url &optional same-window)
"Ask Emacs to load URL into a buffer and show it in another window.

View file

@ -239,7 +239,7 @@ parameter, and should return the (possibly) transformed URL."
:version "29.1")
(defface eww-form-submit
'((((type x w32 ns) (class color)) ; Like default mode line
'((((type x w32 ns haiku) (class color)) ; Like default mode line
:box (:line-width 2 :style released-button)
:background "#808080" :foreground "black"))
"Face for eww buffer buttons."
@ -247,7 +247,7 @@ parameter, and should return the (possibly) transformed URL."
:group 'eww)
(defface eww-form-file
'((((type x w32 ns) (class color)) ; Like default mode line
'((((type x w32 ns haiku) (class color)) ; Like default mode line
:box (:line-width 2 :style released-button)
:background "#808080" :foreground "black"))
"Face for eww buffer buttons."
@ -255,7 +255,7 @@ parameter, and should return the (possibly) transformed URL."
:group 'eww)
(defface eww-form-checkbox
'((((type x w32 ns) (class color)) ; Like default mode line
'((((type x w32 ns haiku) (class color)) ; Like default mode line
:box (:line-width 2 :style released-button)
:background "lightgrey" :foreground "black"))
"Face for eww buffer buttons."
@ -263,7 +263,7 @@ parameter, and should return the (possibly) transformed URL."
:group 'eww)
(defface eww-form-select
'((((type x w32 ns) (class color)) ; Like default mode line
'((((type x w32 ns haiku) (class color)) ; Like default mode line
:box (:line-width 2 :style released-button)
:background "lightgrey" :foreground "black"))
"Face for eww buffer buttons."

134
lisp/term/haiku-win.el Normal file
View file

@ -0,0 +1,134 @@
;;; haiku-win.el --- set up windowing on Haiku -*- lexical-binding: t -*-
;; Copyright (C) 2021 Free Software Foundation, Inc.
;; This file is part of GNU Emacs.
;; GNU Emacs is free software: you can redistribute it and/or modify
;; it under the terms of the GNU General Public License as published by
;; the Free Software Foundation, either version 3 of the License, or
;; (at your option) any later version.
;; GNU Emacs is distributed in the hope that it will be useful,
;; but WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
;; GNU General Public License for more details.
;; You should have received a copy of the GNU General Public License
;; along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
;;; Commentary:
;; Support for using Haiku's BeOS derived windowing system.
;;; Code:
(eval-when-compile (require 'cl-lib))
(unless (featurep 'haiku)
(error "%s: Loading haiku-win without having Haiku"
invocation-name))
;; Documentation-purposes only: actually loaded in loadup.el.
(require 'frame)
(require 'mouse)
(require 'scroll-bar)
(require 'menu-bar)
(require 'fontset)
(require 'dnd)
(add-to-list 'display-format-alist '(".*" . haiku-win))
;;;; Command line argument handling.
(defvar x-invocation-args)
(defvar x-command-line-resources)
(defvar haiku-initialized)
(declare-function x-open-connection "haikufns.c")
(declare-function x-handle-args "common-win")
(declare-function haiku-selection-data "haikuselect.c")
(declare-function haiku-selection-put "haikuselect.c")
(declare-function haiku-put-resource "haikufns.c")
(defun haiku--handle-x-command-line-resources (command-line-resources)
"Handle command line X resources specified with the option `-xrm'.
The resources should be a list of strings in COMMAND-LINE-RESOURCES."
(dolist (s command-line-resources)
(let ((components (split-string s ":")))
(when (car components)
(haiku-put-resource (car components)
(string-trim-left
(mapconcat #'identity (cdr components) ":")))))))
(cl-defmethod window-system-initialization (&context (window-system haiku)
&optional display)
"Set up the window system. WINDOW-SYSTEM must be HAIKU.
DISPLAY may be set to the name of a display that will be initialized."
(cl-assert (not haiku-initialized))
(create-default-fontset)
(when x-command-line-resources
(haiku--handle-x-command-line-resources
(split-string x-command-line-resources "\n")))
(x-open-connection (or display "be") x-command-line-resources t)
(setq haiku-initialized t))
(cl-defmethod frame-creation-function (params &context (window-system haiku))
(x-create-frame-with-faces params))
(cl-defmethod handle-args-function (args &context (window-system haiku))
(x-handle-args args))
(defun haiku--selection-type-to-mime (type)
"Convert symbolic selection type TYPE to its MIME equivalent.
If TYPE is nil, return \"text/plain\"."
(cond
((memq type '(TEXT COMPOUND_TEXT STRING UTF8_STRING)) "text/plain")
((stringp type) type)
(t "text/plain")))
(cl-defmethod gui-backend-get-selection (type data-type
&context (window-system haiku))
(haiku-selection-data type (haiku--selection-type-to-mime data-type)))
(cl-defmethod gui-backend-set-selection (type value
&context (window-system haiku))
(haiku-selection-put type "text/plain" value))
(cl-defmethod gui-backend-selection-exists-p (selection
&context (window-system haiku))
(haiku-selection-data selection "text/plain"))
(cl-defmethod gui-backend-selection-owner-p (_
&context (window-system haiku))
t)
(declare-function haiku-read-file-name "haikufns.c")
(defun x-file-dialog (prompt dir default_filename mustmatch only_dir_p)
"SKIP: real doc in xfns.c."
(if (eq (framep-on-display (selected-frame)) 'haiku)
(haiku-read-file-name prompt (selected-frame)
(or dir (and default_filename
(file-name-directory default_filename)))
mustmatch only_dir_p
(file-name-nondirectory default_filename))
(error "x-file-dialog on a tty frame")))
(defun haiku-dnd-handle-drag-n-drop-event (event)
"Handle specified drag-n-drop EVENT."
(interactive "e")
(let* ((string (caddr event))
(window (posn-window (event-start event))))
(with-selected-window window
(raise-frame)
(dnd-handle-one-url window 'private (concat "file:" string)))))
(define-key special-event-map [drag-n-drop]
'haiku-dnd-handle-drag-n-drop-event)
(provide 'haiku-win)
(provide 'term/haiku-win)
;;; haiku-win.el ends here

View file

@ -368,10 +368,15 @@ It is also called if Tooltip mode is on, for text-only displays."
((equal-including-properties tooltip-help-message (current-message))
(message nil)))))
(declare-function menu-or-popup-active-p "xmenu.c" ())
(defun tooltip-show-help (msg)
"Function installed as `show-help-function'.
MSG is either a help string to display, or nil to cancel the display."
(if (display-graphic-p)
(if (and (display-graphic-p)
(or (not (eq window-system 'haiku)) ;; On Haiku, there isn't a reliable way to show tooltips
;; above menus.
(not (menu-or-popup-active-p))))
(let ((previous-help tooltip-help-message))
(setq tooltip-help-message msg)
(cond ((null msg)

View file

@ -53,6 +53,8 @@ developing Emacs.")
(defvar ns-version-string)
(defvar cairo-version-string)
(declare-function haiku-get-version-string "haikufns.c")
(defun emacs-version (&optional here)
"Return string describing the version of Emacs that is running.
If optional argument HERE is non-nil, insert string at point.
@ -71,6 +73,8 @@ to the system configuration; look at `system-configuration' instead."
((featurep 'x-toolkit) ", X toolkit")
((featurep 'ns)
(format ", NS %s" ns-version-string))
((featurep 'haiku)
(format ", Haiku %s" (haiku-get-version-string)))
(t ""))
(if (featurep 'cairo)
(format ", cairo version %s" cairo-version-string)

View file

@ -34,6 +34,7 @@ top_builddir = @top_builddir@
abs_top_srcdir=@abs_top_srcdir@
VPATH = $(srcdir)
CC = @CC@
CXX = @CXX@
CFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
@ -346,10 +347,17 @@ BUILD_DETAILS = @BUILD_DETAILS@
UNEXEC_OBJ = @UNEXEC_OBJ@
HAIKU_OBJ = @HAIKU_OBJ@
HAIKU_CXX_OBJ = @HAIKU_CXX_OBJ@
HAIKU_LIBS = @HAIKU_LIBS@
HAIKU_CFLAGS = @HAIKU_CFLAGS@
DUMPING=@DUMPING@
CHECK_STRUCTS = @CHECK_STRUCTS@
HAVE_PDUMPER = @HAVE_PDUMPER@
HAVE_BE_APP = @HAVE_BE_APP@
## ARM Macs require that all code have a valid signature. Since pdump
## invalidates the signature, we must re-sign to fix it.
DO_CODESIGN=$(patsubst aarch64-apple-darwin%,yes,@configuration@)
@ -367,6 +375,9 @@ endif
# Flags that might be in WARN_CFLAGS but are not valid for Objective C.
NON_OBJC_CFLAGS = -Wignored-attributes -Wignored-qualifiers -Wopenmp-simd
# Ditto, but for C++.
NON_CXX_CFLAGS = -Wmissing-prototypes -Wnested-externs -Wold-style-definition \
-Wstrict-prototypes -Wno-override-init
# -Demacs makes some files produce the correct version for use in Emacs.
# MYCPPFLAGS is for by-hand Emacs-specific overrides, e.g.,
@ -382,17 +393,21 @@ EMACS_CFLAGS=-Demacs $(MYCPPFLAGS) -I. -I$(srcdir) \
$(HARFBUZZ_CFLAGS) $(LIBOTF_CFLAGS) $(M17N_FLT_CFLAGS) $(DEPFLAGS) \
$(LIBSYSTEMD_CFLAGS) $(JSON_CFLAGS) \
$(LIBGNUTLS_CFLAGS) $(NOTIFY_CFLAGS) $(CAIRO_CFLAGS) \
$(WERROR_CFLAGS)
$(WERROR_CFLAGS) $(HAIKU_CFLAGS)
ALL_CFLAGS = $(EMACS_CFLAGS) $(WARN_CFLAGS) $(CFLAGS)
ALL_OBJC_CFLAGS = $(EMACS_CFLAGS) \
$(filter-out $(NON_OBJC_CFLAGS),$(WARN_CFLAGS)) $(CFLAGS) \
$(GNU_OBJC_CFLAGS)
ALL_CXX_CFLAGS = $(EMACS_CFLAGS) \
$(filter-out $(NON_CXX_CFLAGS),$(WARN_CFLAGS)) $(CXXFLAGS)
.SUFFIXES: .m
.SUFFIXES: .m .cc
.c.o:
$(AM_V_CC)$(CC) -c $(CPPFLAGS) $(ALL_CFLAGS) $(PROFILING_CFLAGS) $<
.m.o:
$(AM_V_CC)$(CC) -c $(CPPFLAGS) $(ALL_OBJC_CFLAGS) $(PROFILING_CFLAGS) $<
.cc.o:
$(AM_V_CXX)$(CXX) -c $(CPPFLAGS) $(ALL_CXX_CFLAGS) $(PROFILING_CFLAGS) $<
## lastfile must follow all files whose initialized data areas should
## be dumped as pure by dump-emacs.
@ -414,8 +429,10 @@ base_obj = dispnew.o frame.o scroll.o xdisp.o menu.o $(XMENU_OBJ) window.o \
thread.o systhread.o \
$(if $(HYBRID_MALLOC),sheap.o) \
$(MSDOS_OBJ) $(MSDOS_X_OBJ) $(NS_OBJ) $(CYGWIN_OBJ) $(FONT_OBJ) \
$(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ) $(JSON_OBJ)
obj = $(base_obj) $(NS_OBJC_OBJ)
$(W32_OBJ) $(WINDOW_SYSTEM_OBJ) $(XGSELOBJ) $(JSON_OBJ) \
$(HAIKU_OBJ)
doc_obj = $(base_obj) $(NS_OBJC_OBJ)
obj = $(doc_obj) $(HAIKU_CXX_OBJ)
## Object files used on some machine or other.
## These go in the DOC file on all machines in case they are needed.
@ -429,7 +446,8 @@ SOME_MACHINE_OBJECTS = dosfns.o msdos.o \
w32.o w32console.o w32cygwinx.o w32fns.o w32heap.o w32inevt.o w32notify.o \
w32menu.o w32proc.o w32reg.o w32select.o w32term.o w32xfns.o \
w16select.o widget.o xfont.o ftfont.o xftfont.o gtkutil.o \
xsettings.o xgselect.o termcap.o hbfont.o
xsettings.o xgselect.o termcap.o hbfont.o \
haikuterm.o haikufns.o haikumenu.o haikufont.o
## gmalloc.o if !SYSTEM_MALLOC && !DOUG_LEA_MALLOC, else empty.
GMALLOC_OBJ=@GMALLOC_OBJ@
@ -455,7 +473,11 @@ FIRSTFILE_OBJ=@FIRSTFILE_OBJ@
ALLOBJS = $(FIRSTFILE_OBJ) $(VMLIMIT_OBJ) $(obj) $(otherobj)
# Must be first, before dep inclusion!
ifneq ($(HAVE_BE_APP),yes)
all: emacs$(EXEEXT) $(pdmp) $(OTHER_FILES)
else
all: Emacs Emacs.pdmp $(OTHER_FILES)
endif
ifeq ($(HAVE_NATIVE_COMP):$(NATIVE_DISABLED),yes:)
all: ../native-lisp
endif
@ -527,7 +549,7 @@ LIBES = $(LIBS) $(W32_LIBS) $(LIBS_GNUSTEP) $(LIBX_BASE) $(LIBIMAGE) \
$(FREETYPE_LIBS) $(FONTCONFIG_LIBS) $(HARFBUZZ_LIBS) $(LIBOTF_LIBS) $(M17N_FLT_LIBS) \
$(LIBGNUTLS_LIBS) $(LIB_PTHREAD) $(GETADDRINFO_A_LIBS) $(LCMS2_LIBS) \
$(NOTIFY_LIBS) $(LIB_MATH) $(LIBZ) $(LIBMODULES) $(LIBSYSTEMD_LIBS) \
$(JSON_LIBS) $(LIBGMP) $(LIBGCCJIT_LIBS) $(XINPUT_LIBS)
$(JSON_LIBS) $(LIBGMP) $(LIBGCCJIT_LIBS) $(XINPUT_LIBS) $(HAIKU_LIBS)
## FORCE it so that admin/unidata can decide whether this file is
## up-to-date. Although since charprop depends on bootstrap-emacs,
@ -584,6 +606,18 @@ else
rm -f $@ && cp -f temacs$(EXEEXT) $@
endif
## On Haiku, also produce a binary named Emacs with the appropriate
## icon set.
ifeq ($(HAVE_BE_APP),yes)
Emacs: emacs$(EXEEXT)
cp -f emacs$(EXEEXT) $@
$(AM_V_GEN) $(libsrc)/be-resources \
$(etc)/images/icons/hicolor/32x32/apps/emacs.png $@
Emacs.pdmp: $(pdmp)
$(AM_V_GEN) cp -f $(pdmp) $@
endif
ifeq ($(DUMPING),pdumper)
$(pdmp): emacs$(EXEEXT)
LC_ALL=C $(RUN_TEMACS) -batch $(BUILD_DETAILS) -l loadup --temacs=pdump \
@ -602,11 +636,11 @@ endif
## for the first time, this prevents any variation between configurations
## in the contents of the DOC file.
##
$(etc)/DOC: lisp.mk $(libsrc)/make-docfile$(EXEEXT) $(obj) $(lisp)
$(etc)/DOC: lisp.mk $(libsrc)/make-docfile$(EXEEXT) $(doc_obj) $(lisp)
$(AM_V_GEN)$(MKDIR_P) $(etc)
$(AM_V_at)rm -f $(etc)/DOC
$(AM_V_at)$(libsrc)/make-docfile -d $(srcdir) \
$(SOME_MACHINE_OBJECTS) $(obj) > $(etc)/DOC
$(SOME_MACHINE_OBJECTS) $(doc_obj) > $(etc)/DOC
$(AM_V_at)$(libsrc)/make-docfile -a $(etc)/DOC -d $(lispsource) \
$(shortlisp)
@ -624,7 +658,7 @@ buildobj.h: Makefile
GLOBAL_SOURCES = $(base_obj:.o=.c) $(NS_OBJC_OBJ:.o=.m)
gl-stamp: $(libsrc)/make-docfile$(EXEEXT) $(GLOBAL_SOURCES)
$(AM_V_GLOBALS)$(libsrc)/make-docfile -d $(srcdir) -g $(obj) > globals.tmp
$(AM_V_GLOBALS)$(libsrc)/make-docfile -d $(srcdir) -g $(doc_obj) > globals.tmp
$(AM_V_at)$(top_srcdir)/build-aux/move-if-change globals.tmp globals.h
$(AM_V_at)echo timestamp > $@
@ -649,9 +683,15 @@ endif
## to start if Vinstallation_directory has the wrong value.
temacs$(EXEEXT): $(LIBXMENU) $(ALLOBJS) $(LIBEGNU_ARCHIVE) $(EMACSRES) \
$(charsets) $(charscript) ${emoji-zwj} $(MAKE_PDUMPER_FINGERPRINT)
$(AM_V_CCLD)$(CC) -o $@.tmp \
ifeq ($(HAVE_BE_APP),yes)
$(AM_V_CXXLD)$(CXX) -o $@.tmp \
$(ALL_CFLAGS) $(TEMACS_LDFLAGS) $(LDFLAGS) \
$(ALLOBJS) $(LIBEGNU_ARCHIVE) $(W32_RES_LINK) $(LIBES) -lstdc++
else
$(AM_V_CCLD)$(CC) -o $@.tmp \
$(ALL_CFLAGS) $(CXXFLAGS) $(TEMACS_LDFLAGS) $(LDFLAGS) \
$(ALLOBJS) $(LIBEGNU_ARCHIVE) $(W32_RES_LINK) $(LIBES)
endif
ifeq ($(HAVE_PDUMPER),yes)
$(AM_V_at)$(MAKE_PDUMPER_FINGERPRINT) $@.tmp
ifeq ($(DO_CODESIGN),yes)
@ -736,6 +776,7 @@ ${ETAGS}: FORCE
# to be built before we can get TAGS.
ctagsfiles1 = $(filter-out ${srcdir}/macuvs.h, $(wildcard ${srcdir}/*.[hc]))
ctagsfiles2 = $(wildcard ${srcdir}/*.m)
ctagsfiles3 = $(wildcard ${srcdir}/*.cc)
## In out-of-tree builds, TAGS are generated in the build dir, like
## other non-bootstrap build products (see Bug#31744).
@ -750,7 +791,8 @@ TAGS: ${ETAGS} $(ctagsfiles1) $(ctagsfiles2)
$(ctagsfiles1) \
--regex='{objc}/[ ]*DEFVAR_[A-Z_ (]+"\([^"]+\)"/\1/' \
--regex='{objc}/[ ]*DEFVAR_[A-Z_ (]+"[^"]+",[ ]\([A-Za-z0-9_]+\)/\1/' \
$(ctagsfiles2)
$(ctagsfiles2) \
$(ctagsfiles3)
## Arrange to make tags tables for ../lisp and ../lwlib,
## which the above TAGS file for the C files includes by reference.

View file

@ -6149,6 +6149,10 @@ garbage_collect (void)
xg_mark_data ();
#endif
#ifdef HAVE_HAIKU
mark_haiku_display ();
#endif
#ifdef HAVE_WINDOW_SYSTEM
mark_fringe_data ();
#endif

View file

@ -134,6 +134,13 @@ typedef Emacs_Pixmap Emacs_Pix_Context;
#define FACE_COLOR_TO_PIXEL(face_color, frame) face_color
#endif
#ifdef HAVE_HAIKU
#include "haikugui.h"
typedef struct haiku_display_info Display_Info;
typedef Emacs_Pixmap Emacs_Pix_Container;
typedef Emacs_Pixmap Emacs_Pix_Context;
#endif
#ifdef HAVE_WINDOW_SYSTEM
# include <time.h>
# include "fontset.h"
@ -3011,7 +3018,7 @@ struct redisplay_interface
#ifdef HAVE_WINDOW_SYSTEM
# if (defined USE_CAIRO || defined HAVE_XRENDER \
|| defined HAVE_NS || defined HAVE_NTGUI)
|| defined HAVE_NS || defined HAVE_NTGUI || defined HAVE_HAIKU)
# define HAVE_NATIVE_TRANSFORMS
# endif
@ -3050,6 +3057,14 @@ struct image
#ifdef HAVE_NTGUI
XFORM xform;
#endif
#ifdef HAVE_HAIKU
/* Non-zero if the image has not yet been transformed for display. */
int have_be_transforms_p;
double be_rotate;
double be_scale_x;
double be_scale_y;
#endif
/* Colors allocated for this image, if any. Allocated via xmalloc. */
unsigned long *colors;
@ -3489,7 +3504,8 @@ bool valid_image_p (Lisp_Object);
void prepare_image_for_display (struct frame *, struct image *);
ptrdiff_t lookup_image (struct frame *, Lisp_Object, int);
#if defined HAVE_X_WINDOWS || defined USE_CAIRO || defined HAVE_NS
#if defined HAVE_X_WINDOWS || defined USE_CAIRO || defined HAVE_NS \
|| defined HAVE_HAIKU
#define RGB_PIXEL_COLOR unsigned long
#endif

View file

@ -6146,7 +6146,7 @@ sit_for (Lisp_Object timeout, bool reading, int display_option)
wrong_type_argument (Qnumberp, timeout);
#ifdef USABLE_SIGIO
#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
gobble_input ();
#endif
@ -6453,6 +6453,15 @@ init_display_interactive (void)
}
#endif
#ifdef HAVE_HAIKU
if (!inhibit_window_system && !will_dump_p ())
{
Vinitial_window_system = Qhaiku;
Vwindow_system_version = make_fixnum (1);
return;
}
#endif
/* If no window system has been specified, try to use the terminal. */
if (! isatty (STDIN_FILENO))
fatal ("standard input is not a tty");

View file

@ -109,6 +109,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "getpagesize.h"
#include "gnutls.h"
#ifdef HAVE_HAIKU
#include <kernel/OS.h>
#endif
#ifdef PROFILING
# include <sys/gmon.h>
extern void moncontrol (int mode);
@ -2207,6 +2211,18 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
syms_of_fontset ();
#endif /* HAVE_NS */
#ifdef HAVE_HAIKU
syms_of_haikuterm ();
syms_of_haikufns ();
syms_of_haikumenu ();
syms_of_haikufont ();
syms_of_haikuselect ();
#ifdef HAVE_NATIVE_IMAGE_API
syms_of_haikuimage ();
#endif
syms_of_fontset ();
#endif /* HAVE_HAIKU */
syms_of_gnutls ();
#ifdef HAVE_INOTIFY
@ -2261,6 +2277,10 @@ Using an Emacs configured with --with-x-toolkit=lucid does not have this problem
#if defined WINDOWSNT || defined HAVE_NTGUI
globals_of_w32select ();
#endif
#ifdef HAVE_HAIKU
init_haiku_select ();
#endif
}
init_charset ();
@ -2728,6 +2748,9 @@ shut_down_emacs (int sig, Lisp_Object stuff)
/* Don't update display from now on. */
Vinhibit_redisplay = Qt;
#ifdef HAVE_HAIKU
be_app_quit ();
#endif
/* If we are controlling the terminal, reset terminal modes. */
#ifndef DOS_NT
pid_t tpgrp = tcgetpgrp (STDIN_FILENO);
@ -2737,6 +2760,10 @@ shut_down_emacs (int sig, Lisp_Object stuff)
if (sig && sig != SIGTERM)
{
static char const fmt[] = "Fatal error %d: %n%s\n";
#ifdef HAVE_HAIKU
if (haiku_debug_on_fatal_error)
debugger ("Fatal error in Emacs");
#endif
char buf[max ((sizeof fmt - sizeof "%d%n%s\n"
+ INT_STRLEN_BOUND (int) + 1),
min (PIPE_BUF, MAX_ALLOCA))];
@ -3229,6 +3256,7 @@ Special values:
`ms-dos' compiled as an MS-DOS application.
`windows-nt' compiled as a native W32 application.
`cygwin' compiled using the Cygwin library.
`haiku' compiled for a Haiku system.
Anything else (in Emacs 26, the possibilities are: aix, berkeley-unix,
hpux, usg-unix-v) indicates some sort of Unix system. */);
Vsystem_type = intern_c_string (SYSTEM_TYPE);

View file

@ -6190,7 +6190,7 @@ before any other event (mouse or keypress) is handled. */)
(void)
{
#if (defined USE_GTK || defined USE_MOTIF \
|| defined HAVE_NS || defined HAVE_NTGUI)
|| defined HAVE_NS || defined HAVE_NTGUI || defined HAVE_HAIKU)
if ((NILP (last_nonmenu_event) || CONSP (last_nonmenu_event))
&& use_dialog_box
&& use_file_dialog

View file

@ -65,7 +65,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#define BOOT_TIME_FILE "/var/run/random-seed"
#endif
#if !defined WTMP_FILE && !defined WINDOWSNT
#if !defined WTMP_FILE && !defined WINDOWSNT && defined BOOT_TIME
#define WTMP_FILE "/var/log/wtmp"
#endif

View file

@ -347,6 +347,21 @@ int
double_integer_scale (double d)
{
int exponent = ilogb (d);
#ifdef HAIKU
/* On Haiku, the values returned by ilogb are nonsensical when
confronted with tiny numbers, inf, or NaN, which breaks the trick
used by code on other platforms, so we have to test for each case
manually, and return the appropriate value. */
if (exponent == FP_ILOGB0)
{
if (isnan (d))
return (DBL_MANT_DIG - DBL_MIN_EXP) + 2;
if (isinf (d))
return (DBL_MANT_DIG - DBL_MIN_EXP) + 1;
return (DBL_MANT_DIG - DBL_MIN_EXP);
}
#endif
return (DBL_MIN_EXP - 1 <= exponent && exponent < INT_MAX
? DBL_MANT_DIG - 1 - exponent
: (DBL_MANT_DIG - DBL_MIN_EXP

View file

@ -5751,6 +5751,9 @@ match. */);
#ifdef HAVE_NTGUI
syms_of_w32font ();
#endif /* HAVE_NTGUI */
#ifdef USE_BE_CAIRO
syms_of_ftcrfont ();
#endif
#endif /* HAVE_WINDOW_SYSTEM */
}

View file

@ -965,7 +965,7 @@ extern struct font_driver const nsfont_driver;
extern void syms_of_nsfont (void);
extern void syms_of_macfont (void);
#endif /* HAVE_NS */
#ifdef USE_CAIRO
#if defined (USE_CAIRO) || defined (USE_BE_CAIRO)
extern struct font_driver const ftcrfont_driver;
#ifdef HAVE_HARFBUZZ
extern struct font_driver ftcrhbfont_driver;
@ -999,7 +999,7 @@ extern void font_deferred_log (const char *, Lisp_Object, Lisp_Object);
INLINE bool
font_data_structures_may_be_ill_formed (void)
{
#ifdef USE_CAIRO
#if defined USE_CAIRO || defined USE_BE_CAIRO
/* Although this works around Bug#20890, it is probably not the
right thing to do. */
return gc_in_progress;

View file

@ -226,6 +226,7 @@ Value is:
`w32' for an Emacs frame that is a window on MS-Windows display,
`ns' for an Emacs frame on a GNUstep or Macintosh Cocoa display,
`pc' for a direct-write MS-DOS frame.
`haiku` for an Emacs frame running in Haiku.
See also `frame-live-p'. */)
(Lisp_Object object)
{
@ -244,6 +245,8 @@ See also `frame-live-p'. */)
return Qpc;
case output_ns:
return Qns;
case output_haiku:
return Qhaiku;
default:
emacs_abort ();
}
@ -6020,6 +6023,7 @@ syms_of_frame (void)
DEFSYM (Qw32, "w32");
DEFSYM (Qpc, "pc");
DEFSYM (Qns, "ns");
DEFSYM (Qhaiku, "haiku");
DEFSYM (Qvisible, "visible");
DEFSYM (Qbuffer_predicate, "buffer-predicate");
DEFSYM (Qbuffer_list, "buffer-list");

View file

@ -585,6 +585,7 @@ struct frame
struct x_output *x; /* From xterm.h. */
struct w32_output *w32; /* From w32term.h. */
struct ns_output *ns; /* From nsterm.h. */
struct haiku_output *haiku; /* From haikuterm.h. */
}
output_data;
@ -852,6 +853,11 @@ default_pixels_per_inch_y (void)
#else
#define FRAME_NS_P(f) ((f)->output_method == output_ns)
#endif
#ifndef HAVE_HAIKU
#define FRAME_HAIKU_P(f) false
#else
#define FRAME_HAIKU_P(f) ((f)->output_method == output_haiku)
#endif
/* FRAME_WINDOW_P tests whether the frame is a graphical window system
frame. */
@ -864,6 +870,9 @@ default_pixels_per_inch_y (void)
#ifdef HAVE_NS
#define FRAME_WINDOW_P(f) FRAME_NS_P(f)
#endif
#ifdef HAVE_HAIKU
#define FRAME_WINDOW_P(f) FRAME_HAIKU_P (f)
#endif
#ifndef FRAME_WINDOW_P
#define FRAME_WINDOW_P(f) ((void) (f), false)
#endif

View file

@ -22,7 +22,13 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <cairo-ft.h>
#include "lisp.h"
#ifdef HAVE_X_WINDOWS
#include "xterm.h"
#else /* Otherwise, Haiku */
#include "haikuterm.h"
#include "haiku_support.h"
#include "termchar.h"
#endif
#include "blockinput.h"
#include "charset.h"
#include "composite.h"
@ -30,6 +36,12 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include "ftfont.h"
#include "pdumper.h"
#ifdef USE_BE_CAIRO
#define RED_FROM_ULONG(color) (((color) >> 16) & 0xff)
#define GREEN_FROM_ULONG(color) (((color) >> 8) & 0xff)
#define BLUE_FROM_ULONG(color) ((color) & 0xff)
#endif
#define METRICS_NCOLS_PER_ROW (128)
enum metrics_status
@ -513,11 +525,37 @@ ftcrfont_draw (struct glyph_string *s,
block_input ();
#ifndef USE_BE_CAIRO
cr = x_begin_cr_clip (f, s->gc);
#else
BView_draw_lock (FRAME_HAIKU_VIEW (f));
EmacsWindow_begin_cr_critical_section (FRAME_HAIKU_WINDOW (f));
cr = haiku_begin_cr_clip (f, s);
if (!cr)
{
BView_draw_unlock (FRAME_HAIKU_VIEW (f));
EmacsWindow_end_cr_critical_section (FRAME_HAIKU_WINDOW (f));
unblock_input ();
return 0;
}
BView_cr_dump_clipping (FRAME_HAIKU_VIEW (f), cr);
#endif
if (with_background)
{
#ifndef USE_BE_CAIRO
x_set_cr_source_with_gc_background (f, s->gc);
s->background_filled_p = 1;
#else
struct face *face = s->face;
uint32_t col = s->hl == DRAW_CURSOR ?
FRAME_CURSOR_COLOR (s->f).pixel : face->background;
cairo_set_source_rgb (cr, RED_FROM_ULONG (col) / 255.0,
GREEN_FROM_ULONG (col) / 255.0,
BLUE_FROM_ULONG (col) / 255.0);
#endif
cairo_rectangle (cr, x, y - FONT_BASE (face->font),
s->width, FONT_HEIGHT (face->font));
cairo_fill (cr);
@ -533,13 +571,25 @@ ftcrfont_draw (struct glyph_string *s,
glyphs[i].index,
NULL));
}
#ifndef USE_BE_CAIRO
x_set_cr_source_with_gc_foreground (f, s->gc);
#else
uint32_t col = s->hl == DRAW_CURSOR ?
FRAME_OUTPUT_DATA (s->f)->cursor_fg : face->foreground;
cairo_set_source_rgb (cr, RED_FROM_ULONG (col) / 255.0,
GREEN_FROM_ULONG (col) / 255.0,
BLUE_FROM_ULONG (col) / 255.0);
#endif
cairo_set_scaled_font (cr, ftcrfont_info->cr_scaled_font);
cairo_show_glyphs (cr, glyphs, len);
#ifndef USE_BE_CAIRO
x_end_cr_clip (f);
#else
haiku_end_cr_clip (cr);
EmacsWindow_end_cr_critical_section (FRAME_HAIKU_WINDOW (f));
BView_draw_unlock (FRAME_HAIKU_VIEW (f));
#endif
unblock_input ();
return len;

View file

@ -3108,6 +3108,10 @@ syms_of_ftfont (void)
Fput (Qfreetype, Qfont_driver_superseded_by, Qfreetypehb);
#endif /* HAVE_HARFBUZZ */
#ifdef HAVE_HAIKU
DEFSYM (Qmono, "mono");
#endif
/* Fontconfig's generic families and their aliases. */
DEFSYM (Qmonospace, "monospace");
DEFSYM (Qsans_serif, "sans-serif");

View file

@ -29,6 +29,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
# include FT_BDF_H
#endif
#ifdef USE_BE_CAIRO
#include <cairo.h>
#endif
#ifdef HAVE_HARFBUZZ
#include <hb.h>
#include <hb-ft.h>
@ -62,7 +66,7 @@ struct font_info
hb_font_t *hb_font;
#endif /* HAVE_HARFBUZZ */
#ifdef USE_CAIRO
#if defined (USE_CAIRO) || defined (USE_BE_CAIRO)
cairo_scaled_font_t *cr_scaled_font;
/* Scale factor from the bitmap strike metrics in 1/64 pixels, used
as the hb_position_t value in HarfBuzz, to those in (scaled)

286
src/haiku.c Normal file
View file

@ -0,0 +1,286 @@
/* Haiku subroutines that are general to the Haiku operating system.
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include "lisp.h"
#include "process.h"
#include "coding.h"
#include <kernel/OS.h>
#include <pwd.h>
#include <stdlib.h>
Lisp_Object
list_system_processes (void)
{
team_info info;
int32 cookie = 0;
Lisp_Object lval = Qnil;
while (get_next_team_info (&cookie, &info) == B_OK)
lval = Fcons (make_fixnum (info.team), lval);
return lval;
}
Lisp_Object
system_process_attributes (Lisp_Object pid)
{
CHECK_FIXNUM (pid);
team_info info;
Lisp_Object lval = Qnil;
thread_info inf;
area_info area;
team_id id = (team_id) XFIXNUM (pid);
struct passwd *g;
size_t mem = 0;
if (get_team_info (id, &info) != B_OK)
return Qnil;
bigtime_t everything = 0, vsample = 0;
bigtime_t cpu_eaten = 0, esample = 0;
lval = Fcons (Fcons (Qeuid, make_fixnum (info.uid)), lval);
lval = Fcons (Fcons (Qegid, make_fixnum (info.gid)), lval);
lval = Fcons (Fcons (Qthcount, make_fixnum (info.thread_count)), lval);
lval = Fcons (Fcons (Qcomm, build_string_from_utf8 (info.args)), lval);
g = getpwuid (info.uid);
if (g && g->pw_name)
lval = Fcons (Fcons (Quser, build_string (g->pw_name)), lval);
/* FIXME: Calculating this makes Emacs show up as using 100% CPU! */
for (int32 team_cookie = 0;
get_next_team_info (&team_cookie, &info) == B_OK;)
for (int32 thread_cookie = 0;
get_next_thread_info (info.team, &thread_cookie, &inf) == B_OK;)
{
if (inf.team == id && strncmp (inf.name, "idle thread ", 12))
cpu_eaten += inf.user_time + inf.kernel_time;
everything += inf.user_time + inf.kernel_time;
}
sleep (0.05);
for (int32 team_cookie = 0;
get_next_team_info (&team_cookie, &info) == B_OK;)
for (int32 thread_cookie = 0;
get_next_thread_info (info.team, &thread_cookie, &inf) == B_OK;)
{
if (inf.team == id && strncmp (inf.name, "idle thread ", 12))
esample += inf.user_time + inf.kernel_time;
vsample += inf.user_time + inf.kernel_time;
}
cpu_eaten = esample - cpu_eaten;
everything = vsample - everything;
if (everything)
lval = Fcons (Fcons (Qpcpu, make_float (((double) (cpu_eaten) /
(double) (everything)) * 100)),
lval);
else
lval = Fcons (Fcons (Qpcpu, make_float (0.0)), lval);
for (ssize_t area_cookie = 0;
get_next_area_info (id, &area_cookie, &area) == B_OK;)
mem += area.ram_size;
system_info sinfo;
get_system_info (&sinfo);
int64 max = (int64) sinfo.max_pages * B_PAGE_SIZE;
lval = Fcons (Fcons (Qpmem, make_float (((double) mem /
(double) max) * 100)),
lval);
lval = Fcons (Fcons (Qrss, make_fixnum (mem / 1024)), lval);
return lval;
}
/* Borrowed from w32 implementation. */
struct load_sample
{
time_t sample_time;
bigtime_t idle;
bigtime_t kernel;
bigtime_t user;
};
/* We maintain 1-sec samples for the last 16 minutes in a circular buffer. */
static struct load_sample samples[16*60];
static int first_idx = -1, last_idx = -1;
static int max_idx = ARRAYELTS (samples);
static unsigned num_of_processors = 0;
static int
buf_next (int from)
{
int next_idx = from + 1;
if (next_idx >= max_idx)
next_idx = 0;
return next_idx;
}
static int
buf_prev (int from)
{
int prev_idx = from - 1;
if (prev_idx < 0)
prev_idx = max_idx - 1;
return prev_idx;
}
static double
getavg (int which)
{
double retval = -1.0;
double tdiff;
int idx;
double span = (which == 0 ? 1.0 : (which == 1 ? 5.0 : 15.0)) * 60;
time_t now = samples[last_idx].sample_time;
if (first_idx != last_idx)
{
for (idx = buf_prev (last_idx); ; idx = buf_prev (idx))
{
tdiff = difftime (now, samples[idx].sample_time);
if (tdiff >= span - 2 * DBL_EPSILON * now)
{
long double sys =
(samples[last_idx].kernel + samples[last_idx].user) -
(samples[idx].kernel + samples[idx].user);
long double idl = samples[last_idx].idle - samples[idx].idle;
retval = (idl / (sys + idl)) * num_of_processors;
break;
}
if (idx == first_idx)
break;
}
}
return retval;
}
static void
sample_sys_load (bigtime_t *idle, bigtime_t *system, bigtime_t *user)
{
bigtime_t i = 0, s = 0, u = 0;
team_info info;
thread_info inf;
for (int32 team_cookie = 0;
get_next_team_info (&team_cookie, &info) == B_OK;)
for (int32 thread_cookie = 0;
get_next_thread_info (info.team, &thread_cookie, &inf) == B_OK;)
{
if (!strncmp (inf.name, "idle thread ", 12))
i += inf.user_time + inf.kernel_time;
else
s += inf.kernel_time, u += inf.user_time;
}
*idle = i;
*system = s;
*user = u;
}
int
getloadavg (double loadavg[], int nelem)
{
int elem;
bigtime_t idle, kernel, user;
time_t now = time (NULL);
if (num_of_processors <= 0)
{
system_info i;
if (get_system_info (&i) == B_OK)
num_of_processors = i.cpu_count;
}
/* If system time jumped back for some reason, delete all samples
whose time is later than the current wall-clock time. This
prevents load average figures from becoming frozen for prolonged
periods of time, when system time is reset backwards. */
if (last_idx >= 0)
{
while (difftime (now, samples[last_idx].sample_time) < -1.0)
{
if (last_idx == first_idx)
{
first_idx = last_idx = -1;
break;
}
last_idx = buf_prev (last_idx);
}
}
/* Store another sample. We ignore samples that are less than 1 sec
apart. */
if (last_idx < 0
|| (difftime (now, samples[last_idx].sample_time)
>= 1.0 - 2 * DBL_EPSILON * now))
{
sample_sys_load (&idle, &kernel, &user);
last_idx = buf_next (last_idx);
samples[last_idx].sample_time = now;
samples[last_idx].idle = idle;
samples[last_idx].kernel = kernel;
samples[last_idx].user = user;
/* If the buffer has more that 15 min worth of samples, discard
the old ones. */
if (first_idx == -1)
first_idx = last_idx;
while (first_idx != last_idx
&& (difftime (now, samples[first_idx].sample_time)
>= 15.0 * 60 + 2 * DBL_EPSILON * now))
first_idx = buf_next (first_idx);
}
for (elem = 0; elem < nelem; elem++)
{
double avg = getavg (elem);
if (avg < 0)
break;
loadavg[elem] = avg;
}
/* Always return at least one element, otherwise load-average
returns nil, and Lisp programs might decide we cannot measure
system load. For example, jit-lock-stealth-load's defcustom
might decide that feature is "unsupported". */
if (elem == 0)
loadavg[elem++] = 0.09; /* < display-time-load-average-threshold */
return elem;
}

488
src/haiku_draw_support.cc Normal file
View file

@ -0,0 +1,488 @@
/* Haiku window system support. Hey, Emacs, this is -*- C++ -*-
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include <View.h>
#include <Region.h>
#include <Font.h>
#include <Window.h>
#include <Bitmap.h>
#include <cmath>
#include "haiku_support.h"
#define RGB_TO_UINT32(r, g, b) ((255 << 24) | ((r) << 16) | ((g) << 8) | (b))
#define RED_FROM_ULONG(color) (((color) >> 16) & 0xff)
#define GREEN_FROM_ULONG(color) (((color) >> 8) & 0xff)
#define BLUE_FROM_ULONG(color) ((color) & 0xff)
#define RGB_COLOR_UINT32(r) RGB_TO_UINT32 ((r).red, (r).green, (r).blue)
static void
rgb32_to_rgb_color (uint32_t rgb, rgb_color *color)
{
color->red = RED_FROM_ULONG (rgb);
color->green = GREEN_FROM_ULONG (rgb);
color->blue = BLUE_FROM_ULONG (rgb);
color->alpha = 255;
}
static BView *
get_view (void *vw)
{
BView *view = (BView *) find_appropriate_view_for_draw (vw);
return view;
}
void
BView_StartClip (void *view)
{
BView *vw = get_view (view);
vw->PushState ();
}
void
BView_EndClip (void *view)
{
BView *vw = get_view (view);
vw->PopState ();
}
void
BView_SetHighColor (void *view, uint32_t color)
{
BView *vw = get_view (view);
rgb_color col;
rgb32_to_rgb_color (color, &col);
vw->SetHighColor (col);
}
void
BView_SetLowColor (void *view, uint32_t color)
{
BView *vw = get_view (view);
rgb_color col;
rgb32_to_rgb_color (color, &col);
vw->SetLowColor (col);
}
void
BView_SetPenSize (void *view, int u)
{
BView *vw = get_view (view);
vw->SetPenSize (u);
}
void
BView_FillRectangle (void *view, int x, int y, int width, int height)
{
BView *vw = get_view (view);
BRect rect = BRect (x, y, x + width - 1, y + height - 1);
vw->FillRect (rect);
}
void
BView_FillRectangleAbs (void *view, int x, int y, int x1, int y1)
{
BView *vw = get_view (view);
BRect rect = BRect (x, y, x1, y1);
vw->FillRect (rect);
}
void
BView_StrokeRectangle (void *view, int x, int y, int width, int height)
{
BView *vw = get_view (view);
BRect rect = BRect (x, y, x + width - 1, y + height - 1);
vw->StrokeRect (rect);
}
void
BView_SetViewColor (void *view, uint32_t color)
{
BView *vw = get_view (view);
rgb_color col;
rgb32_to_rgb_color (color, &col);
#ifndef USE_BE_CAIRO
vw->SetViewColor (col);
#else
vw->SetViewColor (B_TRANSPARENT_32_BIT);
#endif
}
void
BView_ClipToRect (void *view, int x, int y, int width, int height)
{
BView *vw = get_view (view);
BRect rect = BRect (x, y, x + width - 1, y + height - 1);
vw->ClipToRect (rect);
}
void
BView_ClipToInverseRect (void *view, int x, int y, int width, int height)
{
BView *vw = get_view (view);
BRect rect = BRect (x, y, x + width - 1, y + height - 1);
vw->ClipToInverseRect (rect);
}
void
BView_StrokeLine (void *view, int sx, int sy, int tx, int ty)
{
BView *vw = get_view (view);
BPoint from = BPoint (sx, sy);
BPoint to = BPoint (tx, ty);
vw->StrokeLine (from, to);
}
void
BView_SetFont (void *view, void *font)
{
BView *vw = get_view (view);
vw->SetFont ((BFont *) font);
}
void
BView_MovePenTo (void *view, int x, int y)
{
BView *vw = get_view (view);
BPoint pt = BPoint (x, y);
vw->MovePenTo (pt);
}
void
BView_DrawString (void *view, const char *chr, ptrdiff_t len)
{
BView *vw = get_view (view);
vw->DrawString (chr, len);
}
void
BView_DrawChar (void *view, char chr)
{
BView *vw = get_view (view);
vw->DrawChar (chr);
}
void
BView_CopyBits (void *view, int x, int y, int width, int height,
int tox, int toy, int towidth, int toheight)
{
BView *vw = get_view (view);
vw->CopyBits (BRect (x, y, x + width - 1, y + height - 1),
BRect (tox, toy, tox + towidth - 1, toy + toheight - 1));
vw->Sync ();
}
/* Convert RGB32 color color from RGB color space to its
HSL components pointed to by H, S and L. */
void
rgb_color_hsl (uint32_t rgb, double *h, double *s, double *l)
{
rgb_color col;
rgb32_to_rgb_color (rgb, &col);
double red = col.red / 255.0;
double green = col.green / 255.0;
double blue = col.blue / 255.0;
double max = std::fmax (std::fmax (red, blue), green);
double min = std::fmin (std::fmin (red, blue), green);
double delta = max - min;
*l = (max + min) / 2.0;
if (!delta)
{
*h = 0;
*s = 0;
return;
}
*s = (*l < 0.5) ? delta / (max + min) :
delta / (20 - max - min);
double rc = (max - red) / delta;
double gc = (max - green) / delta;
double bc = (max - blue) / delta;
if (red == max)
*h = bc - gc;
else if (green == max)
*h = 2.0 + rc + -bc;
else
*h = 4.0 + gc + -rc;
*h = std::fmod (*h / 6, 1.0);
}
static double
hue_to_rgb (double v1, double v2, double h)
{
if (h < 1 / 6)
return v1 + (v2 - v1) * h * 6.0;
else if (h < 0.5)
return v2;
else if (h < 2.0 / 3)
return v1 + (v2 - v1) * (2.0 / 3 - h) * 6.0;
return v1;
}
void
hsl_color_rgb (double h, double s, double l, uint32_t *rgb)
{
if (!s)
*rgb = RGB_TO_UINT32 (std::lrint (l * 255),
std::lrint (l * 255),
std::lrint (l * 255));
else
{
double m2 = l <= 0.5 ? l * (1 + s) : l + s - l * s;
double m1 = 2.0 * l - m2;
*rgb = RGB_TO_UINT32
(std::lrint (hue_to_rgb (m1, m2,
std::fmod (h + 1 / 3.0, 1)) * 255),
std::lrint (hue_to_rgb (m1, m2, h) * 255),
std::lrint (hue_to_rgb (m1, m2,
std::fmod (h - 1 / 3.0, 1)) * 255));
}
}
void
BView_DrawBitmap (void *view, void *bitmap, int x, int y,
int width, int height, int vx, int vy, int vwidth,
int vheight)
{
BView *vw = get_view (view);
BBitmap *bm = (BBitmap *) bitmap;
vw->PushState ();
vw->SetDrawingMode (B_OP_OVER);
vw->DrawBitmap (bm, BRect (x, y, x + width - 1, y + height - 1),
BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1));
vw->PopState ();
}
void
BView_DrawBitmapWithEraseOp (void *view, void *bitmap, int x,
int y, int width, int height)
{
BView *vw = get_view (view);
BBitmap *bm = (BBitmap *) bitmap;
BBitmap bc (bm->Bounds (), B_RGBA32);
BRect rect (x, y, x + width - 1, y + height - 1);
if (bc.InitCheck () != B_OK || bc.ImportBits (bm) != B_OK)
return;
uint32_t *bits = (uint32_t *) bc.Bits ();
size_t stride = bc.BytesPerRow ();
if (bm->ColorSpace () == B_GRAY1)
{
rgb_color low_color = vw->LowColor ();
for (int y = 0; y <= bc.Bounds ().Height (); ++y)
{
for (int x = 0; x <= bc.Bounds ().Width (); ++x)
{
if (bits[y * (stride / 4) + x] == 0xFF000000)
bits[y * (stride / 4) + x] = RGB_COLOR_UINT32 (low_color);
else
bits[y * (stride / 4) + x] = 0;
}
}
}
vw->PushState ();
vw->SetDrawingMode (bm->ColorSpace () == B_GRAY1 ? B_OP_OVER : B_OP_ERASE);
vw->DrawBitmap (&bc, rect);
vw->PopState ();
}
void
BView_DrawMask (void *src, void *view,
int x, int y, int width, int height,
int vx, int vy, int vwidth, int vheight,
uint32_t color)
{
BBitmap *source = (BBitmap *) src;
BBitmap bm (source->Bounds (), B_RGBA32);
if (bm.InitCheck () != B_OK)
return;
for (int y = 0; y <= bm.Bounds ().Height (); ++y)
{
for (int x = 0; x <= bm.Bounds ().Width (); ++x)
{
int bit = haiku_get_pixel ((void *) source, x, y);
if (!bit)
haiku_put_pixel ((void *) &bm, x, y, ((uint32_t) 255 << 24) | color);
else
haiku_put_pixel ((void *) &bm, x, y, 0);
}
}
BView *vw = get_view (view);
vw->SetDrawingMode (B_OP_OVER);
vw->DrawBitmap (&bm, BRect (x, y, x + width - 1, y + height - 1),
BRect (vx, vy, vx + vwidth - 1, vy + vheight - 1));
}
static BBitmap *
rotate_bitmap_270 (BBitmap *bmp)
{
BRect r = bmp->Bounds ();
BBitmap *bm = new BBitmap (BRect (r.top, r.left, r.bottom, r.right),
bmp->ColorSpace (), true);
if (bm->InitCheck () != B_OK)
gui_abort ("Failed to init bitmap for rotate");
int w = bmp->Bounds ().Width () + 1;
int h = bmp->Bounds ().Height () + 1;
for (int y = 0; y < h; ++y)
for (int x = 0; x < w; ++x)
haiku_put_pixel ((void *) bm, y, w - x - 1,
haiku_get_pixel ((void *) bmp, x, y));
return bm;
}
static BBitmap *
rotate_bitmap_90 (BBitmap *bmp)
{
BRect r = bmp->Bounds ();
BBitmap *bm = new BBitmap (BRect (r.top, r.left, r.bottom, r.right),
bmp->ColorSpace (), true);
if (bm->InitCheck () != B_OK)
gui_abort ("Failed to init bitmap for rotate");
int w = bmp->Bounds ().Width () + 1;
int h = bmp->Bounds ().Height () + 1;
for (int y = 0; y < h; ++y)
for (int x = 0; x < w; ++x)
haiku_put_pixel ((void *) bm, h - y - 1, x,
haiku_get_pixel ((void *) bmp, x, y));
return bm;
}
void *
BBitmap_transform_bitmap (void *bitmap, void *mask, uint32_t m_color,
double rot, int desw, int desh)
{
BBitmap *bm = (BBitmap *) bitmap;
BBitmap *mk = (BBitmap *) mask;
int copied_p = 0;
if (rot == 90)
{
copied_p = 1;
bm = rotate_bitmap_90 (bm);
if (mk)
mk = rotate_bitmap_90 (mk);
}
if (rot == 270)
{
copied_p = 1;
bm = rotate_bitmap_270 (bm);
if (mk)
mk = rotate_bitmap_270 (mk);
}
BRect r = bm->Bounds ();
if (r.Width () != desw || r.Height () != desh)
{
BRect n = BRect (0, 0, desw - 1, desh - 1);
BView vw (n, NULL, B_FOLLOW_NONE, 0);
BBitmap *dst = new BBitmap (n, bm->ColorSpace (), true);
if (dst->InitCheck () != B_OK)
if (bm->InitCheck () != B_OK)
gui_abort ("Failed to init bitmap for scale");
dst->AddChild (&vw);
if (!vw.LockLooper ())
gui_abort ("Failed to lock offscreen view for scale");
if (rot != 90 && rot != 270)
{
BAffineTransform tr;
tr.RotateBy (BPoint (desw / 2, desh / 2), rot * M_PI / 180.0);
vw.SetTransform (tr);
}
vw.MovePenTo (0, 0);
vw.DrawBitmap (bm, n);
if (mk)
BView_DrawMask ((void *) mk, (void *) &vw,
0, 0, mk->Bounds ().Width (),
mk->Bounds ().Height (),
0, 0, desw, desh, m_color);
vw.Sync ();
vw.RemoveSelf ();
if (copied_p)
delete bm;
if (copied_p && mk)
delete mk;
return dst;
}
return bm;
}
void
BView_FillTriangle (void *view, int x1, int y1,
int x2, int y2, int x3, int y3)
{
BView *vw = get_view (view);
vw->FillTriangle (BPoint (x1, y1), BPoint (x2, y2),
BPoint (x3, y3));
}
void
BView_SetHighColorForVisibleBell (void *view, uint32_t color)
{
BView *vw = (BView *) view;
rgb_color col;
rgb32_to_rgb_color (color, &col);
vw->SetHighColor (col);
}
void
BView_FillRectangleForVisibleBell (void *view, int x, int y, int width, int height)
{
BView *vw = (BView *) view;
BRect rect = BRect (x, y, x + width - 1, y + height - 1);
vw->FillRect (rect);
}

596
src/haiku_font_support.cc Normal file
View file

@ -0,0 +1,596 @@
/* Haiku window system support. Hey, Emacs, this is -*- C++ -*-
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include <Font.h>
#include <Rect.h>
#include <AffineTransform.h>
#include <cstring>
#include <cmath>
#include "haiku_support.h"
/* Haiku doesn't expose font language data in BFont objects. Thus, we
select a few representative characters for each supported `:lang'
(currently Chinese, Korean and Japanese,) and test for those
instead. */
static uint32_t language_code_points[MAX_LANGUAGE][4] =
{{20154, 20754, 22996, 0}, /* Chinese. */
{51312, 49440, 44544, 0}, /* Korean. */
{26085, 26412, 12371, 0}, /* Japanese. */};
static void
estimate_font_ascii (BFont *font, int *max_width,
int *min_width, int *avg_width)
{
char ch[2];
bool tems[1];
int total = 0;
int count = 0;
int min = 0;
int max = 0;
std::memset (ch, 0, sizeof ch);
for (ch[0] = 32; ch[0] < 127; ++ch[0])
{
tems[0] = false;
font->GetHasGlyphs (ch, 1, tems);
if (tems[0])
{
int w = font->StringWidth (ch);
++count;
total += w;
if (!min || min > w)
min = w;
if (max < w)
max = w;
}
}
*min_width = min;
*max_width = max;
*avg_width = total / count;
}
void
BFont_close (void *font)
{
if (font != (void *) be_fixed_font &&
font != (void *) be_plain_font &&
font != (void *) be_bold_font)
delete (BFont *) font;
}
void
BFont_dat (void *font, int *px_size, int *min_width, int *max_width,
int *avg_width, int *height, int *space_width, int *ascent,
int *descent, int *underline_position, int *underline_thickness)
{
BFont *ft = (BFont *) font;
struct font_height fheight;
bool have_space_p;
char atem[1];
bool otem[1];
ft->GetHeight (&fheight);
atem[0] = ' ';
otem[0] = false;
ft->GetHasGlyphs (atem, 1, otem);
have_space_p = otem[0];
estimate_font_ascii (ft, max_width, min_width, avg_width);
*ascent = std::lrint (fheight.ascent);
*descent = std::lrint (fheight.descent);
*height = *ascent + *descent;
*space_width = have_space_p ? ft->StringWidth (" ") : 0;
*px_size = std::lrint (ft->Size ());
*underline_position = 0;
*underline_thickness = 0;
}
/* Return non-null if FONT contains CHR, a Unicode code-point. */
int
BFont_have_char_p (void *font, int32_t chr)
{
BFont *ft = (BFont *) font;
return ft->IncludesBlock (chr, chr);
}
/* Return non-null if font contains a block from BEG to END. */
int
BFont_have_char_block (void *font, int32_t beg, int32_t end)
{
BFont *ft = (BFont *) font;
return ft->IncludesBlock (beg, end);
}
/* Compute bounds for MB_STR, a character in multibyte encoding,
used with font. The width (in pixels) is returned in ADVANCE,
the left bearing in LB, and the right bearing in RB. */
void
BFont_char_bounds (void *font, const char *mb_str, int *advance,
int *lb, int *rb)
{
BFont *ft = (BFont *) font;
edge_info edge_info;
float size, escapement;
size = ft->Size ();
ft->GetEdges (mb_str, 1, &edge_info);
ft->GetEscapements (mb_str, 1, &escapement);
*advance = std::lrint (escapement * size);
*lb = std::lrint (edge_info.left * size);
*rb = *advance + std::lrint (edge_info.right * size);
}
/* The same, but for a variable amount of chars. */
void
BFont_nchar_bounds (void *font, const char *mb_str, int *advance,
int *lb, int *rb, int32_t n)
{
BFont *ft = (BFont *) font;
edge_info edge_info[n];
float size;
float escapement[n];
size = ft->Size ();
ft->GetEdges (mb_str, n, edge_info);
ft->GetEscapements (mb_str, n, (float *) escapement);
for (int32_t i = 0; i < n; ++i)
{
advance[i] = std::lrint (escapement[i] * size);
lb[i] = advance[i] - std::lrint (edge_info[i].left * size);
rb[i] = advance[i] + std::lrint (edge_info[i].right * size);
}
}
static void
font_style_to_flags (char *st, struct haiku_font_pattern *pattern)
{
char *style = strdup (st);
char *token;
pattern->weight = -1;
pattern->width = NO_WIDTH;
pattern->slant = NO_SLANT;
int tok = 0;
while ((token = std::strtok (!tok ? style : NULL, " ")) && tok < 3)
{
if (token && !strcmp (token, "Thin"))
pattern->weight = HAIKU_THIN;
else if (token && !strcmp (token, "UltraLight"))
pattern->weight = HAIKU_ULTRALIGHT;
else if (token && !strcmp (token, "ExtraLight"))
pattern->weight = HAIKU_EXTRALIGHT;
else if (token && !strcmp (token, "Light"))
pattern->weight = HAIKU_LIGHT;
else if (token && !strcmp (token, "SemiLight"))
pattern->weight = HAIKU_SEMI_LIGHT;
else if (token && !strcmp (token, "Regular"))
{
if (pattern->slant == NO_SLANT)
pattern->slant = SLANT_REGULAR;
if (pattern->width == NO_WIDTH)
pattern->width = NORMAL_WIDTH;
if (pattern->weight == -1)
pattern->weight = HAIKU_REGULAR;
}
else if (token && !strcmp (token, "SemiBold"))
pattern->weight = HAIKU_SEMI_BOLD;
else if (token && !strcmp (token, "Bold"))
pattern->weight = HAIKU_BOLD;
else if (token && (!strcmp (token, "ExtraBold") ||
/* This has actually been seen in the wild. */
!strcmp (token, "Extrabold")))
pattern->weight = HAIKU_EXTRA_BOLD;
else if (token && !strcmp (token, "UltraBold"))
pattern->weight = HAIKU_ULTRA_BOLD;
else if (token && !strcmp (token, "Book"))
pattern->weight = HAIKU_BOOK;
else if (token && !strcmp (token, "Heavy"))
pattern->weight = HAIKU_HEAVY;
else if (token && !strcmp (token, "UltraHeavy"))
pattern->weight = HAIKU_ULTRA_HEAVY;
else if (token && !strcmp (token, "Black"))
pattern->weight = HAIKU_BLACK;
else if (token && !strcmp (token, "Medium"))
pattern->weight = HAIKU_MEDIUM;
else if (token && !strcmp (token, "Oblique"))
pattern->slant = SLANT_OBLIQUE;
else if (token && !strcmp (token, "Italic"))
pattern->slant = SLANT_ITALIC;
else if (token && !strcmp (token, "UltraCondensed"))
pattern->width = ULTRA_CONDENSED;
else if (token && !strcmp (token, "ExtraCondensed"))
pattern->width = EXTRA_CONDENSED;
else if (token && !strcmp (token, "Condensed"))
pattern->width = CONDENSED;
else if (token && !strcmp (token, "SemiCondensed"))
pattern->width = SEMI_CONDENSED;
else if (token && !strcmp (token, "SemiExpanded"))
pattern->width = SEMI_EXPANDED;
else if (token && !strcmp (token, "Expanded"))
pattern->width = EXPANDED;
else if (token && !strcmp (token, "ExtraExpanded"))
pattern->width = EXTRA_EXPANDED;
else if (token && !strcmp (token, "UltraExpanded"))
pattern->width = ULTRA_EXPANDED;
else
{
tok = 1000;
break;
}
tok++;
}
if (pattern->weight != -1)
pattern->specified |= FSPEC_WEIGHT;
if (pattern->slant != NO_SLANT)
pattern->specified |= FSPEC_SLANT;
if (pattern->width != NO_WIDTH)
pattern->specified |= FSPEC_WIDTH;
if (tok > 3)
{
pattern->specified &= ~FSPEC_SLANT;
pattern->specified &= ~FSPEC_WEIGHT;
pattern->specified &= ~FSPEC_WIDTH;
pattern->specified |= FSPEC_STYLE;
std::strncpy ((char *) &pattern->style, st,
sizeof pattern->style - 1);
}
free (style);
}
static bool
font_check_wanted_chars (struct haiku_font_pattern *pattern, font_family family,
char *style)
{
BFont ft;
if (ft.SetFamilyAndStyle (family, style) != B_OK)
return false;
for (int i = 0; i < pattern->want_chars_len; ++i)
if (!ft.IncludesBlock (pattern->wanted_chars[i],
pattern->wanted_chars[i]))
return false;
return true;
}
static bool
font_check_one_of (struct haiku_font_pattern *pattern, font_family family,
char *style)
{
BFont ft;
if (ft.SetFamilyAndStyle (family, style) != B_OK)
return false;
for (int i = 0; i < pattern->need_one_of_len; ++i)
if (ft.IncludesBlock (pattern->need_one_of[i],
pattern->need_one_of[i]))
return true;
return false;
}
static bool
font_check_language (struct haiku_font_pattern *pattern, font_family family,
char *style)
{
BFont ft;
if (ft.SetFamilyAndStyle (family, style) != B_OK)
return false;
if (pattern->language == MAX_LANGUAGE)
return false;
for (uint32_t *ch = (uint32_t *)
&language_code_points[pattern->language]; *ch; ch++)
if (!ft.IncludesBlock (*ch, *ch))
return false;
return true;
}
static bool
font_family_style_matches_p (font_family family, char *style, uint32_t flags,
struct haiku_font_pattern *pattern,
int ignore_flags_p = 0)
{
struct haiku_font_pattern m;
m.specified = 0;
if (style)
font_style_to_flags (style, &m);
if ((pattern->specified & FSPEC_FAMILY) &&
strcmp ((char *) &pattern->family, family))
return false;
if (!ignore_flags_p && (pattern->specified & FSPEC_SPACING) &&
!(pattern->mono_spacing_p) != !(flags & B_IS_FIXED))
return false;
if (pattern->specified & FSPEC_STYLE)
return style && !strcmp (style, pattern->style);
if ((pattern->specified & FSPEC_WEIGHT)
&& (pattern->weight
!= ((m.specified & FSPEC_WEIGHT) ? m.weight : HAIKU_REGULAR)))
return false;
if ((pattern->specified & FSPEC_SLANT)
&& (pattern->slant
!= ((m.specified & FSPEC_SLANT) ? m.slant : SLANT_REGULAR)))
return false;
if ((pattern->specified & FSPEC_WANTED)
&& !font_check_wanted_chars (pattern, family, style))
return false;
if ((pattern->specified & FSPEC_WIDTH)
&& (pattern->width !=
((m.specified & FSPEC_WIDTH) ? m.width : NORMAL_WIDTH)))
return false;
if ((pattern->specified & FSPEC_NEED_ONE_OF)
&& !font_check_one_of (pattern, family, style))
return false;
if ((pattern->specified & FSPEC_LANGUAGE)
&& !font_check_language (pattern, family, style))
return false;
return true;
}
static void
haiku_font_fill_pattern (struct haiku_font_pattern *pattern,
font_family family, char *style,
uint32_t flags)
{
if (style)
font_style_to_flags (style, pattern);
pattern->specified |= FSPEC_FAMILY;
std::strncpy (pattern->family, family,
sizeof pattern->family - 1);
pattern->specified |= FSPEC_SPACING;
pattern->mono_spacing_p = flags & B_IS_FIXED;
}
/* Delete every element of the font pattern PT. */
void
haiku_font_pattern_free (struct haiku_font_pattern *pt)
{
struct haiku_font_pattern *tem = pt;
while (tem)
{
struct haiku_font_pattern *t = tem;
tem = t->next;
delete t;
}
}
/* Find all fonts matching the font pattern PT. */
struct haiku_font_pattern *
BFont_find (struct haiku_font_pattern *pt)
{
struct haiku_font_pattern *r = NULL;
font_family name;
font_style sname;
uint32 flags;
int sty_count;
int fam_count = count_font_families ();
for (int fi = 0; fi < fam_count; ++fi)
{
if (get_font_family (fi, &name, &flags) == B_OK)
{
sty_count = count_font_styles (name);
if (!sty_count &&
font_family_style_matches_p (name, NULL, flags, pt))
{
struct haiku_font_pattern *p = new struct haiku_font_pattern;
p->specified = 0;
p->oblique_seen_p = 1;
haiku_font_fill_pattern (p, name, NULL, flags);
p->next = r;
if (p->next)
p->next->last = p;
p->last = NULL;
p->next_family = r;
r = p;
}
else if (sty_count)
{
for (int si = 0; si < sty_count; ++si)
{
int oblique_seen_p = 0;
struct haiku_font_pattern *head = r;
struct haiku_font_pattern *p = NULL;
if (get_font_style (name, si, &sname, &flags) == B_OK)
{
if (font_family_style_matches_p (name, (char *) &sname, flags, pt))
{
p = new struct haiku_font_pattern;
p->specified = 0;
haiku_font_fill_pattern (p, name, (char *) &sname, flags);
if (p->specified & FSPEC_SLANT &&
((p->slant == SLANT_OBLIQUE) || (p->slant == SLANT_ITALIC)))
oblique_seen_p = 1;
p->next = r;
if (p->next)
p->next->last = p;
r = p;
p->next_family = head;
}
}
if (p)
p->last = NULL;
for (; head; head = head->last)
{
head->oblique_seen_p = oblique_seen_p;
}
}
}
}
}
/* There's a very good chance that this result will get cached if no
slant is specified. Thus, we look through each font that hasn't
seen an oblique style, and add one. */
if (!(pt->specified & FSPEC_SLANT))
{
/* r->last is invalid from here onwards. */
for (struct haiku_font_pattern *p = r; p;)
{
if (!p->oblique_seen_p)
{
struct haiku_font_pattern *n = new haiku_font_pattern;
*n = *p;
n->slant = SLANT_OBLIQUE;
p->next = n;
p = p->next_family;
}
else
p = p->next_family;
}
}
return r;
}
/* Find and open a font matching the pattern PAT, which must have its
family set. */
int
BFont_open_pattern (struct haiku_font_pattern *pat, void **font, float size)
{
int sty_count;
font_family name;
font_style sname;
uint32 flags = 0;
if (!(pat->specified & FSPEC_FAMILY))
return 1;
strncpy (name, pat->family, sizeof name - 1);
sty_count = count_font_styles (name);
if (!sty_count &&
font_family_style_matches_p (name, NULL, flags, pat, 1))
{
BFont *ft = new BFont;
if (ft->SetFamilyAndStyle (name, NULL) != B_OK)
{
delete ft;
return 1;
}
ft->SetSize (size);
ft->SetEncoding (B_UNICODE_UTF8);
ft->SetSpacing (B_BITMAP_SPACING);
*font = (void *) ft;
return 0;
}
else if (sty_count)
{
for (int si = 0; si < sty_count; ++si)
{
if (get_font_style (name, si, &sname, &flags) == B_OK &&
font_family_style_matches_p (name, (char *) &sname, flags, pat))
{
BFont *ft = new BFont;
if (ft->SetFamilyAndStyle (name, sname) != B_OK)
{
delete ft;
return 1;
}
ft->SetSize (size);
ft->SetEncoding (B_UNICODE_UTF8);
ft->SetSpacing (B_BITMAP_SPACING);
*font = (void *) ft;
return 0;
}
}
}
if (pat->specified & FSPEC_SLANT && pat->slant == SLANT_OBLIQUE)
{
struct haiku_font_pattern copy = *pat;
copy.slant = SLANT_REGULAR;
int code = BFont_open_pattern (&copy, font, size);
if (code)
return code;
BFont *ft = (BFont *) *font;
/* XXX Font measurements don't respect shear. Haiku bug?
This apparently worked in BeOS.
ft->SetShear (100.0); */
ft->SetFace (B_ITALIC_FACE);
return 0;
}
return 1;
}
/* Query the family of the default fixed font. */
void
BFont_populate_fixed_family (struct haiku_font_pattern *ptn)
{
font_family f;
font_style s;
be_fixed_font->GetFamilyAndStyle (&f, &s);
ptn->specified |= FSPEC_FAMILY;
strncpy (ptn->family, f, sizeof ptn->family - 1);
}
void
BFont_populate_plain_family (struct haiku_font_pattern *ptn)
{
font_family f;
font_style s;
be_plain_font->GetFamilyAndStyle (&f, &s);
ptn->specified |= FSPEC_FAMILY;
strncpy (ptn->family, f, sizeof ptn->family - 1);
}
int
BFont_string_width (void *font, const char *utf8)
{
return ((BFont *) font)->StringWidth (utf8);
}

207
src/haiku_io.c Normal file
View file

@ -0,0 +1,207 @@
/* Haiku window system support.
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include <signal.h>
#include <stdio.h>
#include <pthread.h>
#include <unistd.h>
#include <OS.h>
#include "haiku_support.h"
#include "lisp.h"
#include "haikuterm.h"
#include "blockinput.h"
#define PORT_CAP 1200
/* The port used to send messages from the application thread to
Emacs. */
port_id port_application_to_emacs;
void
haiku_io_init (void)
{
port_application_to_emacs = create_port (PORT_CAP, "application emacs port");
}
static ssize_t
haiku_len (enum haiku_event_type type)
{
switch (type)
{
case QUIT_REQUESTED:
return sizeof (struct haiku_quit_requested_event);
case FRAME_RESIZED:
return sizeof (struct haiku_resize_event);
case FRAME_EXPOSED:
return sizeof (struct haiku_expose_event);
case KEY_DOWN:
case KEY_UP:
return sizeof (struct haiku_key_event);
case ACTIVATION:
return sizeof (struct haiku_activation_event);
case MOUSE_MOTION:
return sizeof (struct haiku_mouse_motion_event);
case BUTTON_DOWN:
case BUTTON_UP:
return sizeof (struct haiku_button_event);
case ICONIFICATION:
return sizeof (struct haiku_iconification_event);
case MOVE_EVENT:
return sizeof (struct haiku_move_event);
case SCROLL_BAR_VALUE_EVENT:
return sizeof (struct haiku_scroll_bar_value_event);
case SCROLL_BAR_DRAG_EVENT:
return sizeof (struct haiku_scroll_bar_drag_event);
case WHEEL_MOVE_EVENT:
return sizeof (struct haiku_wheel_move_event);
case MENU_BAR_RESIZE:
return sizeof (struct haiku_menu_bar_resize_event);
case MENU_BAR_OPEN:
case MENU_BAR_CLOSE:
return sizeof (struct haiku_menu_bar_state_event);
case MENU_BAR_SELECT_EVENT:
return sizeof (struct haiku_menu_bar_select_event);
case FILE_PANEL_EVENT:
return sizeof (struct haiku_file_panel_event);
case MENU_BAR_HELP_EVENT:
return sizeof (struct haiku_menu_bar_help_event);
case ZOOM_EVENT:
return sizeof (struct haiku_zoom_event);
case REFS_EVENT:
return sizeof (struct haiku_refs_event);
case APP_QUIT_REQUESTED_EVENT:
return sizeof (struct haiku_app_quit_requested_event);
}
emacs_abort ();
}
/* Read the size of the next message into len, returning -1 if the
query fails or there is no next message. */
void
haiku_read_size (ssize_t *len)
{
port_id from = port_application_to_emacs;
ssize_t size;
size = port_buffer_size_etc (from, B_TIMEOUT, 0);
if (size < B_OK)
*len = -1;
else
*len = size;
}
/* Read the next message into BUF, putting its type into TYPE,
assuming the message is at most LEN long. Return 0 if successful
and -1 if the read fails. */
int
haiku_read (enum haiku_event_type *type, void *buf, ssize_t len)
{
int32 typ;
port_id from = port_application_to_emacs;
if (read_port (from, &typ, buf, len) < B_OK)
return -1;
*type = (enum haiku_event_type) typ;
eassert (len >= haiku_len (typ));
return 0;
}
/* The same as haiku_read, but time out after TIMEOUT microseconds.
Input is blocked when an attempt to read is in progress. */
int
haiku_read_with_timeout (enum haiku_event_type *type, void *buf, ssize_t len,
time_t timeout)
{
int32 typ;
port_id from = port_application_to_emacs;
block_input ();
if (read_port_etc (from, &typ, buf, len,
B_TIMEOUT, (bigtime_t) timeout) < B_OK)
{
unblock_input ();
return -1;
}
unblock_input ();
*type = (enum haiku_event_type) typ;
eassert (len >= haiku_len (typ));
return 0;
}
/* Write a message with type TYPE into BUF. */
int
haiku_write (enum haiku_event_type type, void *buf)
{
port_id to = port_application_to_emacs;
if (write_port (to, (int32_t) type, buf, haiku_len (type)) < B_OK)
return -1;
kill (getpid (), SIGPOLL);
return 0;
}
int
haiku_write_without_signal (enum haiku_event_type type, void *buf)
{
port_id to = port_application_to_emacs;
if (write_port (to, (int32_t) type, buf, haiku_len (type)) < B_OK)
return -1;
return 0;
}
void
haiku_io_init_in_app_thread (void)
{
sigset_t set;
sigfillset (&set);
if (pthread_sigmask (SIG_BLOCK, &set, NULL))
perror ("pthread_sigmask");
}
/* Record an unwind protect from C++ code. */
void
record_c_unwind_protect_from_cxx (void (*fn) (void *), void *r)
{
record_unwind_protect_ptr (fn, r);
}
/* SPECPDL_IDX that is safe from C++ code. */
ptrdiff_t
c_specpdl_idx_from_cxx (void)
{
return SPECPDL_INDEX ();
}
/* unbind_to (IDX, Qnil), but safe from C++ code. */
void
c_unbind_to_nil_from_cxx (ptrdiff_t idx)
{
unbind_to (idx, Qnil);
}

155
src/haiku_select.cc Normal file
View file

@ -0,0 +1,155 @@
/* Haiku window system selection support. Hey Emacs, this is -*- C++ -*-
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include <Clipboard.h>
#include <cstdlib>
#include <cstring>
#include "haikuselect.h"
static BClipboard *primary = NULL;
static BClipboard *secondary = NULL;
static BClipboard *system_clipboard = NULL;
int selection_state_flag;
static char *
BClipboard_find_data (BClipboard *cb, const char *type, ssize_t *len)
{
if (!cb->Lock ())
return 0;
BMessage *dat = cb->Data ();
if (!dat)
{
cb->Unlock ();
return 0;
}
const char *ptr;
ssize_t bt;
dat->FindData (type, B_MIME_TYPE, (const void **) &ptr, &bt);
if (!ptr)
{
cb->Unlock ();
return NULL;
}
if (len)
*len = bt;
cb->Unlock ();
return strndup (ptr, bt);
}
static void
BClipboard_set_data (BClipboard *cb, const char *type, const char *dat,
ssize_t len)
{
if (!cb->Lock ())
return;
cb->Clear ();
BMessage *mdat = cb->Data ();
if (!mdat)
{
cb->Unlock ();
return;
}
if (dat)
mdat->AddData (type, B_MIME_TYPE, dat, len);
cb->Commit ();
cb->Unlock ();
}
char *
BClipboard_find_system_data (const char *type, ssize_t *len)
{
if (!system_clipboard)
return 0;
return BClipboard_find_data (system_clipboard, type, len);
}
char *
BClipboard_find_primary_selection_data (const char *type, ssize_t *len)
{
if (!primary)
return 0;
return BClipboard_find_data (primary, type, len);
}
char *
BClipboard_find_secondary_selection_data (const char *type, ssize_t *len)
{
if (!secondary)
return 0;
return BClipboard_find_data (secondary, type, len);
}
void
BClipboard_set_system_data (const char *type, const char *data,
ssize_t len)
{
if (!system_clipboard)
return;
BClipboard_set_data (system_clipboard, type, data, len);
}
void
BClipboard_set_primary_selection_data (const char *type, const char *data,
ssize_t len)
{
if (!primary)
return;
BClipboard_set_data (primary, type, data, len);
}
void
BClipboard_set_secondary_selection_data (const char *type, const char *data,
ssize_t len)
{
if (!secondary)
return;
BClipboard_set_data (secondary, type, data, len);
}
void
BClipboard_free_data (void *ptr)
{
std::free (ptr);
}
void
init_haiku_select (void)
{
system_clipboard = new BClipboard ("system");
primary = new BClipboard ("primary");
secondary = new BClipboard ("secondary");
}

2930
src/haiku_support.cc Normal file

File diff suppressed because it is too large Load diff

869
src/haiku_support.h Normal file
View file

@ -0,0 +1,869 @@
/* Haiku window system support. Hey Emacs, this is -*- C++ -*-
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _HAIKU_SUPPORT_H
#define _HAIKU_SUPPORT_H
#include <stdint.h>
#ifdef HAVE_FREETYPE
#include <ft2build.h>
#include <fontconfig/fontconfig.h>
#include FT_FREETYPE_H
#include FT_SIZES_H
#endif
#ifdef USE_BE_CAIRO
#include <cairo.h>
#endif
enum haiku_cursor
{
CURSOR_ID_NO_CURSOR = 12,
CURSOR_ID_RESIZE_NORTH = 15,
CURSOR_ID_RESIZE_EAST = 16,
CURSOR_ID_RESIZE_SOUTH = 17,
CURSOR_ID_RESIZE_WEST = 18,
CURSOR_ID_RESIZE_NORTH_EAST = 19,
CURSOR_ID_RESIZE_NORTH_WEST = 20,
CURSOR_ID_RESIZE_SOUTH_EAST = 21,
CURSOR_ID_RESIZE_SOUTH_WEST = 22,
CURSOR_ID_RESIZE_NORTH_SOUTH = 23,
CURSOR_ID_RESIZE_EAST_WEST = 24,
CURSOR_ID_RESIZE_NORTH_EAST_SOUTH_WEST = 25,
CURSOR_ID_RESIZE_NORTH_WEST_SOUTH_EAST = 26
};
enum haiku_alert_type
{
HAIKU_EMPTY_ALERT = 0,
HAIKU_INFO_ALERT,
HAIKU_IDEA_ALERT,
HAIKU_WARNING_ALERT,
HAIKU_STOP_ALERT
};
enum haiku_event_type
{
QUIT_REQUESTED,
FRAME_RESIZED,
FRAME_EXPOSED,
KEY_DOWN,
KEY_UP,
ACTIVATION,
MOUSE_MOTION,
BUTTON_DOWN,
BUTTON_UP,
ICONIFICATION,
MOVE_EVENT,
SCROLL_BAR_VALUE_EVENT,
SCROLL_BAR_DRAG_EVENT,
WHEEL_MOVE_EVENT,
MENU_BAR_RESIZE,
MENU_BAR_OPEN,
MENU_BAR_SELECT_EVENT,
MENU_BAR_CLOSE,
FILE_PANEL_EVENT,
MENU_BAR_HELP_EVENT,
ZOOM_EVENT,
REFS_EVENT,
APP_QUIT_REQUESTED_EVENT
};
struct haiku_quit_requested_event
{
void *window;
};
struct haiku_resize_event
{
void *window;
float px_heightf;
float px_widthf;
};
struct haiku_expose_event
{
void *window;
int x;
int y;
int width;
int height;
};
struct haiku_refs_event
{
void *window;
int x, y;
/* Free this with free! */
char *ref;
};
struct haiku_app_quit_requested_event
{
char dummy;
};
#define HAIKU_MODIFIER_ALT (1)
#define HAIKU_MODIFIER_CTRL (1 << 1)
#define HAIKU_MODIFIER_SHIFT (1 << 2)
#define HAIKU_MODIFIER_SUPER (1 << 3)
struct haiku_key_event
{
void *window;
int modifiers;
uint32_t mb_char;
uint32_t unraw_mb_char;
short kc;
};
struct haiku_activation_event
{
void *window;
int activated_p;
};
struct haiku_mouse_motion_event
{
void *window;
bool just_exited_p;
int x;
int y;
uint32_t be_code;
};
struct haiku_button_event
{
void *window;
int btn_no;
int modifiers;
int x;
int y;
};
struct haiku_iconification_event
{
void *window;
int iconified_p;
};
struct haiku_move_event
{
void *window;
int x;
int y;
};
struct haiku_wheel_move_event
{
void *window;
int modifiers;
float delta_x;
float delta_y;
};
struct haiku_menu_bar_select_event
{
void *window;
void *ptr;
};
struct haiku_file_panel_event
{
void *ptr;
};
struct haiku_menu_bar_help_event
{
void *window;
int mb_idx;
};
struct haiku_zoom_event
{
void *window;
int x;
int y;
int width;
int height;
};
#define FSPEC_FAMILY 1
#define FSPEC_STYLE (1 << 1)
#define FSPEC_SLANT (1 << 2)
#define FSPEC_WEIGHT (1 << 3)
#define FSPEC_SPACING (1 << 4)
#define FSPEC_WANTED (1 << 5)
#define FSPEC_NEED_ONE_OF (1 << 6)
#define FSPEC_WIDTH (1 << 7)
#define FSPEC_LANGUAGE (1 << 8)
typedef char haiku_font_family_or_style[64];
enum haiku_font_slant
{
NO_SLANT = -1,
SLANT_OBLIQUE,
SLANT_REGULAR,
SLANT_ITALIC
};
enum haiku_font_width
{
NO_WIDTH = -1,
ULTRA_CONDENSED,
EXTRA_CONDENSED,
CONDENSED,
SEMI_CONDENSED,
NORMAL_WIDTH,
SEMI_EXPANDED,
EXPANDED,
EXTRA_EXPANDED,
ULTRA_EXPANDED
};
enum haiku_font_language
{
LANGUAGE_CN,
LANGUAGE_KO,
LANGUAGE_JP,
MAX_LANGUAGE /* This isn't a language. */
};
struct haiku_font_pattern
{
int specified;
struct haiku_font_pattern *next;
/* The next two fields are only temporarily used during the font
discovery process! Do not rely on them being correct outside
BFont_find. */
struct haiku_font_pattern *last;
struct haiku_font_pattern *next_family;
haiku_font_family_or_style family;
haiku_font_family_or_style style;
int weight;
int mono_spacing_p;
int want_chars_len;
int need_one_of_len;
enum haiku_font_slant slant;
enum haiku_font_width width;
enum haiku_font_language language;
uint32_t *wanted_chars;
uint32_t *need_one_of;
int oblique_seen_p;
};
struct haiku_scroll_bar_value_event
{
void *scroll_bar;
int position;
};
struct haiku_scroll_bar_drag_event
{
void *scroll_bar;
int dragging_p;
};
struct haiku_menu_bar_resize_event
{
void *window;
int width;
int height;
};
struct haiku_menu_bar_state_event
{
void *window;
};
#define HAIKU_THIN 0
#define HAIKU_ULTRALIGHT 20
#define HAIKU_EXTRALIGHT 40
#define HAIKU_LIGHT 50
#define HAIKU_SEMI_LIGHT 75
#define HAIKU_REGULAR 100
#define HAIKU_SEMI_BOLD 180
#define HAIKU_BOLD 200
#define HAIKU_EXTRA_BOLD 205
#define HAIKU_ULTRA_BOLD 210
#define HAIKU_BOOK 400
#define HAIKU_HEAVY 800
#define HAIKU_ULTRA_HEAVY 900
#define HAIKU_BLACK 1000
#define HAIKU_MEDIUM 2000
#ifdef __cplusplus
extern "C"
{
#endif
#include <pthread.h>
#include <OS.h>
#ifdef __cplusplus
typedef void *haiku;
extern void
haiku_put_pixel (haiku bitmap, int x, int y, unsigned long pixel);
extern unsigned long
haiku_get_pixel (haiku bitmap, int x, int y);
#endif
extern port_id port_application_to_emacs;
extern void haiku_io_init (void);
extern void haiku_io_init_in_app_thread (void);
extern void
haiku_read_size (ssize_t *len);
extern int
haiku_read (enum haiku_event_type *type, void *buf, ssize_t len);
extern int
haiku_read_with_timeout (enum haiku_event_type *type, void *buf, ssize_t len,
time_t timeout);
extern int
haiku_write (enum haiku_event_type type, void *buf);
extern int
haiku_write_without_signal (enum haiku_event_type type, void *buf);
extern void
rgb_color_hsl (uint32_t rgb, double *h, double *s, double *l);
extern void
hsl_color_rgb (double h, double s, double l, uint32_t *rgb);
extern void *
BBitmap_new (int width, int height, int mono_p);
extern void *
BBitmap_data (void *bitmap);
extern int
BBitmap_convert (void *bitmap, void **new_bitmap);
extern void
BBitmap_free (void *bitmap);
extern void
BBitmap_dimensions (void *bitmap, int *left, int *top,
int *right, int *bottom, int32_t *bytes_per_row,
int *mono_p);
extern void *
BApplication_setup (void);
extern void *
BWindow_new (void *view);
extern void
BWindow_quit (void *window);
extern void
BWindow_set_offset (void *window, int x, int y);
extern void
BWindow_iconify (void *window);
extern void
BWindow_set_visible (void *window, int visible_p);
extern void
BFont_close (void *font);
extern void
BFont_dat (void *font, int *px_size, int *min_width, int *max_width,
int *avg_width, int *height, int *space_width, int *ascent,
int *descent, int *underline_position, int *underline_thickness);
extern int
BFont_have_char_p (void *font, int32_t chr);
extern int
BFont_have_char_block (void *font, int32_t beg, int32_t end);
extern void
BFont_char_bounds (void *font, const char *mb_str, int *advance,
int *lb, int *rb);
extern void
BFont_nchar_bounds (void *font, const char *mb_str, int *advance,
int *lb, int *rb, int32_t n);
extern void
BWindow_retitle (void *window, const char *title);
extern void
BWindow_resize (void *window, int width, int height);
extern void
BWindow_activate (void *window);
extern void
BView_StartClip (void *view);
extern void
BView_EndClip (void *view);
extern void
BView_SetHighColor (void *view, uint32_t color);
extern void
BView_SetHighColorForVisibleBell (void *view, uint32_t color);
extern void
BView_FillRectangleForVisibleBell (void *view, int x, int y, int width,
int height);
extern void
BView_SetLowColor (void *view, uint32_t color);
extern void
BView_SetPenSize (void *view, int u);
extern void
BView_SetFont (void *view, void *font);
extern void
BView_MovePenTo (void *view, int x, int y);
extern void
BView_DrawString (void *view, const char *chr, ptrdiff_t len);
extern void
BView_DrawChar (void *view, char chr);
extern void
BView_FillRectangle (void *view, int x, int y, int width, int height);
extern void
BView_FillRectangleAbs (void *view, int x, int y, int x1, int y1);
extern void
BView_FillTriangle (void *view, int x1, int y1,
int x2, int y2, int x3, int y3);
extern void
BView_StrokeRectangle (void *view, int x, int y, int width, int height);
extern void
BView_SetViewColor (void *view, uint32_t color);
extern void
BView_ClipToRect (void *view, int x, int y, int width, int height);
extern void
BView_ClipToInverseRect (void *view, int x, int y, int width, int height);
extern void
BView_StrokeLine (void *view, int sx, int sy, int tx, int ty);
extern void
BView_CopyBits (void *view, int x, int y, int width, int height,
int tox, int toy, int towidth, int toheight);
extern void
BView_DrawBitmap (void *view, void *bitmap, int x, int y,
int width, int height, int vx, int vy, int vwidth,
int vheight);
extern void
BView_DrawBitmapWithEraseOp (void *view, void *bitmap, int x,
int y, int width, int height);
extern void
BView_DrawMask (void *src, void *view,
int x, int y, int width, int height,
int vx, int vy, int vwidth, int vheight,
uint32_t color);
extern void *
BBitmap_transform_bitmap (void *bitmap, void *mask, uint32_t m_color,
double rot, int desw, int desh);
extern void
BScreen_px_dim (int *width, int *height);
extern void
BView_resize_to (void *view, int width, int height);
/* Functions for creating and freeing cursors. */
extern void *
BCursor_create_default (void);
extern void *
BCursor_from_id (enum haiku_cursor cursor);
extern void *
BCursor_create_modeline (void);
extern void *
BCursor_create_i_beam (void);
extern void *
BCursor_create_progress_cursor (void);
extern void *
BCursor_create_grab (void);
extern void
BCursor_delete (void *cursor);
extern void
BView_set_view_cursor (void *view, void *cursor);
extern void
BWindow_Flush (void *window);
extern void
BMapKey (uint32_t kc, int *non_ascii_p, unsigned *code);
extern void *
BScrollBar_make_for_view (void *view, int horizontal_p,
int x, int y, int x1, int y1,
void *scroll_bar_ptr);
extern void
BScrollBar_delete (void *sb);
extern void
BView_move_frame (void *view, int x, int y, int x1, int y1);
extern void
BView_scroll_bar_update (void *sb, int portion, int whole, int position);
extern int
BScrollBar_default_size (int horizontal_p);
extern void
BView_invalidate (void *view);
extern void
BView_draw_lock (void *view);
extern void
BView_draw_unlock (void *view);
extern void
BWindow_center_on_screen (void *window);
extern void
BView_mouse_moved (void *view, int x, int y, uint32_t transit);
extern void
BView_mouse_down (void *view, int x, int y);
extern void
BView_mouse_up (void *view, int x, int y);
extern void
BBitmap_import_mono_bits (void *bitmap, void *bits, int wd, int h);
extern void
haiku_font_pattern_free (struct haiku_font_pattern *pt);
extern struct haiku_font_pattern *
BFont_find (struct haiku_font_pattern *pt);
extern int
BFont_open_pattern (struct haiku_font_pattern *pat, void **font, float size);
extern void
BFont_populate_fixed_family (struct haiku_font_pattern *ptn);
extern void
BFont_populate_plain_family (struct haiku_font_pattern *ptn);
extern void
BView_publish_scroll_bar (void *view, int x, int y, int width, int height);
extern void
BView_forget_scroll_bar (void *view, int x, int y, int width, int height);
extern void
BView_get_mouse (void *view, int *x, int *y);
extern void
BView_convert_to_screen (void *view, int *x, int *y);
extern void
BView_convert_from_screen (void *view, int *x, int *y);
extern void
BWindow_change_decoration (void *window, int decorate_p);
extern void
BWindow_set_tooltip_decoration (void *window);
extern void
BWindow_set_avoid_focus (void *window, int avoid_focus_p);
extern void
BView_emacs_delete (void *view);
extern uint32_t
haiku_current_workspace (void);
extern uint32_t
BWindow_workspaces (void *window);
extern void *
BPopUpMenu_new (const char *name);
extern void
BMenu_add_item (void *menu, const char *label, void *ptr, bool enabled_p,
bool marked_p, bool mbar_p, void *mbw_ptr, const char *key,
const char *help);
extern void
BMenu_add_separator (void *menu);
extern void *
BMenu_new_submenu (void *menu, const char *label, bool enabled_p);
extern void *
BMenu_new_menu_bar_submenu (void *menu, const char *label);
extern int
BMenu_count_items (void *menu);
extern void *
BMenu_item_at (void *menu, int idx);
extern void *
BMenu_run (void *menu, int x, int y);
extern void
BPopUpMenu_delete (void *menu);
extern void *
BMenuBar_new (void *view);
extern void
BMenu_delete_all (void *menu);
extern void
BMenuBar_delete (void *menubar);
extern void
BMenu_item_set_label (void *item, const char *label);
extern void *
BMenu_item_get_menu (void *item);
extern void
BMenu_delete_from (void *menu, int start, int count);
extern void
haiku_ring_bell (void);
extern void *
BAlert_new (const char *text, enum haiku_alert_type type);
extern void *
BAlert_add_button (void *alert, const char *text);
extern int32_t
BAlert_go (void *alert);
extern void
BButton_set_enabled (void *button, int enabled_p);
extern void
BView_set_tooltip (void *view, const char *tooltip);
extern void
BAlert_delete (void *alert);
extern void
BScreen_res (double *rrsx, double *rrsy);
extern void
EmacsWindow_parent_to (void *window, void *other_window);
extern void
EmacsWindow_unparent (void *window);
extern int
BFont_string_width (void *font, const char *utf8);
extern void
be_get_version_string (char *version, int len);
extern int
be_get_display_planes (void);
extern int
be_get_display_color_cells (void);
extern void
be_warp_pointer (int x, int y);
extern void
EmacsWindow_move_weak_child (void *window, void *child, int xoff, int yoff);
extern void
EmacsView_set_up_double_buffering (void *vw);
extern void
EmacsView_disable_double_buffering (void *vw);
extern void
EmacsView_flip_and_blit (void *vw);
extern int
EmacsView_double_buffered_p (void *vw);
extern char *
be_popup_file_dialog (int open_p, const char *default_dir, int must_match_p,
int dir_only_p, void *window, const char *save_text,
const char *prompt,
void (*block_input_function) (void),
void (*unblock_input_function) (void));
extern void
record_c_unwind_protect_from_cxx (void (*) (void *), void *);
extern ptrdiff_t
c_specpdl_idx_from_cxx (void);
extern void
c_unbind_to_nil_from_cxx (ptrdiff_t idx);
extern void
EmacsView_do_visible_bell (void *view, uint32_t color);
extern void
BWindow_zoom (void *window);
extern void
EmacsWindow_make_fullscreen (void *window, int fullscreen_p);
extern void
EmacsWindow_unzoom (void *window);
#ifdef HAVE_NATIVE_IMAGE_API
extern int
be_can_translate_type_to_bitmap_p (const char *mime);
extern void *
be_translate_bitmap_from_file_name (const char *filename);
extern void *
be_translate_bitmap_from_memory (const void *buf, size_t bytes);
#endif
extern void
BMenuBar_start_tracking (void *mbar);
extern size_t
BBitmap_bytes_length (void *bitmap);
extern void
BView_show_tooltip (void *view);
#ifdef USE_BE_CAIRO
extern cairo_surface_t *
EmacsView_cairo_surface (void *view);
extern void
BView_cr_dump_clipping (void *view, cairo_t *ctx);
extern void
EmacsWindow_begin_cr_critical_section (void *window);
extern void
EmacsWindow_end_cr_critical_section (void *window);
#endif
extern void
BView_set_and_show_sticky_tooltip (void *view, const char *tooltip,
int x, int y);
extern void
BMenu_add_title (void *menu, const char *text);
extern int
be_plain_font_height (void);
extern int
be_string_width_with_plain_font (const char *str);
extern int
be_get_display_screens (void);
extern void
BWindow_set_min_size (void *window, int width, int height);
extern void
BWindow_set_size_alignment (void *window, int align_width, int align_height);
#ifdef __cplusplus
extern void *
find_appropriate_view_for_draw (void *vw);
}
extern _Noreturn void
gui_abort (const char *msg);
#endif /* _cplusplus */
/* Borrowed from X.Org keysymdef.h */
#define XK_BackSpace 0xff08 /* Back space, back char */
#define XK_Tab 0xff09
#define XK_Linefeed 0xff0a /* Linefeed, LF */
#define XK_Clear 0xff0b
#define XK_Return 0xff0d /* Return, enter */
#define XK_Pause 0xff13 /* Pause, hold */
#define XK_Scroll_Lock 0xff14
#define XK_Sys_Req 0xff15
#define XK_Escape 0xff1b
#define XK_Delete 0xffff /* Delete, rubout */
#define XK_Home 0xff50
#define XK_Left 0xff51 /* Move left, left arrow */
#define XK_Up 0xff52 /* Move up, up arrow */
#define XK_Right 0xff53 /* Move right, right arrow */
#define XK_Down 0xff54 /* Move down, down arrow */
#define XK_Prior 0xff55 /* Prior, previous */
#define XK_Page_Up 0xff55
#define XK_Next 0xff56 /* Next */
#define XK_Page_Down 0xff56
#define XK_End 0xff57 /* EOL */
#define XK_Begin 0xff58 /* BOL */
#define XK_Select 0xff60 /* Select, mark */
#define XK_Print 0xff61
#define XK_Execute 0xff62 /* Execute, run, do */
#define XK_Insert 0xff63 /* Insert, insert here */
#define XK_Undo 0xff65
#define XK_Redo 0xff66 /* Redo, again */
#define XK_Menu 0xff67
#define XK_Find 0xff68 /* Find, search */
#define XK_Cancel 0xff69 /* Cancel, stop, abort, exit */
#define XK_Help 0xff6a /* Help */
#define XK_Break 0xff6b
#define XK_Mode_switch 0xff7e /* Character set switch */
#define XK_script_switch 0xff7e /* Alias for mode_switch */
#define XK_Num_Lock 0xff7f
#define XK_F1 0xffbe
#endif /* _HAIKU_SUPPORT_H_ */

2448
src/haikufns.c Normal file

File diff suppressed because it is too large Load diff

1072
src/haikufont.c Normal file

File diff suppressed because it is too large Load diff

106
src/haikugui.h Normal file
View file

@ -0,0 +1,106 @@
/* Haiku window system support
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _HAIKU_GUI_H_
#define _HAIKU_GUI_H_
#ifdef _cplusplus
extern "C"
{
#endif
typedef struct haiku_char_struct
{
int rbearing;
int lbearing;
int width;
int ascent;
int descent;
} XCharStruct;
struct haiku_rect
{
int x, y;
int width, height;
};
typedef void *haiku;
typedef haiku Emacs_Pixmap;
typedef haiku Emacs_Window;
typedef haiku Emacs_Cursor;
typedef haiku Drawable;
#define NativeRectangle struct haiku_rect
#define CONVERT_TO_EMACS_RECT(xr, nr) \
((xr).x = (nr).x, \
(xr).y = (nr).y, \
(xr).width = (nr).width, \
(xr).height = (nr).height)
#define CONVERT_FROM_EMACS_RECT(xr, nr) \
((nr).x = (xr).x, \
(nr).y = (xr).y, \
(nr).width = (xr).width, \
(nr).height = (xr).height)
#define STORE_NATIVE_RECT(nr, px, py, pwidth, pheight) \
((nr).x = (px), \
(nr).y = (py), \
(nr).width = (pwidth), \
(nr).height = (pheight))
#define ForgetGravity 0
#define NorthWestGravity 1
#define NorthGravity 2
#define NorthEastGravity 3
#define WestGravity 4
#define CenterGravity 5
#define EastGravity 6
#define SouthWestGravity 7
#define SouthGravity 8
#define SouthEastGravity 9
#define StaticGravity 10
#define NoValue 0x0000
#define XValue 0x0001
#define YValue 0x0002
#define WidthValue 0x0004
#define HeightValue 0x0008
#define AllValues 0x000F
#define XNegative 0x0010
#define YNegative 0x0020
#define USPosition (1L << 0) /* user specified x, y */
#define USSize (1L << 1) /* user specified width, height */
#define PPosition (1L << 2) /* program specified position */
#define PSize (1L << 3) /* program specified size */
#define PMinSize (1L << 4) /* program specified minimum size */
#define PMaxSize (1L << 5) /* program specified maximum size */
#define PResizeInc (1L << 6) /* program specified resize increments */
#define PAspect (1L << 7) /* program specified min, max aspect ratios */
#define PBaseSize (1L << 8) /* program specified base for incrementing */
#define PWinGravity (1L << 9) /* program specified window gravity */
typedef haiku Window;
typedef int Display;
#ifdef _cplusplus
};
#endif
#endif /* _HAIKU_GUI_H_ */

109
src/haikuimage.c Normal file
View file

@ -0,0 +1,109 @@
/* Haiku window system support.
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include "lisp.h"
#include "dispextern.h"
#include "haikuterm.h"
#include "coding.h"
#include "haiku_support.h"
bool
haiku_can_use_native_image_api (Lisp_Object type)
{
const char *mime_type = NULL;
if (EQ (type, Qnative_image))
return 1;
#ifdef HAVE_RSVG
if (EQ (type, Qsvg))
return 0;
#endif
if (EQ (type, Qjpeg))
mime_type = "image/jpeg";
else if (EQ (type, Qpng))
mime_type = "image/png";
else if (EQ (type, Qgif))
mime_type = "image/gif";
else if (EQ (type, Qtiff))
mime_type = "image/tiff";
else if (EQ (type, Qbmp))
mime_type = "image/bmp";
else if (EQ (type, Qsvg))
mime_type = "image/svg";
else if (EQ (type, Qpbm))
mime_type = "image/pbm";
if (!mime_type)
return 0;
return be_can_translate_type_to_bitmap_p (mime_type);
}
extern int
haiku_load_image (struct frame *f, struct image *img,
Lisp_Object spec_file, Lisp_Object spec_data)
{
eassert (valid_image_p (img->spec));
void *pixmap = NULL;
if (STRINGP (spec_file))
{
pixmap = be_translate_bitmap_from_file_name
(SSDATA (ENCODE_UTF_8 (spec_file)));
}
else if (STRINGP (spec_data))
{
pixmap = be_translate_bitmap_from_memory
(SSDATA (spec_data), SBYTES (spec_data));
}
void *conv = NULL;
if (!pixmap || !BBitmap_convert (pixmap, &conv))
{
add_to_log ("Unable to load image %s", img->spec);
return 0;
}
if (conv)
{
BBitmap_free (pixmap);
pixmap = conv;
}
int left, top, right, bottom, stride, mono_p;
BBitmap_dimensions (pixmap, &left, &top, &right, &bottom, &stride, &mono_p);
img->width = (1 + right - left);
img->height = (1 + bottom - top);
img->pixmap = pixmap;
return 1;
}
void
syms_of_haikuimage (void)
{
DEFSYM (Qbmp, "bmp");
}

656
src/haikumenu.c Normal file
View file

@ -0,0 +1,656 @@
/* Haiku window system support
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include "lisp.h"
#include "frame.h"
#include "keyboard.h"
#include "menu.h"
#include "buffer.h"
#include "blockinput.h"
#include "haikuterm.h"
#include "haiku_support.h"
static Lisp_Object *volatile menu_item_selection;
int popup_activated_p = 0;
struct submenu_stack_cell
{
void *parent_menu;
void *pane;
};
static void
digest_menu_items (void *first_menu, int start, int menu_items_used,
int mbar_p)
{
void **menus, **panes;
ssize_t menu_len = (menu_items_used + 1 - start) * sizeof *menus;
ssize_t pane_len = (menu_items_used + 1 - start) * sizeof *panes;
menus = alloca (menu_len);
panes = alloca (pane_len);
int i = start, menu_depth = 0;
memset (menus, 0, menu_len);
memset (panes, 0, pane_len);
void *menu = first_menu;
menus[0] = first_menu;
void *window = NULL;
if (FRAMEP (Vmenu_updating_frame) &&
FRAME_LIVE_P (XFRAME (Vmenu_updating_frame)) &&
FRAME_HAIKU_P (XFRAME (Vmenu_updating_frame)))
window = FRAME_HAIKU_WINDOW (XFRAME (Vmenu_updating_frame));
while (i < menu_items_used)
{
if (NILP (AREF (menu_items, i)))
{
menus[++menu_depth] = menu;
i++;
}
else if (EQ (AREF (menu_items, i), Qlambda))
{
panes[menu_depth] = NULL;
menu = panes[--menu_depth] ? panes[menu_depth] : menus[menu_depth];
i++;
}
else if (EQ (AREF (menu_items, i), Qquote))
i += 1;
else if (EQ (AREF (menu_items, i), Qt))
{
Lisp_Object pane_name, prefix;
const char *pane_string;
if (menu_items_n_panes == 1)
{
i += MENU_ITEMS_PANE_LENGTH;
continue;
}
pane_name = AREF (menu_items, i + MENU_ITEMS_PANE_NAME);
prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
if (STRINGP (pane_name) && STRING_MULTIBYTE (pane_name))
{
pane_name = ENCODE_UTF_8 (pane_name);
ASET (menu_items, i + MENU_ITEMS_PANE_NAME, pane_name);
}
pane_string = (NILP (pane_name)
? "" : SSDATA (pane_name));
if (!NILP (prefix))
pane_string++;
if (strcmp (pane_string, ""))
{
panes[menu_depth] =
menu = BMenu_new_submenu (menus[menu_depth], pane_string, 1);
}
i += MENU_ITEMS_PANE_LENGTH;
}
else
{
Lisp_Object item_name, enable, descrip, def, selected, help;
item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
def = AREF (menu_items, i + MENU_ITEMS_ITEM_DEFINITION);
selected = AREF (menu_items, i + MENU_ITEMS_ITEM_SELECTED);
help = AREF (menu_items, i + MENU_ITEMS_ITEM_HELP);
if (STRINGP (item_name) && STRING_MULTIBYTE (item_name))
{
item_name = ENCODE_UTF_8 (item_name);
ASET (menu_items, i + MENU_ITEMS_ITEM_NAME, item_name);
}
if (STRINGP (descrip) && STRING_MULTIBYTE (descrip))
{
descrip = ENCODE_UTF_8 (descrip);
ASET (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY, descrip);
}
if (STRINGP (help) && STRING_MULTIBYTE (help))
{
help = ENCODE_UTF_8 (help);
ASET (menu_items, i + MENU_ITEMS_ITEM_HELP, help);
}
if (i + MENU_ITEMS_ITEM_LENGTH < menu_items_used &&
NILP (AREF (menu_items, i + MENU_ITEMS_ITEM_LENGTH)))
menu = BMenu_new_submenu (menu, SSDATA (item_name), !NILP (enable));
else if (NILP (def) && menu_separator_name_p (SSDATA (item_name)))
BMenu_add_separator (menu);
else if (!mbar_p)
BMenu_add_item (menu, SSDATA (item_name),
!NILP (def) ? aref_addr (menu_items, i) : NULL,
!NILP (enable), !NILP (selected), 0, window,
!NILP (descrip) ? SSDATA (descrip) : NULL,
STRINGP (help) ? SSDATA (help) : NULL);
else
BMenu_add_item (menu, SSDATA (item_name),
!NILP (def) ? (void *) (intptr_t) i : NULL,
!NILP (enable), !NILP (selected), 1, window,
!NILP (descrip) ? SSDATA (descrip) : NULL,
STRINGP (help) ? SSDATA (help) : NULL);
i += MENU_ITEMS_ITEM_LENGTH;
}
}
}
static Lisp_Object
haiku_dialog_show (struct frame *f, Lisp_Object title,
Lisp_Object header, const char **error_name)
{
int i, nb_buttons = 0;
*error_name = NULL;
if (menu_items_n_panes > 1)
{
*error_name = "Multiple panes in dialog box";
return Qnil;
}
Lisp_Object pane_name = AREF (menu_items, MENU_ITEMS_PANE_NAME);
i = MENU_ITEMS_PANE_LENGTH;
if (STRING_MULTIBYTE (pane_name))
pane_name = ENCODE_UTF_8 (pane_name);
block_input ();
void *alert = BAlert_new (SSDATA (pane_name), NILP (header) ? HAIKU_INFO_ALERT :
HAIKU_IDEA_ALERT);
Lisp_Object vals[10];
while (i < menu_items_used)
{
Lisp_Object item_name, enable, descrip, value;
item_name = AREF (menu_items, i + MENU_ITEMS_ITEM_NAME);
enable = AREF (menu_items, i + MENU_ITEMS_ITEM_ENABLE);
descrip = AREF (menu_items, i + MENU_ITEMS_ITEM_EQUIV_KEY);
value = AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
if (NILP (item_name))
{
BAlert_delete (alert);
*error_name = "Submenu in dialog items";
unblock_input ();
return Qnil;
}
if (EQ (item_name, Qquote))
{
i++;
}
if (nb_buttons >= 9)
{
BAlert_delete (alert);
*error_name = "Too many dialog items";
unblock_input ();
return Qnil;
}
if (STRING_MULTIBYTE (item_name))
item_name = ENCODE_UTF_8 (item_name);
if (!NILP (descrip) && STRING_MULTIBYTE (descrip))
descrip = ENCODE_UTF_8 (descrip);
void *button = BAlert_add_button (alert, SSDATA (item_name));
BButton_set_enabled (button, !NILP (enable));
if (!NILP (descrip))
BView_set_tooltip (button, SSDATA (descrip));
vals[nb_buttons] = value;
++nb_buttons;
i += MENU_ITEMS_ITEM_LENGTH;
}
int32_t val = BAlert_go (alert);
unblock_input ();
if (val < 0)
quit ();
else
return vals[val];
return Qnil;
}
Lisp_Object
haiku_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents)
{
Lisp_Object title;
const char *error_name = NULL;
Lisp_Object selection;
ptrdiff_t specpdl_count = SPECPDL_INDEX ();
check_window_system (f);
/* Decode the dialog items from what was specified. */
title = Fcar (contents);
CHECK_STRING (title);
record_unwind_protect_void (unuse_menu_items);
if (NILP (Fcar (Fcdr (contents))))
/* No buttons specified, add an "Ok" button so users can pop down
the dialog. Also, the lesstif/motif version crashes if there are
no buttons. */
contents = list2 (title, Fcons (build_string ("Ok"), Qt));
list_of_panes (list1 (contents));
/* Display them in a dialog box. */
block_input ();
selection = haiku_dialog_show (f, title, header, &error_name);
unblock_input ();
unbind_to (specpdl_count, Qnil);
discard_menu_items ();
if (error_name)
error ("%s", error_name);
return selection;
}
Lisp_Object
haiku_menu_show (struct frame *f, int x, int y, int menuflags,
Lisp_Object title, const char **error_name)
{
int i = 0, submenu_depth = 0;
void *view = FRAME_HAIKU_VIEW (f);
void *menu;
Lisp_Object *subprefix_stack =
alloca (menu_items_used * sizeof (Lisp_Object));
eassert (FRAME_HAIKU_P (f));
*error_name = NULL;
if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
{
*error_name = "Empty menu";
return Qnil;
}
block_input ();
if (STRINGP (title) && STRING_MULTIBYTE (title))
title = ENCODE_UTF_8 (title);
menu = BPopUpMenu_new (STRINGP (title) ? SSDATA (title) : NULL);
if (STRINGP (title))
{
BMenu_add_title (menu, SSDATA (title));
BMenu_add_separator (menu);
}
digest_menu_items (menu, 0, menu_items_used, 0);
BView_convert_to_screen (view, &x, &y);
unblock_input ();
menu_item_selection = BMenu_run (menu, x, y);
FRAME_DISPLAY_INFO (f)->grabbed = 0;
if (menu_item_selection)
{
Lisp_Object prefix, entry;
prefix = entry = Qnil;
i = 0;
while (i < menu_items_used)
{
if (NILP (AREF (menu_items, i)))
{
subprefix_stack[submenu_depth++] = prefix;
prefix = entry;
i++;
}
else if (EQ (AREF (menu_items, i), Qlambda))
{
prefix = subprefix_stack[--submenu_depth];
i++;
}
else if (EQ (AREF (menu_items, i), Qt))
{
prefix
= AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
i += MENU_ITEMS_PANE_LENGTH;
}
/* Ignore a nil in the item list.
It's meaningful only for dialog boxes. */
else if (EQ (AREF (menu_items, i), Qquote))
i += 1;
else
{
entry
= AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
if (menu_item_selection == aref_addr (menu_items, i))
{
if (menuflags & MENU_KEYMAPS)
{
int j;
entry = list1 (entry);
if (!NILP (prefix))
entry = Fcons (prefix, entry);
for (j = submenu_depth - 1; j >= 0; j--)
if (!NILP (subprefix_stack[j]))
entry = Fcons (subprefix_stack[j], entry);
}
BPopUpMenu_delete (menu);
return entry;
}
i += MENU_ITEMS_ITEM_LENGTH;
}
}
}
else if (!(menuflags & MENU_FOR_CLICK))
{
BPopUpMenu_delete (menu);
quit ();
}
BPopUpMenu_delete (menu);
return Qnil;
}
void
free_frame_menubar (struct frame *f)
{
FRAME_MENU_BAR_LINES (f) = 0;
FRAME_MENU_BAR_HEIGHT (f) = 0;
FRAME_EXTERNAL_MENU_BAR (f) = 0;
block_input ();
void *mbar = FRAME_HAIKU_MENU_BAR (f);
if (mbar)
BMenuBar_delete (mbar);
if (FRAME_OUTPUT_DATA (f)->menu_bar_open_p)
--popup_activated_p;
FRAME_OUTPUT_DATA (f)->menu_bar_open_p = 0;
unblock_input ();
adjust_frame_size (f, -1, -1, 2, false, Qmenu_bar_lines);
}
void
initialize_frame_menubar (struct frame *f)
{
/* This function is called before the first chance to redisplay
the frame. It has to be, so the frame will have the right size. */
fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
set_frame_menubar (f, true);
}
void
set_frame_menubar (struct frame *f, bool deep_p)
{
void *mbar = FRAME_HAIKU_MENU_BAR (f);
void *view = FRAME_HAIKU_VIEW (f);
int first_time_p = 0;
if (!mbar)
{
mbar = FRAME_HAIKU_MENU_BAR (f) = BMenuBar_new (view);
first_time_p = 1;
}
Lisp_Object items;
struct buffer *prev = current_buffer;
Lisp_Object buffer;
ptrdiff_t specpdl_count = SPECPDL_INDEX ();
int previous_menu_items_used = f->menu_bar_items_used;
Lisp_Object *previous_items
= alloca (previous_menu_items_used * sizeof *previous_items);
XSETFRAME (Vmenu_updating_frame, f);
if (!deep_p)
{
FRAME_OUTPUT_DATA (f)->menu_up_to_date_p = 0;
items = FRAME_MENU_BAR_ITEMS (f);
Lisp_Object string;
block_input ();
int count = BMenu_count_items (mbar);
int i;
for (i = 0; i < ASIZE (items); i += 4)
{
string = AREF (items, i + 1);
if (!STRINGP (string))
break;
if (STRING_MULTIBYTE (string))
string = ENCODE_UTF_8 (string);
if (i / 4 < count)
{
void *it = BMenu_item_at (mbar, i / 4);
BMenu_item_set_label (it, SSDATA (string));
}
else
BMenu_new_menu_bar_submenu (mbar, SSDATA (string));
}
if (i / 4 < count)
BMenu_delete_from (mbar, i / 4, count - i / 4 + 1);
unblock_input ();
f->menu_bar_items_used = 0;
}
else
{
/* If we are making a new widget, its contents are empty,
do always reinitialize them. */
if (first_time_p)
previous_menu_items_used = 0;
buffer = XWINDOW (FRAME_SELECTED_WINDOW (f))->contents;
specbind (Qinhibit_quit, Qt);
/* Don't let the debugger step into this code
because it is not reentrant. */
specbind (Qdebug_on_next_call, Qnil);
record_unwind_save_match_data ();
if (NILP (Voverriding_local_map_menu_flag))
{
specbind (Qoverriding_terminal_local_map, Qnil);
specbind (Qoverriding_local_map, Qnil);
}
set_buffer_internal_1 (XBUFFER (buffer));
/* Run the Lucid hook. */
safe_run_hooks (Qactivate_menubar_hook);
/* If it has changed current-menubar from previous value,
really recompute the menubar from the value. */
if (! NILP (Vlucid_menu_bar_dirty_flag))
call0 (Qrecompute_lucid_menubar);
safe_run_hooks (Qmenu_bar_update_hook);
fset_menu_bar_items (f, menu_bar_items (FRAME_MENU_BAR_ITEMS (f)));
items = FRAME_MENU_BAR_ITEMS (f);
/* Save the frame's previous menu bar contents data. */
if (previous_menu_items_used)
memcpy (previous_items, xvector_contents (f->menu_bar_vector),
previous_menu_items_used * word_size);
/* Fill in menu_items with the current menu bar contents.
This can evaluate Lisp code. */
save_menu_items ();
menu_items = f->menu_bar_vector;
menu_items_allocated = VECTORP (menu_items) ? ASIZE (menu_items) : 0;
init_menu_items ();
int i;
int count = BMenu_count_items (mbar);
int subitems = ASIZE (items) / 4;
int *submenu_start, *submenu_end, *submenu_n_panes;
Lisp_Object *submenu_names;
submenu_start = alloca ((subitems + 1) * sizeof *submenu_start);
submenu_end = alloca (subitems * sizeof *submenu_end);
submenu_n_panes = alloca (subitems * sizeof *submenu_n_panes);
submenu_names = alloca (subitems * sizeof (Lisp_Object));
for (i = 0; i < subitems; ++i)
{
Lisp_Object key, string, maps;
key = AREF (items, i * 4);
string = AREF (items, i * 4 + 1);
maps = AREF (items, i * 4 + 2);
if (NILP (string))
break;
if (STRINGP (string) && STRING_MULTIBYTE (string))
string = ENCODE_UTF_8 (string);
submenu_start[i] = menu_items_used;
menu_items_n_panes = 0;
parse_single_submenu (key, string, maps);
submenu_n_panes[i] = menu_items_n_panes;
submenu_end[i] = menu_items_used;
submenu_names[i] = string;
}
finish_menu_items ();
submenu_start[i] = -1;
block_input ();
for (i = 0; submenu_start[i] >= 0; ++i)
{
void *mn = NULL;
if (i < count)
mn = BMenu_item_get_menu (BMenu_item_at (mbar, i));
if (mn)
BMenu_delete_all (mn);
else
mn = BMenu_new_menu_bar_submenu (mbar, SSDATA (submenu_names[i]));
menu_items_n_panes = submenu_n_panes[i];
digest_menu_items (mn, submenu_start[i], submenu_end[i], 1);
}
unblock_input ();
set_buffer_internal_1 (prev);
FRAME_OUTPUT_DATA (f)->menu_up_to_date_p = 1;
fset_menu_bar_vector (f, menu_items);
f->menu_bar_items_used = menu_items_used;
}
unbind_to (specpdl_count, Qnil);
}
void
run_menu_bar_help_event (struct frame *f, int mb_idx)
{
Lisp_Object frame;
Lisp_Object vec;
Lisp_Object help;
block_input ();
if (!FRAME_OUTPUT_DATA (f)->menu_up_to_date_p)
{
unblock_input ();
return;
}
XSETFRAME (frame, f);
if (mb_idx < 0)
{
kbd_buffer_store_help_event (frame, Qnil);
unblock_input ();
return;
}
vec = f->menu_bar_vector;
if (mb_idx >= ASIZE (vec))
emacs_abort ();
help = AREF (vec, mb_idx + MENU_ITEMS_ITEM_HELP);
if (STRINGP (help) || NILP (help))
kbd_buffer_store_help_event (frame, help);
unblock_input ();
}
DEFUN ("menu-or-popup-active-p", Fmenu_or_popup_active_p, Smenu_or_popup_active_p,
0, 0, 0, doc: /* SKIP: real doc in xmenu.c. */)
(void)
{
return popup_activated_p ? Qt : Qnil;
}
DEFUN ("haiku-menu-bar-open", Fhaiku_menu_bar_open, Shaiku_menu_bar_open, 0, 1, "i",
doc: /* Show the menu bar in FRAME.
Move the mouse pointer onto the first element of FRAME's menu bar, and
cause it to be opened. If FRAME is nil or not given, use the selected
frame. If FRAME has no menu bar, a pop-up is displayed at the position
of the last non-menu event instead. */)
(Lisp_Object frame)
{
struct frame *f = decode_window_system_frame (frame);
if (FRAME_EXTERNAL_MENU_BAR (f))
{
if (!FRAME_OUTPUT_DATA (f)->menu_up_to_date_p)
set_frame_menubar (f, 1);
}
else
{
return call2 (Qpopup_menu, call0 (Qmouse_menu_bar_map),
last_nonmenu_event);
}
block_input ();
BMenuBar_start_tracking (FRAME_HAIKU_MENU_BAR (f));
unblock_input ();
return Qnil;
}
void
syms_of_haikumenu (void)
{
DEFSYM (Qdebug_on_next_call, "debug-on-next-call");
DEFSYM (Qpopup_menu, "popup-menu");
DEFSYM (Qmouse_menu_bar_map, "mouse-menu-bar-map");
defsubr (&Smenu_or_popup_active_p);
defsubr (&Shaiku_menu_bar_open);
return;
}

134
src/haikuselect.c Normal file
View file

@ -0,0 +1,134 @@
/* Haiku window system selection support.
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include "lisp.h"
#include "blockinput.h"
#include "coding.h"
#include "haikuselect.h"
#include "haikuterm.h"
DEFUN ("haiku-selection-data", Fhaiku_selection_data, Shaiku_selection_data,
2, 2, 0,
doc: /* Retrieve content typed as NAME from the clipboard
CLIPBOARD. CLIPBOARD is the symbol `PRIMARY', `SECONDARY' or
`CLIPBOARD'. NAME is a MIME type denoting the type of the data to
fetch. */)
(Lisp_Object clipboard, Lisp_Object name)
{
CHECK_SYMBOL (clipboard);
CHECK_STRING (name);
char *dat;
ssize_t len;
block_input ();
if (EQ (clipboard, QPRIMARY))
dat = BClipboard_find_primary_selection_data (SSDATA (name), &len);
else if (EQ (clipboard, QSECONDARY))
dat = BClipboard_find_secondary_selection_data (SSDATA (name), &len);
else if (EQ (clipboard, QCLIPBOARD))
dat = BClipboard_find_system_data (SSDATA (name), &len);
else
{
unblock_input ();
signal_error ("Bad clipboard", clipboard);
}
unblock_input ();
if (!dat)
return Qnil;
Lisp_Object str = make_unibyte_string (dat, len);
Lisp_Object lispy_type = Qnil;
if (!strcmp (SSDATA (name), "text/utf-8") ||
!strcmp (SSDATA (name), "text/plain"))
{
if (string_ascii_p (str))
lispy_type = QSTRING;
else
lispy_type = QUTF8_STRING;
}
if (!NILP (lispy_type))
Fput_text_property (make_fixnum (0), make_fixnum (len),
Qforeign_selection, lispy_type, str);
block_input ();
BClipboard_free_data (dat);
unblock_input ();
return str;
}
DEFUN ("haiku-selection-put", Fhaiku_selection_put, Shaiku_selection_put,
3, 3, 0,
doc: /* Add or remove content from the clipboard CLIPBOARD.
CLIPBOARD is the symbol `PRIMARY', `SECONDARY' or `CLIPBOARD'. NAME
is a MIME type denoting the type of the data to add. DATA is the
string that will be placed in the clipboard, or nil if the content is
to be removed. If NAME is the string `text/utf-8' or the string
`text/plain', encode it as UTF-8 before storing it into the
clipboard. */)
(Lisp_Object clipboard, Lisp_Object name, Lisp_Object data)
{
CHECK_SYMBOL (clipboard);
CHECK_STRING (name);
if (!NILP (data))
CHECK_STRING (data);
block_input ();
/* It seems that Haiku applications counter-intuitively expect
UTF-8 data in both text/utf-8 and text/plain. */
if (!NILP (data) && STRING_MULTIBYTE (data) &&
(!strcmp (SSDATA (name), "text/utf-8") ||
!strcmp (SSDATA (name), "text/plain")))
data = ENCODE_UTF_8 (data);
char *dat = !NILP (data) ? SSDATA (data) : NULL;
ptrdiff_t len = !NILP (data) ? SBYTES (data) : 0;
if (EQ (clipboard, QPRIMARY))
BClipboard_set_primary_selection_data (SSDATA (name), dat, len);
else if (EQ (clipboard, QSECONDARY))
BClipboard_set_secondary_selection_data (SSDATA (name), dat, len);
else if (EQ (clipboard, QCLIPBOARD))
BClipboard_set_system_data (SSDATA (name), dat, len);
else
{
unblock_input ();
signal_error ("Bad clipboard", clipboard);
}
unblock_input ();
return Qnil;
}
void
syms_of_haikuselect (void)
{
DEFSYM (QSECONDARY, "SECONDARY");
DEFSYM (QCLIPBOARD, "CLIPBOARD");
DEFSYM (QSTRING, "STRING");
DEFSYM (QUTF8_STRING, "UTF8_STRING");
DEFSYM (Qforeign_selection, "foreign-selection");
defsubr (&Shaiku_selection_data);
defsubr (&Shaiku_selection_put);
}

64
src/haikuselect.h Normal file
View file

@ -0,0 +1,64 @@
/* Haiku window system selection support. Hey Emacs, this is -*- C++ -*-
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _HAIKU_SELECT_H_
#define _HAIKU_SELECT_H_
#ifdef __cplusplus
#include <cstdio>
#endif
#ifdef __cplusplus
#include <stdio.h>
extern "C"
{
extern void init_haiku_select (void);
#endif
/* Whether or not the selection was recently changed. */
extern int selection_state_flag;
/* Find a string with the MIME type TYPE in the system clipboard. */
extern char *
BClipboard_find_system_data (const char *type, ssize_t *len);
/* Ditto, but for the primary selection and not clipboard. */
extern char *
BClipboard_find_primary_selection_data (const char *type, ssize_t *len);
/* Ditto, this time for the secondary selection. */
extern char *
BClipboard_find_secondary_selection_data (const char *type, ssize_t *len);
extern void
BClipboard_set_system_data (const char *type, const char *data, ssize_t len);
extern void
BClipboard_set_primary_selection_data (const char *type, const char *data,
ssize_t len);
extern void
BClipboard_set_secondary_selection_data (const char *type, const char *data,
ssize_t len);
/* Free the returned data. */
extern void BClipboard_free_data (void *ptr);
#ifdef __cplusplus
};
#endif
#endif /* _HAIKU_SELECT_H_ */

3608
src/haikuterm.c Normal file

File diff suppressed because it is too large Load diff

293
src/haikuterm.h Normal file
View file

@ -0,0 +1,293 @@
/* Haiku window system support
Copyright (C) 2021 Free Software Foundation, Inc.
This file is part of GNU Emacs.
GNU Emacs is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or (at
your option) any later version.
GNU Emacs is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#ifndef _HAIKU_TERM_H_
#define _HAIKU_TERM_H_
#include <pthread.h>
#ifdef USE_BE_CAIRO
#include <cairo.h>
#endif
#include "haikugui.h"
#include "frame.h"
#include "character.h"
#include "dispextern.h"
#include "font.h"
#define C_FRAME struct frame *
#define C_FONT struct font *
#define C_TERMINAL struct terminal *
#define HAVE_CHAR_CACHE_MAX 65535
extern int popup_activated_p;
extern void be_app_quit (void);
struct haikufont_info
{
struct font font;
haiku be_font;
struct font_metrics **metrics;
short metrics_nrows;
unsigned short **glyphs;
};
struct haiku_bitmap_record
{
haiku img;
char *file;
int refcount;
int height, width, depth;
};
struct haiku_display_info
{
/* Chain of all haiku_display_info structures. */
struct haiku_display_info *next;
C_TERMINAL terminal;
Lisp_Object name_list_element;
Lisp_Object color_map;
int n_fonts;
int smallest_char_width;
int smallest_font_height;
struct frame *focused_frame;
struct frame *focus_event_frame;
struct frame *last_mouse_glyph_frame;
struct haiku_bitmap_record *bitmaps;
ptrdiff_t bitmaps_size;
ptrdiff_t bitmaps_last;
int grabbed;
int n_planes;
int color_p;
Window root_window;
Lisp_Object rdb;
Emacs_Cursor vertical_scroll_bar_cursor;
Emacs_Cursor horizontal_scroll_bar_cursor;
Mouse_HLInfo mouse_highlight;
C_FRAME highlight_frame;
C_FRAME last_mouse_frame;
C_FRAME last_mouse_motion_frame;
int last_mouse_motion_x;
int last_mouse_motion_y;
struct haiku_rect last_mouse_glyph;
void *last_mouse_scroll_bar;
haiku display;
double resx, resy;
};
struct haiku_output
{
Emacs_Cursor text_cursor;
Emacs_Cursor nontext_cursor;
Emacs_Cursor modeline_cursor;
Emacs_Cursor hand_cursor;
Emacs_Cursor hourglass_cursor;
Emacs_Cursor horizontal_drag_cursor;
Emacs_Cursor vertical_drag_cursor;
Emacs_Cursor left_edge_cursor;
Emacs_Cursor top_left_corner_cursor;
Emacs_Cursor top_edge_cursor;
Emacs_Cursor top_right_corner_cursor;
Emacs_Cursor right_edge_cursor;
Emacs_Cursor bottom_right_corner_cursor;
Emacs_Cursor bottom_edge_cursor;
Emacs_Cursor bottom_left_corner_cursor;
Emacs_Cursor no_cursor;
Emacs_Cursor current_cursor;
struct haiku_display_info *display_info;
int baseline_offset;
int fontset;
Emacs_Color cursor_color;
Window window_desc, parent_desc;
char explicit_parent;
int titlebar_height;
int toolbar_height;
haiku window;
haiku view;
haiku menubar;
int menu_up_to_date_p;
int zoomed_p;
int pending_zoom_x;
int pending_zoom_y;
int pending_zoom_width;
int pending_zoom_height;
int menu_bar_open_p;
C_FONT font;
int hourglass_p;
uint32_t cursor_fg;
bool dirty_p;
/* The pending position we're waiting for. */
int pending_top, pending_left;
};
struct x_output
{
/* Unused, makes term.c happy. */
};
extern struct haiku_display_info *x_display_list;
extern struct font_driver const haikufont_driver;
struct scroll_bar
{
/* These fields are shared by all vectors. */
union vectorlike_header header;
/* The window we're a scroll bar for. */
Lisp_Object window;
/* The next and previous in the chain of scroll bars in this frame. */
Lisp_Object next, prev;
/* Fields after 'prev' are not traced by the GC. */
/* The position and size of the scroll bar in pixels, relative to the
frame. */
int top, left, width, height;
/* The actual scrollbar. */
void *scroll_bar;
/* Non-nil if the scroll bar handle is currently being dragged by
the user. */
int dragging;
/* The update position if we are waiting for a scrollbar update, or
-1. */
int update;
/* The last known position of this scrollbar. */
int position;
/* The total number of units inside this scrollbar. */
int total;
/* True if the scroll bar is horizontal. */
bool horizontal;
};
#define XSCROLL_BAR(vec) ((struct scroll_bar *) XVECTOR (vec))
#define FRAME_DIRTY_P(f) (FRAME_OUTPUT_DATA (f)->dirty_p)
#define MAKE_FRAME_DIRTY(f) (FRAME_DIRTY_P (f) = 1)
#define FRAME_OUTPUT_DATA(f) ((f)->output_data.haiku)
#define FRAME_HAIKU_WINDOW(f) (FRAME_OUTPUT_DATA (f)->window)
#define FRAME_HAIKU_VIEW(f) ((MAKE_FRAME_DIRTY (f)), FRAME_OUTPUT_DATA (f)->view)
#define FRAME_HAIKU_MENU_BAR(f) (FRAME_OUTPUT_DATA (f)->menubar)
#define FRAME_DISPLAY_INFO(f) (FRAME_OUTPUT_DATA (f)->display_info)
#define FRAME_FONT(f) (FRAME_OUTPUT_DATA (f)->font)
#define FRAME_FONTSET(f) (FRAME_OUTPUT_DATA (f)->fontset)
#define FRAME_NATIVE_WINDOW(f) (FRAME_OUTPUT_DATA (f)->window)
#define FRAME_BASELINE_OFFSET(f) (FRAME_OUTPUT_DATA (f)->baseline_offset)
#define FRAME_CURSOR_COLOR(f) (FRAME_OUTPUT_DATA (f)->cursor_color)
#ifdef USE_BE_CAIRO
#define FRAME_CR_SURFACE(f) \
(FRAME_HAIKU_VIEW (f) ? EmacsView_cairo_surface (FRAME_HAIKU_VIEW (f)) : 0);
#endif
extern void syms_of_haikuterm (void);
extern void syms_of_haikufns (void);
extern void syms_of_haikumenu (void);
extern void syms_of_haikufont (void);
extern void syms_of_haikuselect (void);
extern void init_haiku_select (void);
extern void haiku_iconify_frame (struct frame *);
extern void haiku_visualize_frame (struct frame *);
extern void haiku_unvisualize_frame (struct frame *);
extern void haiku_set_offset (struct frame *, int, int, int);
extern void haiku_set_frame_visible_invisible (struct frame *, bool);
extern void haiku_free_frame_resources (struct frame *f);
extern void haiku_scroll_bar_remove (struct scroll_bar *bar);
extern void haiku_clear_under_internal_border (struct frame *f);
extern void haiku_set_name (struct frame *f, Lisp_Object name, bool explicit_p);
extern struct haiku_display_info *haiku_term_init (void);
extern void mark_haiku_display (void);
extern int haiku_get_color (const char *name, Emacs_Color *color);
extern void haiku_set_background_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval);
extern void haiku_set_cursor_color (struct frame *f, Lisp_Object arg, Lisp_Object oldval);
extern void haiku_set_cursor_type (struct frame *f, Lisp_Object arg, Lisp_Object oldval);
extern void haiku_set_internal_border_width (struct frame *f, Lisp_Object arg, Lisp_Object oldval);
extern void haiku_change_tab_bar_height (struct frame *f, int height);
extern void haiku_change_tool_bar_height (struct frame *f, int height);
extern void haiku_query_color (uint32_t col, Emacs_Color *color);
extern unsigned long haiku_get_pixel (haiku bitmap, int x, int y);
extern void haiku_put_pixel (haiku bitmap, int x, int y, unsigned long pixel);
extern Lisp_Object haiku_menu_show (struct frame *f, int x, int y, int menu_flags,
Lisp_Object title, const char **error_name);
extern Lisp_Object haiku_popup_dialog (struct frame *f, Lisp_Object header, Lisp_Object contents);
extern void initialize_frame_menubar (struct frame *f);
extern void run_menu_bar_help_event (struct frame *f, int mb_idx);
extern void put_xrm_resource (Lisp_Object name, Lisp_Object val);
#ifdef HAVE_NATIVE_IMAGE_API
extern bool haiku_can_use_native_image_api (Lisp_Object type);
extern int haiku_load_image (struct frame *f, struct image *img,
Lisp_Object spec_file, Lisp_Object spec_data);
extern void syms_of_haikuimage (void);
#endif
#ifdef USE_BE_CAIRO
extern cairo_t *
haiku_begin_cr_clip (struct frame *f, struct glyph_string *s);
extern void
haiku_end_cr_clip (cairo_t *cr);
#endif
#endif /* _HAIKU_TERM_H_ */

View file

@ -20,6 +20,7 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#include <config.h>
#include <fcntl.h>
#include <math.h>
#include <unistd.h>
/* Include this before including <setjmp.h> to work around bugs with
@ -135,6 +136,27 @@ typedef struct ns_bitmap_record Bitmap_Record;
# define COLOR_TABLE_SUPPORT 1
#endif
#ifdef HAVE_HAIKU
#include "haiku_support.h"
typedef struct haiku_bitmap_record Bitmap_Record;
#define GET_PIXEL(ximg, x, y) haiku_get_pixel (ximg, x, y)
#define PUT_PIXEL haiku_put_pixel
#define NO_PIXMAP 0
#define PIX_MASK_RETAIN 0
#define PIX_MASK_DRAW 1
#define RGB_TO_ULONG(r, g, b) (((r) << 16) | ((g) << 8) | (b))
#define RED_FROM_ULONG(color) (((color) >> 16) & 0xff)
#define GREEN_FROM_ULONG(color) (((color) >> 8) & 0xff)
#define BLUE_FROM_ULONG(color) ((color) & 0xff)
#define RED16_FROM_ULONG(color) (RED_FROM_ULONG (color) * 0x101)
#define GREEN16_FROM_ULONG(color) (GREEN_FROM_ULONG (color) * 0x101)
#define BLUE16_FROM_ULONG(color) (BLUE_FROM_ULONG (color) * 0x101)
#endif
static void image_disable_image (struct frame *, struct image *);
static void image_edge_detection (struct frame *, struct image *, Lisp_Object,
Lisp_Object);
@ -430,6 +452,11 @@ image_create_bitmap_from_data (struct frame *f, char *bits,
return -1;
#endif
#ifdef HAVE_HAIKU
void *bitmap = BBitmap_new (width, height, 1);
BBitmap_import_mono_bits (bitmap, bits, width, height);
#endif
id = image_allocate_bitmap_record (f);
#ifdef HAVE_NS
@ -437,6 +464,11 @@ image_create_bitmap_from_data (struct frame *f, char *bits,
dpyinfo->bitmaps[id - 1].depth = 1;
#endif
#ifdef HAVE_HAIKU
dpyinfo->bitmaps[id - 1].img = bitmap;
dpyinfo->bitmaps[id - 1].depth = 1;
#endif
dpyinfo->bitmaps[id - 1].file = NULL;
dpyinfo->bitmaps[id - 1].height = height;
dpyinfo->bitmaps[id - 1].width = width;
@ -465,7 +497,7 @@ image_create_bitmap_from_data (struct frame *f, char *bits,
ptrdiff_t
image_create_bitmap_from_file (struct frame *f, Lisp_Object file)
{
#ifdef HAVE_NTGUI
#if defined (HAVE_NTGUI) || defined (HAVE_HAIKU)
return -1; /* W32_TODO : bitmap support */
#else
Display_Info *dpyinfo = FRAME_DISPLAY_INFO (f);
@ -561,6 +593,10 @@ free_bitmap_record (Display_Info *dpyinfo, Bitmap_Record *bm)
ns_release_object (bm->img);
#endif
#ifdef HAVE_HAIKU
BBitmap_free (bm->img);
#endif
if (bm->file)
{
xfree (bm->file);
@ -1834,6 +1870,11 @@ image_size_in_bytes (struct image *img)
if (img->mask)
size += w32_image_size (img->mask);
#elif defined HAVE_HAIKU
if (img->pixmap)
size += BBitmap_bytes_length (img->pixmap);
if (img->mask)
size += BBitmap_bytes_length (img->mask);
#endif
return size;
@ -2173,6 +2214,7 @@ compute_image_size (size_t width, size_t height,
single step, but the maths for each element is much more complex
and performing the steps separately makes for more readable code. */
#ifndef HAVE_HAIKU
typedef double matrix3x3[3][3];
static void
@ -2187,6 +2229,7 @@ matrix3x3_mult (matrix3x3 a, matrix3x3 b, matrix3x3 result)
result[i][j] = sum;
}
}
#endif /* not HAVE_HAIKU */
static void
compute_image_rotation (struct image *img, double *rotation)
@ -2244,6 +2287,7 @@ image_set_transform (struct frame *f, struct image *img)
double rotation = 0.0;
compute_image_rotation (img, &rotation);
#ifndef HAVE_HAIKU
# if defined USE_CAIRO || defined HAVE_XRENDER || defined HAVE_NS
/* We want scale up operations to use a nearest neighbor filter to
show real pixels instead of munging them, but scale down
@ -2414,6 +2458,34 @@ image_set_transform (struct frame *f, struct image *img)
img->xform.eDx = matrix[2][0];
img->xform.eDy = matrix[2][1];
# endif
#else
if (rotation != 0 &&
rotation != 90 &&
rotation != 180 &&
rotation != 270 &&
rotation != 360)
{
image_error ("No native support for rotation by %g degrees",
make_float (rotation));
return;
}
rotation = fmod (rotation, 360.0);
if (rotation == 90 || rotation == 270)
{
int w = width;
width = height;
height = w;
}
img->have_be_transforms_p = rotation != 0 || (img->width != width) || (img->height != height);
img->be_rotate = rotation;
img->be_scale_x = 1.0 / (img->width / (double) width);
img->be_scale_y = 1.0 / (img->height / (double) height);
img->width = width;
img->height = height;
#endif /* not HAVE_HAIKU */
}
#endif /* HAVE_IMAGEMAGICK || HAVE_NATIVE_TRANSFORMS */
@ -2820,6 +2892,30 @@ image_create_x_image_and_pixmap_1 (struct frame *f, int width, int height, int d
return 1;
#endif /* HAVE_X_WINDOWS */
#ifdef HAVE_HAIKU
if (depth == 0)
depth = 24;
if (depth != 24 && depth != 1)
{
*pimg = NULL;
image_error ("Invalid image bit depth specified");
return 0;
}
*pixmap = BBitmap_new (width, height, depth == 1);
if (*pixmap == NO_PIXMAP)
{
*pimg = NULL;
image_error ("Unable to create pixmap", Qnil, Qnil);
return 0;
}
*pimg = *pixmap;
return 1;
#endif
#ifdef HAVE_NTGUI
BITMAPINFOHEADER *header;
@ -2960,7 +3056,7 @@ static void
gui_put_x_image (struct frame *f, Emacs_Pix_Container pimg,
Emacs_Pixmap pixmap, int width, int height)
{
#ifdef USE_CAIRO
#if defined USE_CAIRO || defined HAVE_HAIKU
eassert (pimg == pixmap);
#elif defined HAVE_X_WINDOWS
GC gc;
@ -3087,7 +3183,7 @@ image_unget_x_image_or_dc (struct image *img, bool mask_p,
static Emacs_Pix_Container
image_get_x_image (struct frame *f, struct image *img, bool mask_p)
{
#ifdef USE_CAIRO
#if defined USE_CAIRO || defined (HAVE_HAIKU)
return !mask_p ? img->pixmap : img->mask;
#elif defined HAVE_X_WINDOWS
XImage *ximg_in_img = !mask_p ? img->ximg : img->mask_img;
@ -4036,7 +4132,7 @@ xbm_load (struct frame *f, struct image *img)
#endif /* not HAVE_NTGUI */
#endif /* HAVE_XPM */
#if defined HAVE_XPM || defined USE_CAIRO || defined HAVE_NS
#if defined HAVE_XPM || defined USE_CAIRO || defined HAVE_NS || defined HAVE_HAIKU
/* Indices of image specification fields in xpm_format, below. */
@ -4056,7 +4152,7 @@ enum xpm_keyword_index
XPM_LAST
};
#if defined HAVE_XPM || defined HAVE_NS
#if defined HAVE_XPM || defined HAVE_NS || defined HAVE_HAIKU
/* Vector of image_keyword structures describing the format
of valid XPM image specifications. */
@ -4074,7 +4170,7 @@ static const struct image_keyword xpm_format[XPM_LAST] =
{":color-symbols", IMAGE_DONT_CHECK_VALUE_TYPE, 0},
{":background", IMAGE_STRING_OR_NIL_VALUE, 0}
};
#endif /* HAVE_XPM || HAVE_NS */
#endif /* HAVE_XPM || HAVE_NS || HAVE_HAIKU */
#if defined HAVE_X_WINDOWS && !defined USE_CAIRO
@ -4298,7 +4394,7 @@ init_xpm_functions (void)
#endif /* WINDOWSNT */
#if defined HAVE_XPM || defined HAVE_NS
#if defined HAVE_XPM || defined HAVE_NS || defined HAVE_HAIKU
/* Value is true if COLOR_SYMBOLS is a valid color symbols list
for XPM images. Such a list must consist of conses whose car and
cdr are strings. */
@ -4334,9 +4430,9 @@ xpm_image_p (Lisp_Object object)
&& (! fmt[XPM_COLOR_SYMBOLS].count
|| xpm_valid_color_symbols_p (fmt[XPM_COLOR_SYMBOLS].value)));
}
#endif /* HAVE_XPM || HAVE_NS */
#endif /* HAVE_XPM || HAVE_NS || HAVE_HAIKU */
#endif /* HAVE_XPM || USE_CAIRO || HAVE_NS */
#endif /* HAVE_XPM || USE_CAIRO || HAVE_NS || HAVE_HAIKU */
#if defined HAVE_XPM && defined HAVE_X_WINDOWS && !defined USE_GTK
ptrdiff_t
@ -4705,9 +4801,10 @@ xpm_load (struct frame *f, struct image *img)
#endif /* HAVE_XPM && !USE_CAIRO */
#if (defined USE_CAIRO && defined HAVE_XPM) \
|| (defined HAVE_NS && !defined HAVE_XPM)
|| (defined HAVE_NS && !defined HAVE_XPM) \
|| (defined HAVE_HAIKU && !defined HAVE_XPM)
/* XPM support functions for NS where libxpm is not available, and for
/* XPM support functions for NS and Haiku where libxpm is not available, and for
Cairo. Only XPM version 3 (without any extensions) is supported. */
static void xpm_put_color_table_v (Lisp_Object, const char *,
@ -5444,7 +5541,7 @@ lookup_rgb_color (struct frame *f, int r, int g, int b)
{
#ifdef HAVE_NTGUI
return PALETTERGB (r >> 8, g >> 8, b >> 8);
#elif defined USE_CAIRO || defined HAVE_NS
#elif defined USE_CAIRO || defined HAVE_NS || defined HAVE_HAIKU
return RGB_TO_ULONG (r >> 8, g >> 8, b >> 8);
#else
xsignal1 (Qfile_error,
@ -5517,7 +5614,7 @@ image_to_emacs_colors (struct frame *f, struct image *img, bool rgb_p)
p = colors;
for (y = 0; y < img->height; ++y)
{
#if !defined USE_CAIRO && !defined HAVE_NS
#if !defined USE_CAIRO && !defined HAVE_NS && !defined HAVE_HAIKU
Emacs_Color *row = p;
for (x = 0; x < img->width; ++x, ++p)
p->pixel = GET_PIXEL (ximg, x, y);
@ -5525,7 +5622,7 @@ image_to_emacs_colors (struct frame *f, struct image *img, bool rgb_p)
{
FRAME_TERMINAL (f)->query_colors (f, row, img->width);
}
#else /* USE_CAIRO || HAVE_NS */
#else /* USE_CAIRO || HAVE_NS || HAVE_HAIKU */
for (x = 0; x < img->width; ++x, ++p)
{
p->pixel = GET_PIXEL (ximg, x, y);
@ -5839,6 +5936,7 @@ image_disable_image (struct frame *f, struct image *img)
{
#ifndef HAVE_NTGUI
#ifndef HAVE_NS /* TODO: NS support, however this not needed for toolbars */
#ifndef HAVE_HAIKU
#ifndef USE_CAIRO
#define CrossForeground(f) BLACK_PIX_DEFAULT (f)
@ -5856,6 +5954,7 @@ image_disable_image (struct frame *f, struct image *img)
if (img->mask)
image_pixmap_draw_cross (f, img->mask, 0, 0, img->width, img->height,
MaskForeground (f));
#endif /* !HAVE_HAIKU */
#endif /* !HAVE_NS */
#else
HDC hdc, bmpdc;
@ -6413,6 +6512,8 @@ image_can_use_native_api (Lisp_Object type)
return w32_can_use_native_image_api (type);
# elif defined HAVE_NS
return ns_can_use_native_image_api (type);
# elif defined HAVE_HAIKU
return haiku_can_use_native_image_api (type);
# else
return false;
# endif
@ -6486,6 +6587,9 @@ native_image_load (struct frame *f, struct image *img)
# elif defined HAVE_NS
return ns_load_image (f, img, image_file,
image_spec_value (img->spec, QCdata, NULL));
# elif defined HAVE_HAIKU
return haiku_load_image (f, img, image_file,
image_spec_value (img->spec, QCdata, NULL));
# else
return 0;
# endif
@ -9635,7 +9739,8 @@ imagemagick_load_image (struct frame *f, struct image *img,
init_color_table ();
#if defined (HAVE_MAGICKEXPORTIMAGEPIXELS) && ! defined (HAVE_NS)
#if defined (HAVE_MAGICKEXPORTIMAGEPIXELS) && \
! defined (HAVE_NS) && ! defined (HAVE_HAIKU)
if (imagemagick_render_type != 0)
{
/* Magicexportimage is normally faster than pixelpushing. This
@ -10925,7 +11030,8 @@ The list of capabilities can include one or more of the following:
if (FRAME_WINDOW_P (f))
{
#ifdef HAVE_NATIVE_TRANSFORMS
# if defined HAVE_IMAGEMAGICK || defined (USE_CAIRO) || defined (HAVE_NS)
# if defined HAVE_IMAGEMAGICK || defined (USE_CAIRO) || defined (HAVE_NS) \
|| defined (HAVE_HAIKU)
return list2 (Qscale, Qrotate90);
# elif defined (HAVE_X_WINDOWS) && defined (HAVE_XRENDER)
int event_basep, error_basep;
@ -11015,7 +11121,7 @@ static struct image_type const image_types[] =
{ SYMBOL_INDEX (Qjpeg), jpeg_image_p, jpeg_load, image_clear_image,
IMAGE_TYPE_INIT (init_jpeg_functions) },
#endif
#if defined HAVE_XPM || defined HAVE_NS
#if defined HAVE_XPM || defined HAVE_NS || defined HAVE_HAIKU
{ SYMBOL_INDEX (Qxpm), xpm_image_p, xpm_load, image_clear_image,
IMAGE_TYPE_INIT (init_xpm_functions) },
#endif
@ -11163,7 +11269,7 @@ non-numeric, there is no explicit limit on the size of images. */);
DEFSYM (Qxbm, "xbm");
add_image_type (Qxbm);
#if defined (HAVE_XPM) || defined (HAVE_NS)
#if defined (HAVE_XPM) || defined (HAVE_NS) || defined (HAVE_HAIKU)
DEFSYM (Qxpm, "xpm");
add_image_type (Qxpm);
#endif

View file

@ -3865,7 +3865,7 @@ kbd_buffer_get_event (KBOARD **kbp,
/* One way or another, wait until input is available; then, if
interrupt handlers have not read it, read it now. */
#ifdef USABLE_SIGIO
#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
gobble_input ();
#endif
if (kbd_fetch_ptr != kbd_store_ptr)
@ -6156,7 +6156,6 @@ make_lispy_event (struct input_event *event)
case CONFIG_CHANGED_EVENT:
return list3 (Qconfig_changed_event,
event->arg, event->frame_or_window);
/* The 'kind' field of the event is something we don't recognize. */
default:
emacs_abort ();
@ -7247,7 +7246,7 @@ totally_unblock_input (void)
unblock_input_to (0);
}
#ifdef USABLE_SIGIO
#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
void
handle_input_available_signal (int sig)
@ -7263,7 +7262,7 @@ deliver_input_available_signal (int sig)
{
deliver_process_signal (sig, handle_input_available_signal);
}
#endif /* USABLE_SIGIO */
#endif /* defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL) */
/* User signal events. */
@ -7333,7 +7332,7 @@ handle_user_signal (int sig)
}
p->npending++;
#ifdef USABLE_SIGIO
#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
if (interrupt_input)
handle_input_available_signal (sig);
else
@ -11103,7 +11102,7 @@ See also `current-input-mode'. */)
(Lisp_Object interrupt)
{
bool new_interrupt_input;
#ifdef USABLE_SIGIO
#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
#ifdef HAVE_X_WINDOWS
if (x_display_list != NULL)
{
@ -11114,9 +11113,9 @@ See also `current-input-mode'. */)
else
#endif /* HAVE_X_WINDOWS */
new_interrupt_input = !NILP (interrupt);
#else /* not USABLE_SIGIO */
#else /* not USABLE_SIGIO || USABLE_SIGPOLL */
new_interrupt_input = false;
#endif /* not USABLE_SIGIO */
#endif /* not USABLE_SIGIO || USABLE_SIGPOLL */
if (new_interrupt_input != interrupt_input)
{
@ -11545,12 +11544,16 @@ init_keyboard (void)
sigaction (SIGQUIT, &action, 0);
#endif /* not DOS_NT */
}
#ifdef USABLE_SIGIO
#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
if (!noninteractive)
{
struct sigaction action;
emacs_sigaction_init (&action, deliver_input_available_signal);
#ifdef USABLE_SIGIO
sigaction (SIGIO, &action, 0);
#else
sigaction (SIGPOLL, &action, 0);
#endif
}
#endif

View file

@ -138,7 +138,12 @@ verify (BITS_WORD_MAX >> (BITS_PER_BITS_WORD - 1) == 1);
buffers and strings. Emacs never allocates objects larger than
PTRDIFF_MAX bytes, as they cause problems with pointer subtraction.
In C99, pD can always be "t"; configure it here for the sake of
pre-C99 libraries such as glibc 2.0 and Solaris 8. */
pre-C99 libraries such as glibc 2.0 and Solaris 8.
On Haiku, the size of ptrdiff_t is inconsistent with the value of
PTRDIFF_MAX. In that case, "t" should be sufficient. */
#ifndef HAIKU
#if PTRDIFF_MAX == INT_MAX
# define pD ""
#elif PTRDIFF_MAX == LONG_MAX
@ -148,6 +153,9 @@ verify (BITS_WORD_MAX >> (BITS_PER_BITS_WORD - 1) == 1);
#else
# define pD "t"
#endif
#else
# define pD "t"
#endif
/* Convenience macro for rarely-used functions that do not return. */
#define AVOID _Noreturn ATTRIBUTE_COLD void
@ -3330,7 +3338,7 @@ struct frame;
/* Define if the windowing system provides a menu bar. */
#if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \
|| defined (HAVE_NS) || defined (USE_GTK)
|| defined (HAVE_NS) || defined (USE_GTK) || defined (HAVE_HAIKU)
#define HAVE_EXT_MENU_BAR true
#endif
@ -4429,7 +4437,7 @@ extern Lisp_Object menu_bar_items (Lisp_Object);
extern Lisp_Object tab_bar_items (Lisp_Object, int *);
extern Lisp_Object tool_bar_items (Lisp_Object, int *);
extern void discard_mouse_events (void);
#ifdef USABLE_SIGIO
#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
void handle_input_available_signal (int);
#endif
extern Lisp_Object pending_funcalls;

View file

@ -50,7 +50,8 @@ extern AppendMenuW_Proc unicode_append_menu;
static bool
have_boxes (void)
{
#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI) || defined(HAVE_NS)
#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NTGUI) || defined (HAVE_NS) \
|| defined (HAVE_HAIKU)
if (FRAME_WINDOW_P (XFRAME (Vmenu_updating_frame)))
return 1;
#endif
@ -422,7 +423,8 @@ single_menu_item (Lisp_Object key, Lisp_Object item, Lisp_Object dummy, void *sk
AREF (item_properties, ITEM_PROPERTY_SELECTED),
AREF (item_properties, ITEM_PROPERTY_HELP));
#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) || defined (HAVE_NTGUI)
#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) \
|| defined (HAVE_NTGUI) || defined (HAVE_HAIKU)
/* Display a submenu using the toolkit. */
if (FRAME_WINDOW_P (XFRAME (Vmenu_updating_frame))
&& ! (NILP (map) || NILP (enabled)))
@ -872,6 +874,10 @@ update_submenu_strings (widget_value *first_wv)
}
}
#endif /* USE_X_TOOLKIT || USE_GTK || HAVE_NS || HAVE_NTGUI */
#if defined (USE_X_TOOLKIT) || defined (USE_GTK) || defined (HAVE_NS) \
|| defined (HAVE_NTGUI) || defined (HAVE_HAIKU)
/* Find the menu selection and store it in the keyboard buffer.
F is the frame the menu is on.
MENU_BAR_ITEMS_USED is the length of VECTOR.
@ -959,7 +965,7 @@ find_and_call_menu_selection (struct frame *f, int menu_bar_items_used,
SAFE_FREE ();
}
#endif /* USE_X_TOOLKIT || USE_GTK || HAVE_NS || HAVE_NTGUI */
#endif /* USE_X_TOOLKIT || USE_GTK || HAVE_NS || HAVE_NTGUI || HAVE_HAIKU */
#ifdef HAVE_NS
/* As above, but return the menu selection instead of storing in kb buffer.

View file

@ -259,7 +259,7 @@ static bool process_output_skip;
static void start_process_unwind (Lisp_Object);
static void create_process (Lisp_Object, char **, Lisp_Object);
#ifdef USABLE_SIGIO
#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
static bool keyboard_bit_set (fd_set *);
#endif
static void deactivate_process (Lisp_Object);
@ -5730,7 +5730,7 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
if (! NILP (wait_for_cell) && ! NILP (XCAR (wait_for_cell)))
break;
#ifdef USABLE_SIGIO
#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
/* If we think we have keyboard input waiting, but didn't get SIGIO,
go read it. This can happen with X on BSD after logging out.
In that case, there really is no input and no SIGIO,
@ -5738,7 +5738,11 @@ wait_reading_process_output (intmax_t time_limit, int nsecs, int read_kbd,
if (read_kbd && interrupt_input
&& keyboard_bit_set (&Available) && ! noninteractive)
#ifdef USABLE_SIGIO
handle_input_available_signal (SIGIO);
#else
handle_input_available_signal (SIGPOLL);
#endif
#endif
/* If checking input just got us a size-change event from X,
@ -7732,7 +7736,7 @@ delete_gpm_wait_descriptor (int desc)
# endif
# ifdef USABLE_SIGIO
#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
/* Return true if *MASK has a bit set
that corresponds to one of the keyboard input descriptors. */

View file

@ -299,11 +299,15 @@ sound_perror (const char *msg)
int saved_errno = errno;
turn_on_atimers (1);
#ifdef USABLE_SIGIO
#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
{
sigset_t unblocked;
sigemptyset (&unblocked);
#ifdef USABLE_SIGIO
sigaddset (&unblocked, SIGIO);
#else
sigaddset (&unblocked, SIGPOLL);
#endif
pthread_sigmask (SIG_UNBLOCK, &unblocked, 0);
}
#endif
@ -698,7 +702,7 @@ static void
vox_configure (struct sound_device *sd)
{
int val;
#ifdef USABLE_SIGIO
#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
sigset_t oldset, blocked;
#endif
@ -708,9 +712,13 @@ vox_configure (struct sound_device *sd)
interrupted by a signal. Block the ones we know to cause
troubles. */
turn_on_atimers (0);
#ifdef USABLE_SIGIO
#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
sigemptyset (&blocked);
#ifdef USABLE_SIGIO
sigaddset (&blocked, SIGIO);
#else
sigaddset (&blocked, SIGPOLL);
#endif
pthread_sigmask (SIG_BLOCK, &blocked, &oldset);
#endif
@ -744,7 +752,7 @@ vox_configure (struct sound_device *sd)
}
turn_on_atimers (1);
#ifdef USABLE_SIGIO
#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
pthread_sigmask (SIG_SETMASK, &oldset, 0);
#endif
}
@ -760,10 +768,14 @@ vox_close (struct sound_device *sd)
/* On GNU/Linux, it seems that the device driver doesn't like to
be interrupted by a signal. Block the ones we know to cause
troubles. */
#ifdef USABLE_SIGIO
#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
sigset_t blocked, oldset;
sigemptyset (&blocked);
#ifdef USABLE_SIGIO
sigaddset (&blocked, SIGIO);
#else
sigaddset (&blocked, SIGPOLL);
#endif
pthread_sigmask (SIG_BLOCK, &blocked, &oldset);
#endif
turn_on_atimers (0);
@ -772,7 +784,7 @@ vox_close (struct sound_device *sd)
ioctl (sd->fd, SNDCTL_DSP_SYNC, NULL);
turn_on_atimers (1);
#ifdef USABLE_SIGIO
#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
pthread_sigmask (SIG_SETMASK, &oldset, 0);
#endif

View file

@ -678,6 +678,9 @@ sys_subshell (void)
#ifdef USABLE_SIGIO
saved_handlers[3].code = SIGIO;
saved_handlers[4].code = 0;
#elif defined (USABLE_SIGPOLL)
saved_handlers[3].code = SIGPOLL;
saved_handlers[4].code = 0;
#else
saved_handlers[3].code = 0;
#endif
@ -788,6 +791,7 @@ init_sigio (int fd)
}
#ifndef DOS_NT
#ifdef F_SETOWN
static void
reset_sigio (int fd)
{
@ -795,12 +799,13 @@ reset_sigio (int fd)
fcntl (fd, F_SETFL, old_fcntl_flags[fd]);
#endif
}
#endif /* F_SETOWN */
#endif
void
request_sigio (void)
{
#ifdef USABLE_SIGIO
#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
sigset_t unblocked;
if (noninteractive)
@ -810,7 +815,11 @@ request_sigio (void)
# ifdef SIGWINCH
sigaddset (&unblocked, SIGWINCH);
# endif
# ifdef USABLE_SIGIO
sigaddset (&unblocked, SIGIO);
# else
sigaddset (&unblocked, SIGPOLL);
# endif
pthread_sigmask (SIG_UNBLOCK, &unblocked, 0);
interrupts_deferred = 0;
@ -820,7 +829,7 @@ request_sigio (void)
void
unrequest_sigio (void)
{
#ifdef USABLE_SIGIO
#if defined (USABLE_SIGIO) || defined (USABLE_SIGPOLL)
sigset_t blocked;
if (noninteractive)
@ -830,7 +839,11 @@ unrequest_sigio (void)
# ifdef SIGWINCH
sigaddset (&blocked, SIGWINCH);
# endif
# ifdef USABLE_SIGIO
sigaddset (&blocked, SIGIO);
# else
sigaddset (&blocked, SIGPOLL);
# endif
pthread_sigmask (SIG_BLOCK, &blocked, 0);
interrupts_deferred = 1;
#endif
@ -1256,9 +1269,12 @@ init_sys_modes (struct tty_display_info *tty_out)
/* This code added to insure that, if flow-control is not to be used,
we have an unlocked terminal at the start. */
#ifndef HAIKU /* On Haiku, TCXONC is a no-op and causes spurious
compiler warnings. */
#ifdef TCXONC
if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TCXONC, 1);
#endif
#endif /* HAIKU */
#ifdef TIOCSTART
if (!tty_out->flow_control) ioctl (fileno (tty_out->input), TIOCSTART, 0);
#endif
@ -1674,6 +1690,8 @@ emacs_sigaction_init (struct sigaction *action, signal_handler_t handler)
sigaddset (&action->sa_mask, SIGQUIT);
#ifdef USABLE_SIGIO
sigaddset (&action->sa_mask, SIGIO);
#elif defined (USABLE_SIGPOLL)
sigaddset (&action->sa_mask, SIGPOLL);
#endif
}
@ -2772,6 +2790,7 @@ static const struct speed_struct speeds[] =
#ifdef B150
{ 150, B150 },
#endif
#ifndef HAVE_TINY_SPEED_T
#ifdef B200
{ 200, B200 },
#endif
@ -2859,6 +2878,7 @@ static const struct speed_struct speeds[] =
#ifdef B4000000
{ 4000000, B4000000 },
#endif
#endif /* HAVE_TINY_SPEED_T */
};
/* Convert a numerical speed (e.g., 9600) to a Bnnn constant (e.g.,
@ -3120,8 +3140,9 @@ list_system_processes (void)
}
/* The WINDOWSNT implementation is in w32.c.
The MSDOS implementation is in dosfns.c. */
#elif !defined (WINDOWSNT) && !defined (MSDOS)
The MSDOS implementation is in dosfns.c.
The Haiku implementation is in haiku.c. */
#elif !defined (WINDOWSNT) && !defined (MSDOS) && !defined (HAIKU)
Lisp_Object
list_system_processes (void)
@ -4200,8 +4221,9 @@ system_process_attributes (Lisp_Object pid)
}
/* The WINDOWSNT implementation is in w32.c.
The MSDOS implementation is in dosfns.c. */
#elif !defined (WINDOWSNT) && !defined (MSDOS)
The MSDOS implementation is in dosfns.c.
The HAIKU implementation is in haiku.c. */
#elif !defined (WINDOWSNT) && !defined (MSDOS) && !defined (HAIKU)
Lisp_Object
system_process_attributes (Lisp_Object pid)

View file

@ -60,7 +60,8 @@ enum output_method
output_x_window,
output_msdos_raw,
output_w32,
output_ns
output_ns,
output_haiku
};
/* Input queue declarations and hooks. */
@ -266,7 +267,6 @@ enum event_kind
/* File or directory was changed. */
, FILE_NOTIFY_EVENT
#endif
};
/* Bit width of an enum event_kind tag at the start of structs and unions. */
@ -447,6 +447,7 @@ struct terminal
struct x_display_info *x; /* xterm.h */
struct w32_display_info *w32; /* w32term.h */
struct ns_display_info *ns; /* nsterm.h */
struct haiku_display_info *haiku; /* haikuterm.h */
} display_info;
@ -835,6 +836,9 @@ extern struct terminal *terminal_list;
#elif defined (HAVE_NS)
#define TERMINAL_FONT_CACHE(t) \
(t->type == output_ns ? t->display_info.ns->name_list_element : Qnil)
#elif defined (HAVE_HAIKU)
#define TERMINAL_FONT_CACHE(t) \
(t->type == output_haiku ? t->display_info.haiku->name_list_element : Qnil)
#endif
extern struct terminal *decode_live_terminal (Lisp_Object);

View file

@ -445,6 +445,8 @@ possible return values. */)
return Qpc;
case output_ns:
return Qns;
case output_haiku:
return Qhaiku;
default:
emacs_abort ();
}

View file

@ -23,7 +23,9 @@ ifeq (${V},1)
AM_V_AR =
AM_V_at =
AM_V_CC =
AM_V_CXX =
AM_V_CCLD =
AM_V_CXXLD =
AM_V_ELC =
AM_V_ELN =
AM_V_GEN =
@ -34,7 +36,9 @@ else
AM_V_AR = @echo " AR " $@;
AM_V_at = @
AM_V_CC = @echo " CC " $@;
AM_V_CXX = @echo " CXX " $@;
AM_V_CCLD = @echo " CCLD " $@;
AM_V_CXXLD = @echo " CXXLD " $@;
ifeq ($(HAVE_NATIVE_COMP),yes)
ifeq ($(NATIVE_DISABLED),1)
AM_V_ELC = @echo " ELC " $@;

View file

@ -15657,6 +15657,11 @@ redisplay_internal (void)
}
#endif
#if defined (HAVE_HAIKU)
if (popup_activated_p)
return;
#endif
/* I don't think this happens but let's be paranoid. */
if (redisplaying_p)
return;
@ -25247,6 +25252,11 @@ display_menu_bar (struct window *w)
return;
#endif /* HAVE_NS */
#ifdef HAVE_HAIKU
if (FRAME_HAIKU_P (f))
return;
#endif /* HAVE_HAIKU */
#if defined (USE_X_TOOLKIT) || defined (USE_GTK)
eassert (!FRAME_WINDOW_P (f));
init_iterator (&it, w, -1, -1, f->desired_matrix->rows, MENU_FACE_ID);
@ -33698,6 +33708,11 @@ note_mouse_highlight (struct frame *f, int x, int y)
return;
#endif
#if defined (HAVE_HAIKU)
if (popup_activated_p)
return;
#endif
if (!f->glyphs_initialized_p
|| f->pointer_invisible)
return;

View file

@ -246,6 +246,10 @@ along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>. */
#ifdef HAVE_NS
#define GCGraphicsExposures 0
#endif /* HAVE_NS */
#ifdef HAVE_HAIKU
#define GCGraphicsExposures 0
#endif /* HAVE_HAIKU */
#endif /* HAVE_WINDOW_SYSTEM */
#include "buffer.h"
@ -555,8 +559,8 @@ x_free_gc (struct frame *f, Emacs_GC *gc)
#endif /* HAVE_NTGUI */
#ifdef HAVE_NS
/* NS emulation of GCs */
#if defined (HAVE_NS) || defined (HAVE_HAIKU)
/* NS and Haiku emulation of GCs */
static Emacs_GC *
x_create_gc (struct frame *f,

View file

@ -4461,7 +4461,8 @@ For GNU and Unix system, the first 2 numbers are the version of the X
Protocol used on TERMINAL and the 3rd number is the distributor-specific
release number. For MS Windows, the 3 numbers report the OS major and
minor version and build number. For Nextstep, the first 2 numbers are
hard-coded and the 3rd represents the OS version.
hard-coded and the 3rd represents the OS version. For Haiku, all 3
numbers are hard-coded.
See also the function `x-server-vendor'.
@ -7419,7 +7420,7 @@ Use a file selection dialog. Select DEFAULT-FILENAME in the dialog's file
selection box, if specified. If MUSTMATCH is non-nil, the returned file
or directory must exist.
This function is defined only on NS, MS Windows, and X Windows with the
This function is defined only on NS, Haiku, MS Windows, and X Windows with the
Motif or Gtk toolkits. With the Motif toolkit, ONLY-DIR-P is ignored.
Otherwise, if ONLY-DIR-P is non-nil, the user can select only directories.
On MS Windows 7 and later, the file selection dialog "remembers" the last

View file

@ -14959,7 +14959,7 @@ selected window or cursor position is preserved. */);
A value of nil means Emacs doesn't use toolkit scroll bars.
With the X Window system, the value is a symbol describing the
X toolkit. Possible values are: gtk, motif, xaw, or xaw3d.
With MS Windows or Nextstep, the value is t. */);
With MS Windows, Haiku windowing or Nextstep, the value is t. */);
#ifdef USE_TOOLKIT_SCROLL_BARS
#ifdef USE_MOTIF
Vx_toolkit_scroll_bars = intern_c_string ("motif");