summaryrefslogtreecommitdiff
path: root/lisp/term/android-win.el
diff options
context:
space:
mode:
Diffstat (limited to 'lisp/term/android-win.el')
-rw-r--r--lisp/term/android-win.el186
1 files changed, 162 insertions, 24 deletions
diff --git a/lisp/term/android-win.el b/lisp/term/android-win.el
index 51163e5b9b2..6512ef81ff7 100644
--- a/lisp/term/android-win.el
+++ b/lisp/term/android-win.el
@@ -282,11 +282,12 @@ If it reflects the motion of an item above a frame, call
`dnd-handle-movement' to move the cursor or scroll the window
under the item pursuant to the pertinent user options.
-If it reflects dropped text, insert such text within window at
-the location of the drop.
+If it holds dropped text, insert such text within window at the
+location of the drop.
-If it reflects a list of URIs, then open each URI, converting
-content:// URIs into the special file names which represent them."
+If it holds a list of URIs, or file names, then open each URI or
+file name, converting content:// URIs into the special file
+names which represent them."
(interactive "e")
(let ((message (caddr event))
(posn (event-start event)))
@@ -304,18 +305,22 @@ content:// URIs into the special file names which represent them."
(new-uri-list nil)
(dnd-unescape-file-uris t))
(dolist (uri uri-list)
- (ignore-errors
- (let ((url (url-generic-parse-url uri)))
- (when (equal (url-type url) "content")
- ;; Replace URI with a matching /content file
- ;; name.
- (setq uri (format "file:/content/by-authority/%s%s"
- (url-host url)
- (url-filename url))
- ;; And guarantee that this file URI is not
- ;; subject to URI decoding, for it must be
- ;; transformed back into a content URI.
- dnd-unescape-file-uris nil))))
+ ;; If the URI is a preprepared file name, insert it directly.
+ (if (string-match-p "^/content/by-authority\\(-named\\)?/" uri)
+ (setq uri (concat "file:" uri)
+ dnd-unescape-file-uris nil)
+ (ignore-errors
+ (let ((url (url-generic-parse-url uri)))
+ (when (equal (url-type url) "content")
+ ;; Replace URI with a matching /content file
+ ;; name.
+ (setq uri (format "file:/content/by-authority/%s%s"
+ (url-host url)
+ (url-filename url))
+ ;; And guarantee that this file URI is not
+ ;; subject to URI decoding, for it must be
+ ;; transformed back into a content URI.
+ dnd-unescape-file-uris nil)))))
(push uri new-uri-list))
(dnd-handle-multiple-urls (posn-window posn)
new-uri-list
@@ -398,7 +403,7 @@ directory /content/storage.
(inhibit-read-only t))
(fill-region (point-min) (point-max))))))))
-(defun android-after-splash-screen (fancy-p)
+(defun android-before-splash-screen (fancy-p)
"Insert a brief notice on the absence of storage permissions.
If storage permissions are as yet denied to Emacs, insert a short
notice to that effect, followed by a button that enables the user
@@ -406,20 +411,20 @@ to grant such permissions.
FANCY-P non-nil means the notice will be displayed with faces, in
the style appropriate for its incorporation within the fancy splash
-screen display; see `francy-splash-insert'."
+screen display; see `fancy-splash-insert'."
(unless (android-external-storage-available-p)
(if fancy-p
(fancy-splash-insert
:face '(variable-pitch
font-lock-function-call-face)
- "\nPermissions necessary to access external storage directories have
-been denied. Click "
+ "Permissions necessary to access external storage directories have"
+ "\nbeen denied. Click "
:link '("here" android-display-storage-permission-popup)
- " to grant them.")
+ " to grant them.\n")
(insert
- "Permissions necessary to access external storage directories have been
-denied. ")
- (insert-button "Click here to grant them."
+ "Permissions necessary to access external storage directories"
+ "\nhave been denied. ")
+ (insert-button "Click here to grant them.\n"
'action #'android-display-storage-permission-popup
'follow-link t)
(newline))))
@@ -480,5 +485,138 @@ the UTF-8 coding system."
(concat locale-base locale-modifier)))
+;; Miscellaneous functions.
+
+(declare-function android-browse-url-internal "androidselect.c")
+
+(defun android-browse-url (url &optional send)
+ "Open URL in an external application.
+
+URL should be a URL-encoded URL with a scheme specified unless
+SEND is non-nil. Signal an error upon failure.
+
+If SEND is nil, start a program that is able to display the URL,
+such as a web browser. Otherwise, try to share URL using
+programs such as email clients.
+
+If URL is a file URI, convert it into a `content' address
+accessible to other programs."
+ (when-let* ((uri (url-generic-parse-url url))
+ (filename (url-filename uri))
+ ;; If `uri' is a file URI and the file resides in /content
+ ;; or /assets, copy it to a temporary file before
+ ;; providing it to other programs.
+ (replacement-url (and (string-match-p
+ "/\\(content\\|assets\\)[/$]"
+ filename)
+ (prog1 t
+ (copy-file
+ filename
+ (setq filename
+ (make-temp-file
+ "local"
+ nil
+ (let ((extension
+ (file-name-extension
+ filename)))
+ (if extension
+ (concat "."
+ extension)
+ nil))))
+ t))
+ (concat "file://" filename))))
+ (setq url replacement-url))
+ (android-browse-url-internal url send))
+
+
+;; Coding systems used by androidvfs.c.
+
+(define-ccl-program android-encode-jni
+ `(2 ((loop
+ (read r0)
+ (if (r0 < #x1) ; 0x0 is encoded specially in JNI environments.
+ ((write #xc0)
+ (write #x80))
+ ((if (r0 < #x80) ; ASCII
+ ((write r0))
+ (if (r0 < #x800) ; \u0080 - \u07ff
+ ((write ((r0 >> 6) | #xC0))
+ (write ((r0 & #x3F) | #x80)))
+ ;; \u0800 - \uFFFF
+ (if (r0 < #x10000)
+ ((write ((r0 >> 12) | #xE0))
+ (write (((r0 >> 6) & #x3F) | #x80))
+ (write ((r0 & #x3F) | #x80)))
+ ;; Supplementary characters must be converted into
+ ;; surrogate pairs before encoding.
+ (;; High surrogate
+ (r1 = ((((r0 - #x10000) >> 10) & #x3ff) + #xD800))
+ ;; Low surrogate.
+ (r2 = (((r0 - #x10000) & #x3ff) + #xDC00))
+ ;; Write both surrogate characters.
+ (write ((r1 >> 12) | #xE0))
+ (write (((r1 >> 6) & #x3F) | #x80))
+ (write ((r1 & #x3F) | #x80))
+ (write ((r2 >> 12) | #xE0))
+ (write (((r2 >> 6) & #x3F) | #x80))
+ (write ((r2 & #x3F) | #x80))))))))
+ (repeat))))
+ "Encode characters from the input buffer for Java virtual machines.")
+
+(define-ccl-program android-decode-jni
+ `(1 ((loop
+ ((read-if (r0 >= #x80) ; More than a one-byte sequence?
+ ((if (r0 < #xe0)
+ ;; Two-byte sequence; potentially a NULL
+ ;; character.
+ ((read r4)
+ (r4 &= #x3f)
+ (r0 = (((r0 & #x1f) << 6) | r4)))
+ (if (r0 < ?\xF0)
+ ;; Three-byte sequence, after which surrogate
+ ;; pairs should be processed.
+ ((read r4 r6)
+ (r4 = ((r4 & #x3f) << 6))
+ (r6 &= #x3f)
+ (r0 = ((((r0 & #xf) << 12) | r4) | r6)))
+ ;; Four-byte sequences are not valid under the
+ ;; JVM specification, but Android produces them
+ ;; when encoding Emoji characters for being
+ ;; supposedly less of a surprise to applications.
+ ;; This is obviously not true of programs written
+ ;; to the letter of the documentation, but 50
+ ;; million Frenchmen make a right (and this
+ ;; deviation from the norm is predictably absent
+ ;; from Android's documentation on the subject).
+ ((read r1 r4 r6)
+ (r1 = ((r1 & #x3f) << 12))
+ (r4 = ((r4 & #x3f) << 6))
+ (r6 &= #x3F)
+ (r0 = (((((r0 & #x07) << 18) | r1) | r4) | r6))))))))
+ (if ((r0 & #xf800) == #xd800)
+ ;; High surrogate.
+ ((read-if (r2 >= #xe0)
+ ((r0 = ((r0 & #x3ff) << 10))
+ (read r4 r6)
+ (r4 = ((r4 & #x3f) << 6))
+ (r6 &= #x3f)
+ (r1 = ((((r2 & #xf) << 12) | r4) | r6))
+ (r0 = (((r1 & #x3ff) | r0) + #xffff))))))
+ (write r0)
+ (repeat))))
+ "Decode JVM-encoded characters in the input buffer.")
+
+(define-coding-system 'android-jni
+ "CESU-8 based encoding for communication with the Android runtime."
+ :mnemonic ?J
+ :coding-type 'ccl
+ :eol-type 'unix
+ :ascii-compatible-p nil ; for \0 is encoded as a two-byte sequence.
+ :default-char ?\0
+ :charset-list '(unicode)
+ :ccl-decoder 'android-decode-jni
+ :ccl-encoder 'android-encode-jni)
+
+
(provide 'android-win)
;; android-win.el ends here.