X-Git-Url: https://code.delx.au/gnu-emacs/blobdiff_plain/be65c2f46a9170da6b9a508df1f31234db21fce0..3c53a3cf83c218772d9bcfde4cd60c1face33e93:/src/doprnt.c diff --git a/src/doprnt.c b/src/doprnt.c index aa0b2c2005..3fd6222c9d 100644 --- a/src/doprnt.c +++ b/src/doprnt.c @@ -24,17 +24,29 @@ Boston, MA 02111-1307, USA. */ #include #include #include -#include "lisp.h" -#if STDC_HEADERS +#ifdef STDC_HEADERS #include #endif +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_STDLIB_H +#include +#endif + +#include "lisp.h" + #ifndef DBL_MAX_10_EXP #define DBL_MAX_10_EXP 308 /* IEEE double */ #endif -extern long *xmalloc (), *xrealloc (); +/* Since we use the macro CHAR_HEAD_P, we have to include this, but + don't have to include others because CHAR_HEAD_P does not contains + another macro. */ +#include "charset.h" static int doprnt1 (); @@ -48,6 +60,7 @@ static int doprnt1 (); String arguments are passed as C strings. Integers are passed as C integers. */ +int doprnt (buffer, bufsize, format, format_end, nargs, args) char *buffer; register int bufsize; @@ -62,6 +75,7 @@ doprnt (buffer, bufsize, format, format_end, nargs, args) /* Like doprnt except that strings in ARGS are passed as Lisp_Object. */ +int doprnt_lisp (buffer, bufsize, format, format_end, nargs, args) char *buffer; register int bufsize; @@ -100,12 +114,11 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args) char *big_buffer = 0; register int tem; - char *string; + unsigned char *string; char fixed_buffer[20]; /* Default buffer for small formatting. */ char *fmtcpy; int minlen; - int size; /* Field width factor; e.g., %90d */ - char charbuf[2]; /* Used for %c. */ + unsigned char charbuf[5]; /* Used for %c. */ if (format_end == 0) format_end = format + strlen (format); @@ -123,10 +136,11 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args) if (*fmt == '%') /* Check for a '%' character */ { int size_bound = 0; + int width; /* Columns occupied by STRING. */ fmt++; /* Copy this one %-spec into fmtcpy. */ - string = fmtcpy; + string = (unsigned char *)fmtcpy; *string++ = '%'; while (1) { @@ -198,7 +212,7 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args) abort (); sprintf (sprintf_buffer, fmtcpy, args[cnt++]); /* Now copy into final output, truncating as nec. */ - string = sprintf_buffer; + string = (unsigned char *)sprintf_buffer; goto doit; case 'f': @@ -212,7 +226,7 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args) u.half[1] = args[cnt++]; sprintf (sprintf_buffer, fmtcpy, u.d); /* Now copy into final output, truncating as nec. */ - string = sprintf_buffer; + string = (unsigned char *)sprintf_buffer; goto doit; } @@ -225,24 +239,30 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args) minlen = atoi (&fmtcpy[1]); if (lispstrings) { - string = (char *) ((struct Lisp_String *)args[cnt])->data; - tem = ((struct Lisp_String *)args[cnt])->size; + string = ((struct Lisp_String *)args[cnt])->data; + tem = STRING_BYTES ((struct Lisp_String *)args[cnt]); cnt++; } else { - string = args[cnt++]; + string = (unsigned char *)args[cnt++]; tem = strlen (string); } + width = strwidth (string, tem); goto doit1; /* Copy string into final output, truncating if no room. */ doit: - tem = strlen (string); + /* Coming here means STRING contains ASCII only. */ + width = tem = strlen (string); doit1: + /* We have already calculated: + TEM -- length of STRING, + WIDTH -- columns occupied by STRING when displayed, and + MINLEN -- minimum columns of the output. */ if (minlen > 0) { - while (minlen > tem && bufsize > 0) + while (minlen > width && bufsize > 0) { *bufptr++ = ' '; bufsize--; @@ -251,13 +271,21 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args) minlen = 0; } if (tem > bufsize) - tem = bufsize; - bcopy (string, bufptr, tem); + { + /* Truncate the string at character boundary. */ + tem = bufsize; + while (!CHAR_HEAD_P (string[tem - 1])) tem--; + bcopy (string, bufptr, tem); + /* We must calculate WIDTH again. */ + width = strwidth (bufptr, tem); + } + else + bcopy (string, bufptr, tem); bufptr += tem; bufsize -= tem; if (minlen < 0) { - while (minlen < - tem && bufsize > 0) + while (minlen < - width && bufsize > 0) { *bufptr++ = ' '; bufsize--; @@ -270,9 +298,11 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args) case 'c': if (cnt == nargs) error ("not enough arguments for format string"); - *charbuf = (EMACS_INT) args[cnt++]; + tem = CHAR_STRING ((int) (EMACS_INT) args[cnt], charbuf); string = charbuf; - tem = 1; + cnt++; + string[tem] = 0; + width = strwidth (string, tem); if (fmtcpy[1] != 'c') minlen = atoi (&fmtcpy[1]); goto doit1; @@ -281,8 +311,20 @@ doprnt1 (lispstrings, buffer, bufsize, format, format_end, nargs, args) fmt--; /* Drop thru and this % will be treated as normal */ } } - *bufptr++ = *fmt++; /* Just some characters; Copy 'em */ - bufsize--; + + { + /* Just some character; Copy it if the whole multi-byte form + fit in the buffer. */ + char *save_bufptr = bufptr; + + do { *bufptr++ = *fmt++; } + while (--bufsize > 0 && !CHAR_HEAD_P (*fmt)); + if (!CHAR_HEAD_P (*fmt)) + { + bufptr = save_bufptr; + break; + } + } }; /* If we had to malloc something, free it. */