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
\f
/* Check that ENCODED does not lie on any special directory whose
- contents are read only. Signal a `file-error' if it does. */
+ contents are read only. Signal a `file-error' if it does.
+
+ If WRITE, then don't check that the file lies on `/content' on
+ Android. This special exception allows writing to content
+ provider-supplied files. */
static void
-check_mutable_filename (Lisp_Object encoded)
+check_mutable_filename (Lisp_Object encoded, bool write)
{
#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
if (!strcmp (SSDATA (encoded), "/assets")
|| !strncmp (SSDATA (encoded), "/assets/",
sizeof "/assets/" - 1))
xsignal2 (Qfile_error,
- build_string ("File lies on read-"
- "only directory"),
+ build_string ("File lies on read-only directory"),
+ encoded);
+
+ if (write)
+ return;
+
+ if (!strcmp (SSDATA (encoded), "/content")
+ || !strncmp (SSDATA (encoded), "/content/",
+ sizeof "/content/" - 1))
+ xsignal2 (Qfile_error,
+ build_string ("File lies on read-only directory"),
encoded);
#endif
}
encoded_file = ENCODE_FILE (file);
encoded_newname = ENCODE_FILE (newname);
- check_mutable_filename (encoded_newname);
+ check_mutable_filename (encoded_newname, true);
#ifdef WINDOWSNT
if (NILP (ok_if_already_exists)
encoded_dir = ENCODE_FILE (directory);
dir = SSDATA (encoded_dir);
- check_mutable_filename (encoded_dir);
+ check_mutable_filename (encoded_dir, false);
if (rmdir (dir) != 0)
report_file_error ("Removing directory", directory);
return call1 (Qmove_file_to_trash, filename);
encoded_file = ENCODE_FILE (filename);
- check_mutable_filename (encoded_file);
+ check_mutable_filename (encoded_file, false);
if (unlink (SSDATA (encoded_file)) != 0 && errno != ENOENT)
report_file_error ("Removing old name", filename);
encoded_file = ENCODE_FILE (file);
encoded_newname = ENCODE_FILE (newname);
- check_mutable_filename (encoded_file);
- check_mutable_filename (encoded_newname);
+ check_mutable_filename (encoded_file, false);
+ check_mutable_filename (encoded_newname, false);
bool plain_rename = (case_only_rename
|| (!NILP (ok_if_already_exists)
encoded_file = ENCODE_FILE (file);
encoded_newname = ENCODE_FILE (newname);
- check_mutable_filename (encoded_file);
- check_mutable_filename (encoded_newname);
+ check_mutable_filename (encoded_file, false);
+ check_mutable_filename (encoded_newname, false);
if (link (SSDATA (encoded_file), SSDATA (encoded_newname)) == 0)
return Qnil;
encoded_target = ENCODE_FILE (target);
encoded_linkname = ENCODE_FILE (linkname);
- check_mutable_filename (encoded_target);
- check_mutable_filename (encoded_linkname);
+ check_mutable_filename (encoded_target, false);
+ check_mutable_filename (encoded_linkname, false);
if (symlink (SSDATA (encoded_target), SSDATA (encoded_linkname)) == 0)
return Qnil;
return call4 (handler, Qset_file_modes, absname, mode, flag);
encoded = ENCODE_FILE (absname);
- check_mutable_filename (encoded);
+ check_mutable_filename (encoded, false);
char *fname = SSDATA (encoded);
mode_t imode = XFIXNUM (mode) & 07777;
if (fchmodat (AT_FDCWD, fname, imode, nofollow) != 0)
return call4 (handler, Qset_file_times, absname, timestamp, flag);
Lisp_Object encoded_absname = ENCODE_FILE (absname);
- check_mutable_filename (encoded_absname);
+ check_mutable_filename (encoded_absname, false);
if (utimensat (AT_FDCWD, SSDATA (encoded_absname), ts, nofollow) != 0)
{
return call3 (handler, Qfile_newer_than_file_p, absname1, absname2);
encoded = ENCODE_FILE (absname1);
- check_mutable_filename (encoded);
int err1;
if (emacs_fstatat (AT_FDCWD, SSDATA (encoded), &st1, 0) == 0)
}
encoded_filename = ENCODE_FILE (filename);
+ check_mutable_filename (encoded_filename, false);
+
fn = SSDATA (encoded_filename);
open_flags = O_WRONLY | O_CREAT;
open_flags |= EQ (mustbenew, Qexcl) ? O_EXCL : !NILP (append) ? 0 : O_TRUNC;
return call2 (handler, Qset_visited_file_modtime, Qnil);
encoded = ENCODE_FILE (filename);
- check_mutable_filename (encoded);
if (emacs_fstatat (AT_FDCWD, SSDATA (encoded), &st, 0)
== 0)
static Lisp_Object
make_lock_file_name (Lisp_Object fn)
{
- Lisp_Object lock_file_name = call1 (Qmake_lock_file_name,
- Fexpand_file_name (fn, Qnil));
+ Lisp_Object lock_file_name;
+#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
+ char *name;
+#endif
+
+ fn = Fexpand_file_name (fn, Qnil);
+
+#if defined HAVE_ANDROID && !defined ANDROID_STUBIFY
+ /* Files in /assets and /contents can't have lock files on Android
+ as these directories are fabrications of android.c, and backed by
+ read only data. */
+
+ name = SSDATA (fn);
+
+ if (strcmp (name, "/assets")
+ || strcmp (name, "/assets/")
+ || strcmp (name, "/content")
+ || strcmp (name, "/content/")
+ || strncmp (name, "/assets/", sizeof "/assets")
+ || strncmp (name, "/content/", sizeof "/content"))
+ return Qnil;
+#endif
+
+ lock_file_name = call1 (Qmake_lock_file_name, fn);
+
return !NILP (lock_file_name) ? ENCODE_FILE (lock_file_name) : Qnil;
}