import android.os.Build;
import android.os.Bundle;
import android.os.ParcelFileDescriptor;
+import android.os.Parcelable;
import android.util.Log;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
+import java.util.List;
+
public final class EmacsOpenActivity extends Activity
implements DialogInterface.OnClickListener,
DialogInterface.OnCancelListener
Finally, display any error message, transfer the focus to an
Emacs frame, and finish the activity. */
+ @SuppressWarnings ("deprecation") /* getParcelableExtra */
@Override
public void
onCreate (Bundle savedInstanceState)
ParcelFileDescriptor fd;
byte[] names;
String errorBlurb, scheme;
+ String subjectString, textString, attachmentString;
+ CharSequence tem;
+ String tem1;
+ StringBuilder builder;
+ List<Parcelable> list;
super.onCreate (savedInstanceState);
if (action.equals ("android.intent.action.VIEW")
|| action.equals ("android.intent.action.EDIT")
|| action.equals ("android.intent.action.PICK")
+ || action.equals ("android.intent.action.SEND")
|| action.equals ("android.intent.action.SENDTO"))
{
/* Obtain the URI of the action. */
/* Escape the special characters $ and " before enclosing
the string within the `message-mailto' wrapper. */
fileName = uri.toString ();
- fileName.replace ("\"", "\\\"").replace ("$", "\\$");
- fileName = "(message-mailto \"" + fileName + "\")";
+ fileName = (fileName
+ .replace ("\\", "\\\\")
+ .replace ("\"", "\\\"")
+ .replace ("$", "\\$"));
+ fileName = "(message-mailto \"" + fileName + "\" ";
+
+ /* Parse the intent itself to ascertain if any
+ non-standard subject, body, or something else of the
+ like is set. Such fields, non-standard as they are,
+ yield to fields provided within the URL itself; refer
+ to message-mailto. */
+
+ textString = attachmentString = subjectString = "()";
+
+ tem = intent.getCharSequenceExtra (Intent.EXTRA_SUBJECT);
+
+ if (tem != null)
+ subjectString = ("\"" + (tem.toString ()
+ .replace ("\\", "\\\\")
+ .replace ("\"", "\\\"")
+ .replace ("$", "\\$"))
+ + "\" ");
+
+ tem = intent.getCharSequenceExtra (Intent.EXTRA_TEXT);
+
+ if (tem != null)
+ textString = ("\"" + (tem.toString ()
+ .replace ("\\", "\\\\")
+ .replace ("\"", "\\\"")
+ .replace ("$", "\\$"))
+ + "\" ");
+
+ /* Producing a list of attachments is prey to two
+ mannerisms of the system: in the first instance, these
+ attachments are content URIs which don't allude to
+ their content types; and in the second instance, they
+ are either a list of such URIs or one individual URI,
+ subject to the type of the intent itself. */
+
+ if (Intent.ACTION_SEND.equals (action))
+ {
+ /* The attachment in this case is a single content
+ URI. */
+
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
+ uri = intent.getParcelableExtra (Intent.EXTRA_STREAM,
+ Uri.class);
+ else
+ uri = intent.getParcelableExtra (Intent.EXTRA_STREAM);
+
+ if (uri != null
+ && (scheme = uri.getScheme ()) != null
+ && scheme.equals ("content"))
+ {
+ tem1 = EmacsService.buildContentName (uri);
+ attachmentString = ("'(\"" + (tem1.replace ("\\", "\\\\")
+ .replace ("\"", "\\\"")
+ .replace ("$", "\\$"))
+ + "\")");
+ }
+ }
+ else
+ {
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU)
+ list
+ = intent.getParcelableArrayListExtra (Intent.EXTRA_STREAM,
+ Parcelable.class);
+ else
+ list
+ = intent.getParcelableArrayListExtra (Intent.EXTRA_STREAM);
+
+ if (list != null)
+ {
+ builder = new StringBuilder ("'(");
+
+ for (Parcelable parcelable : list)
+ {
+ if (!(parcelable instanceof Uri))
+ continue;
+
+ uri = (Uri) parcelable;
+
+ if (uri != null
+ && (scheme = uri.getScheme ()) != null
+ && scheme.equals ("content"))
+ {
+ tem1 = EmacsService.buildContentName (uri);
+ builder.append ("\"");
+ builder.append (tem1.replace ("\\", "\\\\")
+ .replace ("\"", "\\\"")
+ .replace ("$", "\\$"));
+ builder.append ("\"");
+ }
+ }
+
+ builder.append (")");
+ attachmentString = builder.toString ();
+ }
+ }
+
+ fileName += subjectString;
+ fileName += textString;
+ fileName += attachmentString;
+ fileName += ")";
/* Execute emacsclient in order to execute this code. */
currentActivity = this;
retval))
;;;###autoload
-(defun message-mailto (&optional url)
+(defun message-mailto (&optional url subject body file-attachments)
"Command to parse command line mailto: links.
This is meant to be used for MIME handlers: Setting the handler
for \"x-scheme-handler/mailto;\" to \"emacs -f message-mailto %u\"
will then start up Emacs ready to compose mail. For emacsclient use
- emacsclient -e \\='(message-mailto \"%u\")'"
+ emacsclient -e \\='(message-mailto \"%u\")'
+
+To facilitate the use of this function within window systems that
+provide message subject, body and attachments independent of URL
+itself, the arguments SUBJECT, BODY and FILE-ATTACHMENTS may also
+provide alternative message subject and body text, which is
+inserted in lieu of nothing if URL does not incorporate such
+information itself, and a list of files to insert as attachments
+to the E-mail."
(interactive)
;; <a href="mailto:someone@example.com?subject=This%20is%20the%20subject&cc=someone_else@example.com&body=This%20is%20the%20body">Send email</a>
(message-mail)
- (message-mailto-1 (or url (pop command-line-args-left))))
+ (message-mailto-1 (or url (pop command-line-args-left))
+ subject body file-attachments))
-(defun message-mailto-1 (url)
- (let ((args (message-parse-mailto-url url)))
+(defun message-mailto-1 (url &optional subject body file-attachments)
+ (let ((args (message-parse-mailto-url url))
+ (need-body nil) (need-subject nil))
(dolist (arg args)
(unless (equal (car arg) "body")
(message-position-on-field (capitalize (car arg)))
(insert (string-replace
"\r\n" "\n"
(mapconcat #'identity (reverse (cdr arg)) ", ")))))
- (when (assoc "body" args)
- (message-goto-body)
- (dolist (body (cdr (assoc "body" args)))
- (insert body "\n")))
+ (if (assoc "body" args)
+ (progn
+ (message-goto-body)
+ (dolist (body (cdr (assoc "body" args)))
+ (insert body "\n")))
+
+ (setq need-body t))
(if (assoc "subject" args)
(message-goto-body)
- (message-goto-subject))))
+ (setq need-subject t)
+ (message-goto-subject))
+ ;; If either one of need-subject and need-body is non-nil then
+ ;; attempt to insert the absent information from an external
+ ;; SUBJECT or BODY.
+ (when (or need-body need-subject)
+ (when (and need-body body)
+ (message-goto-body)
+ (insert body))
+ (when (and need-subject subject)
+ (message-goto-subject)
+ (insert subject)
+ (message-goto-body)))
+ ;; Subsequently insert each attachment enumerated within
+ ;; FILE-ATTACHMENTS.
+ (dolist (file file-attachments)
+ (mml-attach-file file nil 'attachment))))
(provide 'message)