Compare commits

...

471 commits

Author SHA1 Message Date
Po Lu
889b61b999 Update Android port
* java/org/gnu/emacs/EmacsInputConnection.java
(requestCursorUpdates):
* java/org/gnu/emacs/EmacsNative.java (requestCursorUpdates):
* java/org/gnu/emacs/EmacsService.java (updateCursorAnchorInfo):
New functions.
* src/android.c (struct android_emacs_service)
(android_init_emacs_service): Add new method.
(android_update_cursor_anchor_info): New function.
* src/androidfns.c (android_set_preeditarea): New function.
* src/androidgui.h (enum android_ime_operation): New operation
`REQUEST_CURSOR_UPDATES'.
(struct android_ime_event): Document new meaning of `length'.
* src/androidterm.c (android_request_cursor_updates): New
function.
(android_handle_ime_event): Handle new operations.
(handle_one_android_event, android_draw_window_cursor): Update
the preedit area if needed, like on X.
(requestCursorUpdates): New function.
* src/androidterm.h (struct android_output): New field
`need_cursor_updates'.
2023-05-07 11:09:56 +08:00
Po Lu
c0a52c6cef Merge remote-tracking branch 'origin/master' into feature/android 2023-05-07 08:33:48 +08:00
Po Lu
11cb9cc598 Merge remote-tracking branch 'origin/master' into feature/android 2023-05-06 20:35:42 +08:00
Po Lu
c7ca46b0a7 Update Android port
* configure.ac (LIBGMP_CFLAGS): Avoid non portable test
expression.
2023-05-06 20:34:01 +08:00
Po Lu
3198b7dc56 Update Android port
* cross/verbose.mk.android: Get rid of badly aligned ANDROID_CC
messages.
* java/org/gnu/emacs/EmacsInputConnection.java (syncAfterCommit)
(extractAbsoluteOffsets): Add workarounds for several kinds of
machines.
(commitText, getExtractedText): Likewise.
* src/textconv.c (really_commit_text): Improve definition of
POSITION.
(get_extracted_text): Default to providing at least 4
characters.
2023-05-06 11:32:56 +08:00
Po Lu
96f9fe6514 Merge remote-tracking branch 'origin/master' into feature/android 2023-05-06 07:55:02 +08:00
Po Lu
0fbe79727b Fix execution of /proc/self/exe within child processes
* exec/exec.h (struct exec_tracee): New field `new_child'.
Also, make `waiting_for_syscall' a bitfield.
* exec/trace.c (PTRACE_GETEVENTMSG): New declaration.
(MAX_TRACEES): Bump to 4096.
(handle_clone_prepare): New function.
(handle_clone): If required, set `new_child' and wait for a
ptrace event describing the parent to arrive.
(after_fork): Clear new field.
(exec_waitpid): Upon a ptrace event describing a clone, create
the child's tracee if it doesn't already exist.  Otherwise, copy
over the parent's cmdline and start running it.
2023-05-05 19:04:32 +08:00
Po Lu
2ba6c5035c Update Android port
* doc/emacs/android.texi (Android Environment): Document lossage
with SIGSTOP.
* exec/exec.c (exec_0): Check X_OK on file being opened.  Also
handle /proc/self/exe.
2023-05-05 12:10:14 +08:00
Po Lu
d5414f1797 Update Android port
* exec/trace.c (SYS_SECCOMP): Define when not present.
2023-05-05 10:57:26 +08:00
Po Lu
daccdf7e6d Merge remote-tracking branch 'origin/master' into feature/android 2023-05-05 08:27:30 +08:00
Po Lu
ccef1ff072 Document another misfeature of Android
* doc/emacs/android.texi (Android Environment): Describe how to
turn off process killing.
2023-05-04 11:06:18 +08:00
Po Lu
339cdef28e Update Android port
* exec/trace.c (check_signal): New function.
(handle_exec, process_system_call): Handle signal-delivery-stop
while waiting synchronously for syscall completion.
2023-05-04 09:12:26 +08:00
Po Lu
19210f8b77 Merge remote-tracking branch 'origin/master' into feature/android 2023-05-04 08:14:56 +08:00
Po Lu
b0d6c67372 Update Android port
* exec/config.h.in: Autoheader.
* exec/configure.ac: Check for siginfo_t.si_syscall.
* exec/trace.c (exec_waitpid): If SIGSYS is received, and caused by
seccomp, drop it should the call number be the invalid system call
used by Emacs.
2023-05-03 17:01:44 +08:00
Po Lu
7b3c774bce Update Android port
* exec/config.h.in: Autoheader.
* exec/configure.ac: Use system extensions.
(HAVE_PROCESS_VM): Define if process_vm_readv and
process_vm_writev are available.
* exec/trace.c (read_memory, user_copy): Implement in terms of
process_vm if possible.
2023-05-03 16:00:13 +08:00
Po Lu
35eae084bc Remove extra debugging code
* exec/loader-mipsel.s (__start): Remove extraneous debugging
code.
2023-05-03 09:23:06 +08:00
Po Lu
d5b92bce5b Update Android port
* exec/Makefile.in: (.PHONY): Add `bootstrap-clean' and
`extraclean'.
(bootstrap-clean): New rule.
2023-05-03 07:53:38 +08:00
Po Lu
258c98240d Update Android port
* java/Makefile.in (FIND_DELETE): New substitution.
(clean): Use FIND_DELETE.
2023-05-03 07:50:29 +08:00
Po Lu
9283471cb4 Merge remote-tracking branch 'origin/master' into feature/android 2023-05-03 07:45:49 +08:00
Po Lu
f4a5e6d0e5 * doc/emacs/android.texi (Android Environment): Improve doc. 2023-05-02 21:13:42 +08:00
Po Lu
c47716f95b Update Android port
* exec/config.h.in (__bool_true_false_are_defined):
* exec/configure.ac (REENTRANT): New definition.
(READLINKAT_SYSCALL, READLINK_SYSCALL): New defines.  Set on all
hosts.
* exec/exec.c (MIN, MAX): Remove redundant declarations.  Move
to config.h.
(exec_0): Copy name of executable into NAME when !REENTRANT.
* exec/exec.h (struct exec_tracee): New struct `exec_file'.
* exec/trace.c (remove_tracee, handle_exec, handle_readlinkat)
(process_system_call, after_fork): Handle readlinkat system
calls.
2023-05-02 20:45:57 +08:00
Po Lu
f4512cca0b Fix ps name in Android subprocesses
* exec/Makefile.in (.SUFFIXES): Include ., then `srcdir'.
* exec/loader-aarch64.s (_start):
* exec/loader-armeabi.s (_start):
* exec/loader-mips64el.s (__start):
* exec/loader-mipsel.s (__start):
* exec/loader-x86.s (_start):
* exec/loader-x86_64.s (_start): Get basename of opened exec
file and make it the command name.  Fix envp skipping on x86
and various leaks.
2023-05-02 16:44:46 +08:00
Po Lu
5a58a6bc47 Port Android port to older Android systems
* exec/config.h.in: Autoheader.
* exec/configure.ac: Check for declarations of stpcpy and
stpncpy.
* exec/exec.c (stpcpy, stpncpy): Use replacements if
declarations are not present; this happens when a new Android
NDK is building for an old version of Android.
2023-05-02 08:16:00 +08:00
Po Lu
86b7ed619c Merge remote-tracking branch 'origin/master' into feature/android 2023-05-02 08:09:17 +08:00
Po Lu
f92bdbc677 Update Android port
* exec/config.h.in: Update config.h.in.
* exec/configure.ac: Check for stpcpy and stpncpy.
* exec/exec.c (rpl_stpcpy, rpl_stpncpy): Define replacements
when they are not present on the system.
(process_program_header): Fill comment.
2023-05-01 21:42:42 +08:00
Po Lu
8a90992799 ; * src/term.c (syms_of_term): Pretend Android uses TERMINFO. 2023-05-01 21:28:40 +08:00
Po Lu
b9de6e35b7 Fix cwd relative process execution on Android
* exec/exec.c (format_pid): New function.
(exec_0): Make cwd relative file names relative to
/proc/pid/cwd.
* exec/trace.c (handle_exec): Handle EINTR.
(process_system_call): Report failure without clobbering x0.
2023-05-01 21:23:12 +08:00
Po Lu
da6f0d9c6f ; * README: Describe `exec' directory. 2023-05-01 14:25:40 +08:00
Po Lu
843d8797db Fix use dialog box regression on Android
* lisp/subr.el (use-dialog-box-p): Always prefer dialog boxes.
2023-05-01 14:16:07 +08:00
Po Lu
6c3369abe5 Make it easier to quit on Android
* src/android.c (android_write_event):
(JNICALL): Raise SIGIO on key press and window action events.
2023-05-01 13:51:12 +08:00
Po Lu
6a30a74cb2 Fix syscall error reporting on aarch64
* exec/trace.c (process_system_call): Save and restore x0, x1
and x2 regs after replacing them with an invalid file
descriptor.
2023-05-01 13:12:44 +08:00
Po Lu
ddc16de869 Update Android port
* Makefile.in (extraclean): Clean in exec as well.
* configure.ac: Fix detection of absolute srcdir.  Also, pass
CFLAGS.
* exec/Makefile.in: (.c.o): Add -I. so config.h can be
found.:(.s.o): Don't create m4 temporary in srcdir.
* exec/config-mips.m4.in (DADDI2, DADDI3): New macros.  Define
to substitute if as cannot assemble daddi.
* exec/configure.ac (user_h): Look for user.h in asm/ as well.
Use new user.h.  Also look in ptrace.h on arm systems.  Check if
as supports daddi on mips64.
* exec/exec.c (check_interpreter): Fix char signedness bug.
* exec/loader-mips64el.s (__start): Use DADDI2 and DADDI3 for
two- and 3-operand daddi.
* exec/mipsel-user.h: Don't include sgidefs.h.
* java/INSTALL: Document that m4 is now required.
* src/android.c (android_rewrite_spawn_argv): Add missing NULL.
2023-05-01 11:28:22 +08:00
Po Lu
a8f9a4d2d9 Merge remote-tracking branch 'origin/master' into feature/android 2023-05-01 09:48:25 +08:00
Po Lu
5550816f59 Work around system restrictions regarding exec
* doc/emacs/android.texi (Android Environment): Document
`android-use-exec-loader'.
* exec/exec1.c (main): Set program group of child process.
* src/android.c (android_rewrite_spawn_argv): New function.
* src/android.h: Update prototypes.
* src/androidfns.c (syms_of_androidfns): New variable
`android_use_exec_loader'.
* src/callproc.c (emacs_spawn): Rewrite the argument vector to
use exec1 if necessary.
2023-05-01 09:31:58 +08:00
Po Lu
9a7c645dd4 Remove exec/configure
* exec/configure: Remove file.
* .gitignore: Add exec/configure.
2023-05-01 08:15:48 +08:00
Po Lu
368f6f3942 Add helper binary `exec1'
* .gitignore: New files.
* Makefile.in (mostlyclean_dirs): Add libexec, if its Makefile
exists.
* autogen.sh (do_git): Autoreconf in exec as well.
* configure.ac: Configure libexec on Android.
* exec/Makefile.in:
* exec/README:
* exec/config-mips.m4.in:
* exec/config.guess:
* exec/config.h.in:
* exec/config.sub:
* exec/configure:
* exec/configure.ac:
* exec/deps.mk:
* exec/exec.c (MIN, struct exec_open_command)
(struct exec_map_command, struct exec_jump_command)
(write_open_command, write_load_command, process_interpreter_1)
(process_interpreter, process_program_header, insert_args)
(exec_0):
* exec/exec.h (_EXEC_H_, struct elf_header_32)
(struct program_header_32, struct dt_entry_32)
(struct elf_header_64, struct program_header_64)
(struct dt_entry_64, struct exec_tracee):
* exec/exec1.c (main):
* exec/install-sh (scriptversion):
* exec/loader-aarch64.s (_start):
* exec/loader-armeabi.s (_start):
* exec/loader-mips64el.s (__start):
* exec/loader-mipsel.s (__start):
* exec/loader-x86.s (_start):
* exec/loader-x86_64.s (_start):
* exec/mipsel-user.h (_MIPSEL_USER_H_):
* exec/mipsfpu.c (MIPS_ABI_FP_ANY, fpu_reqs, valid_abi_p)
(fp_mode_for_abi, cpu_supports_fr0_p, determine_fpu_mode):
* exec/mipsfpu.h (_MIPSFPU_H_, FP_FR0):
* exec/test.c (print_usage, main):
* exec/trace.c (MAX_TRACEES, aarch64_set_regs, read_memory)
(user_alloca, user_copy, remove_tracee, handle_clone)
(syscall_trap_p, handle_exec, process_system_call, tracing_execve)
(after_fork, find_tracee, exec_waitpid, exec_init): New files.
* java/Makefile.in (CROSS_EXEC_BINS): Add exec1 and
loader.
($(CROSS_EXEC_BINS) &): New target.
2023-04-30 21:37:19 +08:00
Po Lu
4289ed6cff Merge remote-tracking branch 'origin/master' into feature/android 2023-04-30 08:25:24 +08:00
Po Lu
fee9efdf29 Merge remote-tracking branch 'origin/master' into feature/android 2023-04-29 08:28:01 +08:00
Po Lu
3d7c06869d Update Android port
* build-aux/ndk-build-helper.mk (TARGET_ARCH): Define variable.
* configure.ac (ENABLE_CHECKING, CHECK_STRUCTS)
(GC_CHECK_STRING_OVERRUN, GC_CHECK_STRING_FREE_LIST, GLYPH_DEBUG)
(GC_CHECK_STRING_BYTES): Enable checking correctly on Android.
* java/README: Fix typos.
* m4/ndk-build.m4 (ndk_run_test): Pass target arch.
* src/android.c (android_get_content_name, android_close)
(android_fclose, android_check_string): Fix various typos caught
by checking.
* src/charset.c (load_charset_map_from_file): Call emacs_fclose,
not fclose.
* src/image.c (image_set_transform): Fix thinko.
(png_load_body, jpeg_load_body, gif_load): Call emacs_fclose,
not fclose.  Use open instead of fdopen.
* src/xfaces.c (Fx_load_color_file): Likewise.
2023-04-29 08:27:44 +08:00
Po Lu
a87272183b Merge remote-tracking branch 'origin/master' into feature/android 2023-04-28 11:53:06 +08:00
Po Lu
4ea40db823 Merge remote-tracking branch 'origin/master' into feature/android 2023-04-28 08:05:34 +08:00
Po Lu
ab10d1f663 Update Android port
* src/image.c (image_create_bitmap_from_data): Fix typo in
preprocessor conditionals.
2023-04-27 19:23:29 +08:00
Po Lu
7c504d91d1 Merge remote-tracking branch 'origin/master' into feature/android 2023-04-27 18:52:25 +08:00
Po Lu
83a9e4cee1 Update Android port
* doc/emacs/android.texi (Android File System):
(Android Windowing): Make Emacs manual more portable.
2023-04-27 18:45:42 +08:00
Po Lu
04ac6e6be8 Update Android port
* doc/lispref/commands.texi (Misc Events):
* doc/lispref/frames.texi (Accessing Selections):
(X Selections): Fix pieces of the Info manual.
2023-04-27 16:23:57 +08:00
Po Lu
136ae23575 Merge remote-tracking branch 'origin/master' into feature/android 2023-04-27 09:07:19 +08:00
Po Lu
a5e90e4eea Make two well known amusements work on Android
* lisp/play/doctor.el (text-conversion-style):
(doctor-mode):
* lisp/play/dunnet.el (text-conversion-style):
(dun-mode): Set `text-conversion-style' to `action'.
2023-04-26 09:55:32 +08:00
Po Lu
5f389f4b63 Merge remote-tracking branch 'origin/master' into feature/android 2023-04-26 08:48:12 +08:00
Po Lu
9043bef65f Merge remote-tracking branch 'origin/master' into feature/android 2023-04-25 08:33:56 +08:00
Po Lu
85a9757b3c Merge remote-tracking branch 'origin/master' into feature/android 2023-04-24 08:49:30 +08:00
Po Lu
0a113a32c4 Merge remote-tracking branch 'origin/master' into feature/android 2023-04-23 08:36:11 +08:00
Po Lu
74fd40c030 Merge remote-tracking branch 'origin/master' into feature/android 2023-04-22 09:21:25 +08:00
Po Lu
ed2f8c660b Merge remote-tracking branch 'origin/master' into feature/android 2023-04-21 08:32:44 +08:00
Po Lu
a94e9f9644 Merge remote-tracking branch 'origin/master' into feature/android 2023-04-20 08:47:14 +08:00
Po Lu
5b31473189 Merge remote-tracking branch 'origin/master' into feature/android 2023-04-19 09:14:25 +08:00
Po Lu
55388c288a Merge remote-tracking branch 'origin/master' into feature/android 2023-04-18 07:08:25 +08:00
Po Lu
02c214a5e0 Merge remote-tracking branch 'origin/master' into feature/android 2023-04-17 08:14:03 +08:00
Po Lu
fe9e48a16a Merge remote-tracking branch 'origin/master' into feature/android 2023-04-16 08:16:07 +08:00
Po Lu
5919511881 Merge remote-tracking branch 'origin/master' into feature/android 2023-04-15 07:28:19 +08:00
Po Lu
618ba26ed1 Merge remote-tracking branch 'origin/master' into feature/android 2023-04-14 08:02:14 +08:00
Po Lu
e11e56a057 Update Android port
* doc/emacs/android.texi (Android Fonts): Update documentation.
* doc/lispref/frames.texi (Accessing Selections, X Selections):
Fix typos.
* src/sfntfont-android.c (system_font_directories)
(init_sfntfont_android): Add `/product/fonts'.
2023-04-13 19:54:54 +08:00
Po Lu
562b2fca7d Merge remote-tracking branch 'origin/master' into feature/android 2023-04-13 07:32:27 +08:00
Po Lu
91da696bbc Merge remote-tracking branch 'origin/master' into feature/android 2023-04-12 07:22:03 +08:00
Po Lu
933b5b51ab Merge remote-tracking branch 'origin/master' into feature/android 2023-04-11 07:57:31 +08:00
Po Lu
857e2bcb66 Merge remote-tracking branch 'origin/master' into feature/android 2023-04-10 08:16:44 +08:00
Po Lu
23e963b6f0 Merge remote-tracking branch 'origin/master' into feature/android 2023-04-09 09:07:40 +08:00
Po Lu
e1261fff85 Merge remote-tracking branch 'origin/master' into feature/android 2023-04-08 09:35:59 +08:00
Po Lu
3695ae4d63 Document selections on Android more thoroughly
* doc/lispref/elisp.texi (Top):
* doc/lispref/frames.texi (Frames): Add ``Accessing Selections''
to menu.
(Accessing Selections, X Selections, Other Selections): New
nodes.
2023-04-08 09:35:19 +08:00
Po Lu
6abed48e5c Merge remote-tracking branch 'origin/master' into feature/android 2023-04-07 08:25:54 +08:00
Po Lu
65987f8506 Merge remote-tracking branch 'origin/master' into feature/android 2023-04-06 09:56:34 +08:00
Po Lu
3b07a4b315 Implement `yank-media' on Android
* doc/emacs/android.texi (Android Windowing): Update selection
restrictions.
* java/org/gnu/emacs/EmacsClipboard.java (EmacsClipboard): New
functions `getClipboardTargets' and `getClipboardData'.
* java/org/gnu/emacs/EmacsSdk11Clipboard.java
(EmacsSdk11Clipboard, getClipboardTargets, getClipboardData):
Implement.
* java/org/gnu/emacs/EmacsSdk8Clipboard.java: Stub out new
functions.

* lisp/term/android-win.el (android-get-clipboard-1): Implement
MIME type targets.
* src/android.c (android_exception_check)
(android_exception_check_1, android_exception_check_2): Fix
punctuation in warning message.
(android_exception_check_nonnull_1): New function.
* src/android.h: Update prototypes.
* src/androidselect.c (struct android_emacs_clipboard): New
methods.
(android_init_emacs_clipboard): Initialize new methods.
(Fandroid_get_clipboard_targets, android_xfree_inside)
(Fandroid_get_clipboard_data): New functions.
(syms_of_androidselect): Define new subrs.
2023-04-06 09:56:23 +08:00
Po Lu
458c6e5c91 Merge remote-tracking branch 'origin/master' into feature/android 2023-04-05 07:58:05 +08:00
Po Lu
fb87f7a905 ; * lisp/subr.el (read-char-from-minibuffer): Fix typo. 2023-04-04 18:35:11 +08:00
Po Lu
6bdbb4cbfc Update Android port
* lisp/subr.el (read-char-from-minibuffer): Don't use undefined
variable.  Reported by Robert Pluim.
2023-04-04 18:34:44 +08:00
Po Lu
76a8347e43 Merge remote-tracking branch 'origin/master' into feature/android 2023-04-04 07:49:48 +08:00
Po Lu
4a7facac1b Merge remote-tracking branch 'origin/master' into feature/android 2023-04-03 18:39:10 +08:00
Po Lu
add40ccfb9 ; ; * src/androidselect.c (Fandroid_clipboard_exists_p): Add check. 2023-04-03 18:24:02 +08:00
Po Lu
0e0ea976ca Update Android port
* src/sfnt.c (sfnt_normalize_vector): Don't rely on undefined
sign extension semantics.
2023-04-03 10:23:33 +08:00
Po Lu
8bca62d552 Merge remote-tracking branch 'origin/master' into feature/android 2023-04-03 08:12:03 +08:00
Po Lu
1d84b4b286 Merge remote-tracking branch 'origin/master' into feature/android 2023-04-02 09:11:00 +08:00
Po Lu
aeac57fbbd Merge remote-tracking branch 'origin/master' into feature/android 2023-04-01 14:26:45 +08:00
Po Lu
ca53e2bfbc Merge remote-tracking branch 'origin/master' into feature/android 2023-04-01 14:25:00 +08:00
Po Lu
05f8fe3ae3 Merge remote-tracking branch 'origin/master' into feature/android 2023-04-01 08:57:39 +08:00
Po Lu
ab3ef576b4 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-31 09:14:17 +08:00
Po Lu
956cb8ca65 Tweak outline cache stuff
* src/sfntfont.c: Adjust font cache size constants.
2023-03-30 13:04:24 +08:00
Po Lu
8bf461bd36 ; * src/sfnt.c (GETINFO): Fix typo. 2023-03-30 11:25:15 +08:00
Po Lu
8719ad534b ; * src/sfnt.h: Fix typo. 2023-03-30 11:22:11 +08:00
Po Lu
89a30637b3 Update Android port
* src/sfnt.c (sfnt_make_interpreter): New argument `fvar'.  Set
axis count.
(SCANCTRL): Implement selector bit 8.
(GXAXIS): New instruction.
(SFVTPV): Validate graphics state after changing freedom vector.
(sfnt_line_to_vector): Implement `original'.
(sfnt_move): Remove redundant division.
(sfnt_interpret_run): Implement distortable font related GXAXIS
instruction (0x91).
(sfnt_vary_interpreter): Set naxis and norm_coords.
(sfnt_make_test_interpreter, pushb_test_args, pushw_test_args)
(sfnt_name_instruction, main): Adjust accordingly.
* src/sfnt.h (struct sfnt_interpreter, PROTOTYPE):
* src/sfntfont.c (sfntfont_setup_interpreter, sfntfont_open):
Set up distortion information.
2023-03-30 11:18:51 +08:00
Po Lu
804b76ba8d Merge remote-tracking branch 'origin/master' into feature/android 2023-03-30 09:14:02 +08:00
Po Lu
219bfea874 Improve rules for enumerating user fonts
* doc/emacs/android.texi (Android Fonts): Document distortable
font replacement rules.
* src/sfntfont.c (sfnt_replace_fonts_p): New function.
(sfnt_enum_font_1): Call it.
2023-03-29 20:14:43 +08:00
Po Lu
2686a55aa1 Fix optimized move functions
* src/sfnt.c (sfnt_move_x):
(sfnt_move_y):
(sfnt_move): Set N flags and don't forget to
set N points too.
2023-03-29 14:50:55 +08:00
Po Lu
fa6ac5ed1c ; * src/sfnt.c (sfnt_read_avar_table): Fix sequencing problem. 2023-03-29 13:45:18 +08:00
Po Lu
2dc037e4a8 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-29 13:24:34 +08:00
Po Lu
279efc6cc2 Update Android port
* src/sfntfont.c (sfntfont_setup_interpreter): Don't create
interpreter for blatently broken fonts.
2023-03-29 13:23:32 +08:00
Po Lu
67da02444e Update Android port
* src/sfntfont.c (sfntfont_open): Avoid specifying redundant
blends.
2023-03-29 09:44:45 +08:00
Po Lu
13e1fb4c3f Merge remote-tracking branch 'origin/master' into feature/android 2023-03-29 08:42:19 +08:00
Po Lu
af6af86d08 Update Android port
* src/sfnt.c (sfnt_validate_gs): Fix validation of projection
vector.
2023-03-29 08:33:43 +08:00
Po Lu
f92413a796 Update Android port
* src/sfnt.c (sfnt_vary_compound_glyph):
* src/sfntfont.c (sfntfont_get_glyph)
(sfntfont_get_glyph_outline): Avoid clobbering offset size flag
when varying compound glyph.
2023-03-28 19:21:06 +08:00
Po Lu
bf28a372ab Update Android port
* src/sfnt.c (sfnt_vary_simple_glyph, sfnt_vary_compound_glyph):
Fix application of intermediate tuples.
* src/sfntfont.c (sfntfont_open): Set xlfd name after applying
distortion.
2023-03-28 16:34:50 +08:00
Po Lu
2826287b1a Correctly round lbearing values
* src/sfnt.h (SFNT_ROUND_FIXED):
* src/sfntfont.c (sfntfont_probe_widths):
(sfntfont_measure_pcm): Round lbearing properly.
2023-03-28 13:39:10 +08:00
Po Lu
b3d100734b Update Android port
* src/sfntfont.c (sfnt_open_tables): Fix typos in non-HarfBuzz
code.
2023-03-28 12:03:47 +08:00
Po Lu
64206ee3af Merge remote-tracking branch 'origin/master' into feature/android 2023-03-28 09:41:22 +08:00
Po Lu
05f3f9c1c0 Update Android port
* src/androidterm.c (android_draw_image_glyph_string): Restore
potentially clobbered GC clipping.
* src/sfnt.c (sfnt_large_integer_add, sfnt_multiply_divide_round)
(sfnt_mul_fixed_round): New functions.
(sfnt_build_glyph_outline): Take unscaled glyph metrics.
(sfnt_prepare_raster, sfnt_vary_simple_glyph)
(sfnt_vary_compound_glyph, sfnt_vary_interpreter): Use rounding
multiplication to scale deltas.
(main): Adjust tests.
* src/sfntfont.c (sfntfont_get_glyph_outline)
(sfntfont_probe_widths, sfntfont_open, sfntfont_measure_pcm)
(sfntfont_draw): More minor fixes to variable fonts.
2023-03-28 09:41:01 +08:00
Po Lu
ee9c0a482c Update Android port
* src/sfnt.c (sfnt_normalize_blend): Don't crash when axis
variations are not present.
2023-03-27 18:22:23 +08:00
Po Lu
54d79f37ae Merge remote-tracking branch 'origin/master' into feature/android 2023-03-27 16:43:07 +08:00
Po Lu
dd4924ca90 Update Android port
* configure.ac (HAVE_OTF_GET_VARIATION_GLYPHS): Check for
`hb_font_set_var_named_instance'.
* src/sfnt.c (main): Update tests.
* src/sfntfont-android.c (Fandroid_enumerate_fonts): Blacklist
bad font.
* src/sfntfont.c (struct sfnt_font_tables, struct sfnt_font_desc)
(sfnt_decode_instance_name, sfnt_weight_descriptions)
(sfnt_enum_font_1, sfntfont_list_1, sfntfont_desc_to_entity)
(sfntfont_list, struct sfntfont_get_glyph_outline_dcontext)
(sfntfont_get_glyph, sfntfont_get_glyph_outline)
(struct sfnt_font_info, sfnt_close_tables, sfnt_open_tables)
(sfntfont_open, sfntfont_measure_pcm, sfntfont_close)
(sfntfont_draw, sfntfont_begin_hb_font, syms_of_sfntfont)
(mark_sfntfont): Handle variable fonts correctly.
2023-03-27 16:42:52 +08:00
Po Lu
18b34e9ca0 Refactor sfntfont.c
* src/sfnt.c (sfnt_build_glyph_outline): Take scale, not head
and pixel size.
(sfnt_scale_metrics_to_pixel_size): Delete function.
(sfnt_get_scale): New function.
(main): Update tests.
* src/sfnt.h (PROTOTYPE): Update prototypes.
* src/sfntfont.c (struct sfnt_outline_cache)
(sfntfont_get_glyph_outline, struct sfnt_font_info)
(sfntfont_open): Save scale in font information and use it.
(sfntfont_measure_instructed_pcm): Delete function.
(sfntfont_measure_pcm): Make this the only ``measure pcm''
function.
(sfntfont_draw): Rely on sfntfont_get_glyph_outline for the
scale.
2023-03-27 11:24:05 +08:00
Po Lu
67a325243c Refactor sfntfont.c
* src/sfntfont.c (struct sfnt_font_tables): New structure.
(struct sfnt_font_desc): New field `tables'.
(struct sfnt_font_info): New field `desc'.
(sfntfont_setup_interpreter): Drop fd arguments and don't try to
load interpreter tables.
(sfnt_open_tables, sfnt_close_tables): New functions.
(sfnt_reference_font_tables, sfnt_dereference_font_tables): New
functions.
(sfntfont_open, sfntfont_close): Implement in terms of those
functions in order to share tables.
2023-03-27 09:58:42 +08:00
Po Lu
a1c5461eda Merge remote-tracking branch 'origin/master' into feature/android 2023-03-26 14:09:56 +08:00
Po Lu
c0873f2382 Update Android port
* src/sfnt.c (sfnt_table_names): Add avar.
(sfnt_read_glyph): Clear distortion fields.
(sfnt_build_glyph_outline): Calculate the outline origin point.
(sfnt_prepare_raster): Apply the origin point to the X axis
offset.
(sfnt_scale_metrics_to_pixel_size): New function.
(sfnt_build_instructed_outline): Use instructed origin phantom
point to determine the outline origin.
(sfnt_compute_phantom_points): Apply origin and advance
distortion.
(struct sfnt_variation_axis, struct sfnt_instance)
(struct sfnt_fvar_table, sfnt_read_fvar_table)
(struct sfnt_gvar_table, sfnt_read_gvar_table)
(sfnt_read_avar_table, struct sfnt_blend, sfnt_init_blend)
(sfnt_free_blend, sfnt_normalize_blend, struct sfnt_tuple_header)
(struct sfnt_gvar_glyph_header, sfnt_read_packed_deltas)
(sfnt_compute_tuple_scale, sfnt_read_cvar_table)
(sfnt_infer_deltas_1, sfnt_vary_simple_glyph, sfnt_infer_deltas)
(sfnt_vary_glyph, sfnt_vary_compound_glyph)
(sfnt_vary_interpreter): New functions.  Add structs to
sfntfont.h.
(struct sfnt_test_dcontext, sfnt_test_get_glyph, main): Test
distortable font handling.

* src/sfnt.h (SFNT_ENABLE_HINTING):
(enum sfnt_table):
(struct sfnt_glyph):
(struct sfnt_glyph_outline):
(struct sfnt_raster):
(struct sfnt_default_uvs_table):
(struct sfnt_unicode_value_range):
(struct sfnt_nondefault_uvs_table):
(struct sfnt_uvs_mapping):
(struct sfnt_mapped_variation_selector_record):
(struct sfnt_table_offset_rec):
(struct sfnt_uvs_context):
(struct sfnt_mapped_table):
(struct sfnt_variation_axis):
(struct sfnt_instance):
(struct sfnt_fvar_table):
(struct sfnt_short_frac_correspondence):
(struct sfnt_short_frac_segment):
(struct sfnt_avar_table):
(struct sfnt_tuple_variation):
(struct sfnt_cvar_table):
(struct sfnt_gvar_table):
(struct sfnt_blend):
(struct sfnt_metrics_distortion):
(PROTOTYPE): Update prototypes.

* src/sfntfont.c (sfntfont_get_glyph_outline):
(sfntfont_measure_pcm): Adjust calls.
2023-03-26 14:09:15 +08:00
Po Lu
d7457e1ce4 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-24 10:46:14 +08:00
Po Lu
b78ef9bcd1 Update Android port
* src/sfnt.c (sfnt_table_names): Add fvar, gvar, cvar.
(sfnt_read_maxp_table): Call xmalloc, not malloc.
(sfnt_read_simple_glyph): Avoid use-after-free if simple is
invalid.
(sfnt_fill_span): Fix max coverage.
(sfnt_normalize_vector): Fail if magnitude is zero.
(sfnt_measure_distance): Fix opcode order.
(sfnt_dot_fix_14): Fix implementation.
(struct sfnt_variation_axis, struct sfnt_instance)
(struct sfnt_fvar_table, struct sfnt_gvar_table)
(sfnt_read_fvar_table, sfnt_read_gvar_table, struct sfnt_blend)
(sfnt_init_blend, sfnt_free_blend, sfnt_normalize_blend)
(struct sfnt_tuple_header, struct sfnt_gvar_glyph_header)
(sfnt_read_packed_points, sfnt_read_packed_deltas)
(sfnt_compute_tuple_scale, sfnt_infer_deltas_1, sfnt_infer_deltas)
(sfnt_vary_glyph): Add WIP variation glyph implementation.
* src/sfnt.h (enum sfnt_table, struct sfnt_simple_glyph):
Likewise.
2023-03-24 10:43:34 +08:00
Po Lu
b26b4c537b ; * java/INSTALL: Fix typo. 2023-03-20 15:37:11 +08:00
Po Lu
a7902e9d80 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-20 14:48:13 +08:00
Po Lu
6bd1cfa24f Update Android port
* configure.ac: Add support for HarfBuzz on Android.
* java/INSTALL: Document where to get Emacs with HarfBuzz.
* lisp/subr.el (overriding-text-conversion-style, y-or-n-p):
Correctly set text conversion style if y-or-n-p is called inside
the minibuffer.
* src/sfnt.c (sfnt_read_cmap_format_8)
(sfnt_read_cmap_format_12): Fix typos.
(sfnt_read_24, sfnt_read_cmap_format_14): New function.
(sfnt_read_cmap_table_1, sfnt_read_cmap_table): Handle format 14
cmap tables.
(sfnt_read_default_uvs_table, sfnt_read_nondefault_uvs_table)
(sfnt_compare_table_offsets, sfnt_create_uvs_context)
(sfnt_free_uvs_context, sfnt_compare_uvs_mapping)
(sfnt_variation_glyph_for_char, sfnt_map_table, sfnt_unmap_table)
(sfnt_read_table, sfnt_test_uvs): New functions.
(main): Add UVS tests.
* src/sfnt.h (struct sfnt_cmap_format_14)
(struct sfnt_variation_selector_record)
(struct sfnt_default_uvs_table, struct sfnt_unicode_value_range)
(struct sfnt_nondefault_uvs_table, struct sfnt_uvs_mapping)
(struct sfnt_mapped_variation_selector_record)
(struct sfnt_table_offset_rec, struct sfnt_uvs_context)
(struct sfnt_mapped_table): New structures.  Update prototypes.
* src/sfntfont-android.c (android_sfntfont_driver): Register
HarfBuzz callbacks where required.
* src/sfntfont.c (sfntfont_select_cmap): Look for a format 14
table.  Save it in new arg FORMAT14.
(sfntfont_read_cmap): Adjust accordingly.
(struct sfnt_font_info): New field `uvs'.  New fields `hb_font',
`fd' and `directory'.
(sfntfont_open): Open uvs context.  Under HarfBuzz, don't close
the fd or subtable, but save them in the font info instead.
(sfntfont_close): Free UVS context.  Close font fd and table
directory and HarfBuzz font.
(sfntfont_draw): Handle case where s->padding_p.
(sfntfont_get_variation_glyphs): New function.
(sfntfont_unmap_blob, sfntfont_get_font_table)
(sfntfont_begin_hb_font): New functions.
* src/sfntfont.h: Update prototypes.
* src/textconv.c (Fset_text_conversion_style): Fix doc string.
2023-03-20 14:47:39 +08:00
Po Lu
739558c369 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-19 09:07:29 +08:00
Po Lu
f3dd887d18 Update Android port
* java/org/gnu/emacs/EmacsView.java (onAttachedToWindow): Send
measured width and height in exposures again.
2023-03-18 20:05:38 +08:00
Po Lu
84ffda4be5 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-18 15:31:31 +08:00
Po Lu
90348dabbf Remove extraneous debugging code
* src/androidterm.c (handle_one_android_event): Don't log expose
events.
2023-03-18 13:07:59 +08:00
Po Lu
6d28b596a9 Work around pselect lossage on Android
* src/android.c (android_run_select_thread): New flag.  Use it
rather than the rc of pselect and errno to determine whether or
not it has been interrupted.
(android_handle_sigusr1): Set said flag.
2023-03-18 11:59:17 +08:00
Po Lu
634e3fcc20 Update Android port
* java/org/gnu/emacs/EmacsView.java (EmacsView)
(prepareForLayout): New function.  Call this prior to mapping
the view.
(onGlobalLayout): New function.  Register as global layout
listener.
* java/org/gnu/emacs/EmacsWindow.java (EmacsWindow)
(notifyContentRectPosition): New function.  Use specified
xPosition and yPosition when reporting the offsets of children
of the root window.
* java/org/gnu/emacs/EmacsWindowAttachmentManager.java
(registerWindow): Specify activity launch bounds if necessary.
* src/androidterm.c (handle_one_android_event): Send
MOVE_FRAME_EVENT where necessary.
2023-03-18 10:54:26 +08:00
Po Lu
773bdb15ab Merge remote-tracking branch 'origin/master' into feature/android 2023-03-17 21:39:28 +08:00
Po Lu
9d1285883c Include more information in Android bug reports
* src/androidfns.c (Fx_server_vendor, Fx_server_version): New
functions.
(syms_of_androidfns): Define new functions.
* src/androidterm.c (android_set_build_fingerprint)
(syms_of_androidterm): Set new variable
Vandroid_build_manufacturer.
* src/xfns.c (Fx_server_vendor, Fx_server_version): Update doc
strings.
2023-03-17 21:39:15 +08:00
Po Lu
6e83b72706 Fix WINDOWSNT build of fileio.c and image.c
* src/fileio.c (emacs_fd_to_int): Don't define on WINDOWSNT.
* src/image.c (image_create_bitmap_from_data): Don't abort if
!defined HAVE_ANDROID.
2023-03-17 21:21:01 +08:00
Po Lu
e7025ed689 Update Android port
* configure.ac:
* m4/ndk-build.m4 (ndk_INIT):
(ndk_LATE): Avoid AC_REQUIRE magic.
2023-03-17 19:26:16 +08:00
Po Lu
2d666daaa3 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-17 15:05:45 +08:00
Po Lu
45b5c9b8b7 Improve radio button appearance in Android menus
* java/org/gnu/emacs/EmacsContextMenu.java (EmacsContextMenu):
New field `lastGroupId'.
(Item): New field `isRadio'.
(addItem): New arg `isRadio'.
(inflateMenuItems): Apply an empty radio button group if
required.
* src/androidmenu.c (android_init_emacs_context_menu): Adjust
accordingly.
(android_menu_show): Likewise.
2023-03-17 13:10:23 +08:00
Po Lu
da660a1ffa Update Android port
* java/org/gnu/emacs/EmacsView.java (cancelPopupMenu): Dismiss
context menu correctly.
(isOpaque): New function.
* java/org/gnu/emacs/EmacsWindowAttachmentManager.java: Make
consumer list public.
2023-03-17 10:38:09 +08:00
Po Lu
b37bb4279c ; * configure.ac: Add missing precious variable. 2023-03-17 10:03:43 +08:00
Po Lu
3702389a50 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-16 19:56:25 +08:00
Po Lu
584eeb24eb Update Android port
* lisp/frame.el (android-detect-mouse):
* lisp/term/android-win.el (android-get-connection): Add
function declarations.
2023-03-16 18:34:53 +08:00
Po Lu
34e9f7a0ee ; * configure.ac: Remove unnecessary escape. 2023-03-16 15:48:26 +08:00
Po Lu
e38758aaf4 Make ANDROID_CC and SDK_BUILD_TOOLS precious variables
* configure.ac (AUTO_DEPEND, ANDROID_STUBIFY, ANDROID_LDFLAGS):
* lib/Makefile.in (ANDROID_CFLAGS, ANDROID_BUILD_CFLAGS)
(ALL_CFLAGS):
* lib/gnulib.mk.in (AM_DEFAULT_VERBOSITY):
* msdos/sed1v2.inp:
* msdos/sedlibmk.inp:
* src/Makefile.in (ANDROID_OBJ, EMACS_CFLAGS): Make those
variables precious.  Rename ANDROID_CFLAGS substitution to
ANDROID_BUILD_CFLAGS.
2023-03-16 15:46:39 +08:00
Po Lu
5bdbfba4fc Update Android port
* nt/mingw-cfg.site: Suppress build of gnulib printf.
2023-03-16 15:23:21 +08:00
Po Lu
ce66228ac5 Update Android port
* java/org/gnu/emacs/EmacsDocumentsProvider.java (queryRoots): Add
icon to document root.
2023-03-16 14:13:21 +08:00
Po Lu
d04731b588 Update Android port
* lisp/loadup.el (current-load-list): Set to empty load list
after startup.
* src/lread.c (build_load_history): Revert earlier changes.
2023-03-16 09:40:02 +08:00
Po Lu
9a4a7de914 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-16 08:40:35 +08:00
Po Lu
4e9e72ea48 Update Android port
* configure.ac: Improve portability.
2023-03-15 21:17:34 +08:00
Po Lu
3504c7550d Merge remote-tracking branch 'origin/master' into feature/android 2023-03-15 18:28:05 +08:00
Robert Pluim
f57c64925b Fix typos in Android port
* src/fileio.c (Finsert_file_contents):
* src/window.c (replace_buffer_in_windows): Call Fboundp, not
boundp.
2023-03-15 18:27:29 +08:00
Po Lu
af7f0b6f9b Update Android port
* cross/Makefile.in (lib/gnulib.mk): Edit out
build-aux stuff.
* m4/ndk-build.m4: Also look for cross ranlib.
2023-03-15 16:17:32 +08:00
Po Lu
4e05371fd1 ; * src/sfntfont.c (sfntfont_close): Fix warning w/o mmap. 2023-03-15 15:57:59 +08:00
Po Lu
8fbac937fb Port to systems without endian.h
* lib-src/asset-directory-tool.c (main_2): Port to systems
without htole32.
2023-03-15 15:38:19 +08:00
Po Lu
5b9d6738d1 Update Android port
* configure.ac (XCONFIGURE): Disable NS.
* cross/Makefile.in (lib-src/config.h):

(lib/libgnu.a):
(src/android-emacs): Port sed invocation to Mac OS without GNU
sed.
2023-03-15 15:07:29 +08:00
Po Lu
c74bab6067 Update Android port
* doc/lispref/commands.texi (Misc Events): Document variable
`disable-inhibit-text-conversion'.
* java/org/gnu/emacs/EmacsDialog.java (display1): Try an
activity that is certain to be focused first.
* lisp/touch-screen.el (touch-screen-track-tap)
(touch-screen-track-drag): Bind
`disable-inhibit-text-conversion'.
* src/keyboard.c (read_key_sequence): Only disable text
conversion if an actual function or numeric key is found in the
key sequence.
(syms_of_keyboard): New variable
`disable-inhibit-text-conversion'.
* src/lread.c (read_filtered_event): Check new variable.
* src/textconv.c (textconv_query): Remove unused label.
2023-03-15 09:46:01 +08:00
Po Lu
aec73dba8f Omit gnulib modules added by Android port on MinGW
* nt/gnulib-cfg.mk: Omit new gnulib modules.
2023-03-15 08:20:59 +08:00
Po Lu
a39ca9bf8e Update Android port
* lisp/minibuffer.el (minibuffer-setup-on-screen-keyboard):
Handle cases where last-event-frame is a kbd macro.
* src/keyboard.c (lispy_function_keys): Remove duplicates.
2023-03-14 19:51:42 +08:00
Po Lu
aa24854e7f Fix the MS-DOS build
* msdos/sed1v2.inp:
* msdos/sed3v2.inp:
* msdos/sedlibcf.inp:
* msdos/sedlibmk.inp: Update for Android port and new Gnulib
modules.
2023-03-14 15:14:38 +08:00
Po Lu
d6bddca26c Update Android port
* java/org/gnu/emacs/EmacsWindow.java (figureChange): Detect
mice on up events as well.
(onSomeKindOfMotionEvent): Work past framework bug.
* src/androidterm.c (android_perform_conversion_query):
* src/textconv.c (textconv_query):
* src/textconv.h (TEXTCONV_SKIP_ACTIVE_REGION): Remove unused
code.
2023-03-14 13:19:01 +08:00
Po Lu
5964051fce Update Android port
* doc/emacs/android.texi (Android Windowing): Document how to
display dialogs when Emacs is in the background.
* java/org/gnu/emacs/EmacsDialog.java (display1): Use system
dialogs if possible.
2023-03-14 09:48:02 +08:00
Po Lu
e0417a4577 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-14 09:01:48 +08:00
Po Lu
d31f557d4c Update Android port
* etc/NEWS: Announce new option.
* lisp/menu-bar.el (menu-bar-close-window): New option.
(kill-this-buffer):
(kill-this-buffer-enabled-p): Adjust accordingly.
* src/keyboard.c (lispy_function_keys): Add more silly
keys.
2023-03-13 20:39:29 +08:00
Po Lu
e6186b6a2a Update Android port
* src/android.c (android_check_string, android_build_string):
Reduce consing when building menu bar strings.
2023-03-13 18:31:30 +08:00
Po Lu
d3bb4b6687 ; * etc/MACHINES (Android): Update with more recent information. 2023-03-13 15:53:39 +08:00
Po Lu
b776feb7f2 Update Android port
* doc/emacs/android.texi (Android Startup): Document changes to
emacsclient wrapper.
* java/org/gnu/emacs/EmacsOpenActivity.java (EmacsOpenActivity)
(startEmacsClient): Open EmacsActivity if the service is not
running.
* java/org/gnu/emacs/EmacsService.java (onCreate):
* java/org/gnu/emacs/EmacsThread.java (EmacsThread, run): Pass
any file to open to Emacs.
* lisp/term/android-win.el (handle-args-function): Implement.
2023-03-13 13:25:02 +08:00
Po Lu
c3524b15aa Update Android port
* src/image.c (image_create_bitmap_from_file, image_find_image_fd)
(close_android_fd, slurp_file): Return and use `struct
android_fd_or_asset' on Android.
(xbm_load, xpm_load, pbm_load, png_load_body, jpeg_load_body)
(webp_load, svg_load): Adjust accordingly.
2023-03-13 09:58:52 +08:00
Po Lu
a517c24697 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-13 07:52:08 +08:00
Po Lu
08a3749794 Update Android port
* src/android.c (android_get_screen_width):
(android_get_screen_height):
(android_get_mm_width):
(android_get_mm_height):
(android_detect_mouse): Correctly handle Java exceptions.
2023-03-12 20:53:34 +08:00
Po Lu
90c22cb949 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-12 19:37:00 +08:00
Po Lu
776f1ca3e3 Update Android port
* src/android.c (android_check_if_event):
* src/androidgui.h: New function.
* src/androidterm.c (android_event_is_for_frame): New function.
(android_reset_conversion): Free and unqueue all text conversion
events for the given frame.
2023-03-12 19:36:09 +08:00
Po Lu
82b4b9e869 Update Android port
* src/androidterm.c (NATIVE_NAME, JNICALL)
(android_build_extracted_text, android_update_selection): Use
0-based indices for Android buffer positions.  Also, report
surrounding text relative to the region, not to the cursor.
* src/textconv.c (textconv_query): Accept new values of
position.
(really_set_composing_text): Use ephemeral last point.
2023-03-12 17:07:57 +08:00
Po Lu
3573db24ad Merge remote-tracking branch 'origin/master' into feature/android 2023-03-12 15:43:56 +08:00
Po Lu
a17380e80d Update Android port
* java/org/gnu/emacs/EmacsOpenActivity.java (EmacsOpenActivity)
(onCancel): New function.
(displayFailureDialog): Handle dialog cancellation.
* src/sfntfont.c (sfnt_parse_languages): Look for SLNG tag if
DLNG is not present.
2023-03-12 15:43:14 +08:00
Po Lu
b0abc50218 Add Super modifier support to Android port
* src/androidgui.h (enum android_modifier_mask): New modifier
ANDROID_SUPER_MASK.
* src/androidterm.c (android_android_to_emacs_modifiers)
(android_emacs_to_android_modifiers): Add new modifier.
2023-03-12 11:06:47 +08:00
Po Lu
5c2fee0c25 Fix crash during androidterm init
* src/androidterm.c (syms_of_androidterm): Initialize
Vandroid_build_fingerprint in case GC happens.
2023-03-12 10:45:26 +08:00
Po Lu
7971b533a2 ; * src/emacs-module.c (module_reset_handlerlist): Fix macro conflict. 2023-03-12 10:39:56 +08:00
Po Lu
6c68d9bd3a Clean up emacs-module.c
* src/emacs-module.c (MODULE_HANDLE_NONLOCAL_EXIT)
(module_make_global_ref, module_free_global_ref)
(module_make_function, module_get_function_finalizer)
(module_set_function_finalizer, module_make_interactive)
(module_funcall, module_intern, module_type_of)
(module_extract_integer, module_make_integer, module_extract_float)
(module_make_float, module_copy_string_contents)
(module_make_string, module_make_unibyte_string)
(module_make_user_ptr, module_get_user_ptr, module_set_user_ptr)
(module_get_user_finalizer, module_set_user_finalizer)
(module_vec_set, module_vec_get, module_vec_size)
(module_process_input, module_extract_time, module_make_time)
(module_extract_big_integer, module_make_big_integer)
(module_open_channel, module_reset_handlerlist): Adjust as
recommended by Paul Eggert <eggert@cs.ucla.edu>.
2023-03-12 10:37:18 +08:00
Po Lu
b83324d1bd Update Android port
* configure.ac: Take option `--with-shared-user-id' and give it
to AndroidManifest.xml.in.
* java/AndroidManifest.xml.in: Substitute that into the
application info.
* java/INSTALL (BUILDING WITH A SHARED USER ID): New section.
2023-03-12 09:53:41 +08:00
Po Lu
26640b7a4f Merge remote-tracking branch 'origin/master' into feature/android 2023-03-11 19:08:24 +08:00
Po Lu
a697ca5562 Improve default value of `with_mailutils' on Android
* configure.ac: Default to off on Android.
2023-03-11 18:58:18 +08:00
Po Lu
b931a92ac4 ; * configure.ac: Fix typo. 2023-03-11 17:43:15 +08:00
Po Lu
c4b77b82de Update Android port
* configure.ac (HAVE_MAILUTILS, with_mailutils)
(ANDROID_SDK_8_OR_EARLIER, XCONFIGURE): Fix POP and mailutils
configuration on Android.
* java/Makefile.in:
* src/callproc.c (syms_of_callproc): Avoid using built-in
movemail when --with-mailutils.
2023-03-11 17:42:24 +08:00
Po Lu
78faad6330 Update Android port
* src/android.c (android_resolve_handle)
(android_resolve_handle2): Don't perform checking done by
CheckJNI by default.
(android_copy_area): Check for errors here because CopyArea can
perform a lot of consing.
(android_define_cursor): Remove redundant code.
2023-03-11 15:56:53 +08:00
Po Lu
4a328b8578 Fix problems with the menu bar on large screen Android devices
* java/org/gnu/emacs/EmacsActivity.java (onContextMenuClosed):
Process submenu closing normally if it happens more than 300 ms
after a submenu item was selected.
* java/org/gnu/emacs/EmacsContextMenu.java (EmacsContextMenu)
(onMenuItemClick, display1): Give `wasSubmenuSelected' different
values depending on how the submenu was selected.
2023-03-11 11:35:59 +08:00
Po Lu
98c7825f5d ; * lib/gnulib.mk.in: Update from gnulib. 2023-03-11 09:58:01 +08:00
Po Lu
f573ce3f66 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-11 09:55:05 +08:00
Po Lu
248b345961 Don't use GCC extensions in src/emacs-module.c
* configure.ac: Default modules to on.  Remove check for
__attribute__((cleanup)).  However, keep the new `ifavailable'
value for systems without dlopen.

* src/emacs-module.c (MODULE_HANDLE_NONLOCAL_EXIT): Don't rely
on cleanup attribute and correctly reset handlerlist upon
longjmp.
(MODULE_INTERNAL_CLEANUP): New macro.
(module_make_global_ref, module_free_global_ref)
(module_make_function, module_get_function_finalizer)
(module_set_function_finalizer, module_make_interactive)
(module_funcall, module_intern, module_type_of)
(module_extract_integer, module_make_integer, module_extract_float)
(module_make_float, module_copy_string_contents)
(module_make_string, module_make_unibyte_string)
(module_make_user_ptr, module_get_user_ptr, module_set_user_ptr)
(module_get_user_finalizer, module_set_user_finalizer)
(module_vec_set, module_vec_get, module_vec_size)
(module_process_input, module_extract_time, module_make_time)
(module_extract_big_integer, module_make_big_integer)
(module_open_channel): Call MODULE_INTERNAL_CLEANUP prior to
returning.
2023-03-11 09:53:24 +08:00
Po Lu
e9a879260d Implement hourglass cursor on Android
* lisp/term/android-win.el (x-pointer-arrow, x-pointer-left-ptr)
(x-pointer-left-side, x-pointer-sb-h-double-arrow)
(x-pointer-sb-v-double-arrow, x-pointer-watch, x-pointer-xterm)
(x-pointer-invisible): New constants.
* src/androidterm.c (android_show_hourglass)
(android_hide_hourglass): New functions.
(android_toggle_visible_pointer, android_define_frame_cursor):
Define or don't define hourglass cursor if x->hourglass.
(android_redisplay_interface): Add new functions.
* src/androidterm.h (struct android_output): New field
`hourglass'.
2023-03-11 08:34:57 +08:00
Po Lu
769a4e7ff5 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-11 07:53:45 +08:00
Po Lu
1eb546309b Update Android port
* doc/emacs/android.texi (Android Windowing): Document how to
pass multimedia keys to the system.
* java/org/gnu/emacs/EmacsNative.java (EmacsNative): New
function.
* java/org/gnu/emacs/EmacsView.java (onKeyDown, onKeyMultiple)
(onKeyUp): Check that function.
* java/org/gnu/emacs/EmacsWindow.java (defineCursor): Handle
cases where cursor is NULL.
* src/android.c (NATIVE_NAME): New function.
* src/androidfns.c (syms_of_androidfns): New variable.
* src/keyboard.c (lispy_function_keys): Add volume keys.
2023-03-10 19:13:22 +08:00
Po Lu
98d43dbef5 * java/org/gnu/emacs/EmacsCursor.java: New file. 2023-03-10 15:16:13 +08:00
Po Lu
ae5513ede5 Implement mouse cursors on Android 7.0 and later
* java/org/gnu/emacs/EmacsWindow.java (defineCursor): New
function.
* src/android.c (struct android_emacs_cursor): New struct.
(android_init_emacs_cursor): New function.
(JNICALL): Call it.
(android_create_font_cursor, android_define_cursor)
(android_free_cursor): New functions.
* src/android.h (enum android_handle_type): Add cursor handle
type.
* src/androidfns.c (Fx_create_frame, android_create_tip_frame)
(enum mouse_cursor, struct mouse_cursor_types, mouse_cursor_types)
(struct mouse_cursor_data, android_set_mouse_color)
(syms_of_androidfns):
* src/androidgui.h (enum android_cursor_shape):
* src/androidterm.c (make_invisible_cursor)
(android_toggle_invisible_pointer, android_free_frame_resources)
(android_define_frame_cursor):
* src/androidterm.h (struct android_display_info)
(struct android_output): Port mouse cursor code over from X.
2023-03-10 15:16:05 +08:00
Po Lu
a7c8ae7d67 ; * java/org/gnu/emacs/EmacsNative.java: Add missing dependency. 2023-03-10 11:39:30 +08:00
Po Lu
417e0539cf Avoid using Linux sysfs APIs to access battery state on Android
* lisp/battery.el (battery-status-function): Don't look for /sys,
/proc* on Android.  Explain why.
2023-03-10 10:02:36 +08:00
Po Lu
488a75f2e2 Port Android battery status to Android 4.4 and earlier
* java/org/gnu/emacs/EmacsService.java (EmacsService)
(queryBattery19): New function.
(queryBattery): Call it on old systems.  Also, return AC line
status and temperature.
* lisp/battery.el (battery-android): Implement more format
directives.
* src/android.c (android_query_battery): Handle new status
fields.
* src/android.h (struct android_battery_state): Add `plugged'
and `temperature'.
* src/androidfns.c (Fandroid_query_battery): Return new fields.
2023-03-10 09:40:41 +08:00
Po Lu
4392423cb6 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-10 08:43:13 +08:00
Po Lu
f34d9fab89 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-09 19:57:06 +08:00
Po Lu
a7f0f9498f Update Android port
* src/android.c (android_destroy_handle): Handle OOM errors in
android_destroy_handle.
2023-03-09 19:42:13 +08:00
Po Lu
7e3c22536f ; * textconv.c: Remove out-of-date comment. 2023-03-09 19:05:24 +08:00
Po Lu
e859a14bee Fix menu and popup race conditions on Android
* java/org/gnu/emacs/EmacsActivity.java (onContextMenuClosed):
* java/org/gnu/emacs/EmacsContextMenu.java (EmacsContextMenu)
(onMenuItemClick, run):
* java/org/gnu/emacs/EmacsDialog.java (EmacsDialog, onClick)
(createDialog, onDismiss): Take menu event serial, and pass it
along in context menu events.
* java/org/gnu/emacs/EmacsNative.java (sendContextMenu): New
argument.
* src/android.c (sendContextMenu): Pass serial number in event.

* src/androidgui.h (struct android_menu_event): New field
`menu_event_serial'.
* src/androidmenu.c (FIND_METHOD_STATIC)
(android_init_emacs_context_menu): Adjust method declarations.
(android_menu_show, android_dialog_show):
* src/androidterm.c (handle_one_android_event): Expect serial in
context menu events.
* src/androidterm.h: Update prototypes.
2023-03-09 16:30:02 +08:00
Po Lu
745890de52 Fix webp test for Android
* configure.ac (HAVE_WEBP): Disable WebPGetInfo check when
REALLY_ANDROID.
2023-03-09 14:57:45 +08:00
Po Lu
c99354042a Merge remote-tracking branch 'origin/master' into feature/android 2023-03-09 14:53:37 +08:00
Po Lu
682a6542cd Update Android port
* java/debug.sh (is_root): Port to android versions which don't
support `chmod +x'.
* src/android.c (android_content_name_p): Disable before API
level 19.
2023-03-09 14:50:32 +08:00
Po Lu
dcc3c63c6e Update Android port
* java/org/gnu/emacs/EmacsContextMenu.java (EmacsContextMenu)
(addItem): New argument `tooltip'.
2023-03-09 11:27:00 +08:00
Po Lu
55634b5f79 Update Android port
* src/android.c (android_build_string): Convert the text to
UTF-16, and create the Java string using that.
(android_build_jstring): Update comment.
* src/androidmenu.c (android_init_emacs_context_menu): Add
String argument to `addItem'.
(android_menu_show): Correctly pass help strings in regular menu
items.
* src/sfnt.c (_sfnt_swap16, _sfnt_swap32): Avoid reserved names.
2023-03-09 10:50:03 +08:00
Po Lu
009d4cfc88 Fix crash upon restoring desktop
* src/android.c (android_set_input_focus): Don't call method on
window using service class.
2023-03-09 09:36:36 +08:00
Po Lu
ad678306c4 ; * src/sfnt.c (ODD): Use PUSH_UNCHECKED. 2023-03-09 09:33:22 +08:00
Po Lu
5e3bba2dbe Merge remote-tracking branch 'origin/master' into feature/android 2023-03-09 09:27:12 +08:00
Po Lu
1bf8fd61c5 Update Android port
* src/fileio.c (Fcopy_file): On Android, ignore ENOSYS and
ENOTSUP when restoring file times, as the system call used is
supported by many kernels.
2023-03-08 21:18:50 +08:00
Po Lu
c15f9aee2e Merge remote-tracking branch 'origin/master' into feature/android 2023-03-08 20:07:12 +08:00
Po Lu
f9e68ed00e Fix occasional crash
* src/androidterm.c (android_build_extracted_text): Return NULL
if text class not initialized.
(android_update_selection): Check that EXTRACTED is not NULL.
2023-03-08 20:06:41 +08:00
Po Lu
bb55528c7b Update Android port
* doc/emacs/android.texi (Android File System): Document what
`temp~unlinked' means in the temporary files directory.
* java/org/gnu/emacs/EmacsService.java (updateExtractedText):
New function.
* java/org/gnu/emacs/EmacsView.java (onCreateInputConnection):
Ask the input method nicely to not display the extracted text
UI.
* src/android.c (struct android_emacs_service): New method
`updateExtractedText'.
(android_hack_asset_fd_fallback): Improve naming convention.
Fix typo.
(android_init_emacs_service): Add new method.
(android_update_extracted_text): New function.
(android_open_asset): Fix typo.
* src/androidgui.h: Update prototypes.
* src/androidterm.c (struct android_get_extracted_text_context):
New field `flags'.
(android_get_extracted_text): Set flags on the frame's output
data.
(android_build_extracted_text): New function.
(getExtractedText): Move out class structures.
(android_update_selection): Send updates to extracted text if
the input method asked for them.
(android_reset_conversion): Clear extracted text flags.
* src/androidterm.h (struct android_output): New fields for
storing extracted text data.
2023-03-08 15:04:49 +08:00
Po Lu
fdff5442a5 Fix double free upon encountering invalid font
* src/sfnt.c (sfnt_read_cmap_table): Don't allocate too big
data.  Also, free elements of (*data), not offsets into data
itself.
2023-03-08 10:19:26 +08:00
Po Lu
06cfa27e37 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-08 08:29:31 +08:00
Po Lu
abe279cb17 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-07 20:18:15 +08:00
Po Lu
84d27fe53b Save build timestamps in Android builds
* java/Makefile.in (install_temp/assets/build_info): New
rule.:(emacs.apk-in): Depend on that file.
* lisp/version.el (android-read-build-system)
(android-read-build-time): New functions.
(emacs-build-system, emacs-build-time): Use those functions on
Android, as dumping is done after installation on Android.
* src/fileio.c (Finsert_file_contents):
* src/window.c (replace_buffer_in_windows): Don't call functions
if they are not defined, which can happen during loadup.
2023-03-07 20:18:02 +08:00
Po Lu
83c29bd40e Update Android port
* java/org/gnu/emacs/EmacsWindow.java (onSomeKindOfMotionEvent):
Dismiss splurious LeaveNotify events from button presses.
* src/android.c (android_change_window_attributes)
(android_change_gc, android_set_clip_rectangles)
(android_reparent_window, android_clear_window, android_map_window)
(android_unmap_window, android_resize_window, android_move_window)
(android_swap_buffers, android_fill_rectangle, android_copy_area)
(android_fill_polygon, android_draw_rectangle, android_draw_point)
(android_draw_line, android_clear_area, android_bell)
(android_set_input_focus, android_raise_window)
(android_lower_window, android_set_dont_focus_on_map)
(android_set_dont_accept_focus, android_get_keysym_name)
(android_toggle_on_screen_keyboard, android_restart_emacs)
(android_display_toast, android_update_ic, android_reset_ic)
(android_set_fullscreen): Optimize by specifying the class
explicitly when calling a method.
2023-03-07 16:49:45 +08:00
Po Lu
327c2658ac Merge remote-tracking branch 'origin/master' into feature/android 2023-03-07 15:25:28 +08:00
Po Lu
44cf1ed7e5 Update Android port
* src/lread.c (lread_fd, file_tell, infile, skip_dyn_bytes)
(skip_dyn_eof, readbyte_from_stdio, safe_to_load_version)
(close_infile_unwind, close_file_unwind_android_fd): New
function.
(Fload, Flocate_file_internal, openp): New argument PLATFORM.
All callers changed.
(skip_lazy_string): Add optimized versions of various functions
for accessing Android assets.
2023-03-07 14:20:50 +08:00
Po Lu
a11ad7149b Merge remote-tracking branch 'origin/master' into feature/android 2023-03-07 08:43:36 +08:00
Po Lu
7c8cc9a633 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-06 16:06:37 +08:00
Po Lu
c0a6f14f4a Update Android port
* java/org/gnu/emacs/EmacsNative.java (EmacsNative): New
function requestSelectionUpdate.
* java/org/gnu/emacs/EmacsView.java (onCreateInputConnection):
Call it instead of losing if getting the current selection
fails.
* src/android-asset.h (AAsset_seek): Define stub.
* src/android.c (android_open): Take mode_t.
(android_open_asset, android_close_asset, android_asset_read_quit)
(android_asset_read, android_asset_lseek, android_asset_fstat):
New functions.
* src/android.h (struct android_fd_or_asset): Update prototypes.
* src/androidgui.h (enum android_ime_operation): Add new
operation to update the selection position.
* src/androidterm.c (android_handle_ime_event): Handle new
operation.
(requestSelectionUpdate): New function.
* src/fileio.c (close_file_unwind_emacs_fd): New function.
(Fcopy_file, union read_non_regular, read_non_regular)
(Finsert_file_contents): Use optimized codepath to insert
Android asset files.
* src/frame.h (enum text_conversion_operation): New operation.
* src/textconv.c (really_request_point_update)
(handle_pending_conversion_events_1, request_point_update): New
functions.
* src/textconv.h: Update prototypes.
2023-03-06 15:30:29 +08:00
Po Lu
31883b8de1 * src/conf_post.h: Avoid macro redeclaration. 2023-03-06 11:46:19 +08:00
Po Lu
97ca0a8551 Update Android port
* java/org/gnu/emacs/EmacsService.java (sync): Delete function.
* java/org/gnu/emacs/EmacsView.java (handleDirtyBitmap): Erase
with window background.
(onDetachedFromWindow): Only recycle bitmap if non-NULL.
* java/org/gnu/emacs/EmacsWindow.java (background): New field.
(changeWindowBackground): Set it.
* src/android.c (struct android_emacs_service): Remove `sync'.
(android_init_emacs_service): Likewise.
(android_sync): Delete function.
* src/androidfns.c (android_create_tip_frame): Set frame
background color correctly.
(Fx_show_tip): Make the tip frame visible.
* src/androidgui.h: Update prototypes.
* src/androidterm.c (handle_one_android_event): Handle tooltip
movement correctly.
2023-03-06 11:25:51 +08:00
Po Lu
0dbbdd20f4 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-05 19:59:06 +08:00
Po Lu
1cae464859 Update Android port
* java/org/gnu/emacs/EmacsActivity.java (onCreate):
* java/org/gnu/emacs/EmacsContextMenu.java:
* java/org/gnu/emacs/EmacsDocumentsProvider.java (getMimeType):
* java/org/gnu/emacs/EmacsDrawLine.java (perform):
* java/org/gnu/emacs/EmacsDrawRectangle.java (perform):
* java/org/gnu/emacs/EmacsFillPolygon.java:
* java/org/gnu/emacs/EmacsFontDriver.java:
* java/org/gnu/emacs/EmacsHandleObject.java:
* java/org/gnu/emacs/EmacsInputConnection.java:
* java/org/gnu/emacs/EmacsMultitaskActivity.java
(EmacsMultitaskActivity):
* java/org/gnu/emacs/EmacsNative.java:
* java/org/gnu/emacs/EmacsNoninteractive.java
(EmacsNoninteractive, main):
* java/org/gnu/emacs/EmacsOpenActivity.java (EmacsOpenActivity)
(startEmacsClient):
* java/org/gnu/emacs/EmacsSdk7FontDriver.java:
* java/org/gnu/emacs/EmacsSdk8Clipboard.java:
* java/org/gnu/emacs/EmacsService.java (EmacsService, onCreate):
* java/org/gnu/emacs/EmacsView.java (EmacsView, onLayout):
* java/org/gnu/emacs/EmacsWindow.java (EmacsWindow):
* java/org/gnu/emacs/EmacsWindowAttachmentManager.java
(EmacsWindowAttachmentManager): Remove redundant includes.
Reorganize some functions around, remove duplicate `getLibDir'
functions, and remove unused local variables.
2023-03-05 19:58:28 +08:00
Po Lu
26b3b8433d Update Android port
* java/org/gnu/emacs/EmacsOpenActivity.java (onCreate): Don't
set the style here.
* java/res/values-v11/style.xml:
* java/res/values-v14/style.xml:
* java/res/values-v29/style.xml:
* java/res/values/style.xml: Define styles for the emacsclient
wrapper.
* src/keyboard.c (read_key_sequence): Don't disable text
conversion if use_mouse_menu or if a menu bar prefix key is
being displayed.
2023-03-05 15:55:24 +08:00
Po Lu
0760d5cc98 Update Android port
* etc/PROBLEMS: Document problem with default monospace font.
* src/fileio.c (check_mutable_filename): Check /content as well.
(Fcopy_file, Fdelete_directory_internal, Fdelete_file)
(Frename_file, Fadd_name_to_file, Fmake_symbolic_link)
(Fset_file_modes, Fset_file_times, Ffile_newer_than_file_p)
(write_region): Adjust accordingly.
(Fset_visited_file_modtime): Remove unnecessary restriction.
* src/filelock.c (make_lock_file_name): Don't interlock files
under /assets and /content.
* src/inotify.c (Finotify_add_watch): Fix typo.
2023-03-05 14:53:12 +08:00
Po Lu
e0f4002161 Fix cross compilation of cross/lib in some cases
* cross/Makefile.in: (config.status): Depend on
top_builddir/config.status instead.
2023-03-05 11:04:06 +08:00
Po Lu
7f288bf04a ; * configure.ac: Fix another typo. 2023-03-05 10:57:06 +08:00
Po Lu
bf66725034 ; * cross/Makefile.in (builddir): Define. 2023-03-05 10:42:41 +08:00
Po Lu
56d783cf9d ; * cross/README: Update. 2023-03-05 10:22:49 +08:00
Po Lu
f484f6b74f Remove redundant gnulib files
* cross/lib: Delete.  Make configure generate it instead.
2023-03-05 10:22:33 +08:00
Po Lu
3be448f429 Remove redundant second copy of gnulib
* .gitignore: Simplify cross/lib rule.
* admin/merge-gnulib (avoided_flags): Stop copying to cross/lib.
* configure.ac: Link gnulib source and header files to
cross/lib.
* cross/Makefile.in (LIB_SRCDIR): Make relative to builddir.
(maintainer-clean): Merge with distclean.  Remove links created
by configure.
2023-03-05 10:18:28 +08:00
Po Lu
1f4818d3e3 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-05 08:09:03 +08:00
Po Lu
b5bf4dc5b5 Fix x86_64 builds of libjpeg on Android
* cross/ndk-build/ndk-build-shared-library.mk:
* cross/ndk-build/ndk-build-static-library.mk: Specify right ELF
format for 64 bit executables.
2023-03-04 21:05:02 +08:00
Po Lu
8f3f9c2550 Fix calls to nasm in cross/ndk-build
* cross/ndk-build/ndk-build-shared-library.mk:
* cross/ndk-build/ndk-build-static-library.mk: Ensure nasm
generates ELF objects.
2023-03-04 21:01:28 +08:00
Po Lu
df74188dba Merge remote-tracking branch 'origin/master' into feature/android 2023-03-04 20:22:39 +08:00
Po Lu
46c8e7617a Fix out of bound write after poly of single pixel span
* src/sfnt.c (sfnt_fill_span): Specifically handle spans that
span a single pixel by computing the coverage in the center.
2023-03-04 19:54:21 +08:00
Po Lu
2634765bc3 Improve context menus on old versions of Android
* java/org/gnu/emacs/EmacsActivity.java (EmacsActivity): New
field `lastClosedMenu'.
(onContextMenuClosed): Don't send event if a menu is closed
twice in a row.  Also, clear wasSubmenuSelected immediately.
* java/org/gnu/emacs/EmacsContextMenu.java: Display submenus
manually in Android 6.0 and earlier.
* java/org/gnu/emacs/EmacsView.java (onCreateContextMenu)
(popupMenu): Adjust accordingly.
2023-03-04 15:55:09 +08:00
Po Lu
39a7e6b79f Port to broken Android NDK version
* configure.ac: Check for __ctype_get_mb_cur_max.
Then see if MB_CUR_MAX is defined to it, and define
REPLACEMENT_MB_CUR_MAX if so and it does not link.
* java/INSTALL: Update documentation.
* src/conf_post.h (MB_CUR_MAX): Define replacement if
necessary.
2023-03-04 13:38:00 +08:00
Po Lu
798003b04f ; * m4/ndk-build.m4 (ndk_INIT): Fix typo. 2023-03-04 11:47:32 +08:00
Po Lu
138d500b60 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-04 11:25:09 +08:00
Po Lu
0e995d06a8 Improve support for building Android C++ dependencies
* configure.ac: Call ndk_LATE after gl_EARLY.
* cross/ndk-build/Makefile.in (NDK_BUILD_CXX): New variable.
* cross/ndk-build/ndk-build-shared-library.mk:
* cross/ndk-build/ndk-build-static-library.mk: Use it.
* java/INSTALL: Describe how to build C++ dependencies.
* m4/ndk-build.m4 (ndk_LATE): New macro.
(ndk_INIT): Try to find a suitable C++ compiler.
(ndk_CHECK_MODULES): Make sure the C++ compiler works before
allowing C++ dependencies.
2023-03-04 11:19:25 +08:00
Po Lu
0d363aded1 Fix cross-compilation of C++ code with old NDK versions
* cross/ndk-build/Makefile.in (NDK_BUILD_CFLAGS_CXX): New variable.
* cross/ndk-build/ndk-build-shared-library.mk
($(call objname,$(LOCAL_MODULE),$(basename $(1)))):
* cross/ndk-build/ndk-build-static-library.mk
($(call objname,$(LOCAL_MODULE),$(basename $(1)))): Use it to build
C++ code.
2023-03-04 08:45:11 +08:00
Po Lu
edfa0f8fa0 Minor fixes to configury
* configure.ac (ANDROID_SDK_8_OR_EARLIER): Pass through
`--with-ndk-cxx-shared'.
* m4/ndk-build.m4: Fix quoting of $CC.
2023-03-03 21:58:48 +08:00
Po Lu
ece6d61301 Fix out-of-tree builds with native dependencies
* cross/ndk-build/ndk-build-shared-library.mk:
* cross/ndk-build/ndk-build-static-library.mk: Include
ndk-resolve.mk in srcdir.
2023-03-03 21:22:00 +08:00
Po Lu
468e8d7322 ; * cross/ndk-build/README: Update accordingly. 2023-03-03 21:14:08 +08:00
Po Lu
d8ea139e83 Improve ndk-build implementation
* build-aux/ndk-build-helper.mk: Define in terms of BUILD_AUXDIR.
* m4/ndk-build.m4 (ndk_INIT): Find right build-aux directory.
Remove uses of unportable shell constructs.
2023-03-03 21:13:58 +08:00
Po Lu
48b5a770f2 Fix visiting and saving writable content provider files
* java/org/gnu/emacs/EmacsService.java (checkContentUri):
Improve debug output.
* lisp/files.el (basic-save-buffer): Check whether or not file
itself exists before checking for the existence of the directory
containing it.
* src/android.c (android_open): Don't forget to set errno after
open_content_uri fails.
2023-03-03 16:00:27 +08:00
Po Lu
4354a3b699 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-03 15:25:53 +08:00
Po Lu
bc9239eb51 Update Android port
* java/org/gnu/emacs/EmacsActivity.java (EmacsActivity)
(onCreate): Add view tree observer.
(onGlobalLayout): Sync fullscreen state.
(syncFullscreenWith): Improve visibility flag setting.

* src/textconv.c (select_window): New function.
(textconv_query):
(restore_selected_window):
(really_commit_text):
(really_set_composing_text):
(really_set_composing_region):
(really_delete_surrounding_text):
(really_set_point_and_mark):
(get_extracted_text): Call it instead of Fselect_window
to avoid selecting the mini window if it is no longer active.
2023-03-03 15:23:21 +08:00
Po Lu
bf93380c1c Merge remote-tracking branch 'origin/master' into feature/android 2023-03-03 08:57:33 +08:00
Po Lu
e18cbd0cc6 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-02 20:45:21 +08:00
Po Lu
a6a586ffc1 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-02 20:00:06 +08:00
Po Lu
42674a7144 ; * doc/emacs/input.texi (On-Screen Keyboards): Fix indexing. 2023-03-02 19:51:06 +08:00
Po Lu
960230d88d Summary: Update Android port
* INSTALL: Document where to find Android installation
instructions.
* configure.ac (CHECK_LISP_OBJECT_TYPE): Pacify
-Wsuggest-attribute=noreturn only on Android.
* cross/ndk-build/README: New file.
* doc/emacs/android.texi (Android):
* doc/emacs/emacs.texi (Top):
* doc/emacs/input.texi (Other Input Devices): Untabify menus.
* etc/NEWS: Move INSTALL.android to java/INSTALL.
* java/INSTALL: New file.
* java/README:
* src/coding.c (from_unicode_buffer): Make Android specific code
only build on Android.
2023-03-02 18:31:35 +08:00
Po Lu
951bdd021f * INSTALL.android: Remove file. 2023-03-02 18:29:46 +08:00
Po Lu
cb233cb88a Fix Makefile race conditions
* configure.ac: Make cross/* and related directories.
* cross/Makefile.in (src/verbose.mk, lib/libgnu.a)
(src/config.h): Stop making directories here.
(lib-src/config.h): New config.h rule.
($(LIBSRC_BINARIES)): Add it.
(clean): Don't remove CLEAN_SUBDIRS, but clean inside.
2023-03-02 15:59:33 +08:00
Po Lu
44341959e8 Fix Android handle wraparound
* src/android.c (android_alloc_id): Return correct values upon
wraparound.
2023-03-02 13:48:03 +08:00
Po Lu
09aa948ab4 Improve criteria for restoring fullscreen state on Android
* java/Makefile.in ($(CLASS_FILES) &): Touch all class files,
even those javac chose not to rebuild.

* java/org/gnu/emacs/EmacsActivity.java (onWindowFocusChanged):
Restore fullscreen state here.
(onResume): And not here.
2023-03-02 12:30:36 +08:00
Po Lu
424077fadf Fix sectioning of android texi files
* doc/emacs/android.texi (Android):
* doc/emacs/emacs.texi (Top, GNU Free Documentation License):
Rearrange menu and sectioning.
2023-03-02 10:50:08 +08:00
Po Lu
7fb3c0d039 Update Android port
* doc/emacs/android.texi (Android Windowing): Reword
documentation.
* java/org/gnu/emacs/EmacsActivity.java (EmacsActivity):
* java/org/gnu/emacs/EmacsContextMenu.java (EmacsContextMenu):
* java/org/gnu/emacs/EmacsFontDriver.java (EmacsFontDriver):
* java/org/gnu/emacs/EmacsSdk7FontDriver.java
(EmacsSdk7FontDriver):
* java/org/gnu/emacs/EmacsService.java (queryBattery):
* java/org/gnu/emacs/EmacsWindow.java (EmacsWindow): Make
functions final and classes static where necessary.
* src/android.c (struct android_emacs_service): New method
`display_toast'.
(android_init_emacs_service): Load new method.
(android_display_toast): New function.
* src/android.h: Export.
* src/androidfns.c (Fandroid_detect_mouse):
* src/androidselect.c (Fandroid_clipboard_owner_p)
(Fandroid_set_clipboard, Fandroid_get_clipboard)
(Fandroid_browse_url): Prevent crashes when called from
libandroid-emacs.so.
* src/androidterm.c (handle_one_android_event): Fix out of date
commentary.
2023-03-02 09:27:37 +08:00
Po Lu
5e416d02c5 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-02 08:38:06 +08:00
Po Lu
daf9c62871 Fix out-of-tree Android builds
* configure.ac (JAVA_PUSH_LINT): Push to WARN_JAVAFLAGS instead
of JAVAFLAGS.
(cross/lib): Always AS_MKDIR_P.
* cross/Makefile.in (srcdir): New variable.
(LIB_SRCDIR): Take realpath relative to srcdir, not
.:(src/verbose.mk): Depend on verbose.mk.android in srcdir.
(lib/Makefile): Edit srcdir and VPATH to LIB_SRCDIR.
(src/Makefile): Edit -I$$(top_srcdir) to -I../$(srcdir)/lib,
instead of ommitting it.
(clean): Allow ndk-build clean to fail.

* java/Makefile.in (builddir): New variable.
(WARN_JAVAFLAGS): Likewise.
(JAVAFLAGS): Define in terms of WARN_JAVAFLAGS.
(SIGN_EMACS, SIGN_EMACS_V2): Use emacs.keystore relative to
srcdir.  Allow inclusion of ndk-build.mk to fail.
(install_temp, emacs.apk-in)
(../config.status): Depend relative to top_srcdir.
(AndroidManifest.xml, $(APK_NAME)): Likewise.
(RESOURCE_FILE, CLASS_FILES, classes.dex): Output class files
to $(srcdir); these are arch independents, so this is okay.
2023-03-01 19:35:19 +08:00
Po Lu
a0c3643abd Merge remote-tracking branch 'origin/master' into feature/android 2023-03-01 15:55:20 +08:00
Po Lu
920168c5d8 Fix mostlyclean rules
* cross/Makefile.in: Remove outdated comment.
* src/Makefile.in: (.PHONY): Clean android-emacs and
libemacs.so, not emacs.so and aemacs.
2023-03-01 15:54:57 +08:00
Po Lu
ad8e12b9f9 Update Android port
* doc/emacs/android.texi (Android File System): Document new
behavior of starting a subprocess from /assets.
* java/org/gnu/emacs/EmacsWindow.java (onSomeKindOfMotionEvent):
Don't use isFromSource where not present.
* src/androidterm.c (android_scroll_run): Avoid undefined
behavior writing to bitfields.
* src/callproc.c (get_current_directory): When trying to run a
subprocess inside /assets, run it from the home directory
instead.
2023-03-01 15:49:02 +08:00
Po Lu
194b3f948c Update Android port
* java/AndroidManifest.xml.in: Specify @style/EmacsStyle.
* java/org/gnu/emacs/EmacsActivity.java (onCreate): Stop setting
the theme here.
* java/res/values-v11/style.xml:
* java/res/values-v14/style.xml:
* java/res/values-v29/style.xml:
* java/res/values/style.xml: Extract style resources into
res/values.
2023-03-01 14:31:57 +08:00
Po Lu
15bcb446be Update Android port
* java/Makefile.in (ETAGS, clean): New rules to generate tags.
* java/org/gnu/emacs/EmacsActivity.java (EmacsActivity):
* java/org/gnu/emacs/EmacsApplication.java (EmacsApplication):
* java/org/gnu/emacs/EmacsContextMenu.java (EmacsContextMenu):
* java/org/gnu/emacs/EmacsCopyArea.java (EmacsCopyArea):
* java/org/gnu/emacs/EmacsDialog.java (EmacsDialog)::(dialog.
Then):
* java/org/gnu/emacs/EmacsDocumentsProvider.java
(EmacsDocumentsProvider):
* java/org/gnu/emacs/EmacsDrawLine.java (EmacsDrawLine):
* java/org/gnu/emacs/EmacsDrawPoint.java (EmacsDrawPoint):
* java/org/gnu/emacs/EmacsDrawRectangle.java
(EmacsDrawRectangle):
* java/org/gnu/emacs/EmacsFillPolygon.java (EmacsFillPolygon):
* java/org/gnu/emacs/EmacsFillRectangle.java
(EmacsFillRectangle):
* java/org/gnu/emacs/EmacsGC.java (EmacsGC):
* java/org/gnu/emacs/EmacsInputConnection.java
(EmacsInputConnection):
* java/org/gnu/emacs/EmacsNative.java (EmacsNative):
* java/org/gnu/emacs/EmacsNoninteractive.java
(EmacsNoninteractive):
* java/org/gnu/emacs/EmacsOpenActivity.java (EmacsOpenActivity):
* java/org/gnu/emacs/EmacsPixmap.java (EmacsPixmap):
* java/org/gnu/emacs/EmacsPreferencesActivity.java
(EmacsPreferencesActivity):
* java/org/gnu/emacs/EmacsSdk11Clipboard.java
(EmacsSdk11Clipboard):
* java/org/gnu/emacs/EmacsSdk23FontDriver.java
(EmacsSdk23FontDriver):
* java/org/gnu/emacs/EmacsSdk8Clipboard.java
(EmacsSdk8Clipboard):
* java/org/gnu/emacs/EmacsService.java (EmacsService):
* java/org/gnu/emacs/EmacsSurfaceView.java (EmacsSurfaceView)
(buffers):
* java/org/gnu/emacs/EmacsView.java (EmacsView, ViewGroup):
* java/org/gnu/emacs/EmacsWindow.java (EmacsWindow, drawables):
* java/org/gnu/emacs/EmacsWindowAttachmentManager.java
(EmacsWindowAttachmentManager): Make classes final where
appropriate.
2023-03-01 12:00:46 +08:00
Po Lu
f8a2619d98 More fixes to JNI error checking
* src/android.c (android_query_tree, android_get_geometry)
(android_translate_coordinates, android_query_battery):
Correctly handle result of GetTArrayElements.
(android_exception_check_nonnull): New function.
* src/android.h:
* src/androidselect.c (Fandroid_get_clipboard): Likewise.
2023-03-01 09:30:01 +08:00
Po Lu
49d5aa3657 Merge remote-tracking branch 'origin/master' into feature/android 2023-03-01 09:15:08 +08:00
Po Lu
03c0cb8671 Merge remote-tracking branch 'origin/master' into feature/android 2023-02-28 18:20:25 +08:00
Po Lu
d96dac96e7 Update Android port
* src/sfnt.c (main):
* src/sfntfont.c (sfntfont_get_glyph_outline): Remove outdated
comment.
2023-02-28 18:20:05 +08:00
Po Lu
744f19c22f Get rid of android_lookup_method
* src/android.c (struct android_emacs_window): New methods.
(android_init_emacs_window): Add new methods.
(android_lookup_method): Delete now-unused function.
(android_change_window_attributes, android_reparent_window)
(android_map_window, android_unmap_window, android_resize_window)
(android_move_window, android_set_input_focus)
(android_raise_window, android_lower_window, android_get_geometry)
(android_translate_coordinates, android_set_dont_focus_on_map)
(android_set_dont_accept_focus): Don't look up the class and
method each time when calling a function; that's just waste.
2023-02-26 15:00:47 +08:00
Po Lu
74a7d34361 Update from gnulib
* cross/lib/unistd.in.h:
* lib/gnulib.mk.in (INT64_MAX_EQ_LONG_MAX):
* m4/gnulib-comp.m4 (gl_EARLY): Update from gnulib.
2023-02-26 14:14:43 +08:00
Po Lu
28f6add67f Merge remote-tracking branch 'origin/master' into feature/android 2023-02-26 14:11:18 +08:00
Po Lu
39ddf1855b Update Android port
* doc/lispref/commands.texi (Misc Events): Update documentation.
* java/org/gnu/emacs/EmacsService.java (EmacsService)
(onStartCommand): Improve notification message.
* src/android.c (android_hack_asset_fd): Detect if ashmem is
available dynamically.
(android_detect_ashmem): New function.
* src/textconv.c (record_buffer_change): Use markers to
represent BEG and END instead.
(syms_of_textconv): Update doc string.
2023-02-26 10:33:41 +08:00
Po Lu
687f4fadde Merge remote-tracking branch 'origin/master' into feature/android 2023-02-26 07:33:09 +08:00
Po Lu
8fa86cc7cd Update Android port
* java/debug.sh (is_root): Fix tee detection again for old
systems which don't return exit codes from adb shell.
* src/android.c (android_run_select_thread, NATIVE_NAME,
JNICALL):
* src/android.h (NATIVE_NAME):
* src/androidterm.c (JNICALL, NATIVE_NAME): Apply stack
alignment to all JNICALL functions.
2023-02-25 21:52:11 +08:00
Po Lu
80f26cc398 ; * src/android.c (android_open): Clean up unused variables. 2023-02-25 20:17:59 +08:00
Po Lu
df29bb71fc Update Android port
* java/org/gnu/emacs/EmacsNoninteractive.java (main): Port to
Android 2.2.
* src/android-asset.h (AAsset_openFileDescriptor): Delete stub
function.
* src/android.c (android_check_compressed_file): Delete
function.
(android_open): Stop trying to find compressed files or to use
the system provided file descriptor.  Explain why.
2023-02-25 20:11:48 +08:00
Po Lu
8e4c5db193 Update Android port
* doc/emacs/android.texi (Android Startup, Android File System)
(Android Environment, Android Windowing, Android
Troubleshooting): Improve documentation; fix typos.
* doc/lispref/commands.texi (Misc Events): Likewise.
* java/org/gnu/emacs/EmacsService.java (queryBattery): New
function.
* lisp/battery.el (battery-status-function): Set appropriately
for Android.
(battery-android): New function.
* src/android.c (struct android_emacs_service): New method
`query_battery'.
(android_check_content_access): Improve exception checking.
(android_init_emacs_service): Look up new method.
(android_destroy_handle, android_create_window)
(android_init_android_rect_class, android_init_emacs_gc_class)
(android_set_clip_rectangles)
(android_create_pixmap_from_bitmap_data, android_fill_polygon)
(android_get_image, android_put_image, android_bell)
(android_set_input_focus, android_raise_window)
(android_lower_window, android_query_tree, android_get_geometry)
(android_translate_coordinates, android_wc_lookup_string)
(android_damage_window, android_build_string)
(android_build_jstring, android_exception_check_1)
(android_exception_check_2): New functions.
(android_browse_url): Improve exception handling.  Always use
android_exception_check and don't leak local refs.
(android_query_battery): New function.
* src/android.h (struct android_battery_state): New struct.
* src/androidfns.c (Fandroid_query_battery, syms_of_androidfns):
New function.
* src/androidfont.c (androidfont_from_lisp, DO_SYMBOL_FIELD)
(DO_CARDINAL_FIELD, androidfont_list, androidfont_match)
(androidfont_draw, androidfont_open_font)
(androidfont_close_font):
* src/androidselect.c (Fandroid_set_clipboard)
(Fandroid_get_clipboard):
* src/sfnt.c (sfnt_map_glyf_table):
* src/sfntfont.c (sfntfont_free_outline_cache)
(sfntfont_free_raster_cache, sfntfont_close): Allow font close
functions to be called twice.
2023-02-25 19:11:07 +08:00
Po Lu
d5cccfdc56 Merge remote-tracking branch 'origin/master' into feature/android 2023-02-25 14:24:17 +08:00
Po Lu
ea74f3c067 Improve Android configury
* configure.ac (JAVA_PUSH_LINT): New macro.
(JAVAFLAGS): New variable.  Check for various lint flags and
macros and enable them.
* java/Makefile.in (ANDROID_ABI):
* java/org/gnu/emacs/EmacsSdk7FontDriver.java: Remove compiler
warning.
2023-02-24 22:25:48 +08:00
Po Lu
4ff3904e3c Enable normal-erase-is-backspace on Android
* lisp/frame.el (display-symbol-keys-p):
* lisp/simple.el (normal-erase-is-backspace-setup-frame): Return
appropriate values on Android.
2023-02-24 21:22:47 +08:00
Po Lu
d3e71edc71 Merge remote-tracking branch 'origin/master' into feature/android 2023-02-24 21:20:08 +08:00
Po Lu
b91e8ada70 Fix auto-revert-mode on Android
* src/inotify.c (Finotify_add_watch): Handle asset files.
2023-02-24 21:18:35 +08:00
Po Lu
4aaa6fd24c ; * src/keyboard.c (lispy_function_keys): Add missing delete key. 2023-02-24 09:06:15 +08:00
Po Lu
4bcf251308 Merge remote-tracking branch 'origin/master' into feature/android 2023-02-24 09:01:29 +08:00
Po Lu
0b7d9bbc8a Make sure scroll-bar.el is loaded on Android
* lisp/loadup.el: Update commentary.
* src/androidterm.c (syms_of_androidterm): Define
Vx_toolkit_scroll_bars.
* src/xterm.c (syms_of_xterm): Update doc string.xf64
2023-02-23 21:49:02 +08:00
Po Lu
e3595debd0 Merge remote-tracking branch 'origin/master' into feature/android 2023-02-23 21:38:41 +08:00
Po Lu
351813556d Fix ImageMagick build on Android
* INSTALL.android (-linux_arm_sources):
* build-aux/ndk-build-helper-1.mk:
(NDK_$(LOCAL_MODULE)_STATIC_LIBRARIES)::(NDK_CXX_FLAG_$(LOCAL_MODULE)):
* build-aux/ndk-build-helper-2.mk:
(NDK_$(LOCAL_MODULE)_STATIC_LIBRARIES)::(NDK_CXX_FLAG_$(LOCAL_MODULE)):
* cross/ndk-build/ndk-build-shared-library.mk (objname)::($(call
objname,$(LOCAL_MODULE),$(basename
$(1))))::(ALL_OBJECT_FILES$(LOCAL_MODULE)):
* cross/ndk-build/ndk-build-static-library.mk (objname)::($(call
objname,$(LOCAL_MODULE),$(basename
$(1))))::(ALL_OBJECT_FILES$(LOCAL_MODULE)):
(ALL_SOURCE_FILES): Update ImageMagick build instructions and
C++ module detection.
2023-02-23 21:31:42 +08:00
Po Lu
c0a39006a2 ; * src/android.c (android_run_select_thread): Fix typos. 2023-02-23 18:19:32 +08:00
Po Lu
8747568d69 Make android_select more robust
* src/android.c (android_run_select_thread): Lock select_mutex
before signalling condition variable.
(android_select): Unlock event queue mutex prior to waiting for
it.
2023-02-23 18:05:57 +08:00
Po Lu
1d84465236 ; Fix typo
* cross/ndk-build/ndk-build-shared-library.mk: Fix typo.
2023-02-22 21:24:59 +08:00
Po Lu
2222c7c335 * src/image.c (imagemagick_load_image): Check HAVE_DECL_xxx. 2023-02-22 21:20:52 +08:00
Po Lu
767da53fa3 Update Android port
ImageMagick now builds but does not link yet some of the time.

* INSTALL.android: Document ImageMagick and caveats.
* build-aux/ndk-build-helper-1.mk (NDK_SO_NAMES):
* build-aux/ndk-build-helper-2.mk (NDK_A_NAMES):
* build-aux/ndk-build-helper.mk (TARGET_ARCH_ABI): Define architecture
and don't respect explicitly specified library names.
* configure.ac: Enable ImageMagick and lcms2 on Android.
* cross/ndk-build/ndk-build-shared-library.mk (objname)::($(call
objname,$(LOCAL_MODULE),$(basename
$(1))))::(ALL_OBJECT_FILES$(LOCAL_MODULE)):
* cross/ndk-build/ndk-build-static-library.mk (objname)::($(call
objname,$(LOCAL_MODULE),$(basename $(1)))):
(NDK_CFLAGS, ALL_SOURCE_FILES): Handle sources files which start with
$(LOCAL_PATH).
* cross/ndk-build/ndk-clear-vars.mk: Don't undefine; clear variables
instead.
* m4/ndk-build.m4 (ndk_SEARCH_MODULE): Redirect make stderr to
config.log.xf64
2023-02-22 21:20:30 +08:00
Po Lu
f3b6cbb675 ; * src/androidmenu.c (android_menu_show): Fix typo. 2023-02-22 19:31:31 +08:00
Po Lu
1e6f957c0d Update Android port
* doc/emacs/input.texi (On-Screen Keyboards): Document changes
to text conversion.
* java/org/gnu/emacs/EmacsInputConnection.java (getExtractedText)
(EmacsInputConnection):
* src/keyboard.c (read_key_sequence): Disable text conversion
after reading prefix key.
* src/textconv.c (get_extracted_text): Fix returned value when
request length is zero.
2023-02-22 14:59:27 +08:00
Po Lu
8356412d62 Merge remote-tracking branch 'origin/master' into feature/android 2023-02-22 11:31:39 +08:00
Po Lu
86f10534dc Add cross-compilation test for cleanup attribute
* configure.ac: Per title.
2023-02-22 11:19:57 +08:00
Po Lu
137bdaced6 Update Android port
* INSTALL.android: Port to MIPS.
* configure.ac (modules): Default to ifavailable.
Write actual test for __attribute__((cleanup)).
* m4/ndk-build.m4: Recognize mips and mips64.
* src/emacs-module.c: Remove broken HAS_ATTRIBUTE test.
2023-02-22 11:01:44 +08:00
Po Lu
a892c0487a Merge remote-tracking branch 'origin/master' into feature/android 2023-02-21 21:08:16 +08:00
Po Lu
77feba7456 Update Android port
* java/org/gnu/emacs/EmacsContextMenu.java (EmacsContextMenu)
(addSubmenu, inflateMenuItems): Handle tooltips correctly.
* src/android.c (android_scan_directory_tree): Fix limit
generation for root directory.
* src/androidmenu.c (android_init_emacs_context_menu)
(android_menu_show): Implement menu item help text on Android
8.0 and later.
2023-02-21 21:07:57 +08:00
Po Lu
8ca4162ecd Update from gnulib
* admin/merge-gnulib (GNULIB_MODULES):
* cross/lib/getopt-pfx-core.h (optind):
* cross/lib/limits.in.h (BOOL_WIDTH):
* cross/lib/math.in.h:
* cross/lib/stpncpy.c (__stpncpy):
* cross/lib/string.in.h:
* lib/getopt-pfx-core.h (optind):
* lib/gnulib.mk.in (ANDROID_MIN_SDK):
(GL_COND_OBJ_STDIO_READ_CONDITION):
(LIBS):
(NDK_BUILD_AR):
(REPLACE__EXIT):
(libgnu_a_SOURCES):
* lib/limits.in.h (BOOL_WIDTH):
* lib/math.in.h:
* lib/stpncpy.c (__stpncpy):
* lib/string.in.h:
* m4/assert_h.m4 (gl_ASSERT_H):
* m4/fdopendir.m4 (gl_FUNC_FDOPENDIR):
* m4/getdelim.m4 (gl_FUNC_GETDELIM):
* m4/getline.m4 (gl_FUNC_GETLINE):
* m4/gnulib-common.m4 (gl_COMMON_BODY):
(gl_CONDITIONAL_HEADER):
(gl_CHECK_FUNCS_ANDROID):
* m4/gnulib-comp.m4 (gl_EARLY):
(gl_INIT):
(gl_FILE_LIST):
* m4/limits-h.m4:
* m4/lstat.m4 (gl_FUNC_LSTAT_FOLLOWS_SLASHED_SYMLINK):
* m4/malloc.m4 (_AC_FUNC_MALLOC_IF):
* m4/printf.m4 (gl_PRINTF_SIZES_C99):
(gl_PRINTF_INFINITE):
(gl_PRINTF_INFINITE_LONG_DOUBLE):
(gl_PRINTF_DIRECTIVE_A):
(gl_PRINTF_DIRECTIVE_F):
(gl_PRINTF_FLAG_ZERO):
(gl_SNPRINTF_PRESENCE):
(gl_SNPRINTF_DIRECTIVE_N):
(gl_VSNPRINTF_ZEROSIZE_C99):
* m4/pselect.m4 (gl_FUNC_PSELECT):
* m4/readlink.m4 (gl_FUNC_READLINK):
* m4/realloc.m4 (_AC_FUNC_REALLOC_IF):
* m4/signbit.m4 (gl_SIGNBIT):
* m4/stpncpy.m4 (gl_FUNC_STPNCPY):
* m4/symlink.m4 (gl_FUNC_SYMLINK): Add gnulib module stpncpy.
* src/android.c: Include string.h.
2023-02-21 16:29:57 +08:00
Po Lu
7aa4ffddd8 Update Android port
* doc/emacs/android.texi (Android Startup): Document `content'
special directory.
* java/debug.sh (is_root): Improve /bin/tee detection.
* java/org/gnu/emacs/EmacsNative.java (EmacsNative): New
function `dup'.
* java/org/gnu/emacs/EmacsOpenActivity.java (EmacsOpenActivity)
(checkReadableOrCopy, onCreate): Create content directory names
when the file is not readable.
* java/org/gnu/emacs/EmacsService.java (EmacsService)
(openContentUri, checkContentUri): New functions.
* src/android.c (struct android_emacs_service): New methods.
(android_content_name_p, android_get_content_name)
(android_check_content_access): New function.
(android_fstatat, android_open): Implement opening content URIs.
(dup): Export to Java.
(android_init_emacs_service): Initialize new methods.
(android_faccessat): Implement content file names.
2023-02-21 15:28:06 +08:00
Po Lu
d197d73491 Merge remote-tracking branch 'origin/master' into feature/android 2023-02-21 10:36:37 +08:00
Po Lu
fce2e2f264 Merge remote-tracking branch 'origin/master' into feature/android 2023-02-20 22:15:02 +08:00
Po Lu
57c19f477f Update Android port
* INSTALL.android: Explain where to get tree-sitter.

* configure.ac: Add support for dynamic modules and tree-sitter.

* doc/emacs/android.texi (Android Windowing):
* java/org/gnu/emacs/EmacsSdk11Clipboard.java
(EmacsSdk11Clipboard, ownsClipboard): Improve clipboard handling
and documentation.
2023-02-20 22:14:29 +08:00
Po Lu
fecd0a9fed Fix crash inside font-list-family
* src/androidfont.c (androidfont_list_family): Don't
unconditionally initialize the Android font driver.
2023-02-20 11:56:13 +08:00
Po Lu
ba87d2c28b Merge remote-tracking branch 'origin/master' into feature/android 2023-02-20 11:41:16 +08:00
Po Lu
34ba481c8e Improve SFNT driver lookup efficiency
* src/fontset.c (fontset_find_font): Add compatibility test to
registry strangeness case.
* src/sfnt.c (sfnt_read_cmap_table): Don't read subtable data if
DATA is NULL.
* src/sfntfont.c (struct sfnt_font_desc): New field `registry'.
(sfnt_registry_for_subtable): New function.
(sfntfont_identify_cmap): Move above sfnt_grok_registry.
(sfnt_grok_registry): New function.
(sfnt_enum_font_1): Call it.
(sfntfont_registries_compatible_p): New function.
(sfntfont_list_1): Check registry compatibility.
(sfntfont_registry_for_desc): New function.
(mark_sfntfont): Mark desc->registry.
2023-02-20 11:38:59 +08:00
Po Lu
b91396bace Improve reliability of Java code rebuilds
* java/Makefile.in ($(CLASS_FILES)): Depend on the Java
compiler's internal dependency tracking.
2023-02-20 10:50:04 +08:00
Po Lu
1727777a46 Match font registry after font is opened
* src/fontset.c (fontset_find_font): Work around TrueType
performance problem.
2023-02-19 23:33:19 +08:00
Po Lu
e5232fc0e5 Merge remote-tracking branch 'origin/master' into feature/android 2023-02-19 22:41:42 +08:00
Po Lu
05791d09f6 * cross/Makefile.in (src/libemacs.so): Depend on libgnu.a. 2023-02-19 21:57:17 +08:00
Po Lu
585ee91b21 More fixes to parallel Make
* cross/ndk-build/ndk-build.mk.in (NDK_BUILD_MODULES)
(NDK_BUILD_SHARED, NDK_BUILD_STATIC): Define group rule to build
all files so that they are built within one make process.
* java/Makefile.in: Reorganize cross compilation and make sure
there is only one make subprocess for each subdirectory of
cross.
2023-02-19 21:52:21 +08:00
Po Lu
f319605207 More parallel build fixes
* cross/Makefile.in: (.PHONY):
* java/Makefile.in: (.PHONY):
* src/Makefile.in: (libemacs.so): Avoid calling ndk-build from
two places at once.  Build android-emacs separately from
libemacs.so.
2023-02-19 21:25:37 +08:00
Po Lu
18f723faa8 Fix parallel compilation of Android port
* cross/Makefile.in ($(top_builddir)/lib/libgnu.a):
* java/Makefile.in (CROSS_LIBS): Explicitly depend on gnulib
to prevent it from being built at the same time from different
jobs.
2023-02-19 20:45:32 +08:00
Po Lu
c09dca3fb0 Fix sfntfont.c build without mmap
* src/sfntfont.c (sfntfont_close): Don't unlink font if mmap is
not available.
2023-02-19 20:23:36 +08:00
Po Lu
47dbdb06dc Improve Android documentation
* INSTALL.android: Say where building Emacs is supported.
* doc/emacs/android.texi (Android Startup): Describe how to
connect via ADB.
2023-02-19 20:16:32 +08:00
Po Lu
0998ab3ade Report both sides of the region to the input method upon setup
* java/org/gnu/emacs/EmacsNative.java (getSelection): Return
array of ints.
* java/org/gnu/emacs/EmacsView.java (onCreateInputConnection):
Adjust accordingly.
* src/androidterm.c (struct android_get_selection_context): New
field `mark'.
(android_get_selection): Set the mark field as appropriate.
(getSelection): Adjust accordingly.
2023-02-19 19:56:51 +08:00
Po Lu
0aa19e993b Fix gamegrid.el with high resolution displays
* lisp/play/gamegrid.el (gamegrid-setup-default-font): Clamp
font size at eight.
2023-02-19 19:34:04 +08:00
Po Lu
efc46330aa Allow opening more files in emacsclient on Android
* java/org/gnu/emacs/EmacsOpenActivity.java (EmacsOpenActivity)
(checkReadableOrCopy): New function.
(onCreate): If the file specified is not readable from C, read
it into a temporary file and ask Emacs to open that.
2023-02-19 15:29:46 +08:00
Po Lu
c8f49c9276 Implement `fullscreen' on Android 4.0 and later
* doc/emacs/android.texi (Android Windowing): Document what new
frame parameters are now supported.
* java/org/gnu/emacs/EmacsActivity.java (EmacsActivity): New
field `isFullscreen'.
(detachWindow, attachWindow): Sync fullscreen state.
(onWindowFocusChanged): Add more logging.
(onResume): Restore previous fullscreen state.
(syncFullscreen): New function.
* java/org/gnu/emacs/EmacsWindow.java (EmacsWindow)
(setFullscreen): New function.
* src/android.c (struct android_emacs_window): Add new method.
(android_init_emacs_window): Look up new method.
(android_set_fullscreen): New function.
* src/androidgui.h:
* src/androidterm.c (android_fullscreen_hook): Implement
accordingly.
2023-02-19 13:17:43 +08:00
Po Lu
c6809eb927 Fix crashes in desktop-save-mode
* lisp/subr.el (overriding-text-conversion-style, y-or-n-p):
Disable text conversion when reading from minibuffer.
* src/androidfns.c (android_make_monitor_attribute_list): New
function.
(Fandroid_display_monitor_attributes_list): Call it to set
monitor_frames, which avoids a NULL pointer dereference.
Reported by Angelo Graziosi <angelo.g0@libero.it>.
2023-02-19 10:47:32 +08:00
Po Lu
2bcfa0e68e Merge remote-tracking branch 'origin/master' into feature/android 2023-02-19 10:17:02 +08:00
Po Lu
4ab9fa7507 ; * lisp/loadup.el: Fix merge typos. 2023-02-18 23:17:07 +08:00
Po Lu
c045d5322c Merge remote-tracking branch 'origin/master' into feature/android 2023-02-18 23:13:51 +08:00
Po Lu
a61f9cb77c Update Android port
* doc/emacs/input.texi (On-Screen Keyboards): Document
`touch-screen-always-display'.
* doc/lispref/commands.texi (Misc Events): Improve documentation
of text conversion events.
* java/org/gnu/emacs/EmacsDialog.java (toAlertDialog, display1):
Reorder buttons to make more sense.
* lisp/elec-pair.el (electric-pair-analyze-conversion): New
function.
* lisp/simple.el (analyze-text-conversion): Improve integration
with electric pair modes.
* lisp/term.el (term-mode): Always display the onscreen
keyboard.
* lisp/touch-screen.el (touch-screen-display-keyboard)
(touch-screen-handle-point-up): Respect new options.
* src/textconv.c (really_set_composing_text): Stop widenining
unnecessarily.
(really_delete_surrounding_text): Really delete surrounding
text.  Give text conversion analyzers the buffer text.
(syms_of_textconv): Update doc string.
2023-02-18 23:09:30 +08:00
Po Lu
fa1b27930e Notify input methods when editing fails
* INSTALL.android: Clarify build instructions.
* src/textconv.c (struct complete_edit_check_context): New
structure.
(complete_edit_check): New function.
(handle_pending_conversion_events_1): If the window is known,
then ensure that any editing failures are reported to the input
method.
2023-02-18 14:48:08 +08:00
Po Lu
3a0b3cd086 * configure.ac: Fix typo. 2023-02-18 13:05:03 +08:00
Po Lu
265435fdf8 Update Android port
* configure.ac: Check for madvise.
* lisp/international/fontset.el (script-representative-chars):
Improve detection of CJK fonts.
* src/pdumper.c (dump_discard_mem): Use madvise if possible.
* src/sfnt.c (sfnt_map_glyf_table, sfnt_unmap_glyf_table): New
functions.
* src/sfnt.h (struct sfnt_glyf_table): New field.
* src/sfntfont.c (struct sfnt_font_info, sfntfont_open)
(sfntfont_close, sfntfont_detect_sigbus): Allow mmapping fonts
if possible.
* src/sfntfont.h: Update prototypes.
* src/sysdep.c (handle_sigbus, init_sigbus, init_signals):
Initialize SIGBUS correctly.
2023-02-18 11:50:44 +08:00
Po Lu
ce440ae92c Merge remote-tracking branch 'origin/master' into feature/android 2023-02-18 09:39:46 +08:00
Po Lu
e88730a4b4 Work around race condition bug in Android 13's input manager
* src/androidterm.c (android_get_selection): Use ephemeral last
point.
* src/textconv.c (report_selected_window_change): Set
w->ephemeral_last_point to the window's point now.
2023-02-17 21:31:43 +08:00
Po Lu
d70bb47aeb Update emacsbug and version.el for the Android port
* java/Makefile.in (install_temp/assets/version): New generated
file.
* lisp/loadup.el: Set emacs versions appropriately prior to
dumping on Android.
* lisp/mail/emacsbug.el (emacs-build-description): Insert
Android build fingerprint.
* lisp/version.el (emacs-repository-version-android)
(emacs-repository-get-version, emacs-repository-get-branch):
Implement for Android.
* src/androidterm.c (android_set_build_fingerprint): New
function.
(syms_of_androidterm): New variable `android-build-fingerprint'.
2023-02-17 21:09:00 +08:00
Po Lu
1f81186d67 * src/android.c (android_exception_check): Fix typo. 2023-02-17 19:16:00 +08:00
Po Lu
2341d1d52a Merge remote-tracking branch 'origin/master' into feature/android 2023-02-17 19:09:58 +08:00
Po Lu
ecb48e8d63 Improve logging of Java exceptions
* src/android.c (android_exception_check): Print more detailed
information.
2023-02-17 19:08:55 +08:00
Po Lu
60ed861b10 Fix crash on old versions of Android
* java/org/gnu/emacs/EmacsService.java (nameKeysym): Implement
stub on Android 3.0 and earlier.
2023-02-17 19:02:23 +08:00
Po Lu
88afd96e36 Fix build and running on Android 2.2
* INSTALL.android: Document that Android 2.2 is now supported,
with caveats.
* configure.ac (ANDROID_MIN_SDK, ANDROID_SDK_18_OR_EARLIER)
(SYSTEM_TYPE, ANDROID_STUBIFY, SIZEOF_LONG): Correctly detect
things missing on Android 2.2.
* java/Makefile.in (ANDROID_JAR, JARSIGNER_FLAGS):
* java/debug.sh (jdb, gdbserver, line):
* java/org/gnu/emacs/EmacsApplication.java (findDumpFile):
* java/org/gnu/emacs/EmacsService.java (onCreate):
* java/org/gnu/emacs/EmacsThread.java (EmacsThread, run): Run
parameter initialization on main thread.
* src/android-asset.h (struct android_asset_manager)
(struct android_asset, AAssetManager_fromJava, AAssetManager_open)
(AAsset_close, android_asset_create_stream)
(android_asset_read_internal, AAsset_openFileDescriptor)
(AAsset_getLength, AAsset_getBuffer, AAsset_read): New file.
* src/android.c (android_user_full_name, android_hack_asset_fd)
(android_check_compressed_file): Implement for Android 2.2.
* src/process.c (Fprocess_send_eof): Don't call tcdrain if
unavailable.
* src/sfntfont-android.c (system_font_directories): Fix compiler
warning.
* src/sfntfont.c (sfntfont_read_cmap): Correctly test rc of
emacs_open.
* src/textconv.c (handle_pending_conversion_events_1): Mark
buffer UNINIT.
2023-02-17 16:27:00 +08:00
Po Lu
759e6a24ab Merge remote-tracking branch 'origin/master' into feature/android 2023-02-16 23:57:21 +08:00
Po Lu
2dcce30290 Update Android port
* doc/emacs/android.texi (Android Fonts):
* doc/emacs/input.texi (On-Screen Keyboards):
* doc/lispref/commands.texi (Misc Events): Update documentation.
* java/org/gnu/emacs/EmacsInputConnection.java (setSelection):
New function.
* java/org/gnu/emacs/EmacsSurfaceView.java (EmacsSurfaceView)
(reconfigureFrontBuffer): Make bitmap references weak
references.
* java/org/gnu/emacs/EmacsView.java (handleDirtyBitmap): Don't
clear surfaceView bitmap.
* lisp/comint.el (comint-mode):
* lisp/international/fontset.el (script-representative-chars)
(setup-default-fontset): Improve detection of CJK fonts.
* lisp/isearch.el (set-text-conversion-style): New variable.
(isearch-mode, isearch-done): Save and restore the text
conversion style.
* lisp/minibuffer.el (minibuffer-mode): Set an appropriate text
conversion style.
* lisp/simple.el (analyze-text-conversion): Run
post-self-insert-hook properly.
* lisp/subr.el (read-char-from-minibuffer): Disable text
conversion when reading character.
* src/androidterm.c (show_back_buffer): Don't check that F is
not garbaged.
(android_update_selection, android_reset_conversion): Use the
ephemeral last point and handle text conversion being disabled.
* src/buffer.c (syms_of_buffer): Convert old style DEFVAR.
* src/keyboard.c (kbd_buffer_get_event): Handle text conversion
first.
* src/lisp.h: Update prototypes.
* src/lread.c (read_filtered_event): Temporarily disable text
conversion.
* src/sfnt.c (sfnt_decompose_glyph_1, sfnt_decompose_glyph_2):
New functions.
(sfnt_decompose_glyph, sfnt_decompose_instructed_outline):
Refactor contour decomposition to those two functions.
(main): Update tests.
* src/sfntfont-android.c (system_font_directories): Add empty
field.
(Fandroid_enumerate_fonts, init_sfntfont_android): Enumerate
fonts in a user fonts directory.
* src/sfntfont.c (struct sfnt_font_desc): New field
`num_glyphs'.
(sfnt_enum_font_1): Set num_glyphs and avoid duplicate fonts.
(sfntfont_glyph_valid): New function.
(sfntfont_lookup_char, sfntfont_list_1): Make sure glyphs found
are valid.

* src/textconv.c (sync_overlay, really_commit_text)
(really_set_composing_text, really_set_composing_region)
(really_delete_surrounding_text, really_set_point_and_mark)
(handle_pending_conversion_events_1)
(handle_pending_conversion_events, conversion_disabled_p)
(disable_text_conversion, resume_text_conversion)
(Fset_text_conversion_style, syms_of_textconv): Update to
respect new options.
* src/textconv.h:
* src/window.h (GCALIGNED_STRUCT): New field
`ephemeral_last_point'.
* src/xdisp.c (mark_window_display_accurate_1): Set it.
2023-02-16 23:57:01 +08:00
Po Lu
cf24b61985 Update Android port
* doc/emacs/input.texi (On-Screen Keyboards):
* doc/lispref/commands.texi (Misc Events): Improve documentation
of text conversion stuff.
* java/org/gnu/emacs/EmacsInputConnection.java (beginBatchEdit)
(endBatchEdit, commitCompletion, commitText, deleteSurroundingText)
(finishComposingText, getSelectedText, getTextAfterCursor)
(EmacsInputConnection, setComposingRegion, performEditorAction)
(getExtractedText): Condition debug code on DEBUG_IC.
* java/org/gnu/emacs/EmacsService.java (EmacsService, updateIC):
Likewise.
* lisp/bindings.el (global-map):
* lisp/electric.el (global-map): Make `text-conversion'
`analyze-text-conversion'.
* lisp/progmodes/prog-mode.el (prog-mode): Enable text
conversion in input methods.
* lisp/simple.el (analyze-text-conversion): New function.
* lisp/textmodes/text-mode.el (text-conversion-style)
(text-mode): Likewise.
* src/androidterm.c (android_handle_ime_event): Handle
set_point_and_mark.
(android_sync_edit): Give Emacs 100 ms instead.
(android_perform_conversion_query): Skip the active region, not
the conversion region.
(getSelectedText): Implement properly.
(android_update_selection): Expose mark to input methods.
(android_reset_conversion): Handle `text-conversion-style'.
* src/buffer.c (init_buffer_once, syms_of_buffer): Add buffer
local variable `text-conversion-style'.
* src/buffer.h (struct buffer, bset_text_conversion_style): New
fields.
* src/emacs.c (android_emacs_init): Call syms_of_textconv.
* src/frame.h (enum text_conversion_operation): Rename
TEXTCONV_SET_POINT.
* src/lisp.h: Export syms_of_textconv.

* src/marker.c (set_marker_internal): Force redisplay when the
mark is set and the buffer is visible on builds that use text
conversion.  Explain why.

* src/textconv.c (copy_buffer): Fix copying past gap.
(get_mark): New function.
(textconv_query): Implement new flag.
(sync_overlay): New function.  Display conversion text in an
overlay.
(record_buffer_change, really_commit_text)
(really_set_composing_text, really_set_composing_region)
(really_delete_surrounding_text, really_set_point)
(handle_pending_conversion_events_1, decrement_inside)
(handle_pending_conversion_events, textconv_set_point)
(get_extracted_text, register_textconv_interface): Various fixes
and improvements.

* src/textconv.h (struct textconv_interface): Update
documentation.
* src/window.h (GCALIGNED_STRUCT): New field `prev_mark'.
* src/xdisp.c (mark_window_display_accurate_1): Handle
prev_mark.
2023-02-15 22:51:44 +08:00
Po Lu
dd7066901f Make debug.sh detect adb running as root
* java/debug.sh: Run gdbserver directly if possible.
2023-02-15 13:39:47 +08:00
Po Lu
b875a2eaf3 Fix small bugs
* src/androidterm.c (android_handle_ime_event): Pacify compiler
warnings.
* src/textconv.c (really_set_composing_text)
(handle_pending_conversion_events, get_extracted_text): Fix
reentrancy problems and uses of uninitialized values.
2023-02-15 13:38:53 +08:00
Po Lu
a62fa69ec9 Merge remote-tracking branch 'origin/master' into feature/android 2023-02-15 12:24:22 +08:00
Po Lu
a158c1d5b9 Update Android port
* configure.ac (HAVE_TEXT_CONVERSION): Define on Android.
* doc/emacs/input.texi (On-Screen Keyboards): Document ``text
conversion'' slightly.
* doc/lispref/commands.texi (Misc Events): Document new
`text-conversion' event.
* java/org/gnu/emacs/EmacsContextMenu.java (display): Use
`syncRunnable'.
* java/org/gnu/emacs/EmacsDialog.java (display): Likewise.
* java/org/gnu/emacs/EmacsEditable.java: Delete file.
* java/org/gnu/emacs/EmacsInputConnection.java
(EmacsInputConnection): Reimplement from scratch.
* java/org/gnu/emacs/EmacsNative.java (EmacsNative): Add new
functions.
* java/org/gnu/emacs/EmacsService.java (EmacsService, getEmacsView)
(getLocationOnScreen, sync, getClipboardManager, restartEmacs):
Use syncRunnable.
(syncRunnable): New function.
(updateIC, resetIC): New functions.

* java/org/gnu/emacs/EmacsView.java (EmacsView): New field
`inputConnection' and `icMode'.
(onCreateInputConnection): Update accordingly.
(setICMode, getICMode): New functions.

* lisp/bindings.el (global-map): Ignore text conversion events.
* src/alloc.c (mark_frame): Mark text conversion data.
* src/android.c (struct android_emacs_service): New fields
`update_ic' and `reset_ic'.
(event_serial): Export.
(android_query_sem): New function.
(android_init_events): Initialize new semaphore.
(android_write_event): Export.
(android_select): Check for UI thread code.
(setEmacsParams, android_init_emacs_service): Initialize new
methods.
(android_check_query, android_begin_query, android_end_query)
(android_run_in_emacs_thread):
(android_update_ic, android_reset_ic): New functions for
managing synchronous queries from one thread to another.

* src/android.h: Export new functions.
* src/androidgui.h (enum android_event_type): Add input method
events.
(enum android_ime_operation, struct android_ime_event)
(union android_event, enum android_ic_mode): New structs and
enums.

* src/androidterm.c (android_window_to_frame): Allow DPYINFO to
be NULL.
(android_decode_utf16, android_handle_ime_event)
(handle_one_android_event, android_sync_edit)
(android_copy_java_string, beginBatchEdit, endBatchEdit)
(commitCompletion, deleteSurroundingText, finishComposingText)
(getSelectedtext, getTextAfterCursor, getTextBeforeCursor)
(setComposingText, setComposingRegion, setSelection, getSelection)
(performEditorAction, getExtractedText): New functions.
(struct android_conversion_query_context):
(android_perform_conversion_query):
(android_text_to_string):
(struct android_get_selection_context):
(android_get_selection):
(struct android_get_extracted_text_context):
(android_get_extracted_text):
(struct android_extracted_text_request_class):
(struct android_extracted_text_class):
(android_update_selection):
(android_reset_conversion):
(android_set_point):
(android_compose_region_changed):
(android_notify_conversion):
(text_conversion_interface): New functions and structures.
(android_term_init): Initialize text conversion.

* src/coding.c (syms_of_coding): Define Qutf_16le on Android.
* src/frame.c (make_frame): Clear conversion data.
(delete_frame): Reset conversion state.

* src/frame.h (enum text_conversion_operation)
(struct text_conversion_action, struct text_conversion_state)
(GCALIGNED_STRUCT): Update structures.
* src/keyboard.c (read_char, readable_events, kbd_buffer_get_event)
(syms_of_keyboard): Handle text conversion events.
* src/lisp.h:
* src/process.c: Fix includes.

* src/textconv.c (enum textconv_batch_edit_flags, textconv_query)
(reset_frame_state, detect_conversion_events)
(restore_selected_window, really_commit_text)
(really_finish_composing_text, really_set_composing_text)
(really_set_composing_region, really_delete_surrounding_text)
(really_set_point, complete_edit)
(handle_pending_conversion_events_1)
(handle_pending_conversion_events, start_batch_edit)
(end_batch_edit, commit_text, finish_composing_text)
(set_composing_text, set_composing_region, textconv_set_point)
(delete_surrounding_text, get_extracted_text)
(report_selected_window_change, report_point_change)
(register_texconv_interface): New functions.

* src/textconv.h (struct textconv_interface)
(TEXTCONV_SKIP_CONVERSION_REGION): Update prototype.
* src/xdisp.c (mark_window_display_accurate_1):
* src/xfns.c (xic_string_conversion_callback):
* src/xterm.c (init_xterm): Adjust accordingly.
2023-02-15 12:23:03 +08:00
Po Lu
5a7855e84a Merge remote-tracking branch 'origin/master' into feature/android 2023-02-12 20:40:29 +08:00
Po Lu
19eb27d477 Merge remote-tracking branch 'origin/master' into feature/android 2023-02-12 20:32:31 +08:00
Po Lu
0198b8cffd Update Android port
* doc/emacs/android.texi (Android Environment): Document
notifications permission.
* java/org/gnu/emacs/EmacsEditable.java (EmacsEditable):
* java/org/gnu/emacs/EmacsInputConnection.java
(EmacsInputConnection): New files.
* java/org/gnu/emacs/EmacsNative.java (EmacsNative): Load
library dependencies in a less verbose fashion.
* java/org/gnu/emacs/EmacsView.java (EmacsView): Make imManager
public.
(onCreateInputConnection): Set InputType to TYPE_NULL for now.
* java/org/gnu/emacs/EmacsWindow.java (EmacsWindow, onKeyDown)
(onKeyUp, getEventUnicodeChar): Correctly handle key events with
strings.
* lisp/term/android-win.el (android-clear-preedit-text)
(android-preedit-text): New special event handlers.
* src/android.c (struct android_emacs_window): Add function
lookup_string.
(android_init_emacs_window): Adjust accordingly.
(android_wc_lookup_string): New function.
* src/androidgui.h (struct android_key_event): Improve
commentary.
(enum android_lookup_status): New enum.
* src/androidterm.c (handle_one_android_event): Synchronize IM
lookup code with X.
* src/coding.c (from_unicode_buffer): Implement on Android.
* src/coding.h:
* src/sfnt.c: Fix commentary.
2023-02-12 20:32:25 +08:00
Po Lu
ab48881a2f Fix displaying popup menus from a menu entry on Android
* java/org/gnu/emacs/EmacsActivity.java (EmacsActivity, onDestroy)
(onWindowFocusChanged): Keep track of the last focused activity.
* java/org/gnu/emacs/EmacsDialog.java (display1): Use it if
there is no current focus.
2023-02-11 10:26:34 +08:00
Po Lu
c4c34f72a1 Merge remote-tracking branch 'origin/master' into feature/android 2023-02-11 09:27:59 +08:00
Po Lu
dc120c7ad6 Improve appearance of the Android preferences screen
* .gitignore: Add org/gnu/emacs/R.java.
* cross/Makefile.in (top_builddir): Include verbose.mk.  Rewrite
rules to print nice looking statements.
* doc/emacs/android.texi (Android, Android Startup)
(Android Environment, Android Windowing, Android Fonts):
* doc/emacs/emacs.texi (Top): Add an extra ``Android
Troubleshooting'' node and move troubleshooting details there.
* java/Makefile.in: Generate R.java; improve appearance by using
verbose.mk.

* java/org/gnu/emacs/EmacsPreferencesActivity.java: Reimplement
in terms of PreferencesActivity.
* java/org/gnu/emacs/EmacsView.java (handleDirtyBitmap): Avoid
flicker.
* java/res/xml/preferences.xml: New file.
* src/verbose.mk.in (AM_V_AAPT, AM_V_SILENT): New variables.
2023-02-10 23:03:43 +08:00
Po Lu
2489126e68 Implement more features for the Emacs ``documents provider''
* java/org/gnu/emacs/EmacsDocumentsProvider.java (queryRoots):
Implement isChild.
(getNotificationUri, notifyChange): New functions.
(queryDocument1): Set rename and remove flags.
(queryDocument, queryChildDocuments): Allow the requester to
detect changes in the directory hierarchy.
(createDocument, deleteDocument, removeDocument): Signal changes
to the directory hierarchy.
2023-02-10 21:07:14 +08:00
Po Lu
9b50500b22 ; * java/org/gnu/emacs/EmacsCopyArea.java (perform): Fix typo. 2023-02-10 19:25:10 +08:00
Po Lu
338f4be900 Merge remote-tracking branch 'origin/master' into feature/android 2023-02-10 19:09:37 +08:00
Po Lu
664140fc26 Fix buffer swapping on Android 7.1 and earlier
* java/org/gnu/emacs/EmacsSurfaceView.java
(reconfigureFrontBuffer): Don't use function only present on
Android 8.0 and later.
2023-02-10 19:06:38 +08:00
Po Lu
a1941cd7a7 Update Android port
* doc/emacs/android.texi (Android Windowing): Remove yet another
limitation.
* java/debug.sh: Make this work on systems which prohibit
attaching to app processes from adbd.
* java/org/gnu/emacs/EmacsCopyArea.java (perform): Avoid
creating copies whenever possible.
* java/org/gnu/emacs/EmacsSurfaceView.java (EmacsSurfaceView):
Remove SurfaceView based implementation and use manual double
buffering with invalidate instead.
* java/org/gnu/emacs/EmacsView.java (EmacsView, handleDirtyBitmap)
(raise, lower, onDetachedFromWindow): Adjust accordingly.
* java/org/gnu/emacs/EmacsWindow.java (windowUpdated): Remove
function.
* src/sfntfont.c (sfntfont_open): Set font->max_width correctly.
2023-02-10 18:57:51 +08:00
Po Lu
60270d8ee3 Fix IUP for contours which start past end
Found with Droid Sans Mono hinted with ttfautohint 1.8.4.

* src/sfnt.c (IUP_SINGLE_PAIR): If i is initially more than end,
make it start.
(sfnt_verbose): Handle cases where interpreter->glyph_zone is
NULL.
(main): Update tests.
2023-02-10 17:55:01 +08:00
Po Lu
283f34f09d Fix typo
* src/sfnt.c (sfnt_read_cmap_table): Fix typo.
(main): Update tests.
2023-02-10 10:59:22 +08:00
Po Lu
03c929e528 Merge remote-tracking branch 'origin/master' into feature/android 2023-02-09 22:56:58 +08:00
Po Lu
209ae003b7 Allow other text editors to edit files in Emacs' home directory
* java/AndroidManifest.xml.in: Declare the new documents
provider.
* java/README: Describe the meaning of files in res/values.
* java/org/gnu/emacs/EmacsDocumentsProvider.java
(EmacsDocumentsProvider): New file.
* java/res/values-v19/bool.xml:
* java/res/values/bool.xml: New files.
2023-02-09 22:56:41 +08:00
Po Lu
f0f45ab10d ; * src/sfnt.c (main): Update tests. 2023-02-09 20:32:58 +08:00
Po Lu
85dd157c38 Implement instructing compound glyphs
* src/sfnt.c (sfnt_read_simple_glyph, sfnt_read_compound_glyph)
(sfnt_read_glyph): Take size_t offsets.
(struct sfnt_compound_glyph_context)
(sfnt_expand_compound_glyph_context)
(sfnt_decompose_compound_glyph): Take size_t contour offsets.
(sfnt_decompose_glyph): Always close contour even if the first
point isn't on-curve.
(sfnt_build_outline_edges): Fix coding style.
(sfnt_interpret_iup): Skip phantom points during IUP.
(sfnt_decompose_instructed_outline): Clarify documentation.
Always close contour even if the first point isn't on-curve.
(struct sfnt_test_dcontext, sfnt_test_move_to, sfnt_test_line_to)
(sfnt_test_curve_to, sfnt_transform_f26dot6, sfnt_test_get_glyph)
(sfnt_test_free_glyph, sfnt_test_span, sfnt_test_edge_ignore)
(sfnt_interpret_compound_glyph_2, sfnt_test_edges, main): Update
tests.

* src/sfnt.h: Export new function.

* src/sfntfont.c (sfntfont_get_glyph_outline): Handle compound
glyphs.
(sfntfont_measure_instructed_pcm, sfntfont_measure_pcm)
(sfntfont_draw): Update accordingly.
2023-02-09 20:13:42 +08:00
Po Lu
c201043b4b Update Android port
* src/sfnt.c (SCFS): Fix order of arguments.
(sfnt_normalize_vector): Make sure vx and vy are within a
reasonable range.
(sfnt_move): Don't move when vectors are orthogonal.
(main): Update.
2023-02-08 23:39:46 +08:00
Po Lu
6de4deb47e Update Android port
* doc/emacs/android.texi (Android Startup): Fix typos.
* src/sfnt.c (sfnt_interpret_msirp): Fix order in which operands
to MSIRP are popped.
(main): Reduce ppem values.
2023-02-08 22:51:43 +08:00
Po Lu
2c5e36e00b Merge remote-tracking branch 'origin/master' into feature/android 2023-02-08 22:41:46 +08:00
Po Lu
0bd4b7fdab Update Android port
* doc/lispref/frames.texi (On-Screen Keyboards): Describe return
value of `frame-toggle-on-screen-keyboard'.
* java/org/gnu/emacs/EmacsSurfaceView.java (surfaceChanged)
(surfaceCreated, EmacsSurfaceView): Remove unuseful
synchronization code.  The framework doesn't seem to look at
this at all.

* java/org/gnu/emacs/EmacsView.java (EmacsView):
(onLayout): Lay out the window after children.
(swapBuffers): Properly implement `force'.
(windowUpdated): Delete function.

* lisp/frame.el (frame-toggle-on-screen-keyboard): Return
whether or not the on screen keyboard might've been displayed.

* lisp/minibuffer.el (minibuffer-on-screen-keyboard-timer):
(minibuffer-on-screen-keyboard-displayed):
(minibuffer-setup-on-screen-keyboard):
(minibuffer-exit-on-screen-keyboard): Improve OSK dismissal when
there are consecutive minibuffers.

* lisp/touch-screen.el (touch-screen-window-selection-changed):
New function.
(touch-screen-handle-point-up): Register it as a window
selection changed function.

* src/android.c (struct android_emacs_window)
(android_init_emacs_window): Remove references to
`windowUpdated'.
(android_window_updated): Delete function.
* src/android.h (struct android_output): Remove
`last_configure_serial'.
* src/androidterm.c (handle_one_android_event)
(android_frame_up_to_date):
* src/androidterm.h (struct android_output): Remove frame
synchronization, as that does not work on Android.
2023-02-08 22:40:10 +08:00
Po Lu
7fb0df0ce2 Fix graphics state when instructing glyphs
* src/sfntfont.c (sfntfont_get_glyph_outline): Take new argument
STATE and restore it prior to instructing the glyph.
(sfntfont_measure_instructed_pcm, sfntfont_measure_pcm)
(sfntfont_draw): Adjust accordingly.
2023-02-08 20:03:19 +08:00
Po Lu
ad3def330c Correctly round bearing values while computing pcm
* src/sfntfont.c (sfntfont_measure_instructed_pcm)
(sfntfont_measure_pcm): Ceil rbearing value.
2023-02-08 17:04:42 +08:00
Po Lu
1a70941c8e Improve text display on Android port
* src/sfnt.c (sfnt_build_glyph_outline): Clear
build_outline_context.
(sfnt_poly_coverage): Extend coverage map.
(sfnt_prepare_raster): Always floor coordinates, since the
increase in coverage makes this hack unnecessary.
(sfnt_build_outline_edges): Likewise.
(sfnt_compare_edges): Remove function.
(sfnt_edge_sort): New function.  Since edges are already
partially sorted, and there are not many, insertion sort
suffices.
(sfnt_poly_edges): Use sfnt_edge_sort.
(sfnt_fill_span): Stop rounding x0 and x1 to the grid, and make
coverage computation static.
(sfnt_lookup_glyph_metrics): Fix return code for unscaled
metrics.
(sfnt_scale_metrics): New function.
(SFNT_ENABLE_HINTING): Remove define.
(struct sfnt_cvt_table, struct sfnt_fpgm_table)
(struct sfnt_prep_table): Move to sfnt.h.
(sfnt_read_cvt_table):
(sfnt_read_fpgm_table, sfnt_read_prep_table): Make TEST_STATIC.
(struct sfnt_unit_vector, struct sfnt_interpreter_definition)
(struct sfnt_interpreter_zone, struct sfnt_graphics_state):
(struct sfnt_interpreter): Move to sfnt.h.
(sfnt_make_interpreter): Make TEST_STATIC.
(POP, PUSH, DELTAP1, DELTAP2, DELTAP3): When TEST, define to
regular push and pop.
(sfnt_deltac):
(sfnt_deltap): Fix order of arguments.
(IUP_SINGLE_PAIR): Fix interpolation loop wraparound.
(sfnt_interpret_font_program):
(sfnt_interpret_control_value_program): Make TEST_STATIC.
(struct sfnt_instructed_outline): Move to sfnt.h.
(sfnt_build_instructed_outline): Make TEST_STATIC.
(sfnt_interpret_simple_glyph):
(sfnt_x_raster):
(sfnt_test_raster):
(all_tests):
(sfnt_verbose):
(main): Improve test code.

* src/sfnt.h (SFNT_ENABLE_HINTING, struct sfnt_cvt_table)
(struct sfnt_fpgm_table, struct sfnt_prep_table)
(struct sfnt_unit_vector, struct sfnt_interpreter_definition)
(struct sfnt_interpreter_zone, struct sfnt_graphics_state)
(struct sfnt_interpreter, struct sfnt_instructed_outline)
(PROTOTYPE): New definitions.
* src/sfntfont-android.c (sfntfont_android_put_glyphs): Make
coordinate generation more straightforward.
* src/sfntfont.c (sfntfont_get_glyph_outline): New arguments
INTERPRETER and METRICS.
(struct sfnt_font_info): New tables.
(sfntfont_setup_interpreter): New function.
(sfntfont_open): Avoid memory leak.  Set up interpreter.
(sfntfont_measure_instructed_pcm): New function.
(sfntfont_measure_pcm): Delegate to measure_instructed_pcm where
appropriate.
(sfntfont_close): Free new tables.
(sfntfont_draw): Scale metrics properly.
2023-02-08 16:34:29 +08:00
Po Lu
bd55cca4b8 Merge remote-tracking branch 'origin/master' into feature/android 2023-02-07 23:06:46 +08:00
Po Lu
45d3b0f6dc Remove junk from instruction table
* src/sfnt.c (sfnt_name_instruction): Do so.
2023-02-07 23:03:46 +08:00
Po Lu
712c7450ce Remove bresenham stuff
* src/sfnt.c (sfnt_step_edge, sfnt_step_edge_n)
(sfnt_build_outline_edges, sfnt_test_edge, main):
* src/sfnt.h (struct sfnt_edge): Stop using error corrected line
drawing, as it's actually slower.
2023-02-07 23:03:08 +08:00
Po Lu
795f5a16b5 Update Android port
* INSTALL.android: Describe patches for BoringSSL on ARM.

* src/sfnt.c (sfnt_build_glyph_outline): Remove redundant
multiplication.
(sfnt_prepare_raster): Update offset calculation for changes.
(sfnt_step_edge, sfnt_step_edge_n): Handle bresenham terms.
(sfnt_build_outline_edges): Don't subtract floored xmin, just
xmin.
(sfnt_saturate_short): Make clang generate better code.
(sfnt_fill_span): Stop rounding coordinates.
(sfnt_poly_span): Poly consecutive on transitions all in one go.
(sfnt_lookup_glyph_metrics): Remove redundant multiplication.
(struct sfnt_interpreter): New hooks for debugging.
(sfnt_large_integer_add): New function.
(sfnt_mul_f26dot6_fixed): Round product.
(sfnt_make_interpreter): Remove redundant multiplication.

(CHECK_STACK_ELEMENTS, POP_UNCHECKED, PUSH_UNCHECKED): New
macros.
(MOVE, POP, SWAP, CINDEX, RS, RCVT, LT, LTEQ, GT, GTEQ, EQ, NEQ)
(EVEN, AND, OR, NOT, ADD, SUB, DIV, MUL, ABS, NEG, FLOOR, CEILING)
(GETINFO, ROLL, _MAX, _MIN, ROUND, NROUND, GC, MD): Don't check
SP redundantly, especially when pushing an element right after
popping one.
(sfnt_move_glyph_zone): Don't touch points by passing NULL as
flags.
(sfnt_direct_move_zp2): Touch P in the directions of the
movement.
(sfnt_interpret_scfs): Fix coding style.
(sfnt_interpret_simple_glyph): Don't round Y coordinates.
(sfnt_test_span, sfnt_test_edges, sfnt_debug_edges, sfnt_test_edge)
(sfnt_x_raster, sfnt_test_raster, rcvt_test_args)
(deltac1_test_args, deltac2_test_args, deltac3_test_args)
(roll_1_test_args, sfnt_run_hook, sfnt_identify_instruction)
(sfnt_verbose, main): Improve debug code and tests.

* src/sfnt.h (struct sfnt_edge): Add bresenham terms.
2023-02-07 22:25:54 +08:00
Po Lu
9b79f429ed Port emacsclient wrapper to Android 7.1 and earlier
* java/org/gnu/emacs/EmacsNative.java (EmacsNative): Load every
native library on which Emacs depends prior to loading libemacs
itself.

* java/org/gnu/emacs/EmacsOpenActivity.java (readEmacsClientLog)
(EmacsOpenActivity, startEmacsClient): Don't use redirectError
on Android 7.1 and earlier.
2023-02-06 22:55:42 +08:00
Po Lu
e1c7b8ad61 Adjust ndk-build implementation for old NDK versions
* configure.ac: Pass ANDROID_CFLAGS to ndk_INIT.
* cross/ndk-build/Makefile.in (NDK_BUILD_CFLAGS):
* cross/ndk-build/ndk-build-shared-library.mk
($(call objname,$(LOCAL_MODULE),$(basename $(1)))):
($$(error Unsupported suffix):
* cross/ndk-build/ndk-build-static-library.mk
($(call objname,$(LOCAL_MODULE),$(basename $(1)))):
($$(error Unsupported suffix): Use NDK_BUILD_CFLAGS.
* m4/ndk-build.m4 (ndk_INIT): Accept cflags.
(ndk_CONFIG_FILES): Export NDK_BUILD_CFLAGS.
2023-02-06 22:26:45 +08:00
Po Lu
85d225df87 Merge remote-tracking branch 'origin/master' into feature/android 2023-02-06 22:03:40 +08:00
Po Lu
fc82efc1fe Update Android port
* java/AndroidManifest.xml.in: Prevent the Emacs activity from
being overlayed by the emacsclient wrapper.
* java/org/gnu/emacs/EmacsOpenActivity.java (run): Likewise.
(onCreate): Set an appropriate theme on ICS and up.

* java/org/gnu/emacs/EmacsWindow.java (onTouchEvent): Handle
ACTION_CANCEL correctly.
2023-02-06 22:00:08 +08:00
Po Lu
7275e32d0b Update Android port
* src/sfnt.c (struct sfnt_build_glyph_outline_context)
(sfnt_build_glyph_outline, sfnt_fill_span): Improve glyph
appearance by rounding coordinate values.

(struct sfnt_interpreter): New fields `twilight_original_x',
`twilight_original_y'.
(sfnt_make_interpreter): Set new fields.
(DELTAP1, DELTAP2, DELTAP3, SVTCAy, SPVTL, SFVTL, MD): Implement
instructions.
(sfnt_save_projection_vector): New argument `dual_only'.  All
callers changed.
(sfnt_address_zp2, sfnt_address_zp1, sfnt_address_zp0): Obtain
original positions in the twilight zone as well.
(sfnt_check_zp1, sfnt_interpret_fliprgoff, sfnt_interpret_fliprgon)
(sfnt_interpret_flippt, sfnt_interpret_scfs, sfnt_interpret_miap)
(sfnt_interpret_alignrp, sfnt_line_to_vector, P)
(sfnt_interpret_msirp, sfnt_interpret_ip, sfnt_interpret_call)
(load_point, sfnt_interpret_iup_1, sfnt_interpret_iup)
(sfnt_interpret_run, struct sfnt_scaled_outline)
(struct sfnt_instructed_outline, sfnt_decompose_instructed_outline)
(sfnt_build_instructed_outline, sfnt_compute_phantom_points)
(sfnt_interpret_simple_glyph, all_tests, sfnt_setup_debugger)
(sfnt_name_instruction, sfnt_draw_debugger, sfnt_run_hook)
(sfnt_verbose, main): Make glyph instructing work.

* src/sfnt.h (SFNT_POLY_ROUND): New enumerator.
2023-02-06 21:19:04 +08:00
Po Lu
98c90135fe Update Android port
* INSTALL.android: Explain how to build selinux.
* configure.ac: Enable selinux on Android.
* cross/ndk-build/ndk-build-shared-library.mk: ($(call
objname,$(LOCAL_MODULE),$(basename $(1))))::($$(error
Unsupported suffix)::(NDK_CFLAGS_$(LOCAL_MODULE)):
* cross/ndk-build/ndk-build-static-library.mk: ($(call
objname,$(LOCAL_MODULE),$(basename $(1))))::($$(error
Unsupported suffix)::(NDK_CFLAGS_$(LOCAL_MODULE)): Correctly
handle files with a .cc suffix, and clang-specific asflags.
* cross/ndk-build/ndk-clear-vars.mk: Handle AOSP extensions
LOCAL_ADDITIONAL_DEPENDENCIES,
LOCAL_CLANG_ASFLAGS_$(NDK_BUILD_ARCH) and LOCAL_IS_HOST_MODULE.

* doc/emacs/android.texi (Android Startup): Explain emacsclient
wrapper.

* java/org/gnu/emacs/EmacsView.java (EmacsView): New flag
`isCurrentlyTextEditor'.
(showOnScreenKeyboard, hideOnScreenKeyboard): Set as
appropriate.
(onCheckIsTextEditor): Return its value.

* lisp/touch-screen.el (touch-screen-handle-scroll): Don't ding
at buffer limits.
* m4/ndk-build.m4: Improve doc.

* src/Makefile.in (LIBSELINUX_CFLAGS): New variable.
(EMACS_CFLAGS): Add it.
2023-02-05 23:02:14 +08:00
Po Lu
1b8beed960 Update from gnulib
* admin/merge-gnulib (avoided_flags):
* cross/lib/cdefs.h (__bos):
(__glibc_unsigned_or_positive):
(__glibc_unsafe_len):
(__glibc_fortify):
(__glibc_fortify_n):
* cross/lib/isnan.c:
* cross/lib/libc-config.h:
* cross/lib/openat-proc.c (openat_proc_name):
* cross/lib/vasnprintf.c (VASNPRINTF):
* cross/lib/verify.h (_Static_assert):
(_GL_SA3):
* lib/gnulib.mk.in (HAVE_GRANTPT):
(HAVE_SPAWN_H):
(NEXT_AS_FIRST_DIRECTIVE_LIMITS_H):
(NEXT_LIMITS_H):
(REPLACE_GETSUBOPT):
(REPLACE_ILOGB):
(SYSTEM_TYPE):
(BUILT_SOURCES):
* lib/isnan.c:
* lib/vasnprintf.c (VASNPRINTF):
* lib/verify.h (_GL_SA3):
* m4/gnulib-common.m4 (gl_COMMON_BODY):
* m4/gnulib-comp.m4 (gl_INIT): Update from gnulib.
2023-02-05 21:06:11 +08:00
Po Lu
0ee01457a8 Merge remote-tracking branch 'origin/master' into feature/android 2023-02-05 20:55:21 +08:00
Po Lu
87cdbbeb8a Update Android port
* src/sfnt.c (struct sfnt_graphics_state):
(LOOPCALL):
(DELTAC3):
(PROJECT):
(SHPIX):
(sfnt_save_projection_vector):
(sfnt_check_zp0):
(sfnt_dual_project_vector):
(sfnt_interpret_scfs):
(sfnt_round_symmetric):
(sfnt_interpret_miap):
(sfnt_interpret_alignrp_1):
(sfnt_interpret_alignrp):
(sfnt_measure_distance):
(sfnt_interpret_msirp):
(sfnt_interpret_ip):
(sfnt_interpret_mdap):
(sfnt_deltap):
(sfnt_dual_project_onto_any_vector):
(sfnt_validate_gs):
(sfnt_set_projection_vector):
(sfnt_interpret_shp):
(sfnt_interpret_run):
(sfnt_check_sloop):
(main): Check in more WIP font code.
2023-02-05 20:49:19 +08:00
Po Lu
420533a8f9 Add emacsclient desktop file equivalent on Android
* doc/emacs/android.texi (Android File System):
* java/AndroidManifest.xml.in: Update with new activity.  Remove
Android 10 restrictions through a special flag.

* java/org/gnu/emacs/EmacsNative.java (getProcName): New
function.
* java/org/gnu/emacs/EmacsOpenActivity.java (EmacsOpenActivity):
New file.
* java/org/gnu/emacs/EmacsService.java (getLibraryDirection):
Remove unused annotation.
* lib-src/emacsclient.c (decode_options): Set alt_display on
Android.
* src/android.c (android_proc_name): New function.
(NATIVE_NAME): Export via JNI.
2023-02-04 23:32:07 +08:00
Po Lu
bfce0ce57f Merge remote-tracking branch 'origin/master' into feature/android 2023-02-04 19:50:00 +08:00
Po Lu
9ffb5c0cf3 Add additional permissions to Android port
* doc/emacs/android.texi (Android Environment):
* java/AndroidManifest.xml.in: Add network state permissions.
2023-02-04 19:49:51 +08:00
Po Lu
a2c3b9a787 Update Android port
* src/sfnt.c (sfnt_multiply_divide_signed):
(struct sfnt_interpreter_zone):
(struct sfnt_graphics_state):
(struct sfnt_interpreter):
(sfnt_mul_f2dot14):
(sfnt_interpret_trap):
(WCVTF):
(ALIGNPTS):
(sfnt_scale_by_freedom_vector):
(sfnt_interpret_utp):
(sfnt_address_zp2):
(sfnt_address_zp1):
(sfnt_address_zp0):
(sfnt_check_zp2):
(sfnt_move_zp0):
(sfnt_move_zp1):
(sfnt_move_glyph_zone):
(sfnt_move_twilight_zone):
(sfnt_direct_move_zp2):
(sfnt_interpret_alignpts):
(sfnt_interpret_isect):
(sfnt_line_to_vector):
(sfnt_deltac):
(sfnt_interpret_mdap):
(sfnt_interpret_call):
(sfnt_dot_fix_14):
(sfnt_move_x):
(sfnt_move_y):
(sfnt_move):
(sfnt_validate_gs):
(sfnt_interpret_shz):
(sfnt_interpret_shc):
(sfnt_interpret_shp):
(sfnt_interpret_iup_1):
(sfnt_interpret_iup):
(sfnt_interpret_run):
(sfnt_interpret_font_program):
(sfnt_interpret_control_value_program):
(sfnt_interpret_simple_glyph):
(jrot_test_args):
(jrof_test_args):
(all_tests):
(main): Check in more WIP code.
2023-02-04 19:47:54 +08:00
Po Lu
aa32c9b78b Add Emacs icon for Android package
* java/AndroidManifest.xml.in: Add new icon.
* java/Makefile.in (srcdir): New variable.
(JAVA_FILES, RESOURCE_FILES): Update variables.
(emacs.apk-in): Apply resources.
* java/README: Describe directory tree.
2023-02-02 10:31:10 +08:00
Po Lu
718b1d73d7 Add Emacs icon for Android
* java/res/drawable/emacs.png: New file.
2023-02-02 10:30:15 +08:00
Po Lu
0964328587 Update Android port
* src/android.c (android_get_current_api_level): New function.
* src/android.h: Export it.
* src/sfntfont-android.c (init_sfntfont_android): Make device
API level detection always work.
2023-02-02 10:18:18 +08:00
Po Lu
5a3ce490b9 Clean up compiler warnings
* src/sfnt.c (sfnt_multiply_divide_signed): Add MAYBE_UNUSED.
2023-02-02 10:13:46 +08:00
Po Lu
7b43566a28 Merge remote-tracking branch 'origin/master' into feature/android 2023-02-02 10:11:32 +08:00
Po Lu
adb145f155 Update Android port
* src/sfnt.c (xmalloc, xrealloc): Improve behavior upon
allocation failures during test.
(sfnt_table_names): Add prep.
(sfnt_transform_coordinates): Allow applying offsets during
coordinate transform.
(sfnt_decompose_compound_glyph): Defer offset computation until
any component compound glyph is loaded, then apply it during the
transform process.

(sfnt_multiply_divide): Make available everywhere.  Implement on
64 bit systems.
(sfnt_multiply_divide_signed): New function.
(sfnt_mul_fixed): Fix division overflow.

(sfnt_curve_to_and_build_1, sfnt_build_glyph_outline): Remove
outdated comment.
(sfnt_build_outline_edges): Fix coding style.
(sfnt_lookup_glyph_metrics): Allow looking up metrics without
scaling.
(struct sfnt_cvt_table): Fix type of cvt values.
(struct sfnt_prep_table): New structure.
(sfnt_read_cvt_table): Read cvt values in terms of fwords, not
longs (as Apple's doc seems to say).
(sfnt_read_fpgm_table): Fix memory allocation for font program
table.
(sfnt_read_prep_table): New function.
(struct sfnt_interpreter_zone): New structure.
(struct sfnt_interpreter_graphics_state): New fields `project',
`move', `vector_dot_product'.  Rename to `sfnt_graphics_state'.
(struct sfnt_interpreter, sfnt_mul_f26dot6): Stop doing rounding
division.
(sfnt_init_graphics_state):
(sfnt_make_interpreter):
(MOVE):
(SSW):
(RAW):
(SDS):
(ADD):
(SUB):
(ABS):
(NEG):
(WCVTF):
(_MIN):
(S45ROUND):
(SVTCAx):
(sfnt_set_srounding_state):
(sfnt_skip_code):
(sfnt_interpret_unimplemented):
(sfnt_interpret_fdef):
(sfnt_interpret_idef):
(sfnt_interpret_if):
(sfnt_interpret_else):
(sfnt_round_none):
(sfnt_round_to_grid):
(sfnt_round_to_double_grid):
(sfnt_round_down_to_grid):
(sfnt_round_up_to_grid):
(sfnt_round_to_half_grid):
(sfnt_round_super):
(sfnt_validate_gs):
(sfnt_interpret_run):
(sfnt_interpret_font_program):
(struct sfnt_test_dcontext):
(sfnt_test_move_to):
(sfnt_test_line_to):
(sfnt_test_curve_to):
(sfnt_test_get_glyph):
(sfnt_test_free_glyph):
(sfnt_test_span):
(sfnt_test_edge_ignore):
(sfnt_test_edge):
(sfnt_test_raster):
(test_interpreter_profile):
(test_cvt_values):
(test_interpreter_cvt):
(test_interpreter_head):
(sfnt_make_test_interpreter):
(struct sfnt_interpreter_test):
(sfnt_run_interpreter_test):
(struct sfnt_generic_test_args):
(sfnt_generic_check):
(sfnt_check_srp0):
(sfnt_check_szp0):
(sfnt_check_sloop):
(struct sfnt_rounding_test_args):
(sfnt_check_rounding):
(sfnt_check_smd):
(sfnt_check_scvtci):
(sfnt_check_sswci):
(sfnt_check_ssw):
(sfnt_check_flipon):
(sfnt_check_flipoff):
(npushb_test_args):
(npushw_test_args):
(pushb_test_args):
(pushw_test_args):
(stack_overflow_test_args):
(stack_underflow_test_args):
(rtg_test_args):
(rtg_symmetric_test_args):
(rtg_1_test_args):
(rtg_1_symmetric_test_args):
(rthg_test_args):
(rthg_1_test_args):
(rtdg_test_args):
(rtdg_1_test_args):
(rtdg_2_test_args):
(rtdg_3_test_args):
(else_test_args):
(jmpr_test_args):
(dup_test_args):
(pop_test_args):
(clear_test_args):
(swap_test_args):
(depth_test_args):
(cindex_test_args):
(mindex_test_args):
(raw_test_args):
(loopcall_test_args):
(call_test_args):
(fdef_test_args):
(fdef_1_test_args):
(endf_test_args):
(ws_test_args):
(rs_test_args):
(wcvtp_test_args):
(rcvt_test_args):
(mppem_test_args):
(mps_test_args):
(debug_test_args):
(lt_test_args):
(all_tests):
(main): Implement more instructions.

* src/sfnt.h (enum sfnt_table, struct sfnt_glyph_metrics): Add
new tables.  Add comment.
2023-02-02 10:11:02 +08:00
Po Lu
d8e42afeac Merge remote-tracking branch 'origin/master' into feature/android 2023-01-30 21:49:19 +08:00
Po Lu
eb72569dbe Merge remote-tracking branch 'origin/master' into feature/android 2023-01-30 21:46:52 +08:00
Po Lu
46e8ab23ea Merge remote-tracking branch 'origin/master' into feature/android 2023-01-30 21:19:55 +08:00
Po Lu
f69583941c Update Android port
* cross/ndk-build/ndk-build-shared-library.mk: ($(call
objname,$(LOCAL_MODULE),$(basename $(1)))):
* cross/ndk-build/ndk-build-static-library.mk: ($(call
objname,$(LOCAL_MODULE),$(basename $(1)))): Revert broken typo
fixes.
* src/sfnt.c (TEST_STATIC): Define ARRAYELTS.
(sfnt_table_names): New CVT and FPGM tables.
(sfnt_decompose_compound_glyph, sfnt_decompose_glyph)
(struct sfnt_large_integer, sfnt_multiply_divide_1)
(sfnt_count_leading_zero_bits, sfnt_multiply_divide_2)
(sfnt_multiply_divide, sfnt_mul_fixed, sfnt_div_fixed)
(sfnt_ceil_fixed, sfnt_build_glyph_outline): Fix fixed point
multiplication routines on systems without 64 bit long long
type.
(SFNT_ENABLE_HINTING, struct sfnt_test_dcontext, sfnt_test_move_to)
(sfnt_test_line_to, sfnt_test_curve_to, sfnt_test_get_glyph)
(sfnt_test_free_glyph, sfnt_test_span, sfnt_test_edge_ignore)
(sfnt_read_cvt_table, sfnt_test_edge, sfnt_test_raster)
(sfnt_read_fpgm_table, struct sfnt_unit_vector)
(struct sfnt_interpreter_definition)
(struct sfnt_interpreter_graphics_state, struct sfnt_interpreter)
(sfnt_div_f26dot6, sfnt_mul_f26dot6, sfnt_floor_f26dot6)
(sfnt_ceil_f26dot6, sfnt_round_f26dot6, sfnt_init_graphics_state)
(sfnt_make_interpreter, enum sfnt_interpreter_run_context)
(sfnt_interpret_trap, STACKSIZE, sfnt_set_srounding_state)
(sfnt_skip_code, sfnt_interpret_unimplemented, sfnt_interpret_fdef)
(sfnt_interpret_idef, sfnt_interpret_if, sfnt_interpret_else)
(sfnt_round_none, sfnt_round_to_grid, sfnt_round_to_double_grid)
(sfnt_round_down_to_grid, sfnt_round_up_to_grid)
(sfnt_round_to_half_grid, sfnt_round_super, sfnt_validate_gs)
(sfnt_interpret_run, sfnt_interpret_font_program)
(test_interpreter_profile, test_cvt_values, test_interpreter_cvt)
(test_interpreter_head, sfnt_make_test_interpreter)
(struct sfnt_interpreter_test, sfnt_run_interpreter_test)
(struct sfnt_generic_test_args, sfnt_generic_check)
(sfnt_check_srp0, sfnt_check_szp0, sfnt_check_sloop)
(struct sfnt_rounding_test_args, sfnt_check_rounding)
(sfnt_check_smd, sfnt_check_scvtci, sfnt_check_sswci)
(sfnt_check_ssw, sfnt_check_flipon, sfnt_check_flipoff)
(npushb_test_args, npushw_test_args, pushb_test_args)
(pushw_test_args, stack_overflow_test_args)
(stack_underflow_test_args, rtg_test_args, rtg_symmetric_test_args)
(rtg_1_test_args, rtg_1_symmetric_test_args, rthg_test_args)
(rthg_1_test_args, rtdg_test_args, rtdg_1_test_args)
(rtdg_2_test_args, rtdg_3_test_args, else_test_args)
(jmpr_test_args, dup_test_args, pop_test_args, clear_test_args)
(swap_test_args, depth_test_args, cindex_test_args)
(mindex_test_args, raw_test_args, loopcall_test_args)
(call_test_args, fdef_test_args, fdef_1_test_args, endf_test_args)
(ws_test_args, rs_test_args, wcvtp_test_args, rcvt_test_args)
(mppem_test_args, mps_test_args, debug_test_args, lt_test_args)
(all_tests, main): Check in WIP hinting code.

* src/sfnt.h (enum sfnt_table): Add `cvt ' and `fpgm' tables.
2023-01-30 21:19:33 +08:00
Po Lu
d272df1817 Merge remote-tracking branch 'origin/master' into feature/android 2023-01-29 19:02:37 +08:00
Po Lu
ad90fe7db7 Check in missing files
* .gitignore:
* cross/lib/_Noreturn.h (_Noreturn): Add missing gnulib files.
2023-01-29 12:48:54 +08:00
Po Lu
492aa74b13 Update Android port
* INSTALL.android (module_target): Clarify documentation.
* cross/ndk-build/ndk-build-shared-library.mk:
* cross/ndk-build/ndk-build-static-library.mk: Fix building Neon objects.
* java/AndroidManifest.xml.in: Add a version code.
2023-01-29 11:21:07 +08:00
Po Lu
f9e32ce157 Implement `restart-emacs' on Android
* java/org/gnu/emacs/EmacsService.java (restartEmacs): New
function.
* src/android.c (struct android_emacs_service)
(android_init_emacs_service): Add new method.
(android_restart_emacs): New function.
* src/android.h: Update prototypes.
* src/emacs.c (Fkill_emacs): Call android_restart_emacs whenever
appropriate.
2023-01-28 21:21:45 +08:00
Po Lu
22749d69e5 Add libtiff support to Android port
* INSTALL.android: Document how to build with libtiff.

* build-aux/ndk-build-helper-1.mk (NDK_SO_NAME):
* build-aux/ndk-build-helper-2.mk (NDK_A_NAME):
* build-aux/ndk-build-helper-4.mk: Decrease number of duplicate
dependencies found.
* configure.ac (ANDROID_SDK_18_OR_EARLIER, XCONFIGURE, PNG_CFLAGS)
(HAVE_TIFF): Allow using libtiff on Android.
* cross/ndk-build/ndk-clear-vars.mk: Undefine additional
variables.
* cross/ndk-build/ndk-resolve.mk: Split CFLAGS resolution from
a-name resolution, and do not recursively add archive or shared
object names for dependencies of shared libraries.

* src/Makefile.in (TIFF_CFLAGS): New variable.
(EMACS_CFLAGS): Use it.
2023-01-28 20:47:26 +08:00
Po Lu
1ba1f277b6 ; * src/image.c (syms_of_image): Fix typo. 2023-01-28 16:33:50 +08:00
Po Lu
198b8160cf Update Android port
* doc/emacs/android.texi (Android File System): Describe an
easier way to disable scoped storage.
* java/AndroidManifest.xml.in: Add new permission to allow that.
* java/README: Add more text describing Java.
* java/org/gnu/emacs/EmacsContextMenu.java (Item): New fields
`isCheckable' and `isChecked'.
(EmacsContextMenu, addItem): New arguments.
(inflateMenuItems): Set checked status as appropriate.

* java/org/gnu/emacs/EmacsCopyArea.java (perform): Disallow
operations where width and height are less than or equal to
zero.
* lisp/menu-bar.el (menu-bar-edit-menu): Make
execute-extended-command available as a menu item.
* src/androidmenu.c (android_init_emacs_context_menu)
(android_menu_show):
* src/menu.c (have_boxes): Implement menu check boxes.
2023-01-28 16:29:22 +08:00
Po Lu
5bd38905ac Set up fontset stuff on Android
* lisp/term/android-win.el (window-system-initialization):
Create default fontset.
2023-01-28 15:25:50 +08:00
Po Lu
32910a0ef0 Fix file descriptor leaks
* src/sfntfont.c (sfntfont_read_cmap):
(sfntfont_open): Fix leaks of file descriptors.
2023-01-28 15:25:29 +08:00
Po Lu
6f2a518f27 Update from gnulib
* cross/lib/stdalign.in.h (_GL_STDALIGN_H):
(_):
(__alignof_is_defined):
* cross/lib/vasnprintf.c:
* lib/gnulib.mk.in (ANDROID_MIN_SDK):
(HAVE_SPAWN_H):
(LIBGCCJIT_LIBS):
(NATIVE_COMPILATION_AOT):
(NEXT_AS_FIRST_DIRECTIVE_LIMITS_H):
(NEXT_LIMITS_H):
(SIZEOF_LONG):
(stdalign.h):
* ../../../../dev/null:
* lib/stdalign.in.h (_GL_STDALIGN_H):
(_):
(__alignof_is_defined):
* lib/vasnprintf.c:
* m4/gnulib-common.m4 (gl_COMMON_BODY):
* m4/stdalign.m4 (gl_ALIGNASOF):
* m4/stddef_h.m4: Update from gnulib.
2023-01-28 14:33:58 +08:00
Po Lu
8732a5bd78 Merge remote-tracking branch 'origin/master' into feature/android 2023-01-28 14:30:27 +08:00
Po Lu
e3b50ec8ec Update Android port
* INSTALL.android: Document support for gnutls and libgmp.
* build-aux/ndk-build-helper-1.mk (NDK_SO_NAMES, NDK_INCLUDES)
(SYSTEM_LIBRARIES):
* build-aux/ndk-build-helper-2.mk: Recursively resolve and add
shared library dependencies; even those of static libraries.
* build-aux/ndk-module-extract.awk: Fix makefile_imports code.
* configure.ac (ANDROID_SDK_18_OR_EARLIER, XCONFIGURE)
(LIBGMP_CFLAGS): Enable GMP and gnutls on Android.

* cross/ndk-build/Makefile.in (LOCAL_EXPORT_C_INCLUDES):
* cross/ndk-build/ndk-build-shared-library.mk: ($(call
objname,$(LOCAL_MODULE),$(basename $(1))))::($$(error
Unsupported suffix)::($(LOCAL_MODULE_FILENAME)):
* cross/ndk-build/ndk-build-static-library.mk: ($(call
objname,$(LOCAL_MODULE),$(basename $(1))))::($$(error
Unsupported suffix):
* cross/ndk-build/ndk-clear-vars.mk:
* cross/ndk-build/ndk-resolve.mk (NDK_SYSTEM_LIBRARIES):
(NDK_LOCAL_EXPORT_C_INCLUDES_$(LOCAL_MODULE)):
(NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE)):
Implement ``LOCAL_ASM_RULE'' and ``LOCAL_C_ADDITIONAL_FLAGS''
extensions for libgmp.

* doc/emacs/input.texi (Touchscreens): Document how to
horizontally scroll.
* java/org/gnu/emacs/EmacsActivity.java (attachWindow): Give the
view focus again if necessary.
(onPause): Call right super function.
* java/org/gnu/emacs/EmacsPreferencesActivity.java (onClick):
Clear dumpFileName lest Emacs try to load a nonexistent dump
file.
* java/org/gnu/emacs/EmacsView.java (onDetachedFromWindow)
(onAttachedToWindow): Call super functions.
(onCreateInputConnection): Make sure the IME never obscures
Emacs.
* java/org/gnu/emacs/EmacsWindow.java (EmacsWindow, onKeyDown)
(onKeyUp): Improve tracking of quit keys.

* lisp/isearch.el (isearch-mode): Bring up the onscreen
keyboard.
* lisp/touch-screen.el (touch-screen-current-tool): Add three
fields.
(touch-screen-handle-scroll): Allow hscrolling as well.
(touch-screen-handle-touch): Add additional fields to
`touch-screen-current-tool'.
* src/Makefile.in (LIBGMP_CFLAGS, EMACS_CFLAGS): Add new
variable.
* src/android.c (android_run_select_thread):
(android_write_event): Use pthread_cond_broadcast because
pthread_cond_signal does nothing on some Android
versions/devices?
2023-01-28 14:29:51 +08:00
Po Lu
65dddd7c99 Merge remote-tracking branch 'origin/master' into feature/android 2023-01-26 22:19:31 +08:00
Po Lu
f459c43e94 * doc/emacs/input.texi (On-Screen Keyboards): Fix typo. 2023-01-26 22:14:39 +08:00
Po Lu
b0e7ae6d5b Update Android port
* INSTALL.android: Describe that apksigner is also required.
* configure.ac: Correctly add cross/Makefile to
SUBDIR_MAKEFILES.
* cross/Makefile.in: (config.status): Depend on
$(top_srcdir)/config.status.
* doc/emacs/input.texi (On-Screen Keyboards): Document how to
quit without a physical keyboard.
* java/org/gnu/emacs/EmacsNative.java (EmacsNative): New
function `quit'.
* java/org/gnu/emacs/EmacsWindow.java (EmacsWindow): New field
`lastVolumeButtonPress'.
(onKeyDown): Quit if necessary.
* m4/ndk-build.m4 (ndk_where_cc): Fix search if CC is not a
single word.
* src/android.c (android_open): Remove unused variable.
(quit): New function.
* src/androidmenu.c (android_process_events_for_menu): Allow
quitting the menu.
* src/xterm.c (handle_one_xevent, x_term_init, syms_of_xterm):
Implement features described above, so they work on free
operating systems.
* src/xterm.h (struct x_display_info): New fields `quit_keysym',
`quit_keysym_time'.
2023-01-26 22:11:04 +08:00
Po Lu
22f7ad1057 Update Android port
* INSTALL.android: Document how to install sqlite3.
* build-aux/ndk-build-helper-1.mk (SYSTEM_LIBRARIES):
* build-aux/ndk-build-helper-2.mk (SYSTEM_LIBRARIES): Add liblog
and libandroid.
* configure.ac (SQLITE3_LIBS, HAVE_SQLITE3)
(HAVE_SQLITE3_LOAD_EXTENSION): Support on Android.
(APKSIGNER): Look for this new required binary.

* cross/ndk-build/ndk-build-shared-library.mk (objname):
* cross/ndk-build/ndk-build-static-library.mk (objname): Avoid
duplicate rules by prefixing objects with module type.

* cross/ndk-build/ndk-build.mk.in (NDK_BUILD_SHARED): Fix
definition.
* cross/ndk-build/ndk-resolve.mk:
(NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE)): Handle new system
libraries.

* doc/emacs/android.texi (Android File System): Document Android
10 system restriction.

* java/AndroidManifest.xml.in: Target Android 33, not 28.
* java/Makefile.in (SIGN_EMACS_V2, APKSIGNER): New variables.
($(APK_NAME)): Make sure to apply a ``version 2 signature'' to
the package as well.

* java/org/gnu/emacs/EmacsNative.java (EmacsNative): New
argument apiLevel.
* java/org/gnu/emacs/EmacsNoninteractive.java (main):
* java/org/gnu/emacs/EmacsThread.java (run): Pass API level.
* m4/ndk-build.m4 (ndk_package_mape): Add package mapping for
sqlite3.
* src/Makefile.in (SQLITE3_CFLAGS): New substition.
(EMACS_CFLAGS): Add that variable.

* src/android.c (android_api_level): New variable.
(initEmacs): Set it.
(android_file_access_p): Make static.
(android_hack_asset_fd): Adjust for restrictions in Android 29
and later.
(android_close_on_exec): New function.
(android_open): Adjust to not duplicate file descriptor even if
CLOEXEC.
(android_faccessat): Use fstatat at-func emulation.

* src/android.h: Update prototypes.
* src/dired.c (file_name_completion_dirp):
* src/fileio.c (file_access_p, Faccess_file): Now that
sys_faccessat takes care of everything, stop calling
android_file_access_p.
2023-01-26 19:54:38 +08:00
Po Lu
4255d7f051 Update Android port
* .gitignore: Ignore lib/math.h.
* INSTALL.android: Update accordingly.
* build-aux/ndk-build-helper-1.mk:
* build-aux/ndk-build-helper-2.mk:
* build-aux/ndk-build-helper.mk:
* build-aux/ndk-module-extract.awk: Handle C++ modules.
* configure.ac: Enable libxml2 on Android.

* cross/ndk-build/Makefile.in:
* cross/ndk-build/ndk-build-shared-library.mk:
* cross/ndk-build/ndk-build-static-library.mk:
* cross/ndk-build/ndk-build.mk.in:
* cross/ndk-build/ndk-resolve.mk: Fix dependency resolution of
includes.

* java/org/gnu/emacs/EmacsView.java (popupMenu): Fix minimum SDK
version for actual popup menus.
* lib/math.h: Delete file.

* m4/ndk-build.m4 (ndk_SEARCH_MODULE, ndk_CHECK_MODULES): Look
for nasm and C++ libraries.

* src/android.c (faccessat): Rename to `android_faccessat'.
* src/android.h: Update prototypes.
* src/dired.c (file_name_completion_dirp):
* src/fileio.c (file_access_p, Faccess_file, file_directory_p):
* src/lisp.h:
* src/lread.c (openp):
* src/process.c (allocate_pty): Use sys_faccessat.
* src/sysdep.c (sys_faccessat): New function.
2023-01-26 15:37:04 +08:00
Po Lu
8125e26a32 Remove unused file
* cross/ndk-build/ndk-build.in: Delete unused file.
2023-01-26 14:13:24 +08:00
Po Lu
0b1ef9ea31 Update Android port
* java/org/gnu/emacs/EmacsDrawLine.java: Fix this again.  Gosh,
how does Android do this.
* java/org/gnu/emacs/EmacsNoninteractive.java (main): Port to
Android 2.3.3.

* java/org/gnu/emacs/EmacsSdk11Clipboard.java
(EmacsSdk11Clipboard): Port to Android 4.0.3.
* java/org/gnu/emacs/EmacsService.java (getClipboardManager):
New function.

* src/alloc.c (find_string_data_in_pure): Fix Android alignment
issue.

* src/android-emacs.c (main): Port to Android 4.4.
* src/android.c (initEmacs): Align stack to 32 bytes, so it ends
up aligned to 16 even though gcc thinks the stack is already
aligned to 16 bytes.

* src/callproc.c (init_callproc): Use /system/bin/sh instead of
/bin/sh by default.
2023-01-25 22:07:51 +08:00
Po Lu
d3b29ccc89 Remove extra header
* cross/lib/math.h: Delete header.
2023-01-25 22:05:15 +08:00
Po Lu
888d351496 Minor fixes to Android port
* java/Makefile.in: (emacs.apk-in): Don't call cp with empty
args.
* java/org/gnu/emacs/EmacsDrawLine.java (perform): Fix for
PostScript filling semantics.
* src/Makefile.in (android-emacs): Build android-emacs directly.
2023-01-25 19:15:30 +08:00
Po Lu
d63ee136d9 Merge remote-tracking branch 'origin/master' into feature/android 2023-01-25 18:45:09 +08:00
Po Lu
0900bfbcc5 Update Android port
* doc/emacs/android.texi (Android Startup, Android Environment):
Document that restrictions on starting Emacs have been lifted.

* java/README: Document Java for Emacs developers and how the
Android port works.

* java/org/gnu/emacs/EmacsApplication.java (EmacsApplication)
(findDumpFile): New function.
(onCreate): Factor out dump file finding functions to there.

* java/org/gnu/emacs/EmacsNative.java (EmacsNative): Update
function declarations.
* java/org/gnu/emacs/EmacsNoninteractive.java
(EmacsNoninteractive): New class.

* java/org/gnu/emacs/EmacsService.java (EmacsService, getApkFile)
(onCreate): Pass classpath to setEmacsParams.
* java/org/gnu/emacs/EmacsThread.java (EmacsThread): Make run an
override.
* lisp/loadup.el: Don't dump on Android when noninteractive.
* lisp/shell.el (shell--command-completion-data): Handle
inaccessible directories.
* src/Makefile.in (android-emacs): Link with gnulib.
* src/android-emacs.c (main): Implement to launch app-process
and then EmacsNoninteractive.
* src/android.c (setEmacsParams): New argument `class_path'.
Don't set stuff up when running noninteractive.
* src/android.h (initEmacs): Likewise.
* src/androidfont.c (init_androidfont):
* src/androidselect.c (init_androidselect): Don't initialize
when running noninteractive.
* src/emacs.c (load_pdump): New argument `dump_file'.
(android_emacs_init): Give new argument `dump_file' to
`load_pdump'.
* src/sfntfont-android.c (init_sfntfont_android): Don't
initialize when running noninteractive.
2023-01-25 18:44:47 +08:00
Po Lu
6f9a2a8f29 Import gnulib modules printf-posix and vasprintf-posix
These are neccessary because Android's printf is missing basic format
modifiers such as t.

* admin/merge-gnulib (GNULIB_MODULES): Add printf-posix and
vasprintf-posix.  Update from gnulib.
* configure.ac (CFLAGS): Add -DHAVE_CONFIG_H.
2023-01-25 18:39:36 +08:00
Po Lu
9082b4e6ee Make binaries distributed with Emacs work on Android
* doc/lispref/processes.texi (Subprocess Creation): Document
variables containing program names.
* etc/NEWS: Document new variables.
* java/Makefile.in (CROSS_BINS): Add missing etags binary.
* lisp/cedet/semantic/db-ebrowse.el
(semanticdb-create-ebrowse-database):
* lisp/gnus/mail-source.el (mail-source-movemail-program):
* lisp/hexl.el (hexl-program):
* lisp/htmlfontify.el (hfy-etags-bin):
* lisp/ielm.el (inferior-emacs-lisp-mode):
* lisp/mail/rmail.el (rmail-autodetect):
(rmail-insert-inbox-text):
* lisp/org/org-ctags.el (org-ctags-path-to-ctags):
* lisp/progmodes/cperl-mode.el (cperl-etags):
* lisp/speedbar.el (speedbar-fetch-etags-command):
* lisp/textmodes/reftex-global.el (reftex-create-tags-file): Use
new variables.
* src/callproc.c (syms_of_callproc): New variables naming
binaries redistributed with Emacs.
2023-01-24 21:37:22 +08:00
Po Lu
54836c47c7 Enable libjpeg on Android
* INSTALL.android: Update documentation.
* build-aux/ndk-build-helper-1.mk: When building shared
libraries, do not link libemacs.so with dependent archive files.
* build-aux/ndk-build-helper-2.mk: Add whole archive
dependencies as well.

* configure.ac (HAVE_JPEG): Enable on Android.

* cross/ndk-build/ndk-build-shared-library.mk: Link the shared
object with archive file dependencies.
* cross/ndk-build/ndk-build-static-library.mk: Build all code
position-independently.
* cross/ndk-build/ndk-resolve.mk: Separately resolve a names of
archive and whole archive dependencies.

* src/Makefile.in (JPEG_CFLAGS): New variable.
(EMACS_CFLAGS): Add it.
2023-01-24 19:10:58 +08:00
Po Lu
56e55a8008 Update Android port
* INSTALL.android: Update.
* build-aux/ndk-build-helper-1.mk: Fix typo.
* configure.ac: Enable --with-json on Android.
* cross/ndk-build/ndk-build-shared-library.mk:
(NDK_CFLAGS_$(LOCAL_MODULE)):
(LOCAL_MODULE_FILENAME):
* cross/ndk-build/ndk-build-static-library.mk:
(ALL_OBJECT_FILES$(LOCAL_MODULE)):
(LOCAL_MODULE_FILENAME): Recursively resolve dependencies.
* cross/ndk-build/ndk-resolve.mk: New function.

* doc/emacs/android.texi (Android Startup): Document how Emacs
is dumped during initial startup.

* java/Makefile.in (filename): Fix build with multiple shared
libraries.
* java/README: Improve commentary.
* java/org/gnu/emacs/EmacsApplication.java (onCreate): Look and
set dump file.
* java/org/gnu/emacs/EmacsNative.java (EmacsNative): New
function getFingerprint.
* java/org/gnu/emacs/EmacsPreferencesActivity.java (onCreate):
Add option to erase the dump file.
* java/org/gnu/emacs/EmacsService.java (browseUrl): New
function.
* java/org/gnu/emacs/EmacsThread.java (run): Specify dump file
if found.
* lisp/loadup.el: Always dump during loadup on Android.

* lisp/net/browse-url.el (browse-url--browser-defcustom-type):
(browse-url-default-browser):
(browse-url-default-android-browser): New browse url type.

* m4/ndk-build.m4 (ndk_package_map): Map jansson to libjansson.
* src/android.c (struct android_emacs_service): New method
`browse_url'.
(getFingerprint): New function.
(android_init_emacs_service): Initialize new method.
(android_browse_url): New function.

* src/android.h: Update prototypes.

* src/androidselect.c (Fandroid_browse_url): New function.
(syms_of_androidselect): Define it.

* src/emacs.c (load_pdump): Don't look in fancy places on
Android.
* src/pdumper.c (Fdump_emacs_portable): Allow dumping while
interactive on Android.
(syms_of_pdumper): New variable `pdumper-fingerprint'.

* src/sfntfont-android.c (sfntfont_android_composite_bitmap):
Fix unused variables.
2023-01-24 17:31:16 +08:00
Po Lu
3267a2d6d2 Update from gnulib
Update from gnulib.  In addition,

* admin/merge-gnulib: Fix paths for rename.
2023-01-24 10:46:53 +08:00
Po Lu
2b00f66926 Improve lib-src/Makefile.in
* lib-src/Makefile.in (DONT_INSTALL):
(clean): Correctly define asset-directory-tool.
2023-01-24 10:40:44 +08:00
Po Lu
8acab73908 Merge remote-tracking branch 'origin/master' into feature/android 2023-01-24 10:38:07 +08:00
Po Lu
47d731d214 Fix distclean target
* cross/Makefile.in (distclean bootstrap-clean): Remove Makefile.
2023-01-24 10:37:26 +08:00
Po Lu
4de6b18793 Update Android port
* .gitignore: Update with new files.  Do not ignore std*.in.h.
* INSTALL.android: Explain how to build Emacs with external
dependencies.

* Makefile.in (xcompile, cross): Rename to `cross'.
(clean_dirs): Clean cross, not xcompile.

* README: Document new directories.

* build-aux/ndk-build-helper-1.mk (build_kind, NDK_SO_NAMES):
* build-aux/ndk-build-helper-2.mk (build_kind, NDK_SO_NAMES):
* build-aux/ndk-build-helper-3.mk (build_kind):
* build-aux/ndk-build-helper-4.mk:
* build-aux/ndk-build-helper.mk (NDK_BUILD_DIR, my-dir):
* build-aux/ndk-module-extract.awk: New files.
* configure.ac: Set up libgif, libwebp, and libpng for
ndk-build.
* cross/ndk-build/Makefile.in (srcdir, NDK_BUILD_ANDROID_MK):
* cross/ndk-build/ndk-build-executable.mk:
* cross/ndk-build/ndk-build-shared-library.mk (eq, objname):
* cross/ndk-build/ndk-build-static-library.mk (eq, objname):
* cross/ndk-build/ndk-build.in (NDK_BUILD_MODULES):
* cross/ndk-build/ndk-build.mk.in (NDK_BUILD_MODULES)
(NDK_BUILD_SHARED):
* cross/ndk-build/ndk-clear-vars.mk:
* cross/ndk-build/ndk-prebuilt-shared-library.mk:
* cross/ndk-build/ndk-prebuilt-static-library.mk: New files.
* doc/emacs/android.texi (Android, Android Environment):
Document clipboard support on Android.
* doc/emacs/emacs.texi (Top): Update menus.
* etc/MACHINES: Document Android.
* java/AndroidManifest.xml.in: Respect new
`--with-android-debug' option.
* java/Makefile.in (CROSS_BINS, CROSS_LIBS): Adjust for rename.
Include ndk-build.mk.:(emacs.apk-in): Depend on shared
libraries.  Then, package shared libraries.
* java/org/gnu/emacs/EmacsClipboard.java (EmacsClipboard): New
class.
* java/org/gnu/emacs/EmacsFontDriver.java: Update comment to say
this is unused.
* java/org/gnu/emacs/EmacsNative.java (EmacsNative): New
function `sendExpose'.
* java/org/gnu/emacs/EmacsSdk11Clipboard.java
(EmacsSdk11Clipboard):
* java/org/gnu/emacs/EmacsSdk8Clipboard.java
(EmacsSdk8Clipboard): New classes.
* java/org/gnu/emacs/EmacsView.java (EmacsView, handleDirtyBitmap)
(onDetachedFromWindow): When window is reattached, expose the
frame.

* lib/Makefile.in (VPATH):
(ALL_CFLAGS): Adjust for rename.

* lisp/term/android-win.el (android-clipboard-exists-p)
(android-get-clipboard, android-set-clipboard)
(android-clipboard-owner-p, android-primary-selection)
(android-get-clipboard-1, android-get-primary)
(android-selection-bounds, android-encode-select-string)
(gui-backend-get-selection, gui-backend-selection-exists-p)
(gui-backend-selection-owner-p, gui-backend-set-selection): New
functions.

* m4/ndk-build.m4: New file.
* src/Makefile.in (GIF_CFLAGS, ANDROID_LDFLAGS): New variables.
(EMACS_CFLAGS): Add GIF_CFLAGS.  Include
ndk-build.mk.
(libemacs.so): Depend on and link with required
libraries.

* src/android.c (android_check_compressed_file): New function.
(android_open): Work around Android platform bug.
(sendExpose): New function.
(android_readdir): Set d_type if this is a directory.

* src/androidgui.h (enum android_event_type)
(struct android_expose_event, union android_event): Add expose
events.

* src/androidselect.c (struct android_emacs_clipboard)
(android_init_emacs_clipboard, Fandroid_clipboard_owner_p)
(Fandroid_set_clipboard, Fandroid_get_clipboard)
(Fandroid_clipboard_exists_p, init_androidselect)
(syms_of_androidselect): New file.

* src/androidterm.c (handle_one_android_event): Handle
exposures.
* src/androidterm.h: Update prototypes.
* src/emacs.c (android_emacs_init): Initialize androidselect.
2023-01-24 10:34:40 +08:00
Po Lu
9d3aacedf0 Update android port
* xcompile: Move to cross.
* cross: New directory.
2023-01-24 10:24:13 +08:00
Po Lu
de3d8ae71b Update android port
* xcompile: Move to cross.
* cross: New directory.
2023-01-24 10:23:52 +08:00
Po Lu
62da1e5742 Improve touch-screen support
* doc/lispref/commands.texi (Touchscreen Events): Document
changes.
* lisp/touch-screen.el (touch-screen-current-tool): Update doc
string.
(touch-screen-precision-scroll): New user option.
(touch-screen-handle-scroll): Use traditional scrolling by
default.
(touch-screen-handle-touch): Adust format of
touch-screen-current-tool.
(touch-screen-track-tap): Don't print waiting for events.
(touch-screen-track-drag): Likewise.  Also, don't call UPDATE
until threshold is reached.
(touch-screen-drag-mode-line-1, touch-screen-drag-mode-line):
Improve window dragging.
2023-01-21 21:46:32 +08:00
Po Lu
00fec0dd95 ; * src/fileio.c (Fverify_visited_file_modtime): Fix fs check. 2023-01-21 21:18:44 +08:00
Po Lu
5f6971e5cb Merge remote-tracking branch 'origin/master' into feature/android 2023-01-21 20:04:52 +08:00
Po Lu
aaacf24ca2 Update Android port
* doc/emacs/android.texi (Android File System): Document that
ls-lisp is now used by default.
* java/org/gnu/emacs/EmacsThread.java (EmacsThread): Name the
thread something meaningful.
* lisp/loadup.el (featurep): Load ls-lisp on Android.
* lisp/ls-lisp.el (ls-lisp-use-insert-directory-program):
Default to off on Android.
* src/android.c (android_is_directory): New fucntion.
(android_fstatat): Handle directories created by
`android_opendir'.
(android_open): Return meaningful file mode.
(struct android_dir): New fields `next', `asset_file' and `fd'.
(android_opendir): Populate those fields.
(android_dirfd): New function.
(android_closedir): Close file descriptor if set.
(android_lookup_asset_directory_fd): New function.

* src/android.h: Update prototypes.
* src/androidfont.c (androidfont_check_init): New function.
(androidfont_list, androidfont_match, androidfont_draw)
(androidfont_open_font, androidfont_close_font)
(androidfont_has_char, androidfont_encode_char)
(androidfont_text_extents, androidfont_list_family): Initialize
font driver if necessary.
(init_androidfont): Don't initialize Java font if necessary.

* src/dired.c (open_directory): Return android_dirfd if
appropriate.
(directory_files_internal, file_name_completion_dirp): Implement
correctly for Android.

* src/fileio.c (check_mutable_filename): New function.
(Fcopy_file, Fdelete_directory_internal, Fdelete_file)
(Frename_file, Fadd_name_to_file, Fmake_symbolic_link)
(Fset_file_modes, Fset_file_times, Ffile_newer_than_file_p)
(Fverify_visited_file_modtime, Fset_visited_file_modtime): Check
that files being written to do not lie in /assets.

* src/sfntfont-android.c (GET_SCANLINE_BUFFER)
(sfntfont_android_u255to256, sfntfont_android_over_8888_1)
(sfntfont_android_over_8888, sfntfont_android_composite_bitmap):
Optimize on 64-bit ARM devices.
(sfntfont_android_put_glyphs): Optimize away memset if
background need not be filled.
2023-01-21 20:03:37 +08:00
Po Lu
a03eeb0109 Merge remote-tracking branch 'origin/master' into feature/android 2023-01-20 22:17:48 +08:00
Po Lu
761c763dd6 Update Android port
* src/android.c (android_run_select_thread, android_select)
(android_ftruncate):
* src/android.h (ftruncate): Fix compilation on Android 16 and
up.
2023-01-20 22:15:53 +08:00
Po Lu
26f0dd5089 Update Android port
* src/android.c (android_run_select_thread, android_init_events)
(android_select): Add alternative android_select implementation
for API 16 and lower.
* src/androidterm.c (handle_one_android_event): Fix
use-after-frees.
2023-01-20 21:21:15 +08:00
Po Lu
01ee2bd07b Remove unused file
* xcompile/lib/gnulib.mk.in: Delete.
2023-01-20 19:19:16 +08:00
Po Lu
d44b60c2f0 Update Android port
* .gitignore: Don't ignore verbose.mk.android.
* doc/emacs/Makefile.in (EMACSSOURCES): Add android.texi and
input.texi.
* doc/emacs/android.texi (Android): Document support for the
on-screen keyboard.
(Android Startup): Document how to start Emacs with -Q on
Android.
(Android Environment): Document how Emacs works around the
system ``task killer''.  Document changes to frame deletion
behavior.
* doc/emacs/emacs.texi (Top):
* doc/emacs/input.texi (Other Input Devices, On-Screen
Keyboards): Document how to use Emacs with virtual keyboards.
* doc/lispref/commands.texi (Touchscreen Events): Document
changes to `touch-screen-track-drag'.
* doc/lispref/frames.texi (Frames, On-Screen Keyboards): New
node.
* java/AndroidManifest.xml.in: Add settings activity and
appropriate OSK adjustment mode.
* java/org/gnu/emacs/EmacsActivity.java (onCreate): Allow
creating Emacs with -Q.
(onDestroy): Don't remove if killed by the system.
* java/org/gnu/emacs/EmacsContextMenu.java (inflateMenuItems):
Fix context menus again.
* java/org/gnu/emacs/EmacsNative.java (EmacsNative): Make all
event sending functions return long.
* java/org/gnu/emacs/EmacsPreferencesActivity.java
(EmacsPreferencesActivity): New class.
* java/org/gnu/emacs/EmacsService.java (EmacsService)
(onStartCommand, onCreate, startEmacsService): Start as a
foreground service if necessary to bypass system restrictions.
* java/org/gnu/emacs/EmacsSurfaceView.java (EmacsSurfaceView):
* java/org/gnu/emacs/EmacsThread.java (EmacsThread, run):
* java/org/gnu/emacs/EmacsView.java (EmacsView, onLayout)
(onDetachedFromWindow):
* java/org/gnu/emacs/EmacsWindow.java (EmacsWindow, viewLayout):
Implement frame resize synchronization..
* java/org/gnu/emacs/EmacsWindowAttachmentManager.java
(EmacsWindowAttachmentManager, removeWindowConsumer): Adjust
accordingly for changes to frame deletion behavior.
* lisp/frame.el (android-toggle-on-screen-keyboard)
(frame-toggle-on-screen-keyboard): New function.
* lisp/minibuffer.el (minibuffer-setup-on-screen-keyboard)
(minibuffer-exit-on-screen-keyboard): New functions.
(minibuffer-setup-hook, minibuffer-exit-hook): Add new functions
to hooks.

* lisp/touch-screen.el (touch-screen-relative-xy): Accept new
value of window `frame'.  Return frame coordinates in that case.
(touch-screen-set-point-commands): New variable.
(touch-screen-handle-point-up): Respect that variable.
(touch-screen-track-drag): Return `no-drag' where appropriate.
(touch-screen-drag-mode-line-1, touch-screen-drag-mode-line):
Refactor to use `no-drag'.

* src/android.c (struct android_emacs_window): New methods.
Make all event sending functions return the event serial.
(android_toggle_on_screen_keyboard, android_window_updated): New
functions.
* src/android.h: Update prototypes.
* src/androidfns.c (Fandroid_toggle_on_screen_keyboard)
(syms_of_androidfns): New function.
* src/androidgui.h (struct android_any_event)
(struct android_key_event, struct android_configure_event)
(struct android_focus_event, struct android_window_action_event)
(struct android_crossing_event, struct android_motion_event)
(struct android_button_event, struct android_touch_event)
(struct android_wheel_event, struct android_iconify_event)
(struct android_menu_event): Add `serial' fields.

* src/androidterm.c (handle_one_android_event)
(android_frame_up_to_date):
* src/androidterm.h (struct android_output): Implement frame
resize synchronization.
2023-01-20 19:06:32 +08:00
Po Lu
e07b58dc35 Check in missing file
* xcompile/verbose.mk.android: New file.
2023-01-20 09:26:50 +08:00
Po Lu
f99f759931 Merge remote-tracking branch 'origin/master' into feature/android 2023-01-19 22:20:23 +08:00
Po Lu
a496509ced Update Android port
* .gitignore: Add new files.
* INSTALL.android: Explain how to build Emacs for ancient
versions of Android.
* admin/merge-gnulib (GNULIB_MODULES): Add getdelim.
* build-aux/config.guess (timestamp, version):
* build-aux/config.sub (timestamp, version): Autoupdate.
* configure.ac (BUILD_DETAILS, ANDROID_MIN_SDK):
(ANDROID_STUBIFY): Allow specifying CFLAGS via ANDROID_CFLAGS.
Add new configure tests for Android API version when not
explicitly specified.

* doc/emacs/android.texi (Android): Add reference to ``Other
Input Devices''.
(Android File System): Remove restrictions on directory-files on
the assets directory.
* doc/emacs/emacs.texi (Top): Add Other Input Devices to menu.
* doc/emacs/input.texi (Other Input Devices): New node.
* doc/lispref/commands.texi (Touchscreen Events): Document
changes to touchscreen input events.
* doc/lispref/frames.texi (Pop-Up Menus): Likewise.
* etc/NEWS: Announce changes.
* java/Makefile.in: Use lib-src/asset-directory-tool to generate
an `directory-tree' file placed in /assets.
* java/debug.sh: Large adjustments to support Android 2.2 and
later.

* java/org/gnu/emacs/EmacsContextMenu.java (inflateMenuItems):
* java/org/gnu/emacs/EmacsCopyArea.java (perform):
* java/org/gnu/emacs/EmacsDialog.java (toAlertDialog):
* java/org/gnu/emacs/EmacsDrawLine.java (perform):
* java/org/gnu/emacs/EmacsDrawRectangle.java (perform):
* java/org/gnu/emacs/EmacsDrawable.java (EmacsDrawable):
* java/org/gnu/emacs/EmacsFillPolygon.java (perform):
* java/org/gnu/emacs/EmacsFillRectangle.java (perform):
* java/org/gnu/emacs/EmacsGC.java (EmacsGC):
* java/org/gnu/emacs/EmacsPixmap.java (EmacsPixmap):
(destroyHandle):
* java/org/gnu/emacs/EmacsSdk7FontDriver.java (draw): Avoid
redundant canvas saves and restores.
* java/org/gnu/emacs/EmacsService.java (run):
* java/org/gnu/emacs/EmacsView.java (EmacsView):
(handleDirtyBitmap):
* java/org/gnu/emacs/EmacsWindow.java (changeWindowBackground)
(EmacsWindow): Make compatible with Android 2.2 and later.

* lib-src/Makefile.in (DONT_INSTALL): Add asset-directory-tool
on Android.:(asset-directory-tool{EXEEXT}): New target.
* lib-src/asset-directory-tool.c (struct directory_tree, xmalloc)
(main_1, main_2, main): New file.

* lib, m4: Merge from gnulib.  This will be reverted before
merging to master.

* lisp/button.el (button-map):
(push-button):
* lisp/frame.el (display-popup-menus-p): Improve touchscreen
support.
* lisp/subr.el (event-start):
(event-end): Handle touchscreen events.
* lisp/touch-screen.el (touch-screen-handle-timeout):
(touch-screen-handle-point-update):
(touch-screen-handle-point-up):
(touch-screen-track-tap):
(touch-screen-track-drag):
(touch-screen-drag-mode-line-1):
(touch-screen-drag-mode-line): New functions.
([mode-line touchscreen-begin]):
([bottom-divider touchscreen-begin]): Bind new events.

* lisp/wid-edit.el (widget-event-point):
(widget-keymap):
(widget-event-start):
(widget-button--check-and-call-button):
(widget-button-click): Improve touchscreen support.

* src/alloc.c (make_lisp_symbol): Avoid ICE on Android NDK GCC.
(mark_pinned_symbols): Likewise.

* src/android.c (struct android_emacs_window): New struct.
(window_class): New variable.
(android_run_select_thread): Add workaround for Android platform
bug.
(android_extract_long, android_scan_directory_tree): New
functions.
(android_file_access_p): Use those functions instead.
(android_init_emacs_window): New function.
(android_init_emacs_gc_class): Update signature of `markDirty'.
(android_change_gc, android_set_clip_rectangles): Tell the GC
whether or not clip rects were dirtied.
(android_swap_buffers): Do not look up method every time.
(struct android_dir): Adjust for new directory tree lookup.
(android_opendir, android_readdir, android_closedir): Likewise.
(android_four_corners_bilinear): Fix coding style.
(android_ftruncate): New function.
* src/android.h: Update prototypes.  Replace ftruncate with
android_ftruncate when necessary.

* src/androidterm.c (handle_one_android_event): Pacify GCC.  Fix
touch screen tool bar bug.
* src/emacs.c (using_utf8): Fix compilation error.
* src/fileio.c (Ffile_system_info): Return Qnil when fsusage.o
is not built.
* src/filelock.c (BOOT_TIME_FILE): Fix definition for Android.
* src/frame.c (Fx_parse_geometry): Fix uninitialized variable
uses.
* src/keyboard.c (lispy_function_keys): Fix `back'.
* src/menu.c (x_popup_menu_1): Handle touch screen events.
(Fx_popup_menu): Document changes.

* src/sfnt.c (main): Improve tests.

* src/sfntfont-android.c (sfntfont_android_put_glyphs): Fix
minor problem.
(init_sfntfont_android): Check for
HAVE_DECL_ANDROID_GET_DEVICE_API_LEVEL.
* src/sfntfont.c (struct sfnt_font_desc): New fields `adstyle'
and `languages'.
(sfnt_parse_style): Append tokens to adstyle.
(sfnt_parse_languages): New function.
(sfnt_enum_font_1): Parse supported languages and adstyle.
(sfntfont_list_1): Handle new fields.
(sfntfont_text_extents): Fix uninitialized variable use.
(syms_of_sfntfont, mark_sfntfont): Adjust accordingly.
2023-01-19 22:19:06 +08:00
Po Lu
6253e7e742 Merge remote-tracking branch 'origin/master' into feature/android 2023-01-17 22:11:31 +08:00
Po Lu
1b8258a1f2 Update Android port
* doc/emacs/android.texi (Android Fonts): Document that TTC
format fonts are now supported.
* doc/emacs/emacs.texi (Top): Fix menus.
* doc/lispref/commands.texi (Touchscreen Events)
(Key Sequence Input): Document changes to touchscreen events.
* etc/DEBUG: Describe how to debug 64 bit binaries on Android.

* java/org/gnu/emacs/EmacsCopyArea.java (perform): Explicitly
recycle copy bitmap.
* java/org/gnu/emacs/EmacsDialog.java (EmacsDialog): New class.
* java/org/gnu/emacs/EmacsDrawRectangle.java (perform): Use 5
point PolyLine like X, because Android behaves like Postscript
on some devices and X elsewhere.
* java/org/gnu/emacs/EmacsFillRectangle.java (perform):
Explicitly recycle copy bitmap.
* java/org/gnu/emacs/EmacsPixmap.java (destroyHandle):
Explicitly recycle bitmap and GC if it is big.
* java/org/gnu/emacs/EmacsView.java (EmacsView): Make
`bitmapDirty' a boolean.
(handleDirtyBitmap): Reimplement in terms of that boolean.
Explicitly recycle old bitmap and GC.
(onLayout): Fix lock up.
(onDetachedFromWindow): Recycle bitmap and GC.

* java/org/gnu/emacs/EmacsWindow.java (requestViewLayout):
Update call to explicitlyDirtyBitmap.

* src/android.c (android_run_select_thread, android_select):
Really fix android_select.
(android_build_jstring): New function.
* src/android.h: Update prototypes.
* src/androidmenu.c (android_process_events_for_menu): Totally
unblock input before process_pending_signals.
(android_menu_show): Remove redundant unblock_input and
debugging code.
(struct android_emacs_dialog, android_init_emacs_dialog)
(android_dialog_show, android_popup_dialog, init_androidmenu):
Implement popup dialogs on Android.

* src/androidterm.c (android_update_tools)
(handle_one_android_event, android_frame_up_to_date): Allow
tapping tool bar items.
(android_create_terminal): Add dialog hook.
(android_wait_for_event): Adjust call to android_select.
* src/androidterm.h (struct android_touch_point): New field
`tool_bar_p'.
* src/keyboard.c (read_key_sequence, head_table)
(syms_of_keyboard): Prefix touchscreen events with posn.
* src/keyboard.h (EVENT_HEAD): Handle touchscreen events.
* src/process.c (wait_reading_process_output): Adjust call to
android_select.
* src/sfnt.c (sfnt_read_table_directory): If the first long
turns out to be ttcf, return -1.
(sfnt_read_ttc_header): New function.
(main): Test TTC support.

* src/sfnt.h (struct sfnt_ttc_header): New structure.
(enum sfnt_ttc_tag): New enum.

* src/sfntfont-android.c (struct
sfntfont_android_scanline_buffer): New structure.
(GET_SCANLINE_BUFFER): New macro.  Try to avoid so much malloc
upon accessing the scanline buffer.
(sfntfont_android_put_glyphs): Do not use SAFE_ALLOCA to
allocate the scaline buffer.
(Fandroid_enumerate_fonts): Enumerate ttc fonts too.

* src/sfntfont.c (struct sfnt_font_desc): New field `offset'.
(sfnt_enum_font_1): Split out enumeration code from
sfnt_enum_font.
(sfnt_enum_font): Read TTC tables and enumerate each font
therein.
(sfntfont_open): Seek to the offset specified.

* xcompile/Makefile.in (maintainer-clean): Fix depends here.
2023-01-17 22:10:43 +08:00
Po Lu
356249d9fa Fix display of glyphs with word-sized component offsets on Android
* src/sfnt.c (sfnt_decompose_compound_glyph): Handle correctly
the Y offset in components with ARG_1_AND_2_ARE_WORDS.
(main): Update debugging code.
2023-01-16 20:06:01 +08:00
Po Lu
23845804a2 Merge remote-tracking branch 'origin/master' into feature/android 2023-01-16 19:50:42 +08:00
Po Lu
ad59d8986a Update Android port
* doc/emacs/android.texi (Android, Android Environment): Improve
documentation.
* doc/lispref/commands.texi (Touchscreen Events): Document
changes to touchscreen support.
* doc/lispref/display.texi (Defining Faces, Window Systems):
* doc/lispref/frames.texi (Frame Layout, Font and Color
Parameters):
* doc/lispref/os.texi (System Environment): Document Android in
various places.

* java/org/gnu/emacs/EmacsWindow.java (figureChange): Fix crash.
* lisp/loadup.el: ("touch-screen"): Load touch-screen.el.
* lisp/pixel-scroll.el: Autoload two functions.
* lisp/term/android-win.el: Add require 'touch-screen.
* lisp/touch-screen.el (touch-screen-current-tool)
(touch-screen-current-timer, touch-screen-delay)
(touch-screen-relative-xy, touch-screen-handle-scroll)
(touch-screen-handle-timeout, touch-screen-handle-point-update)
(touch-screen-handle-point-up, touch-screen-handle-touch)
(global-map, touch-screen): New file.
* src/android.c (android_run_debug_thread): Fix build on 64 bit
systems.
(JNICALL, android_put_pixel): Likewise.
(android_transform_coordinates, android_four_corners_bilinear)
(android_fetch_pixel_bilinear, android_project_image_bilinear)
(android_fetch_pixel_nearest_24, android_fetch_pixel_nearest_1)
(android_project_image_nearest): New functions.
* src/androidgui.h (struct android_transform): New structure.
* src/androidterm.c (android_note_mouse_movement): Remove
obsolete TODO.
(android_get_scale_factor): New function.
(android_draw_underwave): Scale underwave correctly.
* src/dispextern.h: Support native image transforms on Android.
* src/image.c (matrix_identity, matrix_rotate)
(matrix_mirror_horizontal, matrix_translate): New functions.
(image_set_transform): Implement native image transforms on
Android.
(Fimage_transforms_p): Implement on Android.

* src/keyboard.c (make_lispy_event, syms_of_keyboard): Handle
touch screen- menu bar events.
* src/sfnt.c: Fix typo in comment.
* src/sfntfont-android.c (sfntfont_android_blend, U255TO256)
(sfntfont_android_put_glyphs): Avoid redundant swizzling.
* src/sfntfont.c (sfntfont_lookup_char): Fix build on 64 bit
systems.
2023-01-16 19:50:02 +08:00
Po Lu
da9ae10636 Implement submenus on Android
* java/org/gnu/emacs/EmacsActivity.java (onCreate): Set the
default theme to Theme.DeviceDefault.NoActionBar if possible.
(onContextMenuClosed): Add hack for Android bug.
* java/org/gnu/emacs/EmacsContextMenu.java (EmacsContextMenu)
(onMenuItemClick): Set flag upon submenu selection.
(inflateMenuItems): Set onClickListener for submenus as well.
(display1): Clear new flag.
* java/org/gnu/emacs/EmacsDrawRectangle.java (perform): Fix
rectangle bounds.
* java/org/gnu/emacs/EmacsNative.java (EmacsNative):
* java/org/gnu/emacs/EmacsService.java (onCreate): Pass cache
directory.
(sync): New function.
* src/android.c (struct android_emacs_service): New method
`sync'.
(setEmacsParams, initEmacs): Handle cache directory.
(android_init_emacs_service): Initialize new method `sync'.
(android_sync): New function.
* src/androidfns.c (Fx_show_tip): Call both functions.
* src/androidgui.h: Update prototypes.
* src/androidmenu.c (struct android_menu_subprefix)
(android_free_subprefixes, android_menu_show): Handle submenu
prefixes correctly.
* src/androidterm.c (handle_one_android_event): Clear help echo
on MotionNotify like on X.
* src/menu.c (single_menu_item): Enable submenus on Android.
2023-01-15 15:45:29 +08:00
Po Lu
a336fd98a1 Merge remote-tracking branch 'origin/master' into feature/android 2023-01-15 11:57:20 +08:00
Po Lu
6e2bc91d92 Implement toolkit menus on Android
* java/org/gnu/emacs/EmacsActivity.java (onContextMenuClosed):
New function.
* java/org/gnu/emacs/EmacsContextMenu.java (EmacsContextMenu):
New field `itemAlreadySelected'.
(onMenuItemClick): New function.
(inflateMenuItems): Attach onClickListener as appropriate.
(display1): Clear itemAlreadySelected.
(display): Fix runnable synchronization.
* java/org/gnu/emacs/EmacsNative.java (sendContextMenu): New
function.
* java/org/gnu/emacs/EmacsView.java (popupMenu):
(cancelPopupMenu): Set popupactive correctly.

* src/android.c (android_run_select_thread): Fix android_select
again.
(android_wait_event): New function.
* src/android.h: Update prototypes.
* src/androidgui.h (enum android_event_type): New
`ANDROID_CONTEXT_MENU' event.
(struct android_menu_event, union android_event): Add new event.

* src/androidmenu.c (struct android_emacs_context_menu): New
structure.
(android_init_emacs_context_menu): Add `dismiss' method.
(struct android_dismiss_menu_data): New structure.
(android_dismiss_menu, android_process_events_for_menu): New
functions.
(android_menu_show): Set an actual item ID.
(popup_activated): Define when stubify as well.
(Fmenu_or_popup_active_p): New function.
(syms_of_androidmenu): New function.

* src/androidterm.c (handle_one_android_event): Handle context
menu events.
* src/androidterm.h (struct android_display_info): New field for
menu item ID.
* src/emacs.c (android_emacs_init): Call syms_of_androidmenu.
* src/xdisp.c (note_mouse_highlight): Return if popup_activated
on Android as well.
2023-01-15 11:57:10 +08:00
Po Lu
c02a7b2ff4 Fix android_select
* src/android.c (android_run_select_thread, android_select):
Handle EINTR in sem_wait and fix sigsets.
2023-01-14 22:48:28 +08:00
Po Lu
422035143f Add temporary gnulib patch
* xcompile/lib/fpending.c (__fpending): Fix gnulib problem.
2023-01-14 22:23:08 +08:00
Po Lu
498f207c86 Drop unneeded changes to gnulib
* xcompile/lib/fpending.c (__fpending):
* xcompile/lib/open.c:
* xcompile/lib/unistd.c (_GL_UNISTD_INLINE): Remove Android
patches.
2023-01-14 22:14:10 +08:00
Po Lu
9c6256df0d Merge remote-tracking branch 'origin/master' into feature/android 2023-01-14 22:13:26 +08:00
Po Lu
2b87ab7b27 Update Android port
* java/Makefile.in (clean): Fix distclean and bootstrap-clean rules.
* java/debug.sh (jdb_port):
(attach_existing):
(num_pids):
(line): Add new options to upload a gdbserver binary to the device.

* java/org/gnu/emacs/EmacsActivity.java (EmacsActivity): Make
focusedActivities public.
* java/org/gnu/emacs/EmacsContextMenu.java (EmacsContextMenu):
New class.
* java/org/gnu/emacs/EmacsDrawRectangle.java (perform): Fix
bounds computation.
* java/org/gnu/emacs/EmacsGC.java (markDirty): Set stroke width
explicitly.
* java/org/gnu/emacs/EmacsService.java (EmacsService)
(getLocationOnScreen, nameKeysym): New functions.
* java/org/gnu/emacs/EmacsView.java (EmacsView): Disable focus
highlight.
(onCreateContextMenu, popupMenu, cancelPopupMenu): New
functions.
* java/org/gnu/emacs/EmacsWindow.java (EmacsWindow): Implement a
kind of ``override redirect'' window for tooltips.
* src/android.c (struct android_emacs_service): New method
`name_keysym'.
(android_run_select_thread, android_init_events):
(android_select): Release select thread on semaphores instead of
signals to avoid one nasty race on SIGUSR2 delivery.
(android_init_emacs_service): Initialize new method.
(android_create_window): Handle CW_OVERRIDE_REDIRECT.
(android_move_resize_window, android_map_raised)
(android_translate_coordinates, android_get_keysym_name)
(android_build_string, android_exception_check): New functions.
* src/android.h: Update prototypes.

* src/androidfns.c (android_set_parent_frame, Fx_create_frame)
(unwind_create_tip_frame, android_create_tip_frame)
(android_hide_tip, compute_tip_xy, Fx_show_tip, Fx_hide_tip)
(syms_of_androidfns): Implement tooltips and iconification
reporting.

* src/androidgui.h (enum android_window_value_mask): Add
CWOverrideRedirect.
(struct android_set_window_attributes): Add `override_redirect'.
(ANDROID_IS_MODIFIER_KEY): Recognize Caps Lock.

* src/androidmenu.c (struct android_emacs_context_menu): New
struct.
(android_init_emacs_context_menu, android_unwind_local_frame)
(android_push_local_frame, android_menu_show, init_androidmenu):
New functions.

* src/androidterm.c (handle_one_android_event): Fix NULL pointer
dereference.
(android_fullscreen_hook): Handle fullscreen correctly.
(android_draw_box_rect): Fix top line.
(get_keysym_name): Implement function.
(android_create_terminal): Remove scroll bar stubs and add menu
hook.

* src/androidterm.h: Update prototypes.
* src/emacs.c (android_emacs_init): Initialize androidmenu.c.
* xcompile/Makefile.in: Fix clean rules.
2023-01-14 22:12:16 +08:00
Po Lu
28a9baccd4 Improve reliability of Android build system
* .gitignore: Add new files.
* INSTALL.android: New file.
* Makefile.in (clean_dirs): Clean xcompile as well.
* admin/merge-gnulib (avoided_flags): Import gnulib into Android
directory as well.
* doc/emacs/android.texi (Android):
* doc/emacs/emacs.texi (Top): New node `Android'.
* java/org/gnu/emacs/EmacsThread.java (run): Use right
executable name.
* lib/Makefile.in (ANDROID_CFLAGS): Use better way to refer to
/src.
(vpath): Delete ugly block of vpath statements.
(mostlyclean): Remove Makefile.android.
* lib/fpending.c (__fpending):
* lib/open.c:
* lib/unistd.c (_GL_UNISTD_INLINE): Revert changes to gnulib in
lib/.
* src/android.h:
* src/androidterm.c: Fix build.
* xcompile/Makefile.in (LIB_SRCDIR):
(LIBSRC_BINARIES, src/verbose.mk):
(PRE_BUILD_DEPS, PHONY): Use gnulib in xcompile/lib/ as opposed
to lib/.
* xcompile/README: Adjust README.
2023-01-14 09:34:53 +08:00
Po Lu
a441ac5527 Check in gnulib with Android patches
* xcompile/lib: Check-in gnulib with patches for Android.
2023-01-14 09:27:33 +08:00
Po Lu
a02f52cc9e Merge remote-tracking branch 'origin/master' into feature/android 2023-01-13 16:08:29 +08:00
Po Lu
24910d3f37 Fix crashes in Android port
* java/org/gnu/emacs/EmacsService.java (queryTree): Fix NULL
pointer dereference.
* src/android.c (android_query_tree): Set *nchildren_return.
2023-01-13 16:08:11 +08:00
Po Lu
7e35af1a10 * .gitignore: Add AndroidManifest.xml. 2023-01-13 16:05:55 +08:00
Po Lu
0b61fd7700 * java/AndroidManifest.xml: Remove file that is now generated. 2023-01-13 16:05:08 +08:00
Po Lu
bb3ceb6e04 * src/frame.c (make_monitor_attribute_list): Allow source to be NULL. 2023-01-13 15:53:22 +08:00
Po Lu
f9732131cf Update Android port
* configure.ac (ANDROID_MIN_SDK): New variable.
(DX): Remove and replace with D8.
(XCONFIGURE): Check for the minimum version of Android the cross
compiler compiles for.  Generate java/AndroidManifest.xml from
java/AndroidManifest.xml.in.  Allow using Zlib on Android.

* java/AndroidManifest.xml.in: New file.  Use the minimum SDK
detected by configure.

* java/Makefile.in (top_srcdir, version): New variables.
(DX, D8): Replace with D8.
(ANDROID_MIN_SDK, APK_NAME): New variables.
(.PHONY):
(.PRECIOUS):
(classes.dex):
(emacs.apk): Generate $(APK_NAME) instead of `emacs.apk'.

* java/debug.sh: New option --attach-existing.  Attach to an
existing Emacs instance when specified.

* java/org/gnu/emacs/EmacsActivity.java (EmacsActivity): New
field `isPaused'.
(invalidateFocus1): Fix infinite recursion.
(detachWindow): Deiconify window.
(attachWindow): Iconify the window if the activity is paused.
(onCreate): Use the ``no title bar'' theme.
(onPause, onResume): New functions.
* java/org/gnu/emacs/EmacsNative.java (sendTouchUp, sendTouchDown)
(sendTouchMove, sendWheel, sendIconified, sendDeiconified): New
functions.
* java/org/gnu/emacs/EmacsSdk7FontDriver.java (Sdk7Typeface):
(list): Remove logging for code that is mostly going to be unused.
* java/org/gnu/emacs/EmacsService.java (ringBell, queryTree)
(getScreenWidth, getScreenHeight, detectMouse): New functions.
* java/org/gnu/emacs/EmacsSurfaceView.java (EmacsSurfaceView)
(surfaceChanged, surfaceCreated, surfaceDestroyed): Add extra
debug logging.  Avoid deadlock in surfaceCreated.

* java/org/gnu/emacs/EmacsView.java (EmacsView): Try very hard
to make the SurfaceView respect Z order.  It didn't work.
(handleDirtyBitmap): Copy over the contents from the old bitmap.
(explicitlyDirtyBitmap): New function.
(onLayout): Don't dirty bitmap if unnecessary.
(damageRect, swapBuffers): Don't synchronize so hard.
(onTouchEvent): Call window.onTouchEvent instead.
(moveChildToBack, raise, lower): New functions.

* java/org/gnu/emacs/EmacsWindow.java (Coordinate): New
subclass.
(pointerMap, isMapped, isIconified, dontFocusOnMap)
(dontAcceptFocus): New fields.
(EmacsWindow): Don't immediately register unmapped window.
(viewLayout): Send configure event outside the lock.
(requestViewLayout): Explicitly dirty the bitmap.
(mapWindow): Register the window now.  Respect dontFocusOnMap.
(unmapWindow): Unregister the window now.
(figureChange, onTouchEvent): New functions.
(onSomeKindOfMotionEvent): Handle scroll wheel events.
(reparentTo, makeInputFocus, raise, lower, getWindowGeometry)
(noticeIconified, noticeDeiconified, setDontAcceptFocus)
(setDontFocusOnMap, getDontFocusOnMap): New functions.
* java/org/gnu/emacs/EmacsWindowAttachmentManager.java
(registerWindow, detachWindow): Synchronize.
(noticeIconified, noticeDeiconified): New functions.
(copyWindows): New function.

* lisp/frame.el (frame-geometry, frame-edges)
(mouse-absolute-pixel-position, set-mouse-absolute-pixel-position)
(frame-list-z-order, frame-restack, display-mouse-p)
(display-monitor-attributes-list): Implement on Android.

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

* src/android.c (struct android_emacs_service): New methods
`ringBell', `queryTree', `getScreenWidth', `getScreenHeight',
and `detectMouse'.
(struct android_event_queue, android_init_events)
(android_next_event, android_write_event): Remove write limit.
(android_file_access_p): Handle directories correcty.
(android_close): Fix coding style.
(android_fclose): New function.
(android_init_emacs_service): Initialize new methods.
(android_reparent_window): Implement function.
(android_bell, android_set_input_focus, android_raise_window)
(android_lower_window, android_query_tree, android_get_geometry)
(android_get_screen_width, android_get_screen_height)
(android_get_mm_width, android_get_mm_height, android_detect_mouse)
(android_set_dont_focus_on_map, android_set_dont_accept_focus):
New functions.
(struct android_dir): New structure.
(android_opendir, android_readdir, android_closedir): New
functions.
(emacs_abort): Implement here on Android and poke debuggerd into
generating a tombstone.

* src/android.h: Update prototypes.

* src/androidfns.c (android_set_parent_frame): New function.
(android_default_font_parameter): Use sane font size by default.
(Fx_display_pixel_width, Fx_display_pixel_height)
(Fx_display_mm_width, Fx_display_mm_height)
(Fx_display_monitor_attributes_list): Rename to start with
`android-'.  Implement.  Fiddle with documentation to introduce
Android specific nuances.
(Fandroid_display_monitor_attributes_list): New function.
(Fx_frame_geometry, frame_geometry): New function.
(Fandroid_frame_geometry): Implement correctly.
(Fx_frame_list_z_order): Rename to start with `android-'.
(android_frame_list_z_order, Fandroid_frame_list_z_order):
Implement.
(Fx_frame_restack): Rename to start with `android-'.
(Fandroid_frame_restack): ``Implement''.
(Fx_mouse_absolute_pixel_position): Rename to start with
`android-'.
(Fandroid_mouse_absolute_pixel_position): ``Implement''.
(Fx_set_mouse_absolute_pixel_position): Rename to start with
`android-'.
(Fandroid_set_mouse_absolute_pixel_position): ``Implement''.
(Fandroid_detect_mouse): New function.
(android_set_menu_bar_lines): Use FRAME_ANDROID_DRAWABLE when
clearing area.
(android_set_no_focus_on_map, android_set_no_accept_focus): New
functions.
(android_frame_parm_handlers): Register new frame parameter
handlers.
(syms_of_androidfns): Update appropriately.

* src/androidfont.c (androidfont_draw): Use
FRAME_ANDROID_DRAWABLE instead of FRAME_ANDROID_WINDOW.

* src/androidgui.h (enum android_event_type): New events.
(struct android_touch_event, struct android_wheel_event)
(struct android_iconify_event): New structures.
(union android_event): Add new events.

* src/androidterm.c (android_clear_frame): Use
FRAME_ANDROID_DRAWABLE instead of FRAME_ANDROID_WINDOW.
(android_flash, android_ring_bell): Implement bell ringing.
(android_toggle_invisible_pointer): Don't TODO function that
can't be implemented.
(show_back_buffer, android_flush_dirty_back_buffer_on): Check if
a buffer flip is required before doing the flip.
(android_lower_frame, android_raise_frame): Implement functions.
(android_update_tools, android_find_tool): New functions.
(handle_one_android_event): Handle new iconification, wheel and
touch events.
(android_read_socket): Implement pending-autoraise-frames.
(android_frame_up_to_date): Implement bell ringing.
(android_buffer_flipping_unblocked_hook): Check if a buffer flip
is required before doing the flip.
(android_focus_frame, android_frame_highlight)
(android_frame_unhighlight): New function.
(android_frame_rehighlight): Implement functions.
(android_iconify_frame): Always display error.
(android_set_alpha): Update commentary.
(android_free_frame_resources): Free frame touch points.
(android_scroll_run, android_flip_and_flush)
(android_clear_rectangle, android_draw_fringe_bitmap)
(android_draw_glyph_string_background, android_fill_triangle)
(android_clear_point, android_draw_relief_rect)
(android_draw_box_rect, android_draw_glyph_string_bg_rect)
(android_draw_image_foreground, android_draw_stretch_glyph_string)
(android_draw_underwave, android_draw_glyph_string_foreground)
(android_draw_composite_glyph_string_foreground)
(android_draw_glyphless_glyph_string_foreground)
(android_draw_glyph_string, android_clear_frame_area)
(android_clear_under_internal_border, android_draw_hollow_cursor)
(android_draw_bar_cursor, android_draw_vertical_window_border)
(android_draw_window_divider): Use FRAME_ANDROID_DRAWABLE
instead of FRAME_ANDROID_WINDOW for drawing operations.

* src/androidterm.h (struct android_touch_point): New structure.
(struct android_output): New fields.
(FRAME_ANDROID_NEED_BUFFER_FLIP): New macro.

* src/dired.c (emacs_readdir, open_directory)
(directory_files_internal_unwind, read_dirent)
(directory_files_internal, file_name_completion): Add
indirection over readdir and opendir.  Use android variants on
Android.

* src/dispnew.c (Fopen_termscript):
* src/fileio.c (fclose_unwind): Use emacs_fclose.
(Faccess_file): Call android_file_access_p.
(file_accessible_directory_p): Append right suffix to Android
assets directory.
(do_auto_save_unwind): Use emacs_fclose.
* src/keyboard.c (lispy_function_keys): Use right function key
for page up and page down.
(Fopen_dribble_file): Use emacs_fclose.

* src/lisp.h: New prototype emacs_fclose.

* src/lread.c (close_infile_unwind): Use emacs_fclose.

* src/sfnt.c (sfnt_curve_is_flat): Fix area-squared computation.
(sfnt_prepare_raster): Compute raster width and height
consistently with outline building.
(sfnt_build_outline_edges): Use the same offsets used to set
offy and offx.
(main): Adjust debug code.

* src/sfntfont-android.c (sfntfont_android_saturate32): Delete
function.
(sfntfont_android_blend, sfntfont_android_blendrgb): Remove
unnecessary debug code.
(sfntfont_android_composite_bitmap): Prevent out of bounds
write.
(sfntfont_android_put_glyphs): Use FRAME_ANDROID_DRAWABLE.
(init_sfntfont_android): Initialize Monospace Serif font to
something sensible.
* src/sfntfont.c (sfntfont_text_extents): Clear glyph metrics
before summing up pcm.
(sfntfont_draw): Use s->font instead of s->face->font.

* src/sysdep.c (emacs_fclose): Wrap around android_fclose on
android.

* src/term.c (Fsuspend_tty):
(delete_tty): Use emacs_fclose.
* src/verbose.mk.in (AM_V_DX): Replace with D8 version.
2023-01-13 15:53:08 +08:00
Po Lu
2fa5583d96 Merge remote-tracking branch 'origin/master' into feature/android 2023-01-11 16:07:32 +08:00
Po Lu
494bedde32 Bring up the sfnt-android font driver
* configure.ac (ANDROID_CFLAGS): Add sfnt-related font objects
to ANDROID_OBJ when not building stubs.
* lisp/startup.el (android-fonts-enumerated): New variable.
(normal-top-level): Set it.  Also enumerate fonts as early as
possible upon startup.

* src/alloc.c (cleanup_vector): Only finalize Android font
entities.
(garbage_collect): Mark sfntfont.c.

* src/android.c (struct android_emacs_drawable): New field
`damage_rect'.
(android_init_emacs_drawable): Initialize
Lorg/gnu/emacs/EmacsDrawable;#damageRect(Landroid/graphics/rect;)V.
(android_create_gc): Initialize cached GC fields.
(android_free_gc): Free cached GC clip rectangles.
(android_change_gc): Cache fields as appropriate.
(android_set_clip_rectangles): Set cached clip rectangles for
easy access from C.
(android_get_gc_values): Use cached values.
(android_get_image): Remove obsolete comment.
(android_lock_bitmap, android_damage_window): New functions that
don't parallel anything on X.

* src/android.h: Update prototypes.

* src/androidfns.c (android_default_font_parameter): Set Droid
Sans Mono as the default monospace font.
(Fx_create_frame): Register the sfntfont driver.

* src/androidgui.h (struct android_gc): Add C side caches for
clip rectangles and the foreground and background colors.

* src/androidterm.h: Update prototypes.

* src/dispextern.h (struct gui_box): New struct.
(gui_union_rectangles): New function.

* src/emacs.c (android_emacs_init): Initialize Android font
stuff late.
* src/font.c (font_make_entity): Clear `is_android' field on
Android.
(font_make_entity_android): Set `is_android' field.
* src/font.h (struct font_entity): New field `is_android'.

* src/print.c (print_vectorlike): Don't print private data,
which could include Lisp_Misc.

* src/sfnt.c (sfnt_read_cmap_format_0, sfnt_read_cmap_format_2)
(sfnt_read_cmap_format_4, sfnt_read_cmap_format_6)
(sfnt_read_cmap_format_8, sfnt_read_cmap_format_12): Remove
buggy pragmas.
(sfnt_lookup_glyph_4_1): New function.
(sfnt_lookup_glyph_4): Handle malformed lookup tables found on
Android.
(sfnt_lookup_glyph): Fix overflow problems in glyph checks.
(sfnt_read_glyph): Handle empty glyphs.  This implements some
behavior which everyone else seems to as well, but I can't find
documented in the TrueType Reference Manual.
(sfnt_free_glyph): Export correctly.
(sfnt_transform_coordinates): Make faster.
(sfnt_lerp_half): Fix lerping in some cases.
(sfnt_decompose_glyph): Handle empty glyphs correctly.  Close
contours manually instead of waiting for the edge building
process to do that.  This lets curves be handled correctly.
(struct sfnt_build_glyph_outline_context): Move internal struct
back to sfnt.c.
(sfnt_build_append): Fix detection of initial entry.
(sfnt_curve_to_and_build_1): Fix De Casteljau implementation.
(sfnt_curve_to_and_build): Use fixed point arithmetic to scale
outlines.
(sfnt_build_glyph_outline): Clear reference counts.  Use fixed
point arithmetic.
(sfnt_prepare_raster): Align rasters to 4 bytes,
SFNT_POLY_ALIGNMENT.  Fix calculation of offx and offy.
(sfnt_step_edge_by): Step edge by previously computed step_x.
(sfnt_build_outline_edges): Adjust for already closed contours.
Ignore edges abandoned after grid fit.  Also precompute step_x
to avoid multiplication on each span rastered.
(sfnt_poly_edges): Improve alignment.
(sfnt_fill_span): Rewrite to avoid control flow in while loop.
(sfnt_poly_span): Remove unnecessary code.
(sfnt_raster_glyph_outline): Use raster stride instead of width.
(sfnt_test_edge, sfnt_test_raster, main): Improve debugging
code.

* src/sfnt.h (struct sfnt_glyph_outline): Add refcount field to
outline.
(struct sfnt_build_glyph_outline_context): Remove private
struct.
(struct sfnt_raster): Add refcount field to raster.
(struct sfnt_edge): Improve doc.  Add `source_x' field used when
built with TEST.
(SFNT_CEIL_FIXED): New macro.

* src/sfntfont-android.c (sfntfont_android_saturate32)
(sfntfont_android_scale32, sfntfont_android_mul8x2)
(sfntfont_android_blend, U255TO256)
(sfntfont_android_composite_bitmap, sfntfont_android_union_boxes)
(sfntfont_android_put_glyphs, sfntfont_android_get_cache): New
functions.
(android_sfntfont_driver): New font driver.
(Fandroid_enumerate_fonts): New function.
(syms_of_sfntfont_android_for_pdumper, init_sfntfont_android)
(syms_of_sfntfont_android): Initialize default fonts, special
family mapping and font driver.
* src/sfntfont.c (struct sfnt_font_desc): New fields
`char_cache', `cmap_invalid' and `subtable'.
(sfnt_setup_coding_system): Improve commentary.  Add default
branch.  Fix return value.
(sfnt_safe_encode_coding_object_1)
(sfnt_safe_encode_coding_object_2):
(sfnt_safe_encode_coding_object): Use decode_coding_object
instead of encode_coding_object.
(sfnt_decode_font_string): Adjust for rename.
(sfnt_decode_foundry_name): New function.
(sfnt_weight_descriptions, sfnt_slant_descriptions)
(sfnt_width_descriptions): Fix definitions.
(sfnt_parse_style): Make function work.
(sfnt_enum_font): Initialize designer, char-cache and subtable
platform ID.
(sfntfont_charset_for_name, mark_sfntfont)
(sfntfont_charset_for_cmap): New functions.
(syms_of_sfntfont): New variable `sfnt-default-family-alist'.

* src/sfntfont.h (_SFNTFONT_H_): Update prototypes.

* src/xdisp.c (gui_union_rectangles): New function.
2023-01-11 16:06:15 +08:00
Po Lu
4c09b9a5a6 Merge remote-tracking branch 'origin/master' into feature/android 2023-01-08 15:43:57 +08:00
Po Lu
8dbfb924b6 * configure.ac (ANDROID_OBJS): Add sfntfont files. 2023-01-08 15:43:34 +08:00
Po Lu
ee256d1e25 Check in new files
* src/sfnt.h:
* src/sfntfont-android.c:
* src/sfntfont.c:
* src/sfntfont.h: New files.
2023-01-08 15:43:09 +08:00
Po Lu
1584a58efd Update Android port
Note that the port currently does not work as of this check-in.

* src/android.c (android_change_gc): Fix situations where clip
rects are cleared.
(android_create_pixmap_from_bitmap_data): Fix bitmap data
iteration.
* src/androidfns.c (Fx_show_tip, Fx_hide_tip): Remove annoying
errors.

* src/androidgui.h (enum android_event_type):
(struct android_crossing_event):
(struct android_motion_event):
(struct android_button_event):
(union android_event): New crossing, motion and button events.

* src/androidterm.c (android_note_mouse_movement)
(mouse_or_wdesc_frame, android_construct_mouse_click)
(handle_one_android_event, android_mouse_position)
(android_wait_for_event, android_set_window_size_1)
(android_bitmap_icon, android_free_frame_resources)
(syms_of_androidterm): New functions.  Handle crossing, motion
and button events.

* src/androidterm.h (struct android_display_info): New field
`last_mouse_movement_time'.
(struct android_output): Remove unused `need_buffer_flip' field.

* src/emacs.c (android_emacs_init): Initialize sfntfont.
* src/frame.c (syms_of_frame): Set frame_inhibit_implied_resize
to some reasonable value.
* src/frame.h (GCALIGNED_STRUCT): Set wait_event_type on
Android.

* src/sfnt.c (eassert):
(TEST_STATIC):
(available):
(enum sfnt_table):
(sfnt_table_names):
(SFNT_ENDOF):
(struct sfnt_table_directory):
(enum sfnt_scaler_type):
(sfnt_coerce_fixed):
(struct sfnt_hhea_table):
(struct sfnt_cmap_table):
(enum sfnt_platform_id):
(enum sfnt_unicode_platform_specific_id):
(enum sfnt_macintosh_platform_specific_id):
(enum sfnt_microsoft_platform_specific_id):
(struct sfnt_cmap_encoding_subtable):
(struct sfnt_cmap_encoding_subtable_data):
(struct sfnt_cmap_format_0):
(struct sfnt_cmap_format_2_subheader):
(struct sfnt_cmap_format_2):
(struct sfnt_cmap_format_4):
(struct sfnt_cmap_format_6):
(struct sfnt_cmap_format_8_or_12_group):
(struct sfnt_cmap_format_8):
(struct sfnt_cmap_format_12):
(struct sfnt_maxp_table):
(struct sfnt_loca_table_short):
(struct sfnt_loca_table_long):
(struct sfnt_glyf_table):
(struct sfnt_simple_glyph):
(struct sfnt_compound_glyph_component):
(struct sfnt_compound_glyph):
(struct sfnt_glyph):
(sfnt_read_table_directory):
(file):
(sfnt_read_cmap_table):
(sfnt_read_head_table):
(success):
(sfnt_read_hhea_table):
(sfnt_read_loca_table_short):
(sfnt_read_loca_table_long):
(sfnt_read_maxp_table):
(sfnt_read_glyf_table):
(sfnt_read_compound_glyph):
(sfnt_read_glyph):
(struct sfnt_point):
(sfnt_expand_compound_glyph_context):
(sfnt_decompose_compound_glyph):
(struct sfnt_glyph_outline):
(enum sfnt_glyph_outline_flags):
(struct sfnt_build_glyph_outline_context):
(sfnt_build_append):
(sfnt_build_glyph_outline):
(struct sfnt_raster):
(struct sfnt_edge):
(sfnt_prepare_raster):
(sfnt_build_outline_edges):
(sfnt_raster_glyph_outline): Move structures to sfnt.h.

(struct sfnt_long_hor_metric):
(struct sfnt_hmtx_table):
(struct sfnt_glyph_metrics):
(sfnt_read_hmtx_table):
(sfnt_lookup_glyph_metrics):
(sfnt_read_name_table):
(sfnt_find_name):
(sfnt_read_meta_table):
(sfnt_find_metadata):
(sfnt_test_edge_ignore): New functions.
(main): Add new tests.
* src/xdisp.c (redisplay_tool_bar):
2023-01-08 15:42:37 +08:00
Po Lu
86fe893128 Delete unused files
* java/org/gnu/emacs/EmacsPaintQueue.java
* java/org/gnu/emacs/EmacsPaintReq.java: Remove files.
2023-01-08 15:39:28 +08:00
Po Lu
695e26079e Update Java part of Android port
* java/org/gnu/emacs/EmacsCopyArea.java (EmacsCopyArea, perform)
(paintTo):
* java/org/gnu/emacs/EmacsDrawLine.java (EmacsDrawLine):
* java/org/gnu/emacs/EmacsDrawPoint.java (EmacsDrawPoint):
* java/org/gnu/emacs/EmacsDrawRectangle.java (EmacsDrawRectangle)
(paintTo):
* java/org/gnu/emacs/EmacsDrawable.java (EmacsDrawable):
* java/org/gnu/emacs/EmacsFillPolygon.java (EmacsFillPolygon):
* java/org/gnu/emacs/EmacsFillRectangle.java
(EmacsFillRectangle):
* java/org/gnu/emacs/EmacsFontDriver.java (EmacsFontDriver):
* java/org/gnu/emacs/EmacsGC.java (EmacsGC):
* java/org/gnu/emacs/EmacsNative.java (EmacsNative):
* java/org/gnu/emacs/EmacsPixmap.java (EmacsPixmap):
* java/org/gnu/emacs/EmacsSdk23FontDriver.java
(EmacsSdk23FontDriver):
* java/org/gnu/emacs/EmacsSdk7FontDriver.java
(EmacsSdk7FontDriver, textExtents1, textExtents, draw):
* java/org/gnu/emacs/EmacsService.java (EmacsService, copyArea):
* java/org/gnu/emacs/EmacsSurfaceView.java (EmacsSurfaceView):
* java/org/gnu/emacs/EmacsView.java (EmacsView, onLayout)
(onFocusChanged):
* java/org/gnu/emacs/EmacsWindow.java (EmacsWindow, run)
(resizeWindow, lockCanvas, getBitmap, onKeyDown, onKeyUp)
(onActivityDetached): Move rendering to main thread.  Make
drawing operations completely static.
2023-01-08 15:39:02 +08:00
Po Lu
e816e57039 Check in new file androidmenu.c
* src/androidmenu.c: New file.
2023-01-08 15:37:30 +08:00
Po Lu
dd8078ed11 Check in new file sfnt.c
* src/sfnt.c (xmalloc, xrealloc, xfree, eassert, MIN)
(sfnt_table_names, SFNT_ENDOF, struct sfnt_table_directory)
(enum sfnt_scaler_type, sfnt_coerce_fixed, struct sfnt_hhea_table)
(struct sfnt_cmap_table, enum sfnt_platform_id)
(enum sfnt_unicode_platform_specific_id)
(enum sfnt_macintosh_platform_specific_id)
(enum sfnt_microsoft_platform_specific_id)
(struct sfnt_cmap_encoding_subtable)
(struct sfnt_cmap_encoding_subtable_data)
(struct sfnt_cmap_format_0, struct sfnt_cmap_format_2_subheader)
(struct sfnt_cmap_format_2, struct sfnt_cmap_format_4)
(struct sfnt_cmap_format_6, struct sfnt_cmap_format_8_or_12_group)
(struct sfnt_cmap_format_8, struct sfnt_cmap_format_12)
(struct sfnt_maxp_table, struct sfnt_loca_table_short)
(struct sfnt_loca_table_long, struct sfnt_glyf_table)
(struct sfnt_simple_glyph, struct sfnt_compound_glyph_component)
(struct sfnt_compound_glyph, struct sfnt_glyph, _sfnt_swap16)
(_sfnt_swap32, sfnt_swap16, sfnt_find_table)
(sfnt_read_cmap_format_0, sfnt_read_cmap_format_2)
(sfnt_read_cmap_format_4, sfnt_read_cmap_format_6)
(sfnt_read_cmap_format_8, sfnt_read_cmap_format_12)
(sfnt_read_cmap_table_1, sfnt_read_cmap_table, sfnt_lookup_glyph_0)
(sfnt_lookup_glyph_2, sfnt_bsearch_above, sfnt_compare_uint16)
(sfnt_lookup_glyph_4, sfnt_lookup_glyph_6, sfnt_lookup_glyph_8)
(sfnt_lookup_glyph_12, sfnt_lookup_glyph, sfnt_read_head_table)
(sfnt_read_hhea_table, sfnt_read_loca_table_short)
(sfnt_read_loca_table_long, sfnt_read_maxp_table)
(sfnt_read_glyf_table, sfnt_read_simple_glyph)
(sfnt_read_compound_glyph, sfnt_read_glyph, sfnt_free_glyph)
(struct sfnt_point, sfnt_transform_coordinates)
(struct sfnt_compound_glyph_context)
(sfnt_expand_compound_glyph_context, sfnt_round_fixed)
(sfnt_decompose_compound_glyph, sfnt_lerp_half)
(sfnt_decompose_glyph, struct sfnt_glyph_outline)
(enum sfnt_glyph_outline_flags)
(struct sfnt_build_glyph_outline_context, sfnt_build_append)
(sfnt_move_to_and_build, sfnt_line_to_and_build, sfnt_mul_fixed)
(sfnt_div_fixed, sfnt_ceil_fixed, sfnt_floor_fixed)
(sfnt_curve_is_flat, sfnt_curve_to_and_build_1)
(sfnt_curve_to_and_build, sfnt_build_glyph_outline)
(struct sfnt_raster, struct sfnt_edge, sfnt_poly_coverage)
(sfnt_poly_grid_ceil, sfnt_prepare_raster, sfnt_step_edge_by)
(sfnt_build_outline_edges, sfnt_compare_edges, sfnt_poly_edges)
(sfnt_saturate_short, sfnt_fill_span, sfnt_poly_span)
(sfnt_raster_span, sfnt_raster_edge, sfnt_raster_glyph_outline)
(struct sfnt_long_hor_metric, struct sfnt_hmtx_table)
(struct sfnt_glyph_metrics, sfnt_read_hmtx_table)
(sfnt_lookup_glyph_metrics, struct sfnt_test_dcontext)
(sfnt_test_move_to, sfnt_test_line_to, sfnt_test_curve_to)
(sfnt_test_get_glyph, sfnt_test_free_glyph, sfnt_test_span)
(sfnt_test_edge, sfnt_test_raster, main): Check in
5000-line-long file written by me for reading TrueType and
OpenType fonts with TrueType outlines.
2023-01-07 20:27:30 +08:00
Po Lu
6d823d1077 Merge remote-tracking branch 'origin/master' into feature/android 2023-01-02 21:38:37 +08:00
Po Lu
a32963e11f Update Android port
* Makefile.in (java): Depend on info.
(MAKEFILE_NAME):
(config.status): Remove unneeded changes.
* configure.ac (BUILD_DETAILS, ANDROID_STUBIFY): Don't require a
C++ compiler on Android.
* java/AndroidManifest.xml: <EmacsActivity>: Set launchMode
appropriately.  <EmacsMultitaskActivity>: New activity.
* java/Makefile.in (CROSS_BINS): Add EmacsClient.
* java/org/gnu/emacs/EmacsActivity.java (EmacsActivity)
(onCreate): Use the window attachment manager.
* java/org/gnu/emacs/EmacsCopyArea.java (EmacsCopyArea)
(paintTo): Implement clip masks correctly.
* java/org/gnu/emacs/EmacsDrawRectangle.java (getRect, paintTo):
Fix damage tracking rectangles.
* java/org/gnu/emacs/EmacsFontDriver.java (FontSpec, toString):
New function.
(FontMetrics, EmacsFontDriver): Fix signature of textExtents.
* java/org/gnu/emacs/EmacsMultitaskActivity.java
(EmacsMultitaskActivity): New file.
* java/org/gnu/emacs/EmacsNative.java (EmacsNative): New
functions sendFocusIn, sendFocusOut, sendWindowAction.
* java/org/gnu/emacs/EmacsPaintQueue.java (run): Fix clipping
handling.
* java/org/gnu/emacs/EmacsPixmap.java (EmacsPixmap): Add
constructor for mutable pixmaps.
* java/org/gnu/emacs/EmacsSdk23FontDriver.java
(EmacsSdk23FontDriver): New file.
* java/org/gnu/emacs/EmacsSdk7FontDriver.java
(EmacsSdk7FontDriver, Sdk7Typeface, Sdk7FontEntity, Sdk7FontObject)
(checkMatch, hasChar, encodeChar): Implement text display and
fix font metrics semantics.

* java/org/gnu/emacs/EmacsService.java (EmacsService): Remove
availableChildren.
(getLibraryDirectory, onCreate): Pass pixel density to Emacs.
(clearArea): Fix arguments.  Switch to using the window
attachment manager.
* java/org/gnu/emacs/EmacsSurfaceView.java (surfaceChanged)
(surfaceCreated): Flip buffers on surface attachment.
* java/org/gnu/emacs/EmacsView.java (EmacsView, swapBuffers):
New argument FORCE.  Always swap if it is true.
(onKeyMultiple, onFocusChanged): New functions.

* java/org/gnu/emacs/EmacsWindow.java (EmacsWindow, destroyHandle)
(run): Switch to using the window attachment manager.
* java/org/gnu/emacs/EmacsWindowAttachmentManager.java
(EmacsWindowAttachmentManager): New file.

* lisp/cus-edit.el (custom-button, custom-button-mouse)
(custom-button-pressed):
* lisp/faces.el (tool-bar): Define faces correctly on Android.
* src/android.c (struct android_emacs_pixmap): Add mutable
constructor.
(struct android_emacs_drawable): New structure.
(android_write_event): Check if event queue hasn't yet been
initialized.
(android_select): Set errno to EINTR if pselect fails.
(android_close): Remove unused debugging code.
(android_get_home_directory): New function.
(Java_org_gnu_emacs_EmacsNative_setEmacsParams): Set pixel
density and compute game path.
(android_init_emacs_drawable): New function.
(Java_org_gnu_emacs_EmacsNative_sendKeyPress): New argument
`unicode_char'.  Pass it in events.
(Java_org_gnu_emacs_EmacsNative_sendKeyRelease): Likewise.
(Java_org_gnu_emacs_EmacsNative_sendFocusIn)
(Java_org_gnu_emacs_EmacsNative_sendFocusOut)
(Java_org_gnu_emacs_EmacsNative_sendWindowAction): New
functions.
(android_resolve_handle): Export function.
(android_change_gc): Clear clip rects under the right
circumstances.  Set right clip mask field.
(android_create_pixmap_from_bitmap_data): Use correct alpha
channels.
(android_create_pixmap): Create mutable pixmap and avoid
redundant color array allocation.
(android_create_bitmap_from_data, android_create_image)
(android_destroy_image, android_put_pixel, android_get_pixel)
(android_get_image, android_put_image, faccessat): New
functions.

* src/android.h: Update prototypes.

* src/androidfns.c (android_default_font_parameter): Prefer
monospace to Droid Sans Mono.
* src/androidfont.c (struct android_emacs_font_driver): New
method `draw'.
(struct android_emacs_font_spec): New field `dpi'.
(struct androidfont_info): Add font metrics cache.
(android_init_font_driver, android_init_font_spec): Adjust
accordingly.
(androidfont_from_lisp, androidfont_from_java): Handle new
fields.
(androidfont_draw): Implement function.
(androidfont_open_font): Set pixel size correctly.
(androidfont_close_font): Free metrics cache.
(androidfont_cache_text_extents)
(androidfont_check_cached_extents): New functions.
(androidfont_text_extents): Cache glyph metrics somewhere for
future use.
(androidfont_list_family): Implement function.

* src/androidgui.h (enum android_event_type): New focus and
window action events.
(enum android_modifier_mask): New masks.
(struct android_key_event): New field `unicode_char'.
(ANDROID_IS_MODIFIER_KEY): Newmacro.
(struct android_focus_event, struct
android_window_action_event): New structs.
(union android_event): Add new fields.
(enum android_image_format, struct android_image): New enums and
structs.

* src/androidterm.c (android_android_to_emacs_modifiers)
(android_emacs_to_android_modifiers, android_lower_frame)
(android_raise_frame, android_new_focus_frame)
(android_focus_changed, android_detect_focus_change): New
functions.
(handle_one_android_event): Implement focus and key event
handling.
(android_frame_rehighlight): New function.
(android_frame_raise_lower): Implement accordingly.
(android_make_frame_invisible): Clear highlight_frame if
required.
(android_free_frame_resources): Clear x_focus_event_frame if
required.
(android_draw_fringe_bitmap, android_draw_image_foreground)
(android_draw_image_foreground_1)
(android_draw_image_glyph_string): Remove unnecessary code.
(android_create_terminal, android_term_init): Set the baud rate
to something sensible.
* src/androidterm.h (struct android_bitmap_record): Make
structure the same as on X.
(struct android_display_info): New focus tracking fields.
(struct android_output): Likewise.
* src/dispextern.h (struct image): Add ximg and mask_img on
Android.

* src/emacs.c (android_emacs_init): Fix argc sorting iteration.

* src/fileio.c (user_homedir):
(get_homedir): Implement correctly on Android.

* src/font.h (PT_PER_INCH): Define correctly on Android.

* src/fringe.c (X, swap_nibble, init_fringe_bitmap): Swap fringe
bitmaps correctly on Android.

* src/image.c (GET_PIXEL, image_create_bitmap_from_data)
(image_create_bitmap_from_file, free_bitmap_record)
(image_unget_x_image_or_dc, struct image_type)
(prepare_image_for_display, image_clear_image_1)
(image_size_in_bytes, x_check_image_size)
(x_create_x_image_and_pixmap, x_destroy_x_image)
(image_check_image_size, image_create_x_image_and_pixmap_1)
(image_destroy_x_image, gui_put_x_image, image_put_x_image)
(image_get_x_image, image_unget_x_image)
(Create_Pixmap_From_Bitmap_Data, image_pixmap_draw_cross)
(MaskForeground, image_types, syms_of_image): Implement all of
the above on Android in terms of an API very similar to X.

* src/keyboard.c (FUNCTION_KEY_OFFSET, lispy_function_keys):
Define on Android to something sensible.

* src/lread.c (build_load_history): Fix problem.
2023-01-02 21:38:19 +08:00
Po Lu
fd074f3133 Merge remote-tracking branch 'origin/master' into feature/android 2022-12-31 18:05:12 +08:00
Po Lu
cfbc8a5dbc Bring up the Android operating system and its window system
* .dir-locals.el (c-mode): Add ANDROID_EXPORT noise macro.
* .gitignore: Add new files to ignore.
* Makefile.in: Adjust for Android.
* admin/merge-gnulib: Add new warning.
* configure.ac: Detect Android.  Run cross-configuration for
Android when appropriate.

* etc/DEBUG: Document how to debug Emacs on Android.

* java/AndroidManifest.xml:
* java/Makefile.in:
* java/README:
* java/debug.sh:
* java/org/gnu/emacs/EmacsActivity.java (EmacsActivity):
* java/org/gnu/emacs/EmacsApplication.java (EmacsApplication):
* java/org/gnu/emacs/EmacsCopyArea.java (EmacsCopyArea):
* java/org/gnu/emacs/EmacsDrawLine.java (EmacsDrawLine):
* java/org/gnu/emacs/EmacsDrawPoint.java (EmacsDrawPoint):
* java/org/gnu/emacs/EmacsDrawRectangle.java
(EmacsDrawRectangle):
* java/org/gnu/emacs/EmacsDrawable.java (EmacsDrawable):
* java/org/gnu/emacs/EmacsFillPolygon.java (EmacsFillPolygon):
* java/org/gnu/emacs/EmacsFillRectangle.java
(EmacsFillRectangle):
* java/org/gnu/emacs/EmacsFontDriver.java (EmacsFontDriver):
* java/org/gnu/emacs/EmacsGC.java (EmacsGC):
* java/org/gnu/emacs/EmacsHandleObject.java (EmacsHandleObject):
* java/org/gnu/emacs/EmacsNative.java (EmacsNative):
* java/org/gnu/emacs/EmacsPaintQueue.java (EmacsPaintQueue):
* java/org/gnu/emacs/EmacsPaintReq.java (EmacsPaintReq):
* java/org/gnu/emacs/EmacsPixmap.java (EmacsPixmap):
* java/org/gnu/emacs/EmacsSdk7FontDriver.java
(EmacsSdk7FontDriver):
* java/org/gnu/emacs/EmacsService.java (class Holder<T>)
(EmacsService):
* java/org/gnu/emacs/EmacsSurfaceView.java (EmacsSurfaceView):
* java/org/gnu/emacs/EmacsThread.java (EmacsThread):
* java/org/gnu/emacs/EmacsView.java (EmacsView):
* java/org/gnu/emacs/EmacsWindow.java (EmacsWindow): New files
and classes.

* lib-src/Makefile.in (srcdir):
* lib/Makefile.in (VPATH):
(HAVE_NATIVE_COMP):
(libgnu_a_SOURCES):
(DEPFLAGS): Configure correctly for cross-compiling.

* lib/faccessat.c:
* lib/fpending.c (__fpending):
* lib/open.c:
* lib/unistd.c (_GL_UNISTD_INLINE): Temporary adjustments to
gnulib.

* lisp/frame.el (display-graphic-p):
(display-screens):
(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): Adjust for new window system `android'.

* lisp/image/wallpaper.el (x-open-connection): Add declaration.
* lisp/loadup.el (featurep): Load up files for Android.
* lisp/net/eww.el (eww-form-submit, eww-form-file)
(eww-form-checkbox, eww-form-select): Adjust faces for android.
* lisp/term/android-win.el: New file.
* src/Makefile.in: Add new targets emacs.so and android-emacs,
then adjust for cross compilation.
* src/alloc.c (cleanup_vector): Clean up Android font entities
as well.
(garbage_collect): Mark androidterm.
* src/android-emacs.c (main):
* src/android.c (ANDROID_THROW, enum android_fd_table_entry_flags)
(struct android_emacs_service, struct android_emacs_pixmap)
(struct android_graphics_point, struct android_event_container)
(struct android_event_queue, android_run_select_thread)
(android_handle_sigusr1, android_init_events, android_pending)
(android_next_event, android_write_event, android_select)
(android_run_debug_thread, android_user_full_name)
(android_get_asset_name, android_fstat, android_fstatat)
(android_file_access_p, android_hack_asset_fd, android_open)
(android_close, JNICALL, android_init_emacs_service)
(android_init_emacs_pixmap, android_init_graphics_point)
(MAX_HANDLE, struct android_handle_entry, android_alloc_id)
(android_destroy_handle, android_resolve_handle)
(android_resolve_handle2, android_change_window_attributes)
(android_create_window, android_set_window_background)
(android_destroy_window, android_init_android_rect_class)
(android_init_emacs_gc_class, android_create_gc, android_free_gc)
(android_change_gc, android_set_clip_rectangles)
(android_reparent_window, android_lookup_method)
(android_clear_window, android_map_window, android_unmap_window)
(android_resize_window, android_move_window, android_swap_buffers)
(android_get_gc_values, android_set_foreground)
(android_fill_rectangle, android_create_pixmap_from_bitmap_data)
(android_set_clip_mask, android_set_fill_style, android_copy_area)
(android_free_pixmap, android_set_background, android_fill_polygon)
(android_draw_rectangle, android_draw_point, android_draw_line)
(android_create_pixmap, android_set_ts_origin, android_clear_area):
* src/android.h (ANDROID_EXPORT):
* src/androidfns.c (android_display_info_for_name)
(check_android_display_info, check_x_display_info, gamma_correct)
(android_defined_color, android_decode_color)
(android_implicitly_set_name, android_explicitly_set_name)
(android_set_tool_bar_lines, android_change_tool_bar_height)
(android_set_tab_bar_lines, android_change_tab_bar_height)
(android_set_scroll_bar_default_height)
(android_set_scroll_bar_default_width, android_icon_verify)
(android_icon, android_make_gc, android_free_gcs)
(unwind_create_frame, do_unwind_create_frame)
(android_default_font_parameter, android_create_frame_window)
(Fx_create_frame, Fxw_color_defined_p, Fxw_color_values)
(Fxw_display_color_p, Fx_display_grayscale_p)
(Fx_display_pixel_width, Fx_display_pixel_height)
(Fx_display_planes, Fx_display_color_cells, Fx_display_screens)
(Fx_display_mm_width, Fx_display_mm_height)
(Fx_display_backing_store, Fx_display_visual_class)
(Fx_display_monitor_attributes_list, Fx_frame_geometry)
(Fx_frame_list_z_order, Fx_frame_restack)
(Fx_mouse_absolute_pixel_position)
(Fx_set_mouse_absolute_pixel_position, Fandroid_get_connection)
(Fx_display_list, Fx_show_tip, Fx_hide_tip)
(android_set_background_color, android_set_border_color)
(android_set_cursor_color, android_set_cursor_type)
(android_set_foreground_color)
(android_set_child_frame_border_width)
(android_set_internal_border_width, android_set_menu_bar_lines)
(android_set_mouse_color, android_set_title, android_set_alpha)
(android_frame_parm_handlers, syms_of_androidfns):
* src/androidfont.c (struct android_emacs_font_driver)
(struct android_emacs_font_spec, struct android_emacs_font_metrics)
(struct android_emacs_font_object, struct android_integer)
(struct androidfont_info, struct androidfont_entity)
(android_init_font_driver, android_init_font_spec)
(android_init_font_metrics, android_init_integer)
(android_init_font_object, androidfont_get_cache)
(androidfont_from_lisp, androidfont_from_java, androidfont_list)
(androidfont_match, androidfont_draw, androidfont_open_font)
(androidfont_close_font, androidfont_has_char)
(androidfont_encode_char, androidfont_text_extents)
(androidfont_list_family, androidfont_driver)
(syms_of_androidfont_for_pdumper, syms_of_androidfont)
(init_androidfont, android_finalize_font_entity):
* src/androidgui.h (_ANDROID_GUI_H_, struct android_rectangle)
(struct android_point, enum android_gc_function)
(enum android_gc_value_mask, enum android_fill_style)
(enum android_window_value_mask)
(struct android_set_window_attributes, struct android_gc_values)
(struct android_gc, enum android_swap_action, enum android_shape)
(enum android_coord_mode, struct android_swap_info)
(NativeRectangle, struct android_any_event)
(struct android_key_event, struct android_configure_event)
(union android_event):
* src/androidterm.c (android_window_to_frame, android_clear_frame)
(android_ring_bell, android_toggle_invisible_pointer)
(android_update_begin, android_update_end, show_back_buffer)
(android_flush_dirty_back_buffer_on, handle_one_android_event)
(android_read_socket, android_frame_up_to_date)
(android_buffer_flipping_unblocked_hook)
(android_query_frame_background_color, android_parse_color)
(android_alloc_nearest_color, android_query_colors)
(android_mouse_position, android_get_focus_frame)
(android_focus_frame, android_frame_rehighlight)
(android_frame_raise_lower, android_make_frame_visible)
(android_make_frame_invisible)
(android_make_frame_visible_invisible, android_fullscreen_hook)
(android_iconify_frame, android_set_window_size_1)
(android_set_window_size, android_set_offset, android_set_alpha)
(android_new_font, android_bitmap_icon, android_free_pixmap_hook)
(android_free_frame_resources, android_delete_frame)
(android_delete_terminal, android_scroll_run)
(android_after_update_window_line, android_flip_and_flush)
(android_clear_rectangle, android_reset_clip_rectangles)
(android_clip_to_row, android_draw_fringe_bitmap)
(android_set_cursor_gc, android_set_mouse_face_gc)
(android_set_mode_line_face_gc, android_set_glyph_string_gc)
(android_set_glyph_string_clipping)
(android_set_glyph_string_clipping_exactly)
(android_compute_glyph_string_overhangs)
(android_clear_glyph_string_rect)
(android_draw_glyph_string_background, android_fill_triangle)
(android_make_point, android_inside_rect_p, android_clear_point)
(android_draw_relief_rect, android_draw_box_rect)
(HIGHLIGHT_COLOR_DARK_BOOST_LIMIT, android_setup_relief_color)
(android_setup_relief_colors, android_draw_glyph_string_box)
(android_draw_glyph_string_bg_rect, android_draw_image_relief)
(android_draw_image_foreground, android_draw_image_foreground_1)
(android_draw_image_glyph_string)
(android_draw_stretch_glyph_string, android_draw_underwave)
(android_draw_glyph_string_foreground)
(android_draw_composite_glyph_string_foreground)
(android_draw_glyphless_glyph_string_foreground)
(android_draw_glyph_string, android_define_frame_cursor)
(android_clear_frame_area, android_clear_under_internal_border)
(android_draw_hollow_cursor, android_draw_bar_cursor)
(android_draw_window_cursor, android_draw_vertical_window_border)
(android_draw_window_divider, android_redisplay_interface)
(frame_set_mouse_pixel_position, get_keysym_name)
(android_create_terminal, android_term_init, syms_of_androidterm)
(mark_androidterm):
* src/androidterm.h (_ANDROID_TERM_H_, struct android_display_info)
(struct android_output, FRAME_ANDROID_OUTPUT, XSCROLL_BAR): New
files.
* src/dired.c (file_attributes): Do not use openat on Android.
* src/dispextern.h (No_Cursor): Define appropriately on Android.
(struct glyph_string, struct face): Make gc field of type struct
android_gc on Android.
* src/dispnew.c (clear_current_matrices, clear_desired_matrices)
(adjust_frame_glyphs_for_window_redisplay, free_glyphs)
(update_frame, scrolling, char_ins_del_cost, update_frame_line)
(init_display_interactive): Disable text terminal support
completely on Android.  Fix non-toolkit menus for non-X systems.
* src/editfns.c (Fuser_full_name): Call android_user_full_name.
* src/emacs.c (android_emacs_init): Make main this on Android.
Prohibit argv sorting from exceeding end of argv.
* src/epaths.in: Add path definitions for Android.

* src/fileio.c (file_access_p): Call android_file_access_p.
(file_name_directory): Avoid using openat on Android.
(Fcopy_file): Adjust to call sys_fstat instead.
(file_directory_p):
(Finsert_file_contents):
(write_region): Likewise.
* src/filelock.c:
* src/fns.c (Flocale_info): Pacify warning on Android.
* src/font.c (font_make_entity_android): New function.
* src/font.h:
* src/frame.c (Fframep):
(Fwindow_system): Handle new window system `android'.  Update doc strings.
(Fmake_terminal_frame): Disable on Android.
(gui_display_get_resource): Disable get_string_resource_hook on Android.
(syms_of_frame): New defsym `android'.

* src/frame.h (GCALIGNED_STRUCT): Add new output data for
Android.
(ENUM_BF): Expand enumerator size.
(FRAME_ANDROID_P, FRAME_WINDOW_P, MOUSE_HL_INFO): Add
definitions for Android.

* src/image.c (GET_PIXEL):
(image_create_bitmap_from_file):
(image_create_x_image_and_pixmap_1):
(image_get_x_image):
(slurp_file):
(lookup_rgb_color):
(image_to_emacs_colors):
(image_from_emacs_colors):
(image_pixmap_draw_cross):
(image_disable_image):
(MaskForeground):
(gif_load): Add stubs for Android.

* src/lisp.h:
* src/lread.c (safe_to_load_version, maybe_swap_for_eln1, openp):
* src/pdumper.c (pdumper_load): Call sys_fstat instead of fstat.
* src/process.c (wait_reading_process_output): Use
android_select instead of pselect.
* src/scroll.c: Disable on Android.
* src/sysdep.c (widen_foreground_group, reset_sys_modes)
(init_signals, emacs_fstatat, sys_fstat): New function.
(emacs_open, emacs_open_noquit, emacs_close): Implement
differently on Android.
(close_output_streams): Disable what is not required on Android.

* src/term.c (OUTPUT1_IF, encode_terminal_code, string_cost)
(string_cost_one_line, per_line_cost, calculate_costs)
(struct fkey_table, tty_append_glyph, produce_glyphs)
(tty_capable_p, Fsuspend_tty, Fresume_tty, device, init_tty)
(maybe_fatal, syms_of_term): Disable text terminal support on
Android.

* src/termhooks.h (enum output_method): Add android output
method.
(GCALIGNED_STRUCT, TERMINAL_FONT_CACHE): Define for Android.

* src/terminal.c (Fterminal_live_p): Implement for Android.

* src/verbose.mk.in (AM_V_GLOBALS): Add JAVAC and DX.
* src/xdisp.c (redisplay_internal): Disable text terminals on Android.
(display_menu_bar):
(display_tty_menu_item):
(draw_row_with_mouse_face):
(expose_frame): Make the non toolkit menu bar work on Android.

* src/xfaces.c (GCGraphicsExposures):
(x_create_gc):
(x_free_gc):
(Fx_load_color_file): Define for Android.

* xcompile/Makefile.in (top_srcdir):
(top_builddir):
* xcompile/README:
* xcompile/langinfo.h (nl_langinfo): New files.
2022-12-31 18:04:18 +08:00
315 changed files with 99628 additions and 936 deletions

View file

@ -12,7 +12,7 @@
(c-mode . ((c-file-style . "GNU")
(c-noise-macro-names . ("INLINE" "NO_INLINE" "ATTRIBUTE_NO_SANITIZE_UNDEFINED"
"UNINIT" "CALLBACK" "ALIGN_STACK" "ATTRIBUTE_MALLOC"
"ATTRIBUTE_DEALLOC_FREE"))
"ATTRIBUTE_DEALLOC_FREE" "ANDROID_EXPORT"))
(electric-quote-comment . nil)
(electric-quote-string . nil)
(indent-tabs-mode . t)

45
.gitignore vendored
View file

@ -52,6 +52,23 @@ src/config.h
src/epaths.h
src/emacs-module.h
# Built by recursive call to `configure'.
*.android
!INSTALL.android
!verbose.mk.android
# Built by `javac'.
java/install_temp/*
java/*.apk*
java/*.dex
java/org/gnu/emacs/*.class
# Built by `aapt'.
java/org/gnu/emacs/R.java
# Built by `config.status'.
java/AndroidManifest.xml
# C-level sources built by 'make'.
lib/alloca.h
lib/assert.h
@ -70,8 +87,10 @@ lib/limits.h
lib/malloc/*.gl.h
lib/signal.h
lib/std*.h
lib/math.h
!lib/std*.in.h
!lib/stdio-impl.h
!lib/_Noreturn.h
lib/string.h
lib/sys/
lib/time.h
@ -81,6 +100,18 @@ src/globals.h
src/lisp.mk
src/verbose.mk
# Stuff built during cross compilation
cross/lib/*
cross/src/*
cross/lib-src/*
cross/sys/*
cross/config.status
cross/*.bak
cross/ndk-build/Makefile
cross/ndk-build/ndk-build.mk
cross/ndk-build/*.o
# Lisp-level sources built by 'make'.
*cus-load.el
*loaddefs.el
@ -186,6 +217,7 @@ ID
# Executables.
*.exe
a.out
lib-src/asset-directory-tool
lib-src/be-resources
lib-src/blessmail
lib-src/ctags
@ -208,6 +240,7 @@ nextstep/GNUstep/Emacs.base/Resources/Info-gnustep.plist
src/bootstrap-emacs
src/emacs
src/emacs-[0-9]*
src/sfnt
src/Emacs
src/temacs
src/dmpstruct.h
@ -338,3 +371,15 @@ lib-src/seccomp-filter-exec.pfc
# GDB history
.gdb_history
_gdb_history
# Files ignored in exec/.
exec/config.status
exec/loader
exec/test
exec/exec1
exec/deps/*
exec/autom4te.cache
exec/config.h
exec/config-mips.m4
exec/configure
exec/*.s.s

View file

@ -5,9 +5,9 @@ See the end of the file for license conditions.
This file contains general information on building GNU Emacs. For
more information specific to the MS-Windows, GNUstep/macOS, and MS-DOS
ports, also read the files nt/INSTALL, nextstep/INSTALL, and
msdos/INSTALL.
more information specific to the MS-Windows, GNUstep/macOS, MS-DOS,
and Android ports, also read the files nt/INSTALL, nextstep/INSTALL,
msdos/INSTALL, and java/INSTALL.
For information about building from a Git checkout (rather than an
Emacs release), read the INSTALL.REPO file first.

View file

@ -106,15 +106,15 @@ top_builddir = @top_builddir@
FIND_DELETE = @FIND_DELETE@
HAVE_NATIVE_COMP = @HAVE_NATIVE_COMP@
USE_STARTUP_NOTIFICATION = @USE_STARTUP_NOTIFICATION@
HAVE_NATIVE_COMP = @HAVE_NATIVE_COMP@
HAVE_BE_APP = @HAVE_BE_APP@
HAVE_PGTK = @HAVE_PGTK@
HAVE_GSETTINGS = @HAVE_GSETTINGS@
ANDROID = @ANDROID@
# ==================== Where To Install Things ====================
# Location to install Emacs.app under GNUstep / macOS.
@ -339,6 +339,10 @@ EMACS_PDMP = `./src/emacs${EXEEXT} --fingerprint`.pdmp
# Subdirectories to make recursively.
SUBDIR = $(NTDIR) lib lib-src src lisp
ifeq ($(ANDROID),yes)
SUBDIR := $(SUBDIR) java
endif
# The subdir makefiles created by config.status.
SUBDIR_MAKEFILES_IN = @SUBDIR_MAKEFILES_IN@
SUBDIR_MAKEFILES = $(patsubst ${srcdir}/%,%,${SUBDIR_MAKEFILES_IN:.in=})
@ -467,20 +471,20 @@ epaths-force:
esac; \
done
@(gamedir='${gamedir}'; \
sed < ${srcdir}/src/epaths.in > epaths.h.$$$$ \
-e 's;\(#.*PATH_LOADSEARCH\).*$$;\1 "${standardlisppath}";' \
-e 's;\(#.*PATH_REL_LOADSEARCH\).*$$;\1 "${lispdirrel}";' \
-e 's;\(#.*PATH_SITELOADSEARCH\).*$$;\1 "${locallisppath}";' \
-e 's;\(#.*PATH_DUMPLOADSEARCH\).*$$;\1 "${buildlisppath}";' \
-e '/^#define PATH_[^ ]*SEARCH /s/\([":]\):*/\1/g' \
-e '/^#define PATH_[^ ]*SEARCH /s/:"/"/' \
-e 's;\(#.*PATH_EXEC\).*$$;\1 "${archlibdir}";' \
-e 's;\(#.*PATH_INFO\).*$$;\1 "${infodir}";' \
-e 's;\(#.*PATH_DATA\).*$$;\1 "${etcdir}";' \
-e 's;\(#.*PATH_BITMAPS\).*$$;\1 "${bitmapdir}";' \
-e 's;\(#.*PATH_X_DEFAULTS\).*$$;\1 "${x_default_search_path}";' \
-e 's;\(#.*PATH_GAME\).*$$;\1 $(PATH_GAME);' \
-e 's;\(#.*PATH_DOC\).*$$;\1 "${etcdocdir}";') && \
sed < ${srcdir}/src/epaths.in > epaths.h.$$$$ \
-e 's;\(#define.*PATH_LOADSEARCH\).*$$;\1 "${standardlisppath}";' \
-e 's;\(#define.*PATH_REL_LOADSEARCH\).*$$;\1 "${lispdirrel}";' \
-e 's;\(#define.*PATH_SITELOADSEARCH\).*$$;\1 "${locallisppath}";' \
-e 's;\(#define.*PATH_DUMPLOADSEARCH\).*$$;\1 "${buildlisppath}";' \
-e '/^#define PATH_[^ ]*SEARCH /s/\([":]\):*/\1/g' \
-e '/^#define PATH_[^ ]*SEARCH /s/:"/"/' \
-e 's;\(#define.*PATH_EXEC\).*$$;\1 "${archlibdir}";' \
-e 's;\(#define.*PATH_INFO\).*$$;\1 "${infodir}";' \
-e 's;\(#define.*PATH_DATA\).*$$;\1 "${etcdir}";' \
-e 's;\(#define.*PATH_BITMAPS\).*$$;\1 "${bitmapdir}";' \
-e 's;\(#define.*PATH_X_DEFAULTS\).*$$;\1 "${x_default_search_path}";' \
-e 's;\(#define.*PATH_GAME\).*$$;\1 $(PATH_GAME);' \
-e 's;\(#define.*PATH_DOC\).*$$;\1 "${etcdocdir}";') && \
${srcdir}/build-aux/move-if-change epaths.h.$$$$ src/epaths.h
# The w32 build needs a slightly different editing, and it uses
@ -532,6 +536,12 @@ lisp: src
lib lib-src lisp nt: Makefile
$(MAKE) -C $@ all
java: lisp info
$(MAKE) -C $@ all
cross: src
$(MAKE) -C $@ all
trampolines: src lisp
ifeq ($(HAVE_NATIVE_COMP),yes)
$(MAKE) -C lisp trampolines
@ -569,10 +579,13 @@ $(MAKEFILE_NAME): config.status $(srcdir)/configure \
# Don't erase these files if make is interrupted while refreshing them.
.PRECIOUS: Makefile config.status
# Note that calling config.status --recheck is insufficient on Android
# due to the recursive calls to configure.
config.status: ${srcdir}/configure
if [ -x ./config.status ]; then \
if [ -x ./config.status ]; then \
$(CFG) ./config.status --recheck; \
else \
else \
$(CFG) $(srcdir)/configure $(CONFIGURE_FLAGS); \
fi
@ -987,6 +1000,12 @@ endef
mostlyclean_dirs = src oldXMenu lwlib lib lib-src nt doc/emacs doc/misc \
doc/lispref doc/lispintro test
### Add the libexec directory to mostlyclean_dirs if its Makefile has
### been created.
ifneq ($(wildcard exec/Makefile),)
mostlyclean_dirs := $(mostlyclean_dirs) exec
endif
$(foreach dir,$(mostlyclean_dirs),$(eval $(call submake_template,$(dir),mostlyclean)))
mostlyclean: $(mostlyclean_dirs:=_mostlyclean)
@ -999,7 +1018,8 @@ mostlyclean: $(mostlyclean_dirs:=_mostlyclean)
### with them.
###
### Delete '.dvi' files here if they are not part of the distribution.
clean_dirs = $(mostlyclean_dirs) nextstep admin/charsets admin/unidata
clean_dirs = $(mostlyclean_dirs) java cross nextstep admin/charsets \
admin/unidata
$(foreach dir,$(clean_dirs),$(eval $(call submake_template,$(dir),clean)))
@ -1081,6 +1101,8 @@ extraclean: maintainer-clean
-[ "${srcdir}" = "." ] || \
find ${srcdir} '(' -name '*~' -o -name '#*' ')' ${FIND_DELETE}
-find . '(' -name '*~' -o -name '#*' ')' ${FIND_DELETE}
-rm -f ${srcdir}/exec/config-tmp-* ${srcdir}/exec/aclocal.m4 \
${srcdir}/src/config.in ${srcdir}/exec/configure
# The src subdir knows how to do the right thing
# even when the build directory and source dir are different.

5
README
View file

@ -95,6 +95,11 @@ There are several subdirectories:
'admin' holds files used by Emacs developers, and Unicode data files.
'build-aux' holds auxiliary files used during the build.
'm4' holds Autoconf macros used for generating the configure script.
'java' holds the Java code for the Emacs port to Android.
'cross' holds Makefiles and an additional copy of gnulib used to build
Emacs for Android devices.
'exec' holds the source code to several helper executables used to run
user-installed programs on Android.
Building Emacs on non-Posix platforms requires tools that aren't part
of the standard distribution of the OS. The platform-specific README

View file

@ -37,15 +37,15 @@ GNULIB_MODULES='
fchmodat fcntl fcntl-h fdopendir file-has-acl
filemode filename filevercmp flexmember fpieee
free-posix fstatat fsusage fsync futimens
getloadavg getopt-gnu getrandom gettime gettimeofday gitlog-to-changelog
getline getloadavg getopt-gnu getrandom gettime gettimeofday gitlog-to-changelog
ieee754-h ignore-value intprops largefile libgmp lstat
manywarnings memmem-simple mempcpy memrchr memset_explicit
minmax mkostemp mktime
nanosleep nproc nstrftime
pathmax pipe2 pselect pthread_sigmask
pathmax pipe2 printf-posix vasprintf-posix pselect pthread_sigmask
qcopy-acl readlink readlinkat regex
sig2str sigdescr_np socklen stat-time std-gnu11 stdbool stddef stdio
stpcpy strnlen strtoimax symlink sys_stat sys_time
stpcpy stpncpy strnlen strtoimax symlink sys_stat sys_time
tempname time-h time_r time_rz timegm timer-time timespec-add timespec-sub
update-copyright unlocked-io utimensat
vla warnings
@ -114,6 +114,11 @@ for module in $AVOIDED_MODULES; do
avoided_flags="$avoided_flags --avoid=$module"
done
# Clean the lib directory as well.
if [ -e "$src"/lib/Makefile ]; then
make -C "$src"/lib maintainer-clean
fi
"$gnulib_srcdir"/gnulib-tool --dir="$src" $GNULIB_TOOL_FLAGS \
$avoided_flags $GNULIB_MODULES &&
rm -- "$src"lib/gl_openssl.h \

View file

@ -256,6 +256,12 @@ Please report any problems with this script to bug-gnu-emacs@gnu.org .'
## Let autoreconf figure out what, if anything, needs doing.
## Use autoreconf's -f option in case autoreconf itself has changed.
autoreconf -fi -I m4 || exit
echo "Running 'autoreconf -fi' in exec ..."
# Now, run autoreconf inside the exec directory to generate its
# configure script.
autoreconf -fi exec || exit
fi

View file

@ -0,0 +1,112 @@
# ndk-build-helper-1.mk -- Helper for ndk-build.m4.
# Copyright (C) 2023 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/>.
# Print out information now defined. Important details include:
# - list of source files to compile.
# - module export include directories.
# - module export CFLAGS.
# - module export LDFLAGS.
# - module name.
build_kind = shared
NDK_SO_NAMES =
NDK_A_NAMES =
# Record this module's dependencies. This information is used later
# on to recurse over libraries.
NDK_$(LOCAL_MODULE)_STATIC_LIBRARIES := $(LOCAL_STATIC_LIBRARIES) $(LOCAL_WHOLE_STATIC_LIBRARIES)
NDK_$(LOCAL_MODULE)_SHARED_LIBRARIES := $(LOCAL_SHARED_LIBRARIES)
NDK_$(LOCAL_MODULE)_EXPORT_INCLUDES := $(LOCAL_EXPORT_C_INCLUDE_DIRS) $(LOCAL_EXPORT_C_INCLUDES)
NDK_CXX_FLAG_$(LOCAL_MODULE) :=
$(info Building $(build_kind))
$(info $(LOCAL_MODULE))
$(info $(addprefix $(LOCAL_PATH)/,$(LOCAL_SRC_FILES) $(LOCAL_SRC_FILES$(EMACS_ABI))))
ifeq ($(findstring lib,$(LOCAL_MODULE)),lib)
NDK_SO_NAMES = $(LOCAL_MODULE)_emacs.so
else
NDK_SO_NAMES = lib$(LOCAL_MODULE)_emacs.so
endif
define add-so-name-1
# Now recurse over this module's dependencies.
$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_SHARED_LIBRARIES)),$$(eval $$(call add-so-name,$$(module))))
$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_STATIC_LIBRARIES)),$$(eval $$(call add-so-name-1,$$(module))))
endef
define add-so-name
ifeq ($(findstring lib,$(1)),lib)
NDK_SO_NAME = $(1)_emacs.so
else
NDK_SO_NAME = lib$(1)_emacs.so
endif
ifeq ($$(findstring $$(NDK_SO_NAME),$$(NDK_SO_NAMES)),)
NDK_SO_NAMES := $$(NDK_SO_NAMES) $$(NDK_SO_NAME)
# Now recurse over this module's dependencies.
$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_SHARED_LIBRARIES)),$$(eval $$(call add-so-name,$$(module))))
# Recurse over static library dependencies of this shared library.
$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_STATIC_LIBRARIES) $$(NDK_$(1)_WHOLE_LIBRARIES)),$$(eval $$(call add-so-name-1,$$(module))))
endif
ifneq ($$(findstring stdc++,$$(NDK_$(1)_SHARED_LIBRARIES)),)
NDK_CXX_FLAG_$(LOCAL_MODULE) := yes
endif
endef
# Figure out includes from dependencies as well.
NDK_INCLUDES := $(LOCAL_EXPORT_C_INCLUDE_DIRS) $(LOCAL_EXPORT_C_INCLUDES)
define add-includes
ifeq ($$(findstring $$(NDK_$(1)_EXPORT_INCLUDES),$$(NDK_INCLUDES)),)
NDK_INCLUDES += $$(NDK_$(1)_EXPORT_INCLUDES)
$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_SHARED_LIBRARIES)) $$(NDK_$(1)_STATIC_LIBRARIES),$$(eval $$(call add-includes,$$(module))))
# Recurse over shared library dependencies of this static library.
$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_SHARED_LIBRARIES)),$$(eval $$(call add-so-name,$$(module))))
# Recurse over static or shared library dependencies of this static
# library.
$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_STATIC_LIBRARIES)),$$(eval $$(call add-so-name-1,$$(module))))
endif
endef
# Resolve additional dependencies and their export includes based on
# LOCAL_STATIC_LIBRARIES and LOCAL_SHARED_LIBRARIES. Static library
# dependencies can be ignored while building a shared library, as they
# will be linked in to the resulting shared object file later.
SYSTEM_LIBRARIES = z libz libc c libdl dl stdc++ libstdc++ log liblog android libandroid
$(foreach module,$(filter-out $(SYSTEM_LIBRARIES), $(LOCAL_SHARED_LIBRARIES)),$(eval $(call add-so-name,$(module))))
$(foreach module,$(filter-out $(SYSTEM_LIBRARIES), $(LOCAL_SHARED_LIBRARIES) $(LOCAL_STATIC_LIBRARIES) $(LOCAL_WHOLE_STATIC_LIBRARIES)),$(eval $(call add-includes,$(module))))
ifneq ($(findstring stdc++,$(LOCAL_SHARED_LIBRARIES)),)
NDK_CXX_FLAG_$(LOCAL_MODULE) := yes
endif
$(info $(foreach dir,$(NDK_INCLUDES),-I$(dir)))
$(info $(LOCAL_EXPORT_CFLAGS))
$(info $(LOCAL_EXPORT_LDFLAGS) $(abspath $(addprefix $(NDK_BUILD_DIR)/,$(NDK_A_NAMES))) -L$(abspath $(NDK_BUILD_DIR)) $(foreach soname,$(NDK_SO_NAMES),-l:$(soname)))
$(info $(NDK_SO_NAMES))
$(info $(NDK_CXX_FLAG_$(LOCAL_MODULE)))
$(info End)

View file

@ -0,0 +1,105 @@
# ndk-build-helper-2.mk -- Helper for ndk-build.m4.
# Copyright (C) 2023 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/>.
# Say a static library is being built
build_kind = static
NDK_SO_NAMES =
NDK_A_NAMES =
# Record this module's dependencies. This information is used later
# on to recurse over libraries.
NDK_$(LOCAL_MODULE)_STATIC_LIBRARIES := $(LOCAL_STATIC_LIBRARIES) $(LOCAL_WHOLE_STATIC_LIBRARIES)
NDK_$(LOCAL_MODULE)_SHARED_LIBRARIES := $(LOCAL_SHARED_LIBRARIES)
NDK_$(LOCAL_MODULE)_EXPORT_INCLUDES := $(LOCAL_EXPORT_C_INCLUDE_DIRS) $(LOCAL_EXPORT_C_INCLUDES)
NDK_CXX_FLAG_$(LOCAL_MODULE) :=
$(info Building $(build_kind))
$(info $(LOCAL_MODULE))
$(info $(addprefix $(LOCAL_PATH)/,$(LOCAL_SRC_FILES) $(LOCAL_SRC_FILES$(EMACS_ABI))))
ifeq ($(findstring lib,$(LOCAL_MODULE)),lib)
NDK_A_NAMES = $(LOCAL_MODULE).a
else
NDK_A_NAMES = lib$(LOCAL_MODULE).a
endif
define add-a-name
ifeq ($(findstring lib,$(1)),lib)
NDK_A_NAME = $(1).a
else
NDK_A_NAME = lib$(1).a
endif
ifeq ($$(findstring $$(NDK_A_NAME),$$(NDK_A_NAMES)),)
NDK_A_NAMES := $$(NDK_A_NAMES) $$(NDK_A_NAME)
# Now recurse over this module's dependencies.
$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_STATIC_LIBRARIES)),$$(eval $$(call add-a-name,$$(module))))
$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_SHARED_LIBRARIES)),$$(eval $$(call add-so-name,$$(module))))
endif
ifneq ($$(findstring stdc++,$$(NDK_$(1)_SHARED_LIBRARIES)),)
NDK_CXX_FLAG_$(LOCAL_MODULE) := yes
endif
endef
define add-so-name
ifeq ($(findstring lib,$(1)),lib)
NDK_SO_NAME = $(1)_emacs.so
else
NDK_SO_NAME = lib$(1)_emacs.so
endif
ifeq ($$(NDK_SO_NAMES:$$(NDK_SO_NAME)=),$$(NDK_SO_NAMES))
NDK_SO_NAMES := $$(NDK_SO_NAMES) $$(NDK_SO_NAME)
# Now recurse over this module's dependencies.
$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_STATIC_LIBRARIES)),$$(eval $$(call add-a-name,$$(module))))
$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_SHARED_LIBRARIES)),$$(eval $$(call add-so-name,$$(module))))
endif
endef
# Figure out includes from dependencies as well.
NDK_INCLUDES := $(LOCAL_EXPORT_C_INCLUDE_DIRS) $(LOCAL_EXPORT_C_INCLUDES)
define add-includes
ifeq ($$(findstring $$(NDK_$(1)_EXPORT_INCLUDES),$$(NDK_INCLUDES)),)
NDK_INCLUDES += $$(NDK_$(1)_EXPORT_INCLUDES)
$$(foreach module,$$(filter-out $$(SYSTEM_LIBRARIES), $$(NDK_$(1)_SHARED_LIBRARIES)) $$(NDK_$(1)_STATIC_LIBRARIES),$$(eval $$(call add-includes,$$(module))))
endif
endef
# Resolve additional dependencies based on LOCAL_STATIC_LIBRARIES and
# LOCAL_SHARED_LIBRARIES.
SYSTEM_LIBRARIES = z libz libc c libdl dl libstdc++ stdc++ log liblog android libandroid
$(foreach module,$(filter-out $(SYSTEM_LIBRARIES), $(LOCAL_STATIC_LIBRARIES) $(LOCAL_WHOLE_STATIC_LIBRARIES)),$(eval $(call add-a-name,$(module))))
$(foreach module,$(filter-out $(SYSTEM_LIBRARIES), $(LOCAL_SHARED_LIBRARIES)),$(eval $(call add-so-name,$(module))))
$(foreach module,$(filter-out $(SYSTEM_LIBRARIES), $(LOCAL_SHARED_LIBRARIES) $(LOCAL_STATIC_LIBRARIES) $(LOCAL_WHOLE_LIBRARIES)),$(eval $(call add-includes,$(module))))
ifneq ($(findstring stdc++,$(LOCAL_SHARED_LIBRARIES)),)
NDK_CXX_FLAG_$(LOCAL_MODULE) := yes
endif
$(info $(foreach dir,$(NDK_INCLUDES),-I$(dir)))
$(info $(LOCAL_EXPORT_CFLAGS))
$(info $(LOCAL_EXPORT_LDFLAGS) $(abspath $(addprefix $(NDK_BUILD_DIR)/,$(NDK_A_NAMES))) $(and $(NDK_SO_NAMES), -L$(abspath $(NDK_BUILD_DIR)) $(foreach soname,$(NDK_SO_NAMES),-l:$(soname))))
$(info $(NDK_A_NAMES) $(NDK_SO_NAMES))
$(info $(NDK_CXX_FLAG_$(LOCAL_MODULE)))
$(info End)

View file

@ -0,0 +1,28 @@
# ndk-build-helper-3.mk -- Helper for ndk-build.m4.
# Copyright (C) 2023 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/>.
# Say a static library is being built
build_kind = executable
$(info Building $(build_kind))
$(info $(LOCAL_MODULE))
$(info $(addprefix $(ANDROID_MODULE_DIRECTORY),$(LOCAL_SRC_FILES) $(LOCAL_SRC_FILES$(EMACS_ABI))))
$(info $(foreach dir,$(LOCAL_EXPORT_C_INCLUDE_DIRS) $(LOCAL_EXPORT_C_INCLUDES),-I$(dir)))
$(info $(LOCAL_EXPORT_CFLAGS))
$(info $(LOCAL_EXPORT_LDFLAGS))
$(info End)

View file

@ -0,0 +1,39 @@
# Copyright (C) 2023 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/>.
undefine LOCAL_MODULE
undefine LOCAL_MODULE_FILENAME
undefine LOCAL_SRC_FILES
undefine LOCAL_CPP_EXTENSION
undefine LOCAL_CPP_FEATURES
undefine LOCAL_C_INCLUDES
undefine LOCAL_CFLAGS
undefine LOCAL_CPPFLAGS
undefine LOCAL_STATIC_LIBRARIES
undefine LOCAL_SHARED_LIBRARIES
undefine LOCAL_WHOLE_STATIC_LIBRARIES
undefine LOCAL_LDLIBS
undefine LOCAL_LDFLAGS
undefine LOCAL_ALLOW_UNDEFINED_SYMBOLS
undefine LOCAL_ARM_MODE
undefine LOCAL_ARM_NEON
undefine LOCAL_DISABLE_FORMAT_STRING_CHECKS
undefine LOCAL_EXPORT_CFLAGS
undefine LOCAL_EXPORT_CPPFLAGS
undefine LOCAL_EXPORT_C_INCLUDES
undefine LOCAL_EXPORT_C_INCLUDE_DIRS
undefine LOCAL_EXPORT_LDFLAGS
undefine LOCAL_EXPORT_LDLIBS

View file

@ -0,0 +1,81 @@
# ndk-build-helper.mk -- Helper for ndk-build.m4.
# Copyright (C) 2023 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/>.
# This Makefile sets up enough to parse an Android-style Android.mk
# file and return useful information about its contents.
# See the text under ``NDK BUILD SYSTEM IMPLEMENTATION'' in
# cross/ndk-build/README for more details.
# TARGET_ARCH_ABI is the ABI that is being built for.
TARGET_ARCH_ABI := $(EMACS_ABI)
# TARGET_ARCH is the architecture that is being built for.
TARGET_ARCH := $(NDK_BUILD_ARCH)
# NDK_LAST_MAKEFILE is the last Makefile that was included.
NDK_LAST_MAKEFILE = $(lastword $(filter %Android.mk,$(MAKEFILE_LIST)))
# local-makefile is the current Makefile being loaded.
local-makefile = $(NDK_LAST_MAKEFILE)
# Make NDK_BUILD_DIR absolute.
NDK_BUILD_DIR := $(absname $(NDK_BUILD_DIR))
# Make EMACS_SRCDIR absolute. This must be absolute, or nested
# Android.mk files will not be able to find CLEAR_VARS.
EMACS_SRCDIR := $(absname $(EMACS_SRCDIR))
# my-dir is a function that returns the Android module directory. If
# no Android.mk has been loaded, use ANDROID_MODULE_DIRECTORY.
my-dir = $(or $(and $(local-makefile),$(dir $(local-makefile))),$(ANDROID_MODULE_DIRECTORY))
# Return all Android.mk files under the first arg.
all-makefiles-under = $(wildcard $(1)/*/Android.mk)
# Return all Android.mk files in subdirectories of this Makefile's
# location.
all-subdir-makefiles = $(call all-makefiles-under,$(call my-dir))
# These functions are not implemented.
parent-makefile =
grand-parent-makefile =
NDK_IMPORTS :=
# Add the specified module (arg 1) to NDK_IMPORTS.
import-module = $(eval NDK_IMPORTS += $(1))
# Print out module information every time BUILD_SHARED_LIBRARY is
# called.
BUILD_SHARED_LIBRARY=$(BUILD_AUXDIR)ndk-build-helper-1.mk
BUILD_STATIC_LIBRARY=$(BUILD_AUXDIR)ndk-build-helper-2.mk
BUILD_EXECUTABLE=$(BUILD_AUXDIR)ndk-build-helper-3.mk
CLEAR_VARS=$(BUILD_AUXDIR)ndk-build-helper-4.mk
# Now include Android.mk.
include $(ANDROID_MAKEFILE)
# Finally, print out the imports.
$(info Start Imports)
$(info $(NDK_IMPORTS))
$(info End Imports)
# Dummy target.
all:

View file

@ -0,0 +1,88 @@
/^Building.+$/ {
kind = $2
}
/^Start Imports$/ {
imports = 1
}
// {
if (imports && ++imports > 2)
{
if (!match ($0, /^End Imports$/))
makefile_imports = makefile_imports " " $0
}
else if (!match ($0, /^End$/) && !match ($0, /^Building.+$/))
{
if (kind)
{
if (target_found)
cxx_deps = $0
else if (ldflags_found)
{
target = $0
target_found = 1
}
else if (cflags_found)
{
ldflags = $0
ldflags_found = 1
}
else if (includes_found)
{
cflags = $0
cflags_found = 1
}
else if (src_found)
{
includes = $0
includes_found = 1
}
else if (name_found)
{
src = $0
src_found = 1;
}
else
{
name = $0
name_found = 1
}
}
}
}
/^End$/ {
if (name == MODULE && (kind == "shared" || kind == "static"))
{
printf "module_name=%s\n", name
printf "module_kind=%s\n", kind
printf "module_src=\"%s\"\n", src
printf "module_includes=\"%s\"\n", includes
printf "module_cflags=\"%s\"\n", cflags
printf "module_ldflags=\"%s\"\n", ldflags
printf "module_target=\"%s\"\n", target
printf "module_cxx_deps=\"%s\"\n", cxx_deps
}
src = ""
name = ""
kind = ""
includes = ""
cflags = ""
ldflags = ""
name_found = ""
src_found = ""
includes_found = ""
cflags_found = ""
ldflags_found = ""
target_found = ""
}
/^End Imports$/ {
imports = ""
# Strip off leading whitespace.
gsub (/^[ \t]+/, "", makefile_imports)
printf "module_imports=\"%s\"\n", makefile_imports
makefile_imports = ""
}

File diff suppressed because it is too large Load diff

190
cross/Makefile.in Normal file
View file

@ -0,0 +1,190 @@
### @configure_input@
# Copyright (C) 2023 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/>.
top_srcdir = @top_srcdir@
srcdir = @srcdir@
top_builddir = @top_builddir@
builddir = @builddir@
-include $(top_builddir)/src/verbose.mk
# Cross-compiling Emacs for Android.
# The cross compiled binaries are built by having ``variant''
# Makefiles generated at configure-time. First,
# $(top_builddir)/src/Makefile.android,
# $(top_builddir)/lib/Makefile.android,
# $(top_builddir)/lib/gnulib.mk.android and
# $(top_builddir)/lib-src/Makefile.android are copied to their usual
# locations in this directory.
# N.B. that LIB_SRCDIR is actually relative to builddir, because that
# is where the gnulib files get linked.
LIB_SRCDIR = $(realpath $(builddir)/lib)
LIB_TOP_SRCDIR = $(realpath $(top_srcdir))
SRC_SRCDIR = $(realpath $(top_srcdir)/src)
SRC_TOP_SRCDIR = $(realpath $(top_srcdir))
LIB_SRC_SRCDIR = $(realpath $(top_srcdir)/lib-src)
LIB_SRC_TOP_SRCDIR = $(realpath $(top_src))
# This is a list of binaries to build and install in lib-src.
LIBSRC_BINARIES = lib-src/etags lib-src/ctags lib-src/emacsclient \
lib-src/ebrowse lib-src/hexl lib-src/movemail
CLEAN_SUBDIRS=src lib-src lib
.PHONY: all
all: lib/libgnu.a src/libemacs.so src/android-emacs $(LIBSRC_BINARIES)
# This Makefile relies on builddir and top_builddir being relative
# paths in *.android.
# This file is used to tell lib/gnulib.mk when
# $(top_builddir)/config.status changes.
config.status: $(top_builddir)/config.status
$(AM_V_GEN) touch config.status
src/verbose.mk: $(srcdir)/verbose.mk.android
$(AM_V_SILENT) cp -f $(srcdir)/verbose.mk.android \
src/verbose.mk
# Gnulib, make-fingerprint and make-docfile must be built before
# entering any of the rules below, or they will get the Android
# versions of many headers.
.PHONY: $(top_builddir)/lib/libgnu.a
$(top_builddir)/lib/libgnu.a:
$(MAKE) -C $(top_builddir)/lib libgnu.a
.PHONY: $(top_builddir)/lib-src/make-fingerprint
$(top_builddir)/lib-src/make-fingerprint: $(top_builddir)/lib/libgnu.a
$(MAKE) -C $(top_builddir)/lib-src make-fingerprint
.PHONY: $(top_builddir)/lib-src/make-docfile
$(top_builddir)/lib-src/make-docfile: $(top_builddir)/lib/libgnu.a
$(MAKE) -C $(top_builddir)/lib-src make-docfile
PRE_BUILD_DEPS=$(top_builddir)/lib/libgnu.a \
$(top_builddir)/lib-src/make-fingerprint \
$(top_builddir)/lib-src/make-docfile
lib/config.h: $(top_builddir)/src/config.h.android
$(AM_V_GEN) cp -f -p $(top_builddir)/src/config.h.android \
lib/config.h
lib-src/config.h: $(top_builddir)/src/config.h.android
$(AM_V_GEN) cp -f -p $(top_builddir)/src/config.h.android \
lib-src/config.h
# Figure out where build-aux is.
# Then, replace the build-aux directory with its actual location,
# in case MKDIR_P points there.
relative_buildaux_dir := $(subst /,\/,$(top_srcdir)/build-aux)
lib/gnulib.mk: $(top_builddir)/lib/gnulib.mk.android
$(AM_V_GEN) \
sed -e 's/^srcdir =.*$$/srcdir = $(subst /,\/,$(LIB_SRCDIR))/g' \
-e 's/$(relative_buildaux_dir)/$(subst /,\/,../$(top_builddir))\/build-aux/g' \
< $(top_builddir)/lib/gnulib.mk.android > $@
lib/Makefile: $(top_builddir)/lib/Makefile.android
$(AM_V_GEN) \
sed -e 's/^top_srcdir =.*$$/top_srcdir = $(subst /,\/,$(LIB_TOP_SRCDIR))/g' \
-e 's/^srcdir =.*$$/srcdir = $(subst /,\/,$(LIB_SRCDIR))/g' \
-e 's/^VPATH =.*$$/VPATH = $(subst /,\/,$(LIB_SRCDIR))/g' \
< $(top_builddir)/lib/Makefile.android > $@
# What is needed to build gnulib.
LIB_DEPS = lib/config.h lib/gnulib.mk lib/Makefile
.PHONY: lib/libgnu.a
lib/libgnu.a: src/verbose.mk config.status $(LIB_DEPS) $(PRE_BUILD_DEPS)
$(MAKE) -C lib libgnu.a
# Edit srcdir and top_srcdir to the right locations.
# Edit references to ../admin/unidata to read ../../admin/unidata.
# Next, edit libsrc to the location at top_srcdir! It is important
# that src/Makefile uses the binaries there, instead of any
# cross-compiled binaries at ./lib-src.
# Edit out anything saying -I($(top_srcdir)/lib) into
# -I$../(srcdir)/lib; that should be covered by -I$(lib)
src/Makefile: $(top_builddir)/src/Makefile.android
$(AM_V_GEN) \
sed -e 's/^srcdir =.*$$/srcdir = $(subst /,\/,$(SRC_SRCDIR))/g' \
-e 's/^top_srcdir =.*$$/top_srcdir = $(subst /,\/,$(LIB_TOP_SRCDIR))/g' \
-e 's/\.\.\/admin\/unidata/..\/..\/admin\/unidata/g' \
-e 's/\.\.\/admin\/charsets/..\/..\/admin\/charsets/g' \
-e 's/^libsrc =.*$$/libsrc = \.\.\/\.\.\/lib-src/g' \
-e 's/libsrc =.*$$/libsrc = \.\.\/\.\.\/lib-src/g' \
-e 's/-I\$$(top_srcdir)\/lib/-I..\/$(subst /,\/,$(srcdir))\/lib/g' \
< $(top_builddir)/src/Makefile.android > $@
src/config.h: $(top_builddir)/src/config.h.android
$(AM_V_GEN) cp -f -p $< $@
.PHONY: src/android-emacs src/libemacs.so
src/libemacs.so: src/Makefile src/config.h src/verbose.mk \
lib/libgnu.a $(PRE_BUILD_DEPS)
$(MAKE) -C src libemacs.so
src/android-emacs: src/Makefile src/config.h lib/libgnu.a \
$(PRE_BUILD_DEPS)
$(MAKE) -C src android-emacs
# Edit out SCRIPTS, it interferes with the build.
# Make BASE_CFLAGS also include cross/lib as well as ../lib.
lib-src/Makefile: $(top_builddir)/lib-src/Makefile.android
$(AM_V_GEN) \
sed -e 's/-I\$${srcdir}\/\.\.\/lib//g' \
-e 's/^srcdir=.*$$/srcdir = $(subst /,\/,$(LIB_SRC_SRCDIR))/g' \
-e 's/^top_srcdir=.*$$/top_srcdir = $(subst /,\/,$(LIB_SRC_TOP_SRCDIR))/g' \
-e 's/^SCRIPTS=.*$$/SCRIPTS=/g' \
-e 's/-I\.\.\/lib/-I..\/lib -I..\/$(subst /,\/,$(srcdir))\/lib/g' \
< $(top_builddir)/lib-src/Makefile.android > $@
.PHONY: $(LIBSRC_BINARIES)
$(LIBSRC_BINARIES) &: src/verbose.mk $(top_builddir)/$@ lib/libgnu.a \
lib-src/config.h lib-src/Makefile $(PRE_BUILD_DEPS)
# Finally, go into lib-src and make everything being built
$(MAKE) -C lib-src $(foreach bin,$(LIBSRC_BINARIES),$(notdir $(bin)))
.PHONY: clean maintainer-clean distclean
clean:
for dir in $(CLEAN_SUBDIRS); do \
find $$dir -type f -delete; \
done
rm -rf lib/config.h lib-src/config.h
# ndk-build won't have been generated in a non-Android build.
-make -C ndk-build clean
maintainer-clean distclean bootstrap-clean: clean
# Remove links created by configure.
for dir in $(CLEAN_SUBDIRS); do \
find $$dir -type l -delete; \
done
rm -rf lib/Makefile lib/gnulib.mk ndk-build/Makefile
rm -rf ndk-build/ndk-build.mk Makefile

5
cross/README Normal file
View file

@ -0,0 +1,5 @@
This directory holds Makefiles and other required assets to build an
Emacs binary independently for another toolchain.
The directory ndk-build also contains an implementation of the Android
`ndk-build' build system.

20
cross/langinfo.h Normal file
View file

@ -0,0 +1,20 @@
/* Replacement langinfo.h file for building GNU Emacs on Android.
Copyright (C) 2023 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/>. */
#define nl_langinfo(ignore) "ASCII"

144
cross/ndk-build/Makefile.in Normal file
View file

@ -0,0 +1,144 @@
### @configure_input@
# Copyright 2023 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/>.
# ndk-build works by including a bunch of Makefiles which set
# variables, and then having those Makefiles include another makefile
# which actually builds targets.
srcdir = @srcdir@
# This is a list of Android.mk files which provide targets.
NDK_BUILD_ANDROID_MK = @NDK_BUILD_ANDROID_MK@
NDK_BUILD_ARCH = @NDK_BUILD_ARCH@
NDK_BUILD_ABI = @NDK_BUILD_ABI@
NDK_BUILD_SDK = @NDK_BUILD_SDK@
NDK_BUILD_CC = @NDK_BUILD_CC@
NDK_BUILD_CXX = @NDK_BUILD_CXX@
NDK_BUILD_AR = @NDK_BUILD_AR@
NDK_BUILD_NASM = @NDK_BUILD_NASM@
NDK_BUILD_CFLAGS = @NDK_BUILD_CFLAGS@
# This is a list of targets to build.
NDK_BUILD_MODULES = @NDK_BUILD_MODULES@
# This is set by the Android in tree build system and is used by some
# libraries to look for the NDK. Its value is unimportant.
NDK_ROOT = /tmp/
# Finally, here are rules common to Emacs.
.PHONY: all
all: $(NDK_BUILD_MODULES)
define uniqify
$(if $1,$(firstword $1) $(call uniqify,$(filter-out $(firstword $1),$1)))
endef
# Remove duplicate files.
NDK_BUILD_ANDROID_MK := $(call uniqify,$(NDK_BUILD_ANDROID_MK))
# Remove duplicate modules as well. These can occur when a single
# module imports a module and also declares it in
# LOCAL_SHARED_LIBRARIES.
NDK_BUILD_MODULES := $(call uniqify,$(NDK_BUILD_MODULES))
# Define CFLAGS for compiling C++ code; this involves removing all
# -std=NNN options.
NDK_BUILD_CFLAGS_CXX := $(filter-out -std=%,$(NDK_BUILD_CFLAGS))
define subr-1
# Define ndk-build functions. Many of these are identical to those in
# build-aux/ndk-build-helper.mk.
# NDK_LAST_MAKEFILE is the last Makefile that was included.
NDK_LAST_MAKEFILE = $$(lastword $$(filter %Android.mk,$$(MAKEFILE_LIST)))
# local-makefile is the current Makefile being loaded.
local-makefile = $$(NDK_LAST_MAKEFILE)
# my-dir is a function that returns the Android module directory. If
# no Android.mk has been loaded, use the directory of the Makefile
# being included.
my-dir = $$(or $$(and $$(local-makefile),$$(dir $$(local-makefile))),$(dir $(1)))
# Return all Android.mk files under the first arg.
all-makefiles-under = $$(wildcard $$(1)/*/Android.mk)
# Return all Android.mk files in subdirectories of this Makefile's
# location.
all-subdir-makefiles = $$(call all-makefiles-under,$$(call my-dir))
# NDK-defined include variables.
CLEAR_VARS = $(srcdir)/ndk-clear-vars.mk
BUILD_EXECUTABLE = $(srcdir)/ndk-build-executable.mk
BUILD_SHARED_LIBRARY = $(srcdir)/ndk-build-shared-library.mk
BUILD_STATIC_LIBRARY = $(srcdir)/ndk-build-static-library.mk
PREBUILT_SHARED_LIBRARY = $(srcdir)/ndk-prebuilt-shared-library.mk
PREBUILT_STATIC_LIBRARY = $(srcdir)/ndk-prebuilt-static-library.mk
# Target information variables.
TARGET_ARCH = $(NDK_BUILD_ARCH)
TARGET_PLATFORM = android-$(NDK_BUILD_SDK)
TARGET_ARCH_ABI = $(NDK_BUILD_ABI)
TARGET_ABI = $(TARGET_PLATFORM)-$(TARGET_ABI)
# Module description variables. These are defined by Android.mk.
LOCAL_PATH :=
LOCAL_MODULE :=
LOCAL_MODULE_FILENAME :=
LOCAL_SRC_FILES :=
LOCAL_CPP_EXTENSION :=
LOCAL_CPP_FEATURES :=
LOCAL_C_INCLUDES :=
LOCAL_CFLAGS :=
LOCAL_CPPFLAGS :=
LOCAL_STATIC_LIBRARIES :=
LOCAL_SHARED_LIBRARIES :=
LOCAL_WHOLE_STATIC_LIBRARIES :=
LOCAL_LDLIBS :=
LOCAL_LDFLAGS :=
LOCAL_ALLOW_UNDEFINED_SYMBOLS :=
LOCAL_ARM_MODE :=
LOCAL_ARM_NEON :=
LOCAL_DISABLE_FORMAT_STRING_CHECKS :=
LOCAL_EXPORT_CFLAGS :=
LOCAL_EXPORT_CPPFLAGS :=
LOCAL_EXPORT_C_INCLUDES :=
LOCAL_EXPORT_LDFLAGS :=
LOCAL_EXPORT_LDLIBS :=
LOCAL_ASM_RULE_DEFINED :=
LOCAL_ASM_RULE :=
# Now load Android.mk.
include $(1)
endef
# Now define rules for each Android.mk file.
$(foreach android_mk,$(NDK_BUILD_ANDROID_MK),$(eval $(call subr-1,$(android_mk))))
.PHONY: clean mostlyclean
clean mostlyclean:
rm -rf *.o *.so *.a
.PHONY: extraclean dist-clean maintainer-clean
extraclean dist-clean maintainer-clean:
rm -rf Makefile

353
cross/ndk-build/README Normal file
View file

@ -0,0 +1,353 @@
NDK BUILD SYSTEM IMPLEMENTATION
Copyright (C) 2023 Free Software Foundation, Inc.
See the end of the file for license conditions.
Emacs implements ndk-build itself, because the version that comes with
the Android NDK is not easy to use from another Makefile, and keeps
accumulating incompatible changes.
The Emacs implementation of ndk-build consists of one m4 file:
m4/ndk-build.m4
four Makefiles in build-aux, run during configure:
build-aux/ndk-build-helper-1.mk
build-aux/ndk-build-helper-2.mk
build-aux/ndk-build-helper-3.mk
build-aux/ndk-build-helper.mk
one awk script in build-awx, run during configure:
build-aux/ndk-module-extract.awk
seven Makefiles in cross/ndk-build,
cross/ndk-build/ndk-build-shared-library.mk
cross/ndk-build/ndk-build-static-library.mk
cross/ndk-build/ndk-build-executable.mk
cross/ndk-build/ndk-clear-vars.mk
cross/ndk-build/ndk-prebuilt-shared-library.mk
cross/ndk-build/ndk-prebuilt-static-library.mk
cross/ndk-build/ndk-resolve.mk
and finally, two more Makefiles in cross/ndk-build, generated by
configure:
cross/ndk-build/Makefile (generated from cross/ndk-build/Makefile.in)
cross/ndk-build/ndk-build.mk (generated from cross/ndk-build/ndk-build.mk.in)
m4/ndk-build.m4 is a collection of macros which are used by the
configure script to set up the ndk-build system, look for modules, add
the appropriate options to LIBS and CFLAGS, and generate the Makefiles
necessary to build the rest of Emacs.
Immediately after determining the list of directories in which to look
for ``Android.mk'' files, the version and type of Android system being
built for, configure calls:
ndk_INIT([$android_abi], [$ANDROID_SDK], [cross/ndk-build])
This expands to a sequence of shell script that enumerates all of the
Android.mk files specified in "$with_ndk_path", sets up some shell
functions used by the rest of the ndk-build code run by the configure
script, and teaches the ndk-build system that the Makefiles to be
generated are found in the directory "cross/ndk-build/Makefile".
When configure is cross-compiling for Android, the macro
EMACS_CHECK_MODULES will expand to the macro ndk_CHECK_MODULES,
instead of pkg-config.m4's PKG_CHECK_MODULES. Thus, the following
code:
EMACS_CHECK_MODULES([PNG], [libpng >= 1.0.0])
will actually expand to:
ndk_CHECK_MODULES([PNG], [libpng >= 1.0.0], [HAVE_PNG=yes],
[HAVE_PNG=no])
which in turn expands to a sequence shell script that first invokes:
make -f build-aux/ndk-build-helper.mk
for each ``Android.mk'' file found by ndk_INIT, with the following
variables given to Make:
EMACS_SRCDIR=. # the source directory (in which configure is running)
BUILD_AUXDIR=$ndk_AUX_DIR # the build-aux directory
EMACS_ABI=$ndk_ABI # this is the $android_abi given to ndk_INIT
ANDROID_MAKEFILE="/opt/android/libpng/Android.mk"
ANDROID_MODULE_DIRECTORY="/opt/android/libpng"
NDK_BUILD_DIR="$ndk_DIR" # this is the directory given as to ndk_INIT
build-aux/ndk-build-helper.mk will then evaluate the contents
$(ANDROID_MAKEFILE), the ``Android.mk'' file, for the first time. The
purpose of this evaluation is to establish a list of packages (or
modules) provided by the ``Android.mk'' file, and the corresponding
Makefile targets and compiler and linker flags required to build and
link to those tagets.
Before doing so, build-aux/ndk-build-helper.mk will define several
variables and functions required by all ``Android.mk'' files. The
most important of these are:
my-dir # the directory containing the Android.mk file.
BUILD_SHARED_LIBRARY # build-aux/ndk-build-helper-1.mk
BUILD_STATIC_LIBRARY # build-aux/ndk-build-helper-2.mk
BUILD_EXECUTABLE # build-aux/ndk-build-helper-3.mk
CLEAR_VARS # build-aux/ndk-build-helper-4.mk
Then, ``Android.mk'' will include $(CLEAN_VARS), possibly other
``Android.mk'' files, (to clear variables previously set), set several
variables describing each module to the ndk-build system, and include
one of $(BUILD_SHARED_LIBRARY), $(BUILD_STATIC_LIBRARY) and
$(BUILD_EXECUTABLE).
Each one of those three scripts will then read from the variables set
by ``Android.mk'', resolve dependencies, and print out some text
describing the module to Emacs. For example, the shared library
module "libpng" results in the following text being printed:
Building shared
libpng
/opt/android/libpng/png.c /opt/android/libpng/pngerror.c /opt/android/libpng/pngget.c /opt/android/libpng/pngmem.c /opt/android/libpng/pngpread.c /opt/android/libpng/pngread.c /opt/android/libpng/pngrio.c /opt/android/libpng/pngrtran.c /opt/android/libpng/pngrutil.c /opt/android/libpng/pngset.c /opt/android/libpng/pngtrans.c /opt/android/libpng/pngwio.c /opt/android/libpng/pngwrite.c /opt/android/libpng/pngwtran.c /opt/android/libpng/pngwutil.c
-I/opt/android/libpng
-L/opt/emacs/cross/ndk-build -l:libpng_emacs.so
libpng_emacs.so
End
The output is arranged as follows:
- The first line consists of the word ``Building'', followed by
either ``shared'', ``static'', or ``executable'', depending on
what type of module being built.
- The second line consists of the name of the module currently being
built.
- The third line consists of all of the source code files comprising
the module.
- The fourth line consists of the text that has to be added to
CFLAGS in order to find the includes associated with the module.
- The fifth line consists of the text that has to be added to LIBS
in order to link with this module and all of its dependencies.
- The sixth line consists of the Make targets (more on this later)
that will build the final shared object or library archive of this
module, along with all of its dependencies.
- The seventh line is either empty, or the name of a dependency on
the C++ standard library. This is used to determine whether or
not Emacs will include the C++ standard library in the application
package.
The output from Make is given to an awk script,
build-aux/ndk-module-extract.awk. This is responsible for parsing the
that output and filtering out modules other than what is being built:
awk -f build-aux/ndk-module-extract.awk MODULE=libpng
eventually generating this section of shell script:
module_name=libpng
module_kind=shared
module_src="/opt/android/libpng/png.c /opt/android/libpng/pngerror.c /opt/android/libpng/pngget.c /opt/android/libpng/pngmem.c /opt/android/libpng/pngpread.c /opt/android/libpng/pngread.c /opt/android/libpng/pngrio.c /opt/android/libpng/pngrtran.c /opt/android/libpng/pngrutil.c /opt/android/libpng/pngset.c /opt/android/libpng/pngtrans.c /opt/android/libpng/pngwio.c /opt/android/libpng/pngwrite.c /opt/android/libpng/pngwtran.c /opt/android/libpng/pngwutil.c"
module_includes="-I/opt/android/libpng"
module_cflags=""
module_ldflags=" -L/opt/emacs/cross/ndk-build -l:libpng_emacs.so"
module_target="libpng_emacs.so"
module_cxx_deps=""
module_imports=""
which is then evaluated by `configure'. Once the variable
`module_name' is set, configure apends the remaining
$(module_includes), $(module_cflags) and $(module_ldflags) to the
module's CFLAGS and LIBS variables, and appends the list of Makefile
targets specified to the variable NDK_BUILD_MODULES.
In some cases, an ``Android.mk'' file may chose to import a module
defined in ``--with-ndk-path'', but not defined inside its own
``Android.mk'' file. build-aux/ndk-build-helper.mk defines the
`import-module' function to add the modules being imported to a
variable, which is then printed out after ``ndk-build-helper.mk''
completes. For example, libxml2 imports the ``libicucc'' module,
which results in the following text being printed:
Building shared
libxml2
/home/oldosfan/libxml2/SAX.c /home/oldosfan/libxml2/entities.c /home/oldosfan/libxml2/encoding.c /home/oldosfan/libxml2/error.c /home/oldosfan/libxml2/parserInternals.c /home/oldosfan/libxml2/parser.c /home/oldosfan/libxml2/tree.c /home/oldosfan/libxml2/hash.c /home/oldosfan/libxml2/list.c /home/oldosfan/libxml2/xmlIO.c /home/oldosfan/libxml2/xmlmemory.c /home/oldosfan/libxml2/uri.c /home/oldosfan/libxml2/valid.c /home/oldosfan/libxml2/xlink.c /home/oldosfan/libxml2/debugXML.c /home/oldosfan/libxml2/xpath.c /home/oldosfan/libxml2/xpointer.c /home/oldosfan/libxml2/xinclude.c /home/oldosfan/libxml2/DOCBparser.c /home/oldosfan/libxml2/catalog.c /home/oldosfan/libxml2/globals.c /home/oldosfan/libxml2/threads.c /home/oldosfan/libxml2/c14n.c /home/oldosfan/libxml2/xmlstring.c /home/oldosfan/libxml2/buf.c /home/oldosfan/libxml2/xmlregexp.c /home/oldosfan/libxml2/xmlschemas.c /home/oldosfan/libxml2/xmlschemastypes.c /home/oldosfan/libxml2/xmlunicode.c /home/oldosfan/libxml2/xmlreader.c /home/oldosfan/libxml2/relaxng.c /home/oldosfan/libxml2/dict.c /home/oldosfan/libxml2/SAX2.c /home/oldosfan/libxml2/xmlwriter.c /home/oldosfan/libxml2/legacy.c /home/oldosfan/libxml2/chvalid.c /home/oldosfan/libxml2/pattern.c /home/oldosfan/libxml2/xmlsave.c /home/oldosfan/libxml2/xmlmodule.c /home/oldosfan/libxml2/schematron.c /home/oldosfan/libxml2/SAX.c /home/oldosfan/libxml2/entities.c /home/oldosfan/libxml2/encoding.c /home/oldosfan/libxml2/error.c /home/oldosfan/libxml2/parserInternals.c /home/oldosfan/libxml2/parser.c /home/oldosfan/libxml2/tree.c /home/oldosfan/libxml2/hash.c /home/oldosfan/libxml2/list.c /home/oldosfan/libxml2/xmlIO.c /home/oldosfan/libxml2/xmlmemory.c /home/oldosfan/libxml2/uri.c /home/oldosfan/libxml2/valid.c /home/oldosfan/libxml2/xlink.c /home/oldosfan/libxml2/debugXML.c /home/oldosfan/libxml2/xpath.c /home/oldosfan/libxml2/xpointer.c /home/oldosfan/libxml2/xinclude.c /home/oldosfan/libxml2/DOCBparser.c /home/oldosfan/libxml2/catalog.c /home/oldosfan/libxml2/globals.c /home/oldosfan/libxml2/threads.c /home/oldosfan/libxml2/c14n.c /home/oldosfan/libxml2/xmlstring.c /home/oldosfan/libxml2/buf.c /home/oldosfan/libxml2/xmlregexp.c /home/oldosfan/libxml2/xmlschemas.c /home/oldosfan/libxml2/xmlschemastypes.c /home/oldosfan/libxml2/xmlunicode.c /home/oldosfan/libxml2/xmlreader.c /home/oldosfan/libxml2/relaxng.c /home/oldosfan/libxml2/dict.c /home/oldosfan/libxml2/SAX2.c /home/oldosfan/libxml2/xmlwriter.c /home/oldosfan/libxml2/legacy.c /home/oldosfan/libxml2/chvalid.c /home/oldosfan/libxml2/pattern.c /home/oldosfan/libxml2/xmlsave.c /home/oldosfan/libxml2/xmlmodule.c /home/oldosfan/libxml2/schematron.c
-L/home/oldosfan/emacs-dev/emacs-android/cross/ndk-build -l:libxml2_emacs.so -l:libicuuc_emacs.so
libxml2_emacs.so libicuuc_emacs.so
End
Start Imports
libicuuc
End Imports
Upon encountering the ``Start Imports'' section,
build-aux/ndk-module-extract.awk collects all imports until it
encounters the line ``End Imports'', at which point it prints:
module_imports="libicuuc"
Then, if the list of imports is not empty, ndk_CHECK_MODULES
additionally calls itself for each import before appending the
module's own ``Android.mk'', ensuring that the module's imported
dependencies are included by $ndk_DIR/Makefile before itself.
Finally, immediately before generating src/Makefile.android, configure
expands:
ndk_CONFIG_FILES
to generate $ndk_DIR/Makefile and $ndk_DIR/ndk-build.mk.
Now, the $ndk_DIR directory is set up to build all modules upon which
depends, and $ndk_DIR/ndk-build.mk includes a list of files required
to link Emacs, along with the rules to chdir into $ndk_DIR in order to
build them.
$ndk_DIR/ndk-build.mk is included by cross/src/Makefile
(Makefile.android) and java/Makefile. It defines three different
variables:
NDK_BUILD_MODULES the file names of all modules to be built.
NDK_BUILD_STATIC absolute names of all library archives
to be built.
NDK_BUILD_SHARED absolute names of all shared libraries to
be built.
and then proceeds to define rules to build each of the modules in
$(NDK_BUILD_MODULES).
cross/src/Makefile arranges to have all dependencies of Emacs not
already built built before linking ``libemacs.so'' with them.
java/Makefile additionally arranges to have all shared object
dependencies built before the application package is built, which is
normally redundant because they should have already been built before
linking ``libemacs.so''.
Building the modules is performed through $ndk_DIR/Makefile, which
contains the actual implementation of the ``ndk-build'' build system.
First, it defines certain variables constant within the ``ndk-build''
build system, such as the files included by ``Android.mk'' to build
shared or static libraries, and CLEAR_VARS. The most important of
these are:
CLEAR_VARS cross/ndk-build/ndk-clear-vars.mk
BUILD_EXECUTABLE cross/ndk-build/ndk-build-executable.mk
BUILD_SHARED_LIBRARY cross/ndk-build/ndk-build-shared-library.mk
BUILD_STATIC_LIBRARY cross/ndk-build/ndk-build-static-library.mk
PREBUILT_SHARED_LIBRARY cross/ndk-build/ndk-prebuilt-shared-library.mk
PREBUILT_STATIC_LIBRARY cross/ndk-build/ndk-prebuilt-static-library.mk
Then, it loads each Emacs dependency's ``Android.mk'' file. For each
module defined there, ``Android.mk'' includes $(CLEAR_VARS) to unset
all variables specific to each module, and then includes
$(BUILD_SHARED_LIBRARY) or $(BUILD_STATIC_LIBRARY) for each shared or
static library module.
This results in cross/ndk-build/ndk-build-shared-library.mk or
cross/ndk-build/ndk-build-static-library being included, just like the
Makefiles in build-aux were inside the configure script.
Each one of those two scripts then defines rules to build all of the
object files associated with the module, and then link or archive
them. The name under which the module is linked is the same as the
Make target found on the sixth line of output from
build-aux/ndk-build-helper.mk.
In doing so, they both include the file ndk-resolve.mk.
ndk-resolve.mk is expected to recursively add all of the exported
CFLAGS and includes of any dependencies to the compiler and linker
command lines for the module being built.
When building a shared library module, ndk-resolve.mk is also expected
to define the variables NDK_LOCAL_A_NAMES_$(LOCAL_MODULE) and
NDK_WHOLE_A_NAMES_$(LOCAL_MODULE), containing all static library
dependencies' archive files. They are to be linked in to the
resulting shared object file.
This is done by including cross/ndk-build/ndk-resolve.mk each time a
shared or static library module is going to be built. How is this
done?
First, ndk-resolve.mk saves the LOCAL_PATH, LOCAL_STATIC_LIBRARIES,
LOCAL_SHARED_LIBRARIES, LOCAL_EXPORT_CFLAGS and
LOCAL_EXPORT_C_INCLUDES from the module.
Next, ndk-resolve loops through the dependencies the module has
specified, appending its CFLAGS and includes to the command line for
the current module.
Then, that process is repeated for each such dependency which has not
already been resolved, until all dependencies have been resolved.
libpng is a very simple module, providing only a single shared object
module. This module is named libpng_emacs.so and is eventually built
and packaged into the library directory of the Emacs application
package. Now, let us look at a more complex module, libwebp:
When built with libwebp, Emacs depends on a single library,
libwebpdemux. This library is named ``libwebpdemux'' on Unix systems,
and that is the name by which it is found with pkg-config.
However, the library's module is only named ``webpdemux'' on Android.
When ndk_CHECK_MODULES begins to look for a module, it first tries to
see if its name is found in the variable `ndk_package_map', which was
set inside ndk_INIT. In this case, it finds the following word:
libwebpdemux:webpdemux
and immediately replaces ``libwebpdemux'' with ``webpdemux''.
Then, it locates the ``Android.mk'' file containing a static library
module named webpdemux and gives the output from
build-aux/ndk-build-helper.mk to the awk script, resulting in:
module_name=webpdemux
module_kind=static
module_src="/opt/android/webp/src/demux/anim_decode.c /opt/android/webp/src/demux/demux.c"
module_includes="-I/opt/android/webp/src"
module_cflags=""
module_ldflags=" cross/ndk-build/libwebpdemux.a cross/ndk-build/libwebp.a cross/ndk-build/libwebpdecoder_static.a "
module_target="libwebpdemux.a libwebp.a libwebpdecoder_static.a"
The attentive reader will notice that in addition to the
``libwebpdemux.a'' archive associated with the ``webpdemux'' library,
Emacs has been made to link with two additional libraries. This is
because the ``webpdemux'' module specifies a dependency on the
``webp'' module (defined in the same Android.mk).
build-aux/ndk-build-helper.mk resolved that dependency, noticing that
it in turn specified another dependency on ``webpdecoder_static'',
which in turn was added to the linker command line and list of targets
to build.
As a result, all three dependencies will be built and linked to Emacs,
instead of just the single ``webpdemux'' dependency that was
specified.
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/>.

View file

@ -0,0 +1,22 @@
# Copyright 2023 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/>.
# ndk-build works by including a bunch of Makefiles which set
# variables, and then having those Makefiles include another makefile
# which actually builds targets.
# Building executables is not supported

View file

@ -0,0 +1,171 @@
# Copyright 2023 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/>.
# ndk-build works by including a bunch of Makefiles which set
# variables, and then having those Makefiles include another makefile
# which actually builds targets.
eq = $(and $(findstring $(1),$(2)),$(findstring $(2),$(1)))
# Objects for shared libraries are prefixed with `-shared-' in
# addition to the name of the module, because a common practice in
# Android.mk files written by Google is to define two modules with the
# same name but of different types.
objname = $(1)-shared-$(subst /,_,$(2).o)
# LOCAL_SRC_FILES sometimes contains absolute file names. Filter them
# out with this function. If $(2), this is a file relative to the
# build directory.
maybe-absolute = $(or $(and $(2),$(1)),$(and $(wildcard $(1)),$(1)),$(LOCAL_PATH)/$(1))
# Here are the default flags to link shared libraries with.
NDK_SO_DEFAULT_LDFLAGS := -lc -lm
define single-object-target
ifeq (x$(suffix $(1)),x.c)
$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(call maybe-absolute,$(1),$(2))
$(NDK_BUILD_CC) -c $$< -o $$@ $(NDK_CFLAGS_$(LOCAL_MODULE)) $(NDK_BUILD_CFLAGS) $(call LOCAL_C_ADDITIONAL_FLAGS,$(1))
else
ifeq (x$(suffix $(1)),x.$(or $(LOCAL_CPP_EXTENSION),cpp))
$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(call maybe-absolute,$(1))
$(NDK_BUILD_CXX) -c $$< -o $$@ $(NDK_CFLAGS_$(LOCAL_MODULE)) $(NDK_BUILD_CFLAGS_CXX) $(NDK_CXXFLAGS_$(LOCAL_MODULE))
else
ifneq ($(or $(call eq,x$(suffix $(1)),x.s),$(call eq,x$(suffix $(1)),x.S)),)
$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(call maybe-absolute,$(1),$(2))
$(NDK_BUILD_CC) -c $$< -o $$@ $(NDK_ASFLAGS_$(LOCAL_MODULE))
else
ifneq (x$(suffix $(1)),x.asm)
ifeq (x$(suffix $(1)),x.cc)
$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(call maybe-absolute,$(1),$(2))
$(NDK_BUILD_CXX) -c $$< -o $$@ $(NDK_CFLAGS_$(LOCAL_MODULE)) $(NDK_BUILD_CFLAGS_CXX) $(NDK_CXXFLAGS_$(LOCAL_MODULE))
else
$$(error Unsupported suffix: $(suffix $(1)))
endif
else
ifneq (x$(LOCAL_ASM_RULE_DEFINED),x)
# Call this function to define a rule that will generate $(1) from
# $(2), a ``.asm'' file. This is an Emacs extension.
$(call LOCAL_ASM_RULE,$(call objname,$(LOCAL_MODULE),$(basename $(1))),$(LOCAL_PATH)/$(strip $(1)))
else
ifeq ($(findstring x86,$(NDK_BUILD_ARCH)),)
$$(error Trying to build nasm file on non-Intel platform!)
else
$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(LOCAL_PATH)/$(1)
$(NDK_BUILD_NASM) -felf$(findstring 64,$(NDK_BUILD_ARCH)) -o $$@ -i $(LOCAL_PATH) -i $$(dir $$<) $(NDK_ASFLAGS_$(LOCAL_MODULE)) $$<
endif
endif
endif
endif
endif
endif
ALL_OBJECT_FILES$(LOCAL_MODULE) += $(call objname,$(LOCAL_MODULE),$(basename $(1)))
endef
define single-neon-target
# Define rules for the target.
$$(eval $$(call single-object-target,$(patsubst %.neon,%,$(1)),))
endef
# Make sure to not add a prefix to local includes that already specify
# $(LOCAL_PATH).
NDK_CFLAGS_$(LOCAL_MODULE) := $(addprefix -I,$(LOCAL_C_INCLUDES))
NDK_CFLAGS_$(LOCAL_MODULE) += -fPIC -iquote $(LOCAL_PATH) $(LOCAL_EXPORT_CFLAGS) $(LOCAL_CFLAGS) $(LOCAL_CFLAGS_$(NDK_BUILD_ARCH))
NDK_ASFLAGS_$(LOCAL_MODULE) := $(LOCAL_ASFLAGS) $(LOCAL_ASFLAGS_$(NDK_BUILD_ARCH)) $(and $(findstring clang,$(NDK_BUILD_CC)),$(LOCAL_CLANG_ASFLAGS_$(NDK_BUILD_ARCH)))
NDK_LDFLAGS_$(LOCAL_MODULE) := $(LOCAL_LDLIBS) $(LOCAL_LDFLAGS)
NDK_CXXFLAGS_$(LOCAL_MODULE) := $(LOCAL_CPPFLAGS) $(LOCAL_RTTI_FLAG)
# Now look for features in LOCAL_CPP_FEATURES and enable them.
ifneq ($(findstring exceptions,$(LOCAL_CPPFLAGS)),)
NDK_CXXFLAGS_$(LOCAL_MODULE) += -fexceptions
endif
ifneq ($(findstring rtti,$(LOCAL_CPPFLAGS)),)
NDK_CXXFLAGS_$(LOCAL_MODULE) += -frtti
endif
ALL_OBJECT_FILES$(LOCAL_MODULE) :=
ifeq ($(NDK_BUILD_ARCH)$(NDK_ARM_MODE),armarm)
NDK_CFLAGS ::= -marm
else
ifeq ($(NDK_BUILD_ARCH),arm)
NDK_CFLAGS ::= -mthumb
endif
endif
ifeq ($(findstring lib,$(LOCAL_MODULE)),lib)
LOCAL_MODULE_FILENAME := $(LOCAL_MODULE)_emacs
else
LOCAL_MODULE_FILENAME := lib$(LOCAL_MODULE)_emacs
endif
# Since a shared library is being built, suffix the library with
# _emacs. Otherwise, libraries already on the system will be found
# first, with potentially nasty consequences.
LOCAL_MODULE_FILENAME := $(LOCAL_MODULE_FILENAME).so
# Record this module's dependencies and exported includes and CFLAGS,
# and then add that of its dependencies.
include $(srcdir)/ndk-resolve.mk
# Then define rules to build all objects.
ALL_SOURCE_FILES := $(LOCAL_SRC_FILES) $(LOCAL_SRC_FILES_$(NDK_BUILD_ARCH))
# This defines all dependencies.
ALL_OBJECT_FILES$(LOCAL_MODULE) :=
# Now filter out code that is built with neon. Define rules to build
# those separately.
NEON_SOURCE_FILES := $(filter %.neon,$(ALL_SOURCE_FILES))
ALL_SOURCE_FILES := $(filter-out %.neon,$(ALL_SOURCE_FILES))
$(foreach source,$(ALL_SOURCE_FILES),$(eval $(call single-object-target,$(source),)))
$(foreach source,$(NEON_SOURCE_FILES),$(eval $(call single-neon-target,$(source))))
# Now define the rule to build the shared library. Shared libraries
# link with all of the archive files from the static libraries on
# which they depend, and also any shared libraries they depend on.
define define-module-rule
$(LOCAL_MODULE_FILENAME): $(ALL_OBJECT_FILES$(LOCAL_MODULE)) $(NDK_LOCAL_A_NAMES_$(LOCAL_MODULE)) $(NDK_WHOLE_A_NAMES_$(LOCAL_MODULE)) $(NDK_LOCAL_SO_NAMES_$(LOCAL_MODULE))
$(NDK_BUILD_CC) $(1) $(2) -o $$@ -shared $(NDK_LDFLAGS_$(LOCAL_MODULE)) $(NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE)) $(NDK_SO_DEFAULT_LDFLAGS) $(foreach so,$(NDK_LOCAL_SO_NAMES_$(LOCAL_MODULE)),-L $(abspath $(CURDIR)) -l:$(so))
endef
NDK_WHOLE_ARCHIVE_PREFIX = -Wl,--whole-archive
NDK_WHOLE_ARCHIVE_SUFFIX = -Wl,--no-whole-archive
$(eval $(call define-module-rule,$(ALL_OBJECT_FILES$(LOCAL_MODULE)) $(NDK_LOCAL_A_NAMES_$(LOCAL_MODULE)),$(and $(strip $(NDK_WHOLE_A_NAMES_$(LOCAL_MODULE))),$(NDK_WHOLE_ARCHIVE_PREFIX) $(NDK_WHOLE_A_NAMES_$(LOCAL_MODULE)) $(NDK_WHOLE_ARCHIVE_SUFFIX))))

View file

@ -0,0 +1,142 @@
# Copyright 2023 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/>.
# ndk-build works by including a bunch of Makefiles which set
# variables, and then having those Makefiles include another makefile
# which actually builds targets.
eq = $(and $(findstring $(1),$(2)),$(findstring $(2),$(1)))
objname = $(1)-static-$(subst /,_,$(2).o)
maybe-absolute = $(or $(and $(2),$(1)),$(and $(wildcard $(1)),$(1)),$(LOCAL_PATH)/$(1))
define single-object-target
ifeq (x$(suffix $(1)),x.c)
$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(call maybe-absolute,$(1),$(2))
$(NDK_BUILD_CC) -c $$< -o $$@ $(NDK_BUILD_CFLAGS) $(NDK_CFLAGS_$(LOCAL_MODULE)) $(call LOCAL_C_ADDITIONAL_FLAGS,$(1))
else
ifeq (x$(suffix $(1)),x.$(or $(LOCAL_CPP_EXTENSION),cpp))
$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(call maybe-absolute,$(1),$(2))
$(NDK_BUILD_CXX) -c $$< -o $$@ $(NDK_BUILD_CFLAGS_CXX) $(NDK_CFLAGS_$(LOCAL_MODULE)) $(NDK_CXXFLAGS_$(LOCAL_MODULE))
else
ifneq ($(or $(call eq,x$(suffix $(1)),x.s),$(call eq,x$(suffix $(1)),x.S)),)
$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(call maybe-absolute,$(1),$(2))
$(NDK_BUILD_CC) -c $$< -o $$@ $(NDK_ASFLAGS_$(LOCAL_MODULE))
else
ifneq (x$(suffix $(1)),x.asm)
ifeq (x$(suffix $(1)),x.cc)
$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(call maybe-absolute,$(1),$(2))
$(NDK_BUILD_CXX) -c $$< -o $$@ $(NDK_BUILD_CFLAGS_CXX) $(NDK_CFLAGS_$(LOCAL_MODULE)) $(NDK_CXXFLAGS_$(LOCAL_MODULE))
else
$$(error Unsupported suffix: $(suffix $(1)))
endif
else
ifneq (x$(LOCAL_ASM_RULE_DEFINED),x)
# Call this function to define a rule that will generate $(1) from
# $(2), a ``.asm'' file. This is an Emacs extension.
$(call LOCAL_ASM_RULE,$(call objname,$(LOCAL_MODULE),$(basename $(1))),$(LOCAL_PATH)/$(strip $(1)))
else
ifeq ($(findstring x86,$(NDK_BUILD_ARCH)),)
$$(error Trying to build nasm file on non-Intel platform!)
else
$(call objname,$(LOCAL_MODULE),$(basename $(1))): $(call maybe-absolute,$(1),$(2))
$(NDK_BUILD_NASM) -felf$(findstring 64,$(NDK_BUILD_ARCH)) -o $$@ -i $(LOCAL_PATH) -i $$(dir $$<) $(NDK_ASFLAGS_$(LOCAL_MODULE)) $$<
endif
endif
endif
endif
endif
endif
ALL_OBJECT_FILES$(LOCAL_MODULE) += $(call objname,$(LOCAL_MODULE),$(basename $(1)))
endef
define single-neon-target
# Define rules for the target.
$$(eval $$(call single-object-target,$(patsubst %.neon,%,$(1)),))
endef
NDK_CFLAGS_$(LOCAL_MODULE) := $(addprefix -I,$(LOCAL_C_INCLUDES))
NDK_CFLAGS_$(LOCAL_MODULE) += -fPIC -iquote $(LOCAL_PATH) $(LOCAL_EXPORT_CFLAGS) $(LOCAL_CFLAGS) $(LOCAL_CFLAGS_$(NDK_BUILD_ARCH))
NDK_ASFLAGS_$(LOCAL_MODULE) := $(LOCAL_ASFLAGS) $(LOCAL_ASFLAGS_$(NDK_BUILD_ARCH)) $(and $(findstring clang,$(NDK_BUILD_CC)),$(LOCAL_CLANG_ASFLAGS_$(NDK_BUILD_ARCH)))
NDK_LDFLAGS_$(LOCAL_MODULE) := $(LOCAL_LDLIBS) $(LOCAL_LDFLAGS)
NDK_CXXFLAGS_$(LOCAL_MODULE) := $(LOCAL_CPPFLAGS) $(LOCAL_RTTI_FLAG)
ALL_OBJECT_FILES$(LOCAL_MODULE) :=
# Now look for features in LOCAL_CPP_FEATURES and enable them.
ifneq ($(findstring exceptions,$(LOCAL_CPPFLAGS)),)
NDK_CXXFLAGS_$(LOCAL_MODULE) += -fexceptions
endif
ifneq ($(findstring rtti,$(LOCAL_CPPFLAGS)),)
NDK_CXXFLAGS_$(LOCAL_MODULE) += -frtti
endif
ifeq ($(NDK_BUILD_ARCH)$(NDK_ARM_MODE),armarm)
NDK_CFLAGS ::= -marm
else
ifeq ($(NDK_BUILD_ARCH),arm)
NDK_CFLAGS ::= -mthumb
endif
endif
ifeq ($(findstring lib,$(LOCAL_MODULE)),lib)
LOCAL_MODULE_FILENAME := $(LOCAL_MODULE)
else
LOCAL_MODULE_FILENAME := lib$(LOCAL_MODULE)
endif
LOCAL_MODULE_FILENAME := $(LOCAL_MODULE_FILENAME).a
# Record this module's dependencies and exported includes and CFLAGS,
# and then add that of its dependencies.
include $(srcdir)/ndk-resolve.mk
# Then define rules to build all objects.
ALL_SOURCE_FILES := $(LOCAL_SRC_FILES) $(LOCAL_SRC_FILES_$(NDK_BUILD_ARCH))
# Now filter out code that is built with neon. Define rules to build
# those separately.
NEON_SOURCE_FILES := $(filter %.neon,$(ALL_SOURCE_FILES))
ALL_SOURCE_FILES := $(filter-out %.neon,$(ALL_SOURCE_FILES))
# This defines all dependencies.
ALL_OBJECT_FILES$(LOCAL_MODULE) =
$(foreach source,$(ALL_SOURCE_FILES),$(eval $(call single-object-target,$(source),)))
$(foreach source,$(NEON_SOURCE_FILES),$(eval $(call single-neon-target,$(source),)))
# Now define the rule to build the library.
$(LOCAL_MODULE_FILENAME): $(ALL_OBJECT_FILES$(LOCAL_MODULE))
$(NDK_BUILD_AR) r $@ $^

View file

@ -0,0 +1,68 @@
### @configure_input@
# Copyright (C) 2023 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/>.
# This file is included all over the place to get and build
# prerequisites.
NDK_BUILD_MODULES = @NDK_BUILD_MODULES@
NDK_BUILD_CXX_SHARED = @NDK_BUILD_CXX_SHARED@
NDK_BUILD_ANY_CXX_MODULE = @NDK_BUILD_ANY_CXX_MODULE@
NDK_BUILD_SHARED =
NDK_BUILD_STATIC =
define uniqify
$(if $1,$(firstword $1) $(call uniqify,$(filter-out $(firstword $1),$1)))
endef
# Remove duplicate modules. These can occur when a single module
# imports a module and also declares it in LOCAL_SHARED_LIBRARIES.
NDK_BUILD_MODULES := $(call uniqify,$(NDK_BUILD_MODULES))
# Here are all of the files to build.
NDK_BUILD_ALL_FILES := $(foreach file,$(NDK_BUILD_MODULES), \
$(top_builddir)/cross/ndk-build/$(file))
# The C++ standard library must be extracted from the Android NDK
# directories and included in the application package, if any module
# requires the C++ standard library.
ifneq ($(NDK_BUILD_ANY_CXX_MODULE),)
NDK_BUILD_SHARED += $(NDK_BUILD_CXX_SHARED)
endif
define subr-1
ifeq ($(suffix $(1)),.so)
NDK_BUILD_SHARED += $(top_builddir)/cross/ndk-build/$(1)
else
ifeq ($(suffix $(1)),.a)
NDK_BUILD_STATIC += $(top_builddir)/cross/ndk-build/$(1)
endif
endif
endef
# Generate rules for each module.
$(foreach module,$(NDK_BUILD_MODULES),$(eval $(call subr-1,$(module))))
# Generate rules to build everything now.
# Make sure to use the top_builddir currently defined.
NDK_TOP_BUILDDIR := $(top_builddir)
$(NDK_BUILD_ALL_FILES) &:
$(MAKE) -C $(NDK_TOP_BUILDDIR)/cross/ndk-build $(NDK_BUILD_MODULES)

View file

@ -0,0 +1,57 @@
# Copyright 2023 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/>.
# ndk-build works by including a bunch of Makefiles which set
# variables, and then having those Makefiles include another makefile
# which actually builds targets.
LOCAL_MODULE :=
LOCAL_MODULE_FILENAME :=
LOCAL_SRC_FILES :=
LOCAL_CPP_EXTENSION :=
LOCAL_CPP_FEATURES :=
LOCAL_C_INCLUDES :=
LOCAL_CFLAGS :=
LOCAL_CPPFLAGS :=
LOCAL_STATIC_LIBRARIES :=
LOCAL_SHARED_LIBRARIES :=
LOCAL_WHOLE_STATIC_LIBRARIES :=
LOCAL_LDLIBS :=
LOCAL_LDFLAGS :=
LOCAL_ALLOW_UNDEFINED_SYMBOLS :=
LOCAL_ARM_MODE :=
LOCAL_ARM_NEON :=
LOCAL_DISABLE_FORMAT_STRING_CHECKS :=
LOCAL_EXPORT_CFLAGS :=
LOCAL_EXPORT_CPPFLAGS :=
LOCAL_EXPORT_C_INCLUDES :=
LOCAL_EXPORT_C_INCLUDE_DIRS :=
LOCAL_EXPORT_LDFLAGS :=
LOCAL_EXPORT_LDLIBS :=
# AOSP extensions.
LOCAL_SRC_FILES_$(NDK_BUILD_ARCH) :=
LOCAL_ASFLAGS_$(NDK_BUILD_ARCH) :=
LOCAL_CFLAGS_$(NDK_BUILD_ARCH) :=
LOCAL_ADDITIONAL_DEPENDENCIES :=
LOCAL_CLANG_ASFLAGS_$(NDK_BUILD_ARCH) :=
LOCAL_IS_HOST_MODULE :=
# Emacs extensions!
LOCAL_ASM_RULE_DEFINED :=
LOCAL_ASM_RULE :=
LOCAL_C_ADDITIONAL_FLAGS :=

View file

@ -0,0 +1,24 @@
### @configure_input@
# Copyright 2023 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/>.
# ndk-build works by including a bunch of Makefiles which set
# variables, and then having those Makefiles include another makefile
# which actually builds targets.
$(warn Prebuilt shared libraries are not supported)

View file

@ -0,0 +1,24 @@
### @configure_input@
# Copyright 2023 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/>.
# ndk-build works by including a bunch of Makefiles which set
# variables, and then having those Makefiles include another makefile
# which actually builds targets.
$(warn Prebuilt static libraries are not supported)

View file

@ -0,0 +1,162 @@
# Copyright 2023 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/>.
# ndk-build works by including a bunch of Makefiles which set
# variables, and then having those Makefiles include another makefile
# which actually builds targets.
# List of system libraries to ignore.
NDK_SYSTEM_LIBRARIES = z libz libc c libdl dl stdc++ libstdc++ log liblog android libandroid
# Save information.
NDK_LOCAL_PATH_$(LOCAL_MODULE) := $(LOCAL_PATH)
NDK_LOCAL_STATIC_LIBRARIES_$(LOCAL_MODULE) := $(LOCAL_STATIC_LIBRARIES) $(LOCAL_WHOLE_STATIC_LIBRARIES)
NDK_LOCAL_WHOLE_LIBRARIES_$(LOCAL_MODULE) := $(LOCAL_WHOLE_STATIC_LIBRARIES)
NDK_LOCAL_SHARED_LIBRARIES_$(LOCAL_MODULE) := $(LOCAL_SHARED_LIBRARIES)
NDK_LOCAL_EXPORT_CFLAGS_$(LOCAL_MODULE) := $(LOCAL_EXPORT_CFLAGS)
NDK_LOCAL_EXPORT_C_INCLUDES_$(LOCAL_MODULE) := $(LOCAL_EXPORT_C_INCLUDES) $(LOCAL_EXPORT_C_INCLUDE_DIRS)
NDK_LOCAL_A_NAMES_$(LOCAL_MODULE) :=
NDK_WHOLE_A_NAMES_$(LOCAL_MODULE) :=
NDK_LOCAL_SO_NAMES_$(LOCAL_MODULE) :=
NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) :=
# List of all dependencies resolved for this module thus far.
# Used to avoid infinite recursion.
# Separate the variable which lists modules for which CFLAGS
# have been resolved from the variable which lists modules
# for which library dependencies have been resolved, in order
# to catch the case where a library dependency is skipped
# despite its CFLAGS being added.
NDK_RESOLVED_$(LOCAL_MODULE) :=
NDK_RESOLVED_CFLAGS_$(LOCAL_MODULE) :=
define ndk-resolve
ifeq ($$(filter $(1)$(and $(3),whole),$$(NDK_RESOLVED_CFLAGS_$(LOCAL_MODULE))),)
# Always mark this module's cflags as having been resolved, even if
# this is a whole library.
NDK_RESOLVED_CFLAGS_$(LOCAL_MODULE) += $(1)
NDK_CFLAGS_$(LOCAL_MODULE) += $(NDK_LOCAL_EXPORT_CFLAGS_$(1))
NDK_CFLAGS_$(LOCAL_MODULE) += $(addprefix -I,$(NDK_LOCAL_EXPORT_C_INCLUDES_$(1)))
endif
ifeq ($$(filter $(1)$(and $(3),whole),$$(NDK_RESOLVED_$(LOCAL_MODULE))),)
# Now append local libraries, as long as this library isn't a shared
# library itself.
ifeq ($(4),)
# Mark this module's library dependencies as having been resolved.
NDK_RESOLVED_$(LOCAL_MODULE) += $(1)
# If this is a whole library, then mark this as resolved too, and
# remove the library from the normal static library list.
ifneq ($(3),)
NDK_RESOLVED_$(LOCAL_MODULE) += $(1)whole
endif
# If the module happens to be zlib, then add -lz to the shared library
# flags.
ifeq ($(strip $(1)),libz)
NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -lz
endif
ifeq ($(strip $(1)),z)
NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -lz
endif
# Likewise for libdl.
ifeq ($(strip $(1)),libdl)
NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -ldl
endif
ifeq ($(strip $(1)),dl)
NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -ldl
endif
# Likewise for libstdc++.
ifeq ($(strip $(1)),libstdc++)
NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -lstdc++
endif
ifeq ($(strip $(1)),dl)
NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -lstdc++
endif
# Likewise for liblog.
ifeq ($(strip $(1)),liblog)
NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -llog
endif
ifeq ($(strip $(1)),log)
NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -llog
endif
# Likewise for libandroid.
ifeq ($(strip $(1)),libandroid)
NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -landroid
endif
ifeq ($(strip $(1)),android)
NDK_SO_EXTRA_FLAGS_$(LOCAL_MODULE) += -landroid
endif
ifeq ($(findstring $(1),$(NDK_SYSTEM_LIBRARIES))$(2)$(3),)
ifneq ($(findstring lib,$(1)),)
NDK_LOCAL_SO_NAMES_$(LOCAL_MODULE) += $(1)_emacs.so
else
NDK_LOCAL_SO_NAMES_$(LOCAL_MODULE) += lib$(1)_emacs.so
endif
endif
ifneq ($(2),)
ifneq ($(findstring lib,$(1)),)
NDK_LOCAL_A_NAMES_$(LOCAL_MODULE) += $(1).a
else
NDK_LOCAL_A_NAMES_$(LOCAL_MODULE) += lib$(1).a
endif
endif
ifneq ($(3),)
ifneq ($(findstring lib,$(1)),)
NDK_WHOLE_A_NAMES_$(LOCAL_MODULE) += $(1).a
else
NDK_WHOLE_A_NAMES_$(LOCAL_MODULE) += lib$(1).a
endif
# Remove this archive from the regular archive list, should it already
# exists. Any given archive should only appear once, and if an
# archive has been specified as whole it should always be whole.
NDK_LOCAL_A_NAMES_$(LOCAL_MODULE) := $$(filter-out lib$(1).a,$$(NDK_LOCAL_A_NAMES_$(LOCAL_MODULE)))
NDK_LOCAL_A_NAMES_$(LOCAL_MODULE) := $$(filter-out $(1).a,$$(NDK_LOCAL_A_NAMES_$(LOCAL_MODULE)))
endif
endif
$$(foreach module,$$(NDK_LOCAL_STATIC_LIBRARIES_$(1)),$$(eval $$(call ndk-resolve,$$(module),1,,$(or $(4),$(if $(2)$(3),,1)))))
$$(foreach module,$$(NDK_LOCAL_SHARED_LIBRARIES_$(1)),$$(eval $$(call ndk-resolve,$$(module),,,$(or $(4),$(if $(2)$(3),,1)))))
$$(foreach module,$$(NDK_LOCAL_WHOLE_LIBRARIES_$(1)),$$(eval $$(call ndk-resolve,$$(module),,1,$(or $(4),$(if $(2)$(3),,1)))))
endif
endef
# Add shared libraries to the shared object names when they appear as
# a top level dependency. However, do not recursively add the names
# of this module's shared library dependencies, if it is just a shared
# library, since it will link to those shared libraries itself.
$(foreach module,$(LOCAL_SHARED_LIBRARIES),$(eval $(call ndk-resolve,$(module),,,)))
$(foreach module,$(LOCAL_STATIC_LIBRARIES),$(eval $(call ndk-resolve,$(module),1,,)))
$(foreach module,$(LOCAL_WHOLE_STATIC_LIBRARIES), $(eval $(call ndk-resolve,$(module),,1,)))

55
cross/verbose.mk.android Normal file
View file

@ -0,0 +1,55 @@
### verbose.mk --- Makefile fragment for GNU Emacs during
### cross-compilation.
## Copyright (C) 2023 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/>.
# 'make' verbosity.
V = 0
ifeq (${V},1)
AM_V_AR =
AM_V_at =
AM_V_CC =
AM_V_CXX =
AM_V_CCLD =
AM_V_CXXLD =
AM_V_GEN =
else
# Whether $(info ...) works. This is to work around a bug in GNU Make
# 4.3 and earlier, which implements $(info MSG) via two system calls
# { write (..., "MSG", 3); write (..., "\n", 1); }
# which looks bad when make -j interleaves two of these at about the same time.
#
# Later versions of GNU Make have the 'notintermediate' feature,
# so assume that $(info ...) works if this feature is present.
#
have_working_info = $(filter notintermediate,$(value .FEATURES))
#
# The workaround is to use the shell and 'echo' rather than $(info ...).
# The workaround is done only for AM_V_ELC and AM_V_ELN,
# since the bug is not annoying elsewhere.
AM_V_AR = @$(info $ AR $@)
AM_V_at = @
AM_V_CC = @$(info $ CC $@)
AM_V_CXX = @$(info $ CXX $@)
AM_V_CCLD = @$(info $ CCLD $@)
AM_V_CXXLD = @$(info $ CXXLD $@)
AM_V_GEN = @$(info $ GEN $@)
AM_V_NO_PD = --no-print-directory
endif

View file

@ -146,6 +146,8 @@ EMACSSOURCES= \
${srcdir}/glossary.texi \
${srcdir}/ack.texi \
${srcdir}/kmacro.texi \
${srcdir}/android.texi \
${srcdir}/input.texi \
$(EMACS_XTRA)
## Disable implicit rules.

647
doc/emacs/android.texi Normal file
View file

@ -0,0 +1,647 @@
@c This is part of the Emacs manual.
@c Copyright (C) 2023 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Android
@appendix Emacs and Android
@cindex Android
Android is a mobile operating system developed by the Open Handset
Alliance. This section describes the peculiarities of using Emacs on
an Android device running Android 2.2 or later.
Android devices commonly rely on user input through a touch screen
or digitizer device and on-screen keyboard. For more information
about using such devices with Emacs, @pxref{Other Input Devices}.
@menu
* What is Android?:: Preamble.
* Android Startup:: Starting up Emacs on Android.
* Android Environment:: Running Emacs under Android.
* Android File System:: The Android file system.
* Android Windowing:: The Android window system.
* Android Fonts:: Font selection under Android.
* Android Troubleshooting:: Dealing with problems.
@end menu
@node What is Android?
@section Android history
Android is an operating system for mobile devices developed by the
Open Handset Alliance, a group of companies interested in developing
handsets that can run a common set of software. It is supposedly free
software.
Like the X Consortium of times past, the Open Handset Alliance
believes that ``openness'' (namely, the regular release of the Android
source code) is simply a tool to increase the popularity of the
Android platform. Computer companies normally produce proprietary
software. The companies in the Open Handset Alliance are no different
-- most versions of Android installed on devices are proprietary, by
virtue of containing proprietary components, that often cannot even be
replaced by the user.
Android is not designed to respect users' freedom. Almost all
versions of Android (including some which are supposedly free
software) include support for Digital Restrictions Management,
technology that is designed to limit users' ability to copy media to
and from their own devices. Most Android devices also come with
proprietary Google applications which are required to run the system,
and many other Android applications.
Thus, it must be necessary to consider Android proprietary software
from a practical standpoint. That is an injustice. If you use
Android, we urge you to switch to a free operating system, if only for
your freedom's sake.
We support GNU Emacs on proprietary operating systems because we
hope this taste of freedom will inspire users to escape from them.
@node Android Startup
@section Starting up Emacs on Android
Emacs is not installed on Android devices from source code, or by a
package manager. Instead, Emacs is compiled for Android on a
different operating system, with the resulting binaries packaged into
an archive, that is then transferred to the device and unpacked.
After being unpacked, Emacs instructs the system to display an
application icon on the desktop. Emacs then starts up once the
application icon is clicked.
@cindex ``adb logcat''
During startup, Emacs will display messages in the system log
buffer; reading that buffer requires the Android Debug Bridge
(@command{adb}) utility to be installed on another computer; it cannot
be read on the computer running Android itself.
After enabling the ``USB Debugging'' feature on the Android system,
and connecting it via USB to another system with the @command{adb}
utility installed, the log can be viewed by running the following
command on that other system:
@example
$ adb logcat | grep -E "(android_run_debug_thread|[Ee]macs)"
@end example
Assuming that the @command{adb} utility is installed on a GNU/Linux
or Unix system, follow the steps below to connect to your device.
@enumerate
@item
Enable ``developer options'' on your device, by going to the ``About''
page in the system settings application and clicking on the ``build
version'' or ``kernel version'' items five to seven times.
@item
Open the ``developer options'' settings page, which should be under
the ``system'' page in the settings application.
@item
Turn on the switch ``USB debugging''.
@item
Connect one end of a USB cable to your device, and the other end to
your computer's USB port.
@item
Run the command @command{adb shell} on your computer. This will fail
or hang because you have not yet granted your computer permission to
access the connected device.
@item
Confirm the pop-up displayed on your device asking whether or not it
should allow access from your computer.
@end enumerate
Depending on the versions of Android and @command{adb} installed,
there may be other ways to establish a connection. See the official
documentation at
@url{https://developer.android.com/studio/command-line/adb} for more
details.
@cindex emacsclient wrapper, android
Since there is no other way to start the @command{emacsclient}
program (@pxref{Emacs Server}) from another Android program, Emacs
provides a wrapper around the @command{emacsclient} program, which is
registered with the system as an application that can open all text
files.
When that wrapper is selected as the program with which to open a
file, it invokes @command{emacsclient} with the options
@command{--reuse-frame}, @command{--timeout=10}, @command{--no-wait},
and the name of the file being opened. Then, upon success, the focus
is transferred to any open Emacs frame.
However, if Emacs is not running at the time the wrapper is opened,
it starts Emacs and gives it the file to open as an argument. Note
that if that Emacs in turn does not start the Emacs server, subsequent
attempts to open the file with the wrapper will fail.
@cindex /content directory, android
Some files are given to Emacs as ``content identifiers'', which the
system provides access to outside the normal filesystem APIs. Emacs
internally supports a temporary @file{/content} directory which is
used to access those files. Do not make any assumptions about the
contents of this directory, or try to open files in it yourself.
This feature is not provided on Android 4.3 and earlier, in which
case the file is copied to a temporary directory instead.
@node Android File System
@section What files Emacs can access under Android
@cindex /assets directory, android
Emacs exposes a special directory on Android systems: the name of
the directory is @file{/assets}, and it contains the @file{etc},
@file{lisp} and @file{info} directories which are normally installed
in @file{/usr/share/emacs} directory on GNU and Unix systems. On
Android systems, the Lisp emulation of @command{ls} (@pxref{ls in
Lisp}) is also enabled by default, as the @command{ls} binary which
comes with the system varies by manufacturer and usually does not
support all of the features required by Emacs. One copy of
@command{ls} shipped with some Android devices is even known to lack
support for the @code{-l} flag.
@cindex limitations of the /assets directory
This directory exists because Android does not extract the contents
of application packages on to the file system while unpacking them,
but instead requires programs like Emacs to access its contents using
a special ``asset manager'' interface. Here are the peculiarities
that result from such an implementation:
@itemize @bullet
@item
Subprocesses (such as @command{ls}) can not run from the
@file{/assets} directory; if you try to run a subprocess with
@code{current-directory} set to @file{/assets} or a subdirectory
thereof, it will run from the home directory instead.
@item
There are no @file{.} and @file{..} directories inside the
@file{/assets} directory.
@item
Files in the @file{/assets} directory are always read only, and have
to be completely read in to memory each time they are opened.
@end itemize
Aside from the @file{/assets} directory, Android programs normally
have access to three other directories. They are:
@itemize @bullet
@item
The @dfn{app data} directory. This also serves as the home directory
for Emacs, and is always accessible read-write.
@item
The @dfn{app library} directory. This is automatically appended to
@code{exec-path} upon startup.
@item
The @dfn{external storage} directory. This is accessible to Emacs
when the user grants the ``Files and Media'' permission to Emacs via
system settings.
@end itemize
The external storage directory is found at @file{/sdcard}. The
other directories are not found at any fixed location, although the
app data directory is typically symlinked to
@file{/data/data/org.gnu.emacs}.
@cindex temp~unlinked.NNNN files, Android
On Android devices running very old (2.6.29) versions of the Linux
kernel, Emacs needs to create files named starting with
@file{temp~unlinked} in the the temporary file directory in order to
read from asset files. Do not create files with such names yourself,
or they may be overwritten or removed.
@cindex file system limitations, Android 11
On Android 11 and later, the Android system restricts applications
from accessing files in the @file{/sdcard} directory using
file-related system calls such as @code{open} and @code{readdir}.
This restriction is known as ``Scoped Storage'', and supposedly
makes the system more secure. Unfortunately, it also means that Emacs
cannot access files in those directories, despite holding the
necessary permissions. Thankfully, the Open Handset Alliance's
version of Android allows this restriction to be disabled on a
per-program basis; the corresponding option in the system settings
panel is:
@example
System -> Apps -> Special App Access -> All files access -> Emacs
@end example
After you disable or enable this setting as appropriate and grant
Emacs the ``Files and Media'' permission, it will be able to access
files under @file{/sdcard} as usual.
These settings are not present on many proprietary versions of
Android.
@node Android Environment
@section Running Emacs under Android
From the perspective of users, Android is mostly a single user
operating system; however, from the perspective of applications and
Emacs, the system has an overwhelming number of users.
Each application runs in its own user, with his own home directory,
which is the app data directory (@pxref{Android File System}.)
Each application is also prohibited from accessing system
directories, and the app data directories of other applications.
Emacs comes with several binaries. While being executable files,
they are packaged as libraries in the library directory, because
otherwise the system will not unpack them while Emacs is being
installed. This means, instead of specifying @code{ctags} or
@code{emacsclient} in a subprocess, Lisp code must specify
@code{libctags.so} or @code{libemacsclient.so} on the command line
instead when starting either of those programs in a subprocess.
The @file{/assets} directory containing Emacs start-up files is
supposed to be inaccessible to processes not directly created by
@code{zygote}, the system service responsible for starting
applications. Since required Lisp is found in the @file{/assets}
directory, it would thus follow that it is not possible for Emacs to
start itself as a subprocess. A special binary named
@command{libandroid-emacs.so} is provided with Emacs, and does its
best to start Emacs, for the purpose of running Lisp in batch mode.
However, the approach it takes was devised by reading Android source
code, and is not sanctioned by the Android compatibility definition
documents, so your mileage may vary.
@cindex call-process, Android
@vindex android-use-exec-loader
Android 10 and later also prohibit Emacs itself from running
executables inside the app data directory, obstensibly for security
readers. On these systems, Emacs normally applies a workaround;
however, this workaround requires running all sub-processes through
another subprocess which implements an executable loader and applies
process tracing to all its children, which may prove to be problematic
for various different reasons. In that case, the workaround can be
disabled by changing the variable @code{android-use-exec-loader} to
@code{nil}.
When this workaround is in effect, process IDs retrieved through the
@code{process-id} function will be that of the executable loader
process; its child will belong to the same process group as the
loader. As a result, @code{interrupt-process}, and other related
functions will work correctly, but using the process ID returned by
@code{process-id} for other purposes will not.
One side effect of the mechanism by which process tracing is carried
out is that job control facilities will not be able to stop
subprocesses, and the @code{SIGSTOP} signal will appear to have no
effect.
In addition, Android 12 also terminates subprocesses which are
consuming CPU while Emacs itself is in the background. The system
determines which processes are consuming too much CPU in intervals of
five minutes, and terminates the process that has consumed the most
CPU time.
Android 12.1 and Android 13 provide an option to disable this
behavior; to use it, enable ``USB debugging'' (@pxref{Android
Startup}) connect the Android system to another computer, and run:
@example
$ adb shell "settings put global settings_enable_monitor_phantom_procs false"
@end example
@section Running Emacs in the background
@cindex emacs killed, android
@cindex emacs in the background, android
Application processes are treated as disposable entities by the
system. When all Emacs frames move to the background, Emacs is liable
to be killed by the system at any time, for the purpose of saving
system resources.
On Android 7.1 and earlier, Emacs tells the system to treat it as a
``background service''. The system will try to avoid killing Emacs
unless the device is under memory stress.
Android 8.0 removed the ability for background services to receive
such special treatment. However, Emacs applies a workaround: the
system considers applications that create a permanent notification to
be performing active work, and will avoid killing such applications.
Thus, on those systems, Emacs displays a permanent notification for as
long as it is running. Once the notification is displayed, it can be
safely hidden through the system settings without resulting in Emacs
being killed.
However, it is not guaranteed that the system will not kill Emacs,
even if the notification is being displayed. While the Open Handset
Alliance's sample implementation of Android behaves correctly, many
manufacturers place additional restrictions on program execution in
the background in their proprietary versions of Android. There is a
list of such troublesome manufacturers and sometimes workarounds, at
@url{https://dontkillmyapp.com/}.
@section Android permissions
@cindex external storage, android
Android also defines a permissions system that determines what
system services Emacs is allowed to access. Programs must specify
what permissions they want; what then happens depends on the version
of Android being used:
@itemize @bullet
@item
On Android 5.1 and earlier, Emacs automatically receives the following
permissions it has requested upon being installed:
@itemize @minus
@item
@code{android.permission.READ_CONTACTS}
@item
@code{android.permission.WRITE_CONTACTS}
@item
@code{android.permission.VIBRATE}
@item
@code{android.permission.ACCESS_COARSE_LOCATION}
@item
@code{android.permission.ACCESS_NETWORK_STATE}
@item
@code{android.permission.INTERNET}
@item
@code{android.permission.SET_WALLPAPER}
@item
@code{android.permission.WRITE_EXTERNAL_STORAGE}
@item
@code{android.permission.SEND_SMS}
@item
@code{android.permission.RECEIVE_SMS}
@item
@code{android.permission.RECEIVE_MMS}
@item
@code{android.permission.WRITE_SMS}
@item
@code{android.permission.READ_SMS}
@item
@code{android.permission.NFC}
@item
@code{android.permission.TRANSMIT_IR}
@item
@code{android.permission.READ_PHONE_STATE}
@item
@code{android.permission.WAKE_LOCK}
@item
@code{android.permission.FOREGROUND_SEVICE}
@item
@code{android.permission.REQUEST_INSTALL_PACKAGES}
@item
@code{android.permission.REQUEST_DELETE_PACKAGES}
@item
@code{android.permission.SYSTEM_ALERT_WINDOW}
@item
@code{android.permission.RECORD_AUDIO}
@item
@code{android.permission.CAMERA}
@end itemize
While most of these permissions are left unused by Emacs itself, they
are declared by Emacs as they could be useful for other programs; for
example, the permission to access contacts may be useful for EUDC.
@item
On Android 6.0 and later, Emacs only receives the following
permissions upon installation:
@itemize @minus
@item
@code{android.permission.VIBRATE}
@item
@code{android.permission.ACCESS_NETWORK_STATE}
@item
@code{android.permission.INTERNET}
@item
@code{android.permission.SET_WALLPAPER}
@item
@code{android.permission.NFC}
@item
@code{android.permission.TRANSMIT_IR}
@item
@code{android.permission.WAKE_LOCK}
@item
@code{android.permission.POST_NOTIFICATIONS}
@end itemize
Other permissions must be granted by the user through the system
settings application. Consult the manufacturer of your device for
more details, as how to do this varies by device.
@end itemize
@node Android Windowing
@section The Android window system
Android has an unusual window system; there, all windows are
maximized or full-screen, and only one window can be displayed at a
time. On larger devices, the system allows up to four windows to be
tiled on the screen at any time.
Windows on Android do not continue to exist indefinitely after they
are created. Instead, the system may choose to terminate windows that
are not on screen in order to save memory, with the assumption that
the program will save its contents to disk and restore them later,
when the user asks for it to be opened again. As this is obviously
not possible with Emacs, Emacs separates the resources associated with
a frame from its system window.
Each system window created (including the initial window created
during Emacs startup) is appended to a list of windows that do not
have associated frames. When a frame is created, Emacs looks up any
window within that list, and displays the contents of the frame
within; if there is no window at all, then one is created. Likewise,
when a new window is created by the system, Emacs places the contents
of any frame that is not already displayed within a window inside.
When a frame is closed, the corresponding system window is also
closed. Upon startup, the system creates a window itself (within
which Emacs displays the first window system frame shortly
thereafter.) Emacs differentiates between that window and windows
created on behalf of other frames to determine what to do when the
system window associated with a frame is closed:
@itemize @bullet
@item
When the system closes the window created during application startup
in order to save memory, Emacs retains the frame for when that window
is created later.
@item
When the user closes the window created during application startup,
and the window was not previously closed by the system in order to
save resources, Emacs deletes any frame displayed within that window.
@item
When the user or the system closes any window created by Emacs on
behalf of a specific frame, Emacs deletes the frame displayed within
that window.
@end itemize
@cindex windowing limitations, android
@cindex frame parameters, android
Emacs only supports a limited subset of GUI features on Android; the
limitations are as follows:
@itemize @bullet
@item
Scroll bars are not supported, as they are close to useless on Android
devices.
@item
The @code{alpha}, @code{alpha-background}, @code{z-group},
@code{override-redirect}, @code{mouse-color}, @code{title},
@code{wait-for-wm}, @code{sticky}, @code{undecorated} and
@code{tool-bar-position} frame parameters (@pxref{Frame Parameters,,,
elisp, the Emacs Lisp Reference Manual}) are unsupported.
@item
On Android 4.0 and earlier, the @code{fullscreen} frame parameter is
always @code{maximized} for top-level frames; on later versions of
Android, it can also be @code{fullscreen}.
@end itemize
@cindex selections, android
@cindex android clipboard
Emacs does not implement all selection related features supported
under the X Window System on Android. For example, only the
@code{CLIPBOARD} and @code{PRIMARY} selections (@pxref{Cut and Paste})
are supported, and Emacs is only able to set selections to plain text.
In addition, the Android system itself places certain restrictions
on what selection data Emacs can access:
@itemize @bullet
@item
On Android 2.3 and earlier, the function @code{gui-selection-owner-p}
always returns @code{nil} for the clipboard selection.
@item
Between Android 3.0 and Android 9.0, Emacs is able to access the
clipboard whenever it wants, and @code{gui-selection-owner-p} always
returns accurate results.
@item
Under Android 10.0 and later, Emacs can only access clipboard data
when one of its frames has the input focus, and
@code{gui-selection-owner-p} always returns @code{nil} for the
clipboard selection.
@end itemize
Since the Android system itself has no concept of a primary
selection, Emacs provides an emulation instead. This means there is
no way to transfer the contents of the primary selection to another
application via cut-and-paste.
@vindex android-pass-multimedia-buttons-to-system
@cindex volume/multimedia buttons, Android
The volume keys are normally reserved by Emacs and used to provide
the ability to quit Emacs without a physical keyboard
(@pxref{On-Screen Keyboards}.) However, if you want them to adjust
the volume instead, you can set the variable
@code{android-pass-multimedia-buttons-to-system} to a non-@code{nil}
value; note that you will no longer be able to quit Emacs using the
volume buttons in that case.
@cindex dialog boxes, android
Emacs is unable to display dialog boxes (@pxref{Dialog Boxes}) while
it does not have the input focus on Android 6.0 or later. If this is
important to you, this ability can be restored by granting Emacs
permission to display over other programs. Normally, this can be done
from the:
@example
System -> Apps -> Emacs -> More -> Display over other apps
@end example
menu in the system settings, but this procedure may vary by device.
@node Android Fonts
@section Font backends and selection under Android
@cindex fonts, android
Emacs supports two font backends under Android: they are respectively
named @code{sfnt-android} and @code{android}.
Upon startup, Emacs enumerates all the TrueType format fonts in the
directories @file{/system/fonts} and @file{/product/fonts}, and the
@file{fonts} directory (@dfn{user fonts directory}) inside the Emacs
home directory. Emacs assumes there will always be a font named
``Droid Sans Mono'', and then defaults to using this font. These
fonts are then displayed by the @code{sfnt-android} font driver.
When running on Android, Emacs currently lacks support for OpenType
fonts. This means that only a subset of the fonts installed on the
system are currently available to Emacs. If you are interested in
lifting this limitation, please contact @email{emacs-devel@@gnu.org}.
If the @code{sfnt-android} font driver fails to find any fonts at
all, Emacs falls back to the @code{android} font driver. This is a
very lousy font driver, because of limitations and inaccuracies in the
font metrics provided by the Android platform. In that case, Emacs
uses the ``Monospace'' typeface configured on your system; this should
always be Droid Sans Mono.
@cindex TrueType GX fonts, android
@cindex distortable fonts, android
Like on X systems, Emacs supports distortable fonts under Android.
These fonts (also termed ``TrueType GX fonts'', ``variable fonts'',
and ``multiple master fonts'') provide multiple different styles
(``Bold'', ``Italic'', etc) using a single font file.
When a user-installed distortable font is found, each font that a
previously discovered font provided will no longer be used. In
addition, any previously specified distortable fonts with the same
family name are also removed. When a conventional font is found, any
previous conventional font with the same style and family will be
removed; distortable fonts with the same family will no longer be used
to provide that style.
@node Android Troubleshooting
@section What to do when something goes wrong on Android
@cindex troubleshooting, android
@cindex emacs -Q, android
Since Android has no command line, there is normally no way to
specify command-line arguments when starting Emacs. This is very
nasty when you make a mistake in your Emacs initialization files that
prevents Emacs from starting up at all, as the system normally
prevents other programs from accessing Emacs's home directory.
However, Emacs can be started with the equivalent of the
@code{--quick} option (@pxref{Initial Options}) through a special
preferences screen, which can be accessed through the Emacs ``app
info'' page in the system settings application.
Consult the manufacturer of your device for more details, as how to
do this varies by device.
@cindex dumping, android
The first time any given copy of Emacs starts on a device, it spends
a while loading the preloaded Lisp files which normally come with
Emacs. This produces a ``dump file'' (@pxref{Initial Options}) in the
files directory, containing an identifier unique to this copy of
Emacs.
The next time that same copy of Emacs starts up, it simply loads the
data contained in that dump file, greatly improving start up time.
If by some unforeseen circumstance the dump file is corrupted, Emacs
can crash. If that happens, the dump file stored in the Emacs files
directory can be erased through the same preferences screen.
@cindex accessing Emacs directories, Android
Emacs supports an alternative method of rescuing broken Emacs
installations on Android 4.4 and later: Emacs exports a ``documents
provider'' which accesses the contents of Emacs's home directory, that
can then be accessed by any file manager program.
If you can find out how to open that documents provider in the file
manager that comes with your device, you can rename, delete, or edit
your initialization or dump files from there instead.

View file

@ -223,7 +223,9 @@ Appendices
* Antinews:: Information about Emacs version 28.
* Mac OS / GNUstep:: Using Emacs under macOS and GNUstep.
* Haiku:: Using Emacs on Haiku.
* Android:: Using Emacs on Android.
* Microsoft Windows:: Using Emacs on Microsoft Windows and MS-DOS.
* Other Input Devices:: Using Emacs with other input devices.
* Manifesto:: What's GNU? Gnu's Not Unix!
* Glossary:: Terms used in this manual.
@ -1260,6 +1262,21 @@ Emacs and Haiku
* Haiku Basics:: Basic Emacs usage and installation under Haiku.
* Haiku Fonts:: The various options for displaying fonts on Haiku.
Emacs and Android
* What is Android?:: Preamble.
* Android Startup:: Starting up Emacs on Android.
* Android Environment:: Running Emacs under Android.
* Android File System:: The Android file system.
* Android Windowing:: The Android window system.
* Android Fonts:: Font selection under Android.
* Android Troubleshooting:: Dealing with problems.
Emacs and unconventional input devices
* Touchscreens:: Using Emacs on touchscreens.
* On-Screen Keyboards:: Using Emacs with virtual keyboards.
Emacs and Microsoft Windows/MS-DOS
* Windows Startup:: How to start Emacs on Windows.
@ -1630,8 +1647,10 @@ Lisp programming.
@include anti.texi
@include macos.texi
@include haiku.texi
@include android.texi
@c Includes msdos-xtra.
@include msdos.texi
@include input.texi
@include gnu.texi
@include glossary.texi
@ifnottex

146
doc/emacs/input.texi Normal file
View file

@ -0,0 +1,146 @@
@c This is part of the Emacs manual.
@c Copyright (C) 2023 Free Software Foundation, Inc.
@c See file emacs.texi for copying conditions.
@node Other Input Devices
@appendix Emacs and unconventional input devices
@cindex other input devices
Emacs was originally developed with the assumption that users will
be sitting in front of a desktop computer, with a keyboard and perhaps
a suitable pointing device such as a mouse.
However, recent developments in the X Window System, and in other
operating systems such as Android, mean that this assumption no longer
holds true. As a result, Emacs now has support for other kinds of
input devices, which is detailed here.
@menu
* Touchscreens:: Using Emacs on touchscreens.
* On-Screen Keyboards:: Using Emacs with virtual keyboards.
@end menu
@node Touchscreens
@section Using Emacs on touchscreens
@cindex touchscreens
Touchscreen input works by having the user press tools onto the
screen, which can be his own fingers, or a pointing device such as a
stylus, in order to manipulate the contents there in.
When running under the X Window System or Android, Emacs
automatically detects and maps the following touchscreen gestures to
common actions:
@itemize @bullet
@item
@cindex tapping, touchscreens
``Tapping'', meaning to briefly place and lift a tool from the
display, will result in Emacs selecting the window that was tapped,
and executing any command bound to @code{mouse-1} at that location in
the window. If the tap happened on top of a link (@pxref{Mouse
References}), then Emacs will follow the link instead.
@item
@cindex scrolling, touchscreens
``Scrolling'', meaning to place a tool on the display and move it up
or down, will result in Emacs scrolling the window contents in the
direction where the tool moves.
If the tool is moved left or right, Emacs additionally scrolls the
window horizontally to follow (@pxref{Horizontal Scrolling}.)
@item
@cindex dragging, touchscreens
``Dragging'', meaning to place a tool on the display and leave it
there for a while before moving the tool around, will make Emacs set
the point to where the tool was and begin selecting text under the
tool as it moves around, much like what would happen if @code{mouse-1}
were to be held down. @xref{Mouse Commands}.
@end itemize
@vindex touch-screen-delay
By default, Emacs considers a tool as having been left on the
display for a while after 0.7 seconds, but this can be changed by
customizing the variable @code{touch-screen-delay}.
@node On-Screen Keyboards
@section Using Emacs with virtual keyboards
@cindex virtual keyboards
@cindex on-screen keyboards
When there is no physical keyboard attached to a system, the
windowing system typically provides an on-screen keyboard, more often
known as a ``virtual keyboard'', containing rows of clickable buttons
that send keyboard input to the application, much like a real keyboard
would. This virtual keyboard is hidden by default, as it uses up
valuable on-screen real estate, and must be opened once the program
being used is ready to accept keyboard input.
Under the X Window System, the client that provides the on-screen
keyboard typically detects when the application is ready to accept
keyboard input through a set of complex heuristics, and automatically
displays the keyboard when necessary.
On other systems such as Android, Emacs must tell the system when it
is ready to accept keyboard input. Typically, this is done in
response to a touchscreen ``tap'' gesture (@pxref{Touchscreens}), or
once to the minibuffer becomes in use (@pxref{Minibuffer}.)
@vindex touch-screen-set-point-commands
When a ``tap'' gesture results in a command being executed, Emacs
checks to see whether or not the command is supposed to set the point
by looking for it in the list @code{touch-screen-set-point-commands}.
If it is, then Emacs looks up whether or not the text under the point
is read-only; if not, it activates the on-screen keyboard, assuming
that the user is about to enter text in to the current buffer.
@vindex touch-screen-display-keyboard
The user option @code{touch-screen-display-keyboard} forces Emacs to
always display the on screen keyboard; it may also be bound buffer
locally, meaning to always display the keyboard when the buffer is
selected.
Emacs also provides a set of functions to show or hide the on-screen
keyboard. For more details, @pxref{On-Screen Keyboards,,, elisp, The
Emacs Lisp Reference Manual}.
@cindex quitting, without a keyboard
Since it may not be possible for Emacs to display the on screen
keyboard when it is executing a command, Emacs implements a feature on
devices with only an on-screen keyboard, by which two rapid clicks of
a hardware button that is always present on the device results in
Emacs quitting. @xref{Quitting}.
@vindex x-quit-keysym
The exact button is used to do this varies by system: on X, it is
defined in the variable @code{x-quit-keysym}, and on Android, it is
always the volume down button.
@cindex text conversion, keyboards
Most input methods designed to work with on-screen keyboards perform
buffer edits differently from desktop input methods.
On a conventional desktop windowing system, an input method will
simply display the contents of any on going character compositions on
screen, and send the appropriate key events to Emacs after completion.
However, on screen keyboard input methods directly perform edits to
the selected window of each frame; this is known as ``text
conversion'', or ``string conversion'' under the X Window System.
Emacs enables these input methods whenever the buffer local value of
@code{text-conversion-style} is non-@code{nil}, normally inside
derivatives of @code{text-mode} and @code{prog-mode}.
Text conversion is performed asynchronously whenever Emacs receives
a request to perform the conversion from the input method, and Emacs
is not currently reading a key sequence for which one prefix key has
already been read (@pxref{Keys}.) After the conversion completes, a
@code{text-conversion} event is sent. @xref{Misc Events,,, elisp, the
Emacs Reference Manual}.
@vindex text-conversion-face
If the input method needs to work on a region of the buffer, then
the region becomes known as the ``composing region'' (or
``preconversion region''.) The variable @code{text-conversion-face}
describes whether or not to display the composing region in a specific
face.

View file

@ -2011,11 +2011,18 @@ the position of the finger when the event occurred.
This event is sent when @var{point} is created by the user pressing a
finger against the touchscreen.
These events also have imaginary prefixes keys added by
@code{read-key-sequence} when they originate on top of a special part
of a frame or window. @xref{Key Sequence Input}. The reason the
other touch screen events do not undergo this treatment is that they
are rarely useful without being used in tandem from their
corresponding @code{touchscreen-begin} events.
@cindex @code{touchscreen-update} event
@item (touchscreen-update @var{points})
This event is sent when a point on the touchscreen has changed
position. @var{points} is a list of touch points containing the
up-to-date positions of each touch point currently on the touchscreen.
up-to-date positions of each touch point currently on the touchscxcompile/reen.
@cindex @code{touchscreen-end} event
@item (touchscreen-end @var{point})
@ -2024,6 +2031,45 @@ display, because another program took the grab, or because the user
raised the finger from the touchscreen.
@end table
If a touchpoint is pressed against the menu bar, then Emacs will not
generate any corresponding @code{touchscreen-begin} or
@code{touchscreen-end} events; instead, the menu bar may be displayed
when @code{touchscreen-end} should have been delivered.
@cindex handling touch screen events
@cindex tap and drag, touch screen gestures
Emacs provides two functions to handle touch screen events. They are
intended to be used by a command bound to @code{touchscreen-begin} to
handle common gestures.
@defun touch-screen-track-tap event &optional update data
This function is used to track a single ``tap'' gesture originating
from the @code{touchscreen-begin} event @var{event}, often used to
set the point or to activate a button. It waits for a
@code{touchscreen-end} event with the same touch identifier to arrive,
at which point it returns @code{t}, signifying the end of the gesture.
If a @code{touchscreen-update} event arrives in the mean time and
contains at least one touchpoint with the same identifier as in
@var{event}, the function @var{update} is called with two arguments,
the list of touchpoints in that @code{touchscreen-update} event, and
@var{data}.
If any other event arrives in the mean time, @code{nil} is returned.
The caller should not perform any action in that case.
@end defun
@defun touch-screen-track-drag event update &optional data
This function is used to track a single ``drag'' gesture originating
from the @code{touchscreen-begin} event @code{event}.
It behaves like @code{touch-screen-track-tap}, except that it returns
@code{no-drag} and refrains from calling @var{update} if the
touchpoint in @code{event} did not move far enough (by default, 5
pixels from its position in @code{event}) to qualify as an actual
drag.
@end defun
@node Focus Events
@subsection Focus Events
@cindex focus event
@ -2160,6 +2206,69 @@ the buffer in which the xwidget will be displayed, using
A few other event types represent occurrences within the system.
@table @code
@cindex @code{text-conversion} event
@item text-conversion
This kind of event is sent @strong{after} a system-wide input method
performs an edit to one or more buffers.
@vindex text-conversion-edits
Once the event is sent, the input method may already have made
changes to multiple buffers inside many different frames. To
determine which buffers have been changed, and what edits have
been made to them, use the variable
@code{text-conversion-edits}, which is set prior to each
@code{text-conversion} event being sent; it is a list of the
form:
@example
@w{@code{((@var{buffer} @var{beg} @var{end} @var{ephemeral}) ...)}}
@end example
Where @var{ephemeral} is the buffer which was modified, @var{beg} and
@var{end} are markers set to the positions of the edit at the time it
was completed, and @var{ephemeral} is either a string, containing any
text which was inserted, or any text before point which was deleted,
@code{t}, meaning that the edit is a temporary edit made by the input
method, and @code{nil}, meaning that some text was deleted after
point.
@vindex text-conversion-style
Whether or not this event is sent depends on the value of the
buffer-local variable @code{text-conversion-style}, which determines
how an input method that wishes to make edits to buffer contents will
behave.
This variable can have one of three values:
@table @code
@item nil
This means that the input method will be disabled entirely, and key
events will be sent instead of text conversion events.
@item action
This means that the input method will be enabled, but @key{RET} will
be sent wherever the input method wanted to insert a new line.
@item t
This, or any other value, means that the input method will be enabled
and make edits terminated by @code{text-conversion} events.
@end table
@findex disable-text-conversion
Changes to the value of this variable will only take effect upon
the next redisplay after the buffer becomes the selected buffer
of a frame. If you need to disable text conversion in a way
that takes immediate effect, call the function
@code{set-text-conversion-style} instead. This can potentially
lock up the input method for a significant amount of time, so do
not do this lightly!
@vindex disable-inhibit-text-conversion
In addition, text conversion is automatically disabled after a prefix
key is read by the command loop, or through @code{read-key-sequence}.
This can be disabled by setting or binding the variable
@code{disable-inhibit-text-conversion} to a non-@code{nil} value.
@cindex @code{delete-frame} event
@item (delete-frame (@var{frame}))
This kind of event indicates that the user gave the window manager
@ -3036,19 +3145,21 @@ with any other events.
@cindex @code{right-divider}, prefix key
@cindex @code{bottom-divider}, prefix key
@cindex mouse events, in special parts of window or frame
When mouse events occur in special parts of a window or frame, such as a mode
line or a scroll bar, the event type shows nothing special---it is the
same symbol that would normally represent that combination of mouse
button and modifier keys. The information about the window part is kept
elsewhere in the event---in the coordinates. But
@code{read-key-sequence} translates this information into imaginary
prefix keys, all of which are symbols: @code{tab-line}, @code{header-line},
@code{horizontal-scroll-bar}, @code{menu-bar}, @code{tab-bar}, @code{mode-line},
@cindex touch screen events, in special parts of window or frame
When mouse or @code{touch-screen-begin} events occur in special parts
of a window or frame, such as a mode line or a scroll bar, the event
type shows nothing special---it is the same symbol that would normally
represent that combination of mouse button and modifier keys. The
information about the window part is kept elsewhere in the event---in
the coordinates. But @code{read-key-sequence} translates this
information into imaginary prefix keys, all of which are symbols:
@code{tab-line}, @code{header-line}, @code{horizontal-scroll-bar},
@code{menu-bar}, @code{tab-bar}, @code{mode-line},
@code{vertical-line}, @code{vertical-scroll-bar}, @code{left-margin},
@code{right-margin}, @code{left-fringe}, @code{right-fringe},
@code{right-divider}, and @code{bottom-divider}. You can define meanings for
mouse clicks in special window parts by defining key sequences using these
imaginary prefix keys.
@code{right-divider}, and @code{bottom-divider}. You can define
meanings for mouse clicks in special window parts by defining key
sequences using these imaginary prefix keys.
For example, if you call @code{read-key-sequence} and then click the
mouse on the window's mode line, you get two events, like this:

View file

@ -2933,8 +2933,9 @@ apply to. Here are the possible values of @var{characteristic}:
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), @code{haiku} (for
Haiku), @code{pgtk} (for pure GTK), or @code{tty} (a non-graphics-capable
display). @xref{Window Systems, window-system}.
Haiku), @code{pgtk} (for pure GTK), @code{android} (for Android), 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},
@ -8857,6 +8858,8 @@ Emacs is displaying the frame using MS-DOS direct screen writes.
Emacs is displaying the frame using the Application Kit on Haiku.
@item pgtk
Emacs is displaying the frame using pure GTK facilities.
@item android
Emacs is displaying the frame on Android.
@item nil
Emacs is displaying the frame on a character-based terminal.
@end table

View file

@ -1139,6 +1139,7 @@ Frames
* Dialog Boxes:: Displaying a box to ask yes or no.
* Pointer Shape:: Specifying the shape of the mouse pointer.
* Window System Selections::Transferring text to and from other X clients.
* Accessing Selections:: The multiple different kinds of selections.
* Yanking Media:: Yanking things that aren't plain text.
* Drag and Drop:: Internals of Drag-and-Drop implementation.
* Color Names:: Getting the definitions of color names.

View file

@ -104,9 +104,11 @@ window of another Emacs frame. @xref{Child Frames}.
* Mouse Tracking:: Getting events that say when the mouse moves.
* Mouse Position:: Asking where the mouse is, or moving it.
* Pop-Up Menus:: Displaying a menu for the user to select from.
* On-Screen Keyboards:: Displaying the virtual keyboard.
* Dialog Boxes:: Displaying a box to ask yes or no.
* Pointer Shape:: Specifying the shape of the mouse pointer.
* Window System Selections:: Transferring text to and from other X clients.
* Accessing Selections:: The multiple different kinds of selections.
* Yanking Media:: Yanking things that aren't plain text.
* Drag and Drop:: Internals of Drag-and-Drop implementation.
* Color Names:: Getting the definitions of color names.
@ -695,7 +697,7 @@ The position of the top left corner of the native frame specifies the
indicate that position for the various builds:
@itemize @w{}
@item (1) non-toolkit, Haiku, and terminal frames
@item (1) non-toolkit, Android, Haiku, and terminal frames
@item (2) Lucid, Motif, and MS-Windows frames
@ -2394,6 +2396,7 @@ 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
Haiku, there can be several font drivers (@pxref{Haiku Fonts,,, emacs,
The GNU Emacs Manual}), as on Android (@pxref{Android Fonts,,, emacs,
The GNU Emacs Manual}).
On other systems, there is only one available font backend, so it does
@ -3739,9 +3742,9 @@ This function displays a pop-up menu and returns an indication of
what selection the user makes.
The argument @var{position} specifies where on the screen to put the
top left corner of the menu. It can be either a mouse button event
(which says to put the menu where the user actuated the button) or a
list of this form:
top left corner of the menu. It can be either a mouse button or
@code{touchscreen-begin} event (which says to put the menu where the
user actuated the button) or a list of this form:
@example
((@var{xoffset} @var{yoffset}) @var{window})
@ -3826,6 +3829,30 @@ keymap. It won't be called if @code{x-popup-menu} returns for some
other reason without displaying a pop-up menu.
@end defvar
@node On-Screen Keyboards
@section On-Screen Keyboards
An on-screen keyboard is a special kind of pop up provided by the
system, with rows of clickable buttons that act as a real keyboard.
On certain systems (@pxref{On-Screen Keyboards,,,emacs, The Emacs
Manual}), Emacs is supposed to display and hide the on screen keyboard
depending on whether or not the user is about to type something.
@defun frame-toggle-on-screen-keyboard frame hide
This function displays or hides the on-screen keyboard on behalf of
the frame @var{frame}. If @var{hide} is non-@code{nil}, then the
on-screen keyboard is hidden; otherwise, it is displayed.
It returns whether or not the on screen keyboard @strong{may} have
been displayed, which should be used to determine whether or not to
hide the on-screen keyboard later.
This has no effect if the system automatically detects when to display
the on-screen keyboard, or when it does not provide any on-screen
keyboard.
@end defun
@node Dialog Boxes
@section Dialog Boxes
@cindex dialog boxes
@ -4033,6 +4060,542 @@ For backward compatibility, there are obsolete aliases
names of @code{gui-get-selection} and @code{gui-set-selection} before
Emacs 25.1.
@node Accessing Selections
@section Accessing Selections
@code{gui-get-selection} is able to retrieve multiple different
kinds of selection data from any number of selections. However, the
data types and selections that Emacs understands is not precisely
specified and differs depending on the window system on which Emacs is
running.
At the same time, @code{gui-set-selection} hides a great deal of
complexity behind its back, at least on some systems: its @var{data}
argument need not be a string, but is actually given verbatim to
system specific code.
Emacs's implementation of selections is most complete on the X
Window System. This is both an artifact of history (X was the first
window system supported by Emacs) and one of technical reasons:
instead of using selections only to transfer text and multimedia
content between clients, X uses selections as a general inter-client
communication system, leading to a great proliferation of selection
data types.
Even more confusingly, X also supports another inter-client
communication mechanism: the Inter-Client Exchange. However, ICE is
only used by Emacs to communicate with session managers, and is a
separate topic.
@menu
* X Selections:: Selection data types (and more) on X.
* Other Selections:: How they work on other window systems.
@end menu
@node X Selections
@subsection X Selections
X refrains from defining fixed data types for selection data, or a
fixed number of selections. Selections are instead identified by X
``atoms'', which are unique 29-bit identifiers issued by the X server
for a corresponding name. In Emacs, you can simply write a symbol
with the name of the atom, and Emacs will transparently request these
identifiers where necessary.
When a program ``sets'' a selection under X, it actually makes
itself the ``owner'' of the selection---the X server will then deliver
selection requests to the program, which is obliged to respond to the
requesting client with the selection data.
Similarly, a program does not ``get'' selection data from the X
server. Instead, its selection requests are sent to the client with
the window which last took ownership over the selection, which then
replies with the requested data.
Each selection request contains three parameters:
@itemize @bullet
@item
The window which requested the selection; this is used to identify the
@c Not a typo: X spells ``requestor'' with an o.
requesting program, otherwise known as the @dfn{requestor}.
@item
An atom identifying the ``target'' to which the owner should convert
the selection. It is easiest to think of the conversion target as the
kind of data that the requestor wants: in selection requests made by
Emacs, the target is determined by the @dfn{type} argument to
@code{gui-get-selection}.
@item
A 32-bit timestamp containing the X server time at which the requestor
last obtained input.
@end itemize
The selection owner responds by tranferring to the requestor a
series of bytes, 16 bit words, or 32 bit words, along with another
atom identifying the type of those words. After requesting a
selection, Emacs then applies its own interpretation of the data
format and data type to convert the data transferred by the selection
owner to a Lisp representation, which @code{gui-get-selection}
returns.
By default, Emacs converts selection data consisting of any series
of bytes to a unibyte string containing those bytes, selection data
consisting of a single 16-bit or 32-bit word as an unsigned number,
and selection data consisting of multiple such words as a vector of
unsigned numbers. However, Emacs applies special treatment for
several selection data types:
@table @code
@item INTEGER
16-bit or 32-bit words of this type are treated as signed integers,
instead of unsigned ones. If there are multiple words in the
selection data, a vector is returned; otherwise, the integer is
returned by itself.
@item ATOM
32-bit words of this type are treated as X atoms, and returned (either
alone or as vectors) as Lisp symbols containing the names they
identify. Invalid atoms are returned as @code{nil}.
@item COMPOUND_TEXT
@item UTF8_STRING
@item STRING
Unibyte strings returned for these data types will have a single
@code{foreign-selection} text property set to a symbol with the type
of the selection data.
@end table
Each selection owner must return at least two selection targets:
@code{TARGETS}, which returns a number of atoms describing the
selection targets that the owner supports, and @code{MULTIPLE}, used
for internal purposes by X clients. A selection owner may support any
number of other targets, some of which may be standardized by the X
Consortium's
@url{http://x.org/releases/X11R7.6/doc/xorg-docs/specs/ICCCM/icccm.html,
Inter-Client Communication Conventions Manual}, while others, such as
@code{UTF8_STRING}, were supposed to be standardized by the XFree86
Project, which unfortunately did not happen.
Requests for a given selection target may, by convention, return
data in a specific type, or it may return data in one of several
types, whichever is most convenient for the selection owner; the
latter type of selection target is dubbed a @dfn{polymorphic target}.
A selection target may also return no data at all: by convention, the
selection owner performs some action a side effect upon responding to
a selection request with that target, and as such these targets are
referred to as @dfn{side-effect targets}.
Here are some selection targets which behave in a reasonably
standard manner when used with the @code{CLIPBOARD}, @code{PRIMARY},
or @code{SECONDARY} selections.
@table @code
@item ADOBE_PORTABLE_DOCUMENT_FORMAT
This target returns data in Adobe System's ``Portable Document
Format'' format, as a string.
@item APPLE_PICT
This target returns data in the ``PICT'' image format used on
Macintosh computers, as a string.
@item BACKGROUND
@item BITMAP
@item COLORMAP
@item FOREGROUND
Together, these four targets return integer data necessary to make use
of a bitmap image stored on the X server: the pixel value of the
bitmap's background color, the X identifier of the bitmap, the
colormap inside which the background and foreground are allocated, and
the pixel value of the bitmap's foreground color.
@item CHARACTER_POSITION
This target returns two unsigned 32-bit integers of type @code{SPAN}
describing the start and end positions of the selection data in the
text field containing it, in bytes.
@item COMPOUND_TEXT
This target returns a string of type @code{COMPOUND_TEXT} in the X
Consortium's multi-byte text encoding system.
@item DELETE
This target returns nothing, but as a side-effect deletes the
selection contents from any text field containing them.
@item DRAWABLE
@item PIXMAP
This target returns a list of unsigned 32-bit integers, each of which
corresponds to an X server drawable or pixmap.
@item ENCAPSULATED_POSTSCRIPT
@item _ADOBE_EPS
This target returns a string containing encapsulated Postscript code.
@item FILE_NAME
This target returns a string containing one or more file names,
separated by NULL characters.
@item HOST_NAME
This target returns a string containing the fully-qualified domain
name of the machine on which the selection owner is running.
@item USER
This target returns a string containing the user name of the machine
on which the selection owner is running.
@item LENGTH
This target returns an unsigned 32-bit or 16-bit integer containing
the length of the selection data.
@item LINE_NUMBER
This target returns two unsigned 32-bit integers of type @code{SPAN}
describing the line numbers corresponding to the start and end
positions of the selection data in the text field containing it.
@item MODULE
This target returns the name of any function containing the selection
data. It is mainly used by text editors.
@item STRING
This target returns the selection data as a string of type
@code{STRING}, encoded in ISO Latin-1 format, with Unix newline
characters.
@item C_STRING
This target returns the selection data as a ``C string''. This has
been interpreted as meaning the raw selection data in whatever
encoding used by the owner, either terminated with a NULL byte or not
at all, or an ASCII string which may or may not be terminated.
@item UTF8_STRING
This returns the selection data as a string of type
@code{UTF8_STRING}, encoded in UTF-8, with unspecified EOL format.
@item TIMESTAMP
This target returns the X server time at which the selection owner
took ownership over the selection as a 16-bit or 32-bit word of type
@code{CARDINAL}.
@item TEXT
This polymorphic target returns selection data as a string, either
@code{COMPOUND_TEXT}, @code{STRING}, @code{C_STRING}, or
@code{UTF8_STRING}, whichever data type is convenient for the
selection owner.
@end table
When a request for the targets @code{STRING}, @code{COMPOUND_TEXT},
or @code{UTF8_STRING} is made using the function
@code{gui-get-selection}, and neither @code{selection-coding-system}
nor @code{next-selection-coding-system} are set, the returned strings
are additionally decoded using the appropriate coding system for those
data types: @code{iso-8859-1}, @code{compound-text-with-extensions}
and @code{utf-8} respectively.
In addition to the targets specified above (and the many targets
used by various programs for their own purposes), several popular
programs and toolkits have decided to define selection data types of
their own, without consulting the appropriate X standards bodies.
These targets are usually named after MIME types, such as
@code{text/html} or @code{image/jpeg}, and have been known to contain:
@itemize @bullet
@item
Unterminated, newline terminated, or NULL character terminated file
names of an image or text file.
@item
Image or text data in the appropriate format.
@item
@code{file://} URIs (or possibly newline or NUL terminated lists of
URIs) leading to files in the appropriate format.
@end itemize
These selection targets were first used by Netscape, but are now
found in all kinds of programs, especially those based on recent
versions of the GTK+ or Qt toolkits.
Emacs is also capable of acting as a selection owner. When
@code{gui-set-selection} is called, the selection data specified is
not transferred to the X server; instead, Emacs records it internally
and obtains ownership of the selection.
@defvar selection-converter-alist
Alist of selection targets to ``selection converter'' functions.
When a selection request is received, Emacs looks up the selection
converter associated with the requested selection target.
The selection converter is called with three arguments: the symbol
corresponding to the atom identifying the selection being requested,
the selection target that is being requested, and the value set with
@code{gui-set-selection}. The value which it returns is either a cons
of a symbol specifying the data type and a number, symbol, or a vector
of numbers or symbols, or its cdr by itself.
If the value is the special symbol @code{NULL}, the data type is set
to @code{NULL}, and no data is returned to the requestor.
If the value is a string, it must be a unibyte string; should no
data type be explicitly specified, the data is transferred to the
requestor with the type @code{STRING}.
If the value is a symbol, its ``atom'' is retrieved, and it is
transferred to the requestor as a 32-bit value---if no data type was
specified, its type is @code{ATOM}.
If the value is a number between @code{-32769} and @code{32768}, it
is transferred to the requestor as a 16 bit value---if no data type
was specified, its type is @code{INTEGER}.
If the value is any other number, it is returned as a 32 bit value.
Even if the number returned is unsigned, the requestor will treat
words of type @code{INTEGER} as signed. To return an unsigned value,
specify the type @code{CARDINAL} instead.
If the value is a vector of symbols or numbers, it is returned as a
list of multiple atoms or numbers. The data type returned by default
is determined by that of its first element.
@end defvar
By default, Emacs is configured with selection converters for the
following selection targets:
@table @code
@item TEXT
This selection converter returns selection data as:
@itemize @bullet
@item
A string of type @code{C_STRING}, if the selection contents contain no
multibyte characters, or contains 8-bit characters with all 8 bits
set.
@item
A string of type @code{STRING}, if the selection contents can be
represented as ISO-Latin-1 text.
@item
A string of type @code{COMPOUND_TEXT}, if the selection contents can
be encoded in the X Consortium's Compound Text Encoding, and
@code{selection-coding-system} or @code{next-selection-coding-system}
is set to a coding system whose @code{:mime-charset} property is
@code{x-ctext}.
@item
A string of type @code{UTF8_STRING} otherwise.
@end itemize
@item COMPOUND_TEXT
This selection converter returns selection data as a string of type
@code{COMPOUND_TEXT}.
@item STRING
This selection converter returns selection data as a string of type
@code{STRING}, encoded in ISO-Latin-1 format.
@item UTF8_STRING
This selection converter returns selection data in UTF-8 format.
@item text/plain
@item text/plain;charset=utf-8
@item text/uri-list
@item text/x-xdnd-username
@item XmTRANSFER_SUCCESS
@item XmTRANSFER_FAILURE
@item FILE
@item _DT_NETFILE
These selection converters are used for internal purposes during
drag-and-drop operations and are not available for selections other
than @code{XdndSelection}.
@item TARGETS
This selection converter returns a list of atoms, one for each
selection target understood by Emacs.
@item MULTIPLE
This selection converter is implemented in C code and is used to
implement efficient transfer of selection requests which specify
multiple selection targets at the same time.
@item LENGTH
This selection converter returns the length of the selection data, in
bytes.
@item DELETE
This selection converter is used for internal purposes during
drag-and-drop operations.
@item FILE_NAME
This selection converter returns the file name of the buffer
containing the selection data.
@item CHARACTER_POSITION
This selection converter returns the character positions of each end
of the selection in the buffer containing the selection data.
@item LINE_NUMBER
@item COLUMN_NUMBER
This selection converter returns the line and column numbers of each
end of the selection in the buffer containing the selection data.
@item OWNER_OS
This selection converter returns the name of the operating system on
which Emacs is running.
@item HOST_NAME
This selection converter returns the fully-qualified domain name of
the machine on which Emacs is running.
@item USER
This selection converter returns the username of the user account
under which Emacs is running.
@item CLASS
@item NAME
These selection converters return the resource class and name used by
Emacs.
@item INTEGER
This selection converter returns an integer value verbatim.
@item SAVE_TARGETS
@item _EMACS_INTERNAL
These selection converters are used for internal purposes.
@end table
With the exception of @code{INTEGER}, all selection converters
expect the value given to @code{gui-set-selection} to be one of the
following:
@itemize @bullet
@item
A string.
@item
A list of the form @w{@code{(@var{beg} @var{end} @var{buf})}}, where
@var{beg} and @var{end} are two markers or overlays describing the
bounds of the selection data in the buffer @var{buf}.
@end itemize
@node Other Selections
@subsection Other Selections
Window systems such as MS-Windows, Nextstep, Haiku and Android do
not provide selections corresponding to the X semantics. Each window
system provides its own ad-hoc emulation of selections, none of which
make use of the ``selection converter'' mechanism described above. In
addition, only the @code{PRIMARY}, @code{CLIPBOARD}, and
@code{SECONDARY} selections are typically supported, alongside the
@code{XdndSelection} used for drag-and-drop operations.
GTK itself exposes emulations of X selections to applications, but
those emulations are of varying completeness. While Emacs built with
PGTK will use the same selection interface as Emacs built with X, many
selection targets will not be useful.
On MS-Windows, @code{gui-get-selection} accepts a single target,
@code{STRING}. The value returned is the selection data decoded
using @code{selection-coding-system}.
@code{gui-set-selection} also only accepts strings, encodes them
in the selection coding system, and saves them to the clipboard.
On Nextstep, Emacs only supports saving strings to selections.
However, requests for the following targets are accepted:
@c FIXME: how is the text coding system determined, and do image/* or
@c application/* return image data or file names?
@itemize @bullet
@item text/plain
@item image/png
@item text/html
@item application/pdf
@item application/rtf
@item application/rtfd
@item STRING
@item text/plain
@item image/tiff
@end itemize
On Haiku, Emacs supports the same selection values as on X. In
addition, Emacs fully implements the primary and secondary selections.
However, instead of taking ownership over the selection data, Emacs
transfers the selection data to the window server when
@code{gui-set-selection} is called. The Haiku window server expects
selection data to be provided in the form of a ``message'', containing
associations between data types and selection data.
@defvar haiku-normal-selection-encoders
List of functions which act as selection encoders. When
@code{gui-set-selection} is called, each function in this list is
successively called with its @var{selection} and @var{value}
arguments. If the function returns non-@code{nil}, it should return a
list of the form @w{@code{(@var{key} @var{type} @var{value})}}, where
@var{key} is the name of the data type being transferred, @var{type}
is either a number identifying a data type (in which case @var{value}
should be a unibyte string that is directly transferred to the window
server), or a symbol identifying both a data type and how @var{value}
should be interpreted.
@end defvar
Here are the meaningful values of @var{type}, and what they will
cause Emacs to interpret @var{value} as:
@table @code
@item string
A unibyte string. The string is NULL-terminated after being placed in
the message.
@item ref
A file name. The file is looked up and file system information
identifying the file is placed in the message.
@item short
A 16-bit integer value.
@item long
A 32-bit integer value.
@item llong
A 64-bit integer value.
@item byte
@item char
An unsigned byte between 0 and 255.
@item size_t
A number between 0 and 1 minus two to the power of the word size of
the computer Emacs is running on.
@item ssize_t
A number which fits in the C type @code{ssize_t}.
@item point
A cons of two floats, specifying a coordinate on-screen.
@item float
@item double
A single or double-precision floating point number in an unspecified
format.
@item (haiku-numeric-enum MIME)
A unibyte string containing data in a certain MIME type.
@end table
Under Haiku, @code{gui-get-selection} accepts either the targets
@code{TARGETS} and @code{TIMESTAMP}, where the former returns a vector
containing supported data types (much like on X), and the latter
returns the number of times the selection has been set, the targets
@code{STRING} and @code{UTF8_STRING}, which return text in ISO-Latin-1
and UTF-8 format, or a MIME type, in which the data is returned
undecoded as a unibyte string.
Under Android, @code{gui-get-selection} is restricted to returning
UTF-8 string data of the type @code{STRING}, or image and application
data associated with a MIME type. @code{gui-set-selection} will only
set string data, as on MS-Windows.
@node Yanking Media
@section Yanking Media

View file

@ -972,6 +972,9 @@ Hewlett-Packard HPUX operating system.
@item nacl
Google Native Client (@acronym{NaCl}) sandboxing system.
@item android
The Open Handset Alliance's Android operating system.
@item ms-dos
Microsoft's DOS@. Emacs compiled with DJGPP for MS-DOS binds
@code{system-type} to @code{ms-dos} even when you run it on MS-Windows.

View file

@ -185,6 +185,24 @@ respective remote host. In case of a local @code{default-directory},
the function returns just the value of the variable @code{exec-path}.
@end defun
@cindex programs distributed with Emacs, starting
@vindex ctags-program-name
@vindex etags-program-name
@vindex hexl-program-name
@vindex emacsclient-program-name
@vindex movemail-program-name
@vindex ebrowse-program-manem
When starting a program that is part of the Emacs distribution,
you must take into account that the program may have been renamed in
order to comply with executable naming restrictions present on the
system.
Instead of starting @command{ctags}, for example, you should specify
the value of @code{ctags-program-name} instead. Likewise, instead of
starting @command{movemail}, you must start
@code{movemail-program-name}, and the same goes for @command{etags},
@command{hexl}, @command{emacsclient}, and @command{ebrowse}.
@node Shell Arguments
@section Shell Arguments
@cindex arguments for shell commands

View file

@ -1099,6 +1099,39 @@ Please refer to the LLDB reference on the web for more information
about LLDB. If you already know GDB, you will also find a mapping
from GDB commands to corresponding LLDB commands there.
** Debugging Emacs on Android.
Attaching GDB to Emacs running inside the Android application setup
requires a special script found in the java/ directory, and a suitable
GDB server binary to be present on the Android device, which is
present on the free versions of Android. Connecting to the device
also requires the `adb' (Android Debug Bridge) utility, and telling
the Android system to resume the Emacs process after startup requires
the Java debugger (jdb).
If all three of those tools are present, simply run (from the Emacs
source directory):
../java/debug.sh -- [any extra arguments you wish to pass to gdb]
After which, upon waiting a while, the GDB prompt will show up.
If Emacs crashes and "JNI ERROR" shows up in the Android system log,
then placing a breakpoint on:
break art::JavaVMExt::JniAbort
will let you find the source of the crash.
If there is no `gdbserver' binary present on the device, then you can
specify one to upload, like so:
../java/debug.sh --gdbserver /path/to/gdbserver
In addition, when Emacs runs as a 64-bit process on a system
supporting both 64 and 32-bit binaries, you must specify the path to a
64-bit gdbserver binary.
This file is part of GNU Emacs.

View file

@ -131,6 +131,18 @@ the list at the end of this file.
The earliest release of Haiku that will successfully compile Emacs
is R1/Beta2. For windowing support, R1/Beta3 or later is required.
** Android
Emacs is known to run on all Android versions from 2.2 onwards, on
Linux kernel 2.26.29 or later.
Android 2.2 has only been tested on ARM. mips64 has not been
tested, but builds. With these exceptions, Emacs is known to run on
all supported versions of Android on all supported machines: arm,
armv7, arm64, x86, x86_64, and mips.
See the file INSTALL.android for detailed installation instructions.
* Obsolete platforms

View file

@ -24,6 +24,12 @@ applies, and please also update docstrings as needed.
* Installation Changes in Emacs 30.1
** Emacs has been ported to the Android operating system.
This requires Emacs to be compiled on another computer. The Android
NDK, SDK, and a suitable Java compiler must also be installed.
See the file 'java/INSTALL' for more details.
* Startup Changes in Emacs 30.1
@ -46,6 +52,12 @@ compositing manager, Emacs will now redisplay such a frame even though
'frame-visible-p' returns nil or 'icon' for it. This can happen, for
example, as part of preview for iconified frames.
---
** New user option 'menu-bar-close-window'.
When non-nil, selecting Close from the File menu or clicking Close in
the tool bar will result in the current window being closed, if
possible.
+++
** 'write-region-inhibit-fsync' now defaults to t in interactive mode,
as it has in batch mode since Emacs 24.
@ -79,6 +91,12 @@ plus, minus, check-mark, start, etc.
* Editing Changes in Emacs 30.1
+++
** Emacs now has better support for touchscreen events.
Many touch screen gestures are now implemented, as is support for
tapping buttons and opening menus.
---
** On X, Emacs now supports input methods which perform "string conversion".
This means an input method can now ask Emacs to delete text
@ -380,6 +398,25 @@ hooks named after the feature name, like 'esh-mode-unload-hook'.
* Lisp Changes in Emacs 30.1
+++
** New variables describing the names of built in programs.
The new variables 'ctags-program-name', 'ebrowse-program-name',
'etags-program-name', 'hexl-program-name', 'emacsclient-program-name'
and 'movemail-program-name' should be used instead of "ctags",
"ebrowse", "etags", "hexl", and "emacsclient", when starting one of
these built in programs in a subprocess.
+++
** 'x-popup-menu' now understands touch screen events.
When a 'touchscreen-begin' or 'touchscreen-end' event is passed as the
POSITION argument, it will behave as if that event was a mouse event.
+++
** New functions for handling touch screen events.
The new functions 'touch-screen-track-tap' and
'touch-screen-track-drag' handle tracking common touch screen gestures
from within a command.
** New variable 'inhibit-auto-fill' to temporarily prevent auto-fill.
** Functions and variables to transpose sexps

View file

@ -3301,6 +3301,56 @@ Compose key to stop working.
On X Windows, users should not use Emacs configured with PGTK, since
this and many other problems do not exist on the regular X builds.
* Runtime problems specific to Android
** Text displayed in the default monospace font looks horrible.
Droid Sans Mono (the default Monospace font which comes with Android)
comes with instruction code designed for Microsoft's proprietary
TrueType font scaler. When this code is executed by Emacs to instruct
a glyph containing more than one component, it tries to address
"reference points" which are set to the values of two extra "phantom
points" in the glyph, that are a proprietary extension of the MS font
scaler.
Emacs does not support these extensions, and as a result characters
such as
ĥ
display incorrectly, with the right most edge of the `h' component
stretched very far out to the right, on some low density displays.
The solution is to replace the MS-specific hinting code in Droid Sans
Mono with automatically generated code from the FreeType project's
"ttfautohint" program. First, extract
'/system/fonts/DroidSansMono.ttf' from your device:
$ adb pull /system/fonts/DroidSansMono.ttf
/system/fonts/DroidSansMono.ttf: 1 file pulled, 0 skipped.
23.1 MB/s (90208 bytes in 0.004s)
install the "ttfautohint" program:
http://freetype.org/ttfautohint/
generate a font file with new hinting instructions:
$ ttfautohint DroidSansMono.ttf > DroidSansMono.ttf.rpl
and upload them to your device, either back to /system/fonts (which is
allowed by free versions of Android, such as Replicant):
$ adb root
$ adb remount
$ adb push DroidSansMono.ttf.rpl /system/fonts/DroidSansMono.ttf
or to the user fonts directory described in the "Android Fonts" node
of the Emacs manual. You may want to perform this procedure even if
you are not seeing problems with character display, as the
automatically generated instructions result in superior display
results that are easier to read.
* Build-time problems
** Configuration

140
exec/Makefile.in Normal file
View file

@ -0,0 +1,140 @@
### @configure_input@
# Copyright (C) 2023 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/>.
# Configure build directory information.
srcdir = @srcdir@
VPATH = @srcdir@
builddir = @builddir@
# Set up compilation tools.
CC = @CC@
AS = @AS@
LD = @LD@
M4 = @M4@
CPP = @CPP@
ASFLAGS = @ASFLAGS@
ARFLAGS = @ARFLAGS@
CFLAGS = @CFLAGS@
CPPFLAGS = @CPPFLAGS@
LDFLAGS = @LDFLAGS@
LOADERFLAGS = @LOADERFLAGS@
FIND_DELETE = @FIND_DELETE@
# Set up object files.
LOADER = @exec_loader@
OBJS = @OBJS@
LOADOBJS = $(patsubst %.s,%.o,$(LOADER))
# Set up automatic dependency tracking.
AUTO_DEPEND = @AUTO_DEPEND@
DEPDIR = deps
ifeq ($(AUTO_DEPEND),yes)
DEPFLAGS = -MMD -MF $(DEPDIR)/$*.d -MP
-include $(OBJS:%.o=$(DEPDIR)/%.d)
-include $(DEPDIR)/test.d
-include $(DEPDIR)/exec1.d
else
DEPFLAGS =
include $(srcdir)/deps.mk
endif
# Set up the appropriate targets.
all: libexec.a loader
# Set up automatic Makefile regeneration.
$(srcdir)/configure: $(srcdir)/configure.ac
cd $(srcdir) && autoreconf
config.status: $(srcdir)/configure
if [ -x config.status ]; then \
./config.status --recheck; \
else \
$(srcdir)/configure; \
fi
Makefile: config.status Makefile.in
MAKE="$(MAKE)" ./config.status
# Set up rules to build targets.
.SUFFIXES: .c .s
.c.o:
$(CC) -c $(CPPFLAGS) $(CFLAGS) $(DEPFLAGS) -I. -I$(srcdir) $< -o $@
.s.o:
$(M4) $< > $(notdir $<).s
$(AS) $(ASFLAGS) $(notdir $<).s -o $@
# Set up dependencies for config-mips.m4.
config-mips.m4: config-mips.m4.in
cd $(srcdir) && ./config.status $@
$(LOADOBJS): config-mips.m4
# Set up rules to build libexec.a.
libexec.a: $(OBJS)
$(AR) cru $(ARFLAGS) $@ $^
# And loader.
loader: $(LOADOBJS)
$(LD) -o $@ $(LOADERFLAGS) $(LOADOBJS)
# And test.
test: test.o libexec.a
$(CC) $(LDFLAGS) $< libexec.a -o $@
# And exec1.
exec1: exec1.o libexec.a
$(CC) $(LDFLAGS) $< libexec.a -o $@
# Set up targets for cleaning.
.PHONY: clean distclean maintainer-clean extraclean bootstrap-clean
clean:
rm -f *.o *.a loader test *.s.s
ifeq ($(AUTO_DEPEND),yes)
rm -rf deps/*.d
endif
distclean: clean
rm -f Makefile config.status config.h config-mips.m4
maintainer-clean: distclean
### This doesn't actually appear in the coding standards, but Karl
### says GCC supports it, and that's where the configuration part of
### the coding standards seem to come from. It's like distclean, but
### it deletes backup and autosave files too.
extraclean: maintainer-clean
-rm -f config-tmp-* $(srcdir)/aclocal.m4 $(srcdir)/configure \
$(srcdir)/src/config.in
-[ "$(srcdir)" = "." ] || \
find $(srcdir) '(' -name '*~' -o -name '#*' ')' $(FIND_DELETE)
-find . '(' -name '*~' -o -name '#*' ')' $(FIND_DELETE)
bootstrap-clean: extraclean

3
exec/README Normal file
View file

@ -0,0 +1,3 @@
This directory holds the source code to a library used to replace the
`execve' and `execveat' system calls, used by the Android port of
Emacs to start executables without intervention from the system.

42
exec/config-mips.m4.in Normal file
View file

@ -0,0 +1,42 @@
dnl Assembler templates for MIPS computers.
dnl
dnl Copyright (C) 2023 Free Software Foundation, Inc.
dnl
dnl This file is part of GNU Emacs.
dnl
dnl GNU Emacs is free software: you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
dnl the Free Software Foundation, either version 3 of the License, or
dnl (at your option) any later version.
dnl
dnl GNU Emacs is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
dnl GNU General Public License for more details.
dnl
dnl You should have received a copy of the GNU General Public License
dnl along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
define(`SYSCALL_open', `ifelse(`@MIPS_N32@',`yes',`6002',`4005')')
define(`SYSCALL_close', `ifelse(`@MIPS_N32@',`yes',`6003',`4006')')
define(`SYSCALL_mmap', `ifelse(`@MIPS_N32@',`yes',`6009',`4090')')
define(`SYSCALL_nanosleep', `ifelse(`@MIPS_N32@',`yes',`6034',`4166')')
define(`SYSCALL_exit', `ifelse(`@MIPS_N32@',`yes',`6058',`4001')')
define(`SYSCALL_prctl', `ifelse(`@MIPS_N32@',`yes',`6153',`4192')')
define(`SYSCALL', `ifelse(`@MIPS_N32@',`yes',` move $a4, $1
move $a5, $2
move $a6, $3
move $a7, $4',` addi $sp, -32
sw $1, 16($sp)
sw $2, 20($sp)
sw $3, 24($sp)
sw $4, 28($sp)')')
define(`RESTORE', `ifelse(`@MIPS_N32@',`yes',` nop',` addi $sp, 32')')
dnl For mips64. Some assemblers don't want to assemble `daddi'.
define(`DADDI2', `ifelse(`@DADDI_BROKEN@',`yes',` li $at, $2
dadd $1, $1, $at',` daddi $1, $2')')
define(`DADDI3', `ifelse(`@DADDI_BROKEN@',`yes',` li $at, $3
dadd $1, $2, $at',` daddi $1, $2, $3')')

1768
exec/config.guess vendored Executable file

File diff suppressed because it is too large Load diff

358
exec/config.h.in Normal file
View file

@ -0,0 +1,358 @@
/* config.h.in. Generated from configure.ac by autoheader. */
/* Copyright (C) 2023 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/>. */
/* Define to number of reserved bytes past the stack frame. */
#undef ABI_RED_ZONE
/* Define if building universal (internal helper macro) */
#undef AC_APPLE_UNIVERSAL_BUILD
/* Define to number of the `clone3' system call. */
#undef CLONE3_SYSCALL
/* Define to number of the `clone' system call. */
#undef CLONE_SYSCALL
/* Virtual address for loading PIC executables */
#undef EXECUTABLE_BASE
/* Define to 1 if the system utilizes 64-bit ELF. */
#undef EXEC_64
/* Define to number of the `exec' system call. */
#undef EXEC_SYSCALL
/* Define to 1 if you have the declaration of `stpcpy', and to 0 if you don't.
*/
#undef HAVE_DECL_STPCPY
/* Define to 1 if you have the declaration of `stpncpy', and to 0 if you
don't. */
#undef HAVE_DECL_STPNCPY
/* Define to 1 if you have the `getpagesize' function. */
#undef HAVE_GETPAGESIZE
/* Define to 1 if you have the <inttypes.h> header file. */
#undef HAVE_INTTYPES_H
/* Define to 1 if you have the <minix/config.h> header file. */
#undef HAVE_MINIX_CONFIG_H
/* Define to 1 if process_vm_readv is available. */
#undef HAVE_PROCESS_VM
/* Define to 1 if `si_syscall' is a member of `siginfo_t'. */
#undef HAVE_SIGINFO_T_SI_SYSCALL
/* Define to 1 if stdbool.h conforms to C99. */
#undef HAVE_STDBOOL_H
/* Define to 1 if you have the <stdint.h> header file. */
#undef HAVE_STDINT_H
/* Define to 1 if you have the <stdio.h> header file. */
#undef HAVE_STDIO_H
/* Define to 1 if you have the <stdlib.h> header file. */
#undef HAVE_STDLIB_H
/* Define to 1 if you have the `stpcpy' function. */
#undef HAVE_STPCPY
/* Define to 1 if you have the `stpncpy' function. */
#undef HAVE_STPNCPY
/* Define to 1 if you have the <strings.h> header file. */
#undef HAVE_STRINGS_H
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
/* Define to 1 if you have the <sys/param.h> header file. */
#undef HAVE_SYS_PARAM_H
/* Define to 1 if you have the <sys/stat.h> header file. */
#undef HAVE_SYS_STAT_H
/* Define to 1 if you have the <sys/types.h> header file. */
#undef HAVE_SYS_TYPES_H
/* Define to 1 if you have the <sys/uio.h> header file. */
#undef HAVE_SYS_UIO_H
/* Define to 1 if the system has the type `uintptr_t'. */
#undef HAVE_UINTPTR_T
/* Define to 1 if you have the <unistd.h> header file. */
#undef HAVE_UNISTD_H
/* Define to 1 if you have the <wchar.h> header file. */
#undef HAVE_WCHAR_H
/* Define to 1 if the system has the type `_Bool'. */
#undef HAVE__BOOL
/* Virtual address for loading PIC interpreters */
#undef INTERPRETER_BASE
/* Define to 1 if MIPS NABI calling convention is being used. */
#undef MIPS_NABI
/* Define to the address where bug reports for this package should be sent. */
#undef PACKAGE_BUGREPORT
/* Define to the full name of this package. */
#undef PACKAGE_NAME
/* Define to the full name and version of this package. */
#undef PACKAGE_STRING
/* Define to the one symbol short name of this package. */
#undef PACKAGE_TARNAME
/* Define to the home page for this package. */
#undef PACKAGE_URL
/* Define to the version of this package. */
#undef PACKAGE_VERSION
/* Define to number of the `readlinkat' system call. */
#undef READLINKAT_SYSCALL
/* Define to number of the `readlink' system call. */
#undef READLINK_SYSCALL
/* Define to 1 if the library is used within a signal handler. */
#undef REENTRANT
/* Define to 1 if the stack grows downwards. */
#undef STACK_GROWS_DOWNWARDS
/* Define to register holding the stack pointer. */
#undef STACK_POINTER
/* Define to 1 if all of the C90 standard headers exist (not just the ones
required in a freestanding environment). This macro is provided for
backward compatibility; new code need not use it. */
#undef STDC_HEADERS
/* Define to register holding arg1 to system calls. */
#undef SYSCALL_ARG1_REG
/* Define to register holding arg2 to system calls. */
#undef SYSCALL_ARG2_REG
/* Define to register holding arg3 to system calls. */
#undef SYSCALL_ARG3_REG
/* Define to register holding arg0 to system calls. */
#undef SYSCALL_ARG_REG
/* Define to header holding system call numbers. */
#undef SYSCALL_HEADER
/* Define to register holding the system call number. */
#undef SYSCALL_NUM_REG
/* Define to register holding value of system calls. */
#undef SYSCALL_RET_REG
/* Define to header holding USER_REGS_STRUCT. */
#undef USER_HEADER
/* Define to structure holding user registers. */
#undef USER_REGS_STRUCT
/* Define to word type used by tracees. */
#undef USER_WORD
/* Enable extensions on AIX 3, Interix. */
#ifndef _ALL_SOURCE
# undef _ALL_SOURCE
#endif
/* Enable general extensions on macOS. */
#ifndef _DARWIN_C_SOURCE
# undef _DARWIN_C_SOURCE
#endif
/* Enable general extensions on Solaris. */
#ifndef __EXTENSIONS__
# undef __EXTENSIONS__
#endif
/* Enable GNU extensions on systems that have them. */
#ifndef _GNU_SOURCE
# undef _GNU_SOURCE
#endif
/* Enable X/Open compliant socket functions that do not require linking
with -lxnet on HP-UX 11.11. */
#ifndef _HPUX_ALT_XOPEN_SOCKET_API
# undef _HPUX_ALT_XOPEN_SOCKET_API
#endif
/* Identify the host operating system as Minix.
This macro does not affect the system headers' behavior.
A future release of Autoconf may stop defining this macro. */
#ifndef _MINIX
# undef _MINIX
#endif
/* Enable general extensions on NetBSD.
Enable NetBSD compatibility extensions on Minix. */
#ifndef _NETBSD_SOURCE
# undef _NETBSD_SOURCE
#endif
/* Enable OpenBSD compatibility extensions on NetBSD.
Oddly enough, this does nothing on OpenBSD. */
#ifndef _OPENBSD_SOURCE
# undef _OPENBSD_SOURCE
#endif
/* Define to 1 if needed for POSIX-compatible behavior. */
#ifndef _POSIX_SOURCE
# undef _POSIX_SOURCE
#endif
/* Define to 2 if needed for POSIX-compatible behavior. */
#ifndef _POSIX_1_SOURCE
# undef _POSIX_1_SOURCE
#endif
/* Enable POSIX-compatible threading on Solaris. */
#ifndef _POSIX_PTHREAD_SEMANTICS
# undef _POSIX_PTHREAD_SEMANTICS
#endif
/* Enable extensions specified by ISO/IEC TS 18661-5:2014. */
#ifndef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
# undef __STDC_WANT_IEC_60559_ATTRIBS_EXT__
#endif
/* Enable extensions specified by ISO/IEC TS 18661-1:2014. */
#ifndef __STDC_WANT_IEC_60559_BFP_EXT__
# undef __STDC_WANT_IEC_60559_BFP_EXT__
#endif
/* Enable extensions specified by ISO/IEC TS 18661-2:2015. */
#ifndef __STDC_WANT_IEC_60559_DFP_EXT__
# undef __STDC_WANT_IEC_60559_DFP_EXT__
#endif
/* Enable extensions specified by ISO/IEC TS 18661-4:2015. */
#ifndef __STDC_WANT_IEC_60559_FUNCS_EXT__
# undef __STDC_WANT_IEC_60559_FUNCS_EXT__
#endif
/* Enable extensions specified by ISO/IEC TS 18661-3:2015. */
#ifndef __STDC_WANT_IEC_60559_TYPES_EXT__
# undef __STDC_WANT_IEC_60559_TYPES_EXT__
#endif
/* Enable extensions specified by ISO/IEC TR 24731-2:2010. */
#ifndef __STDC_WANT_LIB_EXT2__
# undef __STDC_WANT_LIB_EXT2__
#endif
/* Enable extensions specified by ISO/IEC 24747:2009. */
#ifndef __STDC_WANT_MATH_SPEC_FUNCS__
# undef __STDC_WANT_MATH_SPEC_FUNCS__
#endif
/* Enable extensions on HP NonStop. */
#ifndef _TANDEM_SOURCE
# undef _TANDEM_SOURCE
#endif
/* Enable X/Open extensions. Define to 500 only if necessary
to make mbstate_t available. */
#ifndef _XOPEN_SOURCE
# undef _XOPEN_SOURCE
#endif
/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
significant byte first (like Motorola and SPARC, unlike Intel). */
#if defined AC_APPLE_UNIVERSAL_BUILD
# if defined __BIG_ENDIAN__
# define WORDS_BIGENDIAN 1
# endif
#else
# ifndef WORDS_BIGENDIAN
# undef WORDS_BIGENDIAN
# endif
#endif
/* Define for Solaris 2.5.1 so the uint32_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
#undef _UINT32_T
/* Define for Solaris 2.5.1 so the uint64_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
#undef _UINT64_T
/* Define for Solaris 2.5.1 so the uint8_t typedef from <sys/synch.h>,
<pthread.h>, or <semaphore.h> is not used. If the typedef were allowed, the
#define below would cause a syntax error. */
#undef _UINT8_T
/* Define as a signed integer type capable of holding a process identifier. */
#undef pid_t
/* Define to `unsigned int' if <sys/types.h> does not define. */
#undef size_t
/* Define to `int' if <sys/types.h> does not define. */
#undef ssize_t
/* Define to the type of an unsigned integer type of width exactly 16 bits if
such a type exists and the standard includes do not define it. */
#undef uint16_t
/* Define to the type of an unsigned integer type of width exactly 32 bits if
such a type exists and the standard includes do not define it. */
#undef uint32_t
/* Define to the type of an unsigned integer type of width exactly 64 bits if
such a type exists and the standard includes do not define it. */
#undef uint64_t
/* Define to the type of an unsigned integer type of width exactly 8 bits if
such a type exists and the standard includes do not define it. */
#undef uint8_t
/* Define to the type of an unsigned integer type wide enough to hold a
pointer, if such a type exists, and if the system does not define it. */
#undef uintptr_t
#ifdef HAVE_STDBOOL_H
# include <stdbool.h>
#else
# ifndef HAVE__BOOL
# ifdef __cplusplus
typedef bool _Bool;
# else
# define _Bool signed char
# endif
# endif
# define bool _Bool
# define false 0
# define true 1
# define __bool_true_false_are_defined 1
#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif /* HAVE_SYS_PARAM_H */
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif /* MAX */
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif /* MIN */

1890
exec/config.sub vendored Executable file

File diff suppressed because it is too large Load diff

537
exec/configure.ac Normal file
View file

@ -0,0 +1,537 @@
dnl Autoconf script for GNU Emacs's exec library.
dnl To rebuild the 'configure' script from this, execute the command
dnl autoconf
dnl in the directory containing this script.
dnl If you changed any AC_DEFINES, also run autoheader.
dnl
dnl Copyright (C) 2023 Free Software Foundation, Inc.
dnl
dnl This file is part of GNU Emacs.
dnl
dnl GNU Emacs is free software: you can redistribute it and/or modify
dnl it under the terms of the GNU General Public License as published by
dnl the Free Software Foundation, either version 3 of the License, or
dnl (at your option) any later version.
dnl
dnl GNU Emacs is distributed in the hope that it will be useful,
dnl but WITHOUT ANY WARRANTY; without even the implied warranty of
dnl MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
dnl GNU General Public License for more details.
dnl
dnl You should have received a copy of the GNU General Public License
dnl along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
AC_PREREQ([2.65])
AC_INIT([libexec], [30.0.50], [bug-gnu-emacs@gnu.org], [],
[https://www.gnu.org/software/emacs/])
AH_TOP([/* Copyright (C) 2023 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/>. */])
AC_ARG_WITH([reentrancy],
[AS_HELP_STRING([--with-reentrancy],
[Generate library which can be used within a signal handler.])],
[AC_DEFINE([REENTRANT], [1])])
AC_USE_SYSTEM_EXTENSIONS
AC_PROG_CC
AC_PROG_CPP
AC_PROG_INSTALL
AC_TYPE_UINT8_T
AC_TYPE_UINT16_T
AC_TYPE_UINT32_T
AC_TYPE_UINT64_T
AC_TYPE_UINTPTR_T
AC_TYPE_SIZE_T
AC_TYPE_SSIZE_T
AC_TYPE_PID_T
AC_HEADER_STDBOOL
AC_CHECK_FUNCS([getpagesize stpcpy stpncpy])
AC_CHECK_DECLS([stpcpy, stpncpy])
AC_CHECK_FUNC([process_vm_readv],
[AC_CHECK_FUNC([process_vm_writev],
[AC_CHECK_DECL([process_vm_readv],
[AC_DEFINE([HAVE_PROCESS_VM], [1],
[Define to 1 if process_vm_readv is available.])],
[], [[
#include <sys/uio.h>
]])])])
AC_CHECK_HEADERS([sys/param.h sys/uio.h])
AC_CHECK_MEMBERS([siginfo_t.si_syscall], [], [],
[[
#include <signal.h>
]])
AH_BOTTOM([
#ifdef HAVE_STDBOOL_H
# include <stdbool.h>
#else
# ifndef HAVE__BOOL
# ifdef __cplusplus
typedef bool _Bool;
# else
# define _Bool signed char
# endif
# endif
# define bool _Bool
# define false 0
# define true 1
# define __bool_true_false_are_defined 1
#endif
#ifdef HAVE_SYS_PARAM_H
#include <sys/param.h>
#endif /* HAVE_SYS_PARAM_H */
#ifndef MAX
#define MAX(a, b) ((a) > (b) ? (a) : (b))
#endif /* MAX */
#ifndef MIN
#define MIN(a, b) ((a) < (b) ? (a) : (b))
#endif /* MIN */
])
AC_C_BIGENDIAN
AH_TEMPLATE([SYSCALL_HEADER], [Define to header holding system call numbers.])
AH_TEMPLATE([USER_HEADER], [Define to header holding USER_REGS_STRUCT.])
AH_TEMPLATE([USER_REGS_STRUCT], [Define to structure holding user registers.])
AH_TEMPLATE([SYSCALL_NUM_REG], [Define to register holding the system call number.])
AH_TEMPLATE([SYSCALL_ARG_REG], [Define to register holding arg0 to system calls.])
AH_TEMPLATE([SYSCALL_ARG1_REG], [Define to register holding arg1 to system calls.])
AH_TEMPLATE([SYSCALL_ARG2_REG], [Define to register holding arg2 to system calls.])
AH_TEMPLATE([SYSCALL_ARG3_REG], [Define to register holding arg3 to system calls.])
AH_TEMPLATE([SYSCALL_RET_REG], [Define to register holding value of system calls.])
AH_TEMPLATE([STACK_POINTER], [Define to register holding the stack pointer.])
AH_TEMPLATE([EXEC_SYSCALL], [Define to number of the `exec' system call.])
AH_TEMPLATE([USER_WORD], [Define to word type used by tracees.])
AH_TEMPLATE([EXEC_64], [Define to 1 if the system utilizes 64-bit ELF.])
AH_TEMPLATE([STACK_GROWS_DOWNWARDS], [Define to 1 if the stack grows downwards.])
AH_TEMPLATE([ABI_RED_ZONE], [Define to number of reserved bytes past the stack frame.])
AH_TEMPLATE([EXECUTABLE_BASE], [Virtual address for loading PIC executables])
AH_TEMPLATE([INTERPRETER_BASE], [Virtual address for loading PIC interpreters])
AH_TEMPLATE([CLONE_SYSCALL], [Define to number of the `clone' system call.])
AH_TEMPLATE([CLONE3_SYSCALL], [Define to number of the `clone3' system call.])
AH_TEMPLATE([READLINK_SYSCALL], [Define to number of the `readlink' system call.])
AH_TEMPLATE([READLINKAT_SYSCALL], [Define to number of the `readlinkat' system call.])
AH_TEMPLATE([REENTRANT], [Define to 1 if the library is used within a signal handler.])
AC_CANONICAL_HOST
# Check whether or not sys/user exists. If it doesn't, try
# asm/user.h, and croak if that doesn't exist either.
AS_CASE([$host], [*mips*], [], [*],
[AC_CHECK_HEADER([sys/user.h], [user_h="<sys/user.h>"],
[AC_CHECK_HEADER([asm/user.h], [user_h="<asm/user.h>"],
[AC_MSG_ERROR([Can not find working user.h])])])])
# Look for required tools.
AC_ARG_VAR([M4], [`m4' preprocessor command.])
AC_ARG_VAR([AS], [`as' assembler command.])
AC_ARG_VAR([LD], [`ld' linker command.])
# Check for a working m4.
AC_CHECK_PROGS([M4], [gm4 m4],
[AC_MSG_ERROR([Cannot find m4])])
# Check for a working assembler.
AC_CHECK_TOOL([AS], [as],
[AC_MSG_ERROR([Cannot find a working assembler])])
# And ar.
AC_CHECK_TOOL([AR], [ar],
[AC_MSG_ERROR([Cannot find a working ar])])
# And ld.
AC_CHECK_TOOL([LD], [ld],
[AC_MSG_ERROR([Cannot find a working linker])])
# Now check if ld is a C compiler.
LDPREFIX=
AC_CACHE_CHECK([whether ld is a C compiler],
[exec_cv_ld_is_cc],
[cat <<_ACEOF > conftest.c
AC_LANG_PROGRAM(,)
_ACEOF
exec_cv_ld_is_cc=yes
$LD -c conftest.c -o conftest.$OBJEXT >&AS_MESSAGE_LOG_FD 2>&1 \
|| exec_cv_ld_is_cc=no
rm -f conftest.c conftest.$OBJEXT])
# And if as is a C compiler.
AC_CACHE_CHECK([whether as is a C compiler],
[exec_cv_as_is_cc],
[cat <<_ACEOF > conftest.c
AC_LANG_PROGRAM(,)
_ACEOF
exec_cv_as_is_cc=yes
$AS -c conftest.c -o conftest.$OBJEXT >&AS_MESSAGE_LOG_FD 2>&1 \
|| exec_cv_as_is_cc=no
rm -f conftest.c conftest.$OBJEXT])
# If ld is a C compiler, pass `-nostdlib', `-nostartfiles', and
# `-static'. Also, set LDPREFIX to -Wl,
AS_IF([test "x$exec_cv_ld_is_cc" = "xyes"],
[LOADERFLAGS="$LOADERFLAGS -nostdlib -nostartfiles -static"
LDPREFIX=-Wl,])
# If as is a C compiler, add `-c' to ASFLAGS.
AS_IF([test "x$exec_cv_as_is_cc" = "xyes"],
[ASFLAGS="$ASFLAGS -c"])
AC_DEFUN([exec_CHECK_LINUX_CLONE3],
[
AC_CHECK_DECL([__NR_clone3],
[AC_DEFINE([CLONE3_SYSCALL], [__NR_clone3])],
[], [[
#include <asm/unistd.h>
]])
])
AC_DEFUN([exec_CHECK_MIPS_NABI],
[
AC_CACHE_CHECK([whether MIPS NABI calling convention is used],
[exec_cv_mips_nabi],
[AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[
#include <sgidefs.h>
]], [[
#ifndef __mips64__
#if _MIPS_SIM == _ABIO32
OABI in use.
#endif /* _MIPS_SIM == _ABIO32 */
#endif /* !__mips64__ */
]])], [exec_cv_mips_nabi=yes],
[exec_cv_mips_nabi=no])])
dnl mips64 systems use N64 calling convention, a variant of nabi
dnl calling convention.
AS_IF([test "x$exec_cv_mips_nabi" != "xno"],
[AC_DEFINE([MIPS_NABI], [1],
[Define to 1 if MIPS NABI calling convention is being used.])],
[OBJS="$OBJS mipsfpu.o"])
])
# Determine the system type and define appropriate macros.
exec_loader=
is_mips=
OBJS="exec.o trace.o"
DADDI_BROKEN=no
AS_CASE([$host], [x86_64-*linux*],
[AC_CHECK_MEMBER([struct user_regs_struct.rdi],
[AC_DEFINE([SYSCALL_HEADER], [<asm/unistd.h>])
AC_DEFINE_UNQUOTED([USER_HEADER], [$user_h])
AC_DEFINE([USER_REGS_STRUCT], [struct user_regs_struct])
AC_DEFINE([SYSCALL_NUM_REG], [orig_rax])
AC_DEFINE([SYSCALL_RET_REG], [rax])
AC_DEFINE([SYSCALL_ARG_REG], [rdi])
AC_DEFINE([SYSCALL_ARG1_REG], [rsi])
AC_DEFINE([SYSCALL_ARG2_REG], [rdx])
AC_DEFINE([SYSCALL_ARG3_REG], [r10])
AC_DEFINE([STACK_POINTER], [rsp])
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
AC_DEFINE([USER_WORD], [uintptr_t])
AC_DEFINE([EXEC_64], [1])
AC_DEFINE([ABI_RED_ZONE], [128])
AC_DEFINE([EXECUTABLE_BASE], [0x555555554000])
AC_DEFINE([INTERPRETER_BASE], [0x600000000000])
AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
exec_CHECK_LINUX_CLONE3
# Make sure the loader doesn't conflict with other position
# dependent code.
LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x200000000000"
exec_loader=loader-x86_64.s],
[AC_MSG_ERROR([Missing `rdi' in user_regs_struct])],
[[
#include $user_h
]])], [i[[34567]]86-*linux*],
[AC_CHECK_MEMBER([struct user_regs_struct.edi],
[AC_DEFINE([SYSCALL_HEADER], [<asm/unistd.h>])
AC_DEFINE_UNQUOTED([USER_HEADER], [$user_h])
AC_DEFINE([USER_REGS_STRUCT], [struct user_regs_struct])
AC_DEFINE([SYSCALL_NUM_REG], [orig_eax])
AC_DEFINE([SYSCALL_RET_REG], [eax])
AC_DEFINE([SYSCALL_ARG_REG], [ebx])
AC_DEFINE([SYSCALL_ARG1_REG], [ecx])
AC_DEFINE([SYSCALL_ARG2_REG], [edx])
AC_DEFINE([SYSCALL_ARG3_REG], [esi])
AC_DEFINE([STACK_POINTER], [esp])
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
AC_DEFINE([USER_WORD], [uintptr_t])
AC_DEFINE([EXECUTABLE_BASE], [0x0f000000])
AC_DEFINE([INTERPRETER_BASE], [0xaf000000])
AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
exec_CHECK_LINUX_CLONE3
# Make sure the loader doesn't conflict with other position
# dependent code.
LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0xa0000000"
exec_loader=loader-x86.s],
[AC_MSG_ERROR([Missing `edi' in user_regs_struct])],
[[
#include $user_h
]])], [aarch64-*linux*],
[AC_CHECK_MEMBER([struct user_regs_struct.sp],
[AC_DEFINE([SYSCALL_HEADER], [<asm/unistd.h>])
AC_DEFINE_UNQUOTED([USER_HEADER], [$user_h])
AC_DEFINE([USER_REGS_STRUCT], [struct user_regs_struct])
AC_DEFINE([SYSCALL_NUM_REG], [[regs[8]]])
AC_DEFINE([SYSCALL_RET_REG], [[regs[0]]])
AC_DEFINE([SYSCALL_ARG_REG], [[regs[0]]])
AC_DEFINE([SYSCALL_ARG1_REG], [[regs[1]]])
AC_DEFINE([SYSCALL_ARG2_REG], [[regs[2]]])
AC_DEFINE([SYSCALL_ARG3_REG], [[regs[3]]])
AC_DEFINE([STACK_POINTER], [sp])
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
AC_DEFINE([USER_WORD], [uintptr_t])
AC_DEFINE([EXEC_64], [1])
AC_DEFINE([EXECUTABLE_BASE], [0x3000000000])
AC_DEFINE([INTERPRETER_BASE], [0x3f00000000])
AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
# Note that aarch64 has no `readlink'.
AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
exec_CHECK_LINUX_CLONE3
# Make sure the loader doesn't conflict with other position
# dependent code. ARM places rather significant restrictions on
# virtual addresses for a 64 bit architecture.
LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x2000000000"
exec_loader=loader-aarch64.s],
[AC_MSG_ERROR([Missing `sp' in user_regs_struct])],
[[
#include $user_h
]])], [arm*linux*eabi* | armv7*linux*],
[AC_CHECK_MEMBER([struct user_regs.uregs],
[AC_DEFINE([SYSCALL_HEADER], [<asm/unistd.h>])
AC_DEFINE_UNQUOTED([USER_HEADER], [$user_h])
AC_DEFINE([USER_REGS_STRUCT], [struct user_regs])
AC_DEFINE([SYSCALL_NUM_REG], [[uregs[7]]])
AC_DEFINE([SYSCALL_RET_REG], [[uregs[0]]])
AC_DEFINE([SYSCALL_ARG_REG], [[uregs[0]]])
AC_DEFINE([SYSCALL_ARG1_REG], [[uregs[1]]])
AC_DEFINE([SYSCALL_ARG2_REG], [[uregs[2]]])
AC_DEFINE([SYSCALL_ARG3_REG], [[uregs[3]]])
AC_DEFINE([STACK_POINTER], [[uregs[13]]])
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
AC_DEFINE([USER_WORD], [uintptr_t])
AC_DEFINE([EXECUTABLE_BASE], [0x0f000000])
AC_DEFINE([INTERPRETER_BASE], [0x1f000000])
AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
exec_CHECK_LINUX_CLONE3
LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x20000000"
exec_loader=loader-armeabi.s],
[AC_CHECK_MEMBER([struct pt_regs.uregs],
[AC_DEFINE([SYSCALL_HEADER], [<asm/unistd.h>])
AC_DEFINE_UNQUOTED([USER_HEADER], [<asm/ptrace.h>])
AC_DEFINE([USER_REGS_STRUCT], [struct pt_regs])
AC_DEFINE([SYSCALL_NUM_REG], [[uregs[7]]])
AC_DEFINE([SYSCALL_RET_REG], [[uregs[0]]])
AC_DEFINE([SYSCALL_ARG_REG], [[uregs[0]]])
AC_DEFINE([SYSCALL_ARG1_REG], [[uregs[1]]])
AC_DEFINE([SYSCALL_ARG2_REG], [[uregs[2]]])
AC_DEFINE([SYSCALL_ARG3_REG], [[uregs[3]]])
AC_DEFINE([STACK_POINTER], [[uregs[13]]])
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
AC_DEFINE([USER_WORD], [uintptr_t])
AC_DEFINE([EXECUTABLE_BASE], [0x0f000000])
AC_DEFINE([INTERPRETER_BASE], [0x1f000000])
AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
exec_CHECK_LINUX_CLONE3
LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x20000000"
exec_loader=loader-armeabi.s],
[AC_MSG_ERROR([Missing `uregs' in user_regs_struct or pt_regs])],
[[
#include <asm/ptrace.h>
]])],
[[
#include $user_h
]])], [mipsel*linux*],
[AC_DEFINE([SYSCALL_HEADER], [<asm/unistd.h>])
AC_DEFINE([USER_HEADER], ["mipsel-user.h"])
AC_DEFINE([USER_REGS_STRUCT], [struct mipsel_regs])
AC_DEFINE([SYSCALL_NUM_REG], [[gregs[2]]]) # v0
AC_DEFINE([SYSCALL_RET_REG], [[gregs[4]]]) # a0
AC_DEFINE([SYSCALL_ARG_REG], [[gregs[4]]]) # a0
AC_DEFINE([SYSCALL_ARG1_REG], [[gregs[5]]]) # a1
AC_DEFINE([SYSCALL_ARG2_REG], [[gregs[4]]]) # a2
AC_DEFINE([SYSCALL_ARG3_REG], [[gregs[5]]]) # a3
AC_DEFINE([STACK_POINTER], [[gregs[29]]]) # sp
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
AC_DEFINE([USER_WORD], [uintptr_t])
AC_DEFINE([EXECUTABLE_BASE], [0x0f000000])
AC_DEFINE([INTERPRETER_BASE], [0x1f000000])
AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
AC_CHECK_DECL([_MIPS_SIM], [exec_CHECK_MIPS_NABI],
[AC_MSG_ERROR([_MIPS_SIM could not be determined]),
[[
#include <sgidefs.h>
]]])
exec_CHECK_LINUX_CLONE3
LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x20000000"
is_mips=yes
exec_loader=loader-mipsel.s], [mips64el*linux*],
[AC_DEFINE([SYSCALL_HEADER], [<asm/unistd.h>])
AC_DEFINE([USER_HEADER], ["mipsel-user.h"])
AC_DEFINE([USER_REGS_STRUCT], [struct mipsel_regs])
AC_DEFINE([SYSCALL_NUM_REG], [[gregs[2]]]) # v0
AC_DEFINE([SYSCALL_RET_REG], [[gregs[4]]]) # a0
AC_DEFINE([SYSCALL_ARG_REG], [[gregs[4]]]) # a0
AC_DEFINE([SYSCALL_ARG1_REG], [[gregs[5]]]) # a1
AC_DEFINE([SYSCALL_ARG2_REG], [[gregs[4]]]) # a2
AC_DEFINE([SYSCALL_ARG3_REG], [[gregs[5]]]) # a3
AC_DEFINE([STACK_POINTER], [[gregs[29]]]) # sp
AC_DEFINE([EXEC_SYSCALL], [__NR_execve])
AC_DEFINE([USER_WORD], [uintptr_t])
AC_DEFINE([EXEC_64], [1])
AC_DEFINE([EXECUTABLE_BASE], [0x400000])
AC_DEFINE([INTERPRETER_BASE], [0x3f00000000])
AC_DEFINE([STACK_GROWS_DOWNWARDS], [1])
AC_DEFINE([CLONE_SYSCALL], [__NR_clone])
AC_DEFINE([READLINK_SYSCALL], [__NR_readlink])
AC_DEFINE([READLINKAT_SYSCALL], [__NR_readlinkat])
AC_CACHE_CHECK([whether as understands `daddi'],
[exec_cv_as_daddi],
[exec_cv_as_daddi=no
cat <<_ACEOF >conftest.s
.section text
.global __start
__start:
li $t0, 0
li $t1, 0
daddi $t0, $t1, 1
daddi $t0, $t1, -1
daddi $t0, -1
daddi $t0, 1
_ACEOF
$AS $ASFLAGS conftest.s -o conftest.$OBJEXT \
>&AS_MESSAGE_LOG_FD 2>&1 \
&& exec_cv_as_daddi=yes
rm -f conftest.s conftest.$OBJEXT])
AS_IF([test "x$exec_cv_as_daddi" != "xyes"],
[DADDI_BROKEN=yes])
exec_CHECK_LINUX_CLONE3
exec_CHECK_MIPS_NABI
LOADERFLAGS="$LOADERFLAGS $LDPREFIX-Ttext=0x3e00000000"
is_mips=yes
exec_loader=loader-mips64el.s], [*],
[AC_MSG_ERROR([Please port libexec to $host])])
AC_SUBST([DADDI_BROKEN])
MIPS_N32=$exec_cv_mips_nabi
AC_ARG_VAR([LOADERFLAGS], [Flags used to link the loader.])
AC_ARG_VAR([ARFLAGS], [Flags for the archiver.])
AC_ARG_VAR([ASFLAGS], [Flags for the assembler.])
# Make the assembler optimize for code size. Don't do this on MIPS,
# as the assembler code manages branch delays manually.
AC_CACHE_CHECK([whether as understands -O],
[exec_cv_as_O],
[exec_cv_as_O=no
cat <<_ACEOF >conftest.s
.section text
.global _start
_start:
_ACEOF
$AS $ASFLAGS -O conftest.s -o conftest.$OBJEXT \
>&AS_MESSAGE_LOG_FD 2>&1 \
&& exec_cv_as_O=yes
rm -f conftest.s conftest.$OBJEXT])
AS_IF([test "$exec_cv_as_O" = "yes" \
&& test "$is_mips" != "yes"],
[ASFLAGS="$ASFLAGS -O"])
# Make the assembler generate debug information.
AC_CACHE_CHECK([whether as understands -g],
[exec_cv_as_g],
[exec_cv_as_g=no
cat <<_ACEOF >conftest.s
.section text
.global _start
_start:
_ACEOF
$AS $ASFLAGS -g conftest.s -o conftest.$OBJEXT \
>&AS_MESSAGE_LOG_FD 2>&1 \
&& exec_cv_as_g=yes
rm -f conftest.s conftest.$OBJEXT])
AS_IF([test "$exec_cv_as_g" = "yes"], [ASFLAGS="$ASFLAGS -g"])
# Check for the ability to automatically generate dependencies for C
# source files.
AUTO_DEPEND=no
AS_IF([test "x$GCC" = xyes],
[AC_CACHE_CHECK([whether gcc understands -MMD -MF],
[exec_cv_autodepend],
[SAVE_CFLAGS="$CFLAGS"
CFLAGS="$CFLAGS -MMD -MF deps.d -MP"
AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[]], [[]])],
[exec_cv_autodepend=yes],
[exec_cv_autodepend=no])
CFLAGS="$SAVE_CFLAGS"
test -f deps.d || emacs_cv_autodepend=no
rm -rf deps.d])
AS_IF([test "x$exec_cv_autodepend" = xyes],
[AUTO_DEPEND=yes
AS_MKDIR_P([deps])])])
# Now check for some other stuff.
AC_CACHE_CHECK([for 'find' args to delete a file],
[exec_cv_find_delete],
[AS_IF([touch conftest.tmp && find conftest.tmp -delete 2>/dev/null &&
test ! -f conftest.tmp], [exec_cv_find_delete="-delete"],
[exec_cv_find_delete="-exec rm -f {} ';'"])])
FIND_DELETE=$exec_cv_find_delete
AC_SUBST([FIND_DELETE])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_FILES([Makefile config-mips.m4])
AC_SUBST([AUTO_DEPEND])
AC_SUBST([LOADERFLAGS])
AC_SUBST([ARFLAGS])
AC_SUBST([ASFLAGS])
AC_SUBST([exec_loader])
AC_SUBST([MIPS_N32])
AC_SUBST([OBJS])
AC_OUTPUT

21
exec/deps.mk Normal file
View file

@ -0,0 +1,21 @@
### deps.mk
## Copyright (C) 2023 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/>.
exec.o: exec.h config.h
trace.o: exec.h config.h

1202
exec/exec.c Normal file

File diff suppressed because it is too large Load diff

201
exec/exec.h Normal file
View file

@ -0,0 +1,201 @@
/* Program execution for Emacs.
Copyright (C) 2023 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 _EXEC_H_
#define _EXEC_H_
#ifdef HAVE_STDINT_H
#include <stdint.h>
#endif /* HAVE_STDINT_H */
#include <sys/types.h>
#include USER_HEADER
/* Define a replacement for `uint64_t' if it's not present in the C
library. */
#ifndef UINT64_MAX
typedef struct
{
uint32_t word1;
uint32_t word2;
} xint64_t;
#else /* UINT64_MAX */
typedef uint64_t xint64_t;
#endif /* !UINT64_MAX */
/* 32-bit ELF headers. */
struct elf_header_32
{
unsigned char e_ident[16];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
uint32_t e_entry;
uint32_t e_phoff;
uint32_t e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
};
struct program_header_32
{
uint32_t p_type;
uint32_t p_offset;
uint32_t p_vaddr;
uint32_t p_paddr;
uint32_t p_filesz;
uint32_t p_memsz;
uint32_t p_flags;
uint32_t p_align;
};
struct dt_entry_32
{
uint32_t d_tag;
uint32_t d_val;
};
struct elf_header_64
{
unsigned char e_ident[16];
uint16_t e_type;
uint16_t e_machine;
uint32_t e_version;
xint64_t e_entry;
xint64_t e_phoff;
xint64_t e_shoff;
uint32_t e_flags;
uint16_t e_ehsize;
uint16_t e_phentsize;
uint16_t e_phnum;
uint16_t e_shentsize;
uint16_t e_shnum;
uint16_t e_shstrndx;
};
struct program_header_64
{
uint32_t p_type;
uint32_t p_flags;
xint64_t p_offset;
xint64_t p_vaddr;
xint64_t p_paddr;
xint64_t p_filesz;
xint64_t p_memsz;
xint64_t p_align;
};
struct dt_entry_64
{
xint64_t d_tag;
xint64_t d_val;
};
/* Define some types to the correct values. */
#ifdef EXEC_64
typedef struct elf_header_64 elf_header;
typedef struct program_header_64 program_header;
typedef struct dt_entry_64 dt_entry;
#else /* !EXEC_64 */
typedef struct elf_header_32 elf_header;
typedef struct program_header_32 program_header;
typedef struct dt_entry_32 dt_entry;
#endif /* EXEC_64 */
/* Defined in trace.c. */
/* Structure describing a process being traced. */
struct exec_tracee
{
/* The next process being traced. */
struct exec_tracee *next;
/* The thread ID of this process. */
pid_t pid;
/* Whether or not the tracee is currently waiting for a system call
to complete. */
bool waiting_for_syscall : 1;
/* Whether or not the tracee has been created but is not yet
processed by `handle_clone'. */
bool new_child : 1;
#ifndef REENTRANT
/* Name of the executable being run. */
char *exec_file;
#endif /* !REENTRANT */
};
#ifdef __aarch64__
extern int aarch64_get_regs (pid_t, USER_REGS_STRUCT *);
extern int aarch64_set_regs (pid_t, USER_REGS_STRUCT *, bool);
#endif /* __aarch64__ */
extern USER_WORD user_alloca (struct exec_tracee *, USER_REGS_STRUCT *,
USER_REGS_STRUCT *, USER_WORD);
extern int user_copy (struct exec_tracee *, const unsigned char *,
USER_WORD, USER_WORD);
extern void exec_init (const char *);
extern int tracing_execve (const char *, char *const *,
char *const *);
extern int after_fork (pid_t);
extern pid_t exec_waitpid (pid_t, int *, int);
/* Defined in exec.c. */
extern char *exec_0 (char *, struct exec_tracee *,
size_t *, USER_REGS_STRUCT *);
#endif /* _EXEC_H_ */

94
exec/exec1.c Normal file
View file

@ -0,0 +1,94 @@
/* Program execution for Emacs.
Copyright (C) 2023 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 <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <sys/wait.h>
#include "exec.h"
/* exec1 is a program which takes another program and its arguments,
forks, and executes that program, all while tracing it and its
children to use the program execution mechanism defined in exec.c.
This is necessary to bypass security restrictions which prohibit
Emacs from loading executables from certain directories, by, in
effect, replacing the executable loader in the Linux kernel. */
int
main (int argc, char **argv)
{
pid_t pid, pid1;
extern char **environ;
int wstatus;
pid1 = getpid ();
pid = fork ();
if (!pid)
{
/* Set the process group used to the parent. */
if (setpgid (0, pid1))
perror ("setpgid");
tracing_execve (argv[2], argv + 2, environ);
/* An error occured. Exit with failure. */
exit (127);
}
else
{
/* Provide the file name of the loader. */
exec_init (argv[1]);
if (after_fork (pid))
exit (127);
/* Start waiting for the process to exit. */
while (true)
{
pid1 = exec_waitpid (-1, &wstatus, 0);
/* If the child process exits normally, exit with its status
code. If not, raise the signal that caused it to
exit. */
if (pid == pid1)
{
if (WIFEXITED (wstatus))
exit (WEXITSTATUS (wstatus));
else /* if WIFSIGNALED (wstatus) */
{
raise (WTERMSIG (wstatus));
/* Just in case the signal raised doesn't cause an
exit. */
exit (127);
}
}
/* Otherwise, continue looping. */
}
}
}

541
exec/install-sh Executable file
View file

@ -0,0 +1,541 @@
#!/usr/bin/sh
# install - install a program, script, or datafile
scriptversion=2020-11-14.01; # UTC
# This originates from X11R5 (mit/util/scripts/install.sh), which was
# later released in X11R6 (xc/config/util/install.sh) with the
# following copyright and license.
#
# Copyright (C) 1994 X Consortium
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to
# deal in the Software without restriction, including without limitation the
# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
# sell copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# X CONSORTIUM BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
# AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNEC-
# TION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#
# Except as contained in this notice, the name of the X Consortium shall not
# be used in advertising or otherwise to promote the sale, use or other deal-
# ings in this Software without prior written authorization from the X Consor-
# tium.
#
#
# FSF changes to this file are in the public domain.
#
# Calling this script install-sh is preferred over install.sh, to prevent
# 'make' implicit rules from creating a file called install from it
# when there is no Makefile.
#
# This script is compatible with the BSD install script, but was written
# from scratch.
tab=' '
nl='
'
IFS=" $tab$nl"
# Set DOITPROG to "echo" to test this script.
doit=${DOITPROG-}
doit_exec=${doit:-exec}
# Put in absolute file names if you don't have them in your path;
# or use environment vars.
chgrpprog=${CHGRPPROG-chgrp}
chmodprog=${CHMODPROG-chmod}
chownprog=${CHOWNPROG-chown}
cmpprog=${CMPPROG-cmp}
cpprog=${CPPROG-cp}
mkdirprog=${MKDIRPROG-mkdir}
mvprog=${MVPROG-mv}
rmprog=${RMPROG-rm}
stripprog=${STRIPPROG-strip}
posix_mkdir=
# Desired mode of installed file.
mode=0755
# Create dirs (including intermediate dirs) using mode 755.
# This is like GNU 'install' as of coreutils 8.32 (2020).
mkdir_umask=22
backupsuffix=
chgrpcmd=
chmodcmd=$chmodprog
chowncmd=
mvcmd=$mvprog
rmcmd="$rmprog -f"
stripcmd=
src=
dst=
dir_arg=
dst_arg=
copy_on_change=false
is_target_a_directory=possibly
usage="\
Usage: $0 [OPTION]... [-T] SRCFILE DSTFILE
or: $0 [OPTION]... SRCFILES... DIRECTORY
or: $0 [OPTION]... -t DIRECTORY SRCFILES...
or: $0 [OPTION]... -d DIRECTORIES...
In the 1st form, copy SRCFILE to DSTFILE.
In the 2nd and 3rd, copy all SRCFILES to DIRECTORY.
In the 4th, create DIRECTORIES.
Options:
--help display this help and exit.
--version display version info and exit.
-c (ignored)
-C install only if different (preserve data modification time)
-d create directories instead of installing files.
-g GROUP $chgrpprog installed files to GROUP.
-m MODE $chmodprog installed files to MODE.
-o USER $chownprog installed files to USER.
-p pass -p to $cpprog.
-s $stripprog installed files.
-S SUFFIX attempt to back up existing files, with suffix SUFFIX.
-t DIRECTORY install into DIRECTORY.
-T report an error if DSTFILE is a directory.
Environment variables override the default commands:
CHGRPPROG CHMODPROG CHOWNPROG CMPPROG CPPROG MKDIRPROG MVPROG
RMPROG STRIPPROG
By default, rm is invoked with -f; when overridden with RMPROG,
it's up to you to specify -f if you want it.
If -S is not specified, no backups are attempted.
Email bug reports to bug-automake@gnu.org.
Automake home page: https://www.gnu.org/software/automake/
"
while test $# -ne 0; do
case $1 in
-c) ;;
-C) copy_on_change=true;;
-d) dir_arg=true;;
-g) chgrpcmd="$chgrpprog $2"
shift;;
--help) echo "$usage"; exit $?;;
-m) mode=$2
case $mode in
*' '* | *"$tab"* | *"$nl"* | *'*'* | *'?'* | *'['*)
echo "$0: invalid mode: $mode" >&2
exit 1;;
esac
shift;;
-o) chowncmd="$chownprog $2"
shift;;
-p) cpprog="$cpprog -p";;
-s) stripcmd=$stripprog;;
-S) backupsuffix="$2"
shift;;
-t)
is_target_a_directory=always
dst_arg=$2
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
shift;;
-T) is_target_a_directory=never;;
--version) echo "$0 $scriptversion"; exit $?;;
--) shift
break;;
-*) echo "$0: invalid option: $1" >&2
exit 1;;
*) break;;
esac
shift
done
# We allow the use of options -d and -T together, by making -d
# take the precedence; this is for compatibility with GNU install.
if test -n "$dir_arg"; then
if test -n "$dst_arg"; then
echo "$0: target directory not allowed when installing a directory." >&2
exit 1
fi
fi
if test $# -ne 0 && test -z "$dir_arg$dst_arg"; then
# When -d is used, all remaining arguments are directories to create.
# When -t is used, the destination is already specified.
# Otherwise, the last argument is the destination. Remove it from $@.
for arg
do
if test -n "$dst_arg"; then
# $@ is not empty: it contains at least $arg.
set fnord "$@" "$dst_arg"
shift # fnord
fi
shift # arg
dst_arg=$arg
# Protect names problematic for 'test' and other utilities.
case $dst_arg in
-* | [=\(\)!]) dst_arg=./$dst_arg;;
esac
done
fi
if test $# -eq 0; then
if test -z "$dir_arg"; then
echo "$0: no input file specified." >&2
exit 1
fi
# It's OK to call 'install-sh -d' without argument.
# This can happen when creating conditional directories.
exit 0
fi
if test -z "$dir_arg"; then
if test $# -gt 1 || test "$is_target_a_directory" = always; then
if test ! -d "$dst_arg"; then
echo "$0: $dst_arg: Is not a directory." >&2
exit 1
fi
fi
fi
if test -z "$dir_arg"; then
do_exit='(exit $ret); exit $ret'
trap "ret=129; $do_exit" 1
trap "ret=130; $do_exit" 2
trap "ret=141; $do_exit" 13
trap "ret=143; $do_exit" 15
# Set umask so as not to create temps with too-generous modes.
# However, 'strip' requires both read and write access to temps.
case $mode in
# Optimize common cases.
*644) cp_umask=133;;
*755) cp_umask=22;;
*[0-7])
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw='% 200'
fi
cp_umask=`expr '(' 777 - $mode % 1000 ')' $u_plus_rw`;;
*)
if test -z "$stripcmd"; then
u_plus_rw=
else
u_plus_rw=,u+rw
fi
cp_umask=$mode$u_plus_rw;;
esac
fi
for src
do
# Protect names problematic for 'test' and other utilities.
case $src in
-* | [=\(\)!]) src=./$src;;
esac
if test -n "$dir_arg"; then
dst=$src
dstdir=$dst
test -d "$dstdir"
dstdir_status=$?
# Don't chown directories that already exist.
if test $dstdir_status = 0; then
chowncmd=""
fi
else
# Waiting for this to be detected by the "$cpprog $src $dsttmp" command
# might cause directories to be created, which would be especially bad
# if $src (and thus $dsttmp) contains '*'.
if test ! -f "$src" && test ! -d "$src"; then
echo "$0: $src does not exist." >&2
exit 1
fi
if test -z "$dst_arg"; then
echo "$0: no destination specified." >&2
exit 1
fi
dst=$dst_arg
# If destination is a directory, append the input filename.
if test -d "$dst"; then
if test "$is_target_a_directory" = never; then
echo "$0: $dst_arg: Is a directory" >&2
exit 1
fi
dstdir=$dst
dstbase=`basename "$src"`
case $dst in
*/) dst=$dst$dstbase;;
*) dst=$dst/$dstbase;;
esac
dstdir_status=0
else
dstdir=`dirname "$dst"`
test -d "$dstdir"
dstdir_status=$?
fi
fi
case $dstdir in
*/) dstdirslash=$dstdir;;
*) dstdirslash=$dstdir/;;
esac
obsolete_mkdir_used=false
if test $dstdir_status != 0; then
case $posix_mkdir in
'')
# With -d, create the new directory with the user-specified mode.
# Otherwise, rely on $mkdir_umask.
if test -n "$dir_arg"; then
mkdir_mode=-m$mode
else
mkdir_mode=
fi
posix_mkdir=false
# The $RANDOM variable is not portable (e.g., dash). Use it
# here however when possible just to lower collision chance.
tmpdir=${TMPDIR-/tmp}/ins$RANDOM-$$
trap '
ret=$?
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir" 2>/dev/null
exit $ret
' 0
# Because "mkdir -p" follows existing symlinks and we likely work
# directly in world-writeable /tmp, make sure that the '$tmpdir'
# directory is successfully created first before we actually test
# 'mkdir -p'.
if (umask $mkdir_umask &&
$mkdirprog $mkdir_mode "$tmpdir" &&
exec $mkdirprog $mkdir_mode -p -- "$tmpdir/a/b") >/dev/null 2>&1
then
if test -z "$dir_arg" || {
# Check for POSIX incompatibilities with -m.
# HP-UX 11.23 and IRIX 6.5 mkdir -m -p sets group- or
# other-writable bit of parent directory when it shouldn't.
# FreeBSD 6.1 mkdir -m -p sets mode of existing directory.
test_tmpdir="$tmpdir/a"
ls_ld_tmpdir=`ls -ld "$test_tmpdir"`
case $ls_ld_tmpdir in
d????-?r-*) different_mode=700;;
d????-?--*) different_mode=755;;
*) false;;
esac &&
$mkdirprog -m$different_mode -p -- "$test_tmpdir" && {
ls_ld_tmpdir_1=`ls -ld "$test_tmpdir"`
test "$ls_ld_tmpdir" = "$ls_ld_tmpdir_1"
}
}
then posix_mkdir=:
fi
rmdir "$tmpdir/a/b" "$tmpdir/a" "$tmpdir"
else
# Remove any dirs left behind by ancient mkdir implementations.
rmdir ./$mkdir_mode ./-p ./-- "$tmpdir" 2>/dev/null
fi
trap '' 0;;
esac
if
$posix_mkdir && (
umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir"
)
then :
else
# mkdir does not conform to POSIX,
# or it failed possibly due to a race condition. Create the
# directory the slow way, step by step, checking for races as we go.
case $dstdir in
/*) prefix='/';;
[-=\(\)!]*) prefix='./';;
*) prefix='';;
esac
oIFS=$IFS
IFS=/
set -f
set fnord $dstdir
shift
set +f
IFS=$oIFS
prefixes=
for d
do
test X"$d" = X && continue
prefix=$prefix$d
if test -d "$prefix"; then
prefixes=
else
if $posix_mkdir; then
(umask $mkdir_umask &&
$doit_exec $mkdirprog $mkdir_mode -p -- "$dstdir") && break
# Don't fail if two instances are running concurrently.
test -d "$prefix" || exit 1
else
case $prefix in
*\'*) qprefix=`echo "$prefix" | sed "s/'/'\\\\\\\\''/g"`;;
*) qprefix=$prefix;;
esac
prefixes="$prefixes '$qprefix'"
fi
fi
prefix=$prefix/
done
if test -n "$prefixes"; then
# Don't fail if two instances are running concurrently.
(umask $mkdir_umask &&
eval "\$doit_exec \$mkdirprog $prefixes") ||
test -d "$dstdir" || exit 1
obsolete_mkdir_used=true
fi
fi
fi
if test -n "$dir_arg"; then
{ test -z "$chowncmd" || $doit $chowncmd "$dst"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dst"; } &&
{ test "$obsolete_mkdir_used$chowncmd$chgrpcmd" = false ||
test -z "$chmodcmd" || $doit $chmodcmd $mode "$dst"; } || exit 1
else
# Make a couple of temp file names in the proper directory.
dsttmp=${dstdirslash}_inst.$$_
rmtmp=${dstdirslash}_rm.$$_
# Trap to clean up those temp files at exit.
trap 'ret=$?; rm -f "$dsttmp" "$rmtmp" && exit $ret' 0
# Copy the file name to the temp name.
(umask $cp_umask &&
{ test -z "$stripcmd" || {
# Create $dsttmp read-write so that cp doesn't create it read-only,
# which would cause strip to fail.
if test -z "$doit"; then
: >"$dsttmp" # No need to fork-exec 'touch'.
else
$doit touch "$dsttmp"
fi
}
} &&
$doit_exec $cpprog "$src" "$dsttmp") &&
# and set any options; do chmod last to preserve setuid bits.
#
# If any of these fail, we abort the whole thing. If we want to
# ignore errors from any of these, just make sure not to ignore
# errors from the above "$doit $cpprog $src $dsttmp" command.
#
{ test -z "$chowncmd" || $doit $chowncmd "$dsttmp"; } &&
{ test -z "$chgrpcmd" || $doit $chgrpcmd "$dsttmp"; } &&
{ test -z "$stripcmd" || $doit $stripcmd "$dsttmp"; } &&
{ test -z "$chmodcmd" || $doit $chmodcmd $mode "$dsttmp"; } &&
# If -C, don't bother to copy if it wouldn't change the file.
if $copy_on_change &&
old=`LC_ALL=C ls -dlL "$dst" 2>/dev/null` &&
new=`LC_ALL=C ls -dlL "$dsttmp" 2>/dev/null` &&
set -f &&
set X $old && old=:$2:$4:$5:$6 &&
set X $new && new=:$2:$4:$5:$6 &&
set +f &&
test "$old" = "$new" &&
$cmpprog "$dst" "$dsttmp" >/dev/null 2>&1
then
rm -f "$dsttmp"
else
# If $backupsuffix is set, and the file being installed
# already exists, attempt a backup. Don't worry if it fails,
# e.g., if mv doesn't support -f.
if test -n "$backupsuffix" && test -f "$dst"; then
$doit $mvcmd -f "$dst" "$dst$backupsuffix" 2>/dev/null
fi
# Rename the file to the real destination.
$doit $mvcmd -f "$dsttmp" "$dst" 2>/dev/null ||
# The rename failed, perhaps because mv can't rename something else
# to itself, or perhaps because mv is so ancient that it does not
# support -f.
{
# Now remove or move aside any old file at destination location.
# We try this two ways since rm can't unlink itself on some
# systems and the destination file might be busy for other
# reasons. In this case, the final cleanup might fail but the new
# file should still install successfully.
{
test ! -f "$dst" ||
$doit $rmcmd "$dst" 2>/dev/null ||
{ $doit $mvcmd -f "$dst" "$rmtmp" 2>/dev/null &&
{ $doit $rmcmd "$rmtmp" 2>/dev/null; :; }
} ||
{ echo "$0: cannot unlink or rename $dst" >&2
(exit 1); exit 1
}
} &&
# Now rename the file to the real destination.
$doit $mvcmd "$dsttmp" "$dst"
}
fi || exit 1
trap '' 0
fi
done
# Local variables:
# eval: (add-hook 'before-save-hook 'time-stamp)
# time-stamp-start: "scriptversion="
# time-stamp-format: "%:y-%02m-%02d.%02H"
# time-stamp-time-zone: "UTC0"
# time-stamp-end: "; # UTC"
# End:

187
exec/loader-aarch64.s Normal file
View file

@ -0,0 +1,187 @@
// Copyright (C) 2023 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/>.
// Notice that aarch64 requires that sp be aligned to 16 bytes while
// accessing memory from sp, so x20 is used to chase down the load
// area.
.section .text
.global _start
_start:
//mov x8, 101 // SYS_nanosleep
//adr x0, timespec // req
//mov x1, #0 // rem
//svc #0 // syscall
mov x20, sp // x20 = sp
ldr x10, [x20] // x10 = original SP
add x20, x20, #16 // x20 = start of load area
mov x28, #-1 // x28 = secondary fd
.next_action:
ldr x11, [x20] // action number
and x12, x11, #-17 // actual action number
cbz x12, .open_file // open file?
cmp x12, #3 // jump?
beq .rest_of_exec
cmp x12, #4 // anonymous mmap?
beq .do_mmap_anon
.do_mmap:
ldr x0, [x20, 8] // vm_address
ldr x1, [x20, 32] // length
ldr x2, [x20, 24] // protection
ldr x3, [x20, 40] // flags
tst x11, #16 // primary fd?
mov x4, x29 // primary fd
beq .do_mmap_1
mov x4, x28 // secondary fd
.do_mmap_1:
mov x8, #222 // SYS_mmap
ldr x5, [x20, 16] // file_offset
svc #0 // syscall
ldr x9, [x20, 8] // length
cmp x0, x9 // mmap result
bne .perror // print error
ldr x3, [x20, 48] // clear
add x1, x1, x0 // x1 = vm_address + end
sub x3, x1, x3 // x3 = x1 - clear
mov x0, #0 // x0 = 0
.fill64:
sub x2, x1, x3 // x2 = x1 - x3
cmp x2, #63 // x2 >= 64?
ble .fillb // start filling bytes
stp x0, x0, [x3] // x3[0] = 0, x3[1] = 0
stp x0, x0, [x3, 16] // x3[2] = 0, x3[3] = 0
stp x0, x0, [x3, 32] // x3[4] = 0, x3[5] = 0
stp x0, x0, [x3, 48] // x3[6] = 0, x3[7] = 0
add x3, x3, #64 // x3 += 8
b .fill64
.fillb:
cmp x1, x3 // x1 == x3?
beq .continue // done
strb w0, [x3], #1 // ((char *) x3)++ = 0
b .fillb
.continue:
add x20, x20, #56 // next action
b .next_action
.do_mmap_anon:
ldr x0, [x20, 8] // vm_address
ldr x1, [x20, 32] // length
ldr x2, [x20, 24] // protection
ldr x3, [x20, 40] // flags
mov x4, #-1 // fd
b .do_mmap_1
.open_file:
mov x8, #56 // SYS_openat
mov x0, #-100 // AT_FDCWD
add x1, x20, #8 // file name
mov x2, #0 // O_RDONLY
mov x3, #0 // mode
svc #0 // syscall
cmp x0, #-1 // rc < 0?
ble .perror
mov x19, x1 // x19 == x1
.nextc:
ldrb w2, [x1], #1 // b = *x1++
cmp w2, #47 // dir separator?
bne .nextc1 // not dir separator
mov x19, x1 // x19 = char past separator
.nextc1:
cbnz w2, .nextc // b?
add x1, x1, #7 // round up x1
and x20, x1, #-8 // mask for round, set x20
tst x11, #16 // primary fd?
bne .secondary // secondary fd
mov x29, x0 // primary fd
mov x8, #167 // SYS_prctl
mov x0, #15 // PR_SET_NAME
mov x1, x19 // basename
mov x2, #0 // arg2
mov x3, #0 // arg3
mov x4, #0 // arg4
mov x5, #0 // arg5
svc #0 // syscall
b .next_action // next action
.secondary:
mov x28, x0 // secondary fd
b .next_action // next action.
.perror:
mov x8, #93 // SYS_exit
mvn x0, x0 // x1 = ~x0
add x0, x0, 1 // x1 += 1
svc #0 // exit
.rest_of_exec:
mov x7, x20 // x7 = x20
mov x20, x10 // x20 = x10
ldr x9, [x20] // argc
add x9, x9, #2 // x9 += 2
lsl x9, x9, #3 // argc * 8
add x20, x20, x9 // now past argv
.skipenv:
ldr x9, [x20], #8 // x9 = *envp++
cbnz x9, .skipenv // x9?
.one_auxv:
ldr x9, [x20], #16 // x9 = *sp, sp += 2
cbz x9, .cleanup // !x9?
cmp x9, #3 // is AT_PHDR?
beq .replace_phdr // replace
cmp x9, #4 // is AT_PHENT?
beq .replace_phent // replace
cmp x9, #5 // is AT_PHNUM?
beq .replace_phnum // replace
cmp x9, #9 // is AT_ENTRY?
beq .replace_entry // replace
cmp x9, #7 // is AT_BASE?
beq .replace_base // replace
b .one_auxv // next auxv
.replace_phdr:
ldr x9, [x7, 40] // at_phdr
str x9, [x20, -8] // store value
b .one_auxv
.replace_phent:
ldr x9, [x7, 24] // at_phent
str x9, [x20, -8] // store value
b .one_auxv
.replace_phnum:
ldr x9, [x7, 32] // at_phnum
str x9, [x20, -8] // store value
b .one_auxv
.replace_entry:
ldr x9, [x7, 16] // at_entry
str x9, [x20, -8] // store value
b .one_auxv
.replace_base:
ldr x9, [x7, 48] // at_base
str x9, [x20, -8] // store value
b .one_auxv
.cleanup:
cmp x28, #-1 // is secondary fd set?
bne .cleanup1 // not set
mov x8, #57 // SYS_close
mov x0, x28 // secondary fd
svc #0 // syscall
.cleanup1:
mov x8, #57 // SYS_close
mov x0, x29 // primary fd
svc #0 // syscall
.enter:
mov sp, x10 // restore original SP
mov x0, #0 // clear rtld_fini
ldr x1, [x7, 8] // branch to code
br x1
timespec:
.quad 10
.quad 10

204
exec/loader-armeabi.s Normal file
View file

@ -0,0 +1,204 @@
@ Copyright (C) 2023 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/>.
.section .text
.global _start
_start:
@mov r7, #162 @ SYS_nanosleep
@adr r0, timespec @ req
@mov r1, #0 @ rem
@swi #0 @ syscall
mov r8, sp @ r8 = sp
ldr r9, [r8], #8 @ r9 = original sp, r8 += 8
mov r14, #-1 @ r14 = secondary fd
.next_action:
ldr r11, [r8] @ r11 = action number
and r12, r11, #-17 @ actual action number
cmp r12, #0 @ open file?
beq .open_file @ open file.
cmp r12, #3 @ jump?
beq .rest_of_exec @ jump to code.
cmp r12, #4 @ anonymous mmap?
beq .do_mmap_anon @ anonymous mmap.
.do_mmap:
add r6, r8, #4 @ r6 = r8 + 4
ldm r6!, {r0, r5} @ vm_address, file_offset
ldm r6!, {r1, r2} @ protection, length
mov r3, r1 @ swap
lsr r5, #12 @ divide file offset by page size
mov r1, r2 @ swap
mov r2, r3 @ swap
ldm r6!, {r3, r12} @ flags, clear
tst r11, #16 @ primary fd?
mov r4, r10 @ primary fd
beq .do_mmap_1
mov r4, r14 @ secondary fd
.do_mmap_1:
mov r7, #192 @ SYS_mmap2
swi #0 @ syscall
ldr r2, [r8, #4] @ vm_address
cmp r2, r0 @ rc == vm_address?
bne .perror
add r0, r1, r2 @ r0 = length + vm_address
sub r3, r0, r12 @ r3 = r0 - clear
mov r1, #0 @ r1 = 0
.align:
cmp r0, r3 @ r0 == r3?
beq .continue @ continue
tst r3, #3 @ r3 & 3?
bne .fill32 @ fill aligned
strb r1, [r3], #1 @ fill byte
b .align @ align again
.fill32:
sub r2, r0, r3 @ r2 = r0 - r3
cmp r2, #31 @ r2 >= 32?
ble .fillb @ start filling bytes
str r1, [r3], #4 @ *r3++ = 0
str r1, [r3], #4 @ *r3++ = 0
str r1, [r3], #4 @ *r3++ = 0
str r1, [r3], #4 @ *r3++ = 0
str r1, [r3], #4 @ *r3++ = 0
str r1, [r3], #4 @ *r3++ = 0
str r1, [r3], #4 @ *r3++ = 0
str r1, [r3], #4 @ *r3++ = 0
b .fill32
.fillb:
cmp r0, r3 @ r0 == r3
beq .continue @ done
strb r1, [r3], #1 @ ((char *) r3)++ = 0
b .fillb
.continue:
add r8, r8, #28 @ next action
b .next_action
.do_mmap_anon:
add r6, r8, #4 @ r6 = r8 + 4
ldm r6!, {r0, r5} @ vm_address, file_offset
ldm r6!, {r1, r2} @ protection, length
mov r3, r1 @ swap
lsr r5, #12 @ divide file offset by page size
mov r1, r2 @ swap
mov r2, r3 @ swap
ldm r6!, {r3, r12} @ flags, clear
mov r4, #-1 @ fd
b .do_mmap_1
.open_file:
mov r7, #5 @ SYS_open
add r0, r8, #4 @ file name
mov r1, #0 @ O_RDONLY
mov r2, #0 @ mode
swi #0 @ syscall
cmp r0, #-1 @ r0 <= -1?
ble .perror
add r8, r8, #4 @ r8 = start of string
mov r1, r8 @ r1 = r8
.nextc:
ldrb r2, [r8], #1 @ b = *r0++
cmp r2, #47 @ dir separator?
bne .nextc1 @ not dir separator
mov r1, r8 @ r1 = char past separator
.nextc1:
cmp r2, #0 @ b?
bne .nextc @ next character
add r8, r8, #3 @ round up r8
and r8, r8, #-4 @ mask for round, set r8
tst r11, #16 @ primary fd?
bne .secondary @ secondary fd
mov r10, r0 @ primary fd
mov r7, #172 @ SYS_prctl
mov r0, #15 @ PR_SET_NAME, r1 = name
mov r2, #0 @ arg2
mov r3, #0 @ arg3
mov r4, #0 @ arg4
mov r5, #0 @ arg5
swi #0 @ syscall
b .next_action @ next action
.secondary:
mov r14, r0 @ secondary fd
b .next_action @ next action
.perror:
mov r7, #1 @ SYS_exit
mvn r0, r0 @ r0 = ~r0
add r0, r0, #1 @ r0 += 1
swi #0
.rest_of_exec:
mov r7, r9 @ r7 = original SP
ldr r6, [r7] @ argc
add r6, r6, #2 @ argc + 2
lsl r6, r6, #2 @ argc *= 4
add r7, r7, r6 @ now past argv
.skipenv:
ldr r6, [r7], #4 @ r6 = *r7++
cmp r6, #0 @ r6?
bne .skipenv @ r6?
.one_auxv:
ldr r6, [r7], #8 @ r6 = *r7, r7 += 2
cmp r6, #0 @ !r6?
beq .cleanup @ r6?
cmp r6, #3 @ is AT_PHDR?
beq .replace_phdr @ replace
cmp r6, #4 @ is AT_PHENT?
beq .replace_phent @ replace
cmp r6, #5 @ is AT_PHNUM?
beq .replace_phnum @ replace
cmp r6, #9 @ is AT_ENTRY?
beq .replace_entry @ replace
cmp r6, #7 @ is AT_BASE?
beq .replace_base @ replace
b .one_auxv @ next auxv
.replace_phdr:
ldr r6, [r8, #20] @ at_phdr
str r6, [r7, #-4] @ store value
b .one_auxv
.replace_phent:
ldr r6, [r8, #12] @ at_phent
str r6, [r7, #-4] @ store value
b .one_auxv
.replace_phnum:
ldr r6, [r8, #16] @ at_phnum
str r6, [r7, #-4] @ store value
b .one_auxv
.replace_entry:
ldr r6, [r8, #8] @ at_entry
str r6, [r7, #-4] @ store value
b .one_auxv
.replace_base:
ldr r6, [r8, #24] @ at_base
str r6, [r7, #-4] @ store value
b .one_auxv
.cleanup:
cmp r14, #-1 @ secondary fd set?
bne .cleanup1 @ not set
mov r7, #6 @ SYS_close
mov r0, r14 @ secondary fd
swi #0 @ syscall
.cleanup1:
mov r7, #6 @ SYS_close
mov r0, r10 @ primary fd
swi #0 @ syscall
.enter:
mov sp, r9 @ restore original SP
mov r0, #0 @ clear rtld_fini
ldr r1, [r8, #4] @ branch to code
bx r1
timespec:
.long 10
.long 10
@ Local Variables:
@ asm-comment-char: 64
@ End:

234
exec/loader-mips64el.s Normal file
View file

@ -0,0 +1,234 @@
# Copyright (C) 2023 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-mips.m4')
.set noreorder # delay slots managed by hand
.set noat # no assembler macros
.section .text
.global __start
__start:
dnl li $v0, 5034 # SYS_nanosleep
dnl dla $a0, .timespec # rqtp
dnl li $a1, 0 # rmtp
dnl syscall # syscall
ld $s2, ($sp) # original stack pointer
DADDI3( $s0, $sp, 16) # start of load area
DADDI2( $sp, -16) # primary fd, secondary fd
li $t0, -1 # secondary fd
sd $t0, 8($sp) # initialize secondary fd
.next_action:
ld $s1, ($s0) # action number
andi $t0, $s1, 15 # t0 = action number & 15
beqz $t0, .open_file # open file?
nop # delay slot
DADDI2( $t0, -3) # t0 -= 3
beqz $t0, .rest_of_exec # jump to code
nop # delay slot
li $t1, 1
beq $t0, $t1, .do_mmap_anon # anonymous mmap?
nop # delay slot
.do_mmap:
ld $t0, 8($s0) # vm address
ld $t1, 16($s0) # file_offset
ld $t2, 24($s0) # protection
ld $t3, 32($s0) # length
ld $v0, 40($s0) # flags
ld $v1, ($sp) # primary fd
andi $s3, $s1, 16 # s1 & 16?
beqz $s3, .do_mmap_1 # secondary fd?
nop # delay slot
ld $v1, 8($sp) # secondary fd
.do_mmap_1:
move $a0, $t0 # syscall arg
move $a1, $t3 # syscall arg
move $a2, $t2 # syscall arg
move $a3, $v0 # syscall arg
move $a4, $v1 # syscall arg
move $a5, $t1 # syscall arg
li $v0, 5009 # SYS_mmap
syscall # syscall
bne $a3, $zero, .perror # perror?
nop # delay slot
ld $t1, 48($s0) # clear
dadd $t0, $a0, $a1 # t0 = end of mapping
dsub $t1, $t0, $t1 # t1 = t0 - clear
.align:
beq $t0, $t1, .continue # already finished
nop # delay slot
andi $t2, $t1, 7 # t1 & 7?
bnez $t2, .filld # start filling longs
nop # delay slot
.filld:
dsub $t2, $t0, $t1 # t2 = t0 - t1
sltiu $t2, $t2, 64 # t2 < 64?
bne $t2, $zero, .fillb # fill bytes
nop # delay slot
sd $zero, ($t1) # zero doubleword
DADDI2( $t1, 8) # next doubleword
sd $zero, ($t1) # zero doubleword
DADDI2( $t1, 8) # next doubleword
sd $zero, ($t1) # zero doubleword
DADDI2( $t1, 8) # next doubleword
sd $zero, ($t1) # zero doubleword
DADDI2( $t1, 8) # next doubleword
sd $zero, ($t1) # zero doubleword
DADDI2( $t1, 8) # next doubleword
sd $zero, ($t1) # zero doubleword
DADDI2( $t1, 8) # next doubleword
sd $zero, ($t1) # zero doubleword
DADDI2( $t1, 8) # next doubleword
sd $zero, ($t1) # zero doubleword
DADDI2( $t1, 8) # next doubleword
j .filld # fill either doubleword or byte
nop # delay slot
.fillb:
beq $t0, $t1, .continue # already finished?
nop # delay slot
sb $zero, ($t1) # clear byte
DADDI2( $t1, 1) # t1++
.continue:
DADDI2( $s0, 56) # s0 = next action
j .next_action # next action
nop # delay slot
.do_mmap_anon:
ld $t0, 8($s0) # vm address
ld $t1, 16($s0) # file_offset
ld $t2, 24($s0) # protection
ld $t3, 32($s0) # length
ld $v0, 40($s0) # flags
li $v1, -1 # fd
j .do_mmap_1 # do mmap
nop # branch delay slot
.open_file:
li $v0, 5002 # SYS_open
DADDI3( $a0, $s0, 8) # start of name
move $a1, $zero # flags = O_RDONLY
move $a2, $zero # mode = 0
syscall # syscall
bne $a3, $zero, .perror # perror
nop # delay slot
DADDI2( $s0, 8) # start of string
move $t3, $s0 # t3 = s0
.nextc:
lb $t0, ($s0) # load byte
DADDI2( $s0, 1) # s0++
li $t1, 47 # directory separator `/'
bne $t0, $t1, .nextc1 # is separator char?
nop # delay slot
move $t3, $s0 # t3 = char past separator
.nextc1:
bnez $t0, .nextc # next character?
nop # delay slot
DADDI2( $s0, 7) # adjust for round
li $t2, -8 # t2 = -8
and $s0, $s0, $t2 # mask for round
andi $t0, $s1, 16 # t1 = s1 & 16
move $t1, $sp # address of primary fd
beqz $t0, .primary # primary fd?
nop # delay slot
DADDI2( $t1, 8) # address of secondary fd
sd $v0, ($t1) # store fd
j .next_action # next action
nop # delay slot
.primary:
sd $v0, ($t1) # store fd
li $v0, 5153 # SYS_prctl
li $a0, 15 # PR_SET_NAME
move $a1, $t3 # char past separator
move $a2, $zero # a2
move $a3, $zero # a3
move $a4, $zero # a4
move $a5, $zero # a5
syscall # syscall
j .next_action # next action
nop # delay slot
.perror:
move $a0, $v0 # errno
li $v0, 5058 # SYS_exit
syscall # syscall
.rest_of_exec:
move $s1, $s2 # original SP
ld $t0, ($s1) # argc
dsll $t0, $t0, 3 # argc *= 3
DADDI2( $t0, 16) # argc += 16
dadd $s1, $s1, $t0 # s1 = start of envp
.skipenv:
ld $t0, ($s1) # t0 = *s1
DADDI2( $s1, 8) # s1++
bne $t0, $zero, .skipenv # skip again
nop # delay slot
dla $t3, .auxvtab # address of auxv table
.one_auxv:
ld $t0, ($s1) # t0 = auxv type
li $t1, 10 # t1 = 10
beqz $t0, .finish # is AT_IGNORE?
nop # delay slot
sltu $t1, $t0, $t1 # t1 = t0 < num offsets
beqz $t1, .next # next auxv
nop # delay slot
dsll $t1, $t0, 2 # t1 = t0 * 4
dadd $t1, $t3, $t1 # t1 = .auxvtab + t1
lw $t2, ($t1) # t2 = *t1
beqz $t2, .next # skip auxv
nop # delay slot
dadd $t2, $s0, $t2 # t2 = s0 + t2
ld $t2, ($t2) # t2 = *t2
sd $t2, 8($s1) # set auxv value
.next:
DADDI2( $s1, 16) # next auxv
j .one_auxv # next auxv
nop # delay slot
.finish:
ld $t0, 8($sp) # secondary fd
li $t1, -1 # t1 = -1
ld $s1, ($sp) # s1 = primary fd
li $v0, 5003 # SYS_close
beq $t0, $t2, .finish1 # secondary fd set?
nop # delay slot
move $a0, $t0 # secondary fd
syscall # syscall
li $v0, 5003 # SYS_close
.finish1:
move $a0, $s1 # primary fd
syscall # syscall
.jump:
move $v0, $zero # rtld_fini
ld $t0, 8($s0) # entry
move $sp, $s2 # restore stack pointer, delay slot
jr $t0 # enter
nop # delay slot
.auxvtab:
.long 0 # 0
.long 0 # 1
.long 0 # 2
.long 40 # 3 AT_PHDR
.long 24 # 4 AT_PHENT
.long 32 # 5 AT_PHNUM
.long 0 # 6
.long 48 # 7 AT_BASE
.long 0 # 8
.long 16 # 9 AT_ENTRY
.timespec:
.quad 10
.quad 10
# Local Variables:
# asm-comment-char: 35
# End:

236
exec/loader-mipsel.s Normal file
View file

@ -0,0 +1,236 @@
# Copyright (C) 2023 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-mips.m4')
# Make sure not to use t4 through t7, in order to maintain portability
# with N32 ABI systems.
.set noreorder # delay slots managed by hand
.section .text
.global __start
__start:
dnl li $v0, SYSCALL_nanosleep # SYS_nanosleep
dnl la $a0, .timespec # rqtp
dnl li $a1, 0 # rmtp
dnl syscall # syscall
lw $s6, ($sp) # original stack pointer
addi $s0, $sp, 8 # start of load area
addi $sp, -8 # primary fd, secondary fd
li $t0, -1 # secondary fd
sw $t0, 4($sp) # initialize secondary fd
.next_action:
lw $s2, ($s0) # action number
nop # delay slot
andi $t0, $s2, 15 # t0 = s2 & 15
beqz $t0, .open_file # open file?
li $t1, 3 # t1 = 3, delay slot
beq $t0, $t1, .rest_of_exec # jump to code
li $t1, 4 # t1 = 4, delay slot
beq $t0, $t1, .do_mmap_anon # anonymous mmap
.do_mmap:
lw $a0, 4($s0) # vm_address, delay slot
lw $v1, 8($s0) # file_offset
lw $a2, 12($s0) # protection
lw $a1, 16($s0) # length
lw $a3, 20($s0) # flags
lw $v0, ($sp) # primary fd
andi $t1, $s2, 16 # t1 = s2 & 16
beqz $t1, .do_mmap_1 # secondary fd?
nop # delay slot
lw $v0, 4($sp) # secondary fd
nop # delay slot
.do_mmap_1:
SYSCALL(`$v0',`$v1',`$zero',`$zero') # syscall args
li $v0, SYSCALL_mmap # SYS_mmap
syscall # syscall
bne $a3, $zero, .perror # perror
RESTORE() # delay slot, restore sp
lw $s5, 24($s0) # clear
add $t0, $a0, $a1 # t0 = length + vm_address, delay slot
sub $t1, $t0, $s5 # t1 = t0 - clear
.align:
beq $t0, $t1, .continue # already finished?
nop # delay slot
andi $t2, $t1, 3 # t1 & 3?
bnez $t2, .fillw # start filling longs
nop # delay slot
sb $zero, ($t1) # clear byte
addi $t1, $t1, 1 # t1++
j .align # continue
nop # delay slot
.fillw:
sub $t2, $t0, $t1 # t2 = t0 - t1
sltiu $t2, $t2, 32 # r2 < 32?
bne $t2, $zero, .fillb # fill bytes
nop # delay slot
sw $zero, ($t1) # zero word
addi $t1, $t1, 4 # next word
sw $zero, ($t1) # zero word
addi $t1, $t1, 4 # next word
sw $zero, ($t1) # zero word
addi $t1, $t1, 4 # next word
sw $zero, ($t1) # zero word
addi $t1, $t1, 4 # next word
sw $zero, ($t1) # zero word
addi $t1, $t1, 4 # next word
sw $zero, ($t1) # zero word
addi $t1, $t1, 4 # next word
sw $zero, ($t1) # zero word
addi $t1, $t1, 4 # next word
sw $zero, ($t1) # zero word
addi $t1, $t1, 4 # next word
j .fillw # fill either word or byte
nop # delay slot
.fillb:
beq $t0, $t1, .continue # already finished?
nop # delay slot
sb $zero, ($t1) # clear byte
addi $t1, $t1, 1 # t1++
.continue:
addi $s0, $s0, 28 # s0 = next action
j .next_action # next action
nop # delay slot
.do_mmap_anon:
lw $v1, 8($s0) # file_offset
lw $a2, 12($s0) # protection
lw $a1, 16($s0) # length
lw $a3, 20($s0) # flags
li $t4, -1 # fd
j .do_mmap_1 # do mmap
nop # delay slot
.open_file:
li $v0, SYSCALL_open # SYS_open
addi $a0, $s0, 4 # start of name
move $a1, $zero # flags = O_RDONLY
move $a2, $zero # mode = 0
syscall # syscall
bne $a3, $zero, .perror # perror
addi $s0, $s0, 4 # start of string, delay slot
move $t3, $s0 # t3 = char past separator
.nextc:
lb $t0, ($s0) # load byte
addi $s0, $s0, 1 # s0++
li $t1, 47 # directory separator `/'
bne $t0, $t1, .nextc1 # is separator char?
nop # delay slot
move $t3, $s0 # t3 = char past separator
.nextc1:
bnez $t0, .nextc # next character?
nop # delay slot
addi $s0, $s0, 3 # adjust for round
li $t2, -4 # t2 = -4
and $s0, $s0, $t2 # mask for round
andi $t0, $s2, 16 # t1 = s2 & 16
beqz $t0, .primary # primary fd?
move $t0, $sp # address of primary fd, delay slot
addi $t0, $t0, 4 # address of secondary fd
j .next_action # next action
.primary:
sw $v0, ($t0) # store fd, delay slot
li $v0, SYSCALL_prctl # SYS_prctl
li $a0, 15 # PR_SET_NAME
move $a1, $t3 # name
move $a2, $zero # arg1
move $a3, $zero # arg2
SYSCALL(`$a2',`$a2',`$a2',`$a2') # syscall args
syscall # syscall
RESTORE() # restore sp
j .next_action # next action
nop # delay slot
.perror:
move $a0, $v0 # errno
li $v0, SYSCALL_exit # SYS_exit
syscall # syscall
.rest_of_exec:
move $s1, $s6 # s1 = original SP
lw $t0, ($s1) # argc
nop # delay slot
sll $t0, $t0, 2 # argc *= 4
addi $t0, $t0, 8 # argc += 8
add $s1, $s1, $t0 # s1 = start of envp
.skipenv:
lw $t0, ($s1) # t0 = *s1
addi $s1, $s1, 4 # s1++
bne $t0, $zero, .skipenv # skip again
nop # delay slot
la $s2, .auxvtab # address of auxv table
.one_auxv:
lw $t0, ($s1) # t0 = auxv type
li $t1, 10 # t1 = 10, delay slot
beqz $t0, .finish # is AT_IGNORE?
sltu $t1, $t0, $t1 # t1 = t0 < num offsets, delay slot
beq $t1, $zero, .next # next auxv
sll $t1, $t0, 2 # t1 = t0 * 4, delay slot
add $t1, $s2, $t1 # t1 = .auxvtab + t1
lw $t2, ($t1) # t2 = *t1
nop # delay slot
beqz $t2, .next # skip auxv
add $t2, $s0, $t2 # t2 = s0 + t2
lw $t2, ($t2) # t2 = *t2
nop # delay slot
sw $t2, 4($s1) # set auxv value
.next:
addi $s1, $s1, 8 # next auxv
j .one_auxv # next auxv
nop # delay slot
.finish:
lw $t0, 4($sp) # secondary fd
lw $s1, ($sp) # primary fd, delay slot, preserved
li $t2, -1 # immediate -1
beq $t0, $t2, .finish1 # secondary fd set?
li $v0, SYSCALL_close # SYS_close, delay slot
move $a0, $t0 # fd
syscall # syscall
li $v0, SYSCALL_close # SYS_close
.finish1:
move $a0, $s1 # primary fd
syscall # syscall
li $v0, SYSCALL_prctl # SYS_prctl
li $a0, 45 # PR_SET_FP_MODE
lw $a1, 28($s0) # fpu_mode
move $a2, $zero # arg3
move $a3, $zero # arg4
SYSCALL(`$a2',`$a2',`$a2',`$a2') # syscall args
syscall # syscall
RESTORE() # restore sp
.jump:
move $v0, $zero # rtld_fini
lw $t0, 4($s0) # entry
move $sp, $s6 # restore stack pointer, delay slot
jr $t0 # enter
nop # delay slot
.auxvtab:
.long 0 # 0
.long 0 # 1
.long 0 # 2
.long 20 # 3 AT_PHDR
.long 12 # 4 AT_PHENT
.long 16 # 5 AT_PHNUM
.long 0 # 6
.long 24 # 7 AT_BASE
.long 0 # 8
.long 8 # 9 AT_ENTRY
.timespec:
.long 10
.long 10
# Local Variables:
# asm-comment-char: 35
# End:

203
exec/loader-x86.s Normal file
View file

@ -0,0 +1,203 @@
define(`CC', `
dnl')
CC Copyright (C) 2023 Free Software Foundation, Inc.
CC
CC This file is part of GNU Emacs.
CC
CC GNU Emacs is free software: you can redistribute it and/or modify
CC it under the terms of the GNU General Public License as published
CC by the Free Software Foundation, either version 3 of the License,
CC or (at your option) any later version.
CC
CC GNU Emacs is distributed in the hope that it will be useful, but
CC WITHOUT ANY WARRANTY; without even the implied warranty of
CC MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
CC General Public License for more details.
CC
CC You should have received a copy of the GNU General Public License
CC along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
.section .text
.global _start
_start:
dnl movl $162, %eax CC SYS_nanosleep
dnl leal timespec, %ebx
dnl xorl %ecx, %ecx
dnl int $0x80
leal 8(%esp), %ebp CC ebp = start of load area
subl $8, %esp CC (%esp) = primary fd, 4(%esp) = secondary fd
movl $-1, 4(%esp)
.next_action:
movl (%ebp), %edx CC edx = action number
andl $-17, %edx
cmpl $0, %edx CC open file?
je .open_file
cmpl $3, %edx CC jump?
je .rest_of_exec
cmpl $4, %edx CC anonymous mmap?
je .do_mmap_anon
.do_mmap:
subl $24, %esp
movl $90, %eax CC SYS_old_mmap
movl %esp, %ebx
movl 4(%ebp), %ecx CC address
movl %ecx, (%esp)
movl 16(%ebp), %ecx CC length
movl %ecx, 4(%esp)
movl 12(%ebp), %ecx CC protection
movl %ecx, 8(%esp)
movl 20(%ebp), %ecx CC flags
movl %ecx, 12(%esp)
testl $16, (%ebp) CC primary?
movl 28(%esp), %ecx
cmovzl 24(%esp), %ecx
movl %ecx, 16(%esp) CC fd
movl 8(%ebp), %ecx CC offset
movl %ecx, 20(%esp)
.do_mmap_1:
int $0x80
addl $24, %esp CC restore esp
cmpl $-1, %eax CC mmap failed?
je .perror
movl 24(%ebp), %ecx CC clear
testl %ecx, %ecx
jz .continue
movl 4(%ebp), %esi CC start of mapping
addl 16(%ebp), %esi CC end of mapping
subl %ecx, %esi CC start of clear area
.again:
testl %ecx, %ecx
jz .continue
subl $1, %ecx
movb $0, (%esi, %ecx, 1)
jmp .again
.continue:
leal 28(%ebp), %ebp
jmp .next_action
.do_mmap_anon:
subl $24, %esp
movl $90, %eax CC SYS_old_mmap
movl %esp, %ebx
movl 4(%ebp), %ecx CC address
movl %ecx, (%esp)
movl 16(%ebp), %ecx CC length
movl %ecx, 4(%esp)
movl 12(%ebp), %ecx CC protection
movl %ecx, 8(%esp)
movl 20(%ebp), %ecx CC flags
movl %ecx, 12(%esp)
movl $-1, 16(%esp) CC fd
movl 8(%ebp), %ecx CC offset
movl %ecx, 20(%esp)
jmp .do_mmap_1
.open_file:
movl $5, %eax CC SYS_open
leal 4(%ebp), %ebx CC ebx = %esp + 8
pushl %ebx
xorl %ecx, %ecx CC flags = O_RDONLY
xorl %edx, %edx CC mode = 0
int $0x80
cmpl $-1, %eax CC open failed?
jle .perror
movl %ebp, %esi CC (esi) = original action number
popl %ebp CC ebp = start of string
movl %ebp, %ecx CC char past separator
decl %ebp
.nextc:
incl %ebp
movb (%ebp), %dl CC dl = *ebp
cmpb $47, %dl CC dl == '\?'?
jne .nextc1
leal 1(%ebp), %ecx CC ecx = char past separator
.nextc1:
cmpb $0, %dl CC dl == 0?
jne .nextc
addl $4, %ebp CC adjust past ebp prior to rounding
andl $-4, %ebp CC round ebp up to the next long
testl $16, (%esi) CC original action number & 16?
jz .primary
movl %eax, 4(%esp) CC secondary fd = eax
jmp .next_action
.primary:
pushl %ebp
xorl %esi, %esi CC arg3
movl %eax, 4(%esp) CC primary fd = eax
xorl %edx, %edx CC arg2
movl $15, %ebx CC PR_SET_NAME, arg1 = ecx
xorl %edi, %edi CC arg4
movl $172, %eax CC SYS_prctl
xorl %ebp, %ebp CC arg5
int $0x80 CC syscall
popl %ebp
jmp .next_action
.perror:
movl %eax, %ebx
negl %ebx
movl $1, %eax
int $0x80
.rest_of_exec:
movl 8(%esp), %ecx CC ecx = original stack pointer
movl (%ecx), %esi CC esi = argc
leal 8(%ecx, %esi, 4), %ecx CC ecx = start of environ
.skip_environ:
movl (%ecx), %esi CC envp[N]
addl $4, %ecx
testl %esi, %esi CC envp[n] ?
jnz .skip_environ CC otherwise, esi is now at the start of auxv
.one_auxv:
movl (%ecx), %esi CC auxv type
leal 8(%ecx), %ecx CC skip to next auxv
testl %esi, %esi CC is 0?
jz .cleanup
cmpl $3, %esi CC is AT_PHDR
je .replace_phdr
cmpl $4, %esi CC is AT_PHENT?
je .replace_phent
cmpl $5, %esi CC is AT_PHNUM?
je .replace_phnum
cmpl $9, %esi CC is AT_ENTRY?
je .replace_entry
cmpl $7, %esi CC is AT_BASE
je .replace_base
jmp .one_auxv
.replace_phdr:
movl 20(%ebp), %esi
movl %esi, -4(%ecx)
jmp .one_auxv
.replace_phent:
movl 12(%ebp), %esi
movl %esi, -4(%ecx)
jmp .one_auxv
.replace_phnum:
movl 16(%ebp), %esi
movl %esi, -4(%ecx)
jmp .one_auxv
.replace_entry:
movl 8(%ebp), %esi
movl %esi, -4(%ecx)
jmp .one_auxv
.replace_base:
movl 24(%ebp), %esi
movl %esi, -4(%ecx)
jmp .one_auxv
.cleanup:
movl $6, %eax CC SYS_close
cmpl $-1, 4(%esp) CC see if interpreter fd is set
je .cleanup_1
movl 4(%esp), %ebx
int $0x80
movl $6, %eax CC SYS_close
.cleanup_1:
movl (%esp), %ebx
int $0x80
.enter:
pushl $0
popfl CC restore floating point state
movl 8(%esp), %esp CC restore initial stack pointer
xorl %edx, %edx CC clear rtld_fini
jmpl *4(%ebp) CC entry
timespec:
.long 10
.long 10

195
exec/loader-x86_64.s Normal file
View file

@ -0,0 +1,195 @@
define(`CC', `
dnl')
CC Copyright (C) 2023 Free Software Foundation, Inc.
CC
CC This file is part of GNU Emacs.
CC
CC GNU Emacs is free software: you can redistribute it and/or modify
CC it under the terms of the GNU General Public License as published
CC by the Free Software Foundation, either version 3 of the License,
CC or (at your option) any later version.
CC
CC GNU Emacs is distributed in the hope that it will be useful, but
CC WITHOUT ANY WARRANTY; without even the implied warranty of
CC MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
CC General Public License for more details.
CC
CC You should have received a copy of the GNU General Public License
CC along with GNU Emacs. If not, see <https://www.gnu.org/licenses/>.
.section .text
.global _start
_start:
dnl movq $35, %rax CC SYS_nanosleep
dnl leaq timespec(%rip), %rdi
dnl xorq %rsi, %rsi
dnl syscall
popq %r13 CC original SP
popq %r15 CC size of load area.
movq $-1, %r12 CC r12 is the interpreter fd
.next_action:
movq (%rsp), %r14 CC action number
movq %r14, %r15 CC original action number
andq $-17, %r14
cmpq $0, %r14 CC open file?
je .open_file
cmpq $3, %r14 CC jump?
je .rest_of_exec
cmpq $4, %r14 CC anonymous mmap?
je .do_mmap_anon
.do_mmap:
movq $9, %rax CC SYS_mmap
movq 8(%rsp), %rdi CC address
movq 16(%rsp), %r9 CC offset
movq 24(%rsp), %rdx CC protection
movq 32(%rsp), %rsi CC length
movq 40(%rsp), %r10 CC flags
CC set r8 to the primary fd unless r15 & 16
testq $16, %r15
movq %r12, %r8
cmovzq %rbx, %r8
.do_mmap_1:
syscall
cmpq $-1, %rax CC mmap failed
je .perror
movq 48(%rsp), %r9 CC clear
testq %r9, %r9
jz .continue
movq 8(%rsp), %r10 CC start of mapping
addq 32(%rsp), %r10 CC end of mapping
subq %r9, %r10 CC start of clear area
.again:
testq %r9, %r9
jz .continue
subq $1, %r9
movb $0, (%r10, %r9, 1)
jmp .again
.continue:
leaq 56(%rsp), %rsp
jmp .next_action
.do_mmap_anon:
movq $9, %rax CC SYS_mmap
movq 8(%rsp), %rdi CC address
movq 16(%rsp), %r9 CC offset
movq 24(%rsp), %rdx CC protection
movq 32(%rsp), %rsi CC length
movq 40(%rsp), %r10 CC flags
movq $-1, %r8 CC -1
jmp .do_mmap_1
.open_file:
movq $2, %rax CC SYS_open
leaq 8(%rsp), %rdi CC rdi = %rsp + 8
xorq %rsi, %rsi CC flags = O_RDONLY
xorq %rdx, %rdx CC mode = 0
syscall
cmpq $-1, %rax CC open failed
jle .perror
movq %rdi, %rsp CC rsp = start of string
subq $1, %rsp
movq %rsp, %r14 CC r14 = start of string
.nextc:
addq $1, %rsp
movb (%rsp), %dil CC rdi = *rsp
cmpb $47, %dil CC *rsp == '/'?
jne .nextc1
movq %rsp, %r14 CC r14 = rsp
addq $1, %r14 CC r14 = char past separator
.nextc1:
cmpb $0, %dil CC *rsp == 0?
jne .nextc
addq $8, %rsp CC adjust past rsp prior to rounding
andq $-8, %rsp CC round rsp up to the next quad
testq $16, %r15 CC r15 & 16?
jz .primary
movq %rax, %r12 CC otherwise, move fd to r12
jmp .next_action
.primary:
movq %rax, %rbx CC if not, move fd to rbx
movq $157, %rax CC SYS_prctl
movq $15, %rdi CC PR_SET_NAME
movq %r14, %rsi CC arg1
xorq %rdx, %rdx CC arg2
xorq %r10, %r10 CC arg3
xorq %r8, %r8 CC arg4
xorq %r9, %r9 CC arg5
syscall
jmp .next_action
.perror:
movq %rax, %r12 CC error code
negq %r12
movq $1, %rax CC SYS_write
movq $1, %rdi CC stdout
leaq error(%rip), %rsi CC buffer
movq $23, %rdx CC count
syscall
movq $60, %rax CC SYS_exit
movq %r12, %rdi CC code
syscall
.rest_of_exec: CC rsp now points to six quads:
movq %rsp, %r8 CC now, they are r8
movq %r13, %rsp CC restore SP
popq %r10 CC argc
leaq 8(%rsp,%r10,8), %rsp CC now at start of environ
.skip_environ:
popq %r10 CC envp[N]
testq %r10, %r10 CC envp[n]?
jnz .skip_environ CC otherwise, rsp is now at the start of auxv
.one_auxv:
popq %rcx CC auxv type
addq $8, %rsp CC skip value
testq %rcx, %rcx CC is 0?
jz .cleanup
cmpq $3, %rcx CC is AT_PHDR?
je .replace_phdr
cmpq $4, %rcx CC is AT_PHENT?
je .replace_phent
cmpq $5, %rcx CC is AT_PHNUM?
je .replace_phnum
cmpq $9, %rcx CC is AT_ENTRY?
je .replace_entry
cmpq $7, %rcx CC is AT_BASE?
je .replace_base
jmp .one_auxv
.replace_phdr:
movq 40(%r8), %r9
movq %r9, -8(%rsp) CC set at_phdr
jmp .one_auxv
.replace_phent:
movq 24(%r8), %r9
movq %r9, -8(%rsp) CC set at_phent
jmp .one_auxv
.replace_phnum:
movq 32(%r8), %r9
movq %r9, -8(%rsp) CC set at_phnum
jmp .one_auxv
.replace_entry:
movq 16(%r8), %r9
movq %r9, -8(%rsp) CC set at_entry
jmp .one_auxv
.replace_base:
movq 48(%r8), %r9
movq %r9, -8(%rsp) CC set at_base
jmp .one_auxv
.cleanup:
movq $3, %rax CC SYS_close
cmpq $-1, %r12 CC see if interpreter fd is set
je .cleanup_1
movq %r12, %rdi
syscall
movq $3, %rax CC SYS_close
.cleanup_1:
movq %rbx, %rdi
syscall
.enter:
pushq $0
popfq CC clear FP state
movq %r13, %rsp CC restore SP
xorq %rdx, %rdx CC clear rtld_fini
jmpq *8(%r8) CC entry
error:
.ascii "_start: internal error."
timespec:
.quad 10
.quad 10

43
exec/mipsel-user.h Normal file
View file

@ -0,0 +1,43 @@
/* Program execution for Emacs.
Copyright (C) 2023 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 _MIPSEL_USER_H_
#define _MIPSEL_USER_H_
#include <sys/user.h>
#ifndef ELF_NGREG
#define ELF_NGREG 45
#endif /* ELF_NGREG */
/* This file defines a structure containing user mode general purpose
registers on 32-bit mipsel systems. */
struct mipsel_regs
{
/* General purpose registers. */
uint64_t gregs[ELF_NGREG];
};
#endif /* _MIPSEL_USER_H_ */

289
exec/mipsfpu.c Normal file
View file

@ -0,0 +1,289 @@
/* Program execution for Emacs.
Copyright (C) 2023 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 <errno.h>
#include "mipsfpu.h"
/* OABI MIPS systems support several different modes of execution.
Each mode differs in the size and utilization of the hardware
floating-point registers.
Linux normally sets the floating point mode to one appropriate for
execution, taking into account the floating point modes of the
interpreter and executable binaries. However, this logic is
forsaken when the `execve' system call is overwritten.
Thus, the correct floating point mode must be determined and set
within the loader binary. */
/* Various constants used throughout this code. */
#define MIPS_ABI_FP_ANY 0 /* FP ABI doesn't matter */
#define MIPS_ABI_FP_DOUBLE 1 /* -mdouble-float */
#define MIPS_ABI_FP_SINGLE 2 /* -msingle-float */
#define MIPS_ABI_FP_SOFT 3 /* -msoft-float */
#define MIPS_ABI_FP_OLD_64 4 /* -mips32r2 -mfp64 */
#define MIPS_ABI_FP_XX 5 /* -mfpxx */
#define MIPS_ABI_FP_64 6 /* -mips32r2 -mfp64 */
#define MIPS_ABI_FP_64A 7 /* -mips32r2 -mfp64 -mno-odd-spreg */
#define EF_MIPS_NOREORDER 1 /* A .noreorder directive was used. */
#define EF_MIPS_PIC 2 /* Contains PIC code. */
#define EF_MIPS_CPIC 4 /* Uses PIC calling sequence. */
#define EF_MIPS_XGOT 8
#define EF_MIPS_64BIT_WHIRL 16
#define EF_MIPS_ABI2 32
#define EF_MIPS_ABI_ON32 64
#define EF_MIPS_FP64 512 /* Uses FP64 (12 callee-saved). */
#define EF_MIPS_NAN2008 1024 /* Uses IEEE 754-2008 NaN encoding. */
#define EF_MIPS_ARCH 0xf0000000 /* MIPS architecture level. */
/* Structure describing the requirements of a single floating-point
ABI. */
struct mode_description
{
/* Whether or not the ABI only executes single precision
instructions, and can operate in both 32-bit or 64-bit floating
point mode. */
bool single;
/* Whether or not the ABI performs floating point operations in
software, using integer registers. */
bool soft;
/* Whether or not the ABI requires the use of 64-bit floating point
registers. */
bool fr1;
/* Whether or not the ABI requires the use of 64-bit floating point
registers on NABI systems, and 32-bit ones on OABI systems. */
bool frdefault;
/* Whether or not this ABI requires single precision floating point
emulation. */
bool fre;
};
static struct mode_description fpu_reqs[] =
{
[MIPS_ABI_FP_ANY] = { true, true, true, true, true, },
[MIPS_ABI_FP_DOUBLE] = { false, false, false, true, true, },
[MIPS_ABI_FP_SINGLE] = { true, false, false, false, false, },
[MIPS_ABI_FP_SOFT] = { false, true, false, false, false, },
[MIPS_ABI_FP_OLD_64] = { false, false, false, false, false, },
[MIPS_ABI_FP_XX] = { false, false, true, true, true, },
[MIPS_ABI_FP_64] = { false, false, true, false, false, },
[MIPS_ABI_FP_64A] = { false, false, true, false, true, },
};
/* Return whether or not the given floating-point ABI is valid. */
static bool
valid_abi_p (int abi)
{
switch (abi)
{
case MIPS_ABI_FP_ANY:
case MIPS_ABI_FP_DOUBLE:
case MIPS_ABI_FP_SINGLE:
case MIPS_ABI_FP_SOFT:
case MIPS_ABI_FP_OLD_64:
case MIPS_ABI_FP_XX:
case MIPS_ABI_FP_64:
case MIPS_ABI_FP_64A:
return true;
default:
return false;
}
}
/* Return the floating point mode appropriate for the specified
floating point ABI. */
static int
fp_mode_for_abi (int abi)
{
struct mode_description *desc;
desc = &fpu_reqs[abi];
if (desc->fre)
return FP_FRE;
else if (desc->fr1)
return FP_FR1;
return FP_FR0;
}
/* Determine whether or not the CPU is capable of operating in FR0
floating point mode. */
bool
cpu_supports_fr0_p (void)
{
#if defined __mips_isa_rev && __mips_isa_rev >= 6
return true;
#else /* !defined __mips_isa_rev | mips_isa_rev < 6 */
return false;
#endif /* defined __mips_isa_rev && mips_isa_rev >= 6 */
}
/* Determine the FPU mode for the executable whose ELF header is
HEADER. If INTERPRETER is non-NULL, also take an interpreter whose
header is INTERPRETER into account.
ABIFLAGS should be HEADER's corresponding PT_MIPS_ABIFLAGS program
header, and ABIFLAGS1 should be that of INTERPRETER, if set. Both
fields may be NULL if no PT_MIPS_ABIFLAGS header is present; in
that case, use HEADER->e_flags to determine the ABI instead.
Return the FPU mode in *MODE. Value is 0 upon success, 1
otherwise, with errno set. */
int
determine_fpu_mode (elf_header *header, elf_header *interpreter,
int *mode, struct mips_elf_abi_flags *abiflags,
struct mips_elf_abi_flags *abiflags1)
{
int exec_abi, interpreter_abi;
struct mode_description *exec_desc, *interpreter_desc, common;
/* Figure out the executable's floating point ABI. First, consult
header->e_flags, and use the old 64-bit floating point ABI if it
is specified. */
exec_abi = MIPS_ABI_FP_ANY;
/* First, check HEADER->e_flags. */
if (header->e_flags & EF_MIPS_FP64)
exec_abi = MIPS_ABI_FP_OLD_64;
/* Next, use ABIFLAGS if it exists. */
if (abiflags && valid_abi_p (abiflags->fp_abi))
exec_abi = abiflags->fp_abi;
else if (abiflags)
{
errno = ENOEXEC;
return 1;
}
/* Now determine that of the interpreter. */
interpreter_abi = MIPS_ABI_FP_ANY;
if (interpreter)
{
if (interpreter->e_flags & EF_MIPS_FP64)
interpreter_abi = MIPS_ABI_FP_OLD_64;
if (abiflags1 && valid_abi_p (abiflags->fp_abi))
interpreter_abi = abiflags->fp_abi;
else if (abiflags1)
{
errno = ELIBBAD;
return 1;
}
}
/* If no interpreter flag is set, just return that of the
executable. */
if (!interpreter)
{
*mode = fp_mode_for_abi (exec_abi);
return 0;
}
/* Otherwise, compare both ABIs and try to find one which will run
both kinds of code.
First, see if there's an easy way out: both ABIs are identical,
or one ABI is MIPS_ABI_FP_ANY. */
if (exec_abi == interpreter_abi)
{
*mode = fp_mode_for_abi (exec_abi);
return 0;
}
else if (exec_abi == MIPS_ABI_FP_ANY)
{
*mode = fp_mode_for_abi (interpreter_abi);
return 0;
}
else if (interpreter_abi == MIPS_ABI_FP_ANY)
{
*mode = fp_mode_for_abi (exec_abi);
return 0;
}
/* If that doesn't work, compare various characteristics of both
ABIs and select an appropriate floating point mode. */
exec_desc = &fpu_reqs[exec_abi];
interpreter_desc = &fpu_reqs[interpreter_abi];
/* Merge both sets of requirements. */
common.single = exec_desc->single && interpreter_desc->single;
common.soft = exec_desc->soft && interpreter_desc->soft;
common.fr1 = exec_desc->fr1 && interpreter_desc->fr1;
common.frdefault = exec_desc->frdefault && interpreter_desc->frdefault;
common.fre = exec_desc->fre && interpreter_desc->fre;
/* Default to a mode capable of running code expecting 32-bit
registers. */
if (!(header->e_flags & EF_MIPS_ABI2))
*mode = FP_FR0;
else
/* But in this case, use FR1. */
*mode = FP_FR1;
if (common.fre && !common.frdefault && !common.fr1)
/* Floating point emulation mode is required. */
*mode = FP_FRE;
else if ((common.fr1 && common.frdefault)
|| (common.single && !common.frdefault)
|| common.fr1)
/* 64-bit mode is required. */
*mode = FP_FR1;
else if (!common.fre && !common.frdefault
&& !common.fr1 && !common.single
&& !common.soft)
{
/* The floating point modes specified are incompatible. */
errno = ELIBBAD;
return -1;
}
return 0;
}

82
exec/mipsfpu.h Normal file
View file

@ -0,0 +1,82 @@
/* Program execution for Emacs.
Copyright (C) 2023 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 _MIPSFPU_H_
#define _MIPSFPU_H_
#include "exec.h"
struct mips_elf_abi_flags
{
/* Version of flags structure. */
uint16_t version;
/* The level of the ISA: 1-5, 32, 64. */
uint8_t isa_level;
/* The revision of ISA: 0 for MIPS V and below, 1-n otherwise. */
uint8_t isa_rev;
/* The size of general purpose registers. */
uint8_t gpr_size;
/* The size of co-processor 1 registers. */
uint8_t cpr1_size;
/* The size of co-processor 2 registers. */
uint8_t cpr2_size;
/* The floating-point ABI. */
uint8_t fp_abi;
/* Mask of processor-specific extensions. */
uint32_t isa_ext;
/* Mask of ASEs used. */
uint32_t ases;
/* Mask of general flags. */
uint32_t flags1;
/* Mask of general flags. */
uint32_t flags2;
};
/* Floating point modes. */
#define FP_FR0 0
#define FP_FR1 1
#define FP_FRE 3
/* Defined in mipsfpu.c. */
extern bool cpu_supports_fr0_p (void);
extern int determine_fpu_mode (elf_header *, elf_header *,
int *, struct mips_elf_abi_flags *,
struct mips_elf_abi_flags *);
#endif /* _MIPSFPU_H_ */

105
exec/test.c Normal file
View file

@ -0,0 +1,105 @@
/* Program execution for Emacs.
Copyright (C) 2023 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 <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/wait.h>
#include "exec.h"
static void
print_usage (void)
{
fprintf (stderr, "test loader-name program [args...]\n"
"Run the given program using the specified loader.\n");
}
extern char **environ;
/* This program uses libexec to wrap the execution of a child
process. */
int
main (int argc, char **argv)
{
pid_t pid, child;
int sig;
sigset_t sigset;
/* Check that there are a sufficient number of arguments. */
if (argc < 3)
{
print_usage ();
return 1;
}
exec_init (argv[1]);
/* Block SIGCHLD to avoid reentrant modification of the child
process list. */
sigemptyset (&sigset);
sigaddset (&sigset, SIGCHLD);
sigprocmask (SIG_BLOCK, &sigset, NULL);
if (!(pid = fork ()))
{
tracing_execve (argv[2], argv + 2, environ);
fprintf (stderr, "tracing_execve: %s\n",
strerror (errno));
exit (1);
}
else if (after_fork (pid))
{
fprintf (stderr, "after_fork: %s\n",
strerror (errno));
exit (1);
}
/* Now start waiting for child processes to exit. */
while (true)
{
child = exec_waitpid (-1, &sig, 0);
/* If pid is -1, a system call has been handled. */
if (child == -1)
continue;
/* If the main process exits, then exit as well. */
if (child == pid && !WIFSTOPPED (sig))
return (WIFEXITED (sig)
? WEXITSTATUS (sig)
: WTERMSIG (sig));
}
}

1420
exec/trace.c Normal file

File diff suppressed because it is too large Load diff

201
java/AndroidManifest.xml.in Normal file
View file

@ -0,0 +1,201 @@
<!-- @configure_input@
Copyright (C) 2023 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/>. -->
<!-- targetSandboxVersion must be 1. Otherwise, fascist security
restrictions prevent Emacs from making HTTP connections. -->
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.gnu.emacs"
android:targetSandboxVersion="1"
android:installLocation="auto"
android:requestLegacyExternalStorage="true"
android:versionCode="@emacs_major_version@"
android:versionName="@version@">
<!-- Paste in every permission in existence so Emacs can do
anything. -->
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.SET_WALLPAPER" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.RECEIVE_SMS" />
<uses-permission android:name="android.permission.RECEIVE_MMS"/>
<uses-permission android:name="android.permission.WRITE_SMS"/>
<uses-permission android:name="android.permission.READ_SMS"/>
<uses-permission android:name="android.permission.NFC" />
<uses-permission android:name="android.permission.TRANSMIT_IR" />
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.WAKE_LOCK"/>
<uses-permission android:name="android.permission.FOREGROUND_SERVICE"/>
<uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES"/>
<uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES"/>
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.CAMERA" />
<!-- This is required on Android 11 or later to access /sdcard. -->
<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE"/>
<uses-sdk android:minSdkVersion="@ANDROID_MIN_SDK@"
android:targetSdkVersion="33"/>
<application android:name="org.gnu.emacs.EmacsApplication"
android:label="Emacs"
android:icon="@drawable/emacs"
android:hardwareAccelerated="true"
android:supportsRtl="true"
android:theme="@style/EmacsStyle"
android:debuggable="@ANDROID_DEBUGGABLE@"
@ANDROID_SHARED_USER_ID@
android:extractNativeLibs="true">
<activity android:name="org.gnu.emacs.EmacsActivity"
android:launchMode="singleInstance"
android:windowSoftInputMode="adjustResize"
android:exported="true"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="org.gnu.emacs.EmacsOpenActivity"
android:taskAffinity="open.dialog"
android:excludeFromRecents="true"
android:exported="true">
<!-- Allow Emacs to open all kinds of files known to Android. -->
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<action android:name="android.intent.action.EDIT"/>
<action android:name="android.intent.action.PICK"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="image/aces"/>
<data android:mimeType="image/avci"/>
<data android:mimeType="image/avcs"/>
<data android:mimeType="image/avif"/>
<data android:mimeType="image/bmp"/>
<data android:mimeType="image/cgm"/>
<data android:mimeType="image/dicom-rle"/>
<data android:mimeType="image/dpx"/>
<data android:mimeType="image/emf"/>
<data android:mimeType="image/example"/>
<data android:mimeType="image/fits"/>
<data android:mimeType="image/g3fax"/>
<data android:mimeType="image/heic"/>
<data android:mimeType="image/heic-sequence"/>
<data android:mimeType="image/heif"/>
<data android:mimeType="image/heif-sequence"/>
<data android:mimeType="image/hej2k"/>
<data android:mimeType="image/hsj2"/>
<data android:mimeType="image/jls"/>
<data android:mimeType="image/jp2"/>
<data android:mimeType="image/jph"/>
<data android:mimeType="image/jphc"/>
<data android:mimeType="image/jpm"/>
<data android:mimeType="image/jpx"/>
<data android:mimeType="image/jxr"/>
<data android:mimeType="image/jxrA"/>
<data android:mimeType="image/jxrS"/>
<data android:mimeType="image/jxs"/>
<data android:mimeType="image/jxsc"/>
<data android:mimeType="image/jxsi"/>
<data android:mimeType="image/jxss"/>
<data android:mimeType="image/ktx"/>
<data android:mimeType="image/ktx2"/>
<data android:mimeType="image/naplps"/>
<data android:mimeType="image/png"/>
<data android:mimeType="image/prs.btif"/>
<data android:mimeType="image/prs.pti"/>
<data android:mimeType="image/pwg-raster"/>
<data android:mimeType="image/svg+xml"/>
<data android:mimeType="image/t38"/>
<data android:mimeType="image/tiff"/>
<data android:mimeType="image/tiff-fx"/>
<data android:mimeType="image/xpm"/>
<data android:mimeType="text/*"/>
<data android:mimeType="application/*xml"/>
<data android:mimeType="application/atom+xml"/>
<data android:mimeType="application/dxf"/>
<data android:mimeType="application/ecmascript"/>
<data android:mimeType="application/javascript"/>
<data android:mimeType="application/json"/>
<data android:mimeType="application/*log*"/>
<data android:mimeType="application/octet-stream"/>
<data android:mimeType="application/soap+xm"/>
<data android:mimeType="application/x-caramel"/>
<data android:mimeType="application/x-klaunch"/>
<data android:mimeType="application/x-latex"/>
<data android:mimeType="application/x-sh"/>
<data android:mimeType="application/x-tcl"/>
<data android:mimeType="application/x-tex*"/>
<data android:mimeType="application/x-troff*"/>
<data android:mimeType="application/xhtml+xml"/>
<data android:mimeType="application/xml*"/>
<data android:mimeType="application/zip"/>
<data android:mimeType="application/x-zip-compressed"/>
</intent-filter>
</activity>
<activity android:name="org.gnu.emacs.EmacsMultitaskActivity"
android:windowSoftInputMode="adjustResize"
android:exported="true"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden"/>
<activity android:autoRemoveFromRecents="true"
android:label="Emacs options"
android:exported="true"
android:name=".EmacsPreferencesActivity">
<intent-filter>
<action android:name="android.intent.action.APPLICATION_PREFERENCES" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
<provider android:name="org.gnu.emacs.EmacsDocumentsProvider"
android:authorities="org.gnu.emacs"
android:exported="true"
android:grantUriPermissions="true"
android:permission="android.permission.MANAGE_DOCUMENTS"
android:enabled="@bool/isAtLeastKitKat">
<intent-filter>
<action
android:name="android.content.action.DOCUMENTS_PROVIDER"/>
</intent-filter>
</provider>
<service android:name="org.gnu.emacs.EmacsService"
android:directBootAware="false"
android:enabled="true"
android:exported="false"
android:label="GNU Emacs service"/>
</application>
</manifest>

968
java/INSTALL Normal file
View file

@ -0,0 +1,968 @@
Installation instructions for Android
Copyright (C) 2023 Free Software Foundation, Inc.
See the end of the file for license conditions.
Please read the entirety of this file before attempting to build Emacs
as an application package which can run on Android devices.
When building from the source repository, make sure to read
INSTALL.REPO as well.
Android is an unusual operating system in that program binaries cannot
be produced on computers running Android themselves. Instead, they
must be built on some other computer using a set of tools known as the
``Android SDK'' (Software Development Kit) and the ``Android NDK''
(Native Development Kit.) Appropriate versions of both must be
obtained to build GNU Emacs; after being built, the generated binaries
will work on almost all Android devices. This document does not
elaborate on how both sets of tools can be obtained. However, for
your freedom's sake, you should use the Android SDK provided by the
Debian project.
In addition to the Android SDK and Android NDK, Emacs also requires
the Java compiler from OpenJDK 1.7.0 to be installed on your system,
along with a working `m4' macro processor. Building on GNU systems is
all that is officially supported. We are told that Mac OS works too,
and other Unix systems will likely work as well, but MS Windows and
Cygwin will not.
Once all of those tools are obtained, you may invoke the `configure'
script like so:
./configure --with-android=/path/to/android.jar \
ANDROID_CC=/path/to/android/ndk/cc \
SDK_BUILD_TOOLS=/path/to/sdk/build/tools
Replacing the paths in the command line above with:
- the path to the `android.jar' headers which come with the Android
SDK. They must correspond to Android version 13 (API level 33) or
later.
- the path to the C compiler in the Android NDK, for the kind of CPU
you are building Emacs to run on.
- the path to the directory in the Android SDK containing binaries
such as `aapt', `apksigner', and `d8'. These are used to build
the application package.
Where the type of CPU can either be `armeabi', `armv7*', `i686',
`x86_64', `mips', or `mips64'.
After the configuration process completes, you may run:
make all
Once `make' finishes, there should be a file in the `java' directory
named along the lines of:
emacs-<version>-<api-version>-<abi>.apk
where <api-version> is the oldest version of Android that the package
will run on, and <abi> is the type of Android machine the package was
built for.
The generated package can be uploaded onto an SD card (or similar
medium) and installed on-device.
BUILDING WITH OLD NDK VERSIONS
Building Emacs with an old version of the Android NDK requires special
setup. This is because there is no separate C compiler binary for
each version of Android in those versions of the NDK.
Before running `configure', you must identify three variables:
- What kind of Android system you are building Emacs for.
- The minimum API version of Android you want to build Emacs for.
- The locations of the system root and include files for that
version of Android in the NDK.
That information must then be specified as arguments to the NDK C
compiler. For example:
./configure [...] \
ANDROID_CC="i686-linux-android-gcc \
--sysroot=/path/to/ndk/platforms/android-14/arch-x86/"
ANDROID_CFLAGS="-isystem /path/to/ndk/sysroot/usr/include \
-isystem /path/to/ndk/sysroot/usr/include/i686-linux-android \
-D__ANDROID_API__=14"
Where __ANDROID_API__ and the version identifier in
"platforms/android-14" defines the version of Android you are building
for, and the include directories specify the paths to the relevant
Android headers. In addition, it may be necessary to specify
"-gdwarf-2", due to a bug in the Android NDK.
Even older versions of the Android SDK do not require the extra
`-isystem' directives.
Emacs is known to run on Android 2.2 (API version 8) or later, with
the NDK r10b or later. We wanted to make Emacs work on even older
versions of Android, but they are missing the required JNI graphics
library that allows Emacs to display text from C code.
Due to an extremely nasty bug in the Android 2.2 system, the generated
Emacs package cannot be compressed in builds for Android 2.2. As a
result, the Emacs package will be approximately 100 megabytes larger
than a compressed package for a newer version of Android.
BUILDING C++ DEPENDENCIES
With a new version of the NDK, dependencies containing C++ code should
build without any futher configuration. However, older versions
require that you use the ``make_standalone_toolchain.py'' script in
the NDK distribution to create a ``standalone toolchain'', and use
that instead, in order for C++ headers to be found.
See https://developer.android.com/ndk/guides/standalone_toolchain for
more details; when a ``standalone toolchain'' is specified, the
configure script will try to determine the location of the C++
compiler based on the C compiler specified. If that automatic
detection does not work, you can specify a C++ compiler yourself, like
so:
./configure --with-ndk-cxx=/path/to/toolchain/bin/i686-linux-android-g++
Some versions of the NDK have a bug, where GCC fails to locate
``stddef.h'' after being copied to a standalone toolchain. To work
around this problem (which normally exhibits itself when building C++
code), add:
-isystem /path/to/toolchain/include/c++/4.9.x
to ANDROID_CFLAGS.
DEBUG AND RELEASE BUILDS
Android makes a distinction between ``debug'' and ``release'' builds
of applications. With ``release'' builds, the system will apply
stronger optimizations to the application at the cost of being unable
to debug them with the steps in etc/DEBUG.
Emacs is built as a debuggable package by default, but:
./configure --without-android-debug
will create a release build of Emacs instead. This may be useful when
running Emacs on resource constrained machines.
If you are building an Emacs package for redistribution, we urge you
to provide both debug and release versions.
BUILDING WITH A SHARED USER ID
Sometimes it may be desirable to build Emacs so that it is able to
access executables from another program. To achieve this, that other
program must have a ``shared user ID'', and be signed with the same
signing key used to sign Emacs (normally `emacs.keystore'.)
Once you have both that signing key and its ``shared user ID'', you
can give it to configure:
./configure --with-shared-user-id=MY.SHARED.USER.ID
Don't do this if you already have Emacs installed with a different
shared user ID, as the system does not allow programs to change their
user IDs after being installed.
BUILDING WITH THIRD PARTY LIBRARIES
The Android NDK does not support the usual ways of locating third
party libraries, especially not via `pkg-config'. Instead, it uses
its own system called `ndk-build'. The one exception to this rule is
zlib, which is considered a part of the Android OS itself and is
available on all devices running Android.
Android also requires that each application include its own
dependencies, as the system makes no guarantee about the existence of
any particular library.
Emacs is not built with the `ndk-build' system. Instead, it is built
with Autoconf and Make.
However, it supports building and including dependencies which use the
similarly Make-based `ndk-build' system.
To use dependencies built through `ndk-build', you must specify a list
of directories within which Emacs will search for ``Android.mk''
files, like so:
./configure "--with-ndk-path=directory1 directory2"
If `configure' complains about not being able to find
``libc++_shared.so'', then you must locate that file in your copy of
the NDK, and specify it like so:
./configure --with-ndk-cxx-shared=/path/to/sysroot/libc++_shared.so
Emacs will then read the ``Android.mk'' file in each directory, and
automatically build and use those modules.
When building for Intel systems, some ``ndk-build'' modules require
the Netwide Assembler, usually installed under ``nasm'', to be present
on the system that is building Emacs.
Google, Inc. has adapted many common Emacs dependencies to use the
`ndk-build' system. Here is a non-exhaustive list of what is known to
work, along with what has to be patched to make them work:
libpng - https://android.googlesource.com/platform/external/libpng
libwebp - https://android.googlesource.com/platform/external/webp
(You must apply the patch at the end of this file for the resulting
binary to work on armv7 devices.)
giflib - https://android.googlesource.com/platform/external/giflib
(You must add LOCAL_EXPORT_CFLAGS := -I$(LOCAL_PATH) before
its Android.mk includes $(BUILD_STATIC_LIBRARY))
libjpeg-turbo - https://android.googlesource.com/platform/external/libjpeg-turbo
(You must add LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH) before
its Android.mk includes $(BUILD_SHARED_LIBRARY))
libxml2 - https://android.googlesource.com/platform/external/libxml2/
(You must also place the dependency icu4c in ``--with-ndk-path'',
and apply the patch at the end of this file.)
icu4c - https://android.googlesource.com/platform/external/icu/
(You must apply the patch at the end of this file.)
sqlite3 - https://android.googlesource.com/platform/external/sqlite/
(You must apply the patch at the end of this file, and add the `dist'
directory to ``--with-ndk-path''.)
libselinux - https://android.googlesource.com/platform/external/libselinux
(You must apply the patches at the end of the file, and obtain
the following three dependencies.)
libpackagelistparser
https://android.googlesource.com/platform/system/core/+/refs/heads/nougat-mr1-dev/libpackagelistparser/
libpcre - https://android.googlesource.com/platform/external/pcre
libcrypto - https://android.googlesource.com/platform/external/boringssl
(You must apply the patch at the end of this file when building for
ARM systems.)
Many of these dependencies have been migrated over to the
``Android.bp'' build system now used to build Android itself.
However, the old ``Android.mk'' Makefiles are still present in older
branches, and can be easily adapte to newer versions.
In addition, some Emacs dependencies provide `ndk-build' support
themselves:
libjansson - https://github.com/akheron/jansson
(You must add LOCAL_EXPORT_INCLUDES := $(LOCAL_C_INCLUDES) before
its Android.mk includes $(BUILD_SHARED_LIBRARY), then copy
android/jansson_config.h to android/jansson_private_config.h.)
Emacs developers have ported the following dependencies to ARM Android
systems:
gnutls, gmp - https://sourceforge.net/projects/android-ports-for-gnu-emacs
(Please see the section GNUTLS near the end of this file.)
libtiff - https://sourceforge.net/projects/android-ports-for-gnu-emacs
(Extract and point ``--with-ndk-path'' to tiff-4.5.0-emacs.tar.gz.)
tree-sitter - https://sourceforge.net/projects/android-ports-for-gnu-emacs
(Please see the section TREE-SITTER near the end of this file.)
harfbuzz - https://sourceforge.net/projects/android-ports-for-gnu-emacs
(Please see the section HARFBUZZ near the end of this file.)
And other developers have ported the following dependencies to Android
systems:
ImageMagick, lcms2 - https://github.com/MolotovCherry/Android-ImageMagick7
(Please see the section IMAGEMAGICK near the end of this file.)
We anticipate that most untested non-trivial ndk-build dependencies
will need adjustments in Emacs to work, as the Emacs build system
which emulates ndk-build is in an extremely early state.
GNUTLS
Modified copies of GnuTLS and its dependencies (such as libgmp,
libtasn1, p11-kit) which can be built with the ndk-build system can be
found at https://sourceforge.net/projects/android-ports-for-gnu-emacs.
They have only been tested on arm64 Android systems running Android
5.0 or later, and armv7l systems running Android 13 or later, so your
mileage may vary, especially if you are trying to build Emacs for
another kind of machine.
To build Emacs with GnuTLS, you must unpack each of the following tar
archives in that site:
gmp-6.2.1-emacs.tgz
gnutls-3.7.8-emacs.tar.gz
libtasn1-4.19.0-emacs.tar.gz
p11-kit-0.24.1-emacs.tar.gz
nettle-3.8-emacs.tar.gz
and add the resulting folders to ``--with-ndk-path''. Note that you
should not try to build these packages separately using any
`configure' script or Makefiles inside.
TREE-SITTER
A copy of tree-sitter modified to build with the ndk-build system can
also be found that URL. To build Emacs with tree-sitter, you must
unpack the following tar archive in that site:
tree-sitter-0.20.7-emacs.tar.gz
and add the resulting folder to ``--with-ndk-build''.
HARFBUZZ
A copy of HarfBuzz modified to build with the ndk-build system can
also be found at that URL. To build Emacs with HarfBuzz, you must
unpack the following tar archive in that site:
harfbuzz-7.1.0-emacs.tar.gz
and add the resulting folder to ``--with-ndk-build''.
IMAGEMAGICK
There is a third party port of ImageMagick to Android. Unfortunately,
the port also uses its own patched versions of libpng, libjpeg,
libtiff and libwebp, which conflict with those used by Emacs. Its
Makefiles were also written for MS Windows, so you must also apply the
patch at the end of this file.
PATCH FOR LIBXML2
This patch must be applied to the Android.mk in Google's version of
libxml2 before it can be built for Emacs. In addition, you must also
revert the commit `edb5870767fed8712a9b77ef34097209b61ab2db'.
diff --git a/Android.mk b/Android.mk
index 07c7b372..24f67e49 100644
--- a/Android.mk
+++ b/Android.mk
@@ -80,6 +80,7 @@ LOCAL_SHARED_LIBRARIES := libicuuc
LOCAL_MODULE:= libxml2
LOCAL_CLANG := true
LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
+LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)
include $(BUILD_SHARED_LIBRARY)
# For the host
@@ -94,3 +95,5 @@ LOCAL_MODULE := libxml2
LOCAL_CLANG := true
LOCAL_ADDITIONAL_DEPENDENCIES += $(LOCAL_PATH)/Android.mk
include $(BUILD_HOST_STATIC_LIBRARY)
+
+$(call import-module,libicuuc)
PATCH FOR ICU
This patch must be applied to icu4j/Android.mk in Google's version of
icu before it can be built for Emacs.
diff --git a/icu4j/Android.mk b/icu4j/Android.mk
index d1ab3d5..69eff81 100644
--- a/icu4j/Android.mk
+++ b/icu4j/Android.mk
@@ -69,7 +69,7 @@ include $(BUILD_STATIC_JAVA_LIBRARY)
# Path to the ICU4C data files in the Android device file system:
icu4c_data := /system/usr/icu
icu4j_config_root := $(LOCAL_PATH)/main/classes/core/src
-include external/icu/icu4j/adjust_icudt_path.mk
+include $(LOCAL_PATH)/adjust_icudt_path.mk
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(icu4j_src_files)
diff --git a/icu4c/source/common/Android.mk b/icu4c/source/common/Android.mk
index 8e5f757..44bb130 100644
--- a/icu4c/source/common/Android.mk
+++ b/icu4c/source/common/Android.mk
@@ -231,7 +231,7 @@ include $(CLEAR_VARS)
LOCAL_SRC_FILES += $(src_files)
LOCAL_C_INCLUDES += $(c_includes) $(optional_android_logging_includes)
LOCAL_CFLAGS += $(local_cflags) -DPIC -fPIC
-LOCAL_SHARED_LIBRARIES += libdl $(optional_android_logging_libraries)
+LOCAL_SHARED_LIBRARIES += libdl libstdc++ $(optional_android_logging_libraries)
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE := libicuuc
LOCAL_RTTI_FLAG := -frtti
PATCH FOR SQLITE3
diff --git a/dist/Android.mk b/dist/Android.mk
index bf277d2..36734d9 100644
--- a/dist/Android.mk
+++ b/dist/Android.mk
@@ -141,6 +141,7 @@ include $(BUILD_HOST_EXECUTABLE)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := $(common_src_files)
LOCAL_CFLAGS += $(minimal_sqlite_flags)
+LOCAL_EXPORT_C_INCLUDES += $(LOCAL_PATH)
LOCAL_MODULE:= libsqlite_static_minimal
LOCAL_SDK_VERSION := 23
include $(BUILD_STATIC_LIBRARY)
diff --git a/dist/sqlite3.c b/dist/sqlite3.c
index b0536a4..8fa1ee9 100644
--- a/dist/sqlite3.c
+++ b/dist/sqlite3.c
@@ -26474,7 +26474,7 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
*/
#if !defined(HAVE_POSIX_FALLOCATE) \
&& (_XOPEN_SOURCE >= 600 || _POSIX_C_SOURCE >= 200112L)
-# define HAVE_POSIX_FALLOCATE 1
+/* # define HAVE_POSIX_FALLOCATE 1 */
#endif
/*
PATCH FOR WEBP
diff --git a/Android.mk b/Android.mk
index c7bcb0f5..d4da1704 100644
--- a/Android.mk
+++ b/Android.mk
@@ -28,9 +28,10 @@ ifneq ($(findstring armeabi-v7a, $(TARGET_ARCH_ABI)),)
# Setting LOCAL_ARM_NEON will enable -mfpu=neon which may cause illegal
# instructions to be generated for armv7a code. Instead target the neon code
# specifically.
- NEON := c.neon
- USE_CPUFEATURES := yes
- WEBP_CFLAGS += -DHAVE_CPU_FEATURES_H
+ # NEON := c.neon
+ # USE_CPUFEATURES := yes
+ # WEBP_CFLAGS += -DHAVE_CPU_FEATURES_H
+ NEON := c
else
NEON := c
endif
PATCHES FOR SELINUX
diff --git a/Android.mk b/Android.mk
index 659232e..1e64fd6 100644
--- a/Android.mk
+++ b/Android.mk
@@ -116,3 +116,7 @@ LOCAL_STATIC_LIBRARIES := libselinux
LOCAL_WHOLE_STATIC_LIBRARIES := libpcre
LOCAL_C_INCLUDES := external/pcre
include $(BUILD_HOST_EXECUTABLE)
+
+$(call import-module,libpcre)
+$(call import-module,libpackagelistparser)
+$(call import-module,libcrypto)
diff --git a/src/android.c b/src/android.c
index 5206a9f..b351ffc 100644
--- a/src/android.c
+++ b/src/android.c
@@ -21,8 +21,7 @@
#include <selinux/label.h>
#include <selinux/avc.h>
#include <openssl/sha.h>
-#include <private/android_filesystem_config.h>
-#include <log/log.h>
+#include <android/log.h>
#include "policy.h"
#include "callbacks.h"
#include "selinux_internal.h"
@@ -686,6 +685,7 @@ static int seapp_context_lookup(enum seapp_kind kind,
seinfo = parsedseinfo;
}
+#if 0
userid = uid / AID_USER;
isOwner = (userid == 0);
appid = uid % AID_USER;
@@ -702,9 +702,13 @@ static int seapp_context_lookup(enum seapp_kind kind,
username = "_app";
appid -= AID_APP;
} else {
+#endif
username = "_isolated";
+ appid = 0;
+#if 0
appid -= AID_ISOLATED_START;
}
+#endif
if (appid >= CAT_MAPPING_MAX_ID || userid >= CAT_MAPPING_MAX_ID)
goto err;
@@ -1662,8 +1666,10 @@ int selinux_log_callback(int type, const char *fmt, ...)
va_start(ap, fmt);
if (vasprintf(&strp, fmt, ap) != -1) {
+#if 0
LOG_PRI(priority, "SELinux", "%s", strp);
LOG_EVENT_STRING(AUDITD_LOG_TAG, strp);
+#endif
free(strp);
}
va_end(ap);
PATCH FOR BORINGSSL
diff --git a/Android.mk b/Android.mk
index 3e3ef2a..277d4a9 100644
--- a/Android.mk
+++ b/Android.mk
@@ -27,7 +27,9 @@ LOCAL_MODULE := libcrypto
LOCAL_EXPORT_C_INCLUDE_DIRS := $(LOCAL_PATH)/src/include
LOCAL_ADDITIONAL_DEPENDENCIES := $(LOCAL_PATH)/Android.mk $(LOCAL_PATH)/crypto-sources.mk
LOCAL_CFLAGS += -fvisibility=hidden -DBORINGSSL_SHARED_LIBRARY -DBORINGSSL_IMPLEMENTATION -DOPENSSL_SMALL -Wno-unused-parameter
+LOCAL_CFLAGS_arm = -DOPENSSL_STATIC_ARMCAP -DOPENSSL_NO_ASM
LOCAL_SDK_VERSION := 9
+LOCAL_LDFLAGS = --no-undefined
# sha256-armv4.S does not compile with clang.
LOCAL_CLANG_ASFLAGS_arm += -no-integrated-as
LOCAL_CLANG_ASFLAGS_arm64 += -march=armv8-a+crypto
diff --git a/sources.mk b/sources.mk
index e82f3d5..be3a3c4 100644
--- a/sources.mk
+++ b/sources.mk
@@ -337,20 +337,20 @@ linux_aarch64_sources := \
linux-aarch64/crypto/sha/sha256-armv8.S\
linux-aarch64/crypto/sha/sha512-armv8.S\
-linux_arm_sources := \
- linux-arm/crypto/aes/aes-armv4.S\
- linux-arm/crypto/aes/aesv8-armx32.S\
- linux-arm/crypto/aes/bsaes-armv7.S\
- linux-arm/crypto/bn/armv4-mont.S\
- linux-arm/crypto/modes/ghash-armv4.S\
- linux-arm/crypto/modes/ghashv8-armx32.S\
- linux-arm/crypto/sha/sha1-armv4-large.S\
- linux-arm/crypto/sha/sha256-armv4.S\
- linux-arm/crypto/sha/sha512-armv4.S\
- src/crypto/chacha/chacha_vec_arm.S\
- src/crypto/cpu-arm-asm.S\
- src/crypto/curve25519/asm/x25519-asm-arm.S\
- src/crypto/poly1305/poly1305_arm_asm.S\
+# linux_arm_sources := \
+# linux-arm/crypto/aes/aes-armv4.S\
+# linux-arm/crypto/aes/aesv8-armx32.S\
+# linux-arm/crypto/aes/bsaes-armv7.S\
+# linux-arm/crypto/bn/armv4-mont.S\
+# linux-arm/crypto/modes/ghash-armv4.S\
+# linux-arm/crypto/modes/ghashv8-armx32.S\
+# linux-arm/crypto/sha/sha1-armv4-large.S\
+# linux-arm/crypto/sha/sha256-armv4.S\
+# linux-arm/crypto/sha/sha512-armv4.S\
+# src/crypto/chacha/chacha_vec_arm.S\
+# src/crypto/cpu-arm-asm.S\
+# src/crypto/curve25519/asm/x25519-asm-arm.S\
+# src/crypto/poly1305/poly1305_arm_asm.S\
linux_x86_sources := \
linux-x86/crypto/aes/aes-586.S\
PATCH FOR IMAGEMAGICK
diff --git a/Android.mk b/Android.mk
index 5ab6699..4441417 100644
--- a/Android.mk
+++ b/Android.mk
@@ -52,6 +52,20 @@ LZMA_LIB_PATH := $(LOCAL_PATH)/xz-5.2.4
BZLIB_LIB_PATH := $(LOCAL_PATH)/bzip-1.0.8
LCMS_LIB_PATH := $(LOCAL_PATH)/liblcms2-2.9
+LIBBZ2_ENABLED := true
+LIBFFTW_ENABLED := true
+LIBFREETYPE2_ENABLED := true
+LIBJPEG_TURBO_ENABLED := true
+LIBLZMA_ENABLED := true
+LIBOPENJPEG_ENABLED := true
+LIBPNG_ENABLED := true
+LIBTIFF_ENABLED := true
+LIBWEBP_ENABLED := true
+LIBXML2_ENABLED := true
+LIBZLIB_ENABLED := true
+LIBLCMS2_ENABLED := true
+BUILD_MAGICKWAND := true
+
#-------------------------------------------------------------
# Include all modules
#-------------------------------------------------------------
@@ -68,6 +82,9 @@ include $(MAKE_PATH)/libjpeg-turbo.mk
# libopenjpeg
include $(MAKE_PATH)/libopenjpeg.mk
+# libwebp
+include $(MAKE_PATH)/libwebp.mk
+
# libtiff
include $(MAKE_PATH)/libtiff.mk
@@ -77,9 +94,6 @@ include $(MAKE_PATH)/libpng.mk
# libfreetype2
include $(MAKE_PATH)/libfreetype2.mk
-# libwebp
-include $(MAKE_PATH)/libwebp.mk
-
# libfftw
include $(MAKE_PATH)/libfftw.mk
diff --git a/libjpeg-turbo-2.0.2/jconfig.h b/libjpeg-turbo-2.0.2/jconfig.h
index 47d14c9..5c6f8ee 100644
--- a/libjpeg-turbo-2.0.2/jconfig.h
+++ b/libjpeg-turbo-2.0.2/jconfig.h
@@ -1,57 +1,43 @@
-/* autogenerated jconfig.h based on Android.mk var JCONFIG_FLAGS */
+/* autogenerated jconfig.h based on Android.mk var JCONFIG_FLAGS */
#ifndef JPEG_LIB_VERSION
#define JPEG_LIB_VERSION 62
#endif
-
#ifndef LIBJPEG_TURBO_VERSION
#define LIBJPEG_TURBO_VERSION 2.0.2
#endif
-
#ifndef LIBJPEG_TURBO_VERSION_NUMBER
#define LIBJPEG_TURBO_VERSION_NUMBER 202
#endif
-
#ifndef C_ARITH_CODING_SUPPORTED
#define C_ARITH_CODING_SUPPORTED
#endif
-
#ifndef D_ARITH_CODING_SUPPORTED
#define D_ARITH_CODING_SUPPORTED
#endif
-
#ifndef MEM_SRCDST_SUPPORTED
#define MEM_SRCDST_SUPPORTED
#endif
-
#ifndef WITH_SIMD
#define WITH_SIMD
#endif
-
#ifndef BITS_IN_JSAMPLE
#define BITS_IN_JSAMPLE 8
#endif
-
#ifndef HAVE_LOCALE_H
#define HAVE_LOCALE_H
#endif
-
#ifndef HAVE_STDDEF_H
#define HAVE_STDDEF_H
#endif
-
#ifndef HAVE_STDLIB_H
#define HAVE_STDLIB_H
#endif
-
#ifndef NEED_SYS_TYPES_H
#define NEED_SYS_TYPES_H
#endif
-
#ifndef HAVE_UNSIGNED_CHAR
#define HAVE_UNSIGNED_CHAR
#endif
-
#ifndef HAVE_UNSIGNED_SHORT
#define HAVE_UNSIGNED_SHORT
#endif
-
diff --git a/libxml2-2.9.9/encoding.c b/libxml2-2.9.9/encoding.c
index a3aaf10..60f165b 100644
--- a/libxml2-2.9.9/encoding.c
+++ b/libxml2-2.9.9/encoding.c
@@ -2394,7 +2394,6 @@ xmlCharEncOutput(xmlOutputBufferPtr output, int init)
{
int ret;
size_t written;
- size_t writtentot = 0;
size_t toconv;
int c_in;
int c_out;
@@ -2451,7 +2450,6 @@ retry:
xmlBufContent(in), &c_in);
xmlBufShrink(in, c_in);
xmlBufAddLen(out, c_out);
- writtentot += c_out;
if (ret == -1) {
if (c_out > 0) {
/* Can be a limitation of iconv or uconv */
@@ -2536,7 +2534,6 @@ retry:
}
xmlBufAddLen(out, c_out);
- writtentot += c_out;
goto retry;
}
}
@@ -2567,9 +2564,7 @@ xmlCharEncOutFunc(xmlCharEncodingHandler *handler, xmlBufferPtr out,
xmlBufferPtr in) {
int ret;
int written;
- int writtentot = 0;
int toconv;
- int output = 0;
if (handler == NULL) return(-1);
if (out == NULL) return(-1);
@@ -2612,7 +2607,6 @@ retry:
in->content, &toconv);
xmlBufferShrink(in, toconv);
out->use += written;
- writtentot += written;
out->content[out->use] = 0;
if (ret == -1) {
if (written > 0) {
@@ -2622,8 +2616,6 @@ retry:
ret = -3;
}
- if (ret >= 0) output += ret;
-
/*
* Attempt to handle error cases
*/
@@ -2700,7 +2692,6 @@ retry:
}
out->use += written;
- writtentot += written;
out->content[out->use] = 0;
goto retry;
}
diff --git a/libxml2-2.9.9/xpath.c b/libxml2-2.9.9/xpath.c
index 5e3bb9f..505ec82 100644
--- a/libxml2-2.9.9/xpath.c
+++ b/libxml2-2.9.9/xpath.c
@@ -10547,7 +10547,7 @@ xmlXPathCompFilterExpr(xmlXPathParserContextPtr ctxt) {
static xmlChar *
xmlXPathScanName(xmlXPathParserContextPtr ctxt) {
- int len = 0, l;
+ int l;
int c;
const xmlChar *cur;
xmlChar *ret;
@@ -10567,7 +10567,6 @@ xmlXPathScanName(xmlXPathParserContextPtr ctxt) {
(c == '_') || (c == ':') ||
(IS_COMBINING(c)) ||
(IS_EXTENDER(c)))) {
- len += l;
NEXTL(l);
c = CUR_CHAR(l);
}
diff --git a/make/libicu4c.mk b/make/libicu4c.mk
index 21ec121..8b77865 100644
--- a/make/libicu4c.mk
+++ b/make/libicu4c.mk
@@ -250,7 +250,7 @@ LOCAL_MODULE := libicuuc
LOCAL_SRC_FILES := $(src_files)
# when built in android, they require uconfig_local (because of android project), but we don't need this
-$(shell > $(ICU_COMMON_PATH)/unicode/uconfig_local.h echo /* Autogenerated stub file to make libicuuc build happy */) \
+$(shell > $(ICU_COMMON_PATH)/unicode/uconfig_local.h echo /\* Autogenerated stub file to make libicuuc build happy \*/) \
ifeq ($(LIBXML2_ENABLED),true)
include $(BUILD_STATIC_LIBRARY)
diff --git a/make/libjpeg-turbo.mk b/make/libjpeg-turbo.mk
index d39dd41..fdebcf3 100644
--- a/make/libjpeg-turbo.mk
+++ b/make/libjpeg-turbo.mk
@@ -230,30 +230,30 @@ JCONFIG_FLAGS += \
HAVE_UNSIGNED_SHORT
JCONFIGINT_FLAGS += \
- BUILD="20190814" \
- PACKAGE_NAME="libjpeg-turbo" \
- VERSION="2.0.2"
+ BUILD=\"20190814\" \
+ PACKAGE_NAME=\"libjpeg-turbo\" \
+ VERSION=\"2.0.2\"
# originally defined in jconfigint.h, but the substitution has problems with spaces
LOCAL_CFLAGS := \
-DINLINE="inline __attribute__((always_inline))"
# create definition file jconfig.h, needed in order to build
-$(shell echo /* autogenerated jconfig.h based on Android.mk var JCONFIG_FLAGS */ > $(JPEG_LIB_PATH)/jconfig.h)
+$(shell echo \/\* autogenerated jconfig.h based on Android.mk var JCONFIG_FLAGS \*\/ > $(JPEG_LIB_PATH)/jconfig.h)
$(foreach name,$(JCONFIG_FLAGS), \
$(if $(findstring =,$(name)), \
- $(shell >>$(JPEG_LIB_PATH)/jconfig.h echo #ifndef $(firstword $(subst =, ,$(name)))) \
+ $(shell >>$(JPEG_LIB_PATH)/jconfig.h echo \#ifndef $(firstword $(subst =, ,$(name)))) \
, \
- $(shell >>$(JPEG_LIB_PATH)/jconfig.h echo #ifndef $(name)) \
+ $(shell >>$(JPEG_LIB_PATH)/jconfig.h echo \#ifndef $(name)) \
) \
- $(shell >>$(JPEG_LIB_PATH)/jconfig.h echo #define $(subst =, ,$(name))) \
- $(shell >>$(JPEG_LIB_PATH)/jconfig.h echo #endif) \
+ $(shell >>$(JPEG_LIB_PATH)/jconfig.h echo \#define $(subst =, ,$(name))) \
+ $(shell >>$(JPEG_LIB_PATH)/jconfig.h echo \#endif) \
$(shell >> $(JPEG_LIB_PATH)/jconfig.h echo.) \
)
# create definition file jconfigint.h, needed in order to build
-$(shell >$(JPEG_LIB_PATH)/jconfigint.h echo /* autogenerated jconfigint.h based on Android.mk vars JCONFIGINT_FLAGS */)
-$(foreach name,$(JCONFIGINT_FLAGS),$(shell >>$(JPEG_LIB_PATH)/jconfigint.h echo #define $(subst =, ,$(name))))
+$(shell >$(JPEG_LIB_PATH)/jconfigint.h echo /\* autogenerated jconfigint.h based on Android.mk vars JCONFIGINT_FLAGS \*/)
+$(foreach name,$(JCONFIGINT_FLAGS),$(shell >>$(JPEG_LIB_PATH)/jconfigint.h echo \#define $(subst =, ,$(name))))
ifeq ($(LIBJPEG_TURBO_ENABLED),true)
include $(BUILD_STATIC_LIBRARY)
diff --git a/make/liblcms2.mk b/make/liblcms2.mk
index e1fd3b9..29ca791 100644
--- a/make/liblcms2.mk
+++ b/make/liblcms2.mk
@@ -10,6 +10,10 @@ LOCAL_C_INCLUDES := \
$(LCMS_LIB_PATH)/include \
$(LCMS_LIB_PATH)/src
+LOCAL_EXPORT_C_INCLUDES := \
+ $(LCMS_LIB_PATH) \
+ $(LCMS_LIB_PATH)/include \
+ $(LCMS_LIB_PATH)/src
LOCAL_CFLAGS := \
-DHAVE_FUNC_ATTRIBUTE_VISIBILITY=1 \
diff --git a/make/libmagick++-7.mk b/make/libmagick++-7.mk
index 5352ccb..929396d 100644
--- a/make/libmagick++-7.mk
+++ b/make/libmagick++-7.mk
@@ -12,7 +12,7 @@ LOCAL_C_INCLUDES := \
ifneq ($(STATIC_BUILD),true)
LOCAL_LDFLAGS += -fexceptions
- LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog -lz
+ LOCAL_LDLIBS := -llog -lz
endif
LOCAL_SRC_FILES := \
diff --git a/make/libmagickcore-7.mk b/make/libmagickcore-7.mk
index 81293b2..d51fced 100644
--- a/make/libmagickcore-7.mk
+++ b/make/libmagickcore-7.mk
@@ -25,6 +25,7 @@ else ifeq ($(TARGET_ARCH_ABI),x86_64)
endif
+LOCAL_EXPORT_C_INCLUDES += $(IMAGE_MAGICK)
LOCAL_C_INCLUDES += \
$(IMAGE_MAGICK) \
@@ -45,10 +46,9 @@ LOCAL_C_INCLUDES += \
$(BZLIB_LIB_PATH) \
$(LCMS_LIB_PATH)/include
-
ifneq ($(STATIC_BUILD),true)
# ignored in static library builds
- LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog -lz
+ LOCAL_LDLIBS := -llog -lz
endif
diff --git a/make/libmagickwand-7.mk b/make/libmagickwand-7.mk
index 7be2fb6..0bbcca5 100644
--- a/make/libmagickwand-7.mk
+++ b/make/libmagickwand-7.mk
@@ -14,7 +14,7 @@ LOCAL_C_INCLUDES := \
# always ignored in static builds
ifneq ($(STATIC_BUILD),true)
- LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog -lz
+ LOCAL_LDLIBS := -llog -lz
endif
LOCAL_SRC_FILES := \
@@ -54,6 +54,29 @@ ifeq ($(OPENCL_BUILD),true)
LOCAL_SHARED_LIBRARIES += libopencl
endif
+LOCAL_SHARED_LIBRARIES += libstdc++
+
+ifeq ($(TARGET_ARCH_ABI),arm64-v8a)
+ LOCAL_EXPORT_C_INCLUDES += $(IMAGE_MAGICK)/configs/arm64
+ LOCAL_C_INCLUDES += $(IMAGE_MAGICK)/configs/arm64
+else ifeq ($(TARGET_ARCH_ABI),armeabi-v7a)
+ LOCAL_EXPORT_C_INCLUDES += $(IMAGE_MAGICK)/configs/arm
+ LOCAL_C_INCLUDES += $(IMAGE_MAGICK)/configs/arm
+else ifeq ($(TARGET_ARCH_ABI),x86)
+ LOCAL_EXPORT_C_INCLUDES += $(IMAGE_MAGICK)/configs/x86
+ LOCAL_C_INCLUDES += $(IMAGE_MAGICK)/configs/x86
+else ifeq ($(TARGET_ARCH_ABI),x86_64)
+ LOCAL_EXPORT_C_INCLUDES += $(IMAGE_MAGICK)/configs/x86-64
+ LOCAL_C_INCLUDES += $(IMAGE_MAGICK)/configs/x86-64
+
+ ifneq ($(STATIC_BUILD),true)
+ LOCAL_LDFLAGS += -latomic
+ endif
+
+endif
+
+LOCAL_EXPORT_C_INCLUDES += $(IMAGE_MAGICK)
+
ifeq ($(BUILD_MAGICKWAND),true)
ifeq ($(STATIC_BUILD),true)
LOCAL_STATIC_LIBRARIES := \
diff --git a/make/libpng.mk b/make/libpng.mk
index 24fb8ac..dda05fd 100644
--- a/make/libpng.mk
+++ b/make/libpng.mk
@@ -30,6 +30,7 @@ ifeq ($(TARGET_ARCH_ABI), arm64-v8a)
endif # TARGET_ARCH_ABI == arm64-v8a
+LOCAL_EXPORT_C_INCLUDES := $(PNG_LIB_PATH)
LOCAL_C_INCLUDES := $(PNG_LIB_PATH)
LOCAL_SRC_FILES += \
diff --git a/make/libtiff.mk b/make/libtiff.mk
index ca43f25..2b17508 100644
--- a/make/libtiff.mk
+++ b/make/libtiff.mk
@@ -12,6 +12,9 @@ LOCAL_C_INCLUDES := \
$(LZMA_LIB_PATH)/liblzma/api \
$(WEBP_LIB_PATH)/src
+LOCAL_EXPORT_C_INCLUDES := \
+ $(TIFF_LIB_PATH)
+
ifeq ($(LIBLZMA_ENABLED),true)
LOCAL_CFLAGS += -DLZMA_SUPPORT=1
endif
diff --git a/make/magick.mk b/make/magick.mk
index 3ba4b1d..5471608 100644
--- a/make/magick.mk
+++ b/make/magick.mk
@@ -18,7 +18,7 @@ LOCAL_C_INCLUDES := \
$(FREETYPE_LIB_PATH)/include
-LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -llog -lz
+LOCAL_LDLIBS := -llog -lz
LOCAL_SRC_FILES := \
$(IMAGE_MAGICK)/utilities/magick.c \
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/>.

330
java/Makefile.in Normal file
View file

@ -0,0 +1,330 @@
### @configure_input@
# Copyright (C) 2023 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/>.
top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
srcdir = @srcdir@
builddir = @builddir@
version = @version@
# Don't install movemail if mailutils are to be used.
emacs_use_mailutils = @emacs_use_mailutils@
# This is the host lib-src and lib, not the cross compiler's lib-src.
libsrc = ../lib-src
EXEEXT = @EXEEXT@
-include ${top_builddir}/src/verbose.mk
SHELL = @SHELL@
JAVAC = @JAVAC@
AAPT = @AAPT@
D8 = @D8@
ZIPALIGN = @ZIPALIGN@
JARSIGNER = @JARSIGNER@
APKSIGNER = @APKSIGNER@
JARSIGNER_FLAGS =
ANDROID_JAR = @ANDROID_JAR@
ANDROID_ABI = @ANDROID_ABI@
ANDROID_SDK_18_OR_EARLIER = @ANDROID_SDK_18_OR_EARLIER@
ANDROID_SDK_8_OR_EARLIER = @ANDROID_SDK_8_OR_EARLIER@
WARN_JAVAFLAGS = @WARN_JAVAFLAGS@
JAVAFLAGS = $(WARN_JAVAFLAGS) -classpath "$(ANDROID_JAR):$(srcdir)"
FIND_DELETE = @FIND_DELETE@
# Android 4.3 and earlier require Emacs to be signed with a different
# digital signature algorithm.
ifneq (,$(ANDROID_SDK_18_OR_EARLIER))
JARSIGNER_FLAGS = -sigalg MD5withRSA -digestalg SHA1
else
JARSIGNER_FLAGS =
endif
# When building Emacs for Android 2.2, assets must not be compressed.
# Otherwise, the asset manager fails to extract files larger than 1
# MB.
ifneq (,$(ANDROID_SDK_8_OR_EARLIER))
AAPT_ASSET_ARGS = -0 ""
else
AAPT_ASSET_ARGS =
endif
SIGN_EMACS = -keystore $(srcdir)/emacs.keystore -storepass \
emacs1 $(JARSIGNER_FLAGS)
SIGN_EMACS_V2 = sign --v2-signing-enabled --ks \
$(srcdir)/emacs.keystore -debuggable-apk-permitted \
--ks-pass pass:emacs1
JAVA_FILES := $(wildcard $(srcdir)/org/gnu/emacs/*.java)
RESOURCE_FILES := $(foreach file,$(wildcard $(srcdir)/res/*), \
$(wildcard $(file)/*))
# R.java is a file generated by the `aapt' utility containing
# constants that can then be used to locate ``resource identifiers''.
# It is not a regular file and should not be compiled as Java source
# code. Instead, it is automatically included by the Java compiler.
RESOURCE_FILE := $(srcdir)/org/gnu/emacs/R.java
# CLASS_FILES is what should actually be built and included in the
# resulting Emacs executable. The Java compiler might generate more
# than one class file for each source file, so this only serves as a
# list of dependencies for Make.
CLASS_FILES := $(foreach file,$(JAVA_FILES),$(basename $(file)).class)
# Remove RESOURCE_FILE from JAVA_FILES, if it is already present.
JAVA_FILES := $(filter-out $(RESOURCE_FILE),$(JAVA_FILES))
# Compute the name for the Emacs application package. This should be:
# emacs-<version>-<min-sdk>-<abi>.apk
ANDROID_MIN_SDK := @ANDROID_MIN_SDK@
APK_NAME := emacs-$(version)-$(ANDROID_MIN_SDK)-$(ANDROID_ABI).apk
# How this stuff works.
# emacs.apk depends on emacs.apk-in, which is simply a ZIP archive
# containing the following files:
# lib/$(ANDROID_ABI)/libemacs.so
# lib/$(ANDROID_ABI)/libandroid-emacs.so
# lib/$(ANDROID_ABI)/libctags.so
# lib/$(ANDROID_ABI)/libetags.so
# lib/$(ANDROID_ABI)/libhexl.so
# lib/$(ANDROID_ABI)/libmovemail.so
# lib/$(ANDROID_ABI)/librcs2log.so
# lib/$(ANDROID_ABI)/libebrowse.so
# assets/info/
# assets/etc/
# assets/lisp/
.PHONY: emacs.apk-in all
all: $(APK_NAME)
# Binaries to cross-compile.
CROSS_SRC_BINS := $(top_builddir)/cross/src/android-emacs
CROSS_LIBSRC_BINS := $(top_builddir)/cross/lib-src/ctags \
$(top_builddir)/cross/lib-src/hexl \
$(top_builddir)/cross/lib-src/ebrowse \
$(top_builddir)/cross/lib-src/emacsclient \
$(top_builddir)/cross/lib-src/etags
CROSS_LIBSRC_BINS_MOVEMAIL := $(top_builddir)/cross/lib-src/movemail
CROSS_EXEC_BINS := $(top_builddir)/exec/exec1 $(top_builddir)/exec/loader
CROSS_BINS = $(CROSS_SRC_BINS) $(CROSS_LIBSRC_BINS) $(CROSS_EXEC_BINS)
ifneq ($(emacs_use_mailutils),yes)
CROSS_LIBSRC_BINS := $(CROSS_LIBSRC_BINS) $(CROSS_LIBSRC_BINS_MOVEMAIL)
endif
# Libraries to cross-compile.
CROSS_LIBS = $(top_builddir)/cross/src/libemacs.so
# Make sure gnulib is built first!
# If not, then the recursive invocations of make below will try to
# build gnulib at the same time.
CROSS_ARCHIVES = $(top_builddir)/cross/lib/libgnu.a
# Third party libraries to compile.
-include $(top_builddir)/cross/ndk-build/ndk-build.mk
.PHONY: $(CROSS_BINS) $(CROSS_LIBS) $(CROSS_ARCHIVES)
# There should only be a single invocation of $(MAKE) -C
# $(top_srcdir)/cross for each directory under $(top_srcdir)/cross.
$(CROSS_SRC_BINS) $(CROSS_LIBS) &: $(CROSS_ARCHIVES)
$(MAKE) -C $(top_builddir)/cross $(foreach file, \
$(CROSS_SRC_BINS) \
$(CROSS_LIBS), \
src/$(notdir $(file)))
$(CROSS_LIBSRC_BINS) &: $(CROSS_ARCHIVES)
$(MAKE) -C $(top_builddir)/cross $(foreach file, \
$(CROSS_LIBSRC_BINS), \
lib-src/$(notdir $(file)))
$(CROSS_ARCHIVES):
$(MAKE) -C $(top_builddir)/cross lib/libgnu.a
# These two binaries are helpers used to execute binaries on Android
# 10 and later.
$(CROSS_EXEC_BINS) &:
$(MAKE) -C $(top_builddir)/exec $(notdir $(CROSS_EXEC_BINS))
# This is needed to generate the ``.directory-tree'' file used by the
# Android emulations of readdir and faccessat.
$(libsrc)/asset-directory-tool:
$(MAKE) -C $(libsrc) $(notdir $@)
# install_tmp is a directory used to generate emacs.apk-in.
# That is then packaged into $(APK_NAME).
# There is no need to depend on NDK_BUILD_SHARED as libemacs.so
# does already.
.PHONY: install_temp install_temp/assets/directory-tree
install_temp: $(CROSS_BINS) $(CROSS_LIBS) $(RESOURCE_FILES)
$(AM_V_GEN)
# Make the working directory for this stuff
$(AM_V_SILENT) rm -rf install_temp
$(AM_V_SILENT) mkdir -p install_temp/lib/$(ANDROID_ABI)
$(AM_V_SILENT) mkdir -p install_temp/assets/etc
$(AM_V_SILENT) mkdir -p install_temp/assets/lisp
$(AM_V_SILENT) mkdir -p install_temp/assets/info
# Install architecture independents to assets/etc and assets/lisp
$(AM_V_SILENT) cp -r $(top_srcdir)/lisp install_temp/assets
$(AM_V_SILENT) cp -r $(top_srcdir)/etc install_temp/assets
$(AM_V_SILENT) cp -r $(top_srcdir)/info install_temp/assets
# Remove undesirable files from those directories.
$(AM_V_SILENT) \
for subdir in `find install_temp -type d -print`; do \
chmod a+rx $${subdir} ; \
rm -rf $${subdir}/.gitignore ; \
rm -rf $${subdir}/.DS_Store ; \
rm -rf $${subdir}/#* ; \
rm -rf $${subdir}/.#* ; \
rm -rf $${subdir}/*~ ; \
rm -rf $${subdir}/*.orig ; \
rm -rf $${subdir}/ChangeLog* ; \
rm -rf $${subdir}/[mM]akefile*[.-]in ; \
rm -rf $${subdir}/Makefile; \
done
# Generate the directory tree for those directories.
# Install architecture dependents to lib/$(ANDROID_ABI). This
# perculiar naming scheme is required to make Android preserve these
# binaries upon installation.
$(AM_V_SILENT) \
for file in $(CROSS_BINS); do \
if [ -x $$file ]; then \
filename=`basename $$file`; \
cp -f $$file install_temp/lib/$(ANDROID_ABI)/lib$${filename}.so; \
fi \
done
$(AM_V_SILENT) \
for file in $(CROSS_LIBS); do \
if [ -x $$file ]; then \
cp -f $$file install_temp/lib/$(ANDROID_ABI); \
fi \
done
ifneq ($(NDK_BUILD_SHARED),)
$(AM_V_SILENT) cp -f $(NDK_BUILD_SHARED) \
install_temp/lib/$(ANDROID_ABI)
endif
install_temp/assets/directory-tree: $(libsrc)/asset-directory-tool \
install_temp install_temp/assets/version
$(AM_V_GEN) $(libsrc)/asset-directory-tool install_temp/assets \
install_temp/assets/directory-tree
install_temp/assets/version: install_temp
$(AM_V_GEN) { (git rev-parse HEAD || echo "Unknown") \
&& (git rev-parse --abbrev-ref HEAD \
|| echo "Unknown") } 2> /dev/null > $@
install_temp/assets/build_info: install_temp
$(AM_V_GEN) { hostname; date +%s; } > $@
emacs.apk-in: install_temp install_temp/assets/directory-tree \
install_temp/assets/version install_temp/assets/build_info \
AndroidManifest.xml
# Package everything. Specifying the assets on this command line is
# necessary for AAssetManager_getNextFileName to work on old versions
# of Android. Make sure not to generate R.java, as it's already been
# generated.
$(AM_V_AAPT) $(AAPT) p -I "$(ANDROID_JAR)" -F $@ \
-f -M AndroidManifest.xml $(AAPT_ASSET_ARGS) \
-A install_temp/assets \
-S $(top_srcdir)/java/res -J install_temp
$(AM_V_SILENT) pushd install_temp &> /dev/null; \
$(AAPT) add ../$@ `find lib -type f`; \
popd &> /dev/null
$(AM_V_SILENT) rm -rf install_temp
# Makefile itself.
.PRECIOUS: $(top_srcdir)/config.status Makefile
$(top_srcdir)/config.status: $(top_srcdir)/configure.ac $(top_srcdir)/m4/*.m4
$(MAKE) -C $(dir $@) $(notdir $@)
Makefile: $(top_srcdir)/config.status $(top_srcdir)/java/Makefile.in
$(MAKE) -C .. java/$@
# AndroidManifest.xml:
AndroidManifest.xml: $(top_srcdir)/configure.ac $(top_srcdir)/m4/*.m4 \
$(srcdir)/AndroidManifest.xml.in
pushd ..; ./config.status java/AndroidManifest.xml; popd
# R.java:
$(RESOURCE_FILE): $(RESOURCE_FILES)
$(AM_V_GEN) $(AAPT) p -I "$(ANDROID_JAR)" -f \
-J $(dir $@) -M AndroidManifest.xml \
-S $(top_srcdir)/java/res
# Make all class files depend on R.java being built.
$(CLASS_FILES): $(RESOURCE_FILE)
.SUFFIXES: .java .class
$(CLASS_FILES) &: $(JAVA_FILES)
$(AM_V_JAVAC) $(JAVAC) $(JAVAFLAGS) $(JAVA_FILES)
$(AM_V_SILENT) touch $(CLASS_FILES)
# N.B. that find must be called all over again in case javac generated
# nested classes.
classes.dex: $(CLASS_FILES)
$(AM_V_D8) $(D8) --classpath $(ANDROID_JAR) \
$(subst $$,\$$,$(shell find $(srcdir) -type f \
-name *.class)) --output $(builddir)
# When emacs.keystore expires, regenerate it with:
#
# keytool -genkey -v -keystore emacs.keystore -alias "Emacs keystore" \
# -keyalg RSA -sigalg SHA1withRSA -keysize 2048 -validity 100000
.PHONY: clean maintainer-clean
$(APK_NAME): classes.dex emacs.apk-in $(srcdir)/emacs.keystore
$(AM_V_GEN)
$(AM_V_SILENT) cp -f emacs.apk-in $@.unaligned
$(AM_V_SILENT) $(AAPT) add $@.unaligned classes.dex
$(AM_V_SILENT) $(JARSIGNER) $(SIGN_EMACS) $@.unaligned "Emacs keystore"
$(AM_V_SILENT) $(ZIPALIGN) -f 4 $@.unaligned $@
# Signing must happen after alignment!
$(AM_V_SILENT) $(APKSIGNER) $(SIGN_EMACS_V2) $@
$(AM_V_SILENT) rm -f $@.unaligned *.idsig
# TAGS generation.
ETAGS = $(top_builddir)/lib-src/etags
$(ETAGS): FORCE
$(MAKE) -C ../lib-src $(notdir $@)
tagsfiles = $(JAVA_FILES) $(RESOURCE_FILE)
.PHONY: tags FORCE
tags: TAGS
TAGS: $(ETAGS) $(tagsfiles)
$(AM_V_GEN) $(ETAGS) $(tagsfiles)
clean:
rm -f *.apk emacs.apk-in *.dex *.unaligned *.class *.idsig
rm -rf install-temp $(RESOURCE_FILE) TAGS
find . -name '*.class' $(FIND_DELETE)
maintainer-clean distclean bootstrap-clean: clean
rm -f Makefile ndk-build.mk

908
java/README Normal file
View file

@ -0,0 +1,908 @@
This directory holds the Java sources of the port of GNU Emacs to
Android-like systems, along with files needed to create an application
package out of them. If you need to build this port, please read the
file INSTALL in this directory.
The ``org/gnu/emacs'' subdirectory contains the Java sources under the
``org.gnu.emacs'' package identifier.
``AndroidManifest.xml'' contains a manifest describing the Java
sources to the system.
The ``res'' directory contains resources, mainly the Emacs icon and
several ``boolean resources'' which are used as a form of conditional
evaluation for manifest entries.
`emacs.keystore' is the signing key used to build Emacs. It is kept
here, and we encourage all people redistributing Emacs to use this
key. It holds no security value, and otherwise it will be impossible
to install different builds of Emacs on top of each other.
Please keep the Java code indented with tabs and formatted according
to the rules for C code in the GNU coding standards. Always use
C-style comments.
======================================================================
OVERVIEW OF JAVA
Emacs developers do not know Java, and there is no reason they should
have to. Thus, the code in this directory is confined to what is
strictly necessary to support Emacs, and only uses a subset of Java
written in a way that is easily understandable to C programmers.
Java is required because the entire Android runtime is based around
Java, and there is no way to write an Android program which runs
without Java.
This text exists to prime other Emacs developers, already familar with
C, on the basic architecture of the Android port, and to teach them
how to read and write the Java code found in this directory.
Java is an object oriented language with automatic memory management
compiled down to bytecode, which is then subject to interpretation by
a Java virtual machine.
What that means, is that:
struct emacs_window
{
int some_fields;
int of_emacs_window;
};
static void
do_something_with_emacs_window (struct emacs_window *a, int n)
{
a->some_fields = a->of_emacs_window + n;
}
would be written:
public class EmacsWindow
{
public int someFields;
public int ofEmacsWindow;
public void
doSomething (int n)
{
someFields = ofEmacsWindow + n;
}
}
and instead of doing:
do_something_with_emacs_window (my_window, 1);
you say:
myWindow.doSomething (1);
In addition to functions associated with an object of a given class
(such as EmacsWindow), Java also has two other kinds of functions.
The first are so-called ``static'' functions (the static means
something entirely different from what it does in C.)
A static function, while still having to be defined within a class,
can be called without any object. Instead of the object, you write
the name of the Java class within which it is defined. For example,
the following C code:
int
multiply_a_with_b_and_then_add_c (int a, int b, int c)
{
return a * b + c;
}
would be:
public class EmacsSomething
{
public static int
multiplyAWithBAndThenAddC (int a, int b, int c)
{
return a * b + c;
}
};
Then, instead of calling:
int foo;
foo = multiply_a_with_b_then_add_c (1, 2, 3);
you say:
int foo;
foo = EmacsSomething.multiplyAWithBAndThenAddC (1, 2, 3);
In Java, ``static'' does not mean that the function is only used
within its compilation unit! Instead, the ``private'' qualifier is
used to mean more or less the same thing:
static void
this_procedure_is_only_used_within_this_file (void)
{
do_something ();
}
becomes
public class EmacsSomething
{
private static void
thisProcedureIsOnlyUsedWithinThisClass ()
{
}
}
the other kind are called ``constructors''. They are functions that
must be called to allocate memory to hold a class:
public class EmacsFoo
{
int bar;
public
EmacsFoo (int tokenA, int tokenB)
{
bar = tokenA + tokenB;
}
}
now, the following statement:
EmacsFoo foo;
foo = new EmacsFoo (1, 2);
becomes more or less equivalent to the following C code:
struct emacs_foo
{
int bar;
};
struct emacs_foo *
make_emacs_foo (int token_a, int token_b)
{
struct emacs_foo *foo;
foo = xmalloc (sizeof *foo);
foo->bar = token_a + token_b;
return foo;
}
/* ... */
struct emacs_foo *foo;
foo = make_emacs_foo (1, 2);
A class may have any number of constructors, or no constructors at
all, in which case the compiler inserts an empty constructor.
Sometimes, you will see Java code that looks like this:
allFiles = filesDirectory.listFiles (new FileFilter () {
@Override
public boolean
accept (File file)
{
return (!file.isDirectory ()
&& file.getName ().endsWith (".pdmp"));
}
});
This is Java's version of GCC's nested function extension. The major
difference is that the nested function may still be called even after
it goes out of scope, and always retains a reference to the class and
local variables around where it was called.
Being an object-oriented language, Java also allows defining that a
class ``extends'' another class. The following C code:
struct a
{
long thirty_two;
};
struct b
{
struct a a;
long long sixty_four;
};
extern void do_something (struct a *);
void
my_function (struct b *b)
{
do_something (&b->a);
}
is roughly equivalent to the following Java code, split into two
files:
A.java
public class A
{
int thirtyTwo;
public void
doSomething ()
{
etcEtcEtc ();
}
};
B.java
public class B extends A
{
long sixty_four;
public static void
myFunction (B b)
{
b.doSomething ();
}
}
the Java runtime has transformed the call to ``b.doSomething'' to
``((A) b).doSomething''.
However, Java also allows overriding this behavior, by specifying the
@Override keyword:
public class B extends A
{
long sixty_four;
@Override
public void
doSomething ()
{
Something.doSomethingTwo ();
super.doSomething ();
}
}
now, any call to ``doSomething'' on a ``B'' created using ``new B ()''
will end up calling ``Something.doSomethingTwo'', before calling back
to ``A.doSomething''. This override also applies in reverse; that is
to say, even if you write:
((A) b).doSomething ();
B's version of doSomething will still be called, if ``b'' was created
using ``new B ()''.
This mechanism is used extensively throughout the Java language and
Android windowing APIs.
Elsewhere, you will encounter Java code that defines arrays:
public class EmacsFrobinicator
{
public static void
emacsFrobinicate (int something)
{
int[] primesFromSomething;
primesFromSomething = new int[numberOfPrimes];
/* ... */
}
}
Java arrays are similar to C arrays in that they can not grow. But
they are very much unlike C arrays in that they are always references
(as opposed to decaying into pointers in only some situations), and
contain information about their length.
If another function named ``frobinicate1'' takes an array as an
argument, then it need not take the length of the array.
Instead, it may simply iterate over the array like so:
int i, k;
for (i = 0; i < array.length; ++i)
{
k = array[i];
Whatever.doSomethingWithK (k);
}
The syntax used to define arrays is also slightly different. As
arrays are always references, there is no way for you to tell the
runtime to allocate an array of size N in a structure (class.)
Instead, if you need an array of that size, you must declare a field
with the type of the array, and allocate the array inside the class's
constructor, like so:
public class EmacsArrayContainer
{
public int[] myArray;
public
EmacsArrayContainer ()
{
myArray = new array[10];
}
}
while in C, you could just have written:
struct emacs_array_container
{
int my_array[10];
};
or, possibly even better,
typedef int emacs_array_container[10];
Alas, Java has no equivalent of `typedef'.
Like in C, Java string literals are delimited by double quotes.
Unlike C, however, strings are not NULL-terminated arrays of
characters, but a distinct type named ``String''. They store their
own length, characters in Java's 16-bit ``char'' type, and are capable
of holding NULL bytes.
Instead of writing:
wchar_t character;
extern char *s;
size_t s;
for (/* determine n, s in a loop. */)
s += mbstowc (&character, s, n);
or:
const char *byte;
for (byte = my_string; *byte; ++byte)
/* do something with *byte. */;
or perhaps even:
size_t length, i;
char foo;
length = strlen (my_string);
for (i = 0; i < length; ++i)
foo = my_string[i];
you write:
char foo;
int i;
for (i = 0; i < myString.length (); ++i)
foo = myString.charAt (0);
Java also has stricter rules on what can be used as a truth value in a
conditional. While in C, any non-zero value is true, Java requires
that every truth value be of the boolean type ``boolean''.
What this means is that instead of simply writing:
if (foo || bar)
where foo can either be 1 or 0, and bar can either be NULL or a
pointer to something, you must explicitly write:
if (foo != 0 || bar != null)
in Java.
JAVA NATIVE INTERFACE
Java also provides an interface for C code to interface with Java.
C functions exported from a shared library become static Java
functions within a class, like so:
public class EmacsNative
{
/* Obtain the fingerprint of this build of Emacs. The fingerprint
can be used to determine the dump file name. */
public static native String getFingerprint ();
/* Set certain parameters before initializing Emacs.
assetManager must be the asset manager associated with the
context that is loading Emacs. It is saved and remains for the
remainder the lifetime of the Emacs process.
filesDir must be the package's data storage location for the
current Android user.
libDir must be the package's data storage location for native
libraries. It is used as PATH.
cacheDir must be the package's cache directory. It is used as
the `temporary-file-directory'.
pixelDensityX and pixelDensityY are the DPI values that will be
used by Emacs.
classPath must be the classpath of this app_process process, or
NULL.
emacsService must be the EmacsService singleton, or NULL. */
public static native void setEmacsParams (AssetManager assetManager,
String filesDir,
String libDir,
String cacheDir,
float pixelDensityX,
float pixelDensityY,
String classPath,
EmacsService emacsService);
}
Where the corresponding C functions are located in android.c, and
loaded by the special invocation:
static
{
System.loadLibrary ("emacs");
};
where ``static'' defines a section of code which will be run upon the
object (containing class) being loaded. This is like:
__attribute__((constructor))
on systems where shared object constructors are supported.
See http://docs.oracle.com/en/java/javase/19/docs/specs/jni/intro.html
for more details.
OVERVIEW OF ANDROID
When the Android system starts an application, it does not actually
call the application's ``main'' function. It may not even start the
application's process if one is already running.
Instead, Android is organized around components. When the user opens
the ``Emacs'' icon, the Android system looks up and starts the
component associated with the ``Emacs'' icon. In this case, the
component is called an activity, and is declared in
the AndroidManifest.xml in this directory:
<activity android:name="org.gnu.emacs.EmacsActivity"
android:launchMode="singleTop"
android:windowSoftInputMode="adjustResize"
android:exported="true"
android:configChanges="orientation|screenSize|screenLayout|keyboardHidden">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
This tells Android to start the activity defined in ``EmacsActivity''
(defined in org/gnu/emacs/EmacsActivity.java), a class extending the
Android class ``Activity''.
To do so, the Android system creates an instance of ``EmacsActivity''
and the window system window associated with it, and eventually calls:
Activity activity;
activity.onCreate (...);
But which ``onCreate'' is really called?
It is actually the ``onCreate'' defined in EmacsActivity.java, as
it overrides the ``onCreate'' defined in Android's own Activity class:
@Override
public void
onCreate (Bundle savedInstanceState)
{
FrameLayout.LayoutParams params;
Intent intent;
Then, this is what happens step-by-step within the ``onCreate''
function:
/* See if Emacs should be started with -Q. */
intent = getIntent ();
EmacsService.needDashQ
= intent.getBooleanExtra ("org.gnu.emacs.START_DASH_Q",
false);
Here, Emacs obtains the intent (a request to start a component) which
was used to start Emacs, and sets a special flag if it contains a
request for Emacs to start with the ``-Q'' command-line argument.
/* Set the theme to one without a title bar. */
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
setTheme (android.R.style.Theme_DeviceDefault_NoActionBar);
else
setTheme (android.R.style.Theme_NoTitleBar);
Next, Emacs sets an appropriate theme for the activity's associated
window decorations.
params = new FrameLayout.LayoutParams (LayoutParams.MATCH_PARENT,
LayoutParams.MATCH_PARENT);
/* Make the frame layout. */
layout = new FrameLayout (this);
layout.setLayoutParams (params);
/* Set it as the content view. */
setContentView (layout);
Then, Emacs creates a ``FrameLayout'', a widget that holds a single
other widget, and makes it the activity's ``content view''.
The activity itself is a ``FrameLayout'', so the ``layout parameters''
here apply to the FrameLayout itself, and not its children.
/* Maybe start the Emacs service if necessary. */
EmacsService.startEmacsService (this);
And after that, Emacs calls the static function ``startEmacsService'',
defined in the class ``EmacsService''. This starts the Emacs service
component if necessary.
/* Add this activity to the list of available activities. */
EmacsWindowAttachmentManager.MANAGER.registerWindowConsumer (this);
super.onCreate (savedInstanceState);
Finally, Emacs registers that this activity is now ready to receive
top-level frames (windows) created from Lisp.
Activities come and go, but Emacs has to stay running in the mean
time. Thus, Emacs also defines a ``service'', which is a long-running
component that the Android system allows to run in the background.
Let us go back and review the definition of ``startEmacsService'':
public static void
startEmacsService (Context context)
{
if (EmacsService.SERVICE == null)
{
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
/* Start the Emacs service now. */
context.startService (new Intent (context,
EmacsService.class));
else
/* Display the permanant notification and start Emacs as a
foreground service. */
context.startForegroundService (new Intent (context,
EmacsService.class));
}
}
If ``EmacsService.SERVICE'' does not yet exist, what this does is to
tell the ``context'' (the equivalent of an Xlib Display *) to start a
service defined by the class ``EmacsService''. Eventually, this
results in ``EmacsService.onCreate'' being called:
@Override
public void
onCreate ()
{
AssetManager manager;
Context app_context;
String filesDir, libDir, cacheDir, classPath;
double pixelDensityX;
double pixelDensityY;
Here is what this function does, step-by-step:
SERVICE = this;
First, it sets the special static variable ``SERVICE'' to ``this'',
which is a pointer to the ``EmacsService' object that was created.
handler = new Handler (Looper.getMainLooper ());
Next, it creates a ``Handler'' object for the ``main looper''.
This is a helper structure which allows executing code on the Android
user interface thread.
manager = getAssets ();
app_context = getApplicationContext ();
metrics = getResources ().getDisplayMetrics ();
pixelDensityX = metrics.xdpi;
pixelDensityY = metrics.ydpi;
Finally, it obtains:
- the asset manager, which is used to retrieve assets packaged
into the Emacs application package.
- the application context, used to obtain application specific
information.
- the display metrics, and from them, the X and Y densities in dots
per inch.
Then, inside a ``try'' block:
try
{
/* Configure Emacs with the asset manager and other necessary
parameters. */
filesDir = app_context.getFilesDir ().getCanonicalPath ();
libDir = getLibraryDirectory ();
cacheDir = app_context.getCacheDir ().getCanonicalPath ();
It obtains the names of the Emacs home, shared library, and temporary
file directories.
/* Now provide this application's apk file, so a recursive
invocation of app_process (through android-emacs) can
find EmacsNoninteractive. */
classPath = getApkFile ();
The name of the Emacs application package.
Log.d (TAG, "Initializing Emacs, where filesDir = " + filesDir
+ ", libDir = " + libDir + ", and classPath = " + classPath);
Prints a debug message to the Android system log with this
information.
EmacsNative.setEmacsParams (manager, filesDir, libDir,
cacheDir, (float) pixelDensityX,
(float) pixelDensityY,
classPath, this);
And calls the native function ``setEmacsParams'' (defined in
android.c) to configure Emacs with this information.
/* Start the thread that runs Emacs. */
thread = new EmacsThread (this, needDashQ);
thread.start ();
Then, it allocates an ``EmacsThread'' object, and starts that thread.
Inside that thread is where Emacs's C code runs.
}
catch (IOException exception)
{
EmacsNative.emacsAbort ();
return;
And here is the purpose of the ``try'' block. Functions related to
file names in Java will signal errors of various types upon failure.
This ``catch'' block means that the Java virtual machine will abort
execution of the contents of the ``try'' block as soon as an error of
type ``IOException'' is encountered, and begin executing the contents
of the ``catch'' block.
Any failure of that type here is a crash, and
``EmacsNative.emacsAbort'' is called to quickly abort the process to
get a useful backtrace.
}
}
Now, let us look at the definition of the class ``EmacsThread'', found
in org/gnu/emacs/EmacsThread.java:
public class EmacsThread extends Thread
{
/* Whether or not Emacs should be started -Q. */
private boolean startDashQ;
public
EmacsThread (EmacsService service, boolean startDashQ)
{
super ("Emacs main thread");
this.startDashQ = startDashQ;
}
@Override
public void
run ()
{
String args[];
if (!startDashQ)
args = new String[] { "libandroid-emacs.so", };
else
args = new String[] { "libandroid-emacs.so", "-Q", };
/* Run the native code now. */
EmacsNative.initEmacs (args, EmacsApplication.dumpFileName);
}
};
The class itself defines a single field, ``startDashQ'', a constructor
with an unused argument of the type ``EmacsService'' (which is useful
while debugging) and a flag ``startDashQ'', and a single function
``run'', overriding the same function in the class ``Thread''.
When ``thread.start'' is called, the Java virtual machine creates a
new thread, and then calls the function ``run'' within that thread.
This function then computes a suitable argument vector, and calls
``EmacsNative.initEmacs'' (defined in android.c), which then calls a
modified version of the regular Emacs ``main'' function.
At that point, Emacs initialization proceeds as usual:
Vinitial_window_system is set, loadup.el calls `normal-top-level',
which calls `command-line', and finally
`window-system-initialization', which initializes the `android'
terminal interface as usual.
What happens here is the same as on other platforms. Now, here is
what happens when the initial frame is created: Fx_create_frame calls
`android_create_frame_window' to create a top level window:
static void
android_create_frame_window (struct frame *f)
{
struct android_set_window_attributes attributes;
enum android_window_value_mask attribute_mask;
attributes.background_pixel = FRAME_BACKGROUND_PIXEL (f);
attribute_mask = ANDROID_CW_BACK_PIXEL;
block_input ();
FRAME_ANDROID_WINDOW (f)
= android_create_window (FRAME_DISPLAY_INFO (f)->root_window,
f->left_pos,
f->top_pos,
FRAME_PIXEL_WIDTH (f),
FRAME_PIXEL_HEIGHT (f),
attribute_mask, &attributes);
unblock_input ();
}
This calls the function `android_create_window' with some arguments
whose meanings are identical to the arguments to `XCreateWindow'.
Here is the definition of `android_create_window', in android.c:
android_window
android_create_window (android_window parent, int x, int y,
int width, int height,
enum android_window_value_mask value_mask,
struct android_set_window_attributes *attrs)
{
static jclass class;
static jmethodID constructor;
jobject object, parent_object, old;
android_window window;
android_handle prev_max_handle;
bool override_redirect;
What does it do? First, some context:
At any time, there can be at most 65535 Java objects referred to by
the rest of Emacs through the Java native interface. Each such object
is assigned a ``handle'' (similar to an XID on X) and given a unique
type. The function `android_resolve_handle' returns the JNI `jobject'
associated with a given handle.
parent_object = android_resolve_handle (parent, ANDROID_HANDLE_WINDOW);
Here, it is being used to look up the `jobject' associated with the
`parent' handle.
prev_max_handle = max_handle;
window = android_alloc_id ();
Next, `max_handle' is saved, and a new handle is allocated for
`window'.
if (!window)
error ("Out of window handles!");
An error is signalled if Emacs runs out of available handles.
if (!class)
{
class = (*android_java_env)->FindClass (android_java_env,
"org/gnu/emacs/EmacsWindow");
assert (class != NULL);
Then, if this initialization has not yet been completed, Emacs
proceeds to find the Java class named ``EmacsWindow''.
constructor
= (*android_java_env)->GetMethodID (android_java_env, class, "<init>",
"(SLorg/gnu/emacs/EmacsWindow;"
"IIIIZ)V");
assert (constructor != NULL);
And it tries to look up the constructor, which should take seven
arguments:
S - a short. (the handle ID)
Lorg/gnu/Emacs/EmacsWindow; - an instance of the EmacsWindow
class. (the parent)
IIII - four ints. (the window geometry.)
Z - a boolean. (whether or not the
window is override-redirect; see
XChangeWindowAttributes.)
old = class;
class = (*android_java_env)->NewGlobalRef (android_java_env, class);
(*android_java_env)->ExceptionClear (android_java_env);
ANDROID_DELETE_LOCAL_REF (old);
Next, it saves a global reference to the class and deletes the local
reference. Global references will never be deallocated by the Java
virtual machine as long as they still exist.
if (!class)
memory_full (0);
}
/* N.B. that ANDROID_CW_OVERRIDE_REDIRECT can only be set at window
creation time. */
override_redirect = ((value_mask
& ANDROID_CW_OVERRIDE_REDIRECT)
&& attrs->override_redirect);
object = (*android_java_env)->NewObject (android_java_env, class,
constructor, (jshort) window,
parent_object, (jint) x, (jint) y,
(jint) width, (jint) height,
(jboolean) override_redirect);
Then, it creates an instance of the ``EmacsWindow'' class with the
appropriate arguments and previously determined constructor.
if (!object)
{
(*android_java_env)->ExceptionClear (android_java_env);
max_handle = prev_max_handle;
memory_full (0);
If creating the object fails, Emacs clears the ``pending exception''
and signals that it is out of memory.
}
android_handles[window].type = ANDROID_HANDLE_WINDOW;
android_handles[window].handle
= (*android_java_env)->NewGlobalRef (android_java_env,
object);
(*android_java_env)->ExceptionClear (android_java_env);
ANDROID_DELETE_LOCAL_REF (object);
Otherwise, it associates a new global reference to the object with the
handle, and deletes the local reference returned from the JNI
NewObject function.
if (!android_handles[window].handle)
memory_full (0);
If allocating the global reference fails, Emacs signals that it is out
of memory.
android_change_window_attributes (window, value_mask, attrs);
return window;
Otherwise, it applies the specified window attributes and returns the
handle of the new window.
}

364
java/debug.sh Executable file
View file

@ -0,0 +1,364 @@
#!/bin/bash
### Run Emacs under GDB or JDB on Android.
## Copyright (C) 2023 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/>.
set -m
oldpwd=`pwd`
cd `dirname $0`
devices=`adb devices | grep device | awk -- '/device\y/ { print $1 }' -`
device=
progname=$0
package=org.gnu.emacs
activity=org.gnu.emacs.EmacsActivity
gdb_port=5039
jdb_port=64013
jdb=no
attach_existing=no
gdbserver=
gdb=gdb
while [ $# -gt 0 ]; do
case "$1" in
## This option specifies the serial number of a device to use.
"--device" )
device="$2"
if [ -z device ]; then
echo "You must specify an argument to --device"
exit 1
fi
shift
;;
"--help" )
echo "Usage: $progname [options] -- [gdb options]"
echo ""
echo " --device DEVICE run Emacs on the specified device"
echo " --port PORT run the GDB server on a specific port"
echo " --jdb-port PORT run the JDB server on a specific port"
echo " --jdb run JDB instead of GDB"
echo " --gdb use specified GDB binary"
echo " --attach-existing attach to an existing process"
echo " --gdbserver BINARY upload and use the specified gdbserver binary"
echo " --help print this message"
echo ""
echo "Available devices:"
for device in $devices; do
echo " " $device
done
echo ""
exit 0
;;
"--jdb" )
jdb=yes
;;
"--gdb" )
shift
gdb=$1
;;
"--gdbserver" )
shift
gdbserver=$1
;;
"--port" )
shift
gdb_port=$1
;;
"--jdb-port" )
shift
jdb_port=$1
;;
"--attach-existing" )
attach_existing=yes
;;
"--" )
shift
gdbargs=$@
break;
;;
* )
echo "$progname: Unrecognized argument $1"
exit 1
;;
esac
shift
done
if [ -z "$devices" ]; then
echo "No devices are available."
exit 1
fi
if [ -z $device ]; then
device=$devices
fi
if [ `wc -w <<< "$devices"` -gt 1 ] && [ -z device ]; then
echo "Multiple devices are available. Please pick one using"
echo "--device and try again."
fi
echo "Looking for $package on device $device"
# Find the application data directory
app_data_dir=`adb -s $device shell run-as $package sh -c 'pwd 2> /dev/null'`
if [ -z $app_data_dir ]; then
echo "The data directory for the package $package was not found."
echo "Is it installed?"
fi
echo "Found application data directory at" "$app_data_dir"
# Generate an awk script to extract PIDs from Android ps output. It
# is enough to run `ps' as the package user on newer versions of
# Android, but that doesn't work on Android 2.3.
cat << EOF > tmp.awk
BEGIN {
pid = 0;
pid_column = 2;
}
{
# Remove any trailing carriage return from the input line.
gsub ("\r", "", \$NF)
# If this is line 1, figure out which column contains the PID.
if (NR == 1)
{
for (n = 1; n <= NF; ++n)
{
if (\$n == "PID")
pid_column=n;
}
}
else if (\$NF == "$package")
print \$pid_column
}
EOF
# Make sure that file disappears once this script exits.
trap "rm -f $(pwd)/tmp.awk" 0
# First, run ps to fetch the list of process IDs.
package_pids=`adb -s $device shell ps`
# Next, extract the list of PIDs currently running.
package_pids=`awk -f tmp.awk <<< $package_pids`
if [ "$attach_existing" != "yes" ]; then
# Finally, kill each existing process.
for pid in $package_pids; do
echo "Killing existing process $pid..."
adb -s $device shell run-as $package kill -9 $pid &> /dev/null
done
# Now run the main activity. This must be done as the adb user and
# not as the package user.
echo "Starting activity $activity and attaching debugger"
# Exit if the activity could not be started.
adb -s $device shell am start -D -n "$package/$activity"
if [ ! $? ]; then
exit 1;
fi
# Sleep for a bit. Otherwise, the process may not have started
# yet.
sleep 1
# Now look for processes matching the package again.
package_pids=`adb -s $device shell ps`
# Next, remove lines matching "ps" itself.
package_pids=`awk -f tmp.awk <<< $package_pids`
fi
pid=$package_pids
num_pids=`wc -w <<< "$package_pids"`
if [ $num_pids -gt 1 ]; then
echo "More than one process was started:"
echo ""
adb -s $device shell run-as $package ps | awk -- "{
if (!match (\$0, /ps/) && match (\$0, /$package/))
print \$0
}"
echo ""
printf "Which one do you want to attach to? "
read pid
elif [ -z $package_pids ]; then
echo "No processes were found to attach to."
exit 1
fi
# If either --jdb was specified or debug.sh is not connecting to an
# existing process, then store a suitable JDB invocation in
# jdb_command. GDB will then run JDB to unblock the application from
# the wait dialog after startup.
if [ "$jdb" = "yes" ] || [ "$attach_existing" != yes ]; then
adb -s $device forward --remove-all
adb -s $device forward "tcp:$jdb_port" "jdwp:$pid"
if [ ! $? ]; then
echo "Failed to forward jdwp:$pid to $jdb_port!"
echo "Perhaps you need to specify a different port with --port?"
exit 1;
fi
jdb_command="jdb -connect \
com.sun.jdi.SocketAttach:hostname=localhost,port=$jdb_port"
if [ $jdb = "yes" ]; then
# Just start JDB and then exit
$jdb_command
exit 1
fi
fi
if [ -n "$jdb_command" ]; then
echo "Starting JDB to unblock application."
# Start JDB to unblock the application.
coproc JDB { $jdb_command; }
# Tell JDB to first suspend all threads.
echo "suspend" >&${JDB[1]}
# Tell JDB to print a magic string once the program is
# initialized.
echo "print \"__verify_jdb_has_started__\"" >&${JDB[1]}
# Now wait for JDB to give the string back.
line=
while :; do
read -u ${JDB[0]} line
if [ ! $? ]; then
echo "Failed to read JDB output"
exit 1
fi
case "$line" in
*__verify_jdb_has_started__*)
# Android only polls for a Java debugger every 200ms, so
# the debugger must be connected for at least that long.
echo "Pausing 1 second for the program to continue."
sleep 1
break
;;
esac
done
# Note that JDB does not exit until GDB is fully attached!
fi
# See if gdbserver has to be uploaded
gdbserver_cmd=
is_root=
if [ -z "$gdbserver" ]; then
gdbserver_bin=/system/bin/gdbserver
else
gdbserver_bin=/data/local/tmp/gdbserver
gdbserver_cat="cat $gdbserver_bin | run-as $package sh -c \
\"tee gdbserver > /dev/null\""
# Upload the specified gdbserver binary to the device.
adb -s $device push "$gdbserver" "$gdbserver_bin"
if (adb -s $device shell ls /system/bin | grep -G tee); then
# Copy it to the user directory.
adb -s $device shell "$gdbserver_cat"
adb -s $device shell "run-as $package chmod 777 gdbserver"
gdbserver_cmd="./gdbserver"
else
# Hopefully this is an old version of Android which allows
# execution from /data/local/tmp. Its `chmod' doesn't support
# `+x' either.
adb -s $device shell "chmod 777 $gdbserver_bin"
gdbserver_cmd="$gdbserver_bin"
# If the user is root, then there is no need to open any kind
# of TCP socket.
if (adb -s $device shell id | grep -G root); then
gdbserver=
is_root=yes
fi
fi
fi
# Now start gdbserver on the device asynchronously.
echo "Attaching gdbserver to $pid on $device..."
exec 5<> /tmp/file-descriptor-stamp
rm -f /tmp/file-descriptor-stamp
if [ -z "$gdbserver" ]; then
if [ "$is_root" = "yes" ]; then
adb -s $device shell $gdbserver_bin --once \
"+/data/local/tmp/debug.$package.socket" --attach $pid >&5 &
gdb_socket="localfilesystem:/data/local/tmp/debug.$package.socket"
else
adb -s $device shell run-as $package $gdbserver_bin --once \
"+debug.$package.socket" --attach $pid >&5 &
gdb_socket="localfilesystem:$app_data_dir/debug.$package.socket"
fi
else
# Normally the program cannot access $gdbserver_bin when it is
# placed in /data/local/tmp.
adb -s $device shell run-as $package $gdbserver_cmd --once \
"0.0.0.0:7654" --attach $pid >&5 &
gdb_socket="tcp:7654"
fi
# Wait until gdbserver successfully runs.
line=
while read -u 5 line; do
case "$line" in
*Attached* )
break;
;;
*error* | *Error* | failed )
echo "GDB error:" $line
exit 1
;;
* )
;;
esac
done
# Now that GDB is attached, tell the Java debugger to resume execution
# and then exit.
if [ -n "$jdb_command" ]; then
echo "resume" >&${JDB[1]}
echo "exit" >&${JDB[1]}
fi
# Forward the gdb server port here.
adb -s $device forward "tcp:$gdb_port" $gdb_socket
if [ ! $? ]; then
echo "Failed to forward $app_data_dir/debug.$package.socket"
echo "to $gdb_port! Perhaps you need to specify a different port"
echo "with --port?"
exit 1;
fi
# Finally, start gdb with any extra arguments needed.
cd "$oldpwd"
$gdb --eval-command "target remote localhost:$gdb_port" $gdbargs

BIN
java/emacs.keystore Normal file

Binary file not shown.

View file

@ -0,0 +1,434 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import java.lang.IllegalStateException;
import java.util.List;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.ViewTreeObserver;
import android.view.Window;
import android.view.WindowInsets;
import android.view.WindowInsetsController;
import android.widget.FrameLayout;
public class EmacsActivity extends Activity
implements EmacsWindowAttachmentManager.WindowConsumer,
ViewTreeObserver.OnGlobalLayoutListener
{
public static final String TAG = "EmacsActivity";
/* The currently attached EmacsWindow, or null if none. */
private EmacsWindow window;
/* The frame layout associated with the activity. */
private FrameLayout layout;
/* List of activities with focus. */
public static List<EmacsActivity> focusedActivities;
/* The last activity to have been focused. */
public static EmacsActivity lastFocusedActivity;
/* The currently focused window. */
public static EmacsWindow focusedWindow;
/* Whether or not this activity is paused. */
private boolean isPaused;
/* Whether or not this activity is fullscreen. */
private boolean isFullscreen;
/* The last context menu to be closed. */
private Menu lastClosedMenu;
static
{
focusedActivities = new ArrayList<EmacsActivity> ();
};
public static void
invalidateFocus1 (EmacsWindow window)
{
if (window.view.isFocused ())
focusedWindow = window;
for (EmacsWindow child : window.children)
invalidateFocus1 (child);
}
public static void
invalidateFocus ()
{
EmacsWindow oldFocus;
/* Walk through each focused activity and assign the window focus
to the bottom-most focused window within. Record the old focus
as well. */
oldFocus = focusedWindow;
focusedWindow = null;
for (EmacsActivity activity : focusedActivities)
{
if (activity.window != null)
invalidateFocus1 (activity.window);
}
/* Send focus in- and out- events to the previous and current
focus. */
if (oldFocus != null)
EmacsNative.sendFocusOut (oldFocus.handle,
System.currentTimeMillis ());
if (focusedWindow != null)
EmacsNative.sendFocusIn (focusedWindow.handle,
System.currentTimeMillis ());
}
@Override
public final void
detachWindow ()
{
syncFullscreenWith (null);
if (window == null)
Log.w (TAG, "detachWindow called, but there is no window");
else
{
/* Clear the window's pointer to this activity and remove the
window's view. */
window.setConsumer (null);
/* The window can't be iconified any longer. */
window.noticeDeiconified ();
layout.removeView (window.view);
window = null;
invalidateFocus ();
}
}
@Override
public final void
attachWindow (EmacsWindow child)
{
Log.d (TAG, "attachWindow: " + child);
if (window != null)
throw new IllegalStateException ("trying to attach window when one"
+ " already exists");
syncFullscreenWith (child);
/* Record and attach the view. */
window = child;
layout.addView (window.view);
child.setConsumer (this);
/* If the window isn't no-focus-on-map, focus its view. */
if (!child.getDontFocusOnMap ())
window.view.requestFocus ();
/* If the activity is iconified, send that to the window. */
if (isPaused)
window.noticeIconified ();
/* Invalidate the focus. */
invalidateFocus ();
}
@Override
public final void
destroy ()
{
finish ();
}
@Override
public final EmacsWindow
getAttachedWindow ()
{
return window;
}
@Override
public final void
onCreate (Bundle savedInstanceState)
{
FrameLayout.LayoutParams params;
Intent intent;
View decorView;
ViewTreeObserver observer;
int matchParent;
/* See if Emacs should be started with -Q. */
intent = getIntent ();
EmacsService.needDashQ
= intent.getBooleanExtra ("org.gnu.emacs.START_DASH_Q",
false);
matchParent = FrameLayout.LayoutParams.MATCH_PARENT;
params
= new FrameLayout.LayoutParams (matchParent,
matchParent);
/* Make the frame layout. */
layout = new FrameLayout (this);
layout.setLayoutParams (params);
/* Set it as the content view. */
setContentView (layout);
/* Maybe start the Emacs service if necessary. */
EmacsService.startEmacsService (this);
/* Add this activity to the list of available activities. */
EmacsWindowAttachmentManager.MANAGER.registerWindowConsumer (this);
/* Start observing global layout changes between Jelly Bean and Q.
This is required to restore the fullscreen state whenever the
on screen keyboard is displayed, as there is otherwise no way
to determine when the on screen keyboard becomes visible. */
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.R)
{
decorView = getWindow ().getDecorView ();
observer = decorView.getViewTreeObserver ();
observer.addOnGlobalLayoutListener (this);
}
super.onCreate (savedInstanceState);
}
@Override
public final void
onGlobalLayout ()
{
syncFullscreenWith (window);
}
@Override
public final void
onDestroy ()
{
EmacsWindowAttachmentManager manager;
boolean isMultitask;
manager = EmacsWindowAttachmentManager.MANAGER;
/* The activity will die shortly hereafter. If there is a window
attached, close it now. */
Log.d (TAG, "onDestroy " + this);
isMultitask = this instanceof EmacsMultitaskActivity;
manager.removeWindowConsumer (this, isMultitask || isFinishing ());
focusedActivities.remove (this);
invalidateFocus ();
/* Remove this activity from the static field, lest it leak. */
if (lastFocusedActivity == this)
lastFocusedActivity = null;
super.onDestroy ();
}
@Override
public final void
onWindowFocusChanged (boolean isFocused)
{
Log.d (TAG, ("onWindowFocusChanged: "
+ (isFocused ? "YES" : "NO")));
if (isFocused && !focusedActivities.contains (this))
{
focusedActivities.add (this);
lastFocusedActivity = this;
/* Update the window insets as the focus change may have
changed the window insets as well, and the system does not
automatically restore visibility flags. */
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN
&& Build.VERSION.SDK_INT < Build.VERSION_CODES.R
&& isFullscreen)
syncFullscreenWith (window);
}
else
focusedActivities.remove (this);
invalidateFocus ();
}
@Override
public final void
onPause ()
{
isPaused = true;
EmacsWindowAttachmentManager.MANAGER.noticeIconified (this);
super.onPause ();
}
@Override
public final void
onResume ()
{
isPaused = false;
EmacsWindowAttachmentManager.MANAGER.noticeDeiconified (this);
super.onResume ();
}
@Override
public final void
onContextMenuClosed (Menu menu)
{
int serial;
Log.d (TAG, "onContextMenuClosed: " + menu);
/* See the comment inside onMenuItemClick. */
if (((EmacsContextMenu.wasSubmenuSelected == -2)
|| (EmacsContextMenu.wasSubmenuSelected >= 0
&& ((System.currentTimeMillis ()
- EmacsContextMenu.wasSubmenuSelected)
<= 300)))
|| menu == lastClosedMenu)
{
EmacsContextMenu.wasSubmenuSelected = -1;
lastClosedMenu = menu;
return;
}
/* lastClosedMenu is set because Android apparently calls this
function twice. */
lastClosedMenu = null;
/* Send a context menu event given that no menu item has already
been selected. */
if (!EmacsContextMenu.itemAlreadySelected)
{
serial = EmacsContextMenu.lastMenuEventSerial;
EmacsNative.sendContextMenu ((short) 0, 0,
serial);
}
super.onContextMenuClosed (menu);
}
@SuppressWarnings ("deprecation")
public final void
syncFullscreenWith (EmacsWindow emacsWindow)
{
WindowInsetsController controller;
Window window;
int behavior, flags;
View view;
if (emacsWindow != null)
isFullscreen = emacsWindow.fullscreen;
else
isFullscreen = false;
/* On Android 11 or later, use the window insets controller to
control whether or not the view is fullscreen. */
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R)
{
window = getWindow ();
/* If there is no attached window, return immediately. */
if (window == null)
return;
behavior = WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
controller = window.getInsetsController ();
controller.setSystemBarsBehavior (behavior);
if (isFullscreen)
controller.hide (WindowInsets.Type.statusBars ()
| WindowInsets.Type.navigationBars ());
else
controller.show (WindowInsets.Type.statusBars ()
| WindowInsets.Type.navigationBars ());
return;
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN)
{
/* On Android 4.1 or later, use `setSystemUiVisibility'. */
window = getWindow ();
if (window == null)
return;
view = window.getDecorView ();
if (isFullscreen)
{
flags = 0;
flags |= View.SYSTEM_UI_FLAG_FULLSCREEN;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
/* These flags means that Emacs will be full screen as
long as the state flag is set. */
flags |= View.SYSTEM_UI_FLAG_HIDE_NAVIGATION;
flags |= View.SYSTEM_UI_FLAG_IMMERSIVE;
flags |= View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
}
/* Apply the given flags. */
view.setSystemUiVisibility (flags);
}
else
view.setSystemUiVisibility (View.SYSTEM_UI_FLAG_VISIBLE);
}
}
@Override
public final void
onAttachedToWindow ()
{
super.onAttachedToWindow ();
/* Update the window insets. */
syncFullscreenWith (window);
}
};

View file

@ -0,0 +1,81 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import java.io.File;
import java.io.FileFilter;
import android.content.Context;
import android.app.Application;
import android.util.Log;
public final class EmacsApplication extends Application
{
private static final String TAG = "EmacsApplication";
/* The name of the dump file to use. */
public static String dumpFileName;
public static void
findDumpFile (Context context)
{
File filesDirectory;
File[] allFiles;
String wantedDumpFile;
int i;
wantedDumpFile = ("emacs-" + EmacsNative.getFingerprint ()
+ ".pdmp");
/* Obtain a list of all files ending with ``.pdmp''. Then, look
for a file named ``emacs-<fingerprint>.pdmp'' and delete the
rest. */
filesDirectory = context.getFilesDir ();
allFiles = filesDirectory.listFiles (new FileFilter () {
@Override
public boolean
accept (File file)
{
return (!file.isDirectory ()
&& file.getName ().endsWith (".pdmp"));
}
});
/* Now try to find the right dump file. */
for (i = 0; i < allFiles.length; ++i)
{
if (allFiles[i].getName ().equals (wantedDumpFile))
dumpFileName = allFiles[i].getAbsolutePath ();
else
/* Delete this outdated dump file. */
allFiles[i].delete ();
}
}
@Override
public void
onCreate ()
{
findDumpFile (this);
super.onCreate ();
}
};

View file

@ -0,0 +1,47 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import android.os.Build;
/* This class provides helper code for accessing the clipboard,
abstracting between the different interfaces on API 8 and 11. */
public abstract class EmacsClipboard
{
public abstract void setClipboard (byte[] bytes);
public abstract int ownsClipboard ();
public abstract boolean clipboardExists ();
public abstract byte[] getClipboard ();
public abstract byte[][] getClipboardTargets ();
public abstract long[] getClipboardData (byte[] target);
/* Create the correct kind of clipboard for this system. */
public static EmacsClipboard
makeClipboard ()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
return new EmacsSdk11Clipboard ();
else
return new EmacsSdk8Clipboard ();
}
};

View file

@ -0,0 +1,374 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import java.util.List;
import java.util.ArrayList;
import android.content.Context;
import android.content.Intent;
import android.os.Build;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.SubMenu;
import android.util.Log;
/* Context menu implementation. This object is built from JNI and
describes a menu hiearchy. Then, `inflate' can turn it into an
Android menu, which can be turned into a popup (or other kind of)
menu. */
public final class EmacsContextMenu
{
private static final String TAG = "EmacsContextMenu";
/* Whether or not an item was selected. */
public static boolean itemAlreadySelected;
/* Whether or not a submenu was selected.
Value is -1 if no; value is -2 if yes, and a context menu
close event will definitely be sent. Any other value is
the timestamp when the submenu was selected. */
public static long wasSubmenuSelected;
/* The serial ID of the last context menu to be displayed. */
public static int lastMenuEventSerial;
/* The last group ID used for a menu item. */
public int lastGroupId;
private static class Item implements MenuItem.OnMenuItemClickListener
{
public int itemID;
public String itemName, tooltip;
public EmacsContextMenu subMenu;
public boolean isEnabled, isCheckable, isChecked;
public EmacsView inflatedView;
public boolean isRadio;
@Override
public boolean
onMenuItemClick (MenuItem item)
{
Log.d (TAG, "onMenuItemClick: " + itemName + " (" + itemID + ")");
if (subMenu != null)
{
/* Android 6.0 and earlier don't support nested submenus
properly, so display the submenu popup by hand. */
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
{
Log.d (TAG, "onMenuItemClick: displaying submenu " + subMenu);
/* Still set wasSubmenuSelected -- if not set, the
dismissal of this context menu will result in a
context menu event being sent. */
wasSubmenuSelected = -2;
/* Running a popup menu from inside a click handler
doesn't work, so make sure it is displayed
outside. */
inflatedView.post (new Runnable () {
@Override
public void
run ()
{
inflatedView.popupMenu (subMenu, 0, 0, true);
}
});
return true;
}
/* After opening a submenu within a submenu, Android will
send onContextMenuClosed for a ContextMenuBuilder. This
will normally confuse Emacs into thinking that the
context menu has been dismissed. Wrong!
Setting this flag makes EmacsActivity to only handle
SubMenuBuilder being closed, which always means the menu
has actually been dismissed.
However, these extraneous events aren't sent on devices
where submenus display without dismissing their parents.
Thus, only ignore the close event if it happens within
300 milliseconds of the submenu being selected. */
wasSubmenuSelected = System.currentTimeMillis ();
return false;
}
/* Send a context menu event. */
EmacsNative.sendContextMenu ((short) 0, itemID,
lastMenuEventSerial);
/* Say that an item has already been selected. */
itemAlreadySelected = true;
return true;
}
};
public List<Item> menuItems;
public String title;
private EmacsContextMenu parent;
/* Create a context menu with no items inside and the title TITLE,
which may be NULL. */
public static EmacsContextMenu
createContextMenu (String title)
{
EmacsContextMenu menu;
menu = new EmacsContextMenu ();
menu.menuItems = new ArrayList<Item> ();
menu.title = title;
return menu;
}
/* Add a normal menu item to the context menu with the id ITEMID and
the name ITEMNAME. Enable it if ISENABLED, else keep it
disabled.
If this is not a submenu and ISCHECKABLE is set, make the item
checkable. Likewise, if ISCHECKED is set, make the item
checked.
If TOOLTIP is non-NULL, set the menu item tooltip to TOOLTIP.
If ISRADIO, then display the check mark as a radio button. */
public void
addItem (int itemID, String itemName, boolean isEnabled,
boolean isCheckable, boolean isChecked,
String tooltip, boolean isRadio)
{
Item item;
item = new Item ();
item.itemID = itemID;
item.itemName = itemName;
item.isEnabled = isEnabled;
item.isCheckable = isCheckable;
item.isChecked = isChecked;
item.tooltip = tooltip;
item.isRadio = isRadio;
menuItems.add (item);
}
/* Create a disabled menu item with the name ITEMNAME. */
public void
addPane (String itemName)
{
Item item;
item = new Item ();
item.itemName = itemName;
menuItems.add (item);
}
/* Add a submenu to the context menu with the specified title and
item name. */
public EmacsContextMenu
addSubmenu (String itemName, String title, String tooltip)
{
EmacsContextMenu submenu;
Item item;
item = new Item ();
item.itemID = 0;
item.itemName = itemName;
item.tooltip = tooltip;
item.subMenu = createContextMenu (title);
item.subMenu.parent = this;
menuItems.add (item);
return item.subMenu;
}
/* Add the contents of this menu to MENU. Assume MENU will be
displayed in INFLATEDVIEW. */
private void
inflateMenuItems (Menu menu, EmacsView inflatedView)
{
Intent intent;
MenuItem menuItem;
SubMenu submenu;
for (Item item : menuItems)
{
if (item.subMenu != null)
{
/* This is a submenu. On versions of Android which
support doing so, create the submenu and add the
contents of the menu to it.
Note that Android 4.0 and later technically supports
having multiple layers of nested submenus, but if they
are used, onContextMenuClosed becomes unreliable. */
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
{
submenu = menu.addSubMenu (item.itemName);
item.subMenu.inflateMenuItems (submenu, inflatedView);
/* This is still needed to set wasSubmenuSelected. */
menuItem = submenu.getItem ();
}
else
menuItem = menu.add (item.itemName);
item.inflatedView = inflatedView;
menuItem.setOnMenuItemClickListener (item);
}
else
{
if (item.isRadio)
menuItem = menu.add (++lastGroupId, Menu.NONE, Menu.NONE,
item.itemName);
else
menuItem = menu.add (item.itemName);
menuItem.setOnMenuItemClickListener (item);
/* If the item ID is zero, then disable the item. */
if (item.itemID == 0 || !item.isEnabled)
menuItem.setEnabled (false);
/* Now make the menu item display a checkmark as
appropriate. */
if (item.isCheckable)
menuItem.setCheckable (true);
if (item.isChecked)
menuItem.setChecked (true);
/* Define an exclusively checkable group if the item is a
radio button. */
if (item.isRadio)
menu.setGroupCheckable (lastGroupId, true, true);
/* If the tooltip text is set and the system is new enough
to support menu item tooltips, set it on the item. */
if (item.tooltip != null
&& Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
menuItem.setTooltipText (item.tooltip);
}
}
}
/* Enter the items in this context menu to MENU.
Assume that MENU will be displayed in VIEW; this may lead to
popupMenu being called on VIEW if a submenu is selected. */
public void
expandTo (Menu menu, EmacsView view)
{
inflateMenuItems (menu, view);
}
/* Return the parent or NULL. */
public EmacsContextMenu
parent ()
{
return this.parent;
}
/* Like display, but does the actual work and runs in the main
thread. */
private boolean
display1 (EmacsWindow window, int xPosition, int yPosition)
{
/* Set this flag to false. It is used to decide whether or not to
send 0 in response to the context menu being closed. */
itemAlreadySelected = false;
/* No submenu has been selected yet. */
wasSubmenuSelected = -1;
return window.view.popupMenu (this, xPosition, yPosition,
false);
}
/* Display this context menu on WINDOW, at xPosition and yPosition.
SERIAL is a number that will be returned in any menu event
generated to identify this context menu. */
public boolean
display (final EmacsWindow window, final int xPosition,
final int yPosition, final int serial)
{
Runnable runnable;
final Holder<Boolean> rc;
rc = new Holder<Boolean> ();
runnable = new Runnable () {
@Override
public void
run ()
{
synchronized (this)
{
lastMenuEventSerial = serial;
rc.thing = display1 (window, xPosition, yPosition);
notify ();
}
}
};
EmacsService.syncRunnable (runnable);
return rc.thing;
}
/* Dismiss this context menu. WINDOW is the window where the
context menu is being displayed. */
public void
dismiss (final EmacsWindow window)
{
Runnable runnable;
EmacsService.SERVICE.runOnUiThread (new Runnable () {
@Override
public void
run ()
{
window.view.cancelPopupMenu ();
itemAlreadySelected = false;
}
});
}
};

View file

@ -0,0 +1,206 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Rect;
import android.graphics.Xfermode;
public final class EmacsCopyArea
{
private static Xfermode overAlu;
static
{
overAlu = new PorterDuffXfermode (Mode.SRC_OVER);
};
private static void
insetRectBy (Rect rect, int left, int top, int right,
int bottom)
{
rect.left += left;
rect.top += top;
rect.right -= right;
rect.bottom -= bottom;
}
public static void
perform (EmacsDrawable source, EmacsGC gc,
EmacsDrawable destination,
int src_x, int src_y, int width, int height,
int dest_x, int dest_y)
{
int i;
Bitmap bitmap;
Paint maskPaint, paint;
Canvas maskCanvas, canvas;
Bitmap srcBitmap, maskBitmap, clipBitmap;
Rect rect, maskRect, srcRect, dstRect, maskDestRect;
boolean needFill;
/* TODO implement stippling. */
if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
return;
paint = gc.gcPaint;
canvas = destination.lockCanvas (gc);
if (canvas == null)
return;
/* A copy must be created or drawBitmap could end up overwriting
itself. */
srcBitmap = source.getBitmap ();
/* If srcBitmap is out of bounds, then adjust the source rectangle
to be within bounds. Note that tiling on windows with
backgrounds is unimplemented. */
if (src_x < 0)
{
width += src_x;
dest_x -= src_x;
src_x = 0;
}
if (src_y < 0)
{
height += src_y;
dest_y -= src_y;
src_y = 0;
}
if (src_x + width > srcBitmap.getWidth ())
width = srcBitmap.getWidth () - src_x;
if (src_y + height > srcBitmap.getHeight ())
height = srcBitmap.getHeight () - src_y;
/* If width and height are empty or negative, then skip the entire
CopyArea operation lest createBitmap throw an exception. */
if (width <= 0 || height <= 0)
return;
rect = new Rect (dest_x, dest_y, dest_x + width,
dest_y + height);
if (gc.clip_mask == null)
{
if (source == destination)
{
/* Create a copy of the bitmap, since Android can't handle
overlapping copies. */
bitmap = Bitmap.createBitmap (srcBitmap,
src_x, src_y, width,
height);
canvas.drawBitmap (bitmap, null, rect, paint);
bitmap.recycle ();
}
else
{
/* But here the bitmaps are known to not overlap, so avoid
that extra consing overhead. */
srcRect = new Rect (src_x, src_y, src_x + width,
src_y + height);
canvas.drawBitmap (srcBitmap, srcRect, rect, paint);
}
}
else
{
/* Drawing with a clip mask involves calculating the
intersection of the clip mask with the dst rect, and
extrapolating the corresponding part of the src rect. */
clipBitmap = gc.clip_mask.bitmap;
dstRect = new Rect (dest_x, dest_y,
dest_x + width,
dest_y + height);
maskRect = new Rect (gc.clip_x_origin,
gc.clip_y_origin,
(gc.clip_x_origin
+ clipBitmap.getWidth ()),
(gc.clip_y_origin
+ clipBitmap.getHeight ()));
clipBitmap = gc.clip_mask.bitmap;
if (!maskRect.setIntersect (dstRect, maskRect))
/* There is no intersection between the clip mask and the
dest rect. */
return;
/* Now figure out which part of the source corresponds to
maskRect and return it relative to srcBitmap. */
srcRect = new Rect (src_x, src_y, src_x + width,
src_y + height);
insetRectBy (srcRect, maskRect.left - dstRect.left,
maskRect.top - dstRect.top,
maskRect.right - dstRect.right,
maskRect.bottom - dstRect.bottom);
/* Finally, create a temporary bitmap that is the size of
maskRect. */
maskBitmap
= Bitmap.createBitmap (maskRect.width (), maskRect.height (),
Bitmap.Config.ARGB_8888);
/* Draw the mask onto the maskBitmap. */
maskCanvas = new Canvas (maskBitmap);
maskPaint = new Paint ();
maskRect.offset (-gc.clip_x_origin,
-gc.clip_y_origin);
maskCanvas.drawBitmap (gc.clip_mask.bitmap,
maskRect,
new Rect (0, 0,
maskRect.width (),
maskRect.height ()),
maskPaint);
maskRect.offset (gc.clip_x_origin,
gc.clip_y_origin);
/* Set the transfer mode to SRC_IN to preserve only the parts
of the source that overlap with the mask. */
maskPaint.setXfermode (EmacsGC.srcInAlu);
/* Draw the source. */
maskDestRect = new Rect (0, 0, srcRect.width (),
srcRect.height ());
maskCanvas.drawBitmap (srcBitmap, srcRect, maskDestRect,
maskPaint);
/* Finally, draw the mask bitmap to the destination. */
paint.setXfermode (overAlu);
canvas.drawBitmap (maskBitmap, null, maskRect, paint);
gc.resetXfermode ();
/* Recycle this unused bitmap. */
maskBitmap.recycle ();
}
destination.damageRect (rect);
}
}

View file

@ -0,0 +1,47 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import android.view.PointerIcon;
import android.os.Build;
/* Cursor wrapper. Note that pointer icons are not supported prior to
Android 24. */
public final class EmacsCursor extends EmacsHandleObject
{
/* The pointer icon associated with this cursor. */
public final PointerIcon icon;
public
EmacsCursor (short handle, int glyph)
{
super (handle);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N)
{
icon = null;
return;
}
icon = PointerIcon.getSystemIcon (EmacsService.SERVICE,
glyph);
}
};

View file

@ -0,0 +1,372 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import java.util.List;
import java.util.ArrayList;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.os.Build;
import android.provider.Settings;
import android.util.Log;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.FrameLayout;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
/* Toolkit dialog implementation. This object is built from JNI and
describes a single alert dialog. Then, `inflate' turns it into
AlertDialog. */
public final class EmacsDialog implements DialogInterface.OnDismissListener
{
private static final String TAG = "EmacsDialog";
/* List of buttons in this dialog. */
private List<EmacsButton> buttons;
/* Dialog title. */
private String title;
/* Dialog text. */
private String text;
/* Whether or not a selection has already been made. */
private boolean wasButtonClicked;
/* Dialog to dismiss after click. */
private AlertDialog dismissDialog;
/* The menu serial associated with this dialog box. */
private int menuEventSerial;
private class EmacsButton implements View.OnClickListener,
DialogInterface.OnClickListener
{
/* Name of this button. */
public String name;
/* ID of this button. */
public int id;
/* Whether or not the button is enabled. */
public boolean enabled;
@Override
public void
onClick (View view)
{
Log.d (TAG, "onClicked " + this);
wasButtonClicked = true;
EmacsNative.sendContextMenu ((short) 0, id, menuEventSerial);
dismissDialog.dismiss ();
}
@Override
public void
onClick (DialogInterface dialog, int which)
{
Log.d (TAG, "onClicked " + this);
wasButtonClicked = true;
EmacsNative.sendContextMenu ((short) 0, id, menuEventSerial);
}
};
/* Create a popup dialog with the title TITLE and the text TEXT.
TITLE may be NULL. MENUEVENTSERIAL is a number which will
identify this popup dialog inside events it sends. */
public static EmacsDialog
createDialog (String title, String text, int menuEventSerial)
{
EmacsDialog dialog;
dialog = new EmacsDialog ();
dialog.buttons = new ArrayList<EmacsButton> ();
dialog.title = title;
dialog.text = text;
dialog.menuEventSerial = menuEventSerial;
return dialog;
}
/* Add a button named NAME, with the identifier ID. If DISABLE,
disable the button. */
public void
addButton (String name, int id, boolean disable)
{
EmacsButton button;
button = new EmacsButton ();
button.name = name;
button.id = id;
button.enabled = !disable;
buttons.add (button);
}
/* Turn this dialog into an AlertDialog for the specified
CONTEXT.
Upon a button being selected, the dialog will send an
ANDROID_CONTEXT_MENU event with the id of that button.
Upon the dialog being dismissed, an ANDROID_CONTEXT_MENU event
will be sent with an id of 0. */
public AlertDialog
toAlertDialog (Context context)
{
AlertDialog dialog;
int size;
EmacsButton button;
LinearLayout layout;
Button buttonView;
ViewGroup.LayoutParams layoutParams;
size = buttons.size ();
if (size <= 3)
{
dialog = new AlertDialog.Builder (context).create ();
dialog.setMessage (text);
dialog.setCancelable (true);
dialog.setOnDismissListener (this);
if (title != null)
dialog.setTitle (title);
/* There are less than 4 buttons. Add the buttons the way
Android intends them to be added. */
if (size >= 1)
{
button = buttons.get (0);
dialog.setButton (DialogInterface.BUTTON_POSITIVE,
button.name, button);
}
if (size >= 2)
{
button = buttons.get (1);
dialog.setButton (DialogInterface.BUTTON_NEGATIVE,
button.name, button);
}
if (size >= 3)
{
button = buttons.get (2);
dialog.setButton (DialogInterface.BUTTON_NEUTRAL,
button.name, button);
}
}
else
{
/* There are more than 4 buttons. Add them all to a
LinearLayout. */
layout = new LinearLayout (context);
layoutParams
= new LinearLayout.LayoutParams (ViewGroup.LayoutParams.WRAP_CONTENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
for (EmacsButton emacsButton : buttons)
{
buttonView = new Button (context);
buttonView.setText (emacsButton.name);
buttonView.setOnClickListener (emacsButton);
buttonView.setLayoutParams (layoutParams);
buttonView.setEnabled (emacsButton.enabled);
layout.addView (buttonView);
}
layoutParams
= new FrameLayout.LayoutParams (ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT);
layout.setLayoutParams (layoutParams);
/* Add that layout to the dialog's custom view.
android.R.id.custom is documented to work. But looking it
up returns NULL, so setView must be used instead. */
dialog = new AlertDialog.Builder (context).setView (layout).create ();
dialog.setMessage (text);
dialog.setCancelable (true);
dialog.setOnDismissListener (this);
if (title != null)
dialog.setTitle (title);
}
return dialog;
}
/* Internal helper for display run on the main thread. */
@SuppressWarnings("deprecation")
private boolean
display1 ()
{
Context context;
int size, type;
Button buttonView;
EmacsButton button;
AlertDialog dialog;
Window window;
if (EmacsActivity.focusedActivities.isEmpty ())
{
/* If focusedActivities is empty then this dialog may have
been displayed immediately after a popup dialog is
dismissed. Or Emacs might legitimately be in the
background. Try the service context first if possible. */
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M
|| Settings.canDrawOverlays (EmacsService.SERVICE))
context = EmacsService.SERVICE;
else
context = EmacsActivity.lastFocusedActivity;
if (context == null)
return false;
}
else
/* Display using the activity context when Emacs is in the
foreground, as this allows the dialog to be dismissed more
consistently. */
context = EmacsActivity.focusedActivities.get (0);
Log.d (TAG, "display1: using context " + context);
dialog = dismissDialog = toAlertDialog (context);
try
{
if (context == EmacsService.SERVICE)
{
/* Apply the system alert window type to make sure this
dialog can be displayed. */
window = dialog.getWindow ();
type = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O
? WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
: WindowManager.LayoutParams.TYPE_PHONE);
window.setType (type);
}
dismissDialog.show ();
}
catch (Exception exception)
{
/* This can happen when the system decides Emacs is not in the
foreground any longer. */
return false;
}
/* If there are less than four buttons, then they must be
individually enabled or disabled after the dialog is
displayed. */
size = buttons.size ();
if (size <= 3)
{
if (size >= 1)
{
button = buttons.get (0);
buttonView
= dialog.getButton (DialogInterface.BUTTON_POSITIVE);
buttonView.setEnabled (button.enabled);
}
if (size >= 2)
{
button = buttons.get (1);
buttonView
= dialog.getButton (DialogInterface.BUTTON_NEGATIVE);
buttonView.setEnabled (button.enabled);
}
if (size >= 3)
{
button = buttons.get (2);
buttonView
= dialog.getButton (DialogInterface.BUTTON_NEUTRAL);
buttonView.setEnabled (button.enabled);
}
}
return true;
}
/* Display this dialog for a suitable activity.
Value is false if the dialog could not be displayed,
and true otherwise. */
public boolean
display ()
{
Runnable runnable;
final Holder<Boolean> rc;
rc = new Holder<Boolean> ();
runnable = new Runnable () {
@Override
public void
run ()
{
synchronized (this)
{
rc.thing = display1 ();
notify ();
}
}
};
EmacsService.syncRunnable (runnable);
return rc.thing;
}
@Override
public void
onDismiss (DialogInterface dialog)
{
Log.d (TAG, "onDismiss: " + this);
if (wasButtonClicked)
return;
EmacsNative.sendContextMenu ((short) 0, 0, menuEventSerial);
}
};

View file

@ -0,0 +1,463 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import android.content.Context;
import android.database.Cursor;
import android.database.MatrixCursor;
import android.os.Build;
import android.os.CancellationSignal;
import android.os.ParcelFileDescriptor;
import android.provider.DocumentsContract.Document;
import android.provider.DocumentsContract.Root;
import static android.provider.DocumentsContract.buildChildDocumentsUri;
import android.provider.DocumentsProvider;
import android.webkit.MimeTypeMap;
import android.net.Uri;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
/* ``Documents provider''. This allows Emacs's home directory to be
modified by other programs holding permissions to manage system
storage, which is useful to (for example) correct misconfigurations
which prevent Emacs from starting up.
This functionality is only available on Android 19 and later. */
public final class EmacsDocumentsProvider extends DocumentsProvider
{
/* Home directory. This is the directory whose contents are
initially returned to requesting applications. */
private File baseDir;
/* The default projection for requests for the root directory. */
private static final String[] DEFAULT_ROOT_PROJECTION;
/* The default projection for requests for a file. */
private static final String[] DEFAULT_DOCUMENT_PROJECTION;
static
{
DEFAULT_ROOT_PROJECTION = new String[] {
Root.COLUMN_ROOT_ID,
Root.COLUMN_MIME_TYPES,
Root.COLUMN_FLAGS,
Root.COLUMN_ICON,
Root.COLUMN_TITLE,
Root.COLUMN_SUMMARY,
Root.COLUMN_DOCUMENT_ID,
Root.COLUMN_AVAILABLE_BYTES,
};
DEFAULT_DOCUMENT_PROJECTION = new String[] {
Document.COLUMN_DOCUMENT_ID,
Document.COLUMN_MIME_TYPE,
Document.COLUMN_DISPLAY_NAME,
Document.COLUMN_LAST_MODIFIED,
Document.COLUMN_FLAGS,
Document.COLUMN_SIZE,
};
}
@Override
public boolean
onCreate ()
{
/* Set the base directory to Emacs's files directory. */
baseDir = getContext ().getFilesDir ();
return true;
}
@Override
public Cursor
queryRoots (String[] projection)
{
MatrixCursor result;
MatrixCursor.RowBuilder row;
/* If the requestor asked for nothing at all, then it wants some
data by default. */
if (projection == null)
projection = DEFAULT_ROOT_PROJECTION;
result = new MatrixCursor (projection);
row = result.newRow ();
/* Now create and add a row for each file in the base
directory. */
row.add (Root.COLUMN_ROOT_ID, baseDir.getAbsolutePath ());
row.add (Root.COLUMN_SUMMARY, "Emacs home directory");
/* Add the appropriate flags. */
row.add (Root.COLUMN_FLAGS, (Root.FLAG_SUPPORTS_CREATE
| Root.FLAG_SUPPORTS_IS_CHILD));
row.add (Root.COLUMN_ICON, R.drawable.emacs);
row.add (Root.FLAG_LOCAL_ONLY);
row.add (Root.COLUMN_TITLE, "Emacs");
row.add (Root.COLUMN_DOCUMENT_ID, baseDir.getAbsolutePath ());
return result;
}
private Uri
getNotificationUri (File file)
{
Uri updatedUri;
Context context;
context = getContext ();
updatedUri
= buildChildDocumentsUri ("org.gnu.emacs",
file.getAbsolutePath ());
return updatedUri;
}
/* Inform the system that FILE's contents (or FILE itself) has
changed. */
private void
notifyChange (File file)
{
Uri updatedUri;
Context context;
context = getContext ();
updatedUri
= buildChildDocumentsUri ("org.gnu.emacs",
file.getAbsolutePath ());
context.getContentResolver ().notifyChange (updatedUri, null);
}
/* Return the MIME type of a file FILE. */
private String
getMimeType (File file)
{
String name, extension, mime;
int extensionSeparator;
MimeTypeMap singleton;
if (file.isDirectory ())
return Document.MIME_TYPE_DIR;
/* Abuse WebView stuff to get the file's MIME type. */
name = file.getName ();
extensionSeparator = name.lastIndexOf ('.');
if (extensionSeparator > 0)
{
singleton = MimeTypeMap.getSingleton ();
extension = name.substring (extensionSeparator + 1);
mime = singleton.getMimeTypeFromExtension (extension);
if (mime != null)
return mime;
}
return "application/octet-stream";
}
/* Append the specified FILE to the query result RESULT.
Handle both directories and ordinary files. */
private void
queryDocument1 (MatrixCursor result, File file)
{
MatrixCursor.RowBuilder row;
String fileName, displayName, mimeType;
int flags;
row = result.newRow ();
flags = 0;
/* fileName is a string that the system will ask for some time in
the future. Here, it is just the absolute name of the file. */
fileName = file.getAbsolutePath ();
/* If file is a directory, add the right flags for that. */
if (file.isDirectory ())
{
if (file.canWrite ())
{
flags |= Document.FLAG_DIR_SUPPORTS_CREATE;
flags |= Document.FLAG_SUPPORTS_DELETE;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
flags |= Document.FLAG_SUPPORTS_RENAME;
}
}
else if (file.canWrite ())
{
/* Apply the correct flags for a writable file. */
flags |= Document.FLAG_SUPPORTS_WRITE;
flags |= Document.FLAG_SUPPORTS_DELETE;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
flags |= Document.FLAG_SUPPORTS_RENAME;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N)
flags |= Document.FLAG_SUPPORTS_REMOVE;
}
displayName = file.getName ();
mimeType = getMimeType (file);
row.add (Document.COLUMN_DOCUMENT_ID, fileName);
row.add (Document.COLUMN_DISPLAY_NAME, displayName);
row.add (Document.COLUMN_SIZE, file.length ());
row.add (Document.COLUMN_MIME_TYPE, mimeType);
row.add (Document.COLUMN_LAST_MODIFIED, file.lastModified ());
row.add (Document.COLUMN_FLAGS, flags);
}
@Override
public Cursor
queryDocument (String documentId, String[] projection)
throws FileNotFoundException
{
MatrixCursor result;
File file;
Context context;
file = new File (documentId);
context = getContext ();
if (projection == null)
projection = DEFAULT_DOCUMENT_PROJECTION;
result = new MatrixCursor (projection);
queryDocument1 (result, file);
/* Now allow interested applications to detect changes. */
result.setNotificationUri (context.getContentResolver (),
getNotificationUri (file));
return result;
}
@Override
public Cursor
queryChildDocuments (String parentDocumentId, String[] projection,
String sortOrder) throws FileNotFoundException
{
MatrixCursor result;
File directory;
Context context;
if (projection == null)
projection = DEFAULT_DOCUMENT_PROJECTION;
result = new MatrixCursor (projection);
/* Try to open the file corresponding to the location being
requested. */
directory = new File (parentDocumentId);
/* Now add each child. */
for (File child : directory.listFiles ())
queryDocument1 (result, child);
context = getContext ();
/* Now allow interested applications to detect changes. */
result.setNotificationUri (context.getContentResolver (),
getNotificationUri (directory));
return result;
}
@Override
public ParcelFileDescriptor
openDocument (String documentId, String mode,
CancellationSignal signal) throws FileNotFoundException
{
return ParcelFileDescriptor.open (new File (documentId),
ParcelFileDescriptor.parseMode (mode));
}
@Override
public String
createDocument (String documentId, String mimeType,
String displayName) throws FileNotFoundException
{
File file, parentFile;
boolean rc;
file = new File (documentId, displayName);
try
{
rc = false;
if (Document.MIME_TYPE_DIR.equals (mimeType))
{
file.mkdirs ();
if (file.isDirectory ())
rc = true;
}
else
{
file.createNewFile ();
if (file.isFile ()
&& file.setWritable (true)
&& file.setReadable (true))
rc = true;
}
if (!rc)
throw new FileNotFoundException ("rc != 1");
}
catch (IOException e)
{
throw new FileNotFoundException (e.toString ());
}
parentFile = file.getParentFile ();
if (parentFile != null)
notifyChange (parentFile);
return file.getAbsolutePath ();
}
private void
deleteDocument1 (File child)
{
File[] children;
/* Don't delete symlinks recursively.
Calling readlink or stat is problematic due to file name
encoding problems, so try to delete the file first, and only
try to delete files recursively afterword. */
if (child.delete ())
return;
children = child.listFiles ();
if (children != null)
{
for (File file : children)
deleteDocument1 (file);
}
child.delete ();
}
@Override
public void
deleteDocument (String documentId)
throws FileNotFoundException
{
File file, parent;
File[] children;
Context context;
/* Java makes recursively deleting a file hard. File name
encoding issues also prevent easily calling into C... */
context = getContext ();
file = new File (documentId);
parent = file.getParentFile ();
if (parent == null)
throw new RuntimeException ("trying to delete file without"
+ " parent!");
if (file.delete ())
{
/* Tell the system about the change. */
notifyChange (parent);
return;
}
children = file.listFiles ();
if (children != null)
{
for (File child : children)
deleteDocument1 (child);
}
if (file.delete ())
/* Tell the system about the change. */
notifyChange (parent);
}
@Override
public void
removeDocument (String documentId, String parentDocumentId)
throws FileNotFoundException
{
deleteDocument (documentId);
}
@Override
public String
getDocumentType (String documentId)
{
return getMimeType (new File (documentId));
}
@Override
public String
renameDocument (String documentId, String displayName)
throws FileNotFoundException
{
File file, newName;
File parent;
file = new File (documentId);
parent = file.getParentFile ();
newName = new File (parent, displayName);
if (parent == null)
throw new FileNotFoundException ("parent is null");
file = new File (documentId);
if (!file.renameTo (newName))
return null;
notifyChange (parent);
return newName.getAbsolutePath ();
}
@Override
public boolean
isChildDocument (String parentDocumentId, String documentId)
{
return documentId.startsWith (parentDocumentId);
}
}

View file

@ -0,0 +1,66 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import java.lang.Math;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
public final class EmacsDrawLine
{
public static void
perform (EmacsDrawable drawable, EmacsGC gc,
int x, int y, int x2, int y2)
{
Rect rect;
Canvas canvas;
Paint paint;
/* TODO implement stippling. */
if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
return;
paint = gc.gcPaint;
rect = new Rect (Math.min (x, x2 + 1),
Math.min (y, y2 + 1),
Math.max (x2 + 1, x),
Math.max (y2 + 1, y));
canvas = drawable.lockCanvas (gc);
if (canvas == null)
return;
paint.setStyle (Paint.Style.STROKE);
/* Since drawLine has PostScript style behavior, adjust the
coordinates appropriately. */
if (gc.clip_mask == null)
canvas.drawLine ((float) x, (float) y + 0.5f,
(float) x2 + 0.5f, (float) y2 + 0.5f,
paint);
/* DrawLine with clip mask not implemented; it is not used by
Emacs. */
drawable.damageRect (rect);
}
}

View file

@ -0,0 +1,31 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
public final class EmacsDrawPoint
{
public static void
perform (EmacsDrawable drawable,
EmacsGC immutableGC, int x, int y)
{
EmacsDrawRectangle.perform (drawable, immutableGC,
x, y, 1, 1);
}
}

View file

@ -0,0 +1,123 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.util.Log;
public final class EmacsDrawRectangle
{
public static void
perform (EmacsDrawable drawable, EmacsGC gc,
int x, int y, int width, int height)
{
Paint maskPaint, paint;
Canvas maskCanvas;
Bitmap maskBitmap;
Rect rect;
Rect maskRect, dstRect;
Canvas canvas;
Bitmap clipBitmap;
/* TODO implement stippling. */
if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
return;
canvas = drawable.lockCanvas (gc);
if (canvas == null)
return;
paint = gc.gcPaint;
paint.setStyle (Paint.Style.STROKE);
rect = new Rect (x, y, x + width, y + height);
if (gc.clip_mask == null)
/* Use canvas.drawRect with a RectF. That seems to reliably
get PostScript behavior. */
canvas.drawRect (new RectF (x + 0.5f, y + 0.5f,
x + width + 0.5f,
y + height + 0.5f),
paint);
else
{
/* Drawing with a clip mask involves calculating the
intersection of the clip mask with the dst rect, and
extrapolating the corresponding part of the src rect. */
clipBitmap = gc.clip_mask.bitmap;
dstRect = new Rect (x, y, x + width, y + height);
maskRect = new Rect (gc.clip_x_origin,
gc.clip_y_origin,
(gc.clip_x_origin
+ clipBitmap.getWidth ()),
(gc.clip_y_origin
+ clipBitmap.getHeight ()));
clipBitmap = gc.clip_mask.bitmap;
if (!maskRect.setIntersect (dstRect, maskRect))
/* There is no intersection between the clip mask and the
dest rect. */
return;
/* Finally, create a temporary bitmap that is the size of
maskRect. */
maskBitmap
= Bitmap.createBitmap (maskRect.width (), maskRect.height (),
Bitmap.Config.ARGB_8888);
/* Draw the mask onto the maskBitmap. */
maskCanvas = new Canvas (maskBitmap);
maskRect.offset (-gc.clip_x_origin,
-gc.clip_y_origin);
maskCanvas.drawBitmap (gc.clip_mask.bitmap,
maskRect, new Rect (0, 0,
maskRect.width (),
maskRect.height ()),
paint);
maskRect.offset (gc.clip_x_origin,
gc.clip_y_origin);
/* Set the transfer mode to SRC_IN to preserve only the parts
of the source that overlap with the mask. */
maskPaint = new Paint ();
maskPaint.setXfermode (EmacsGC.srcInAlu);
maskPaint.setStyle (Paint.Style.STROKE);
/* Draw the source. */
maskCanvas.drawRect (maskRect, maskPaint);
/* Finally, draw the mask bitmap to the destination. */
paint.setXfermode (null);
canvas.drawBitmap (maskBitmap, null, maskRect, paint);
/* Recycle this unused bitmap. */
maskBitmap.recycle ();
}
drawable.damageRect (new Rect (x, y, x + width + 1,
y + height + 1));
}
}

View file

@ -0,0 +1,32 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import android.graphics.Rect;
import android.graphics.Bitmap;
import android.graphics.Canvas;
public interface EmacsDrawable
{
public Canvas lockCanvas (EmacsGC gc);
public void damageRect (Rect damageRect);
public Bitmap getBitmap ();
public boolean isDestroyed ();
};

View file

@ -0,0 +1,82 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import java.lang.Math;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Point;
import android.graphics.Rect;
import android.graphics.RectF;
public final class EmacsFillPolygon
{
public static void
perform (EmacsDrawable drawable, EmacsGC gc, Point points[])
{
Canvas canvas;
Path path;
Paint paint;
Rect rect;
RectF rectF;
int i;
canvas = drawable.lockCanvas (gc);
if (canvas == null)
return;
paint = gc.gcPaint;
/* Build the path from the given array of points. */
path = new Path ();
if (points.length >= 1)
{
path.moveTo (points[0].x, points[0].y);
for (i = 1; i < points.length; ++i)
path.lineTo (points[i].x, points[i].y);
path.close ();
}
/* Compute the damage rectangle. */
rectF = new RectF (0, 0, 0, 0);
path.computeBounds (rectF, true);
rect = new Rect ((int) Math.floor (rectF.left),
(int) Math.floor (rectF.top),
(int) Math.ceil (rectF.right),
(int) Math.ceil (rectF.bottom));
paint.setStyle (Paint.Style.FILL);
if (gc.clip_mask == null)
canvas.drawPath (path, paint);
drawable.damageRect (rect);
/* FillPolygon with clip mask not implemented; it is not used by
Emacs. */
}
}

View file

@ -0,0 +1,116 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.Log;
public final class EmacsFillRectangle
{
public static void
perform (EmacsDrawable drawable, EmacsGC gc,
int x, int y, int width, int height)
{
Paint maskPaint, paint;
Canvas maskCanvas;
Bitmap maskBitmap;
Rect rect;
Rect maskRect, dstRect;
Canvas canvas;
Bitmap clipBitmap;
/* TODO implement stippling. */
if (gc.fill_style == EmacsGC.GC_FILL_OPAQUE_STIPPLED)
return;
canvas = drawable.lockCanvas (gc);
if (canvas == null)
return;
paint = gc.gcPaint;
rect = new Rect (x, y, x + width, y + height);
paint.setStyle (Paint.Style.FILL);
if (gc.clip_mask == null)
canvas.drawRect (rect, paint);
else
{
/* Drawing with a clip mask involves calculating the
intersection of the clip mask with the dst rect, and
extrapolating the corresponding part of the src rect. */
clipBitmap = gc.clip_mask.bitmap;
dstRect = new Rect (x, y, x + width, y + height);
maskRect = new Rect (gc.clip_x_origin,
gc.clip_y_origin,
(gc.clip_x_origin
+ clipBitmap.getWidth ()),
(gc.clip_y_origin
+ clipBitmap.getHeight ()));
clipBitmap = gc.clip_mask.bitmap;
if (!maskRect.setIntersect (dstRect, maskRect))
/* There is no intersection between the clip mask and the
dest rect. */
return;
/* Finally, create a temporary bitmap that is the size of
maskRect. */
maskBitmap
= Bitmap.createBitmap (maskRect.width (), maskRect.height (),
Bitmap.Config.ARGB_8888);
/* Draw the mask onto the maskBitmap. */
maskCanvas = new Canvas (maskBitmap);
maskRect.offset (-gc.clip_x_origin,
-gc.clip_y_origin);
maskCanvas.drawBitmap (gc.clip_mask.bitmap,
maskRect, new Rect (0, 0,
maskRect.width (),
maskRect.height ()),
paint);
maskRect.offset (gc.clip_x_origin,
gc.clip_y_origin);
/* Set the transfer mode to SRC_IN to preserve only the parts
of the source that overlap with the mask. */
maskPaint = new Paint ();
maskPaint.setXfermode (EmacsGC.srcInAlu);
/* Draw the source. */
maskCanvas.drawRect (maskRect, maskPaint);
/* Finally, draw the mask bitmap to the destination. */
paint.setXfermode (null);
canvas.drawBitmap (maskBitmap, null, maskRect, paint);
/* Recycle this unused bitmap. */
maskBitmap.recycle ();
}
drawable.damageRect (rect);
}
}

View file

@ -0,0 +1,173 @@
/* Font backend for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import android.os.Build;
/* This code is mostly unused. See sfntfont-android.c for the code
that is actually used. */
public abstract class EmacsFontDriver
{
/* Font weights. */
public static final int THIN = 0;
public static final int ULTRA_LIGHT = 40;
public static final int LIGHT = 50;
public static final int SEMI_LIGHT = 55;
public static final int REGULAR = 80;
public static final int MEDIUM = 100;
public static final int SEMI_BOLD = 180;
public static final int BOLD = 200;
public static final int EXTRA_BOLD = 205;
public static final int BLACK = 210;
public static final int ULTRA_HEAVY = 250;
/* Font slants. */
public static final int REVERSE_OBLIQUE = 0;
public static final int REVERSE_ITALIC = 10;
public static final int NORMAL = 100;
public static final int ITALIC = 200;
public static final int OBLIQUE = 210;
/* Font widths. */
public static final int ULTRA_CONDENSED = 50;
public static final int EXTRA_CONDENSED = 63;
public static final int CONDENSED = 75;
public static final int SEMI_CONDENSED = 87;
public static final int UNSPECIFIED = 100;
public static final int SEMI_EXPANDED = 113;
public static final int EXPANDED = 125;
public static final int EXTRA_EXPANDED = 150;
public static final int ULTRA_EXPANDED = 200;
/* Font spacings. */
public static final int PROPORTIONAL = 0;
public static final int DUAL = 90;
public static final int MONO = 100;
public static final int CHARCELL = 110;
public static class FontSpec
{
/* The fields below mean the same as they do in enum
font_property_index in font.h. */
public String foundry;
public String family;
public String adstyle;
public String registry;
public Integer width;
public Integer weight;
public Integer slant;
public Integer size;
public Integer spacing;
public Integer avgwidth;
public Integer dpi;
@Override
public String
toString ()
{
return ("foundry: " + foundry
+ " family: " + family
+ " adstyle: " + adstyle
+ " registry: " + registry
+ " width: " + width
+ " weight: " + weight
+ " slant: " + slant
+ " spacing: " + spacing
+ " avgwidth: " + avgwidth
+ " dpi: " + dpi);
}
};
public static class FontMetrics
{
public short lbearing;
public short rbearing;
public short width;
public short ascent;
public short descent;
@Override
public String
toString ()
{
return ("lbearing " + lbearing
+ " rbearing " + rbearing
+ " width " + width
+ " ascent " + ascent
+ " descent " + descent);
}
}
public static class FontEntity extends FontSpec
{
/* No extra fields here. */
};
public abstract class FontObject extends FontSpec
{
public int minWidth;
public int maxWidth;
public int pixelSize;
public int height;
public int spaceWidth;
public int averageWidth;
public int ascent;
public int descent;
public int underlineThickness;
public int underlinePosition;
public int baselineOffset;
public int relativeCompose;
public int defaultAscent;
public int encodingCharset;
public int repertoryCharset;
public
FontObject ()
{
encodingCharset = -1;
repertoryCharset = -1;
}
};
/* These mean the same as they do in struct font_driver. */
public abstract FontEntity[] list (FontSpec fontSpec);
public abstract FontEntity match (FontSpec fontSpec);
public abstract String[] listFamilies ();
public abstract FontObject openFont (FontEntity fontEntity, int pixelSize);
public abstract int hasChar (FontSpec font, char charCode);
public abstract void textExtents (FontObject font, int code[],
FontMetrics fontMetrics);
public abstract int encodeChar (FontObject fontObject, char charCode);
public abstract int draw (FontObject fontObject, EmacsGC gc,
EmacsDrawable drawable, int[] chars,
int x, int y, int backgroundWidth,
boolean withBackground);
public static EmacsFontDriver
createFontDriver ()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
return new EmacsSdk23FontDriver ();
return new EmacsSdk7FontDriver ();
}
};

View file

@ -0,0 +1,121 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import android.graphics.Rect;
import android.graphics.Paint;
import android.graphics.PorterDuff.Mode;
import android.graphics.PorterDuffXfermode;
import android.graphics.Xfermode;
/* X like graphics context structures. Keep the enums in synch with
androidgui.h! */
public final class EmacsGC extends EmacsHandleObject
{
public static final int GC_COPY = 0;
public static final int GC_XOR = 1;
public static final int GC_FILL_SOLID = 0;
public static final int GC_FILL_OPAQUE_STIPPLED = 1;
public static final Xfermode xorAlu, srcInAlu;
public int function, fill_style;
public int foreground, background;
public int clip_x_origin, clip_y_origin;
public int ts_origin_x, ts_origin_y;
public Rect clip_rects[], real_clip_rects[];
public EmacsPixmap clip_mask, stipple;
public Paint gcPaint;
/* ID incremented every time the clipping rectangles of any GC
changes. */
private static long clip_serial;
/* The value of clipRectID after the last time this GCs clip
rectangles changed. 0 if there are no clip rectangles. */
public long clipRectID;
static
{
xorAlu = new PorterDuffXfermode (Mode.XOR);
srcInAlu = new PorterDuffXfermode (Mode.SRC_IN);
}
/* The following fields are only set on immutable GCs. */
public
EmacsGC (short handle)
{
/* For historical reasons the C code has an extra layer of
indirection above this GC handle. struct android_gc is the GC
used by Emacs code, while android_gcontext is the type of the
handle. */
super (handle);
fill_style = GC_FILL_SOLID;
function = GC_COPY;
foreground = 0;
background = 0xffffff;
gcPaint = new Paint ();
}
/* Mark this GC as dirty. Apply parameters to the paint and
recompute real_clip_rects. */
public void
markDirty (boolean clipRectsChanged)
{
int i;
if (clipRectsChanged)
{
if ((ts_origin_x != 0 || ts_origin_y != 0)
&& clip_rects != null)
{
real_clip_rects = new Rect[clip_rects.length];
for (i = 0; i < clip_rects.length; ++i)
{
real_clip_rects[i] = new Rect (clip_rects[i]);
real_clip_rects[i].offset (ts_origin_x, ts_origin_y);
}
}
else
real_clip_rects = clip_rects;
clipRectID = ++clip_serial;
}
gcPaint.setStrokeWidth (1f);
gcPaint.setColor (foreground | 0xff000000);
gcPaint.setXfermode (function == GC_XOR
? xorAlu : srcInAlu);
}
public void
resetXfermode ()
{
gcPaint.setXfermode (function == GC_XOR
? xorAlu : srcInAlu);
}
};

View file

@ -0,0 +1,59 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import java.lang.IllegalStateException;
/* This defines something that is a so-called ``handle''. Handles
must be created by C code, and will remain existing until
destroyHandle is called. C code then refers to the handle by a
number which maps into the Java object representing the handle.
All handle operations must be done from the Emacs thread. */
public abstract class EmacsHandleObject
{
/* Whether or not this handle has been destroyed. */
volatile boolean destroyed;
/* The handle associated with this object. */
public short handle;
public
EmacsHandleObject (short handle)
{
this.handle = handle;
}
public void
destroyHandle () throws IllegalStateException
{
synchronized (this)
{
destroyed = true;
}
}
public boolean
isDestroyed ()
{
return destroyed;
}
};

View file

@ -0,0 +1,348 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import android.view.inputmethod.BaseInputConnection;
import android.view.inputmethod.CompletionInfo;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
import android.view.inputmethod.TextSnapshot;
import android.view.KeyEvent;
import android.os.Build;
import android.util.Log;
/* Android input methods, take number six. See textconv.c for more
details; this is more-or-less a thin wrapper around that file. */
public final class EmacsInputConnection extends BaseInputConnection
{
private static final String TAG = "EmacsInputConnection";
private EmacsView view;
private short windowHandle;
/* Whether or not to synchronize and call `updateIC' with the
selection position after committing text.
This helps with on screen keyboard programs found in some vendor
versions of Android, which rely on immediate updates to the point
position after text is commited in order to place the cursor
within that text. */
private static boolean syncAfterCommit;
/* Whether or not to return empty text with the offset set to zero
if a request arrives that has no flags set and has requested no
characters at all.
This is necessary with on screen keyboard programs found in some
vendor versions of Android which don't rely on the documented
meaning of `ExtractedText.startOffset', and instead take the
selection offset inside at face value. */
private static boolean extractAbsoluteOffsets;
static
{
if (Build.MANUFACTURER.equalsIgnoreCase ("Huawei")
|| Build.MANUFACTURER.equalsIgnoreCase ("Honor"))
extractAbsoluteOffsets = syncAfterCommit = true;
};
public
EmacsInputConnection (EmacsView view)
{
super (view, true);
this.view = view;
this.windowHandle = view.window.handle;
}
@Override
public boolean
beginBatchEdit ()
{
if (EmacsService.DEBUG_IC)
Log.d (TAG, "beginBatchEdit");
EmacsNative.beginBatchEdit (windowHandle);
return true;
}
@Override
public boolean
endBatchEdit ()
{
if (EmacsService.DEBUG_IC)
Log.d (TAG, "endBatchEdit");
EmacsNative.endBatchEdit (windowHandle);
return true;
}
@Override
public boolean
commitCompletion (CompletionInfo info)
{
if (EmacsService.DEBUG_IC)
Log.d (TAG, "commitCompletion: " + info);
EmacsNative.commitCompletion (windowHandle,
info.getText ().toString (),
info.getPosition ());
return true;
}
@Override
public boolean
commitText (CharSequence text, int newCursorPosition)
{
int[] selection;
if (EmacsService.DEBUG_IC)
Log.d (TAG, "commitText: " + text + " " + newCursorPosition);
EmacsNative.commitText (windowHandle, text.toString (),
newCursorPosition);
if (syncAfterCommit)
{
/* Synchronize with the Emacs thread, obtain the new
selection, and report it immediately. */
selection = EmacsNative.getSelection (windowHandle);
if (EmacsService.DEBUG_IC && selection != null)
Log.d (TAG, "commitText: new selection is " + selection[0]
+ ", by " + selection[1]);
if (selection != null)
/* N.B. that the composing region is removed after text is
committed. */
view.imManager.updateSelection (view, selection[0],
selection[1], -1, -1);
}
return true;
}
@Override
public boolean
deleteSurroundingText (int leftLength, int rightLength)
{
if (EmacsService.DEBUG_IC)
Log.d (TAG, ("deleteSurroundingText: "
+ leftLength + " " + rightLength));
EmacsNative.deleteSurroundingText (windowHandle, leftLength,
rightLength);
return true;
}
@Override
public boolean
finishComposingText ()
{
if (EmacsService.DEBUG_IC)
Log.d (TAG, "finishComposingText");
EmacsNative.finishComposingText (windowHandle);
return true;
}
@Override
public String
getSelectedText (int flags)
{
if (EmacsService.DEBUG_IC)
Log.d (TAG, "getSelectedText: " + flags);
return EmacsNative.getSelectedText (windowHandle, flags);
}
@Override
public String
getTextAfterCursor (int length, int flags)
{
String string;
if (EmacsService.DEBUG_IC)
Log.d (TAG, "getTextAfterCursor: " + length + " " + flags);
string = EmacsNative.getTextAfterCursor (windowHandle, length,
flags);
if (EmacsService.DEBUG_IC)
Log.d (TAG, " --> " + string);
return string;
}
@Override
public String
getTextBeforeCursor (int length, int flags)
{
String string;
if (EmacsService.DEBUG_IC)
Log.d (TAG, "getTextBeforeCursor: " + length + " " + flags);
string = EmacsNative.getTextBeforeCursor (windowHandle, length,
flags);
if (EmacsService.DEBUG_IC)
Log.d (TAG, " --> " + string);
return string;
}
@Override
public boolean
setComposingText (CharSequence text, int newCursorPosition)
{
if (EmacsService.DEBUG_IC)
Log.d (TAG, ("setComposingText: "
+ text + " ## " + newCursorPosition));
EmacsNative.setComposingText (windowHandle, text.toString (),
newCursorPosition);
return true;
}
@Override
public boolean
setComposingRegion (int start, int end)
{
if (EmacsService.DEBUG_IC)
Log.d (TAG, "setComposingRegion: " + start + " " + end);
EmacsNative.setComposingRegion (windowHandle, start, end);
return true;
}
@Override
public boolean
performEditorAction (int editorAction)
{
if (EmacsService.DEBUG_IC)
Log.d (TAG, "performEditorAction: " + editorAction);
EmacsNative.performEditorAction (windowHandle, editorAction);
return true;
}
@Override
public ExtractedText
getExtractedText (ExtractedTextRequest request, int flags)
{
ExtractedText text;
int[] selection;
if (EmacsService.DEBUG_IC)
Log.d (TAG, "getExtractedText: " + request.hintMaxChars + ", "
+ request.hintMaxLines + " " + flags);
/* If a request arrives with hintMaxChars, hintMaxLines and flags
set to 0, and the system is known to be buggy, return an empty
extracted text object with the absolute selection positions. */
if (extractAbsoluteOffsets
&& request.hintMaxChars == 0
&& request.hintMaxLines == 0
&& flags == 0)
{
/* Obtain the selection. */
selection = EmacsNative.getSelection (windowHandle);
if (selection == null)
return null;
/* Create the workaround extracted text. */
text = new ExtractedText ();
text.partialStartOffset = -1;
text.partialEndOffset = -1;
text.text = "";
text.selectionStart = selection[0];
text.selectionEnd = selection[1];
}
else
text = EmacsNative.getExtractedText (windowHandle, request,
flags);
if (EmacsService.DEBUG_IC)
Log.d (TAG, "getExtractedText: " + text.text + " @"
+ text.startOffset + ":" + text.selectionStart
+ ", " + text.selectionEnd);
return text;
}
@Override
public boolean
setSelection (int start, int end)
{
if (EmacsService.DEBUG_IC)
Log.d (TAG, "setSelection: " + start + " " + end);
EmacsNative.setSelection (windowHandle, start, end);
return true;
}
@Override
public boolean
sendKeyEvent (KeyEvent key)
{
if (EmacsService.DEBUG_IC)
Log.d (TAG, "sendKeyEvent: " + key);
return super.sendKeyEvent (key);
}
@Override
public boolean
deleteSurroundingTextInCodePoints (int beforeLength, int afterLength)
{
/* This can be implemented the same way as
deleteSurroundingText. */
return this.deleteSurroundingText (beforeLength, afterLength);
}
@Override
public boolean
requestCursorUpdates (int cursorUpdateMode)
{
if (EmacsService.DEBUG_IC)
Log.d (TAG, "requestCursorUpdates: " + cursorUpdateMode);
EmacsNative.requestCursorUpdates (windowHandle, cursorUpdateMode);
return true;
}
/* Override functions which are not implemented. */
@Override
public TextSnapshot
takeSnapshot ()
{
Log.d (TAG, "takeSnapshot");
return null;
}
}

View file

@ -0,0 +1,29 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
/* This class only exists because EmacsActivity is already defined as
an activity, and the system wants a new class in order to define a
new activity. */
public final class EmacsMultitaskActivity extends EmacsActivity
{
}

View file

@ -0,0 +1,254 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import android.content.res.AssetManager;
import android.view.inputmethod.ExtractedText;
import android.view.inputmethod.ExtractedTextRequest;
public final class EmacsNative
{
/* List of native libraries that must be loaded during class
initialization. */
private static final String[] libraryDeps;
/* Like `dup' in C. */
public static native int dup (int fd);
/* Obtain the fingerprint of this build of Emacs. The fingerprint
can be used to determine the dump file name. */
public static native String getFingerprint ();
/* Set certain parameters before initializing Emacs.
assetManager must be the asset manager associated with the
context that is loading Emacs. It is saved and remains for the
remainder the lifetime of the Emacs process.
filesDir must be the package's data storage location for the
current Android user.
libDir must be the package's data storage location for native
libraries. It is used as PATH.
cacheDir must be the package's cache directory. It is used as
the `temporary-file-directory'.
pixelDensityX and pixelDensityY are the DPI values that will be
used by Emacs.
classPath must be the classpath of this app_process process, or
NULL.
emacsService must be the EmacsService singleton, or NULL. */
public static native void setEmacsParams (AssetManager assetManager,
String filesDir,
String libDir,
String cacheDir,
float pixelDensityX,
float pixelDensityY,
String classPath,
EmacsService emacsService);
/* Initialize Emacs with the argument array ARGV. Each argument
must contain a NULL terminated string, or else the behavior is
undefined.
DUMPFILE is the dump file to use, or NULL if Emacs is to load
loadup.el itself.
APILEVEL is the version of Android being used. */
public static native void initEmacs (String argv[], String dumpFile,
int apiLevel);
/* Abort and generate a native core dump. */
public static native void emacsAbort ();
/* Set Vquit_flag to t, resulting in Emacs quitting as soon as
possible. */
public static native void quit ();
/* Send an ANDROID_CONFIGURE_NOTIFY event. The values of all the
functions below are the serials of the events sent. */
public static native long sendConfigureNotify (short window, long time,
int x, int y, int width,
int height);
/* Send an ANDROID_KEY_PRESS event. */
public static native long sendKeyPress (short window, long time, int state,
int keyCode, int unicodeChar);
/* Send an ANDROID_KEY_RELEASE event. */
public static native long sendKeyRelease (short window, long time, int state,
int keyCode, int unicodeChar);
/* Send an ANDROID_FOCUS_IN event. */
public static native long sendFocusIn (short window, long time);
/* Send an ANDROID_FOCUS_OUT event. */
public static native long sendFocusOut (short window, long time);
/* Send an ANDROID_WINDOW_ACTION event. */
public static native long sendWindowAction (short window, int action);
/* Send an ANDROID_ENTER_NOTIFY event. */
public static native long sendEnterNotify (short window, int x, int y,
long time);
/* Send an ANDROID_LEAVE_NOTIFY event. */
public static native long sendLeaveNotify (short window, int x, int y,
long time);
/* Send an ANDROID_MOTION_NOTIFY event. */
public static native long sendMotionNotify (short window, int x, int y,
long time);
/* Send an ANDROID_BUTTON_PRESS event. */
public static native long sendButtonPress (short window, int x, int y,
long time, int state,
int button);
/* Send an ANDROID_BUTTON_RELEASE event. */
public static native long sendButtonRelease (short window, int x, int y,
long time, int state,
int button);
/* Send an ANDROID_TOUCH_DOWN event. */
public static native long sendTouchDown (short window, int x, int y,
long time, int pointerID);
/* Send an ANDROID_TOUCH_UP event. */
public static native long sendTouchUp (short window, int x, int y,
long time, int pointerID);
/* Send an ANDROID_TOUCH_MOVE event. */
public static native long sendTouchMove (short window, int x, int y,
long time, int pointerID);
/* Send an ANDROID_WHEEL event. */
public static native long sendWheel (short window, int x, int y,
long time, int state,
float xDelta, float yDelta);
/* Send an ANDROID_ICONIFIED event. */
public static native long sendIconified (short window);
/* Send an ANDROID_DEICONIFIED event. */
public static native long sendDeiconified (short window);
/* Send an ANDROID_CONTEXT_MENU event. */
public static native long sendContextMenu (short window, int menuEventID,
int menuEventSerial);
/* Send an ANDROID_EXPOSE event. */
public static native long sendExpose (short window, int x, int y,
int width, int height);
/* Return the file name associated with the specified file
descriptor, or NULL if there is none. */
public static native byte[] getProcName (int fd);
/* Notice that the Emacs thread will now start waiting for the main
thread's looper to respond. */
public static native void beginSynchronous ();
/* Notice that the Emacs thread will has finished waiting for the
main thread's looper to respond. */
public static native void endSynchronous ();
/* Return whether or not KEYCODE_VOLUME_DOWN, KEYCODE_VOLUME_UP and
KEYCODE_VOLUME_MUTE should be forwarded to Emacs. */
public static native boolean shouldForwardMultimediaButtons ();
/* Input connection functions. These mostly correspond to their
counterparts in Android's InputConnection. */
public static native void beginBatchEdit (short window);
public static native void endBatchEdit (short window);
public static native void commitCompletion (short window, String text,
int position);
public static native void commitText (short window, String text,
int position);
public static native void deleteSurroundingText (short window,
int leftLength,
int rightLength);
public static native void finishComposingText (short window);
public static native String getSelectedText (short window, int flags);
public static native String getTextAfterCursor (short window, int length,
int flags);
public static native String getTextBeforeCursor (short window, int length,
int flags);
public static native void setComposingText (short window, String text,
int newCursorPosition);
public static native void setComposingRegion (short window, int start,
int end);
public static native void setSelection (short window, int start, int end);
public static native void performEditorAction (short window,
int editorAction);
public static native ExtractedText getExtractedText (short window,
ExtractedTextRequest req,
int flags);
public static native void requestSelectionUpdate (short window);
public static native void requestCursorUpdates (short window, int mode);
/* Return the current value of the selection, or -1 upon
failure. */
public static native int[] getSelection (short window);
static
{
/* Older versions of Android cannot link correctly with shared
libraries that link with other shared libraries built along
Emacs unless all requisite shared libraries are explicitly
loaded from Java.
Every time you add a new shared library dependency to Emacs,
please add it here as well. */
libraryDeps = new String[] { "png_emacs", "selinux_emacs",
"crypto_emacs", "pcre_emacs",
"packagelistparser_emacs",
"gnutls_emacs", "gmp_emacs",
"nettle_emacs", "p11-kit_emacs",
"tasn1_emacs", "hogweed_emacs",
"jansson_emacs", "jpeg_emacs",
"tiff_emacs", "xml2_emacs",
"icuuc_emacs",
"tree-sitter_emacs", };
for (String dependency : libraryDeps)
{
try
{
System.loadLibrary (dependency);
}
catch (UnsatisfiedLinkError exception)
{
/* Ignore this exception. */
}
}
System.loadLibrary ("emacs");
};
};

View file

@ -0,0 +1,203 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import android.os.Looper;
import android.os.Build;
import android.content.Context;
import android.content.res.AssetManager;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/* Noninteractive Emacs.
This is the class that libandroid-emacs.so starts.
libandroid-emacs.so figures out the system classpath, then starts
dalvikvm with the framework jars.
At that point, dalvikvm calls main, which sets up the main looper,
creates an ActivityThread and attaches it to the main thread.
Then, it obtains an application context for the LoadedApk in the
application thread.
Finally, it obtains the necessary context specific objects and
initializes Emacs. */
@SuppressWarnings ("unchecked")
public final class EmacsNoninteractive
{
public static void
main (String[] args)
{
Object activityThread, loadedApk;
Class activityThreadClass, loadedApkClass, contextImplClass;
Class compatibilityInfoClass;
Method method;
Context context;
AssetManager assets;
String filesDir, libDir, cacheDir;
Looper.prepare ();
context = null;
assets = null;
filesDir = libDir = cacheDir = null;
try
{
/* Get the activity thread. */
activityThreadClass = Class.forName ("android.app.ActivityThread");
/* Get the systemMain method. */
method = activityThreadClass.getMethod ("systemMain");
/* Create and attach the activity thread. */
activityThread = method.invoke (null);
context = null;
/* Now get an LoadedApk. */
try
{
loadedApkClass = Class.forName ("android.app.LoadedApk");
}
catch (ClassNotFoundException exception)
{
/* Android 2.2 has no LoadedApk class, but fortunately it
does not need to be used, since contexts can be
directly created. */
loadedApkClass = null;
contextImplClass = Class.forName ("android.app.ContextImpl");
method = activityThreadClass.getDeclaredMethod ("getSystemContext");
context = (Context) method.invoke (activityThread);
method = contextImplClass.getDeclaredMethod ("createPackageContext",
String.class,
int.class);
method.setAccessible (true);
context = (Context) method.invoke (context, "org.gnu.emacs",
0);
}
/* If the context has not already been created, then do what
is appropriate for newer versions of Android. */
if (context == null)
{
/* Get a LoadedApk. How to do this varies by Android version.
On Android 2.3.3 and earlier, there is no
``compatibilityInfo'' argument to getPackageInfo. */
if (Build.VERSION.SDK_INT
<= Build.VERSION_CODES.GINGERBREAD_MR1)
{
method
= activityThreadClass.getMethod ("getPackageInfo",
String.class,
int.class);
loadedApk = method.invoke (activityThread, "org.gnu.emacs",
0);
}
else
{
compatibilityInfoClass
= Class.forName ("android.content.res.CompatibilityInfo");
method
= activityThreadClass.getMethod ("getPackageInfo",
String.class,
compatibilityInfoClass,
int.class);
loadedApk = method.invoke (activityThread, "org.gnu.emacs",
null, 0);
}
if (loadedApk == null)
throw new RuntimeException ("getPackageInfo returned NULL");
/* Now, get a context. */
contextImplClass = Class.forName ("android.app.ContextImpl");
try
{
method
= contextImplClass.getDeclaredMethod ("createAppContext",
activityThreadClass,
loadedApkClass);
method.setAccessible (true);
context = (Context) method.invoke (null, activityThread,
loadedApk);
}
catch (NoSuchMethodException exception)
{
/* Older Android versions don't have createAppContext, but
instead require creating a ContextImpl, and then
calling createPackageContext. */
method
= activityThreadClass.getDeclaredMethod ("getSystemContext");
context = (Context) method.invoke (activityThread);
method
= contextImplClass.getDeclaredMethod ("createPackageContext",
String.class,
int.class);
method.setAccessible (true);
context = (Context) method.invoke (context, "org.gnu.emacs",
0);
}
}
/* Don't actually start the looper or anything. Instead, obtain
an AssetManager. */
assets = context.getAssets ();
/* Now configure Emacs. The class path should already be set. */
filesDir = context.getFilesDir ().getCanonicalPath ();
libDir = EmacsService.getLibraryDirectory (context);
cacheDir = context.getCacheDir ().getCanonicalPath ();
}
catch (Exception e)
{
System.err.println ("Internal error: " + e);
System.err.println ("This means that the Android platform changed,");
System.err.println ("and that Emacs needs adjustments in order to");
System.err.println ("obtain required system internal resources.");
System.err.println ("Please report this bug to bug-gnu-emacs@gnu.org.");
e.printStackTrace ();
System.exit (1);
}
EmacsNative.setEmacsParams (assets, filesDir,
libDir, cacheDir, 0.0f,
0.0f, null, null);
/* Now find the dump file that Emacs should use, if it has already
been dumped. */
EmacsApplication.findDumpFile (context);
/* Start Emacs. */
EmacsNative.initEmacs (args, EmacsApplication.dumpFileName,
Build.VERSION.SDK_INT);
}
};

View file

@ -0,0 +1,472 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
/* This class makes the Emacs server work reasonably on Android.
There is no way to make the Unix socket publicly available on
Android.
Instead, this activity tries to connect to the Emacs server, to
make it open files the system asks Emacs to open, and to emulate
some reasonable behavior when Emacs has not yet started.
First, Emacs registers itself as an application that can open text
and image files.
Then, when the user is asked to open a file and selects ``Emacs''
as the application that will open the file, the system pops up a
window, this activity, and calls the `onCreate' function.
`onCreate' then tries very to find the file name of the file that
was selected, and give it to emacsclient.
If emacsclient successfully opens the file, then this activity
starts EmacsActivity (to bring it on to the screen); otherwise, it
displays the output of emacsclient or any error message that occurs
and exits. */
import android.app.AlertDialog;
import android.app.Activity;
import android.content.ContentResolver;
import android.content.DialogInterface;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
public final class EmacsOpenActivity extends Activity
implements DialogInterface.OnClickListener,
DialogInterface.OnCancelListener
{
private static final String TAG = "EmacsOpenActivity";
public static String fileToOpen;
private class EmacsClientThread extends Thread
{
private ProcessBuilder builder;
public
EmacsClientThread (ProcessBuilder processBuilder)
{
builder = processBuilder;
}
@Override
public void
run ()
{
Process process;
InputStream error;
String errorText;
try
{
/* Start emacsclient. */
process = builder.start ();
process.waitFor ();
/* Now figure out whether or not starting the process was
successful. */
if (process.exitValue () == 0)
finishSuccess ();
else
finishFailure ("Error opening file", null);
}
catch (IOException exception)
{
finishFailure ("Internal error", exception.toString ());
}
catch (InterruptedException exception)
{
finishFailure ("Internal error", exception.toString ());
}
}
}
@Override
public void
onClick (DialogInterface dialog, int which)
{
finish ();
}
@Override
public void
onCancel (DialogInterface dialog)
{
finish ();
}
public String
readEmacsClientLog ()
{
File file, cache;
FileReader reader;
char[] buffer;
int rc;
String what;
/* Because the ProcessBuilder functions necessary to redirect
process output are not implemented on Android 7 and earlier,
print a generic error message. */
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
return ("This is likely because the Emacs server"
+ " is not running, or because you did"
+ " not grant Emacs permission to access"
+ " external storage.");
cache = getCacheDir ();
file = new File (cache, "emacsclient.log");
what = "";
try
{
reader = new FileReader (file);
buffer = new char[2048];
while ((rc = reader.read (buffer, 0, 2048)) != -1)
what += String.valueOf (buffer, 0, 2048);
reader.close ();
return what;
}
catch (IOException exception)
{
return ("Couldn't read emacsclient.log: "
+ exception.toString ());
}
}
private void
displayFailureDialog (String title, String text)
{
AlertDialog.Builder builder;
AlertDialog dialog;
builder = new AlertDialog.Builder (this);
dialog = builder.create ();
dialog.setTitle (title);
if (text == null)
/* Read in emacsclient.log instead. */
text = readEmacsClientLog ();
dialog.setMessage (text);
dialog.setButton (DialogInterface.BUTTON_POSITIVE, "OK", this);
dialog.setOnCancelListener (this);
dialog.show ();
}
/* Check that the specified FILE is readable. If Android 4.4 or
later is being used, return URI formatted into a `/content/' file
name.
If it is not, then copy the file in FD to a location in the
system cache directory and return the name of that file. */
private String
checkReadableOrCopy (String file, ParcelFileDescriptor fd,
Uri uri)
throws IOException, FileNotFoundException
{
File inFile;
FileOutputStream outStream;
InputStream stream;
byte buffer[];
int read;
String content;
Log.d (TAG, "checkReadableOrCopy: " + file);
inFile = new File (file);
if (inFile.canRead ())
return file;
Log.d (TAG, "checkReadableOrCopy: NO");
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
{
content = "/content/" + uri.getEncodedAuthority ();
for (String segment : uri.getPathSegments ())
content += "/" + Uri.encode (segment);
/* Append the URI query. */
if (uri.getEncodedQuery () != null)
content += "?" + uri.getEncodedQuery ();
Log.d (TAG, "checkReadableOrCopy: " + content);
return content;
}
/* inFile is now the file being written to. */
inFile = new File (getCacheDir (), inFile.getName ());
buffer = new byte[4098];
outStream = new FileOutputStream (inFile);
stream = new FileInputStream (fd.getFileDescriptor ());
try
{
while ((read = stream.read (buffer)) >= 0)
outStream.write (buffer, 0, read);
}
finally
{
/* Note that this does not close FD.
Keep in mind that execution is transferred to ``finally''
even if an exception happens inside the while loop
above. */
stream.close ();
outStream.close ();
}
return inFile.getCanonicalPath ();
}
/* Finish this activity in response to emacsclient having
successfully opened a file.
In the main thread, close this window, and open a window
belonging to an Emacs frame. */
public void
finishSuccess ()
{
runOnUiThread (new Runnable () {
@Override
public void
run ()
{
Intent intent;
intent = new Intent (EmacsOpenActivity.this,
EmacsActivity.class);
/* This means only an existing frame will be displayed. */
intent.addFlags (Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
startActivity (intent);
EmacsOpenActivity.this.finish ();
}
});
}
/* Finish this activity after displaying a dialog associated with
failure to open a file.
Use TITLE as the title of the dialog. If TEXT is non-NULL,
display that text in the dialog. Otherwise, use the contents of
emacsclient.log in the cache directory instead, or describe why
that file cannot be read. */
public void
finishFailure (final String title, final String text)
{
runOnUiThread (new Runnable () {
@Override
public void
run ()
{
displayFailureDialog (title, text);
}
});
}
public void
startEmacsClient (String fileName)
{
String libDir;
ProcessBuilder builder;
Process process;
EmacsClientThread thread;
File file;
Intent intent;
/* If the Emacs service is not running, then start Emacs and make
it open this file. */
if (EmacsService.SERVICE == null)
{
fileToOpen = fileName;
intent = new Intent (EmacsOpenActivity.this,
EmacsActivity.class);
finish ();
startActivity (intent);
return;
}
libDir = EmacsService.getLibraryDirectory (this);
builder = new ProcessBuilder (libDir + "/libemacsclient.so",
fileName, "--reuse-frame",
"--timeout=10", "--no-wait");
/* Redirection is unfortunately not possible in Android 7 and
earlier. */
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
file = new File (getCacheDir (), "emacsclient.log");
/* Redirect standard error to a file so that errors can be
meaningfully reported. */
if (file.exists ())
file.delete ();
builder.redirectError (file);
}
/* Track process output in a new thread, since this is the UI
thread and doing so here can cause deadlocks when EmacsService
decides to wait for something. */
thread = new EmacsClientThread (builder);
thread.start ();
}
@Override
public void
onCreate (Bundle savedInstanceState)
{
String action, fileName;
Intent intent;
Uri uri;
ContentResolver resolver;
ParcelFileDescriptor fd;
byte[] names;
String errorBlurb;
super.onCreate (savedInstanceState);
/* Obtain the intent that started Emacs. */
intent = getIntent ();
action = intent.getAction ();
if (action == null)
{
finish ();
return;
}
/* Now see if the action specified is supported by Emacs. */
if (action.equals ("android.intent.action.VIEW")
|| action.equals ("android.intent.action.EDIT")
|| action.equals ("android.intent.action.PICK"))
{
/* Obtain the URI of the action. */
uri = intent.getData ();
if (uri == null)
{
finish ();
return;
}
/* Now, try to get the file name. */
if (uri.getScheme ().equals ("file"))
fileName = uri.getPath ();
else
{
fileName = null;
if (uri.getScheme ().equals ("content"))
{
/* This is one of the annoying Android ``content''
URIs. Most of the time, there is actually an
underlying file, but it cannot be found without
opening the file and doing readlink on its file
descriptor in /proc/self/fd. */
resolver = getContentResolver ();
fd = null;
try
{
fd = resolver.openFileDescriptor (uri, "r");
names = EmacsNative.getProcName (fd.getFd ());
/* What is the right encoding here? */
if (names != null)
fileName = new String (names, "UTF-8");
fileName = checkReadableOrCopy (fileName, fd, uri);
}
catch (FileNotFoundException exception)
{
/* Do nothing. */
}
catch (IOException exception)
{
/* Do nothing. */
}
if (fd != null)
{
try
{
fd.close ();
}
catch (IOException exception)
{
/* Do nothing. */
}
}
}
if (fileName == null)
{
errorBlurb = ("The URI: " + uri + " could not be opened"
+ ", as it does not encode file name inform"
+ "ation.");
displayFailureDialog ("Error opening file", errorBlurb);
return;
}
}
/* And start emacsclient. */
startEmacsClient (fileName);
}
else
finish ();
}
}

View file

@ -0,0 +1,192 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import java.lang.IllegalArgumentException;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Rect;
import android.os.Build;
/* Drawable backed by bitmap. */
public final class EmacsPixmap extends EmacsHandleObject
implements EmacsDrawable
{
/* The depth of the bitmap. This is not actually used, just defined
in order to be consistent with X. */
public int depth, width, height;
/* The bitmap itself. */
public Bitmap bitmap;
/* The canvas used to draw to BITMAP. */
public Canvas canvas;
/* Whether or not GC should be explicitly triggered upon
release. */
private boolean needCollect;
/* ID used to determine whether or not the GC clip rects
changed. */
private long gcClipRectID;
public
EmacsPixmap (short handle, int colors[], int width,
int height, int depth)
{
super (handle);
if (depth != 1 && depth != 24)
throw new IllegalArgumentException ("Invalid depth specified"
+ " for pixmap: " + depth);
switch (depth)
{
case 1:
bitmap = Bitmap.createBitmap (colors, width, height,
Bitmap.Config.ALPHA_8);
break;
case 24:
bitmap = Bitmap.createBitmap (colors, width, height,
Bitmap.Config.ARGB_8888);
bitmap.setHasAlpha (false);
break;
}
this.width = width;
this.height = height;
this.depth = depth;
}
public
EmacsPixmap (short handle, int width, int height, int depth)
{
super (handle);
if (depth != 1 && depth != 24)
throw new IllegalArgumentException ("Invalid depth specified"
+ " for pixmap: " + depth);
switch (depth)
{
case 1:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
bitmap = Bitmap.createBitmap (width, height,
Bitmap.Config.ALPHA_8,
false);
else
bitmap = Bitmap.createBitmap (width, height,
Bitmap.Config.ALPHA_8);
break;
case 24:
/* Emacs doesn't just use the first kind of `createBitmap'
because the latter allows specifying that the pixmap is
always opaque, which really increases efficiency. */
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
bitmap = Bitmap.createBitmap (width, height,
Bitmap.Config.ARGB_8888);
else
bitmap = Bitmap.createBitmap (width, height,
Bitmap.Config.ARGB_8888,
false);
break;
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB_MR1)
/* On these old versions of Android, Bitmap.recycle frees bitmap
contents immediately. */
needCollect = false;
else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT)
needCollect = (bitmap.getByteCount ()
>= 1024 * 512);
else
needCollect = (bitmap.getAllocationByteCount ()
>= 1024 * 512);
bitmap.eraseColor (0xff000000);
this.width = width;
this.height = height;
this.depth = depth;
}
@Override
public Canvas
lockCanvas (EmacsGC gc)
{
int i;
if (canvas == null)
{
canvas = new Canvas (bitmap);
canvas.save ();
}
/* Now see if clipping has to be redone. */
if (gc.clipRectID == gcClipRectID)
return canvas;
/* It does have to be redone. Reapply gc.real_clip_rects. */
canvas.restore ();
canvas.save ();
if (gc.real_clip_rects != null)
{
for (i = 0; i < gc.real_clip_rects.length; ++i)
canvas.clipRect (gc.real_clip_rects[i]);
}
/* Save the clip rect ID again. */
gcClipRectID = gc.clipRectID;
return canvas;
}
@Override
public void
damageRect (Rect damageRect)
{
}
@Override
public Bitmap
getBitmap ()
{
return bitmap;
}
@Override
public void
destroyHandle ()
{
bitmap.recycle ();
bitmap = null;
/* Collect the bitmap storage if the bitmap is big. */
if (needCollect)
Runtime.getRuntime ().gc ();
}
};

View file

@ -0,0 +1,141 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import java.io.File;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.os.Build;
import android.widget.Toast;
import android.preference.*;
/* This module provides a ``preferences'' display for Emacs. It is
supposed to be launched from inside the Settings application to
perform various actions, such as starting Emacs with the ``-Q''
option, which would not be possible otherwise, as there is no
command line on Android.
Android provides a preferences activity, but it is deprecated.
Unfortunately, there is no alternative that looks the same way. */
@SuppressWarnings ("deprecation")
public final class EmacsPreferencesActivity extends PreferenceActivity
{
/* Restart Emacs with -Q. Call EmacsThread.exit to kill Emacs now, and
tell the system to EmacsActivity with some parameters later. */
private void
startEmacsQ ()
{
Intent intent;
intent = new Intent (this, EmacsActivity.class);
intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
intent.putExtra ("org.gnu.emacs.START_DASH_Q", true);
startActivity (intent);
System.exit (0);
}
/* Erase Emacs's dump file. */
private void
eraseDumpFile ()
{
String wantedDumpFile;
File file;
Toast toast;
wantedDumpFile = ("emacs-" + EmacsNative.getFingerprint ()
+ ".pdmp");
file = new File (getFilesDir (), wantedDumpFile);
if (file.exists ())
file.delete ();
/* Make sure to clear EmacsApplication.dumpFileName, or
starting Emacs without restarting this program will
make Emacs try to load a nonexistent dump file. */
EmacsApplication.dumpFileName = null;
/* Display a message stating that the dump file has been
erased. */
toast = Toast.makeText (this, "Dump file removed",
Toast.LENGTH_SHORT);
toast.show ();
}
@Override
public void
onCreate (Bundle savedInstanceState)
{
Preference tem;
Preference.OnPreferenceClickListener listener;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP)
setTheme (android.R.style.Theme_DeviceDefault_Settings);
else if (Build.VERSION.SDK_INT
>= Build.VERSION_CODES.ICE_CREAM_SANDWICH)
setTheme (android.R.style.Theme_DeviceDefault);
/* This must come before using any preference APIs. */
super.onCreate (savedInstanceState);
/* Add preferences from the XML file where they are defined. */
addPreferencesFromResource (R.xml.preferences);
/* Now, set up on click handlers for each of the preferences
items. */
tem = findPreference ("start_quick");
listener = new Preference.OnPreferenceClickListener () {
@Override
public boolean
onPreferenceClick (Preference preference)
{
startEmacsQ ();
return true;
}
};
tem.setOnPreferenceClickListener (listener);
tem = findPreference ("erase_dump");
listener = new Preference.OnPreferenceClickListener () {
@Override
public boolean
onPreferenceClick (Preference preference)
{
eraseDumpFile ();
return true;
}
};
tem.setOnPreferenceClickListener (listener);
}
};

View file

@ -0,0 +1,290 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.ContentResolver;
import android.content.ClipData;
import android.content.ClipDescription;
import android.content.res.AssetFileDescriptor;
import android.net.Uri;
import android.util.Log;
import android.os.Build;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
/* This class implements EmacsClipboard for Android 3.0 and later
systems. */
public final class EmacsSdk11Clipboard extends EmacsClipboard
implements ClipboardManager.OnPrimaryClipChangedListener
{
private static final String TAG = "EmacsSdk11Clipboard";
private ClipboardManager manager;
private boolean ownsClipboard;
private int clipboardChangedCount;
private int monitoredClipboardChangedCount;
private ContentResolver resolver;
public
EmacsSdk11Clipboard ()
{
manager = EmacsService.SERVICE.getClipboardManager ();
/* The system forbids Emacs from reading clipboard data in the
background under Android 10 or later. */
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q)
manager.addPrimaryClipChangedListener (this);
/* Now obtain the content resolver used to open file
descriptors. */
resolver = EmacsService.SERVICE.getContentResolver ();
}
@Override
public synchronized void
onPrimaryClipChanged ()
{
Log.d (TAG, ("onPrimaryClipChanged: "
+ monitoredClipboardChangedCount
+ " " + clipboardChangedCount));
/* Increment monitoredClipboardChangeCount. If it is now greater
than clipboardChangedCount, then Emacs no longer owns the
clipboard. */
monitoredClipboardChangedCount++;
if (monitoredClipboardChangedCount > clipboardChangedCount)
{
ownsClipboard = false;
/* Reset both values back to 0. */
monitoredClipboardChangedCount = 0;
clipboardChangedCount = 0;
}
}
/* Set the clipboard text to CLIPBOARD, a string in UTF-8
encoding. */
@Override
public synchronized void
setClipboard (byte[] bytes)
{
ClipData data;
String string;
try
{
string = new String (bytes, "UTF-8");
data = ClipData.newPlainText ("Emacs", string);
manager.setPrimaryClip (data);
ownsClipboard = true;
/* onPrimaryClipChanged will be called again. Use this
variable to keep track of how many times the clipboard has
been changed. */
++clipboardChangedCount;
}
catch (UnsupportedEncodingException exception)
{
Log.w (TAG, "setClipboard: " + exception);
}
}
/* Return whether or not Emacs owns the clipboard. Value is 1 if
Emacs does, 0 if Emacs does not, and -1 if that information is
unavailable. */
@Override
public synchronized int
ownsClipboard ()
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
return -1;
return ownsClipboard ? 1 : 0;
}
/* Return whether or not clipboard content currently exists. */
@Override
public boolean
clipboardExists ()
{
return manager.hasPrimaryClip ();
}
/* Return the current content of the clipboard, as plain text, or
NULL if no content is available. */
@Override
public byte[]
getClipboard ()
{
ClipData clip;
CharSequence text;
Context context;
clip = manager.getPrimaryClip ();
if (clip == null || clip.getItemCount () < 1)
return null;
context = EmacsService.SERVICE;
try
{
text = clip.getItemAt (0).coerceToText (context);
return text.toString ().getBytes ("UTF-8");
}
catch (UnsupportedEncodingException exception)
{
Log.w (TAG, "getClipboard: " + exception);
}
return null;
}
/* Return an array of targets currently provided by the
clipboard, or NULL if there are none. */
@Override
public byte[][]
getClipboardTargets ()
{
ClipData clip;
ClipDescription description;
byte[][] typeArray;
int i;
/* N.B. that Android calls the clipboard the ``primary clip''; it
is not related to the X primary selection. */
clip = manager.getPrimaryClip ();
description = clip.getDescription ();
i = description.getMimeTypeCount ();
typeArray = new byte[i][i];
try
{
for (i = 0; i < description.getMimeTypeCount (); ++i)
typeArray[i] = description.getMimeType (i).getBytes ("UTF-8");
}
catch (UnsupportedEncodingException exception)
{
return null;
}
return typeArray;
}
/* Return the clipboard data for the given target, or NULL if it
does not exist.
Value is normally an array of three longs: the file descriptor,
the start offset of the data, and its length; length may be
AssetFileDescriptor.UNKOWN_LENGTH, meaning that the data extends
from that offset to the end of the file.
Do not use this function to open text targets; use `getClipboard'
for that instead, as it will handle selection data consisting
solely of a URI. */
@Override
public long[]
getClipboardData (byte[] target)
{
ClipData data;
String mimeType;
int fd;
AssetFileDescriptor assetFd;
Uri uri;
long[] value;
/* Decode the target given by Emacs. */
try
{
mimeType = new String (target, "UTF-8");
}
catch (UnsupportedEncodingException exception)
{
return null;
}
Log.d (TAG, "getClipboardData: "+ mimeType);
/* Now obtain the clipboard data and the data corresponding to
that MIME type. */
data = manager.getPrimaryClip ();
if (data.getItemCount () < 1)
return null;
try
{
uri = data.getItemAt (0).getUri ();
if (uri == null)
return null;
Log.d (TAG, "getClipboardData: "+ uri);
/* Now open the file descriptor. */
assetFd = resolver.openTypedAssetFileDescriptor (uri, mimeType,
null);
/* Duplicate the file descriptor. */
fd = assetFd.getParcelFileDescriptor ().getFd ();
fd = EmacsNative.dup (fd);
/* Return the relevant information. */
value = new long[] { fd, assetFd.getStartOffset (),
assetFd.getLength (), };
/* Close the original offset. */
assetFd.close ();
Log.d (TAG, "getClipboardData: "+ value);
}
catch (FileNotFoundException e)
{
return null;
}
catch (IOException e)
{
return null;
}
/* Don't return value if the file descriptor couldn't be
created. */
return fd != -1 ? value : null;
}
};

View file

@ -0,0 +1,114 @@
/* Font backend for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import android.graphics.Paint;
import android.graphics.Rect;
public final class EmacsSdk23FontDriver extends EmacsSdk7FontDriver
{
private void
textExtents1 (Sdk7FontObject font, int code, FontMetrics metrics,
Paint paint, Rect bounds)
{
char[] text;
text = new char[2];
text[0] = (char) code;
text[1] = 'c';
paint.getTextBounds (text, 0, 1, bounds);
metrics.lbearing = (short) bounds.left;
metrics.rbearing = (short) bounds.right;
metrics.ascent = (short) -bounds.top;
metrics.descent = (short) bounds.bottom;
metrics.width
= (short) paint.getRunAdvance (text, 0, 1, 0, 1, false, 1);
}
@Override
public void
textExtents (FontObject font, int code[], FontMetrics fontMetrics)
{
int i;
Paint paintCache;
Rect boundsCache;
Sdk7FontObject fontObject;
char[] text;
float width;
fontObject = (Sdk7FontObject) font;
paintCache = fontObject.typeface.typefacePaint;
paintCache.setTextSize (fontObject.pixelSize);
boundsCache = new Rect ();
if (code.length == 0)
{
fontMetrics.lbearing = 0;
fontMetrics.rbearing = 0;
fontMetrics.ascent = 0;
fontMetrics.descent = 0;
fontMetrics.width = 0;
}
else if (code.length == 1)
textExtents1 ((Sdk7FontObject) font, code[0], fontMetrics,
paintCache, boundsCache);
else
{
text = new char[code.length + 1];
for (i = 0; i < code.length; ++i)
text[i] = (char) code[i];
text[code.length] = 'c';
paintCache.getTextBounds (text, 0, code.length,
boundsCache);
width = paintCache.getRunAdvance (text, 0, code.length, 0,
code.length,
false, code.length);
fontMetrics.lbearing = (short) boundsCache.left;
fontMetrics.rbearing = (short) boundsCache.right;
fontMetrics.ascent = (short) -boundsCache.top;
fontMetrics.descent = (short) boundsCache.bottom;
fontMetrics.width = (short) width;
}
}
@Override
public int
hasChar (FontSpec font, char charCode)
{
Sdk7FontObject fontObject;
Paint paint;
if (font instanceof Sdk7FontObject)
{
fontObject = (Sdk7FontObject) font;
paint = fontObject.typeface.typefacePaint;
}
else
paint = ((Sdk7FontEntity) font).typeface.typefacePaint;
return paint.hasGlyph (String.valueOf (charCode)) ? 1 : 0;
}
};

View file

@ -0,0 +1,538 @@
/* Font backend for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import java.io.File;
import java.util.LinkedList;
import java.util.List;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Typeface;
import android.graphics.Canvas;
import android.util.Log;
public class EmacsSdk7FontDriver extends EmacsFontDriver
{
private static final String TOFU_STRING = "\uDB3F\uDFFD";
private static final String EM_STRING = "m";
private static final String TAG = "EmacsSdk7FontDriver";
protected static final class Sdk7Typeface
{
/* The typeface and paint. */
public Typeface typeface;
public Paint typefacePaint;
public String familyName;
public int slant, width, weight, spacing;
public
Sdk7Typeface (String fileName, Typeface typeface)
{
String style, testString;
int index, measured, i;
float[] widths;
slant = NORMAL;
weight = REGULAR;
width = UNSPECIFIED;
spacing = PROPORTIONAL;
this.typeface = typeface;
typefacePaint = new Paint ();
typefacePaint.setAntiAlias (true);
typefacePaint.setTypeface (typeface);
/* For the calls to measureText below. */
typefacePaint.setTextSize (10.0f);
/* Parse the file name into some useful data. First, strip off
the extension. */
fileName = fileName.split ("\\.", 2)[0];
/* Next, split the file name by dashes. Everything before the
last dash is part of the family name. */
index = fileName.lastIndexOf ("-");
if (index > 0)
{
style = fileName.substring (index + 1, fileName.length ());
familyName = fileName.substring (0, index);
/* Look for something describing the weight. */
if (style.contains ("Thin"))
weight = THIN;
else if (style.contains ("UltraLight"))
weight = ULTRA_LIGHT;
else if (style.contains ("SemiLight"))
weight = SEMI_LIGHT;
else if (style.contains ("Light"))
weight = LIGHT;
else if (style.contains ("Medium"))
weight = MEDIUM;
else if (style.contains ("SemiBold"))
weight = SEMI_BOLD;
else if (style.contains ("ExtraBold"))
weight = EXTRA_BOLD;
else if (style.contains ("Bold"))
weight = BOLD;
else if (style.contains ("Black"))
weight = BLACK;
else if (style.contains ("UltraHeavy"))
weight = ULTRA_HEAVY;
/* And the slant. */
if (style.contains ("ReverseOblique"))
slant = OBLIQUE;
else if (style.contains ("ReverseItalic"))
slant = REVERSE_ITALIC;
else if (style.contains ("Italic"))
slant = ITALIC;
else if (style.contains ("Oblique"))
slant = OBLIQUE;
/* Finally, the width. */
if (style.contains ("UltraCondensed"))
width = ULTRA_CONDENSED;
else if (style.contains ("ExtraCondensed"))
width = EXTRA_CONDENSED;
else if (style.contains ("SemiCondensed"))
width = SEMI_CONDENSED;
else if (style.contains ("Condensed"))
width = CONDENSED;
else if (style.contains ("SemiExpanded"))
width = SEMI_EXPANDED;
else if (style.contains ("ExtraExpanded"))
width = EXTRA_EXPANDED;
else if (style.contains ("UltraExpanded"))
width = ULTRA_EXPANDED;
else if (style.contains ("Expanded"))
width = EXPANDED;
/* Guess the spacing information. */
testString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
widths = new float[testString.length ()];
measured = typefacePaint.getTextWidths (testString,
0, testString.length (),
widths);
spacing = MONO;
for (i = 0; i < measured; ++i)
{
if (i != 0 && widths[i - 1] != widths[i])
/* This isn't a monospace font. */
spacing = PROPORTIONAL;
}
}
else
familyName = fileName;
}
@Override
public String
toString ()
{
return ("Sdk7Typeface ("
+ String.valueOf (familyName) + ", "
+ String.valueOf (slant) + ", "
+ String.valueOf (width) + ", "
+ String.valueOf (weight) + ", "
+ String.valueOf (spacing) + ")");
}
};
protected static final class Sdk7FontEntity extends FontEntity
{
/* The typeface. */
public Sdk7Typeface typeface;
public
Sdk7FontEntity (Sdk7Typeface typeface)
{
float width;
foundry = "Google";
family = typeface.familyName;
adstyle = null;
weight = typeface.weight;
slant = typeface.slant;
spacing = typeface.spacing;
width = typeface.width;
dpi = Math.round (EmacsService.SERVICE.metrics.scaledDensity * 160f);
this.typeface = typeface;
}
};
protected final class Sdk7FontObject extends FontObject
{
/* The typeface. */
public Sdk7Typeface typeface;
public
Sdk7FontObject (Sdk7Typeface typeface, int pixelSize)
{
float totalWidth;
String testWidth, testString;
this.typeface = typeface;
this.pixelSize = pixelSize;
family = typeface.familyName;
adstyle = null;
weight = typeface.weight;
slant = typeface.slant;
spacing = typeface.spacing;
width = typeface.width;
dpi = Math.round (EmacsService.SERVICE.metrics.scaledDensity * 160f);
/* Compute the ascent and descent. */
typeface.typefacePaint.setTextSize (pixelSize);
ascent
= Math.round (-typeface.typefacePaint.ascent ());
descent
= Math.round (typeface.typefacePaint.descent ());
/* Compute the average width. */
testString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
totalWidth = typeface.typefacePaint.measureText (testString);
if (totalWidth > 0)
avgwidth = Math.round (totalWidth
/ testString.length ());
/* Android doesn't expose the font average width and height
information, so this will have to do. */
minWidth = maxWidth = avgwidth;
/* This is different from avgwidth in the font spec! */
averageWidth = avgwidth;
/* Set the space width. */
totalWidth = typeface.typefacePaint.measureText (" ");
spaceWidth = Math.round (totalWidth);
/* Set the height and default ascent. */
height = ascent + descent;
defaultAscent = ascent;
}
};
private String[] fontFamilyList;
private Sdk7Typeface[] typefaceList;
private Sdk7Typeface fallbackTypeface;
public
EmacsSdk7FontDriver ()
{
int i;
File systemFontsDirectory, fontFile;
Typeface typeface;
systemFontsDirectory = new File ("/system/fonts");
fontFamilyList = systemFontsDirectory.list ();
typefaceList = new Sdk7Typeface[fontFamilyList.length + 3];
/* It would be nice to avoid opening each and every font upon
startup. But that doesn't seem to be possible on
Android. */
for (i = 0; i < fontFamilyList.length; ++i)
{
fontFile = new File (systemFontsDirectory,
fontFamilyList[i]);
typeface = Typeface.createFromFile (fontFile);
typefaceList[i] = new Sdk7Typeface (fontFile.getName (),
typeface);
}
/* Initialize the default monospace and serif typefaces. */
fallbackTypeface = new Sdk7Typeface ("monospace",
Typeface.MONOSPACE);
typefaceList[fontFamilyList.length] = fallbackTypeface;
fallbackTypeface = new Sdk7Typeface ("Monospace",
Typeface.MONOSPACE);
typefaceList[fontFamilyList.length + 1] = fallbackTypeface;
fallbackTypeface = new Sdk7Typeface ("Sans Serif",
Typeface.DEFAULT);
typefaceList[fontFamilyList.length + 2] = fallbackTypeface;
}
private boolean
checkMatch (Sdk7Typeface typeface, FontSpec fontSpec)
{
if (fontSpec.family != null
&& !fontSpec.family.equals (typeface.familyName))
return false;
if (fontSpec.slant != null
&& !fontSpec.weight.equals (typeface.weight))
return false;
if (fontSpec.spacing != null
&& !fontSpec.spacing.equals (typeface.spacing))
return false;
if (fontSpec.weight != null
&& !fontSpec.weight.equals (typeface.weight))
return false;
if (fontSpec.width != null
&& !fontSpec.width.equals (typeface.width))
return false;
return true;
}
@Override
public FontEntity[]
list (FontSpec fontSpec)
{
LinkedList<FontEntity> list;
int i;
list = new LinkedList<FontEntity> ();
for (i = 0; i < typefaceList.length; ++i)
{
if (checkMatch (typefaceList[i], fontSpec))
list.add (new Sdk7FontEntity (typefaceList[i]));
}
return list.toArray (new FontEntity[0]);
}
@Override
public FontEntity
match (FontSpec fontSpec)
{
FontEntity[] entities;
int i;
entities = this.list (fontSpec);
if (entities.length == 0)
return new Sdk7FontEntity (fallbackTypeface);
return entities[0];
}
@Override
public String[]
listFamilies ()
{
return fontFamilyList;
}
@Override
public FontObject
openFont (FontEntity fontEntity, int pixelSize)
{
return new Sdk7FontObject (((Sdk7FontEntity) fontEntity).typeface,
pixelSize);
}
@Override
public int
hasChar (FontSpec font, char charCode)
{
float missingGlyphWidth, emGlyphWidth, width;
Rect rect1, rect2;
Paint paint;
Sdk7FontObject fontObject;
if (font instanceof Sdk7FontObject)
{
fontObject = (Sdk7FontObject) font;
paint = fontObject.typeface.typefacePaint;
}
else
paint = ((Sdk7FontEntity) font).typeface.typefacePaint;
paint.setTextSize (10);
if (Character.isWhitespace (charCode))
return 1;
missingGlyphWidth = paint.measureText (TOFU_STRING);
emGlyphWidth = paint.measureText (EM_STRING);
width = paint.measureText ("" + charCode);
if (width == 0f)
return 0;
if (width != missingGlyphWidth)
return 1;
rect1 = new Rect ();
rect2 = new Rect ();
paint.getTextBounds (TOFU_STRING, 0, TOFU_STRING.length (),
rect1);
paint.getTextBounds ("" + charCode, 0, 1, rect2);
return rect1.equals (rect2) ? 0 : 1;
}
private void
textExtents1 (Sdk7FontObject font, int code, FontMetrics metrics,
Paint paint, Rect bounds)
{
char[] text;
text = new char[1];
text[0] = (char) code;
paint.getTextBounds (text, 0, 1, bounds);
/* bounds is the bounding box of the glyph corresponding to CODE.
Translate these into XCharStruct values.
The origin is at 0, 0, and lbearing is the distance counting
rightwards from the origin to the left most pixel in the glyph
raster. rbearing is the distance between the origin and the
rightmost pixel in the glyph raster. ascent is the distance
counting upwards between the the topmost pixel in the glyph
raster. descent is the distance (once again counting
downwards) between the origin and the bottommost pixel in the
glyph raster.
width is the distance between the origin and the origin of any
character to the right. */
metrics.lbearing = (short) bounds.left;
metrics.rbearing = (short) bounds.right;
metrics.ascent = (short) -bounds.top;
metrics.descent = (short) bounds.bottom;
metrics.width = (short) paint.measureText ("" + text[0]);
}
@Override
public void
textExtents (FontObject font, int code[], FontMetrics fontMetrics)
{
int i;
Paint paintCache;
Rect boundsCache;
Sdk7FontObject fontObject;
char[] text;
float width;
fontObject = (Sdk7FontObject) font;
paintCache = fontObject.typeface.typefacePaint;
paintCache.setTextSize (fontObject.pixelSize);
boundsCache = new Rect ();
if (code.length == 0)
{
fontMetrics.lbearing = 0;
fontMetrics.rbearing = 0;
fontMetrics.ascent = 0;
fontMetrics.descent = 0;
fontMetrics.width = 0;
}
else if (code.length == 1)
textExtents1 ((Sdk7FontObject) font, code[0], fontMetrics,
paintCache, boundsCache);
else
{
text = new char[code.length];
for (i = 0; i < code.length; ++i)
text[i] = (char) code[i];
paintCache.getTextBounds (text, 0, code.length,
boundsCache);
width = paintCache.measureText (text, 0, code.length);
fontMetrics.lbearing = (short) boundsCache.left;
fontMetrics.rbearing = (short) boundsCache.right;
fontMetrics.ascent = (short) -boundsCache.top;
fontMetrics.descent = (short) boundsCache.bottom;
fontMetrics.width = (short) Math.round (width);
}
}
@Override
public int
encodeChar (FontObject fontObject, char charCode)
{
return charCode;
}
@Override
public int
draw (FontObject fontObject, EmacsGC gc, EmacsDrawable drawable,
int[] chars, int x, int y, int backgroundWidth,
boolean withBackground)
{
Rect backgroundRect, bounds;
Sdk7FontObject sdk7FontObject;
char[] charsArray;
int i;
Canvas canvas;
Paint paint;
sdk7FontObject = (Sdk7FontObject) fontObject;
charsArray = new char[chars.length];
for (i = 0; i < chars.length; ++i)
charsArray[i] = (char) chars[i];
backgroundRect = new Rect ();
backgroundRect.top = y - sdk7FontObject.ascent;
backgroundRect.left = x;
backgroundRect.right = x + backgroundWidth;
backgroundRect.bottom = y + sdk7FontObject.descent;
canvas = drawable.lockCanvas (gc);
if (canvas == null)
return 0;
paint = gc.gcPaint;
paint.setStyle (Paint.Style.FILL);
if (withBackground)
{
paint.setColor (gc.background | 0xff000000);
canvas.drawRect (backgroundRect, paint);
paint.setColor (gc.foreground | 0xff000000);
}
paint.setTextSize (sdk7FontObject.pixelSize);
paint.setTypeface (sdk7FontObject.typeface.typeface);
paint.setAntiAlias (true);
canvas.drawText (charsArray, 0, chars.length, x, y, paint);
bounds = new Rect ();
paint.getTextBounds (charsArray, 0, chars.length, bounds);
bounds.offset (x, y);
bounds.union (backgroundRect);
drawable.damageRect (bounds);
paint.setAntiAlias (false);
return 1;
}
};

View file

@ -0,0 +1,147 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
/* Importing the entire package instead of just the legacy
ClipboardManager class avoids the deprecation warning. */
import android.text.*;
import android.content.Context;
import android.util.Log;
import java.io.UnsupportedEncodingException;
/* This class implements EmacsClipboard for Android 2.2 and other
similarly old systems. */
@SuppressWarnings ("deprecation")
public final class EmacsSdk8Clipboard extends EmacsClipboard
{
private static final String TAG = "EmacsSdk8Clipboard";
private ClipboardManager manager;
public
EmacsSdk8Clipboard ()
{
String what;
Context context;
what = Context.CLIPBOARD_SERVICE;
context = EmacsService.SERVICE;
manager
= (ClipboardManager) context.getSystemService (what);
}
/* Set the clipboard text to CLIPBOARD, a string in UTF-8
encoding. */
@Override
public void
setClipboard (byte[] bytes)
{
try
{
manager.setText (new String (bytes, "UTF-8"));
}
catch (UnsupportedEncodingException exception)
{
Log.w (TAG, "setClipboard: " + exception);
}
}
/* Return whether or not Emacs owns the clipboard. Value is 1 if
Emacs does, 0 if Emacs does not, and -1 if that information is
unavailable. */
@Override
public int
ownsClipboard ()
{
return -1;
}
/* Return whether or not clipboard content currently exists. */
@Override
public boolean
clipboardExists ()
{
return manager.hasText ();
}
/* Return the current content of the clipboard, as plain text, or
NULL if no content is available. */
@Override
public byte[]
getClipboard ()
{
String string;
CharSequence text;
text = manager.getText ();
if (text == null)
return null;
string = text.toString ();
try
{
return string.getBytes ("UTF-8");
}
catch (UnsupportedEncodingException exception)
{
Log.w (TAG, "getClipboard: " + exception);
}
return null;
}
/* Return an array of targets currently provided by the
clipboard, or NULL if there are none. */
@Override
public byte[][]
getClipboardTargets ()
{
return null;
}
/* Return the clipboard data for the given target, or NULL if it
does not exist.
Value is normally an array of three longs: the file descriptor,
the start offset of the data, and its length; length may be
AssetFileDescriptor.UNKOWN_LENGTH, meaning that the data extends
from that offset to the end of the file.
Do not use this function to open text targets; use `getClipboard'
for that instead, as it will handle selection data consisting
solely of a URI. */
@Override
public long[]
getClipboardData (byte[] target)
{
return null;
}
};

View file

@ -0,0 +1,914 @@
/* Communication module for Android terminals. -*- c-file-style: "GNU" -*-
Copyright (C) 2023 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/>. */
package org.gnu.emacs;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.util.List;
import android.graphics.Matrix;
import android.graphics.Point;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.inputmethod.CursorAnchorInfo;
import android.view.inputmethod.ExtractedText;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.NotificationChannel;
import android.app.Service;
import android.content.ClipboardManager;
import android.content.Context;
import android.content.ContentResolver;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager.ApplicationInfoFlags;
import android.content.pm.PackageManager;
import android.content.res.AssetManager;
import android.hardware.input.InputManager;
import android.net.Uri;
import android.os.BatteryManager;
import android.os.Build;
import android.os.Looper;
import android.os.IBinder;
import android.os.Handler;
import android.os.ParcelFileDescriptor;
import android.os.Vibrator;
import android.os.VibratorManager;
import android.os.VibrationEffect;
import android.util.Log;
import android.util.DisplayMetrics;
import android.widget.Toast;
class Holder<T>
{
T thing;
};
/* EmacsService is the service that starts the thread running Emacs
and handles requests by that Emacs instance. */
public final class EmacsService extends Service
{
public static final String TAG = "EmacsService";
public static volatile EmacsService SERVICE;
public static boolean needDashQ;
private EmacsThread thread;
private Handler handler;
private ContentResolver resolver;
/* Keep this in synch with androidgui.h. */
public static final int IC_MODE_NULL = 0;
public static final int IC_MODE_ACTION = 1;
public static final int IC_MODE_TEXT = 2;
/* Display metrics used by font backends. */
public DisplayMetrics metrics;
/* Flag that says whether or not to print verbose debugging
information. */
public static final boolean DEBUG_IC = false;
/* Return the directory leading to the directory in which native
library files are stored on behalf of CONTEXT. */
public static String
getLibraryDirectory (Context context)
{
int apiLevel;
apiLevel = Build.VERSION.SDK_INT;
if (apiLevel >= Build.VERSION_CODES.GINGERBREAD)
return context.getApplicationInfo ().nativeLibraryDir;
return context.getApplicationInfo ().dataDir + "/lib";
}
@Override
public int
onStartCommand (Intent intent, int flags, int startId)
{
Notification notification;
NotificationManager manager;
NotificationChannel channel;
String infoBlurb;
Object tem;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
tem = getSystemService (Context.NOTIFICATION_SERVICE);
manager = (NotificationManager) tem;
infoBlurb = ("This notification is displayed to keep Emacs"
+ " running while it is in the background. You"
+ " may disable if you want;"
+ " see (emacs)Android Environment.");
channel
= new NotificationChannel ("emacs", "Emacs persistent notification",
NotificationManager.IMPORTANCE_DEFAULT);
manager.createNotificationChannel (channel);
notification = (new Notification.Builder (this, "emacs")
.setContentTitle ("Emacs")
.setContentText (infoBlurb)
.setSmallIcon (android.R.drawable.sym_def_app_icon)
.build ());
manager.notify (1, notification);
startForeground (1, notification);
}
return START_NOT_STICKY;
}
@Override
public IBinder
onBind (Intent intent)
{
return null;
}
@SuppressWarnings ("deprecation")
private String
getApkFile ()
{
PackageManager manager;
ApplicationInfo info;
manager = getPackageManager ();
try
{
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU)
info = manager.getApplicationInfo ("org.gnu.emacs", 0);
else
info = manager.getApplicationInfo ("org.gnu.emacs",
ApplicationInfoFlags.of (0));
/* Return an empty string upon failure. */
if (info.sourceDir != null)
return info.sourceDir;
return "";
}
catch (Exception e)
{
return "";
}
}
@Override
public void
onCreate ()
{
final AssetManager manager;
Context app_context;
final String filesDir, libDir, cacheDir, classPath;
final double pixelDensityX;
final double pixelDensityY;
SERVICE = this;
handler = new Handler (Looper.getMainLooper ());
manager = getAssets ();
app_context = getApplicationContext ();
metrics = getResources ().getDisplayMetrics ();
pixelDensityX = metrics.xdpi;
pixelDensityY = metrics.ydpi;
resolver = getContentResolver ();
try
{
/* Configure Emacs with the asset manager and other necessary
parameters. */
filesDir = app_context.getFilesDir ().getCanonicalPath ();
libDir = getLibraryDirectory (this);
cacheDir = app_context.getCacheDir ().getCanonicalPath ();
/* Now provide this application's apk file, so a recursive
invocation of app_process (through android-emacs) can
find EmacsNoninteractive. */
classPath = getApkFile ();
Log.d (TAG, "Initializing Emacs, where filesDir = " + filesDir
+ ", libDir = " + libDir + ", and classPath = " + classPath
+ "; fileToOpen = " + EmacsOpenActivity.fileToOpen);
/* Start the thread that runs Emacs. */
thread = new EmacsThread (this, new Runnable () {
@Override
public void
run ()
{
EmacsNative.setEmacsParams (manager, filesDir, libDir,
cacheDir, (float) pixelDensityX,
(float) pixelDensityY,
classPath, EmacsService.this);
}
}, needDashQ,
/* If any file needs to be opened, open it now. */
EmacsOpenActivity.fileToOpen);
thread.start ();
}
catch (IOException exception)
{
EmacsNative.emacsAbort ();
return;
}
}
/* Functions from here on must only be called from the Emacs
thread. */
public void
runOnUiThread (Runnable runnable)
{
handler.post (runnable);
}
public EmacsView
getEmacsView (final EmacsWindow window, final int visibility,
final boolean isFocusedByDefault)
{
Runnable runnable;
final Holder<EmacsView> view;
view = new Holder<EmacsView> ();
runnable = new Runnable () {
public void
run ()
{
synchronized (this)
{
view.thing = new EmacsView (window);
view.thing.setVisibility (visibility);
/* The following function is only present on Android 26
or later. */
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
view.thing.setFocusedByDefault (isFocusedByDefault);
notify ();
}
}
};
syncRunnable (runnable);
return view.thing;
}
public void
getLocationOnScreen (final EmacsView view, final int[] coordinates)
{
Runnable runnable;
runnable = new Runnable () {
public void
run ()
{
synchronized (this)
{
view.getLocationOnScreen (coordinates);
notify ();
}
}
};
syncRunnable (runnable);
}
public void
fillRectangle (EmacsDrawable drawable, EmacsGC gc,
int x, int y, int width, int height)
{
EmacsFillRectangle.perform (drawable, gc, x, y,
width, height);
}
public void
fillPolygon (EmacsDrawable drawable, EmacsGC gc,
Point points[])
{
EmacsFillPolygon.perform (drawable, gc, points);
}
public void
drawRectangle (EmacsDrawable drawable, EmacsGC gc,
int x, int y, int width, int height)
{
EmacsDrawRectangle.perform (drawable, gc, x, y,
width, height);
}
public void
drawLine (EmacsDrawable drawable, EmacsGC gc,
int x, int y, int x2, int y2)
{
EmacsDrawLine.perform (drawable, gc, x, y,
x2, y2);
}
public void
drawPoint (EmacsDrawable drawable, EmacsGC gc,
int x, int y)
{
EmacsDrawPoint.perform (drawable, gc, x, y);
}
public void
copyArea (EmacsDrawable srcDrawable, EmacsDrawable dstDrawable,
EmacsGC gc,
int srcX, int srcY, int width, int height, int destX,
int destY)
{
EmacsCopyArea.perform (srcDrawable, gc, dstDrawable,
srcX, srcY, width, height, destX,
destY);
}
public void
clearWindow (EmacsWindow window)
{
window.clearWindow ();
}
public void
clearArea (EmacsWindow window, int x, int y, int width,
int height)
{
window.clearArea (x, y, width, height);
}
@SuppressWarnings ("deprecation")
public void
ringBell ()
{
Vibrator vibrator;
VibrationEffect effect;
VibratorManager vibratorManager;
Object tem;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
{
tem = getSystemService (Context.VIBRATOR_MANAGER_SERVICE);
vibratorManager = (VibratorManager) tem;
vibrator = vibratorManager.getDefaultVibrator ();
}
else
vibrator
= (Vibrator) getSystemService (Context.VIBRATOR_SERVICE);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
{
effect
= VibrationEffect.createOneShot (50,
VibrationEffect.DEFAULT_AMPLITUDE);
vibrator.vibrate (effect);
}
else
vibrator.vibrate (50);
}
public short[]
queryTree (EmacsWindow window)
{
short[] array;
List<EmacsWindow> windowList;
int i;
if (window == null)
/* Just return all the windows without a parent. */
windowList = EmacsWindowAttachmentManager.MANAGER.copyWindows ();
else
windowList = window.children;
array = new short[windowList.size () + 1];
i = 1;
array[0] = (window == null
? 0 : (window.parent != null
? window.parent.handle : 0));
for (EmacsWindow treeWindow : windowList)
array[i++] = treeWindow.handle;
return array;
}
public int
getScreenWidth (boolean mmWise)
{
DisplayMetrics metrics;
metrics = getResources ().getDisplayMetrics ();
if (!mmWise)
return metrics.widthPixels;
else
return (int) ((metrics.widthPixels / metrics.xdpi) * 2540.0);
}
public int
getScreenHeight (boolean mmWise)
{
DisplayMetrics metrics;
metrics = getResources ().getDisplayMetrics ();
if (!mmWise)
return metrics.heightPixels;
else
return (int) ((metrics.heightPixels / metrics.ydpi) * 2540.0);
}
public boolean
detectMouse ()
{
InputManager manager;
InputDevice device;
int[] ids;
int i;
if (Build.VERSION.SDK_INT
< Build.VERSION_CODES.JELLY_BEAN)
return false;
manager = (InputManager) getSystemService (Context.INPUT_SERVICE);
ids = manager.getInputDeviceIds ();
for (i = 0; i < ids.length; ++i)
{
device = manager.getInputDevice (ids[i]);
if (device == null)
continue;
if (device.supportsSource (InputDevice.SOURCE_MOUSE))
return true;
}
return false;
}
public String
nameKeysym (int keysym)
{
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1)
return KeyEvent.keyCodeToString (keysym);
return String.valueOf (keysym);
}
/* Start the Emacs service if necessary. On Android 26 and up,
start Emacs as a foreground service with a notification, to avoid
it being killed by the system.
On older systems, simply start it as a normal background
service. */
public static void
startEmacsService (Context context)
{
if (EmacsService.SERVICE == null)
{
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.O)
/* Start the Emacs service now. */
context.startService (new Intent (context,
EmacsService.class));
else
/* Display the permanant notification and start Emacs as a
foreground service. */
context.startForegroundService (new Intent (context,
EmacsService.class));
}
}
/* Ask the system to open the specified URL.
Value is NULL upon success, or a string describing the error
upon failure. */
public String
browseUrl (String url)
{
Intent intent;
try
{
intent = new Intent (Intent.ACTION_VIEW, Uri.parse (url));
intent.setFlags (Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity (intent);
}
catch (Exception e)
{
return e.toString ();
}
return null;
}
/* Get a SDK 11 ClipboardManager.
Android 4.0.x requires that this be called from the main
thread. */
public ClipboardManager
getClipboardManager ()
{
final Holder<ClipboardManager> manager;
Runnable runnable;
manager = new Holder<ClipboardManager> ();
runnable = new Runnable () {
public void
run ()
{
Object tem;
synchronized (this)
{
tem = getSystemService (Context.CLIPBOARD_SERVICE);
manager.thing = (ClipboardManager) tem;
notify ();
}
}
};
syncRunnable (runnable);
return manager.thing;
}
public void
restartEmacs ()
{
Intent intent;
intent = new Intent (this, EmacsActivity.class);
intent.addFlags (Intent.FLAG_ACTIVITY_NEW_TASK
| Intent.FLAG_ACTIVITY_CLEAR_TASK);
startActivity (intent);
System.exit (0);
}
/* Wait synchronously for the specified RUNNABLE to complete in the
UI thread. Must be called from the Emacs thread. */
public static void
syncRunnable (Runnable runnable)
{
EmacsNative.beginSynchronous ();
synchronized (runnable)
{
SERVICE.runOnUiThread (runnable);
while (true)
{
try
{
runnable.wait ();
break;
}
catch (InterruptedException e)
{
continue;
}
}
}
EmacsNative.endSynchronous ();
}
public void
updateIC (EmacsWindow window, int newSelectionStart,
int newSelectionEnd, int composingRegionStart,
int composingRegionEnd)
{
if (DEBUG_IC)
Log.d (TAG, ("updateIC: " + window + " " + newSelectionStart
+ " " + newSelectionEnd + " "
+ composingRegionStart + " "
+ composingRegionEnd));
window.view.imManager.updateSelection (window.view,
newSelectionStart,
newSelectionEnd,
composingRegionStart,
composingRegionEnd);
}
public void
resetIC (EmacsWindow window, int icMode)
{
if (DEBUG_IC)
Log.d (TAG, "resetIC: " + window);
window.view.setICMode (icMode);
window.view.imManager.restartInput (window.view);
}
public void
updateCursorAnchorInfo (EmacsWindow window, float x,
float y, float yBaseline,
float yBottom)
{
CursorAnchorInfo info;
CursorAnchorInfo.Builder builder;
Matrix matrix;
int[] offsets;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
return;
offsets = new int[2];
builder = new CursorAnchorInfo.Builder ();
matrix = new Matrix (window.view.getMatrix ());
window.view.getLocationOnScreen (offsets);
matrix.postTranslate (offsets[0], offsets[1]);
builder.setMatrix (matrix);
builder.setInsertionMarkerLocation (x, y, yBaseline, yBottom,
0);
info = builder.build ();
if (DEBUG_IC)
Log.d (TAG, ("updateCursorAnchorInfo: " + x + " " + y
+ " " + yBaseline + "-" + yBottom));
window.view.imManager.updateCursorAnchorInfo (window.view, info);
}
/* Open a content URI described by the bytes BYTES, a non-terminated
string; make it writable if WRITABLE, and readable if READABLE.
Truncate the file if TRUNCATE.
Value is the resulting file descriptor or -1 upon failure. */
public int
openContentUri (byte[] bytes, boolean writable, boolean readable,
boolean truncate)
{
String name, mode;
ParcelFileDescriptor fd;
int i;
/* Figure out the file access mode. */
mode = "";
if (readable)
mode += "r";
if (writable)
mode += "w";
if (truncate)
mode += "t";
/* Try to open an associated ParcelFileDescriptor. */
try
{
/* The usual file name encoding question rears its ugly head
again. */
name = new String (bytes, "UTF-8");
Log.d (TAG, "openContentUri: " + Uri.parse (name));
fd = resolver.openFileDescriptor (Uri.parse (name), mode);
/* Use detachFd on newer versions of Android or plain old
dup. */
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB_MR1)
{
i = fd.detachFd ();
fd.close ();
return i;
}
else
{
i = EmacsNative.dup (fd.getFd ());
fd.close ();
return i;
}
}
catch (Exception exception)
{
return -1;
}
}
public boolean
checkContentUri (byte[] string, boolean readable, boolean writable)
{
String mode, name;
ParcelFileDescriptor fd;
/* Decode this into a URI. */
try
{
/* The usual file name encoding question rears its ugly head
again. */
name = new String (string, "UTF-8");
Log.d (TAG, "checkContentUri: " + Uri.parse (name));
}
catch (UnsupportedEncodingException exception)
{
name = null;
throw new RuntimeException (exception);
}
mode = "r";
if (writable)
mode += "w";
Log.d (TAG, "checkContentUri: checking against mode " + mode);
try
{
fd = resolver.openFileDescriptor (Uri.parse (name), mode);
fd.close ();
Log.d (TAG, "checkContentUri: YES");
return true;
}
catch (Exception exception)
{
Log.d (TAG, "checkContentUri: NO");
Log.d (TAG, exception.toString ());
return false;
}
}
private long[]
queryBattery19 ()
{
IntentFilter filter;
Intent battery;
long capacity, chargeCounter, currentAvg, currentNow;
long status, remaining, plugged, temp;
filter = new IntentFilter (Intent.ACTION_BATTERY_CHANGED);
battery = registerReceiver (null, filter);
if (battery == null)
return null;
capacity = battery.getIntExtra (BatteryManager.EXTRA_LEVEL, 0);
chargeCounter
= (battery.getIntExtra (BatteryManager.EXTRA_SCALE, 0)
/ battery.getIntExtra (BatteryManager.EXTRA_LEVEL, 100) * 100);
currentAvg = 0;
currentNow = 0;
status = battery.getIntExtra (BatteryManager.EXTRA_STATUS, 0);
remaining = -1;
plugged = battery.getIntExtra (BatteryManager.EXTRA_PLUGGED, 0);
temp = battery.getIntExtra (BatteryManager.EXTRA_TEMPERATURE, 0);
return new long[] { capacity, chargeCounter, currentAvg,
currentNow, remaining, status, plugged,
temp, };
}
/* Return the status of the battery. See struct
android_battery_status for the order of the elements
returned.
Value may be null upon failure. */
public long[]
queryBattery ()
{
Object tem;
BatteryManager manager;
long capacity, chargeCounter, currentAvg, currentNow;
long status, remaining, plugged, temp;
int prop;
IntentFilter filter;
Intent battery;
/* Android 4.4 or earlier require applications to use a different
API to query the battery status. */
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP)
return queryBattery19 ();
tem = getSystemService (Context.BATTERY_SERVICE);
manager = (BatteryManager) tem;
remaining = -1;
prop = BatteryManager.BATTERY_PROPERTY_CAPACITY;
capacity = manager.getLongProperty (prop);
prop = BatteryManager.BATTERY_PROPERTY_CHARGE_COUNTER;
chargeCounter = manager.getLongProperty (prop);
prop = BatteryManager.BATTERY_PROPERTY_CURRENT_AVERAGE;
currentAvg = manager.getLongProperty (prop);
prop = BatteryManager.BATTERY_PROPERTY_CURRENT_NOW;
currentNow = manager.getLongProperty (prop);
/* Return the battery status. N.B. that Android 7.1 and earlier
only return ``charging'' or ``discharging''. */
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
status
= manager.getIntProperty (BatteryManager.BATTERY_PROPERTY_STATUS);
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
status = (manager.isCharging ()
? BatteryManager.BATTERY_STATUS_CHARGING
: BatteryManager.BATTERY_STATUS_DISCHARGING);
else
status = (currentNow > 0
? BatteryManager.BATTERY_STATUS_CHARGING
: BatteryManager.BATTERY_STATUS_DISCHARGING);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P)
remaining = manager.computeChargeTimeRemaining ();
plugged = -1;
temp = -1;
/* Now obtain additional information from the battery manager. */
filter = new IntentFilter (Intent.ACTION_BATTERY_CHANGED);
battery = registerReceiver (null, filter);
if (battery != null)
{
plugged = battery.getIntExtra (BatteryManager.EXTRA_PLUGGED, 0);
temp = battery.getIntExtra (BatteryManager.EXTRA_TEMPERATURE, 0);
/* Make status more reliable. */
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M)
status = battery.getIntExtra (BatteryManager.EXTRA_STATUS, 0);
}
return new long[] { capacity, chargeCounter, currentAvg,
currentNow, remaining, status, plugged,
temp, };
}
/* Display the specified STRING in a small dialog box on the main
thread. */
public void
displayToast (final String string)
{
runOnUiThread (new Runnable () {
@Override
public void
run ()
{
Toast toast;
toast = Toast.makeText (getApplicationContext (),
string, Toast.LENGTH_SHORT);
toast.show ();
}
});
}
public void
updateExtractedText (EmacsWindow window, ExtractedText text,
int token)
{
if (DEBUG_IC)
Log.d (TAG, "updateExtractedText: @" + token + ", " + text);
window.view.imManager.updateExtractedText (window.view,
token, text);
}
};

Some files were not shown because too many files have changed in this diff Show more